Release 0.219
0.219.0: A picture where the sentence needs it (branch claude/vibrant-elion-4dda88)
A chat reply could not put a picture mid-answer. Every image a turn produced was collected and rendered as a strip below the whole reply, in the order the tool was called. For the case this feature exists for, an illustrated walkthrough of a product manual, that is the wrong shape: the reader wants each step’s screenshot under that step, not a clump at the bottom to map back by counting. v0.218.10 corrected the prompt to describe that limit honestly. This removes the limit instead.
The renderer already had everything. Chat replies render through the same TipTap
schema Pages uses, image node included, and that node resolves a stored file from
its id. The missing link was one converter: markdownToDoc (Pages, server-side)
turned  into a real image, while the chat converter let
it fall through to a broken <img src="media:...">. So the same syntax now works
in a reply, and the assistant writes each screenshot where it belongs.
Two converters drifting is how the bug happened, so the reference schemes
(media:, page:, mention:) moved to one dependency-free module both import,
with a test that runs the same markdown through both and fails if they disagree
about which picture goes where. The standalone form deliberately does not go
through marked: the <p> wrapper it adds makes ProseMirror close an empty
paragraph before the image, putting a blank line above every picture.
Three edges, decided rather than left to chance:
- Shown twice. A reply that writes the image inline and calls
show_imagefor the same file used to show it in both places. The reply’s own placement wins; the strip copy is dropped at finalize. Mechanical, not prompt-only, because a confused model doing both is exactly the case a prompt misses. - Mid-stream. A half-typed
. Inline markers are stripped on the way out and counted on the trace.show_imageremains the only path that delivers a photo there, andvisual_answersnow says so.
No new surface area: the <img> hits the same owner-gated bytes route Pages and
the attachment strip already use. It answers unauthenticated with 401 and scopes
every read by owner id, so an invented or someone else’s file id is a broken
image, never a leak.