Skip to content

feat: materialize pasted/dropped chat images to server temp file paths (#635) - #754

Open
Shadowzzh wants to merge 1 commit into
agegr:mainfrom
Shadowzzh:feat/image-temp-paths
Open

feat: materialize pasted/dropped chat images to server temp file paths (#635)#754
Shadowzzh wants to merge 1 commit into
agegr:mainfrom
Shadowzzh:feat/image-temp-paths

Conversation

@Shadowzzh

Copy link
Copy Markdown

Closes #635

Summary

When a user pastes, drops, or picks an image in pi-web, the server now writes the received bytes to private temporary files and appends their absolute paths (numbered in attachment order) to the agent's message, matching the TUI's clipboard semantics. Inline image inputs are preserved unchanged for vision models, so each path is an additional, addressable, re-attachable artifact for local file/image tools.

Implementation

  • lib/image-materialization.ts (new): ImageAttachmentStore writes each batch atomically under $TMPDIR/pi-web-clipboard-v1-<pid>-<rand>/batch-<rand>/, with per-image UUID filenames and extensions derived from the declared MIME type (client-supplied names/paths are never used). Directories use 0700 and files 0600 on POSIX. Cleanup is layered: an hourly GC expires the process's files after 24 h of inactivity (refreshed by new submissions, deferred while any session is busy or has queued messages), orphan directories older than 24 h whose owning PID no longer exists are collected on later uploads (skipping live owners, other users' directories and symlinks), and normal process exit removes everything.
  • lib/rpc-manager.ts: prompt / steer / follow_up commands materialize their images before dispatch and append the path annotation to the message. A batch is rolled back only when the submission is rejected before preflight acceptance; files survive provider failures after acceptance so follow-up work can reuse the referenced paths. Text-only messages allocate nothing.
  • Tests & docs: storage unit tests, RPC integration tests (including real read-tool access), a browser E2E exercising picker/paste/drop on desktop and mobile widths, and a design doc (docs/image-attachments.md).

Acceptance criteria

  • Pasting/dropping an image in pi-web creates a temp file on the server (visible in $TMPDIR), not just inline base64.
  • The agent receives a file path (or the file is made available to the agent's read/file tools) for the attached image.
  • Temp files are written with 0600 perms, extension derived from mimeType, and a GC/cleanup mechanism prevents orphan accumulation.
  • Existing behavior (inline base64 for vision models) is preserved where it doesn't conflict.

Design notes

  • Naming uses pi-web-clipboard-*, deliberately distinct from the TUI's pi-clipboard-*, to avoid collisions when both run on the same host.
  • Lifecycle is session/process scoped and ephemeral: paths can expire on restart or OS temporary-directory cleanup; historical messages keep their inline image data but old paths are not recreated. Cross-session path permanence is intentionally out of scope here (per the issue's design notes).

Verification

  • Based on ce18006 (post-v0.9.0, pi-coding-agent 0.85.1) with no drift from main.
  • npx tsc --noEmit clean; npm run lint clean; npm test 969/969 pass (16 new tests covering byte preservation, private permissions, batch isolation/rollback, GC & orphan collection, and the RPC preflight accept/reject lifecycle).
  • Browser E2E (e2e/image-attachments.mjs) runs in the CI e2e job and verifies readable server files at the SDK extension boundary without contacting a model provider.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature: Materialize pasted/dropped images to server-side temp file paths (TUI parity)

1 participant