Compare commits

...

5 Commits

Author SHA1 Message Date
jay 61fac63409 docs: clarify fanout_dispatch guideline about auto delivery vs collect 2026-05-15 05:12:48 +02:00
jay f7f9dca6b2 docs: simplify fanout_dispatch prompt guideline wording 2026-05-15 05:12:46 +02:00
jay 246af50c08 feat: render preview inline in fanout_status output 2026-05-15 05:12:41 +02:00
jay 81e5cb83bc chore: add comment explaining preview caching in processOutputLine 2026-05-15 05:12:21 +02:00
jay 87986ddf6e 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
2026-05-15 05:11:32 +02:00
3 changed files with 27 additions and 6 deletions

View File

@ -245,7 +245,8 @@ export class FanoutController {
}
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.length <= maxChars) return output;
return output.slice(0, maxChars) + "\n… (truncated)";
@ -257,6 +258,7 @@ export class FanoutController {
if (event.type === "message_end" && event.message) {
const msg = event.message as Message;
if (msg.role === "assistant") {
// Cache latest assistant text for live preview
job.usage.turns++;
const usage = msg.usage;
if (usage) {
@ -269,6 +271,21 @@ export class FanoutController {
if (!job.modelUsed && msg.model) job.modelUsed = msg.model;
if (msg.stopReason) job.stopReason = msg.stopReason;
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

@ -51,7 +51,7 @@ export default function (pi: ExtensionAPI) {
promptGuidelines: [
"Use fanout_dispatch to run multiple agents in parallel without blocking the main session.",
"After dispatching, you may do other work. Check status later with fanout_status.",
"When jobs complete, the system will send a follow-up message. Retrieve output with fanout_collect.",
"Completed jobs deliver their output automatically via follow-up messages. Use fanout_collect if you need the full, untruncated result or to archive old jobs.",
],
execute: async (
@ -126,12 +126,14 @@ export default function (pi: ExtensionAPI) {
result.jobs.length > 0
? "\n\n" +
result.jobs
.map(
(j) =>
.map((j) => {
let jobLine =
`- ${j.id} | ${j.agent} | ${j.status}` +
(j.exitCode !== undefined ? ` (exit ${j.exitCode})` : "") +
(j.turns ? ` | ${j.turns} turns` : ""),
)
(j.turns ? ` | ${j.turns} turns` : "") +
(j.preview ? `\n Preview: ${j.preview.slice(0, 120).replace(/\n/g, " ")}${j.preview.length > 120 ? "…" : ""}` : "");
return jobLine;
})
.join("\n")
: "";
return {

View File

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