Skip to content

Stage image attachments for agent sessions - #89

Open
cristicretu wants to merge 2 commits into
mainfrom
codex/issue-77-image-attachments
Open

cristicretu wants to merge 2 commits into
mainfrom
codex/issue-77-image-attachments

Conversation

@cristicretu

@cristicretu cristicretu commented Aug 12, 2026

Copy link
Copy Markdown
Owner

Summary

  • stage PNG, JPEG, GIF, and WebP files dropped on a terminal, open composer, or session row as ordered per-session attachment drafts
  • converge Finder drops and Command-V clipboard images on one private-copy validation and delivery pipeline, with compact filename/size chips plus named remove/clear controls and keyboard shortcuts
  • add typed manifest image-input capabilities for Claude Code and Codex, while requiring explanatory text for conservative unknown-agent path fallback
  • preserve explicit-submit semantics: dropping or pasting never sends, selects, wakes, marks seen, or spawns; existing-session drafts and images remain until the daemon acknowledges the exact session.send_text(submit: true) RPC
  • validate an open-once, no-follow file descriptor, regular-file type, raster signature, copied bytes, 20 MB per-image size, 12-image count, and 100 MB aggregate bounds before delivery
  • keep hover metadata-only, stage explicit drops off the UI executor, JSON-escape staged paths, prune removed-session drafts, and clean owner-only app staging without touching originals
  • reject plain Shell attachment delivery and fail closed for remote image drafts before any partial turn can be sent

Behavior and safety

Local originals are copied from one no-follow file descriptor into generated owner-only staging files. The same descriptor supplies metadata, signature validation, and bounded bytes, closing path-swap and symlink races. User filenames never enter the delivery surface, originals are never deleted, and oversized batches are rejected before paths beyond the remaining count are opened. Draft copies are released on remove, clear, or removed-session pruning; acknowledged submissions persist a 24-hour lease so the agent can still open the path if the app exits, with narrowly scoped stale-process cleanup on a later launch.

Image staging is asynchronous and does not auto-send. Generation and target guards prevent a late File Provider/drop completion from attaching to a newly selected draft, while Clear invalidates all pending staging work. Existing-session submission is single-flight: Escape, click-away, editing, removal, and draft switching remain frozen until the RPC settles; a real asynchronous RPC failure leaves the composer, text, and private image leases intact with visible feedback.

Remote acceptance remains authorization-bound

Remote delivery is deliberately fail-closed and is not implemented by this PR. The issue acceptance criterion requiring image upload to remote sessions therefore remains blocked on a separately authorized protocol change. A direct app-owned SSH/SCP implementation was rejected during review because it would introduce unapproved image egress and bypass Diri's remote-helper boundary.

The safe implementation requires a versioned, engine-owned, session-authorized upload RPC plus Remote Helper protocol support: nonce-scoped owner-only destinations, all-or-nothing writes, paths returned only after the whole batch succeeds, rollback, and TTL cleanup. The current UI instead shows Remote image upload is unavailable in this build; nothing will be sent and preserves the draft. This PR references rather than closes #77 for that reason.

Validation

  • cargo test --workspace (all unit, integration, and doc suites passed; diri-app: 382 passed, 2 ignored)
  • cargo clippy --workspace --all-targets -- -D warnings
  • cargo check --workspace --all-targets
  • cargo fmt --all -- --check
  • git diff --check
  • cargo build --workspace --release
  • focused coverage for no-follow symlink/FIFO rejection, same-FD path-swap resistance, copied-byte accounting, count/aggregate preflight, owner-only permissions, stale cleanup scope, target/generation cancellation, Command-V convergence, per-session cleanup, accessible shortcuts, no-auto-send, RPC failure retention, and exactly-one acknowledged submit

Dependency

Stacked on PR #84 (codex/issue-73-finder-drops) because this deepens its session-row ExternalPaths routing. Please review/merge #84 first.

Refs #77

@cristicretu
cristicretu force-pushed the codex/issue-77-image-attachments branch from f3fb204 to 6359c04 Compare August 13, 2026 08:34
@cristicretu
cristicretu changed the base branch from codex/issue-73-finder-drops to main August 13, 2026 08:34
@cristicretu
cristicretu force-pushed the codex/issue-77-image-attachments branch from 6359c04 to 5d5dfe5 Compare August 13, 2026 11:42
@cristicretu
cristicretu force-pushed the codex/issue-77-image-attachments branch from 5d5dfe5 to 866e7ae Compare August 13, 2026 20:11
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.

Drag images into a session and attach them to any supported agent

1 participant