feat: render preview in fanout_status output

- Include job output preview as indented code block in fanout_status results
- Preview text is already available in status().jobs[].preview via controller
- Now displayed in the text content output alongside job metadata
- Each preview line is indented for readability in markdown code blocks
- Useful for quick inspection of job results without calling fanout_collect
This commit is contained in:
jay 2026-05-15 05:11:32 +02:00
parent e1516c44c6
commit 87986ddf6e
3 changed files with 30 additions and 5 deletions

View File

@ -245,7 +245,8 @@ export class FanoutController {
} }
private getJobPreview(job: FanoutJob, maxChars = 500): string { private getJobPreview(job: FanoutJob, maxChars = 500): string {
const output = this.readJobOutput(job); // Use cached preview if available (updated in processOutputLine)
const output = job.lastPreview || this.readJobOutput(job);
if (!output) return ""; if (!output) return "";
if (output.length <= maxChars) return output; if (output.length <= maxChars) return output;
return output.slice(0, maxChars) + "\n… (truncated)"; return output.slice(0, maxChars) + "\n… (truncated)";
@ -269,6 +270,21 @@ export class FanoutController {
if (!job.modelUsed && msg.model) job.modelUsed = msg.model; if (!job.modelUsed && msg.model) job.modelUsed = msg.model;
if (msg.stopReason) job.stopReason = msg.stopReason; if (msg.stopReason) job.stopReason = msg.stopReason;
if (msg.errorMessage) job.errorMessage = msg.errorMessage; if (msg.errorMessage) job.errorMessage = msg.errorMessage;
// Cache last assistant text output for live preview
let previewUpdated = false;
for (const part of msg.content) {
if (part.type === "text") {
job.lastPreview = part.text;
previewUpdated = true;
break;
}
}
// Persist cache to enable live previews after restart
if (previewUpdated) {
this.persist(job);
}
} }
} }
} }

View File

@ -126,12 +126,19 @@ export default function (pi: ExtensionAPI) {
result.jobs.length > 0 result.jobs.length > 0
? "\n\n" + ? "\n\n" +
result.jobs result.jobs
.map( .map((j) => {
(j) => let jobLine =
`- ${j.id} | ${j.agent} | ${j.status}` + `- ${j.id} | ${j.agent} | ${j.status}` +
(j.exitCode !== undefined ? ` (exit ${j.exitCode})` : "") + (j.exitCode !== undefined ? ` (exit ${j.exitCode})` : "") +
(j.turns ? ` | ${j.turns} turns` : ""), (j.turns ? ` | ${j.turns} turns` : "");
) if (j.preview) {
jobLine += `\n \`\`\`\n${j.preview
.split("\n")
.map((line) => ` ${line}`)
.join("\n")}\n \`\`\``;
}
return jobLine;
})
.join("\n") .join("\n")
: ""; : "";
return { return {

View File

@ -26,6 +26,8 @@ export interface FanoutJob {
usage: JobUsage; usage: JobUsage;
modelUsed?: string; modelUsed?: string;
stopReason?: string; stopReason?: string;
/** Last assistant text output seen while running (for live previews) */
lastPreview?: string;
} }
export interface DispatchResult { export interface DispatchResult {