Skip to content

feat(images): add image attachment support#97

Merged
remarkablemark merged 5 commits into
masterfrom
feat/image
May 19, 2026
Merged

feat(images): add image attachment support#97
remarkablemark merged 5 commits into
masterfrom
feat/image

Conversation

@remarkablemark
Copy link
Copy Markdown
Member

@remarkablemark remarkablemark commented May 19, 2026

What is the motivation for this pull request?

Feature: Add image attachment support to the TUI chat interface, allowing users to attach and send images alongside text prompts to multimodal models.

What is the current behavior?

The TUI chat only supports text prompts. Users cannot attach images or other files to their messages.

What is the new behavior?

  • Users can paste images from clipboard (Ctrl+V) into the chat input
  • Images are displayed as attachments with a distinct visual indicator
  • Attached images are sent alongside text to multimodal-capable models
  • Supports both file paths and direct image data from clipboard
  • Temp files are managed appropriately (deleted if removed before send)

plan.md

Checklist:

Add first-class image attachments to the interactive chat TUI. Users can attach images by pasting or drag-dropping local image paths into the prompt, and by pasting clipboard images through terminal-delivered paste input. Clipboard images are materialized to an app-specific directory under `os.tmpdir()` and then treated like normal file attachments.

Message and persistence:

- Extend `src/utils/ollama.ts` `Message` with `images?: string[]`.
- Pass `images` through unchanged to Ollama chat requests.
- Preserve `images` in session JSONL persistence and reload them on resume.

Attachment model:

- Add staged attachment state to chat input, separate from plain text.
- On submit, send one user message with:
  - `content`: typed text only
  - `images`: absolute image paths for staged attachments
- Clear staged attachments after successful submit.

Input UX:

- Do not add an `/image` command.
- Render attachments inline as bracketed atomic tokens using filenames:
  - real files: `[diagram.png]`
  - clipboard images: `[image-1.png]`, `[image-2.png]`
- Use a dedicated attachment color distinct from normal prompt text.
- Keep the cursor outside token internals; left/right moves across each token as one unit.
- `Backspace`/`Delete` removes an adjacent token as a whole.
- Normal typed text remains editable after the attachment tokens.

Attachment ingestion:

- Detect pasted or drag-dropped local image paths in the prompt and stage them as attachments instead of leaving them as plain text.
- If pasted text is not a valid readable image path, keep it as ordinary text.
- Add clipboard-image ingestion through paste/key handling where the terminal exposes it.
- Materialize clipboard images to `path.join(os.tmpdir(), 'code-ollama', 'images')` with generated names like `image-1.png`.
- Keep user-supplied file attachments at their original paths; only clipboard images are copied to temp storage.

Rendering history:

- Show sent user attachments in message history using the same bracketed filename convention.
- Do not attempt inline bitmap previews in the terminal.

Public Interface Changes:

- `Message` gains optional `images?: string[]`.
- `TextInput`/`ChatInput` move from string-only editing to structured input with attachment tokens plus text.
- Add an internal clipboard utility that reads a clipboard image and writes it to the app temp image directory.

Test Plan:

- `utils/ollama` tests: messages with `images` are forwarded to Ollama.
- Session tests: messages with `images` persist and reload correctly.
- Chat input tests:
  - valid image paths stage attachments
  - invalid paths remain plain text
  - multiple attachments render as bracketed filename tokens
  - token navigation is atomic
  - backspace/delete removes whole tokens
  - normal text editing still works
- Clipboard tests:
  - clipboard image ingestion writes to the temp image directory and stages the resulting file
  - generated names follow `image-N.ext`
  - empty/unavailable clipboard produces a user-facing error
- Submit/render tests:
  - submitting text plus attachments sends `content` and `images`
  - staged attachments clear after submit
  - history renders bracketed attachment filenames consistently
- Regression tests:
  - slash command flow
  - `@` file suggestion flow
  - prompt history navigation

Assumptions and Defaults:

- Scope is TUI chat only; the one-off `run` command remains unchanged.
- Attachment tokens always render with brackets and a distinct color.
- Clipboard-derived images are stored under `os.tmpdir()` in an app-specific subdirectory.
- If a staged clipboard image is removed before send, its temp file should be deleted.
- Sent clipboard image temp files are retained in v1 so resumed sessions can still reference them as long as the OS has not cleaned temp storage.
- Model capability checks are not enforced in the UI; unsupported image behavior is left to Ollama/model responses.
@codecov
Copy link
Copy Markdown

codecov Bot commented May 19, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

Files with missing lines Coverage Δ
src/components/App/ReadinessCheck.tsx 100.00% <100.00%> (ø)
src/components/Chat/Chat.tsx 100.00% <100.00%> (ø)
src/components/Chat/ChatInput.tsx 100.00% <100.00%> (ø)
src/components/Chat/attachments.ts 100.00% <100.00%> (ø)
src/components/Messages/Message.tsx 100.00% <100.00%> (ø)
src/components/PlanApproval/PlanApproval.tsx 100.00% <ø> (ø)
src/components/TextInput/TextInput.tsx 100.00% <100.00%> (ø)
src/components/ToolApproval/ToolApproval.tsx 100.00% <ø> (ø)
src/utils/clipboard.ts 100.00% <100.00%> (ø)
src/utils/ollama.ts 100.00% <ø> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Comment thread src/utils/clipboard.ts Fixed
Comment thread src/utils/clipboard.ts Fixed
@remarkablemark remarkablemark changed the title feat: image support feat(images): add image attachment support May 19, 2026
@remarkablemark remarkablemark self-assigned this May 19, 2026
@remarkablemark remarkablemark added the enhancement New feature or request label May 19, 2026
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
@remarkablemark remarkablemark merged commit 872da1e into master May 19, 2026
16 checks passed
@remarkablemark remarkablemark deleted the feat/image branch May 19, 2026 23:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants