Skip to content

feat(agent): paste images into conversations#206

Merged
DavidBabinec merged 4 commits into
mainfrom
feat/agent-image-paste
Jul 11, 2026
Merged

feat(agent): paste images into conversations#206
DavidBabinec merged 4 commits into
mainfrom
feat/agent-image-paste

Conversation

@DavidBabinec

@DavidBabinec DavidBabinec commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Summary

  • support up to eight PNG, JPEG, or WebP images per message through paste or the image/media picker beside Send, with no conversation-wide image quota
  • persist text/image and image-only turns, lazily rehydrate authenticated conversation images, and render user, assistant, and tool-result images in compact two/three-column galleries
  • open images in the draggable preview and expose the same keyboard-accessible context menu on pending, chat, tool, and preview images
  • copy real image bytes to the clipboard as PNG, save a MIME-correct download to the desktop, or explicitly save a separate asset to Media
  • route Media saves through the canonical permissioned upload pipeline, deduplicate concurrent saves, and keep an already-open Media explorer fresh across stale list responses
  • resolve selected-model image/tool capabilities authoritatively for OpenRouter and Ollama, with bounded model discovery and provider-overflow replay fallback
  • harden first-send cancellation, conversation writer races, ambiguous model changes, auto-title writes, and private response caching
  • document the complete attachment, replay, privacy, Media, and binary-response contracts

Why

This implements the image capability explored in #197 as a native core-agent feature, using the existing conversation, provider, Media, and tool-loop architecture instead of adding a parallel attachment or storage path.

User and developer impact

Users can attach multiple images with optional text, send image-only turns, inspect images in a compact gallery/preview, and use copy, download, or Save to Media actions. The per-message limit protects a single provider request; long conversations are not assigned an artificial image count and are bounded naturally by provider context handling.

Unsupported models and invalid or oversized images fail before persistence. Conversation images remain private, authenticated chat data unless the user explicitly chooses Save to Media, which creates a separate public Media asset and requires media.write.

The shared TypeBox request contract, browser/server limits, capability semantics, persistence behavior, replay rules, context actions, and race handling are documented in docs/features/agent.md, docs/features/media.md, and the HTTP boundary reference.

Verification

  • full suite: 6,134 pass, 0 fail across 659 files
  • bun run build
  • bun run lint
  • git diff --check
  • React Doctor changed-scope review: advisory-only known/false-positive patterns; no correctness, security, compiler, or lint failure
  • independent code-quality review: no remaining P0–P2 findings
  • GitHub Actions: Test, Build & Typecheck, Lint, and all CodeQL analyses passed

const preview = await screen.findByRole('dialog', { name: 'Your attachment' })
const previewImage = preview.querySelector('img')!
fireEvent.contextMenu(previewImage, { clientX: 120, clientY: 130 })
menu = await screen.findByRole('menu', { name: 'Image actions' })
@DavidBabinec DavidBabinec marked this pull request as ready for review July 11, 2026 11:41
@DavidBabinec DavidBabinec merged commit 3ea7af4 into main Jul 11, 2026
9 checks passed
@DavidBabinec DavidBabinec deleted the feat/agent-image-paste branch July 11, 2026 14:22
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.

1 participant