feat(coding-agent): formatted multiline descriptions and tasks in subagent HUD

- Replace newline characters with visual indicators in subagent HUD descriptions and task previews.
- Add unit tests verifying multiline description and task rendering.
This commit is contained in:
can1357
2026-08-19 22:58:25 +02:00
parent 74bc1f442e
commit c39004063e
2 changed files with 30 additions and 3 deletions
@@ -488,13 +488,15 @@ export function renderSubagentHudLines(sessions: ObservableSession[], columns: n
TRUNCATE_LENGTHS.SHORT,
columns - visibleWidth(displayId) - visibleWidth(Bun.stripANSI(badge)) - 10,
);
line += `${theme.fg("accent", ":")} ${theme.fg("accent", truncateToWidth(replaceTabs(distinctDescription), budget))}`;
const formatted = replaceTabs(distinctDescription).replace(/\s*[\r\n]+\s*/g, " ↵ ");
line += `${theme.fg("accent", ":")} ${theme.fg("accent", truncateToWidth(formatted, budget))}`;
} else {
// No spawn description: fall back to a muted task preview, same as
// the inline task rows when a row has no label.
const taskPreview = session.progress?.task?.trim();
if (taskPreview && !labelEchoesHandle(session.id, taskPreview)) {
line += ` ${theme.fg("muted", truncateToWidth(replaceTabs(taskPreview), TRUNCATE_LENGTHS.SHORT))}`;
const formatted = replaceTabs(taskPreview).replace(/\s*[\r\n]+\s*/g, " ↵ ");
line += ` ${theme.fg("muted", truncateToWidth(formatted, TRUNCATE_LENGTHS.SHORT))}`;
}
}
return line;
@@ -182,8 +182,33 @@ describe("subagent HUD lines", () => {
makeSession({ id: "Worker", progress: makeProgress({ id: "Worker", task: "Investigate flaky CI on macOS" }) }),
]);
expect(fromTask).toContain("Worker Investigate flaky CI on macOS");
});
const multiLineTask = render([
makeSession({
id: "ReviewShell",
agent: "scout",
progress: makeProgress({
id: "ReviewShell",
agent: "scout",
task: "Complete assignment thoroughly:\n\n# Target\nFiles: src/foo.ts",
}),
}),
]);
expect(multiLineTask).toContain("ReviewShell");
expect(multiLineTask).toContain("Complete assignment thoroughly: ↵ # Tar");
expect(multiLineTask).not.toContain("\n# Target");
const multiLineDesc = render([
makeSession({
id: "ReviewShell",
agent: "scout",
description: "First line\n\nSecond line",
}),
]);
expect(multiLineDesc).toContain("ReviewShell");
expect(multiLineDesc).toContain("First line ↵ Second line");
expect(multiLineDesc).not.toContain("\nSecond line");
});
it("hides non-detached spawns: sync task calls and eval agent() helpers", () => {
// Sync task spawn (parent blocked on the call) and eval `agent()` spawn
// (no detached flag at all) both stay off the HUD.