feat(kanban): file attachments on tasks (#35395)
Tasks can now carry file attachments (PDFs, images, source docs) that workers read directly — closes the gap where source material had to be pasted as a path into the task body. - kanban_db: task_attachments table (additive), Attachment dataclass, add/list/get/delete accessors, attachments_root/task_attachments_dir path helpers (per-board, HERMES_KANBAN_ATTACHMENTS_ROOT override) - build_worker_context: surfaces each attachment's absolute path so the worker (full file/terminal tool access) reads it via read_file/pdftotext - dashboard API: POST/GET/DELETE attachment routes (multipart upload, 25MB cap, traversal-safe filenames, root-containment check on download) - dashboard UI: Attachments section in the task drawer — upload button, list with download, per-row remove - docs + tests (13 cases: DB accessors, REST round-trip, traversal rejection, collision suffixing, worker-context surfacing) Closes #35338
This commit is contained in:
@@ -155,6 +155,36 @@ events WebSocket is pinned to a board at connection time; switching in
|
||||
the UI opens a fresh WS against the new board.
|
||||
|
||||
|
||||
## File attachments
|
||||
|
||||
Tasks can carry file attachments — PDFs, images, source documents — so a
|
||||
worker has the source material it needs without you pasting paths into the
|
||||
body and hoping it finds them.
|
||||
|
||||
- **Upload** — open a task in the dashboard drawer and use the
|
||||
**Attachments** section's *Upload file* button (multiple files at once
|
||||
are fine). Each upload is capped at 25 MB.
|
||||
- **Storage** — files land under
|
||||
`<hermes-home>/kanban/attachments/<task_id>/` for the default board, or
|
||||
`<hermes-home>/kanban/boards/<slug>/attachments/<task_id>/` for a named
|
||||
board. Set `HERMES_KANBAN_ATTACHMENTS_ROOT` to pin a custom location.
|
||||
- **What the worker sees** — when the dispatcher hands a task to a worker,
|
||||
the worker's context includes an **Attachments** section listing each
|
||||
file's name and its **absolute path**. The worker has full file/terminal
|
||||
tool access, so it reads attachments directly (`read_file`, or shell
|
||||
tools like `pdftotext`).
|
||||
- **Download / remove** — the drawer lists each attachment with a download
|
||||
link and a remove (×) control. Removing an attachment deletes both the
|
||||
metadata row and the on-disk file.
|
||||
|
||||
:::note Remote terminal backends
|
||||
Attachment paths resolve directly on the **local** terminal backend, which
|
||||
is the default for Kanban workers. If you run workers on a remote backend
|
||||
(Docker, Modal), mount the board's `attachments/` directory into the
|
||||
sandbox so the absolute paths in the worker context are reachable.
|
||||
:::
|
||||
|
||||
|
||||
## Quick start
|
||||
|
||||
The commands below are **you** (the human) setting up the board and creating tasks. Once a task is assigned, the dispatcher spawns the assigned profile as a worker, and from there **the model drives the task through `kanban_*` tool calls, not CLI commands** — see [How workers interact with the board](#how-workers-interact-with-the-board).
|
||||
|
||||
Reference in New Issue
Block a user