Repository navigation
Let the assistant work from attached files, pictures, notes and web pages - #9
Merged
Merged
Conversation
A conversation can now be given material to work from: a file (text, Markdown, subtitles, CSV, PDF, Word, HTML), a note from Gecko Notes, or a web page. Each is read as text once, when attached, and kept on the conversation, so every turn reads what the user saw listed and nothing re-reads a note or page afterwards. - Notes are read with the caller's own token; BlockNote bodies become Markdown with Notes' own converter, vendored. - URLs are fetched with every redirect hop checked against private address space after DNS resolution (ported from Notes' web_fetch). - The text is its own system block, between the reference and the project context, so it caches across turns, and is fenced and labelled as data rather than instructions. - Per-item and per-conversation caps refuse rather than silently drop. - The panel gets a paperclip (file, note picker, URL) and drop-to-attach, with removable chips for what is attached. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016K8ApooCKMPBVQiLjaWjcp
Pictures (JPEG, PNG, WebP, GIF) can now be attached to an assistant conversation, as a file or by URL, alongside text material. - Each is made upright, scaled to at most 1568 px and saved as JPEG (PNG where it has transparency) under data/assistant/<session>/, with a small inline thumbnail for the panel's chip. Files go with the attachment or the conversation when either is removed. - Turns send them as image blocks that open the conversation, ahead of the history (system prompts take text only), on both the Anthropic and OpenAI-compatible clients, so they stay in the cached prefix. - Only for a provider marked "can look at images": attaching one for a text-only model is refused with that reason, and if the provider is switched later the material block says the picture isn't shown. - Pixel bombs are refused, and pictures have their own per-conversation cap (ASSISTANT_MAX_IMAGES, 6). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016K8ApooCKMPBVQiLjaWjcp
davior
marked this pull request as ready for review
October 21, 2026 16:07
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
A conversation with the assistant can now be given material to work from:
pypdf), Word (.docx) and HTML. Attach them with the paperclip, or drop them anywhere on the panel.block_markdown.py, copied intoapp/notes/.<article>/<main>is used when it has real content. A URL that points to a PDF, plain text or a picture works too.How
assistant_session.attachments, a JSON TEXT column added by a new Alembic migration. Every later turn reads the same text the user saw listed. Nothing re-reads the note or page afterwards, which is D3's rule applied to attached notes.REFERENCEand the project context. It stays the same for the whole conversation, so prompt caching covers it across turns. It is fenced in<attachment>tags and labelled as data, not instructions, and the text can't close its own fence.data/assistant/<session>/, not in the database. A small inline thumbnail is kept for the chip. The files are deleted when the attachment or the conversation is removed. Each turn sends the pictures as image blocks at the very start of the conversation, ahead of the history (system prompts take text only), on both the Anthropic and OpenAI-compatible clients, so they stay in the cached prefix too. The text block lists them by number, and says they aren't in the library and so can't be used as visuals.app/web_fetch.pyis a synchronous port of Notes' fetcher. Every redirect hop is checked against private address space after DNS resolution, and literal IPs are checked without a lookup. Only text, PDF and image content types are read, and the size is capped while the body streams in.config.py):POST /api/assistant/sessions: an empty conversation, so material can be attached before the first request.POST /sessions/{id}/attachments/{file|note|url}andDELETE /sessions/{id}/attachments/{aid}.GET /api/assistant/notes?q=, for the note picker.Not done
Testing
pytest -q: 662 passed. This includestests/test_assistant_attachments.py(text extraction, picture scaling and refusals, the API, Notes token forwarding, SSRF and redirect refusals, limits, file cleanup, and what reaches the model's prompt and images), new image-body tests intest_provider_conversations.pyfor both protocols, and the migration chain test.npm test: 155 passed, including panel tests for attaching a URL, a note and a picture.npm run buildandnpm run lintare clean.🤖 Generated with Claude Code
https://claude.ai/code/session_016K8ApooCKMPBVQiLjaWjcp