wiki-vault/Sources/Dev/dispatch-attachments.md
2026-07-03 09:48:28 +00:00

3.7 KiB

created path project tags type
2026-07-03 Sources/Dev dispatch-attachments
dispatch
python
project-plan

Goal

Add an attachment capability to the petal-dispatch web client so the user can send images to Lovebug in chat. The immediate goal is clipboard-pasted images reaching the Lovebug/conductor turn so Lovebug can see and discuss them. The longer-term goal is a durable per-session file share, documented here but not built yet.

Locked Decisions

  • P1 source is clipboard paste only. A file-picker and live screen-capture are out of P1 scope; the user is comfortable pasting.
  • P1 target is the Lovebug/conductor turn only, not workers.
  • P1 images are ephemeral with respect to petal-dispatch's message and journal DB. They are not persisted there, so the web chat log shows a small marker rather than the image, and render history stays unaffected. This was the user's explicit call.
  • Images DO persist in the claude CLI session transcript, so Lovebug retains them across resume within the session. This is accepted and desired.
  • P1 transport is a base64 image content-block on the stream-json user turn. No file storage in P1.
  • No-build-step constraint holds. Frontend is inline JS and CSS in index.html. Backend is a petal_dispatch Python change.

Open Items

  • Token weight. A base64 image rides in the transcript and replays on every subsequent turn until the session compacts, so a large screenshot is recurring context cost. A later mitigation is client-side downscaling before send.
  • Web-log marker design. Since the image is not stored for render, the log needs a small placeholder chip such as a paperclip glyph where the image would be.
  • Fused restart timing. The backend change lands in the never-restart fused petal-dispatch, so activation needs a chosen restart window; the conversation resumes via the CLI resume path but the restart is disruptive.

Build Phases

Phase 1 — clipboard image into the conductor turn (active)

Frontend, served live with no restart:

  • Handle paste of an image into the composer. Hold it as base64 in memory, show a paperclip marker chip, and allow removing it before send.
  • On send, include the image data alongside the existing chat POST body.

Backend, needs a fused restart to activate:

  • Accept the image on the chat endpoint.
  • Build the stream-json user message with an image content-block plus the text block, and write that to the claude subprocess stdin.
  • Do not write the image into the message or journal DB. Store only a lightweight marker so the log can show a placeholder.

Outcome: the user pastes a screenshot, Lovebug sees and can discuss it, and render history is undisturbed.

Phase 2 — session file share (documented, future)

A durable per-session file store on the server. Browser uploads land in a per-session folder under the run directory, and files are referenced by path into the relevant claude turn. Requirements: the share folder must sit inside the granted add-dir scope so worker processes can read uploads; upload safety covering size limits and type checks and path-traversal prevention; a listing and cleanup story; and correct host placement given the split ingress and executor topology. There is no current send-now access-later use case, so this stays parked until one appears.

Notes

  • The two-histories distinction is central. petal-dispatch's message DB drives the rendered web log; the claude CLI transcript drives Lovebug's replayed context. P1 deliberately writes to the second and not the first.
  • Frontend serves live; only the Python backend needs the fused restart, so plan the cutover accordingly.
  • Execution routes to a worker building against an isolated git worktree so the live-served checkout is not disturbed mid-build.