feat(maestro): keep agent text visible, collapse only tool calls

Agent text and thought rows stay outside the collapsed tool group as
standalone transcript items instead of being absorbed into it.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Miguel Palhas
2026-09-10 21:55:06 +01:00
co-authored by Claude Opus 4.6
parent cd2184b128
commit cb25320ea0
3 changed files with 21 additions and 74 deletions
+5 -23
View File
@@ -124,7 +124,7 @@ describe("activity grouping", () => {
expect(activityGroupsByTurn(rows, null, false).size).toBe(0);
});
it("absorbs intermediate narration but keeps the final answer outside", () => {
it("keeps intermediate text outside the group as standalone items", () => {
const rows = [
text("user:1", "user", "go"),
tool("tool:1"),
@@ -133,11 +133,11 @@ describe("activity grouping", () => {
text("agent:2", "agent_text", "done"),
];
const group = activityGroupsByTurn(rows, null, false).get("turn:user:1")!;
expect(group.rows.map((r) => r.id)).toEqual(["tool:1", "agent:1", "tool:2"]);
expect(group.rows.map((r) => r.id)).toEqual(["tool:1", "tool:2"]);
expect(group.toolCount).toBe(2);
});
it("keeps the newest thought outside while the turn is still live", () => {
it("keeps thoughts outside the group as standalone items", () => {
const rows = [
text("user:1", "user", "go"),
tool("tool:1"),
@@ -145,26 +145,8 @@ describe("activity grouping", () => {
text("thought:1", "agent_thought", "hmm"),
text("thought:2", "agent_thought", "aha"),
];
const live = activityGroupsByTurn(rows, null, true).get("turn:user:1")!;
expect(live.rows.map((r) => r.id)).toEqual(["tool:1", "tool:2", "thought:1"]);
const ended = activityGroupsByTurn(rows, null, false).get("turn:user:1")!;
expect(ended.rows.map((r) => r.id)).toEqual(["tool:1", "tool:2", "thought:1", "thought:2"]);
});
it("keeps the newest agent_text outside while the turn is still live", () => {
const rows = [
text("user:1", "user", "go"),
tool("tool:1"),
text("agent:1", "agent_text", "working on it"),
tool("tool:2"),
text("agent:2", "agent_text", "almost done"),
];
const live = activityGroupsByTurn(rows, null, true).get("turn:user:1")!;
// "almost done" stays outside as visible narration while the turn is live
expect(live.rows.map((r) => r.id)).toEqual(["tool:1", "agent:1", "tool:2"]);
const ended = activityGroupsByTurn(rows, null, false).get("turn:user:1")!;
// Once ended, the final agent_text stays outside as the answer
expect(ended.rows.map((r) => r.id)).toEqual(["tool:1", "agent:1", "tool:2"]);
const group = activityGroupsByTurn(rows, null, false).get("turn:user:1")!;
expect(group.rows.map((r) => r.id)).toEqual(["tool:1", "tool:2"]);
});
it("tracks the last tool's label and argument for the collapsed header", () => {