inferoa 0.1.0

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.
Files changed (200) hide show
  1. package/LICENSE +176 -0
  2. package/README.md +154 -0
  3. package/dist/src/app.d.ts +16 -0
  4. package/dist/src/app.js +17 -0
  5. package/dist/src/app.js.map +1 -0
  6. package/dist/src/autoresearch/state.d.ts +106 -0
  7. package/dist/src/autoresearch/state.js +469 -0
  8. package/dist/src/autoresearch/state.js.map +1 -0
  9. package/dist/src/cli.d.ts +2 -0
  10. package/dist/src/cli.js +415 -0
  11. package/dist/src/cli.js.map +1 -0
  12. package/dist/src/code-intelligence/codegraph-engine.d.ts +55 -0
  13. package/dist/src/code-intelligence/codegraph-engine.js +593 -0
  14. package/dist/src/code-intelligence/codegraph-engine.js.map +1 -0
  15. package/dist/src/code-intelligence/hub.d.ts +37 -0
  16. package/dist/src/code-intelligence/hub.js +65 -0
  17. package/dist/src/code-intelligence/hub.js.map +1 -0
  18. package/dist/src/config/config.d.ts +12 -0
  19. package/dist/src/config/config.js +229 -0
  20. package/dist/src/config/config.js.map +1 -0
  21. package/dist/src/config/defaults.d.ts +2 -0
  22. package/dist/src/config/defaults.js +44 -0
  23. package/dist/src/config/defaults.js.map +1 -0
  24. package/dist/src/config/secret-vault.d.ts +3 -0
  25. package/dist/src/config/secret-vault.js +106 -0
  26. package/dist/src/config/secret-vault.js.map +1 -0
  27. package/dist/src/context/compressor.d.ts +33 -0
  28. package/dist/src/context/compressor.js +501 -0
  29. package/dist/src/context/compressor.js.map +1 -0
  30. package/dist/src/context/prompt.d.ts +26 -0
  31. package/dist/src/context/prompt.js +572 -0
  32. package/dist/src/context/prompt.js.map +1 -0
  33. package/dist/src/daemon/serve.d.ts +2 -0
  34. package/dist/src/daemon/serve.js +11 -0
  35. package/dist/src/daemon/serve.js.map +1 -0
  36. package/dist/src/daemon/supervisor.d.ts +33 -0
  37. package/dist/src/daemon/supervisor.js +252 -0
  38. package/dist/src/daemon/supervisor.js.map +1 -0
  39. package/dist/src/goals/state.d.ts +105 -0
  40. package/dist/src/goals/state.js +736 -0
  41. package/dist/src/goals/state.js.map +1 -0
  42. package/dist/src/model/endpoint-signals.d.ts +15 -0
  43. package/dist/src/model/endpoint-signals.js +186 -0
  44. package/dist/src/model/endpoint-signals.js.map +1 -0
  45. package/dist/src/model/gateway.d.ts +11 -0
  46. package/dist/src/model/gateway.js +455 -0
  47. package/dist/src/model/gateway.js.map +1 -0
  48. package/dist/src/plans/state.d.ts +28 -0
  49. package/dist/src/plans/state.js +123 -0
  50. package/dist/src/plans/state.js.map +1 -0
  51. package/dist/src/runtime.d.ts +92 -0
  52. package/dist/src/runtime.js +757 -0
  53. package/dist/src/runtime.js.map +1 -0
  54. package/dist/src/session/store.d.ts +84 -0
  55. package/dist/src/session/store.js +593 -0
  56. package/dist/src/session/store.js.map +1 -0
  57. package/dist/src/session/workspace.d.ts +2 -0
  58. package/dist/src/session/workspace.js +14 -0
  59. package/dist/src/session/workspace.js.map +1 -0
  60. package/dist/src/skills/registry.d.ts +24 -0
  61. package/dist/src/skills/registry.js +203 -0
  62. package/dist/src/skills/registry.js.map +1 -0
  63. package/dist/src/tools/autoresearch-tools.d.ts +6 -0
  64. package/dist/src/tools/autoresearch-tools.js +412 -0
  65. package/dist/src/tools/autoresearch-tools.js.map +1 -0
  66. package/dist/src/tools/clarify-tool.d.ts +3 -0
  67. package/dist/src/tools/clarify-tool.js +107 -0
  68. package/dist/src/tools/clarify-tool.js.map +1 -0
  69. package/dist/src/tools/code-intelligence.d.ts +15 -0
  70. package/dist/src/tools/code-intelligence.js +391 -0
  71. package/dist/src/tools/code-intelligence.js.map +1 -0
  72. package/dist/src/tools/context.d.ts +11 -0
  73. package/dist/src/tools/context.js +2 -0
  74. package/dist/src/tools/context.js.map +1 -0
  75. package/dist/src/tools/goal-tools.d.ts +3 -0
  76. package/dist/src/tools/goal-tools.js +279 -0
  77. package/dist/src/tools/goal-tools.js.map +1 -0
  78. package/dist/src/tools/omni-tools.d.ts +8 -0
  79. package/dist/src/tools/omni-tools.js +349 -0
  80. package/dist/src/tools/omni-tools.js.map +1 -0
  81. package/dist/src/tools/permissions.d.ts +11 -0
  82. package/dist/src/tools/permissions.js +74 -0
  83. package/dist/src/tools/permissions.js.map +1 -0
  84. package/dist/src/tools/plan-tools.d.ts +3 -0
  85. package/dist/src/tools/plan-tools.js +314 -0
  86. package/dist/src/tools/plan-tools.js.map +1 -0
  87. package/dist/src/tools/process-tools.d.ts +6 -0
  88. package/dist/src/tools/process-tools.js +199 -0
  89. package/dist/src/tools/process-tools.js.map +1 -0
  90. package/dist/src/tools/registry.d.ts +20 -0
  91. package/dist/src/tools/registry.js +187 -0
  92. package/dist/src/tools/registry.js.map +1 -0
  93. package/dist/src/tools/schemas.d.ts +3 -0
  94. package/dist/src/tools/schemas.js +500 -0
  95. package/dist/src/tools/schemas.js.map +1 -0
  96. package/dist/src/tools/skill-tools.d.ts +6 -0
  97. package/dist/src/tools/skill-tools.js +124 -0
  98. package/dist/src/tools/skill-tools.js.map +1 -0
  99. package/dist/src/tools/text-args.d.ts +5 -0
  100. package/dist/src/tools/text-args.js +22 -0
  101. package/dist/src/tools/text-args.js.map +1 -0
  102. package/dist/src/tools/web-search.d.ts +5 -0
  103. package/dist/src/tools/web-search.js +602 -0
  104. package/dist/src/tools/web-search.js.map +1 -0
  105. package/dist/src/tools/workspace-tools.d.ts +17 -0
  106. package/dist/src/tools/workspace-tools.js +561 -0
  107. package/dist/src/tools/workspace-tools.js.map +1 -0
  108. package/dist/src/tui/activity.d.ts +11 -0
  109. package/dist/src/tui/activity.js +75 -0
  110. package/dist/src/tui/activity.js.map +1 -0
  111. package/dist/src/tui/ansi.d.ts +24 -0
  112. package/dist/src/tui/ansi.js +131 -0
  113. package/dist/src/tui/ansi.js.map +1 -0
  114. package/dist/src/tui/app.d.ts +163 -0
  115. package/dist/src/tui/app.js +4204 -0
  116. package/dist/src/tui/app.js.map +1 -0
  117. package/dist/src/tui/cache-footer.d.ts +21 -0
  118. package/dist/src/tui/cache-footer.js +75 -0
  119. package/dist/src/tui/cache-footer.js.map +1 -0
  120. package/dist/src/tui/clarify.d.ts +14 -0
  121. package/dist/src/tui/clarify.js +187 -0
  122. package/dist/src/tui/clarify.js.map +1 -0
  123. package/dist/src/tui/composer.d.ts +79 -0
  124. package/dist/src/tui/composer.js +592 -0
  125. package/dist/src/tui/composer.js.map +1 -0
  126. package/dist/src/tui/event-view.d.ts +5 -0
  127. package/dist/src/tui/event-view.js +392 -0
  128. package/dist/src/tui/event-view.js.map +1 -0
  129. package/dist/src/tui/home.d.ts +7 -0
  130. package/dist/src/tui/home.js +92 -0
  131. package/dist/src/tui/home.js.map +1 -0
  132. package/dist/src/tui/markdown.d.ts +18 -0
  133. package/dist/src/tui/markdown.js +271 -0
  134. package/dist/src/tui/markdown.js.map +1 -0
  135. package/dist/src/tui/mode-footer.d.ts +9 -0
  136. package/dist/src/tui/mode-footer.js +62 -0
  137. package/dist/src/tui/mode-footer.js.map +1 -0
  138. package/dist/src/tui/plan-view.d.ts +8 -0
  139. package/dist/src/tui/plan-view.js +45 -0
  140. package/dist/src/tui/plan-view.js.map +1 -0
  141. package/dist/src/tui/prompt-queue.d.ts +18 -0
  142. package/dist/src/tui/prompt-queue.js +27 -0
  143. package/dist/src/tui/prompt-queue.js.map +1 -0
  144. package/dist/src/tui/resize.d.ts +7 -0
  145. package/dist/src/tui/resize.js +15 -0
  146. package/dist/src/tui/resize.js.map +1 -0
  147. package/dist/src/tui/session-picker.d.ts +10 -0
  148. package/dist/src/tui/session-picker.js +17 -0
  149. package/dist/src/tui/session-picker.js.map +1 -0
  150. package/dist/src/tui/session-transcript.d.ts +2 -0
  151. package/dist/src/tui/session-transcript.js +44 -0
  152. package/dist/src/tui/session-transcript.js.map +1 -0
  153. package/dist/src/tui/slash-notice.d.ts +2 -0
  154. package/dist/src/tui/slash-notice.js +9 -0
  155. package/dist/src/tui/slash-notice.js.map +1 -0
  156. package/dist/src/tui/slash.d.ts +21 -0
  157. package/dist/src/tui/slash.js +103 -0
  158. package/dist/src/tui/slash.js.map +1 -0
  159. package/dist/src/tui/splash.d.ts +4 -0
  160. package/dist/src/tui/splash.js +64 -0
  161. package/dist/src/tui/splash.js.map +1 -0
  162. package/dist/src/tui/tool-renderer.d.ts +6 -0
  163. package/dist/src/tui/tool-renderer.js +1024 -0
  164. package/dist/src/tui/tool-renderer.js.map +1 -0
  165. package/dist/src/tui/transcript-spacing.d.ts +1 -0
  166. package/dist/src/tui/transcript-spacing.js +4 -0
  167. package/dist/src/tui/transcript-spacing.js.map +1 -0
  168. package/dist/src/types.d.ts +220 -0
  169. package/dist/src/types.js +2 -0
  170. package/dist/src/types.js.map +1 -0
  171. package/dist/src/util/abort.d.ts +3 -0
  172. package/dist/src/util/abort.js +19 -0
  173. package/dist/src/util/abort.js.map +1 -0
  174. package/dist/src/util/clock.d.ts +2 -0
  175. package/dist/src/util/clock.js +7 -0
  176. package/dist/src/util/clock.js.map +1 -0
  177. package/dist/src/util/fs.d.ts +13 -0
  178. package/dist/src/util/fs.js +75 -0
  179. package/dist/src/util/fs.js.map +1 -0
  180. package/dist/src/util/hash.d.ts +6 -0
  181. package/dist/src/util/hash.js +50 -0
  182. package/dist/src/util/hash.js.map +1 -0
  183. package/dist/src/util/limit.d.ts +11 -0
  184. package/dist/src/util/limit.js +29 -0
  185. package/dist/src/util/limit.js.map +1 -0
  186. package/dist/src/util/types.d.ts +22 -0
  187. package/dist/src/util/types.js +33 -0
  188. package/dist/src/util/types.js.map +1 -0
  189. package/dist/src/validation/acceptance.d.ts +12 -0
  190. package/dist/src/validation/acceptance.js +251 -0
  191. package/dist/src/validation/acceptance.js.map +1 -0
  192. package/dist/src/validation/milestone.d.ts +2 -0
  193. package/dist/src/validation/milestone.js +141 -0
  194. package/dist/src/validation/milestone.js.map +1 -0
  195. package/docs/final-acceptance-task.md +193 -0
  196. package/docs/public-source-hygiene.md +21 -0
  197. package/docs/roadmap.md +265 -0
  198. package/docs/tui-product-design.md +270 -0
  199. package/package.json +67 -0
  200. package/skills/coding-workflow/SKILL.md +16 -0
@@ -0,0 +1,1024 @@
1
+ import { ansi, fg256, padRight, terminalWidth, truncateToWidth, visibleWidth } from "./ansi.js";
2
+ import { renderPlanDocumentSurface } from "./plan-view.js";
3
+ const COMPACT_TOOL_FOLD_THRESHOLD = 5;
4
+ const COMPACT_SUCCESS_TOOLS = new Set([
5
+ "list_dir",
6
+ "glob",
7
+ "file_search",
8
+ "read_file",
9
+ "read_resource",
10
+ "web_fetch",
11
+ "web_open",
12
+ "web_search",
13
+ "lsp",
14
+ "codegraph_search",
15
+ "codegraph_status",
16
+ "codegraph_files",
17
+ "skill_list",
18
+ "skill_read",
19
+ ]);
20
+ export function renderToolCards(events, store, options = {}) {
21
+ const groups = groupToolEvents(events);
22
+ const rendered = groups.map((group) => {
23
+ const lines = renderToolGroup(group, store);
24
+ return { group, lines, compact: isCompactToolGroup(group, lines) };
25
+ });
26
+ if (options.collapseCompact === false) {
27
+ return rendered.flatMap((item) => item.lines);
28
+ }
29
+ return collapseCompactToolRows(rendered);
30
+ }
31
+ function groupToolEvents(events) {
32
+ const groups = new Map();
33
+ for (const event of events) {
34
+ const id = stringField(event.data.tool_call_id) ?? `${event.type}:${groups.size}`;
35
+ const name = stringField(event.data.tool_name) ?? stringField(event.data.name) ?? "tool";
36
+ const current = groups.get(id) ?? { id, name, args: {} };
37
+ if (event.type === "tool.call") {
38
+ current.args = objectField(event.data.arguments);
39
+ current.name = name;
40
+ }
41
+ if (event.type === "tool.result") {
42
+ current.result = objectField(event.data.result);
43
+ current.name = name;
44
+ }
45
+ groups.set(id, current);
46
+ }
47
+ return [...groups.values()];
48
+ }
49
+ function renderToolGroup(group, store) {
50
+ const result = group.result;
51
+ const marker = result?.ok === false ? fg256(203, "×") : result?.ok === true ? fg256(48, "•") : fg256(220, "◦");
52
+ const summary = result?.summary ?? "running";
53
+ const width = terminalWidth();
54
+ const action = toolGroupAction(group);
55
+ const detail = toolGroupDetail(group, summary);
56
+ const separator = detail ? (group.name === "run_command" ? " " : ` ${fg256(244, "·")} `) : "";
57
+ const title = ` ${marker} ${fg256(result?.ok === false ? 203 : 255, ansi.bold + action + ansi.reset)}${separator}${fg256(result?.ok === false ? 203 : 250, truncateToWidth(detail, Math.max(20, width - visibleWidth(action) - 12)))}`;
58
+ const body = renderToolBody(group, store);
59
+ if (!shouldExpandToolGroup(group, body)) {
60
+ return [title];
61
+ }
62
+ let firstBodyLine = true;
63
+ return [
64
+ title,
65
+ ...body.map((line) => {
66
+ if (!line) {
67
+ return "";
68
+ }
69
+ if (isFullWidthSurfaceLine(line)) {
70
+ firstBodyLine = false;
71
+ return line;
72
+ }
73
+ const prefix = firstBodyLine ? fg256(238, " ⎿ ") : fg256(238, " ");
74
+ firstBodyLine = false;
75
+ return `${prefix}${line}`;
76
+ }),
77
+ ];
78
+ }
79
+ function renderToolBody(group, store) {
80
+ const result = group.result;
81
+ const data = objectField(result?.data);
82
+ const lines = [];
83
+ switch (group.name) {
84
+ case "list_dir":
85
+ lines.push(...renderDirectoryEntries(data));
86
+ break;
87
+ case "run_command":
88
+ lines.push(...renderCommand(data));
89
+ break;
90
+ case "read_process":
91
+ case "write_process":
92
+ case "stop_process":
93
+ lines.push(...renderProcess(data));
94
+ break;
95
+ case "git_diff":
96
+ case "git_show":
97
+ lines.push(...renderDiff(stringField(data.output) ?? resourceText(result?.resource_uri, store)));
98
+ break;
99
+ case "apply_patch":
100
+ lines.push(...renderDiff(stringField(data.diff) ?? stringField(group.args.patch)));
101
+ break;
102
+ case "edit_file":
103
+ case "ast_edit":
104
+ lines.push(...renderEdit(group.args, data));
105
+ break;
106
+ case "write_file":
107
+ lines.push(`${fg256(39, "path")} ${stringField(data.path) ?? stringField(group.args.path) ?? "unknown"}`);
108
+ if (numberField(data.bytes) !== undefined) {
109
+ lines.push(`${fg256(39, "bytes")} ${numberField(data.bytes)}`);
110
+ }
111
+ if (stringField(data.diff)) {
112
+ lines.push(...renderDiff(stringField(data.diff)));
113
+ }
114
+ break;
115
+ case "read_file":
116
+ case "read_resource":
117
+ lines.push(...renderTextPreview(stringField(data.content) ?? ""));
118
+ break;
119
+ case "codegraph_explore":
120
+ case "codegraph_search":
121
+ case "codegraph_callers":
122
+ case "codegraph_callees":
123
+ case "codegraph_impact":
124
+ case "codegraph_node":
125
+ case "codegraph_status":
126
+ case "codegraph_files":
127
+ lines.push(...renderTextPreview(stringField(data.content) ?? ""));
128
+ break;
129
+ case "file_search":
130
+ case "glob":
131
+ lines.push(...renderMatches(data));
132
+ break;
133
+ case "web_fetch":
134
+ lines.push(...renderWebFetch(data));
135
+ break;
136
+ case "web_open":
137
+ lines.push(...renderWebFetch(data));
138
+ if (stringField(data.note)) {
139
+ lines.push(`${fg256(39, "note")} ${stringField(data.note)}`);
140
+ }
141
+ break;
142
+ case "web_search":
143
+ lines.push(...renderWebSearch(data));
144
+ break;
145
+ case "git_status":
146
+ lines.push(...renderTextPreview(stringField(data.output) ?? resourceText(result?.resource_uri, store) ?? ""));
147
+ break;
148
+ case "todo_write":
149
+ lines.push(...renderTodos(data));
150
+ break;
151
+ case "clarify":
152
+ lines.push(...renderClarifyTool(data));
153
+ break;
154
+ case "goal":
155
+ lines.push(...renderGoalTool(data));
156
+ break;
157
+ case "plan":
158
+ lines.push(...renderPlanTool(data));
159
+ break;
160
+ case "init_experiment":
161
+ case "run_experiment":
162
+ case "log_experiment":
163
+ case "update_notes":
164
+ lines.push(...renderAutoresearchTool(group.name, data));
165
+ break;
166
+ case "complete_step":
167
+ lines.push(`${fg256(39, "step")} ${stringField(data.step_id) ?? stringField(group.args.step_id) ?? "unknown"}`);
168
+ lines.push(...renderEvidenceObject(objectField(data.evidence)));
169
+ break;
170
+ default:
171
+ lines.push(...renderGeneric(data, result?.resource_uri));
172
+ }
173
+ if (result?.resource_uri) {
174
+ lines.push(`${fg256(39, "resource")} ${result.resource_uri}`);
175
+ }
176
+ if (result?.error) {
177
+ lines.push(fg256(203, `${result.error.code}: ${result.error.message}`));
178
+ }
179
+ return lines.length ? lines : [fg256(243, "No display data.")];
180
+ }
181
+ function isCompactToolGroup(group, lines) {
182
+ return group.result?.ok === true && lines.length === 1 && COMPACT_SUCCESS_TOOLS.has(group.name);
183
+ }
184
+ function shouldExpandToolGroup(group, body) {
185
+ if (group.result?.ok === false || group.result?.error) {
186
+ return true;
187
+ }
188
+ if (!group.result) {
189
+ return false;
190
+ }
191
+ if (body.length === 0) {
192
+ return false;
193
+ }
194
+ if ([
195
+ "apply_patch",
196
+ "edit_file",
197
+ "ast_edit",
198
+ "write_file",
199
+ "git_diff",
200
+ "git_show",
201
+ "git_status",
202
+ "run_command",
203
+ "todo_write",
204
+ "clarify",
205
+ "goal",
206
+ "plan",
207
+ "web_search",
208
+ "init_experiment",
209
+ "run_experiment",
210
+ "log_experiment",
211
+ "update_notes",
212
+ "complete_step",
213
+ "codegraph_explore",
214
+ "codegraph_callers",
215
+ "codegraph_callees",
216
+ "codegraph_impact",
217
+ "codegraph_node",
218
+ ].includes(group.name)) {
219
+ return true;
220
+ }
221
+ return false;
222
+ }
223
+ function collapseCompactToolRows(rendered) {
224
+ const output = [];
225
+ let compactRun = [];
226
+ const flushCompactRun = () => {
227
+ if (!compactRun.length) {
228
+ return;
229
+ }
230
+ if (compactRun.length <= COMPACT_TOOL_FOLD_THRESHOLD) {
231
+ output.push(...compactRun.flatMap((item) => item.lines));
232
+ compactRun = [];
233
+ return;
234
+ }
235
+ output.push(...renderToolBatchLines(compactRun));
236
+ compactRun = [];
237
+ };
238
+ for (const item of rendered) {
239
+ if (item.compact) {
240
+ compactRun.push(item);
241
+ continue;
242
+ }
243
+ flushCompactRun();
244
+ output.push(...item.lines);
245
+ }
246
+ flushCompactRun();
247
+ return output;
248
+ }
249
+ function renderToolBatchLines(items) {
250
+ const width = terminalWidth();
251
+ const summary = compactToolRunSummary(items);
252
+ const first = compactToolBrief(items[0]);
253
+ const last = compactToolBrief(items.at(-1));
254
+ const detail = [`${items.length} calls`, summary, "Ctrl+T expand"].filter(Boolean).join(" · ");
255
+ const lines = [` ${fg256(48, "•")} ${fg256(75, "Tool batch")} ${fg256(244, "·")} ${fg256(250, truncateToWidth(detail, Math.max(20, width - 18)))}`];
256
+ if (first) {
257
+ lines.push(` ${fg256(238, "├")} ${fg256(244, truncateToWidth(first, Math.max(20, width - 8)))}`);
258
+ }
259
+ if (last && last !== first) {
260
+ lines.push(` ${fg256(238, "╰")} ${fg256(244, truncateToWidth(last, Math.max(20, width - 8)))}`);
261
+ }
262
+ return lines;
263
+ }
264
+ function compactToolBrief(item) {
265
+ const summary = item?.group.result?.summary;
266
+ if (!summary) {
267
+ return undefined;
268
+ }
269
+ return truncateToWidth(summary, 24);
270
+ }
271
+ function compactToolRunSummary(items) {
272
+ const counts = new Map();
273
+ for (const item of items) {
274
+ counts.set(item.group.name, (counts.get(item.group.name) ?? 0) + 1);
275
+ }
276
+ return [...counts.entries()]
277
+ .sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0]))
278
+ .slice(0, 3)
279
+ .map(([name, count]) => `${count} ${compactToolName(name)}`)
280
+ .join(", ");
281
+ }
282
+ function compactToolName(name) {
283
+ switch (name) {
284
+ case "list_dir":
285
+ return "list";
286
+ case "glob":
287
+ return "scan";
288
+ case "read_file":
289
+ return "read";
290
+ case "file_search":
291
+ return "search";
292
+ case "web_fetch":
293
+ return "fetch";
294
+ case "web_search":
295
+ return "web";
296
+ case "codegraph_explore":
297
+ return "context";
298
+ case "codegraph_search":
299
+ return "semantic";
300
+ case "codegraph_node":
301
+ return "symbol";
302
+ case "codegraph_callers":
303
+ case "codegraph_callees":
304
+ case "codegraph_impact":
305
+ return "trace";
306
+ case "codegraph_files":
307
+ return "files";
308
+ case "codegraph_status":
309
+ return "context-status";
310
+ default:
311
+ return name.replace(/_/g, "-");
312
+ }
313
+ }
314
+ function renderCommand(data) {
315
+ const lines = [
316
+ `${fg256(39, "cmd")} ${stringField(data.command) ?? "unknown"}`,
317
+ `${fg256(39, "cwd")} ${stringField(data.cwd) ?? "."}`,
318
+ `${fg256(39, "exit")} ${numberField(data.code) ?? "running"}${data.timed_out ? " timeout" : ""}`,
319
+ ];
320
+ const output = stringField(data.output);
321
+ if (output) {
322
+ lines.push(...renderIndentedPreview(output, 10, "out"));
323
+ }
324
+ return lines;
325
+ }
326
+ function renderDirectoryEntries(data) {
327
+ const entries = Array.isArray(data.entries) ? data.entries : [];
328
+ if (!entries.length) {
329
+ return [fg256(243, "No entries.")];
330
+ }
331
+ return entries.slice(0, 12).map((item) => {
332
+ const entry = objectField(item);
333
+ const type = stringField(entry.type) ?? "item";
334
+ const icon = type === "directory" ? fg256(75, "dir ") : type === "file" ? fg256(250, "file") : fg256(244, type.padEnd(4).slice(0, 4));
335
+ return `${icon} ${stringField(entry.path) ?? stringField(entry.name) ?? compactObject(entry)}`;
336
+ });
337
+ }
338
+ function renderProcess(data) {
339
+ const lines = [
340
+ `${fg256(39, "process")} ${stringField(data.process_id) ?? "unknown"}`,
341
+ `${fg256(39, "live")} ${data.live === true ? "yes" : data.live === false ? "no" : "unknown"}`,
342
+ ];
343
+ const output = stringField(data.output);
344
+ if (output) {
345
+ lines.push(...renderIndentedPreview(output, 10, "out"));
346
+ }
347
+ return lines;
348
+ }
349
+ function renderEdit(args, data) {
350
+ const path = stringField(data.path) ?? stringField(args.path) ?? "unknown";
351
+ const diff = stringField(data.diff);
352
+ const oldText = stringField(args.old_text);
353
+ const newText = stringField(args.new_text) ?? stringField(args.content);
354
+ const lines = [`${fg256(39, "path")} ${path}`];
355
+ if (diff) {
356
+ lines.push(...renderDiff(diff));
357
+ }
358
+ else if (oldText || newText) {
359
+ lines.push(...renderDiff(simplePatch(path, oldText ?? "", newText ?? "")));
360
+ }
361
+ return lines;
362
+ }
363
+ function renderMatches(data) {
364
+ const matches = Array.isArray(data.matches) ? data.matches : [];
365
+ if (!matches.length) {
366
+ return [fg256(243, "No matches.")];
367
+ }
368
+ return matches.slice(0, 12).map((item) => {
369
+ if (typeof item === "string") {
370
+ return `${fg256(39, "path")} ${item}`;
371
+ }
372
+ const match = objectField(item);
373
+ const location = `${stringField(match.path) ?? "unknown"}:${numberField(match.line) ?? "?"}`;
374
+ return `${fg256(39, location)} ${stringField(match.snippet) ?? ""}`;
375
+ });
376
+ }
377
+ function renderWebSearch(data) {
378
+ const lines = [];
379
+ const provider = stringField(data.provider);
380
+ const query = stringField(data.query);
381
+ if (provider) {
382
+ lines.push(`${fg256(39, "provider")} ${provider}${data.fallback === true ? fg256(244, " · fallback") : ""}`);
383
+ }
384
+ if (query) {
385
+ lines.push(`${fg256(39, "query")} ${query}`);
386
+ }
387
+ const results = Array.isArray(data.results) ? data.results.map(objectField) : [];
388
+ if (results.length) {
389
+ lines.push(`${fg256(39, "results")} ${results.length}`);
390
+ for (const [index, result] of results.slice(0, 5).entries()) {
391
+ const title = stringField(result.title) ?? stringField(result.name) ?? stringField(result.url) ?? "Untitled";
392
+ const url = stringField(result.url) ?? stringField(result.link) ?? stringField(result.href);
393
+ const snippet = stringField(result.snippet) ?? stringField(result.description) ?? stringField(result.content);
394
+ lines.push(`${fg256(244, String(index + 1).padStart(2, "0"))} ${truncateToWidth(title, Math.max(24, terminalWidth() - 16))}`);
395
+ if (url) {
396
+ lines.push(` ${fg256(39, truncateToWidth(url, Math.max(24, terminalWidth() - 12)))}`);
397
+ }
398
+ if (snippet) {
399
+ lines.push(` ${fg256(244, truncateToWidth(snippet.replace(/\s+/g, " "), Math.max(24, terminalWidth() - 12)))}`);
400
+ }
401
+ }
402
+ return lines;
403
+ }
404
+ const text = stringField(data.results_text);
405
+ if (text) {
406
+ lines.push(...renderIndentedPreview(text, 8, "results"));
407
+ return lines;
408
+ }
409
+ return lines.length ? lines : [fg256(243, "No search results.")];
410
+ }
411
+ function renderWebFetch(data) {
412
+ const lines = [
413
+ `${fg256(39, "url")} ${stringField(data.final_url) ?? stringField(data.url) ?? "unknown"}`,
414
+ `${fg256(39, "status")} ${numberField(data.status) ?? "unknown"} · ${stringField(data.content_type) ?? "unknown"}`,
415
+ ];
416
+ const title = stringField(data.title);
417
+ if (title) {
418
+ lines.push(`${fg256(39, "title")} ${title}`);
419
+ }
420
+ const text = stringField(data.text);
421
+ if (text) {
422
+ lines.push(...renderIndentedPreview(text, 10, "text"));
423
+ }
424
+ return lines;
425
+ }
426
+ function renderTodos(data) {
427
+ const items = Array.isArray(data.items) ? data.items.map(objectField) : [];
428
+ if (!items.length) {
429
+ return [fg256(243, "No todo items.")];
430
+ }
431
+ const done = items.filter((item) => normalizedTodoStatus(item) === "done").length;
432
+ const active = items.filter((item) => normalizedTodoStatus(item) === "in_progress").length;
433
+ const queued = items.filter((item) => normalizedTodoStatus(item) === "pending").length;
434
+ return [
435
+ `${fg256(39, "progress")} ${done} done · ${active} active · ${queued} queued`,
436
+ ...items.slice(0, 16).map((todo, index) => {
437
+ const status = normalizedTodoStatus(todo);
438
+ const marker = todoMarker(status);
439
+ const label = todoStatusLabel(status);
440
+ const number = fg256(244, String(index + 1).padStart(2, "0"));
441
+ const content = stringField(todo.content) ?? stringField(todo.title) ?? stringField(todo.id) ?? compactObject(todo);
442
+ const id = stringField(todo.id);
443
+ const suffix = id && id !== content ? fg256(238, ` #${id}`) : "";
444
+ return `${number} ${marker} ${label} ${truncateToWidth(content, Math.max(24, terminalWidth() - 24))}${suffix}`;
445
+ }),
446
+ ];
447
+ }
448
+ function normalizedTodoStatus(todo) {
449
+ const status = (stringField(todo.status) ?? stringField(todo.state) ?? "pending").toLowerCase();
450
+ if (status === "done" || status === "completed" || status === "complete") {
451
+ return "done";
452
+ }
453
+ if (status === "in_progress" || status === "active" || status === "running") {
454
+ return "in_progress";
455
+ }
456
+ if (status === "blocked" || status === "failed") {
457
+ return "blocked";
458
+ }
459
+ return "pending";
460
+ }
461
+ function todoMarker(status) {
462
+ switch (status) {
463
+ case "done":
464
+ return fg256(48, "■");
465
+ case "in_progress":
466
+ return fg256(75, "▶");
467
+ case "blocked":
468
+ return fg256(203, "!");
469
+ case "pending":
470
+ return fg256(244, "□");
471
+ }
472
+ }
473
+ function todoStatusLabel(status) {
474
+ switch (status) {
475
+ case "done":
476
+ return fg256(48, padRight("done", 9));
477
+ case "in_progress":
478
+ return fg256(75, padRight("active", 9));
479
+ case "blocked":
480
+ return fg256(203, padRight("blocked", 9));
481
+ case "pending":
482
+ return fg256(244, padRight("queued", 9));
483
+ }
484
+ }
485
+ function renderClarifyTool(data) {
486
+ const answer = stringField(data.answer) ?? "unknown";
487
+ return [`${fg256(39, "answer")} ${answer}`];
488
+ }
489
+ function renderGoalTool(data) {
490
+ const goal = objectField(data.goal);
491
+ if (!Object.keys(goal).length) {
492
+ return [fg256(243, "No active goal.")];
493
+ }
494
+ const lines = [];
495
+ const summary = stringField(goal.summary);
496
+ if (summary) {
497
+ lines.push(`${fg256(39, "summary")} ${summary}`);
498
+ }
499
+ const completionReport = stringField(data.completion_budget_report);
500
+ if (completionReport) {
501
+ lines.push(`${fg256(39, "report")} ${completionReport}`);
502
+ }
503
+ const remaining = numberField(data.remaining_tokens);
504
+ if (remaining !== undefined) {
505
+ lines.push(`${fg256(39, "remaining")} ${remaining} tokens`);
506
+ }
507
+ const planning = objectField(goal.planning);
508
+ if (Object.keys(planning).length) {
509
+ lines.push(...renderGoalPlanningTool(planning));
510
+ }
511
+ const plan = objectField(goal.plan);
512
+ if (Object.keys(plan).length) {
513
+ lines.push(`${fg256(39, "plan")} ${stringField(plan.summary) ?? stringField(plan.objective) ?? "approved"}`);
514
+ }
515
+ return lines.length ? lines : [fg256(243, "Goal state saved.")];
516
+ }
517
+ function renderGoalPlanningTool(planning) {
518
+ const steps = Array.isArray(planning.steps) ? planning.steps.map(objectField) : [];
519
+ const summary = goalPlanningJsonSummary(steps);
520
+ const activeStepId = stringField(planning.active_step_id);
521
+ const lines = [`${fg256(39, "plan")} ${summary}`];
522
+ const activeStep = activeStepId ? steps.find((step) => stringField(step.id) === activeStepId) : undefined;
523
+ if (activeStep) {
524
+ const id = stringField(activeStep.id) ?? "step";
525
+ lines.push(`${fg256(39, "now")} ${goalStepJsonMarker(stringField(activeStep.status))} ${id} ${stringField(activeStep.title) ?? ""}`);
526
+ }
527
+ return lines;
528
+ }
529
+ function goalPlanningJsonSummary(steps) {
530
+ const labels = [
531
+ ["completed", "completed"],
532
+ ["in_progress", "in progress"],
533
+ ["blocked", "blocked"],
534
+ ["pending", "pending"],
535
+ ["skipped", "skipped"],
536
+ ];
537
+ const parts = labels
538
+ .map(([status, label]) => {
539
+ const count = steps.filter((step) => stringField(step.status) === status).length;
540
+ return count > 0 ? `${count} ${label}` : undefined;
541
+ })
542
+ .filter((part) => Boolean(part));
543
+ return parts.length ? parts.join(" · ") : "no steps";
544
+ }
545
+ function goalStepJsonMarker(status) {
546
+ switch (status) {
547
+ case "completed":
548
+ return fg256(48, "x");
549
+ case "in_progress":
550
+ return fg256(220, "*");
551
+ case "blocked":
552
+ return fg256(203, "!");
553
+ case "skipped":
554
+ return fg256(244, "-");
555
+ default:
556
+ return fg256(244, " ");
557
+ }
558
+ }
559
+ function renderPlanTool(data) {
560
+ const plan = objectField(data.plan);
561
+ if (!Object.keys(plan).length) {
562
+ return [fg256(243, "No active plan.")];
563
+ }
564
+ const lines = [];
565
+ const summary = stringField(plan.summary);
566
+ const body = stringField(plan.body);
567
+ if (!body) {
568
+ lines.push(`${fg256(39, "objective")} ${stringField(plan.objective) ?? "unknown"}`, `${fg256(39, "status")} ${stringField(plan.status) ?? "unknown"}`);
569
+ }
570
+ else if (summary) {
571
+ lines.push(`${fg256(39, "summary")} ${summary}`);
572
+ }
573
+ if (stringField(plan.status) === "drafting" || stringField(plan.status) === "paused") {
574
+ lines.push(`${fg256(39, "review")} ${body?.trim() ? "ready for approval" : fg256(244, "needs plan body")}`);
575
+ }
576
+ if (body) {
577
+ lines.push(...renderPlanDocumentSurface({
578
+ id: stringField(plan.id) ?? "plan",
579
+ objective: stringField(plan.objective) ?? "unknown",
580
+ status: planStatusField(plan.status),
581
+ summary,
582
+ body,
583
+ created_at: "",
584
+ updated_at: "",
585
+ }, { width: terminalWidth(), maxBodyLines: Number.POSITIVE_INFINITY }));
586
+ }
587
+ return lines;
588
+ }
589
+ function isFullWidthSurfaceLine(line) {
590
+ return line.startsWith("\x1b[48;5;");
591
+ }
592
+ function planStatusField(value) {
593
+ return value === "paused" || value === "approved" || value === "dropped" ? value : "drafting";
594
+ }
595
+ function renderAutoresearchTool(name, data) {
596
+ if (name === "log_experiment") {
597
+ const result = objectField(data.result);
598
+ const progress = objectField(data.progress);
599
+ if (!Object.keys(result).length && Object.keys(progress).length) {
600
+ return renderAutoresearchProgressLines(progress);
601
+ }
602
+ return [
603
+ `${fg256(39, "run")} ${numberField(result.run_id) ?? "unknown"}`,
604
+ `${fg256(39, "status")} ${stringField(result.status) ?? "unknown"}`,
605
+ `${fg256(39, "metric")} ${metricField(result.metric)}`,
606
+ ...renderAutoresearchProgressLines(progress),
607
+ ...(stringField(result.description) ? [`${fg256(39, "description")} ${stringField(result.description)}`] : []),
608
+ ];
609
+ }
610
+ if (name === "run_experiment") {
611
+ const progress = objectField(data.progress);
612
+ const pendingRun = objectField(data.pending_run);
613
+ if (Object.keys(pendingRun).length) {
614
+ return [
615
+ `${fg256(39, "pending run")} ${numberField(pendingRun.id) ?? "unknown"}`,
616
+ `${fg256(39, "pending status")} ${booleanField(pendingRun.timed_out) ? "timeout" : `exit ${numberField(pendingRun.exit_code) ?? "unknown"}`}`,
617
+ ...renderAutoresearchProgressLines(progress),
618
+ ...(stringField(pendingRun.output_resource_uri) ? [`${fg256(39, "output")} ${stringField(pendingRun.output_resource_uri)}`] : []),
619
+ ];
620
+ }
621
+ if (numberField(data.duration_ms) === undefined && numberField(data.exit_code) === undefined && Object.keys(progress).length) {
622
+ return renderAutoresearchProgressLines(progress);
623
+ }
624
+ return [
625
+ `${fg256(39, "status")} ${booleanField(data.timed_out) ? "timeout" : `exit ${numberField(data.exit_code) ?? "unknown"}`}`,
626
+ `${fg256(39, "duration")} ${numberField(data.duration_ms) ?? "unknown"}ms`,
627
+ `${fg256(39, "primary")} ${numberField(data.parsed_primary) ?? "missing"}`,
628
+ ...(booleanField(data.output_truncated) ? [`${fg256(39, "output")} truncated`] : []),
629
+ ...renderAutoresearchProgressLines(progress),
630
+ ...(stringField(data.output_resource_uri) ? [`${fg256(39, "output")} ${stringField(data.output_resource_uri)}`] : []),
631
+ ];
632
+ }
633
+ if (name === "init_experiment") {
634
+ const state = objectField(data.autoresearch);
635
+ const experiment = objectField(state.experiment);
636
+ const progress = objectField(data.progress);
637
+ const harness = objectField(data.harness_status);
638
+ if (!Object.keys(experiment).length) {
639
+ const lines = [
640
+ ...(stringField(state.goal) ? [`${fg256(39, "goal")} ${stringField(state.goal)}`] : []),
641
+ ...(stringField(harness.message) ? [`${fg256(39, "harness")} ${stringField(harness.message)}`] : []),
642
+ ...renderAutoresearchProgressLines(progress),
643
+ ];
644
+ return lines.length ? lines : [fg256(243, "Autoresearch initialization did not produce an experiment.")];
645
+ }
646
+ return [
647
+ `${fg256(39, "experiment")} ${stringField(experiment.name) ?? "unknown"}`,
648
+ `${fg256(39, "metric")} ${stringField(experiment.primary_metric) ?? "unknown"}`,
649
+ ...renderAutoresearchProgressLines(progress),
650
+ ...(stringField(harness.message) ? [`${fg256(39, "harness")} ${stringField(harness.message)}`] : []),
651
+ ];
652
+ }
653
+ const notes = stringField(data.notes);
654
+ return notes ? renderIndentedPreview(notes, 6, "notes") : [fg256(243, "Autoresearch notes updated.")];
655
+ }
656
+ function renderAutoresearchProgressLines(progress) {
657
+ const logged = numberField(progress.logged_runs);
658
+ if (logged === undefined) {
659
+ return [];
660
+ }
661
+ const kept = numberField(progress.kept_runs) ?? 0;
662
+ const cap = numberField(progress.keep_cap);
663
+ const pending = numberField(progress.pending_runs) ?? 0;
664
+ return [`${fg256(39, "progress")} ${logged} logged · ${kept}${cap === undefined ? "" : `/${cap}`} keep${pending ? ` · ${pending} pending` : ""}`];
665
+ }
666
+ function renderGeneric(data, resourceUri) {
667
+ if (Object.keys(data).length === 0) {
668
+ return resourceUri ? [] : [fg256(243, "No structured result.")];
669
+ }
670
+ return renderKeyValueObject(data);
671
+ }
672
+ function renderEvidenceObject(data) {
673
+ const rows = renderKeyValueObject(data);
674
+ return rows.length ? rows.map((row, index) => (index === 0 ? `${fg256(39, "evidence")} ${row}` : ` ${row}`)) : [fg256(243, "No evidence fields.")];
675
+ }
676
+ function renderKeyValueObject(data) {
677
+ const entries = Object.entries(data);
678
+ if (!entries.length) {
679
+ return [];
680
+ }
681
+ return entries.slice(0, 12).map(([key, value]) => `${fg256(39, key)} ${compactValue(value)}`);
682
+ }
683
+ function compactValue(value) {
684
+ if (value === null || value === undefined) {
685
+ return fg256(244, "none");
686
+ }
687
+ if (typeof value === "string") {
688
+ return truncateToWidth(value, Math.max(24, terminalWidth() - 20));
689
+ }
690
+ if (typeof value === "number" || typeof value === "boolean") {
691
+ return String(value);
692
+ }
693
+ if (Array.isArray(value)) {
694
+ return value.map((item) => compactValue(item)).join(", ");
695
+ }
696
+ if (typeof value === "object") {
697
+ return Object.entries(value)
698
+ .slice(0, 6)
699
+ .map(([key, item]) => `${key}=${compactValue(item)}`)
700
+ .join(" · ");
701
+ }
702
+ return String(value);
703
+ }
704
+ function compactObject(value) {
705
+ return compactValue(value) || "item";
706
+ }
707
+ function renderDiff(text) {
708
+ if (!text) {
709
+ return [fg256(243, "No diff output.")];
710
+ }
711
+ const source = text.split(/\r?\n/).slice(0, 120);
712
+ const output = [];
713
+ let oldLine = 0;
714
+ let newLine = 0;
715
+ for (let index = 0; index < source.length; index += 1) {
716
+ const line = source[index] ?? "";
717
+ if (line.startsWith("diff --git")) {
718
+ output.push(fg256(171, line));
719
+ continue;
720
+ }
721
+ if (line.startsWith("+++") || line.startsWith("---")) {
722
+ output.push(fg256(243, line));
723
+ continue;
724
+ }
725
+ if (line.startsWith("@@")) {
726
+ const parsed = parseHunkHeader(line);
727
+ if (parsed) {
728
+ oldLine = parsed.oldStart;
729
+ newLine = parsed.newStart;
730
+ }
731
+ output.push(fg256(45, line));
732
+ continue;
733
+ }
734
+ const next = source[index + 1] ?? "";
735
+ if (line.startsWith("-") && !line.startsWith("---") && next.startsWith("+") && !next.startsWith("+++")) {
736
+ output.push(formatDiffRow({ oldLine, newLine: undefined, marker: "-", content: highlightChangedText(line.slice(1), next.slice(1), 203), color: 203 }));
737
+ oldLine += 1;
738
+ output.push(formatDiffRow({ oldLine: undefined, newLine, marker: "+", content: highlightChangedText(next.slice(1), line.slice(1), 48), color: 48 }));
739
+ newLine += 1;
740
+ index += 1;
741
+ continue;
742
+ }
743
+ if (line.startsWith("-") && !line.startsWith("---")) {
744
+ output.push(formatDiffRow({ oldLine, newLine: undefined, marker: "-", content: markIndent(line.slice(1)), color: 203 }));
745
+ oldLine += 1;
746
+ continue;
747
+ }
748
+ if (line.startsWith("+") && !line.startsWith("+++")) {
749
+ output.push(formatDiffRow({ oldLine: undefined, newLine, marker: "+", content: markIndent(line.slice(1)), color: 48 }));
750
+ newLine += 1;
751
+ continue;
752
+ }
753
+ const content = line.startsWith(" ") ? line.slice(1) : line;
754
+ output.push(formatDiffRow({ oldLine, newLine, marker: " ", content: markIndent(content), color: 250 }));
755
+ oldLine += 1;
756
+ newLine += 1;
757
+ }
758
+ if (source.length >= 120) {
759
+ output.push(fg256(243, "... diff truncated"));
760
+ }
761
+ return output;
762
+ }
763
+ function parseHunkHeader(line) {
764
+ const match = /^@@\s+-(\d+)(?:,\d+)?\s+\+(\d+)(?:,\d+)?/.exec(line);
765
+ if (!match) {
766
+ return undefined;
767
+ }
768
+ return { oldStart: Number(match[1]), newStart: Number(match[2]) };
769
+ }
770
+ function formatDiffRow(input) {
771
+ const oldNo = input.oldLine === undefined ? " " : String(input.oldLine).padStart(4);
772
+ const newNo = input.newLine === undefined ? " " : String(input.newLine).padStart(4);
773
+ const gutter = `${fg256(243, oldNo)} ${fg256(243, newNo)} ${fg256(input.color, input.marker)} ${fg256(238, "│")}`;
774
+ const room = Math.max(24, Math.min(120, terminalWidth() - 8) - visibleWidth(gutter) - 1);
775
+ return `${gutter} ${fgLine(input.color, truncateToWidth(input.content, room))}`;
776
+ }
777
+ function markIndent(text) {
778
+ const match = /^(\s+)(.*)$/.exec(text);
779
+ if (!match) {
780
+ return text;
781
+ }
782
+ return `${fg256(238, (match[1] ?? "").replaceAll(" ", "·").replaceAll("\t", "→ "))}${match[2] ?? ""}`;
783
+ }
784
+ function highlightChangedText(text, other, color) {
785
+ const marked = markIndent(text);
786
+ const plainText = text.trimStart();
787
+ const plainOther = other.trimStart();
788
+ let prefix = 0;
789
+ while (prefix < plainText.length && prefix < plainOther.length && plainText[prefix] === plainOther[prefix]) {
790
+ prefix += 1;
791
+ }
792
+ let suffix = 0;
793
+ while (suffix + prefix < plainText.length &&
794
+ suffix + prefix < plainOther.length &&
795
+ plainText[plainText.length - 1 - suffix] === plainOther[plainOther.length - 1 - suffix]) {
796
+ suffix += 1;
797
+ }
798
+ if (prefix + suffix >= plainText.length) {
799
+ return marked;
800
+ }
801
+ const leadingWhitespace = text.length - plainText.length;
802
+ const start = leadingWhitespace + prefix;
803
+ const end = Math.max(start, text.length - suffix);
804
+ return `${markIndent(text.slice(0, start))}${ansi.bold}${fg256(color, text.slice(start, end))}${ansi.reset}${markIndent(text.slice(end))}`;
805
+ }
806
+ function fgLine(code, text) {
807
+ const open = `\x1b[38;5;${code}m`;
808
+ return `${open}${text.replaceAll(ansi.reset, `${ansi.reset}${open}`)}${ansi.reset}`;
809
+ }
810
+ function renderTextPreview(text, maxLines = 12) {
811
+ const lines = text.split(/\r?\n/);
812
+ const preview = lines.slice(0, maxLines);
813
+ if (lines.length > preview.length) {
814
+ preview.push(fg256(243, `... ${lines.length - preview.length} more lines`));
815
+ }
816
+ return preview;
817
+ }
818
+ function renderIndentedPreview(text, maxLines, label) {
819
+ return renderTextPreview(text, maxLines).map((line, index) => (index === 0 ? `${fg256(39, label)} ${line}` : ` ${line}`));
820
+ }
821
+ function simplePatch(file, oldText, newText) {
822
+ const oldLines = oldText.split(/\r?\n/).slice(0, 20);
823
+ const newLines = newText.split(/\r?\n/).slice(0, 20);
824
+ return [`--- ${file}`, `+++ ${file}`, ...oldLines.map((line) => `-${line}`), ...newLines.map((line) => `+${line}`)].join("\n");
825
+ }
826
+ function resourceText(uri, store) {
827
+ if (!uri) {
828
+ return undefined;
829
+ }
830
+ return store.readResource(uri)?.content;
831
+ }
832
+ function toolGroupAction(group) {
833
+ const name = group.name;
834
+ const ok = group.result?.ok;
835
+ const failed = ok === false ? " failed" : "";
836
+ switch (name) {
837
+ case "run_command":
838
+ return `Ran${failed}`;
839
+ case "list_dir":
840
+ return `Listed directory${failed}`;
841
+ case "glob":
842
+ return `Scanned files${failed}`;
843
+ case "file_search":
844
+ return `Searched workspace${failed}`;
845
+ case "read_file":
846
+ case "read_resource":
847
+ return `Read file${failed}`;
848
+ case "codegraph_explore":
849
+ return `Explored context${failed}`;
850
+ case "codegraph_search":
851
+ return `Searched semantic index${failed}`;
852
+ case "codegraph_node":
853
+ return `Read indexed symbol${failed}`;
854
+ case "codegraph_callers":
855
+ case "codegraph_callees":
856
+ case "codegraph_impact":
857
+ return `Traced semantic index${failed}`;
858
+ case "codegraph_files":
859
+ case "codegraph_status":
860
+ return `Checked context engine${failed}`;
861
+ case "write_file":
862
+ return `Wrote file${failed}`;
863
+ case "edit_file":
864
+ case "ast_edit":
865
+ return `Edited file${failed}`;
866
+ case "apply_patch":
867
+ return `Applied patch${failed}`;
868
+ case "git_status":
869
+ return `Checked git status${failed}`;
870
+ case "git_diff":
871
+ case "git_show":
872
+ return `Read git data${failed}`;
873
+ case "todo_write":
874
+ return `Updated todo${failed}`;
875
+ case "clarify":
876
+ return ok === false ? "Question failed" : "Questions answered";
877
+ case "goal":
878
+ return `Updated goal${failed}`;
879
+ case "plan":
880
+ return `Updated plan${failed}`;
881
+ case "init_experiment":
882
+ return `Initialized experiment${failed}`;
883
+ case "run_experiment":
884
+ return `Ran experiment${failed}`;
885
+ case "log_experiment":
886
+ return `Logged experiment${failed}`;
887
+ case "update_notes":
888
+ return `Updated notes${failed}`;
889
+ case "complete_step":
890
+ return `Recorded evidence${failed}`;
891
+ case "web_search":
892
+ return `Searched web${failed}`;
893
+ case "web_fetch":
894
+ return `Fetched URL${failed}`;
895
+ case "web_open":
896
+ return `Opened URL${failed}`;
897
+ default:
898
+ if (name.includes("skill"))
899
+ return `Updated skills${failed}`;
900
+ if (name.includes("process"))
901
+ return `Managed process${failed}`;
902
+ if (name.includes("image") || name.includes("video") || name.includes("vision") || name.includes("audio"))
903
+ return `Used Omni${failed}`;
904
+ return ok === undefined ? `Running ${name}` : `Used tool${failed}`;
905
+ }
906
+ }
907
+ function toolGroupDetail(group, summary) {
908
+ const data = objectField(group.result?.data);
909
+ switch (group.name) {
910
+ case "run_command": {
911
+ const command = stringField(data.command) ?? stringField(group.args.command);
912
+ const code = numberField(data.code);
913
+ if (command && code !== undefined) {
914
+ return `${command} · exited ${code}`;
915
+ }
916
+ return command ?? compactSummary(summary);
917
+ }
918
+ case "list_dir":
919
+ return stringField(group.args.path) ?? stringField(data.path) ?? compactSummary(summary);
920
+ case "glob":
921
+ return stringField(group.args.pattern) ?? compactSummary(summary);
922
+ case "file_search":
923
+ return stringField(group.args.query) ?? compactSummary(summary);
924
+ case "read_file":
925
+ case "read_resource":
926
+ return stringField(group.args.path) ?? stringField(group.args.uri) ?? compactSummary(summary);
927
+ case "codegraph_explore":
928
+ return stringField(group.args.query) ?? compactSummary(summary);
929
+ case "codegraph_search":
930
+ return stringField(group.args.query) ?? compactSummary(summary);
931
+ case "codegraph_node":
932
+ case "codegraph_callers":
933
+ case "codegraph_callees":
934
+ case "codegraph_impact":
935
+ return stringField(group.args.symbol) ?? compactSummary(summary);
936
+ case "codegraph_files":
937
+ return stringField(group.args.path) ?? stringField(group.args.pattern) ?? compactSummary(summary);
938
+ case "codegraph_status":
939
+ return compactSummary(summary);
940
+ case "write_file":
941
+ case "edit_file":
942
+ case "ast_edit":
943
+ return stringField(data.path) ?? stringField(group.args.path) ?? compactSummary(summary);
944
+ case "git_diff":
945
+ case "git_show":
946
+ return stringField(group.args.path) ?? stringField(group.args.rev) ?? compactSummary(summary);
947
+ case "todo_write":
948
+ return compactSummary(summary);
949
+ case "clarify":
950
+ return stringField(data.question) ?? stringField(group.args.question) ?? compactSummary(summary);
951
+ case "goal": {
952
+ const goal = objectField(data.goal);
953
+ return [stringField(goal.objective), stringField(goal.status)].filter(Boolean).join(" · ") || compactSummary(summary);
954
+ }
955
+ case "plan": {
956
+ const plan = objectField(data.plan);
957
+ return [stringField(plan.objective), stringField(plan.status)].filter(Boolean).join(" · ") || compactSummary(summary);
958
+ }
959
+ case "log_experiment": {
960
+ const result = objectField(data.result);
961
+ const run = numberField(result.run_id);
962
+ const status = stringField(result.status);
963
+ const metric = result.metric === undefined ? undefined : `metric ${metricField(result.metric)}`;
964
+ return [`run ${run ?? "?"}`, status, metric].filter(Boolean).join(" · ") || compactSummary(summary);
965
+ }
966
+ case "run_experiment": {
967
+ const pendingRun = objectField(data.pending_run);
968
+ const pendingId = numberField(pendingRun.id);
969
+ if (pendingId !== undefined) {
970
+ return `pending run ${pendingId}`;
971
+ }
972
+ const primary = numberField(data.parsed_primary);
973
+ const exit = numberField(data.exit_code);
974
+ const status = booleanField(data.timed_out) ? "timeout" : `exit ${exit ?? "?"}`;
975
+ return [status, primary === undefined ? "primary missing" : `primary ${primary}`].join(" · ");
976
+ }
977
+ case "init_experiment": {
978
+ const harness = objectField(data.harness_status);
979
+ const harnessMessage = stringField(harness.message);
980
+ if (harnessMessage) {
981
+ return harnessMessage;
982
+ }
983
+ const state = objectField(data.autoresearch);
984
+ const experiment = objectField(state.experiment);
985
+ return stringField(experiment.name) ?? compactSummary(summary);
986
+ }
987
+ case "update_notes":
988
+ return compactSummary(summary);
989
+ case "web_search":
990
+ return stringField(group.args.query) ?? compactSummary(summary);
991
+ case "web_fetch":
992
+ case "web_open":
993
+ return stringField(group.args.url) ?? stringField(data.final_url) ?? compactSummary(summary);
994
+ default:
995
+ return compactSummary(summary);
996
+ }
997
+ }
998
+ function compactSummary(summary) {
999
+ return summary
1000
+ .replace(/^Command exited\s+0$/i, "exited 0")
1001
+ .replace(/^Command exited\s+(\d+)$/i, "exited $1")
1002
+ .replace(/\s+/g, " ")
1003
+ .trim();
1004
+ }
1005
+ function objectField(value) {
1006
+ return value && typeof value === "object" && !Array.isArray(value) ? value : {};
1007
+ }
1008
+ function stringField(value) {
1009
+ return typeof value === "string" && value.length > 0 ? value : undefined;
1010
+ }
1011
+ function numberField(value) {
1012
+ return typeof value === "number" && Number.isFinite(value) ? value : undefined;
1013
+ }
1014
+ function metricField(value) {
1015
+ const metric = numberField(value);
1016
+ if (metric !== undefined) {
1017
+ return String(metric);
1018
+ }
1019
+ return value === null ? "missing" : "unknown";
1020
+ }
1021
+ function booleanField(value) {
1022
+ return value === true;
1023
+ }
1024
+ //# sourceMappingURL=tool-renderer.js.map