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:
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user