lsd-pi 1.3.6 → 1.3.7
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.
- package/dist/cli.js +2 -1
- package/dist/lsd-settings-manager.d.ts +2 -0
- package/dist/lsd-settings-manager.js +5 -0
- package/dist/resource-loader.js +33 -3
- package/dist/resources/extensions/cache-timer/index.js +3 -2
- package/dist/welcome-screen.js +2 -2
- package/package.json +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.collapse-tool-calls.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.collapse-tool-calls.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.collapse-tool-calls.test.js +35 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.collapse-tool-calls.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +6 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.js +12 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/edit-diff.d.ts +5 -0
- package/packages/pi-coding-agent/dist/core/tools/edit-diff.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/edit-diff.js +21 -0
- package/packages/pi-coding-agent/dist/core/tools/edit-diff.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/edit-diff.test.js +16 -1
- package/packages/pi-coding-agent/dist/core/tools/edit-diff.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-summary-line.test.js +12 -4
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-summary-line.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/diff.d.ts +7 -5
- package/packages/pi-coding-agent/dist/modes/interactive/components/diff.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/diff.js +86 -28
- package/packages/pi-coding-agent/dist/modes/interactive/components/diff.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +16 -10
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts +4 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js +26 -4
- package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +14 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +111 -12
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-summary-line.d.ts +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-summary-line.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-summary-line.js +47 -3
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-summary-line.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/__tests__/chat-controller.collapsed-tool-summary.test.js +137 -6
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/__tests__/chat-controller.collapsed-tool-summary.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +40 -14
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/extension-ui-controller.js +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/extension-ui-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +5 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +70 -25
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js +4 -4
- package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js.map +1 -1
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/src/core/settings-manager.collapse-tool-calls.test.ts +46 -0
- package/packages/pi-coding-agent/src/core/settings-manager.ts +18 -0
- package/packages/pi-coding-agent/src/core/tools/edit-diff.test.ts +20 -0
- package/packages/pi-coding-agent/src/core/tools/edit-diff.ts +26 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-summary-line.test.ts +14 -4
- package/packages/pi-coding-agent/src/modes/interactive/components/diff.ts +105 -28
- package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +13 -6
- package/packages/pi-coding-agent/src/modes/interactive/components/settings-selector.ts +31 -4
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +119 -13
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-summary-line.ts +59 -3
- package/packages/pi-coding-agent/src/modes/interactive/controllers/__tests__/chat-controller.collapsed-tool-summary.test.ts +174 -6
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +50 -14
- package/packages/pi-coding-agent/src/modes/interactive/controllers/extension-ui-controller.ts +1 -1
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-state.ts +1 -0
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +73 -25
- package/packages/pi-coding-agent/src/modes/interactive/theme/themes.ts +4 -4
- package/packages/pi-tui/dist/components/editor.js +3 -3
- package/packages/pi-tui/dist/components/editor.js.map +1 -1
- package/packages/pi-tui/src/components/editor.ts +3 -3
- package/pkg/dist/modes/interactive/theme/themes.js +4 -4
- package/pkg/dist/modes/interactive/theme/themes.js.map +1 -1
- package/pkg/package.json +1 -1
- package/src/resources/extensions/cache-timer/index.ts +3 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-summary-line.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/tool-summary-line.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAE9C,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAO1C,MAAM,OAAO,eAAgB,SAAQ,SAAS;IAK7C;QACC,KAAK,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"tool-summary-line.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/tool-summary-line.ts"],"names":[],"mappings":"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","sourcesContent":["import { Container, Text } from \"@gsd/pi-tui\";\n\nimport { theme } from \"../theme/theme.js\";\n\ninterface CollapsedTool {\n\tname: string;\n\telapsed: number;\n}\n\n// Tools that can be mixed together in one summary line\nconst MIXED_GROUPABLE_TOOLS = new Set([\n\t\"read\", \"find\", \"ls\", \"grep\", \"lsp\",\n]);\n\ntype SummaryDescriptor = {\n\taction: string;\n\tsingular: string;\n\tplural: string;\n};\n\nconst TOOL_SUMMARY_DESCRIPTORS: Record<string, SummaryDescriptor> = {\n\tread: { action: \"reading\", singular: \"file\", plural: \"files\" },\n\twrite: { action: \"editing\", singular: \"file\", plural: \"files\" },\n\tedit: { action: \"editing\", singular: \"file\", plural: \"files\" },\n\tgrep: { action: \"searching for\", singular: \"pattern\", plural: \"patterns\" },\n\tfind: { action: \"finding\", singular: \"path\", plural: \"paths\" },\n\tls: { action: \"listing\", singular: \"directory\", plural: \"directories\" },\n\tlsp: { action: \"looking up\", singular: \"symbol\", plural: \"symbols\" },\n\tbash: { action: \"running\", singular: \"command\", plural: \"commands\" },\n\tbg_shell: { action: \"running\", singular: \"background command\", plural: \"background commands\" },\n\tfetch_page: { action: \"reading\", singular: \"page\", plural: \"pages\" },\n\tresolve_library: { action: \"searching for\", singular: \"library\", plural: \"libraries\" },\n\tget_library_docs: { action: \"reading\", singular: \"doc\", plural: \"docs\" },\n\tweb_search: { action: \"searching web for\", singular: \"query\", plural: \"queries\" },\n\t\"search-the-web\": { action: \"searching web for\", singular: \"query\", plural: \"queries\" },\n\tsearch_and_read: { action: \"researching\", singular: \"topic\", plural: \"topics\" },\n\tgoogle_search: { action: \"searching web for\", singular: \"query\", plural: \"queries\" },\n};\n\nfunction formatCount(count: number, singular: string, plural: string): string {\n\treturn `${count} ${count === 1 ? singular : plural}`;\n}\n\nfunction summarizeToolGroup(name: string, count: number): string {\n\tif (name.startsWith(\"browser_\")) {\n\t\treturn `using browser for ${formatCount(count, \"step\", \"steps\")}`;\n\t}\n\n\tconst descriptor = TOOL_SUMMARY_DESCRIPTORS[name];\n\tif (!descriptor) {\n\t\treturn count > 1 ? `${name} ×${count}` : name;\n\t}\n\n\treturn `${descriptor.action} ${formatCount(count, descriptor.singular, descriptor.plural)}`;\n}\n\nexport class ToolSummaryLine extends Container {\n\tprivate tools: CollapsedTool[] = [];\n\tprivate hidden = false;\n\tprivate contentText: Text;\n\n\tcanGroupWith(toolName: string): boolean {\n\t\tif (this.tools.length === 0) return true;\n\t\t// Mixed-groupable tools can share a summary line regardless of order\n\t\tif (MIXED_GROUPABLE_TOOLS.has(toolName) && this.tools.every((t) => MIXED_GROUPABLE_TOOLS.has(t.name))) {\n\t\t\treturn true;\n\t\t}\n\t\t// Otherwise only same-tool grouping\n\t\treturn this.tools.every((tool) => tool.name === toolName);\n\t}\n\n\tconstructor() {\n\t\tsuper();\n\t\tthis.contentText = new Text(\"\", 1, 0);\n\t\tthis.addChild(this.contentText);\n\t}\n\n\taddTool(name: string, elapsed: number): void {\n\t\tthis.tools.push({ name, elapsed });\n\t\tthis.updateDisplay();\n\t}\n\n\tsetHidden(hidden: boolean): void {\n\t\tthis.hidden = hidden;\n\t}\n\n\toverride invalidate(): void {\n\t\tsuper.invalidate();\n\t\tthis.updateDisplay();\n\t}\n\n\toverride render(width: number): string[] {\n\t\tif (this.hidden || this.tools.length === 0) {\n\t\t\treturn [];\n\t\t}\n\t\treturn super.render(width);\n\t}\n\n\tprivate updateDisplay(): void {\n\t\tif (this.tools.length === 0) {\n\t\t\tthis.contentText.setText(\"\");\n\t\t\treturn;\n\t\t}\n\n\t\tconst counts = new Map<string, number>();\n\t\tlet totalElapsed = 0;\n\t\tfor (const tool of this.tools) {\n\t\t\tcounts.set(tool.name, (counts.get(tool.name) ?? 0) + 1);\n\t\t\ttotalElapsed += tool.elapsed;\n\t\t}\n\n\t\tconst groupedTools = [...counts.entries()]\n\t\t\t.map(([name, count]) => summarizeToolGroup(name, count))\n\t\t\t.join(\" · \");\n\t\tconst elapsed = (totalElapsed / 1000).toFixed(1);\n\t\tconst indicator = theme.fg(\"success\", \"●\");\n\t\tconst details = theme.fg(\"muted\", `${groupedTools} · ${elapsed}s`);\n\t\tthis.contentText.setText(`${indicator} ${details}`);\n\t}\n}\n"]}
|
|
@@ -12,6 +12,14 @@ function assistantMessage(content = []) {
|
|
|
12
12
|
timestamp: Date.now(),
|
|
13
13
|
};
|
|
14
14
|
}
|
|
15
|
+
function toolStartEvent(toolCallId, toolName, args = {}) {
|
|
16
|
+
return {
|
|
17
|
+
type: "tool_execution_start",
|
|
18
|
+
toolCallId,
|
|
19
|
+
toolName,
|
|
20
|
+
args,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
15
23
|
function toolEndEvent(toolCallId, toolName) {
|
|
16
24
|
return {
|
|
17
25
|
type: "tool_execution_end",
|
|
@@ -38,7 +46,7 @@ function createChatContainer() {
|
|
|
38
46
|
},
|
|
39
47
|
};
|
|
40
48
|
}
|
|
41
|
-
function createHost() {
|
|
49
|
+
function createHost(options = {}) {
|
|
42
50
|
const chatContainer = createChatContainer();
|
|
43
51
|
return {
|
|
44
52
|
isInitialized: true,
|
|
@@ -55,10 +63,12 @@ function createHost() {
|
|
|
55
63
|
getShowImages: () => true,
|
|
56
64
|
getToolOutputMode: () => "normal",
|
|
57
65
|
getEditorScheme: () => "auto",
|
|
66
|
+
getCollapseToolCalls: () => options.collapseToolCalls ?? true,
|
|
58
67
|
},
|
|
59
68
|
pendingTools: new Map(),
|
|
60
69
|
collapsedToolSummaryLine: undefined,
|
|
61
|
-
|
|
70
|
+
collapsedToolCallsExpanded: options.collapsedToolCallsExpanded ?? options.toolOutputExpanded ?? false,
|
|
71
|
+
toolOutputExpanded: options.toolOutputExpanded ?? false,
|
|
62
72
|
hideThinkingBlock: false,
|
|
63
73
|
notificationSoundEnabled: false,
|
|
64
74
|
defaultEditor: { onEscape: undefined, bottomHint: "" },
|
|
@@ -115,7 +125,61 @@ function summaryLines(host) {
|
|
|
115
125
|
return host.chatContainer.children.filter((child) => child instanceof ToolSummaryLine);
|
|
116
126
|
}
|
|
117
127
|
describe("chat-controller collapsed tool summary lifecycle", () => {
|
|
118
|
-
it("
|
|
128
|
+
it("hides collapsible tool calls immediately to avoid blink before grouping", async () => {
|
|
129
|
+
const host = createHost();
|
|
130
|
+
await handleAgentEvent(host, {
|
|
131
|
+
type: "message_start",
|
|
132
|
+
message: assistantMessage(),
|
|
133
|
+
});
|
|
134
|
+
await handleAgentEvent(host, toolStartEvent("tool-1", "read", { path: "README.md" }));
|
|
135
|
+
const pending = host.pendingTools.get("tool-1");
|
|
136
|
+
assert.ok(pending);
|
|
137
|
+
assert.equal(pending.isHidden(), true);
|
|
138
|
+
await handleAgentEvent(host, toolEndEvent("tool-1", "read"));
|
|
139
|
+
assert.equal(summaryLines(host).length, 1);
|
|
140
|
+
});
|
|
141
|
+
it("hides streamed tool-call blocks immediately to avoid blink before grouping", async () => {
|
|
142
|
+
const host = createHost();
|
|
143
|
+
await handleAgentEvent(host, {
|
|
144
|
+
type: "message_start",
|
|
145
|
+
message: assistantMessage(),
|
|
146
|
+
});
|
|
147
|
+
await handleAgentEvent(host, {
|
|
148
|
+
type: "message_update",
|
|
149
|
+
message: assistantMessage([
|
|
150
|
+
{ type: "toolCall", id: "tool-1", name: "read", arguments: { path: "README.md" } },
|
|
151
|
+
]),
|
|
152
|
+
});
|
|
153
|
+
const pending = host.pendingTools.get("tool-1");
|
|
154
|
+
assert.ok(pending);
|
|
155
|
+
assert.equal(pending.isHidden(), true);
|
|
156
|
+
await handleAgentEvent(host, toolEndEvent("tool-1", "read"));
|
|
157
|
+
assert.equal(summaryLines(host).length, 1);
|
|
158
|
+
});
|
|
159
|
+
it("reveals initially hidden on-error tools when they fail", async () => {
|
|
160
|
+
const host = createHost();
|
|
161
|
+
await handleAgentEvent(host, {
|
|
162
|
+
type: "message_start",
|
|
163
|
+
message: assistantMessage(),
|
|
164
|
+
});
|
|
165
|
+
await handleAgentEvent(host, toolStartEvent("tool-1", "bash", { command: "exit 1" }));
|
|
166
|
+
const pending = host.pendingTools.get("tool-1");
|
|
167
|
+
assert.ok(pending);
|
|
168
|
+
assert.equal(pending.isHidden(), true);
|
|
169
|
+
await handleAgentEvent(host, {
|
|
170
|
+
type: "tool_execution_end",
|
|
171
|
+
toolCallId: "tool-1",
|
|
172
|
+
toolName: "bash",
|
|
173
|
+
isError: true,
|
|
174
|
+
result: {
|
|
175
|
+
content: [{ type: "text", text: "failed" }],
|
|
176
|
+
details: {},
|
|
177
|
+
},
|
|
178
|
+
});
|
|
179
|
+
assert.equal(summaryLines(host).length, 0);
|
|
180
|
+
assert.equal(pending.isHidden(), false);
|
|
181
|
+
});
|
|
182
|
+
it("groups consecutive identical collapsed tools", async () => {
|
|
119
183
|
const host = createHost();
|
|
120
184
|
await handleAgentEvent(host, {
|
|
121
185
|
type: "message_start",
|
|
@@ -132,7 +196,37 @@ describe("chat-controller collapsed tool summary lifecycle", () => {
|
|
|
132
196
|
await handleAgentEvent(host, toolEndEvent("tool-2", "read"));
|
|
133
197
|
const summaries = summaryLines(host);
|
|
134
198
|
assert.equal(summaries.length, 1);
|
|
135
|
-
assert.ok(stripAnsi(summaries[0].render(160).join("\n")).includes("
|
|
199
|
+
assert.ok(stripAnsi(summaries[0].render(160).join("\n")).includes("reading 2 files · 1.0s"));
|
|
200
|
+
});
|
|
201
|
+
it("does not group web fetches", async () => {
|
|
202
|
+
const host = createHost();
|
|
203
|
+
await handleAgentEvent(host, {
|
|
204
|
+
type: "message_start",
|
|
205
|
+
message: assistantMessage(),
|
|
206
|
+
});
|
|
207
|
+
addPendingTool(host, "tool-1", 200);
|
|
208
|
+
await handleAgentEvent(host, toolEndEvent("tool-1", "fetch_page"));
|
|
209
|
+
addPendingTool(host, "tool-2", 300);
|
|
210
|
+
await handleAgentEvent(host, toolEndEvent("tool-2", "fetch_page"));
|
|
211
|
+
const summaries = summaryLines(host);
|
|
212
|
+
assert.equal(summaries.length, 2);
|
|
213
|
+
assert.ok(stripAnsi(summaries[0].render(160).join("\n")).includes("reading 1 page · 0.2s"));
|
|
214
|
+
assert.ok(stripAnsi(summaries[1].render(160).join("\n")).includes("reading 1 page · 0.3s"));
|
|
215
|
+
});
|
|
216
|
+
it("keeps different collapsed tool types in separate summaries", async () => {
|
|
217
|
+
const host = createHost();
|
|
218
|
+
await handleAgentEvent(host, {
|
|
219
|
+
type: "message_start",
|
|
220
|
+
message: assistantMessage(),
|
|
221
|
+
});
|
|
222
|
+
addPendingTool(host, "tool-1", 200);
|
|
223
|
+
await handleAgentEvent(host, toolEndEvent("tool-1", "read"));
|
|
224
|
+
addPendingTool(host, "tool-2", 300);
|
|
225
|
+
await handleAgentEvent(host, toolEndEvent("tool-2", "find"));
|
|
226
|
+
const summaries = summaryLines(host);
|
|
227
|
+
assert.equal(summaries.length, 2);
|
|
228
|
+
assert.ok(stripAnsi(summaries[0].render(160).join("\n")).includes("reading 1 file · 0.2s"));
|
|
229
|
+
assert.ok(stripAnsi(summaries[1].render(160).join("\n")).includes("finding 1 path · 0.3s"));
|
|
136
230
|
});
|
|
137
231
|
it("resets grouping after visible tool result", async () => {
|
|
138
232
|
const host = createHost();
|
|
@@ -152,7 +246,7 @@ describe("chat-controller collapsed tool summary lifecycle", () => {
|
|
|
152
246
|
assert.ok(stripAnsi(summaries[0].render(160).join("\n")).includes("0.2s"));
|
|
153
247
|
assert.ok(stripAnsi(summaries[1].render(160).join("\n")).includes("0.4s"));
|
|
154
248
|
});
|
|
155
|
-
it("
|
|
249
|
+
it("groups identical collapsed tools across empty assistant message boundaries", async () => {
|
|
156
250
|
const host = createHost();
|
|
157
251
|
await handleAgentEvent(host, {
|
|
158
252
|
type: "message_start",
|
|
@@ -168,7 +262,7 @@ describe("chat-controller collapsed tool summary lifecycle", () => {
|
|
|
168
262
|
await handleAgentEvent(host, toolEndEvent("tool-2", "read"));
|
|
169
263
|
const summaries = summaryLines(host);
|
|
170
264
|
assert.equal(summaries.length, 1);
|
|
171
|
-
assert.ok(stripAnsi(summaries[0].render(160).join("\n")).includes("
|
|
265
|
+
assert.ok(stripAnsi(summaries[0].render(160).join("\n")).includes("reading 2 files · 0.7s"));
|
|
172
266
|
});
|
|
173
267
|
it("starts new collapsed group after visible assistant content", async () => {
|
|
174
268
|
const host = createHost();
|
|
@@ -193,5 +287,42 @@ describe("chat-controller collapsed tool summary lifecycle", () => {
|
|
|
193
287
|
assert.ok(stripAnsi(summaries[0].render(160).join("\n")).includes("0.3s"));
|
|
194
288
|
assert.ok(stripAnsi(summaries[1].render(160).join("\n")).includes("0.4s"));
|
|
195
289
|
});
|
|
290
|
+
it("keeps collapsed tool calls visible in intermediate mode", async () => {
|
|
291
|
+
const host = createHost({ collapseToolCalls: true, collapsedToolCallsExpanded: true });
|
|
292
|
+
await handleAgentEvent(host, {
|
|
293
|
+
type: "message_start",
|
|
294
|
+
message: assistantMessage(),
|
|
295
|
+
});
|
|
296
|
+
const tool = addPendingTool(host, "tool-1", 250);
|
|
297
|
+
await handleAgentEvent(host, toolEndEvent("tool-1", "read"));
|
|
298
|
+
const summaries = summaryLines(host);
|
|
299
|
+
assert.equal(tool.hidden, false);
|
|
300
|
+
assert.equal(summaries.length, 1);
|
|
301
|
+
assert.deepEqual(summaries[0].render(160), []);
|
|
302
|
+
});
|
|
303
|
+
it("keeps collapsed tools visible when verbose mode is active", async () => {
|
|
304
|
+
const host = createHost({ collapseToolCalls: true, toolOutputExpanded: true });
|
|
305
|
+
await handleAgentEvent(host, {
|
|
306
|
+
type: "message_start",
|
|
307
|
+
message: assistantMessage(),
|
|
308
|
+
});
|
|
309
|
+
const tool = addPendingTool(host, "tool-1", 250);
|
|
310
|
+
await handleAgentEvent(host, toolEndEvent("tool-1", "read"));
|
|
311
|
+
const summaries = summaryLines(host);
|
|
312
|
+
assert.equal(tool.hidden, false);
|
|
313
|
+
assert.equal(summaries.length, 1);
|
|
314
|
+
assert.deepEqual(summaries[0].render(160), []);
|
|
315
|
+
});
|
|
316
|
+
it("does not collapse tool calls when setting is disabled", async () => {
|
|
317
|
+
const host = createHost({ collapseToolCalls: false });
|
|
318
|
+
await handleAgentEvent(host, {
|
|
319
|
+
type: "message_start",
|
|
320
|
+
message: assistantMessage(),
|
|
321
|
+
});
|
|
322
|
+
const tool = addPendingTool(host, "tool-1", 250);
|
|
323
|
+
await handleAgentEvent(host, toolEndEvent("tool-1", "read"));
|
|
324
|
+
assert.equal(tool.hidden, false);
|
|
325
|
+
assert.equal(summaryLines(host).length, 0);
|
|
326
|
+
});
|
|
196
327
|
});
|
|
197
328
|
//# sourceMappingURL=chat-controller.collapsed-tool-summary.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat-controller.collapsed-tool-summary.test.js","sourceRoot":"","sources":["../../../../../src/modes/interactive/controllers/__tests__/chat-controller.collapsed-tool-summary.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, it } from \"node:test\";\nimport assert from \"node:assert/strict\";\nimport stripAnsi from \"strip-ansi\";\n\nimport { handleAgentEvent } from \"../chat-controller.js\";\nimport { ToolSummaryLine } from \"../../components/tool-summary-line.js\";\nimport { getMarkdownTheme, initTheme } from \"../../theme/theme.js\";\n\ninitTheme(\"dark\");\n\nfunction assistantMessage(content: any[] = []): any {\n return {\n role: \"assistant\",\n content,\n timestamp: Date.now(),\n };\n}\n\nfunction toolEndEvent(toolCallId: string, toolName: string): any {\n return {\n type: \"tool_execution_end\",\n toolCallId,\n toolName,\n isError: false,\n result: {\n content: [],\n details: {},\n },\n };\n}\n\nfunction createChatContainer() {\n return {\n children: [] as any[],\n addChild(child: any) {\n this.children.push(child);\n },\n removeChild(child: any) {\n this.children = this.children.filter((c) => c !== child);\n },\n clear() {\n this.children = [];\n },\n };\n}\n\nfunction createHost(): any {\n const chatContainer = createChatContainer();\n return {\n isInitialized: true,\n init: async () => { },\n ui: {\n requestRender: () => { },\n terminal: { write: () => { } },\n },\n footer: { invalidate: () => { } },\n statusContainer: { clear: () => { }, addChild: () => { } },\n chatContainer,\n settingsManager: {\n getTimestampFormat: () => \"date-time-iso\",\n getShowImages: () => true,\n getToolOutputMode: () => \"normal\",\n getEditorScheme: () => \"auto\",\n },\n pendingTools: new Map(),\n collapsedToolSummaryLine: undefined,\n toolOutputExpanded: false,\n hideThinkingBlock: false,\n notificationSoundEnabled: false,\n defaultEditor: { onEscape: undefined, bottomHint: \"\" },\n session: {\n thinkingLevel: \"off\",\n retryAttempt: 0,\n abortCompaction: () => { },\n abortRetry: () => { },\n },\n keybindings: {},\n pendingMessagesContainer: { clear: () => { } },\n compactionQueuedMessages: [],\n defaultWorkingMessage: \"\",\n workingMessages: [],\n startLoadingTips: () => { },\n stopLoadingTips: () => { },\n getMarkdownThemeWithSettings: () => getMarkdownTheme(),\n addMessageToChat: () => { },\n formatWebSearchResult: () => \"\",\n getRegisteredToolDefinition: () => undefined,\n checkShutdownRequested: async () => { },\n rebuildChatFromMessages: () => { },\n flushCompactionQueue: async () => { },\n showStatus: () => { },\n showError: () => { },\n updatePendingMessagesDisplay: () => { },\n updateTerminalTitle: () => { },\n updateEditorBorderColor: () => { },\n updateEditorExpandHint: () => { },\n getAgentPtyComponent: () => undefined,\n ensureAgentPtyComponent: () => undefined,\n updateAgentPtyComponent: () => { },\n clearAgentPtyComponents: () => { },\n };\n}\n\nfunction addPendingTool(host: any, toolCallId: string, elapsed: number): { hidden?: boolean; component: any } {\n const state: { hidden?: boolean; component: any } = { hidden: false, component: undefined };\n const component = {\n render: () => (state.hidden ? [] : [\"tool\"]),\n updateResult: () => { },\n setHidden: (hidden: boolean) => {\n state.hidden = hidden;\n },\n isHidden: () => !!state.hidden,\n setArgsComplete: () => { },\n getElapsed: () => elapsed,\n };\n state.component = component;\n host.chatContainer.addChild(component);\n host.pendingTools.set(toolCallId, component);\n return state;\n}\n\nfunction summaryLines(host: any): ToolSummaryLine[] {\n return host.chatContainer.children.filter((child: any) => child instanceof ToolSummaryLine);\n}\n\ndescribe(\"chat-controller collapsed tool summary lifecycle\", () => {\n it(\"keeps single grouped summary across text-only message updates\", async () => {\n const host = createHost();\n\n await handleAgentEvent(host, {\n type: \"message_start\",\n message: assistantMessage(),\n });\n\n const first = addPendingTool(host, \"tool-1\", 400);\n await handleAgentEvent(host, toolEndEvent(\"tool-1\", \"read\"));\n assert.equal(host.chatContainer.children.indexOf(summaryLines(host)[0]), host.chatContainer.children.indexOf(first.component) - 1);\n\n await handleAgentEvent(host, {\n type: \"message_update\",\n message: assistantMessage([{ type: \"text\", text: \"streaming text\" }]),\n } as any);\n\n addPendingTool(host, \"tool-2\", 600);\n await handleAgentEvent(host, toolEndEvent(\"tool-2\", \"read\"));\n\n const summaries = summaryLines(host);\n assert.equal(summaries.length, 1);\n assert.ok(stripAnsi(summaries[0].render(160).join(\"\\n\")).includes(\"read ×2 · 1.0s\"));\n });\n\n it(\"resets grouping after visible tool result\", async () => {\n const host = createHost();\n\n await handleAgentEvent(host, {\n type: \"message_start\",\n message: assistantMessage(),\n });\n\n addPendingTool(host, \"tool-1\", 200);\n await handleAgentEvent(host, toolEndEvent(\"tool-1\", \"read\"));\n\n const visibleTool = addPendingTool(host, \"tool-2\", 300);\n await handleAgentEvent(host, toolEndEvent(\"tool-2\", \"write\"));\n assert.equal(visibleTool.hidden, false);\n\n addPendingTool(host, \"tool-3\", 400);\n await handleAgentEvent(host, toolEndEvent(\"tool-3\", \"read\"));\n\n const summaries = summaryLines(host);\n assert.equal(summaries.length, 2);\n assert.ok(stripAnsi(summaries[0].render(160).join(\"\\n\")).includes(\"0.2s\"));\n assert.ok(stripAnsi(summaries[1].render(160).join(\"\\n\")).includes(\"0.4s\"));\n });\n\n it(\"merges adjacent collapsed groups across empty assistant message boundaries\", async () => {\n const host = createHost();\n\n await handleAgentEvent(host, {\n type: \"message_start\",\n message: assistantMessage(),\n });\n\n addPendingTool(host, \"tool-1\", 300);\n await handleAgentEvent(host, toolEndEvent(\"tool-1\", \"read\"));\n\n await handleAgentEvent(host, {\n type: \"message_start\",\n message: assistantMessage(),\n });\n\n addPendingTool(host, \"tool-2\", 400);\n await handleAgentEvent(host, toolEndEvent(\"tool-2\", \"read\"));\n\n const summaries = summaryLines(host);\n assert.equal(summaries.length, 1);\n assert.ok(stripAnsi(summaries[0].render(160).join(\"\\n\")).includes(\"read ×2 · 0.7s\"));\n });\n\n it(\"starts new collapsed group after visible assistant content\", async () => {\n const host = createHost();\n\n await handleAgentEvent(host, {\n type: \"message_start\",\n message: assistantMessage(),\n });\n\n addPendingTool(host, \"tool-1\", 300);\n await handleAgentEvent(host, toolEndEvent(\"tool-1\", \"read\"));\n\n await handleAgentEvent(host, {\n type: \"message_start\",\n message: assistantMessage(),\n });\n await handleAgentEvent(host, {\n type: \"message_update\",\n message: assistantMessage([{ type: \"text\", text: \"visible reply\" }]),\n } as any);\n\n addPendingTool(host, \"tool-2\", 400);\n await handleAgentEvent(host, toolEndEvent(\"tool-2\", \"read\"));\n\n const summaries = summaryLines(host);\n assert.equal(summaries.length, 2);\n assert.ok(stripAnsi(summaries[0].render(160).join(\"\\n\")).includes(\"0.3s\"));\n assert.ok(stripAnsi(summaries[1].render(160).join(\"\\n\")).includes(\"0.4s\"));\n });\n});\n"]}
|
|
1
|
+
{"version":3,"file":"chat-controller.collapsed-tool-summary.test.js","sourceRoot":"","sources":["../../../../../src/modes/interactive/controllers/__tests__/chat-controller.collapsed-tool-summary.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, it } from \"node:test\";\nimport assert from \"node:assert/strict\";\nimport stripAnsi from \"strip-ansi\";\n\nimport { handleAgentEvent } from \"../chat-controller.js\";\nimport { ToolSummaryLine } from \"../../components/tool-summary-line.js\";\nimport { getMarkdownTheme, initTheme } from \"../../theme/theme.js\";\n\ninitTheme(\"dark\");\n\nfunction assistantMessage(content: any[] = []): any {\n return {\n role: \"assistant\",\n content,\n timestamp: Date.now(),\n };\n}\n\nfunction toolStartEvent(toolCallId: string, toolName: string, args: Record<string, unknown> = {}): any {\n return {\n type: \"tool_execution_start\",\n toolCallId,\n toolName,\n args,\n };\n}\n\nfunction toolEndEvent(toolCallId: string, toolName: string): any {\n return {\n type: \"tool_execution_end\",\n toolCallId,\n toolName,\n isError: false,\n result: {\n content: [],\n details: {},\n },\n };\n}\n\nfunction createChatContainer() {\n return {\n children: [] as any[],\n addChild(child: any) {\n this.children.push(child);\n },\n removeChild(child: any) {\n this.children = this.children.filter((c) => c !== child);\n },\n clear() {\n this.children = [];\n },\n };\n}\n\nfunction createHost(options: { collapseToolCalls?: boolean; collapsedToolCallsExpanded?: boolean; toolOutputExpanded?: boolean } = {}): any {\n const chatContainer = createChatContainer();\n return {\n isInitialized: true,\n init: async () => { },\n ui: {\n requestRender: () => { },\n terminal: { write: () => { } },\n },\n footer: { invalidate: () => { } },\n statusContainer: { clear: () => { }, addChild: () => { } },\n chatContainer,\n settingsManager: {\n getTimestampFormat: () => \"date-time-iso\",\n getShowImages: () => true,\n getToolOutputMode: () => \"normal\",\n getEditorScheme: () => \"auto\",\n getCollapseToolCalls: () => options.collapseToolCalls ?? true,\n },\n pendingTools: new Map(),\n collapsedToolSummaryLine: undefined,\n collapsedToolCallsExpanded: options.collapsedToolCallsExpanded ?? options.toolOutputExpanded ?? false,\n toolOutputExpanded: options.toolOutputExpanded ?? false,\n hideThinkingBlock: false,\n notificationSoundEnabled: false,\n defaultEditor: { onEscape: undefined, bottomHint: \"\" },\n session: {\n thinkingLevel: \"off\",\n retryAttempt: 0,\n abortCompaction: () => { },\n abortRetry: () => { },\n },\n keybindings: {},\n pendingMessagesContainer: { clear: () => { } },\n compactionQueuedMessages: [],\n defaultWorkingMessage: \"\",\n workingMessages: [],\n startLoadingTips: () => { },\n stopLoadingTips: () => { },\n getMarkdownThemeWithSettings: () => getMarkdownTheme(),\n addMessageToChat: () => { },\n formatWebSearchResult: () => \"\",\n getRegisteredToolDefinition: () => undefined,\n checkShutdownRequested: async () => { },\n rebuildChatFromMessages: () => { },\n flushCompactionQueue: async () => { },\n showStatus: () => { },\n showError: () => { },\n updatePendingMessagesDisplay: () => { },\n updateTerminalTitle: () => { },\n updateEditorBorderColor: () => { },\n updateEditorExpandHint: () => { },\n getAgentPtyComponent: () => undefined,\n ensureAgentPtyComponent: () => undefined,\n updateAgentPtyComponent: () => { },\n clearAgentPtyComponents: () => { },\n };\n}\n\nfunction addPendingTool(host: any, toolCallId: string, elapsed: number): { hidden?: boolean; component: any } {\n const state: { hidden?: boolean; component: any } = { hidden: false, component: undefined };\n const component = {\n render: () => (state.hidden ? [] : [\"tool\"]),\n updateResult: () => { },\n setHidden: (hidden: boolean) => {\n state.hidden = hidden;\n },\n isHidden: () => !!state.hidden,\n setArgsComplete: () => { },\n getElapsed: () => elapsed,\n };\n state.component = component;\n host.chatContainer.addChild(component);\n host.pendingTools.set(toolCallId, component);\n return state;\n}\n\nfunction summaryLines(host: any): ToolSummaryLine[] {\n return host.chatContainer.children.filter((child: any) => child instanceof ToolSummaryLine);\n}\n\ndescribe(\"chat-controller collapsed tool summary lifecycle\", () => {\n it(\"hides collapsible tool calls immediately to avoid blink before grouping\", async () => {\n const host = createHost();\n\n await handleAgentEvent(host, {\n type: \"message_start\",\n message: assistantMessage(),\n });\n\n await handleAgentEvent(host, toolStartEvent(\"tool-1\", \"read\", { path: \"README.md\" }));\n const pending = host.pendingTools.get(\"tool-1\");\n assert.ok(pending);\n assert.equal(pending.isHidden(), true);\n\n await handleAgentEvent(host, toolEndEvent(\"tool-1\", \"read\"));\n assert.equal(summaryLines(host).length, 1);\n });\n\n it(\"hides streamed tool-call blocks immediately to avoid blink before grouping\", async () => {\n const host = createHost();\n\n await handleAgentEvent(host, {\n type: \"message_start\",\n message: assistantMessage(),\n });\n\n await handleAgentEvent(host, {\n type: \"message_update\",\n message: assistantMessage([\n { type: \"toolCall\", id: \"tool-1\", name: \"read\", arguments: { path: \"README.md\" } },\n ]),\n } as any);\n\n const pending = host.pendingTools.get(\"tool-1\");\n assert.ok(pending);\n assert.equal(pending.isHidden(), true);\n\n await handleAgentEvent(host, toolEndEvent(\"tool-1\", \"read\"));\n assert.equal(summaryLines(host).length, 1);\n });\n\n it(\"reveals initially hidden on-error tools when they fail\", async () => {\n const host = createHost();\n\n await handleAgentEvent(host, {\n type: \"message_start\",\n message: assistantMessage(),\n });\n\n await handleAgentEvent(host, toolStartEvent(\"tool-1\", \"bash\", { command: \"exit 1\" }));\n const pending = host.pendingTools.get(\"tool-1\");\n assert.ok(pending);\n assert.equal(pending.isHidden(), true);\n\n await handleAgentEvent(host, {\n type: \"tool_execution_end\",\n toolCallId: \"tool-1\",\n toolName: \"bash\",\n isError: true,\n result: {\n content: [{ type: \"text\", text: \"failed\" }],\n details: {},\n },\n });\n\n assert.equal(summaryLines(host).length, 0);\n assert.equal(pending.isHidden(), false);\n });\n\n it(\"groups consecutive identical collapsed tools\", async () => {\n const host = createHost();\n\n await handleAgentEvent(host, {\n type: \"message_start\",\n message: assistantMessage(),\n });\n\n const first = addPendingTool(host, \"tool-1\", 400);\n await handleAgentEvent(host, toolEndEvent(\"tool-1\", \"read\"));\n assert.equal(host.chatContainer.children.indexOf(summaryLines(host)[0]), host.chatContainer.children.indexOf(first.component) - 1);\n\n await handleAgentEvent(host, {\n type: \"message_update\",\n message: assistantMessage([{ type: \"text\", text: \"streaming text\" }]),\n } as any);\n\n addPendingTool(host, \"tool-2\", 600);\n await handleAgentEvent(host, toolEndEvent(\"tool-2\", \"read\"));\n\n const summaries = summaryLines(host);\n assert.equal(summaries.length, 1);\n assert.ok(stripAnsi(summaries[0].render(160).join(\"\\n\")).includes(\"reading 2 files · 1.0s\"));\n });\n\n it(\"does not group web fetches\", async () => {\n const host = createHost();\n\n await handleAgentEvent(host, {\n type: \"message_start\",\n message: assistantMessage(),\n });\n\n addPendingTool(host, \"tool-1\", 200);\n await handleAgentEvent(host, toolEndEvent(\"tool-1\", \"fetch_page\"));\n\n addPendingTool(host, \"tool-2\", 300);\n await handleAgentEvent(host, toolEndEvent(\"tool-2\", \"fetch_page\"));\n\n const summaries = summaryLines(host);\n assert.equal(summaries.length, 2);\n assert.ok(stripAnsi(summaries[0].render(160).join(\"\\n\")).includes(\"reading 1 page · 0.2s\"));\n assert.ok(stripAnsi(summaries[1].render(160).join(\"\\n\")).includes(\"reading 1 page · 0.3s\"));\n });\n\n it(\"keeps different collapsed tool types in separate summaries\", async () => {\n const host = createHost();\n\n await handleAgentEvent(host, {\n type: \"message_start\",\n message: assistantMessage(),\n });\n\n addPendingTool(host, \"tool-1\", 200);\n await handleAgentEvent(host, toolEndEvent(\"tool-1\", \"read\"));\n\n addPendingTool(host, \"tool-2\", 300);\n await handleAgentEvent(host, toolEndEvent(\"tool-2\", \"find\"));\n\n const summaries = summaryLines(host);\n assert.equal(summaries.length, 2);\n assert.ok(stripAnsi(summaries[0].render(160).join(\"\\n\")).includes(\"reading 1 file · 0.2s\"));\n assert.ok(stripAnsi(summaries[1].render(160).join(\"\\n\")).includes(\"finding 1 path · 0.3s\"));\n });\n\n it(\"resets grouping after visible tool result\", async () => {\n const host = createHost();\n\n await handleAgentEvent(host, {\n type: \"message_start\",\n message: assistantMessage(),\n });\n\n addPendingTool(host, \"tool-1\", 200);\n await handleAgentEvent(host, toolEndEvent(\"tool-1\", \"read\"));\n\n const visibleTool = addPendingTool(host, \"tool-2\", 300);\n await handleAgentEvent(host, toolEndEvent(\"tool-2\", \"write\"));\n assert.equal(visibleTool.hidden, false);\n\n addPendingTool(host, \"tool-3\", 400);\n await handleAgentEvent(host, toolEndEvent(\"tool-3\", \"read\"));\n\n const summaries = summaryLines(host);\n assert.equal(summaries.length, 2);\n assert.ok(stripAnsi(summaries[0].render(160).join(\"\\n\")).includes(\"0.2s\"));\n assert.ok(stripAnsi(summaries[1].render(160).join(\"\\n\")).includes(\"0.4s\"));\n });\n\n it(\"groups identical collapsed tools across empty assistant message boundaries\", async () => {\n const host = createHost();\n\n await handleAgentEvent(host, {\n type: \"message_start\",\n message: assistantMessage(),\n });\n\n addPendingTool(host, \"tool-1\", 300);\n await handleAgentEvent(host, toolEndEvent(\"tool-1\", \"read\"));\n\n await handleAgentEvent(host, {\n type: \"message_start\",\n message: assistantMessage(),\n });\n\n addPendingTool(host, \"tool-2\", 400);\n await handleAgentEvent(host, toolEndEvent(\"tool-2\", \"read\"));\n\n const summaries = summaryLines(host);\n assert.equal(summaries.length, 1);\n assert.ok(stripAnsi(summaries[0].render(160).join(\"\\n\")).includes(\"reading 2 files · 0.7s\"));\n });\n\n it(\"starts new collapsed group after visible assistant content\", async () => {\n const host = createHost();\n\n await handleAgentEvent(host, {\n type: \"message_start\",\n message: assistantMessage(),\n });\n\n addPendingTool(host, \"tool-1\", 300);\n await handleAgentEvent(host, toolEndEvent(\"tool-1\", \"read\"));\n\n await handleAgentEvent(host, {\n type: \"message_start\",\n message: assistantMessage(),\n });\n await handleAgentEvent(host, {\n type: \"message_update\",\n message: assistantMessage([{ type: \"text\", text: \"visible reply\" }]),\n } as any);\n\n addPendingTool(host, \"tool-2\", 400);\n await handleAgentEvent(host, toolEndEvent(\"tool-2\", \"read\"));\n\n const summaries = summaryLines(host);\n assert.equal(summaries.length, 2);\n assert.ok(stripAnsi(summaries[0].render(160).join(\"\\n\")).includes(\"0.3s\"));\n assert.ok(stripAnsi(summaries[1].render(160).join(\"\\n\")).includes(\"0.4s\"));\n });\n\n it(\"keeps collapsed tool calls visible in intermediate mode\", async () => {\n const host = createHost({ collapseToolCalls: true, collapsedToolCallsExpanded: true });\n\n await handleAgentEvent(host, {\n type: \"message_start\",\n message: assistantMessage(),\n });\n\n const tool = addPendingTool(host, \"tool-1\", 250);\n await handleAgentEvent(host, toolEndEvent(\"tool-1\", \"read\"));\n\n const summaries = summaryLines(host);\n assert.equal(tool.hidden, false);\n assert.equal(summaries.length, 1);\n assert.deepEqual(summaries[0].render(160), []);\n });\n\n it(\"keeps collapsed tools visible when verbose mode is active\", async () => {\n const host = createHost({ collapseToolCalls: true, toolOutputExpanded: true });\n\n await handleAgentEvent(host, {\n type: \"message_start\",\n message: assistantMessage(),\n });\n\n const tool = addPendingTool(host, \"tool-1\", 250);\n await handleAgentEvent(host, toolEndEvent(\"tool-1\", \"read\"));\n\n const summaries = summaryLines(host);\n assert.equal(tool.hidden, false);\n assert.equal(summaries.length, 1);\n assert.deepEqual(summaries[0].render(160), []);\n });\n\n it(\"does not collapse tool calls when setting is disabled\", async () => {\n const host = createHost({ collapseToolCalls: false });\n\n await handleAgentEvent(host, {\n type: \"message_start\",\n message: assistantMessage(),\n });\n\n const tool = addPendingTool(host, \"tool-1\", 250);\n await handleAgentEvent(host, toolEndEvent(\"tool-1\", \"read\"));\n\n assert.equal(tool.hidden, false);\n assert.equal(summaryLines(host).length, 0);\n });\n});\n"]}
|
package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat-controller.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/controllers/chat-controller.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,oBAAoB,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"chat-controller.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/controllers/chat-controller.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,oBAAoB,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AAiBnG,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,wBAAwB,GAAG;IACpE,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,4BAA4B,EAAE,MAAM,GAAG,CAAC;IACxC,gBAAgB,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,GAAG,KAAK,IAAI,CAAC;IACxD,qBAAqB,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,MAAM,CAAC;IACpD,2BAA2B,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,GAAG,CAAC;IACvD,sBAAsB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C,uBAAuB,EAAE,MAAM,IAAI,CAAC;IACpC,oBAAoB,EAAE,CAAC,OAAO,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3E,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,SAAS,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,4BAA4B,EAAE,MAAM,IAAI,CAAC;IACzC,mBAAmB,EAAE,MAAM,IAAI,CAAC;IAChC,uBAAuB,EAAE,MAAM,IAAI,CAAC;IACpC,sBAAsB,EAAE,MAAM,IAAI,CAAC;IACnC,oBAAoB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,GAAG,CAAC;IACjD,uBAAuB,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,KAAK,GAAG,CAAC;IACtE,uBAAuB,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,OAAO,CAAC;QAAC,SAAS,CAAC,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACvK,uBAAuB,EAAE,MAAM,IAAI,CAAC;IACpC,wBAAwB,EAAE;QAAE,KAAK,EAAE,MAAM,IAAI,CAAA;KAAE,CAAC;IAChD,gBAAgB,EAAE,MAAM,IAAI,CAAC;IAC7B,eAAe,EAAE,MAAM,IAAI,CAAC;CAC/B,EAAE,KAAK,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAmgB7C"}
|
|
@@ -6,6 +6,13 @@ import { ToolExecutionComponent } from "../components/tool-execution.js";
|
|
|
6
6
|
import { ToolSummaryLine } from "../components/tool-summary-line.js";
|
|
7
7
|
import { shouldCollapse } from "../../../core/tool-priority.js";
|
|
8
8
|
import { appKey } from "../components/keybinding-hints.js";
|
|
9
|
+
const GROUPABLE_COLLAPSED_TOOLS = new Set([
|
|
10
|
+
"read",
|
|
11
|
+
"find",
|
|
12
|
+
"ls",
|
|
13
|
+
"grep",
|
|
14
|
+
"lsp",
|
|
15
|
+
]);
|
|
9
16
|
export async function handleAgentEvent(host, event) {
|
|
10
17
|
if (!host.isInitialized) {
|
|
11
18
|
await host.init();
|
|
@@ -14,6 +21,22 @@ export async function handleAgentEvent(host, event) {
|
|
|
14
21
|
const resetCollapsedToolSummary = () => {
|
|
15
22
|
host.collapsedToolSummaryLine = undefined;
|
|
16
23
|
};
|
|
24
|
+
// Tools that always render as their own visible row, never folded into a summary line
|
|
25
|
+
const ALWAYS_DIRECT_TOOLS = new Set([
|
|
26
|
+
"bash", "bg_shell",
|
|
27
|
+
"web_search", "search-the-web", "google_search", "search_and_read",
|
|
28
|
+
"fetch_page", "resolve_library", "get_library_docs",
|
|
29
|
+
]);
|
|
30
|
+
const shouldStartToolHidden = (toolName) => {
|
|
31
|
+
const collapseToolCalls = host.settingsManager.getCollapseToolCalls?.() ?? false;
|
|
32
|
+
if (!collapseToolCalls || host.collapsedToolCallsExpanded) {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
if (ALWAYS_DIRECT_TOOLS.has(toolName)) {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
return shouldCollapse(toolName, false);
|
|
39
|
+
};
|
|
17
40
|
const hasVisibleRender = (child) => {
|
|
18
41
|
if (!child?.render)
|
|
19
42
|
return true;
|
|
@@ -24,12 +47,16 @@ export async function handleAgentEvent(host, event) {
|
|
|
24
47
|
return true;
|
|
25
48
|
}
|
|
26
49
|
};
|
|
27
|
-
const
|
|
50
|
+
const canGroupCollapsedTool = (toolName) => GROUPABLE_COLLAPSED_TOOLS.has(toolName);
|
|
51
|
+
const findAdjacentCollapsedToolSummary = (toolName, anchor) => {
|
|
52
|
+
if (!canGroupCollapsedTool(toolName)) {
|
|
53
|
+
return undefined;
|
|
54
|
+
}
|
|
28
55
|
const anchorIndex = anchor ? host.chatContainer.children.indexOf(anchor) : host.chatContainer.children.length;
|
|
29
56
|
for (let i = anchorIndex - 1; i >= 0; i--) {
|
|
30
57
|
const child = host.chatContainer.children[i];
|
|
31
58
|
if (child instanceof ToolSummaryLine) {
|
|
32
|
-
return child;
|
|
59
|
+
return child.canGroupWith(toolName) ? child : undefined;
|
|
33
60
|
}
|
|
34
61
|
if (child instanceof ToolExecutionComponent && child.isHidden()) {
|
|
35
62
|
continue;
|
|
@@ -42,16 +69,10 @@ export async function handleAgentEvent(host, event) {
|
|
|
42
69
|
return undefined;
|
|
43
70
|
};
|
|
44
71
|
const appendCollapsedToolSummary = (toolName, elapsed, anchor) => {
|
|
45
|
-
let summary =
|
|
46
|
-
if (
|
|
47
|
-
summary = findAdjacentCollapsedToolSummary(anchor);
|
|
48
|
-
if (summary) {
|
|
49
|
-
host.collapsedToolSummaryLine = summary;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
if (!summary || !host.chatContainer.children.includes(summary)) {
|
|
72
|
+
let summary = findAdjacentCollapsedToolSummary(toolName, anchor);
|
|
73
|
+
if (!summary) {
|
|
53
74
|
summary = new ToolSummaryLine();
|
|
54
|
-
summary.setHidden(host.
|
|
75
|
+
summary.setHidden(host.collapsedToolCallsExpanded);
|
|
55
76
|
if (anchor) {
|
|
56
77
|
const anchorIndex = host.chatContainer.children.indexOf(anchor);
|
|
57
78
|
if (anchorIndex >= 0) {
|
|
@@ -64,9 +85,10 @@ export async function handleAgentEvent(host, event) {
|
|
|
64
85
|
else {
|
|
65
86
|
host.chatContainer.addChild(summary);
|
|
66
87
|
}
|
|
67
|
-
host.collapsedToolSummaryLine = summary;
|
|
68
88
|
}
|
|
89
|
+
host.collapsedToolSummaryLine = summary;
|
|
69
90
|
summary.addTool(toolName, elapsed);
|
|
91
|
+
return summary;
|
|
70
92
|
};
|
|
71
93
|
switch (event.type) {
|
|
72
94
|
case "session_state_changed":
|
|
@@ -175,6 +197,7 @@ export async function handleAgentEvent(host, event) {
|
|
|
175
197
|
editorScheme: host.settingsManager.getEditorScheme(),
|
|
176
198
|
}, host.getRegisteredToolDefinition(content.name), host.ui);
|
|
177
199
|
component.setExpanded(host.toolOutputExpanded);
|
|
200
|
+
component.setHidden(shouldStartToolHidden(content.name));
|
|
178
201
|
host.chatContainer.addChild(component);
|
|
179
202
|
host.pendingTools.set(content.id, component);
|
|
180
203
|
}
|
|
@@ -190,6 +213,7 @@ export async function handleAgentEvent(host, event) {
|
|
|
190
213
|
editorScheme: host.settingsManager.getEditorScheme(),
|
|
191
214
|
}, undefined, host.ui);
|
|
192
215
|
component.setExpanded(host.toolOutputExpanded);
|
|
216
|
+
component.setHidden(shouldStartToolHidden(content.name));
|
|
193
217
|
host.chatContainer.addChild(component);
|
|
194
218
|
host.pendingTools.set(content.id, component);
|
|
195
219
|
}
|
|
@@ -268,6 +292,7 @@ export async function handleAgentEvent(host, event) {
|
|
|
268
292
|
editorScheme: host.settingsManager.getEditorScheme(),
|
|
269
293
|
}, host.getRegisteredToolDefinition(event.toolName), host.ui);
|
|
270
294
|
component.setExpanded(host.toolOutputExpanded);
|
|
295
|
+
component.setHidden(shouldStartToolHidden(event.toolName));
|
|
271
296
|
host.chatContainer.addChild(component);
|
|
272
297
|
host.pendingTools.set(event.toolCallId, component);
|
|
273
298
|
host.ui.requestRender();
|
|
@@ -315,9 +340,10 @@ export async function handleAgentEvent(host, event) {
|
|
|
315
340
|
const component = host.pendingTools.get(event.toolCallId);
|
|
316
341
|
if (component) {
|
|
317
342
|
component.updateResult({ ...event.result, isError: event.isError });
|
|
318
|
-
|
|
343
|
+
const collapseToolCalls = host.settingsManager.getCollapseToolCalls?.() ?? false;
|
|
344
|
+
if (collapseToolCalls && shouldCollapse(event.toolName, event.isError) && !ALWAYS_DIRECT_TOOLS.has(event.toolName)) {
|
|
319
345
|
appendCollapsedToolSummary(event.toolName, component.getElapsed(), component);
|
|
320
|
-
component.setHidden(
|
|
346
|
+
component.setHidden(!host.collapsedToolCallsExpanded);
|
|
321
347
|
}
|
|
322
348
|
else {
|
|
323
349
|
component.setHidden(false);
|