@leing2021/super-pi 0.23.10 → 0.23.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -521,7 +521,10 @@ export default function ceCoreExtension(pi: ExtensionAPI) {
|
|
|
521
521
|
return renderSubagentCall(args, theme)
|
|
522
522
|
},
|
|
523
523
|
renderResult(result, renderContext, theme, _context) {
|
|
524
|
-
|
|
524
|
+
// Handle partial updates where data is at top level (from onUpdate)
|
|
525
|
+
// rather than nested in .details (from final result return value)
|
|
526
|
+
const data = (result.details || result) as SubagentLiveDetails
|
|
527
|
+
return renderSubagentResult(data, renderContext, theme)
|
|
525
528
|
},
|
|
526
529
|
})
|
|
527
530
|
|
|
@@ -623,19 +626,29 @@ export default function ceCoreExtension(pi: ExtensionAPI) {
|
|
|
623
626
|
{ onUpdate },
|
|
624
627
|
)
|
|
625
628
|
|
|
626
|
-
// Build summary content
|
|
629
|
+
// Build compact summary content for LLM consumption
|
|
627
630
|
const successCount = result.results.filter(r => r.exitCode === 0).length
|
|
628
631
|
const failCount = result.results.filter(r => isFailedResult(r)).length
|
|
629
|
-
const summaries = result.results.map(r => {
|
|
632
|
+
const summaries = result.results.map((r, i) => {
|
|
633
|
+
const icon = isFailedResult(r) ? "✗" : "✓"
|
|
630
634
|
const output = getFinalOutput(r.messages) || r.errorMessage || r.stderr || "(no output)"
|
|
631
|
-
|
|
632
|
-
|
|
635
|
+
// Compact: first non-empty line, stripped of markdown formatting
|
|
636
|
+
const summaryLine = output.split("\n").find((l: string) => l.trim().length > 0) || ""
|
|
637
|
+
const cleaned = summaryLine.replace(/^#+\s*/, "").replace(/\*\*/g, "").trim()
|
|
638
|
+
const oneLine = cleaned.length > 200 ? cleaned.slice(0, 199) + "…" : cleaned
|
|
639
|
+
return `${i + 1}. ${icon} ${r.agent} — ${oneLine}`
|
|
640
|
+
})
|
|
641
|
+
|
|
642
|
+
// Full outputs available in details for expanded view
|
|
643
|
+
const fullOutputs = result.results.map(r => {
|
|
644
|
+
const output = getFinalOutput(r.messages) || ""
|
|
645
|
+
return output
|
|
633
646
|
})
|
|
634
647
|
|
|
635
648
|
return {
|
|
636
649
|
content: [{
|
|
637
650
|
type: "text",
|
|
638
|
-
text: `Parallel: ${successCount}/${result.results.length} succeeded${failCount > 0 ? `, ${failCount} failed` : ""}\n
|
|
651
|
+
text: `Parallel: ${successCount}/${result.results.length} succeeded${failCount > 0 ? `, ${failCount} failed` : ""}\n${summaries.join("\n")}`,
|
|
639
652
|
}],
|
|
640
653
|
details: result,
|
|
641
654
|
}
|
|
@@ -644,7 +657,10 @@ export default function ceCoreExtension(pi: ExtensionAPI) {
|
|
|
644
657
|
return renderSubagentCall(args, theme)
|
|
645
658
|
},
|
|
646
659
|
renderResult(result, renderContext, theme, _context) {
|
|
647
|
-
|
|
660
|
+
// Handle partial updates where data is at top level (from onUpdate)
|
|
661
|
+
// rather than nested in .details (from final result return value)
|
|
662
|
+
const data = (result.details || result) as SubagentLiveDetails
|
|
663
|
+
return renderSubagentResult(data, renderContext, theme)
|
|
648
664
|
},
|
|
649
665
|
})
|
|
650
666
|
|
|
@@ -142,13 +142,14 @@ export function renderSubagentCall(
|
|
|
142
142
|
|
|
143
143
|
if (args.tasks && args.tasks.length > 0) {
|
|
144
144
|
let text =
|
|
145
|
-
theme.fg("toolTitle", theme.bold("
|
|
146
|
-
theme.fg("accent",
|
|
147
|
-
for (
|
|
148
|
-
const
|
|
149
|
-
|
|
145
|
+
theme.fg("toolTitle", theme.bold("⬇ parallel ")) +
|
|
146
|
+
theme.fg("accent", `${args.tasks.length} agents launching...`)
|
|
147
|
+
for (let i = 0; i < args.tasks.length; i++) {
|
|
148
|
+
const t = args.tasks[i]
|
|
149
|
+
const num = theme.fg("muted", `${i + 1}.`)
|
|
150
|
+
const preview = t.task.length > 50 ? `${t.task.slice(0, 50)}...` : t.task
|
|
151
|
+
text += `\n ${num} ${theme.fg("accent", t.agent)} ${theme.fg("dim", preview)}`
|
|
150
152
|
}
|
|
151
|
-
if (args.tasks.length > 3) text += `\n ${theme.fg("muted", `... +${args.tasks.length - 3} more`)}`
|
|
152
153
|
return new Text(text, 0, 0)
|
|
153
154
|
}
|
|
154
155
|
|
|
@@ -373,70 +374,94 @@ function renderParallelResult(
|
|
|
373
374
|
const successCount = results.filter(r => r.exitCode !== -1 && !isFailedResult(r)).length
|
|
374
375
|
const failCount = results.filter(r => r.exitCode !== -1 && isFailedResult(r)).length
|
|
375
376
|
const isRunning = running > 0
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
:
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
377
|
+
|
|
378
|
+
if (isRunning) {
|
|
379
|
+
// --- Live progress: compact status line ---
|
|
380
|
+
const doneCount = successCount + failCount
|
|
381
|
+
const icon = theme.fg("warning", "⏳")
|
|
382
|
+
const bar = renderProgressBar(doneCount, results.length, theme)
|
|
383
|
+
const doneLabel = failCount > 0
|
|
384
|
+
? theme.fg("success", `${successCount}✓`) + " " + theme.fg("error", `${failCount}✗`)
|
|
385
|
+
: theme.fg("success", `${successCount}✓`)
|
|
386
|
+
const runningLabel = theme.fg("dim", `, ${running} running...`)
|
|
387
|
+
return new Text(`${icon} ${bar} ${doneLabel}${runningLabel}`, 0, 0)
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
// --- Completed: summary card layout ---
|
|
391
|
+
const allSuccess = failCount === 0
|
|
392
|
+
const headerIcon = allSuccess ? theme.fg("success", "✓") : theme.fg("warning", "◐")
|
|
393
|
+
const headerText = failCount > 0
|
|
394
|
+
? `${successCount}/${results.length} succeeded, ${failCount} failed`
|
|
395
|
+
: `${successCount}/${results.length} succeeded`
|
|
396
|
+
|
|
397
|
+
if (context.expanded) {
|
|
398
|
+
// Expanded: header + per-task details with tool calls and output
|
|
386
399
|
const container = new Container()
|
|
387
|
-
container.addChild(new Text(`${
|
|
400
|
+
container.addChild(new Text(`${headerIcon} ${theme.fg("toolTitle", theme.bold("parallel "))}${theme.fg("accent", headerText)}`, 0, 0))
|
|
401
|
+
container.addChild(new Spacer(1))
|
|
388
402
|
|
|
389
403
|
for (const r of results) {
|
|
390
404
|
const rIcon = isFailedResult(r) ? theme.fg("error", "✗") : theme.fg("success", "✓")
|
|
391
|
-
const displayItems = getDisplayItems(r.messages)
|
|
392
405
|
const finalOutput = getFinalOutput(r.messages)
|
|
406
|
+
const summaryText = isFailedResult(r)
|
|
407
|
+
? (r.errorMessage || r.stderr || "unknown error")
|
|
408
|
+
: (finalOutput ? summarizeText(finalOutput, 200) : "(no output)")
|
|
393
409
|
|
|
394
|
-
container.addChild(new
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
for (const item of displayItems) {
|
|
398
|
-
if (item.type === "toolCall")
|
|
399
|
-
container.addChild(new Text(theme.fg("muted", "→ ") + formatToolCall(item.name, item.args, theme.fg.bind(theme)), 0, 0))
|
|
400
|
-
}
|
|
401
|
-
if (finalOutput) {
|
|
402
|
-
container.addChild(new Spacer(1))
|
|
410
|
+
container.addChild(new Text(`${rIcon} ${theme.fg("accent", r.agent)} — ${summaryText}`, 0, 0))
|
|
411
|
+
|
|
412
|
+
if (!isFailedResult(r) && finalOutput) {
|
|
403
413
|
container.addChild(new Markdown(finalOutput.trim(), 0, 0, mdTheme))
|
|
404
414
|
}
|
|
415
|
+
|
|
405
416
|
const taskUsage = formatUsageStats(r.usage, r.model)
|
|
406
417
|
if (taskUsage) container.addChild(new Text(theme.fg("dim", taskUsage), 0, 0))
|
|
418
|
+
container.addChild(new Spacer(1))
|
|
407
419
|
}
|
|
408
420
|
|
|
409
421
|
const usageStr = formatUsageStats(aggregateUsage(results))
|
|
410
422
|
if (usageStr) {
|
|
411
|
-
container.addChild(new Spacer(1))
|
|
412
423
|
container.addChild(new Text(theme.fg("dim", `Total: ${usageStr}`), 0, 0))
|
|
413
424
|
}
|
|
414
425
|
return container
|
|
415
426
|
}
|
|
416
427
|
|
|
417
|
-
// Collapsed
|
|
418
|
-
let text = `${
|
|
428
|
+
// Collapsed: one-line summary per task
|
|
429
|
+
let text = `${headerIcon} ${theme.fg("toolTitle", theme.bold("parallel "))}${theme.fg("accent", headerText)}`
|
|
419
430
|
for (const r of results) {
|
|
420
|
-
const rIcon =
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
const displayItems = getDisplayItems(r.messages)
|
|
427
|
-
text += `\n\n${theme.fg("muted", "─── ")}${theme.fg("accent", r.agent)} ${rIcon}`
|
|
428
|
-
if (displayItems.length === 0)
|
|
429
|
-
text += `\n${theme.fg("muted", r.exitCode === -1 ? "(running...)" : "(no output)")}`
|
|
430
|
-
else text += `\n${renderDisplayItems(displayItems, 5)}`
|
|
431
|
+
const rIcon = isFailedResult(r) ? theme.fg("error", "✗") : theme.fg("success", "✓")
|
|
432
|
+
const finalOutput = getFinalOutput(r.messages)
|
|
433
|
+
const summaryText = isFailedResult(r)
|
|
434
|
+
? (r.errorMessage || r.stderr || "unknown error")
|
|
435
|
+
: (finalOutput ? summarizeText(finalOutput, 120) : "(no output)")
|
|
436
|
+
text += `\n ${rIcon} ${theme.fg("accent", r.agent)} — ${summaryText}`
|
|
431
437
|
}
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
}
|
|
436
|
-
if (!context.expanded) text += `\n${theme.fg("muted", "(Ctrl+O to expand)")}`
|
|
438
|
+
const usageStr = formatUsageStats(aggregateUsage(results))
|
|
439
|
+
if (usageStr) text += `\n${theme.fg("dim", usageStr)}`
|
|
440
|
+
text += `\n${theme.fg("muted", "(Ctrl+O to expand)")}`
|
|
437
441
|
return new Text(text, 0, 0)
|
|
438
442
|
}
|
|
439
443
|
|
|
444
|
+
// ---------------------------------------------------------------------------
|
|
445
|
+
// Progress bar & text helpers
|
|
446
|
+
// ---------------------------------------------------------------------------
|
|
447
|
+
|
|
448
|
+
function renderProgressBar(done: number, total: number, theme: Theme): string {
|
|
449
|
+
const width = Math.min(total, 20)
|
|
450
|
+
const filled = Math.round((done / total) * width)
|
|
451
|
+
const empty = width - filled
|
|
452
|
+
const bar = theme.fg("success", "█".repeat(filled)) + theme.fg("dim", "░".repeat(empty))
|
|
453
|
+
return bar
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
function summarizeText(text: string, maxLen: number): string {
|
|
457
|
+
// Take first meaningful paragraph or line
|
|
458
|
+
const firstLine = text.split("\n").find(l => l.trim().length > 0) || ""
|
|
459
|
+
// Strip markdown headers and bold for summary
|
|
460
|
+
const cleaned = firstLine.replace(/^#+\s*/, "").replace(/\*\*/g, "").replace(/\[.*?\]\(.*?\)/g, "").trim()
|
|
461
|
+
if (cleaned.length <= maxLen) return cleaned
|
|
462
|
+
return cleaned.slice(0, maxLen - 1) + "…"
|
|
463
|
+
}
|
|
464
|
+
|
|
440
465
|
// ---------------------------------------------------------------------------
|
|
441
466
|
// Markdown theme helper
|
|
442
467
|
// ---------------------------------------------------------------------------
|