docs(07): document media size limits, storage locations, outbound asymmetry
This commit is contained in:
1 parent
742916903b
commit
4e9f1d028a
1 file changed
+51
-7
+51
-7
@@ -41,10 +41,12 @@ receipt (don't trust the client) using hermes helpers
|
||||
(`gateway/platforms/base.py:2337`). The agent's vision/audio tools can then
|
||||
read the file.
|
||||
|
||||
**Limits:** `get_inbound_media_max_bytes()` / `validate_inbound_media_size`
|
||||
(`base.py:758/779`) enforce the cap; over-limit → 413 +
|
||||
`error {code:"media_too_large"}`. (The 1 MiB `MAX_BODY_BYTES` cap applies to
|
||||
JSON *frame* bodies only, not media uploads.)
|
||||
**Limits:** two caps apply — the plugin's `max_upload_bytes` (default
|
||||
100 MiB) and hermes's `gateway.max_inbound_media_bytes` (default 128 MiB,
|
||||
enforced by `get_inbound_media_max_bytes()` / `validate_inbound_media_size`,
|
||||
`base.py:758/779`); over-limit → 413 + `error {code:"media_too_large"}`.
|
||||
Effective limit is the **min** of both; see §7.7. (The 1 MiB
|
||||
`MAX_BODY_BYTES` cap applies to JSON *frame* bodies only, not media uploads.)
|
||||
|
||||
**Single-shot:** no chunking/resumability — HTTP carries the body; single-user
|
||||
scale makes a one-shot upload sufficient.
|
||||
@@ -94,8 +96,50 @@ delivery-path check is re-run **at pull time**, not just at offer time.
|
||||
|
||||
## 7.6 App-side storage
|
||||
|
||||
- Cache dir: app-specific external cache (`getExternalCacheDir()/media`).
|
||||
- LRU eviction by size (configurable, default 500 MB) so old media doesn't fill
|
||||
the device.
|
||||
- Cache dir: app-specific external cache (`getExternalCacheDir()/media`,
|
||||
internal `cacheDir` fallback; desktop: `~/.iris/cache/media`).
|
||||
- LRU eviction by size (hardcoded 500 MB, `MediaCacheJvm.kt` `maxBytes`) so old
|
||||
media doesn't fill the device.
|
||||
- A `MediaRepository` tracks `{media_id, local_path, kind, size, ts}` in Room so
|
||||
bubbles can re-render players after process death.
|
||||
|
||||
## 7.7 Size limits & where files live
|
||||
|
||||
**Inbound (app → agent) — two caps, effective limit is the min:**
|
||||
|
||||
| Cap | Default | Set via | Enforced by |
|
||||
| --- | --- | --- | --- |
|
||||
| Plugin `max_upload_bytes` | 100 MiB | `gateway.platforms.iris.extra.max_upload_bytes` (config.yaml) | `http_server.py` (Content-Length pre-check) + `media.py` `UploadSession.feed` (mid-stream) → `media_too_large` |
|
||||
| Hermes `gateway.max_inbound_media_bytes` | 128 MiB | `gateway.max_inbound_media_bytes` (config.yaml) | `validate_inbound_media_size` inside `cache_*_from_bytes` (`base.py:758/779`) → `media_too_large` |
|
||||
|
||||
Both are **pure config** — raising the limit needs no code change in the plugin
|
||||
or hermes-agent. The app itself has no upload cap.
|
||||
|
||||
**Why the caps exist:** the upload is streamed to a temp file (disk, bounded
|
||||
RAM in flight), but at completion the plugin reads the **entire blob into
|
||||
memory** (`UploadSession.read_bytes()` → `cache_*_from_bytes` →
|
||||
`write_bytes`), so peak RAM ≈ file size per upload. Hermes's cap exists to
|
||||
prevent OOM-killing the gateway (comment at `base.py:740-749`).
|
||||
|
||||
**Inbound storage (gateway host):**
|
||||
|
||||
- In flight: temp file `upl_*` under `~/.hermes/iris/media/tmp` (removed after
|
||||
completion or failure).
|
||||
- After caching: hermes media cache — `~/.hermes/cache/images/img_<uuid12><ext>`,
|
||||
`cache/audio/audio_<uuid12><ext>`, `cache/videos/video_<uuid12><ext>`,
|
||||
`cache/documents/doc_<uuid12>_<original filename>`. Video/image/audio lose
|
||||
their original filename; documents keep it.
|
||||
- Lifetime: hermes `cleanup_video_cache(max_age_hours=24)` deletes videos older
|
||||
than 24 h.
|
||||
|
||||
**Outbound (agent → app) — no size cap at the gateway.** `media.offer` carries
|
||||
metadata; `GET /v1/media/{id}` streams the full file in 256 KiB chunks
|
||||
regardless of size. The only constraints are the delivery-path re-validation at
|
||||
pull time and the 24 h offer TTL (`MediaStore.prune_outbound`).
|
||||
|
||||
**The effective outbound limit is set by the app:** the device media cache is
|
||||
LRU-capped at 500 MB (§7.6) and `evict()` runs right after each pull completes.
|
||||
A single file > 500 MB makes the eviction loop delete everything — *including
|
||||
the file it just downloaded*. So files > ~500 MB arrive but are immediately
|
||||
discarded. To retain large agent→app files, raise `maxBytes` in
|
||||
`MediaCacheJvm.kt` (or exempt files from eviction).
|
||||
Reference in new issue
Block a user