feat: render the attached screenshot instead of just naming it
The transcript said "_Screenshot attached_" and left it at that, on a note in the test file claiming Vicinae could not resolve a local image. It can. That claim was true of a URL the model invented, not of a file this extension captured itself. Checked against the renderer rather than assumed: - `imageProviderUrl` in `markdown-model.cpp` routes `file://`, and a scheme-less string, through `ImageURL::local`. Anything it does not recognise comes back empty, which is why a bare path is not good enough. - `MdImage.qml` draws it block-level and centred, using the alt text as an italic caption, and caps the rendered height at 200px regardless of the `raycast-width`/`raycast-height` hint it also accepts. So `attachments.ts` gains `imageSource`, which builds a `file://` URL with `pathToFileURL` so a path with a space or non-ascii still resolves, and `markdown.ts` gains `renderAttachments`, used for a turn's attachments and for an unsent pending snip. That second use is the one that matters most: the capture is now visible before the question about it exists. The alt text carries the label, so a deleted file degrades to what the transcript used to say. The 200px cap is a Vicinae limit, so the action panel keeps Open Screenshot for the full image. Tests that asserted the old behaviour are inverted, and imageSource is covered for spaces and non-ascii. Verified: 280 tests, tsc, eslint, prettier, and vici build.
This commit is contained in:
+24
-7
@@ -1,5 +1,6 @@
|
||||
import { imageSource } from "./attachments";
|
||||
import { repairCodeBlocks } from "./code";
|
||||
import type { ChatTurn, ThreadMessage } from "./types";
|
||||
import type { Attachment, ChatTurn, ThreadMessage } from "./types";
|
||||
|
||||
/**
|
||||
* Markdown rendering for the detail panel.
|
||||
@@ -22,6 +23,24 @@ import type { ChatTurn, ThreadMessage } from "./types";
|
||||
|
||||
export const STREAMING_CURSOR = "▍";
|
||||
|
||||
/**
|
||||
* Renders attachments as markdown images.
|
||||
*
|
||||
* Vicinae does resolve a local file: `MdImage.qml` draws it block-level and
|
||||
* centred, uses the alt text as an italic caption underneath, and caps the
|
||||
* height at 200px no matter what is asked for. So this is a thumbnail rather
|
||||
* than something readable, which is why the action panel also offers Open
|
||||
* Screenshot for the full image.
|
||||
*
|
||||
* The alt text is not decoration: it is what remains if the file has since been
|
||||
* deleted, so it says what the picture was rather than leaving a blank space.
|
||||
*/
|
||||
export function renderAttachments(attachments: Attachment[]): string {
|
||||
return attachments
|
||||
.map((attachment) => `})`)
|
||||
.join("\n\n");
|
||||
}
|
||||
|
||||
/** Which optional sections the transcript includes. Driven by preferences. */
|
||||
export interface TranscriptOptions {
|
||||
showToolCalls: boolean;
|
||||
@@ -50,12 +69,10 @@ function renderTools(message: ThreadMessage): string {
|
||||
function renderMessage(message: ThreadMessage, options: TranscriptOptions): string {
|
||||
// The question is identified by its styling alone.
|
||||
if (message.role === "user") {
|
||||
// An attached screenshot cannot be shown here: images render block-level,
|
||||
// centred and capped at 200px (`MdImage.qml`), and there is no form of
|
||||
// `` that resolves to a local capture. The transcript says the
|
||||
// image is there instead, and the action panel opens it.
|
||||
const attached = message.attachments.length > 0 ? "\n\n_Screenshot attached_" : "";
|
||||
return `${quote(message.text)}${attached}`;
|
||||
const images = renderAttachments(message.attachments);
|
||||
const asked = quote(message.text);
|
||||
|
||||
return images ? `${asked}\n\n${images}` : asked;
|
||||
}
|
||||
|
||||
// While a tool is running there is no answer text yet, so the activity line
|
||||
|
||||
Reference in New Issue
Block a user