erosolar-cli 1.7.409 → 1.7.411

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 (192) hide show
  1. package/README.md +6 -6
  2. package/dist/StringUtils.d.ts +1 -4
  3. package/dist/StringUtils.d.ts.map +1 -1
  4. package/dist/StringUtils.js +2 -8
  5. package/dist/StringUtils.js.map +1 -1
  6. package/dist/browser/BrowserSessionManager.d.ts +1 -3
  7. package/dist/browser/BrowserSessionManager.d.ts.map +1 -1
  8. package/dist/browser/BrowserSessionManager.js +4 -24
  9. package/dist/browser/BrowserSessionManager.js.map +1 -1
  10. package/dist/capabilities/toolRegistry.d.ts +2 -0
  11. package/dist/capabilities/toolRegistry.d.ts.map +1 -1
  12. package/dist/capabilities/toolRegistry.js +40 -5
  13. package/dist/capabilities/toolRegistry.js.map +1 -1
  14. package/dist/contracts/agent-profiles.schema.json +5 -5
  15. package/dist/contracts/agent-schemas.json +6 -16
  16. package/dist/contracts/schemas/agent.schema.json +1 -5
  17. package/dist/contracts/schemas/tool-selection.schema.json +1 -7
  18. package/dist/contracts/tools.schema.json +80 -207
  19. package/dist/contracts/unified-schema.json +4 -5
  20. package/dist/contracts/v1/agent.d.ts +0 -3
  21. package/dist/contracts/v1/agent.d.ts.map +1 -1
  22. package/dist/contracts/v1/provider.d.ts +1 -2
  23. package/dist/contracts/v1/provider.d.ts.map +1 -1
  24. package/dist/contracts/v1/toolAccess.d.ts +1 -1
  25. package/dist/contracts/v1/toolAccess.d.ts.map +1 -1
  26. package/dist/core/agent.d.ts +1 -7
  27. package/dist/core/agent.d.ts.map +1 -1
  28. package/dist/core/agent.js +2 -131
  29. package/dist/core/agent.js.map +1 -1
  30. package/dist/core/alphaZeroEngine.d.ts +0 -8
  31. package/dist/core/alphaZeroEngine.d.ts.map +1 -1
  32. package/dist/core/alphaZeroEngine.js +35 -149
  33. package/dist/core/alphaZeroEngine.js.map +1 -1
  34. package/dist/core/alphaZeroOrchestrator.d.ts +0 -17
  35. package/dist/core/alphaZeroOrchestrator.d.ts.map +1 -1
  36. package/dist/core/alphaZeroOrchestrator.js +8 -95
  37. package/dist/core/alphaZeroOrchestrator.js.map +1 -1
  38. package/dist/core/cliTestHarness.d.ts +0 -5
  39. package/dist/core/cliTestHarness.d.ts.map +1 -1
  40. package/dist/core/cliTestHarness.js +3 -14
  41. package/dist/core/cliTestHarness.js.map +1 -1
  42. package/dist/core/contextManager.d.ts +0 -30
  43. package/dist/core/contextManager.d.ts.map +1 -1
  44. package/dist/core/contextManager.js +5 -87
  45. package/dist/core/contextManager.js.map +1 -1
  46. package/dist/core/contextWindow.d.ts +4 -4
  47. package/dist/core/contextWindow.js +9 -9
  48. package/dist/core/contextWindow.js.map +1 -1
  49. package/dist/core/modelDiscovery.js +3 -3
  50. package/dist/core/modelDiscovery.js.map +1 -1
  51. package/dist/core/preferences.d.ts +2 -3
  52. package/dist/core/preferences.d.ts.map +1 -1
  53. package/dist/core/preferences.js +11 -18
  54. package/dist/core/preferences.js.map +1 -1
  55. package/dist/core/secretStore.d.ts.map +1 -1
  56. package/dist/core/secretStore.js +31 -0
  57. package/dist/core/secretStore.js.map +1 -1
  58. package/dist/core/toolPreconditions.d.ts.map +1 -1
  59. package/dist/core/toolPreconditions.js +0 -60
  60. package/dist/core/toolPreconditions.js.map +1 -1
  61. package/dist/core/toolRuntime.d.ts.map +1 -1
  62. package/dist/core/toolRuntime.js +0 -17
  63. package/dist/core/toolRuntime.js.map +1 -1
  64. package/dist/core/types.d.ts +1 -1
  65. package/dist/core/types.d.ts.map +1 -1
  66. package/dist/plugins/providers/google/index.js +3 -2
  67. package/dist/plugins/providers/google/index.js.map +1 -1
  68. package/dist/providers/openaiChatCompletionsProvider.d.ts.map +1 -1
  69. package/dist/providers/openaiChatCompletionsProvider.js +6 -60
  70. package/dist/providers/openaiChatCompletionsProvider.js.map +1 -1
  71. package/dist/runtime/agentController.d.ts.map +1 -1
  72. package/dist/runtime/agentController.js +6 -27
  73. package/dist/runtime/agentController.js.map +1 -1
  74. package/dist/shell/interactiveShell.d.ts +30 -79
  75. package/dist/shell/interactiveShell.d.ts.map +1 -1
  76. package/dist/shell/interactiveShell.js +726 -1519
  77. package/dist/shell/interactiveShell.js.map +1 -1
  78. package/dist/shell/shellApp.d.ts.map +1 -1
  79. package/dist/shell/shellApp.js +41 -15
  80. package/dist/shell/shellApp.js.map +1 -1
  81. package/dist/shell/systemPrompt.d.ts.map +1 -1
  82. package/dist/shell/systemPrompt.js +0 -1
  83. package/dist/shell/systemPrompt.js.map +1 -1
  84. package/dist/shell/terminalInput.d.ts +21 -85
  85. package/dist/shell/terminalInput.d.ts.map +1 -1
  86. package/dist/shell/terminalInput.js +60 -517
  87. package/dist/shell/terminalInput.js.map +1 -1
  88. package/dist/shell/terminalInputAdapter.d.ts +16 -37
  89. package/dist/shell/terminalInputAdapter.d.ts.map +1 -1
  90. package/dist/shell/terminalInputAdapter.js +22 -44
  91. package/dist/shell/terminalInputAdapter.js.map +1 -1
  92. package/dist/shell/updateManager.d.ts +1 -8
  93. package/dist/shell/updateManager.d.ts.map +1 -1
  94. package/dist/shell/updateManager.js +14 -9
  95. package/dist/shell/updateManager.js.map +1 -1
  96. package/dist/subagents/parallelAgentManager.d.ts.map +1 -1
  97. package/dist/subagents/parallelAgentManager.js +2 -1
  98. package/dist/subagents/parallelAgentManager.js.map +1 -1
  99. package/dist/tools/buildTools.d.ts.map +1 -1
  100. package/dist/tools/buildTools.js +76 -19
  101. package/dist/tools/buildTools.js.map +1 -1
  102. package/dist/tools/editTools.js +1 -1
  103. package/dist/tools/editTools.js.map +1 -1
  104. package/dist/tools/enhancedCodeIntelligenceTools.js +2 -1
  105. package/dist/tools/enhancedCodeIntelligenceTools.js.map +1 -1
  106. package/dist/tools/fileTools.js +0 -3
  107. package/dist/tools/fileTools.js.map +1 -1
  108. package/dist/tools/frontendTestingTools.js +1 -1
  109. package/dist/tools/frontendTestingTools.js.map +1 -1
  110. package/dist/tools/learnTools.d.ts +0 -2
  111. package/dist/tools/learnTools.d.ts.map +1 -1
  112. package/dist/tools/learnTools.js +81 -29
  113. package/dist/tools/learnTools.js.map +1 -1
  114. package/dist/tools/localExplore.d.ts.map +1 -1
  115. package/dist/tools/localExplore.js +1 -0
  116. package/dist/tools/localExplore.js.map +1 -1
  117. package/dist/tools/notebookEditTools.js.map +1 -1
  118. package/dist/tools/repoChecksTools.js +3 -4
  119. package/dist/tools/repoChecksTools.js.map +1 -1
  120. package/dist/tools/searchTools.js +0 -4
  121. package/dist/tools/searchTools.js.map +1 -1
  122. package/dist/tools/softwareEngineeringTools.d.ts.map +1 -1
  123. package/dist/tools/softwareEngineeringTools.js +0 -1
  124. package/dist/tools/softwareEngineeringTools.js.map +1 -1
  125. package/dist/tools/webTools.d.ts.map +1 -1
  126. package/dist/tools/webTools.js.map +1 -1
  127. package/dist/ui/ShellUIAdapter.d.ts +16 -44
  128. package/dist/ui/ShellUIAdapter.d.ts.map +1 -1
  129. package/dist/ui/ShellUIAdapter.js +84 -337
  130. package/dist/ui/ShellUIAdapter.js.map +1 -1
  131. package/dist/ui/display.d.ts +37 -18
  132. package/dist/ui/display.d.ts.map +1 -1
  133. package/dist/ui/display.js +310 -95
  134. package/dist/ui/display.js.map +1 -1
  135. package/dist/ui/orchestration/UIUpdateCoordinator.d.ts.map +1 -1
  136. package/dist/ui/orchestration/UIUpdateCoordinator.js +3 -5
  137. package/dist/ui/orchestration/UIUpdateCoordinator.js.map +1 -1
  138. package/dist/ui/shortcutsHelp.d.ts +11 -1
  139. package/dist/ui/shortcutsHelp.d.ts.map +1 -1
  140. package/dist/ui/shortcutsHelp.js +54 -8
  141. package/dist/ui/shortcutsHelp.js.map +1 -1
  142. package/dist/ui/streamingFormatter.d.ts +16 -0
  143. package/dist/ui/streamingFormatter.d.ts.map +1 -0
  144. package/dist/ui/streamingFormatter.js +62 -0
  145. package/dist/ui/streamingFormatter.js.map +1 -0
  146. package/dist/ui/theme.d.ts +100 -100
  147. package/dist/ui/theme.d.ts.map +1 -1
  148. package/dist/ui/theme.js.map +1 -1
  149. package/dist/ui/toolDisplay.d.ts +3 -3
  150. package/dist/ui/toolDisplay.d.ts.map +1 -1
  151. package/dist/ui/toolDisplay.js +8 -7
  152. package/dist/ui/toolDisplay.js.map +1 -1
  153. package/dist/ui/unified/index.d.ts +2 -2
  154. package/dist/ui/unified/index.d.ts.map +1 -1
  155. package/dist/ui/unified/index.js.map +1 -1
  156. package/dist/ui/unified/layout.d.ts +23 -0
  157. package/dist/ui/unified/layout.d.ts.map +1 -1
  158. package/dist/ui/unified/layout.js +113 -11
  159. package/dist/ui/unified/layout.js.map +1 -1
  160. package/package.json +24 -37
  161. package/dist/core/alphaZeroConfig.d.ts +0 -11
  162. package/dist/core/alphaZeroConfig.d.ts.map +0 -1
  163. package/dist/core/alphaZeroConfig.js +0 -59
  164. package/dist/core/alphaZeroConfig.js.map +0 -1
  165. package/dist/core/alphaZeroEnhanced.d.ts +0 -125
  166. package/dist/core/alphaZeroEnhanced.d.ts.map +0 -1
  167. package/dist/core/alphaZeroEnhanced.js +0 -386
  168. package/dist/core/alphaZeroEnhanced.js.map +0 -1
  169. package/dist/core/autonomousVerification.d.ts +0 -103
  170. package/dist/core/autonomousVerification.d.ts.map +0 -1
  171. package/dist/core/autonomousVerification.js +0 -583
  172. package/dist/core/autonomousVerification.js.map +0 -1
  173. package/dist/core/offsecAlphaZeroEnhanced.d.ts +0 -98
  174. package/dist/core/offsecAlphaZeroEnhanced.d.ts.map +0 -1
  175. package/dist/core/offsecAlphaZeroEnhanced.js +0 -441
  176. package/dist/core/offsecAlphaZeroEnhanced.js.map +0 -1
  177. package/dist/core/parallelAgentOrchestrator.d.ts +0 -171
  178. package/dist/core/parallelAgentOrchestrator.d.ts.map +0 -1
  179. package/dist/core/parallelAgentOrchestrator.js +0 -459
  180. package/dist/core/parallelAgentOrchestrator.js.map +0 -1
  181. package/dist/index.d.ts +0 -5
  182. package/dist/index.d.ts.map +0 -1
  183. package/dist/index.js +0 -3
  184. package/dist/index.js.map +0 -1
  185. package/dist/tools/detectCommands.d.ts +0 -8
  186. package/dist/tools/detectCommands.d.ts.map +0 -1
  187. package/dist/tools/detectCommands.js +0 -183
  188. package/dist/tools/detectCommands.js.map +0 -1
  189. package/dist/ui/assistantBlockRenderer.d.ts +0 -30
  190. package/dist/ui/assistantBlockRenderer.d.ts.map +0 -1
  191. package/dist/ui/assistantBlockRenderer.js +0 -121
  192. package/dist/ui/assistantBlockRenderer.js.map +0 -1
@@ -15,6 +15,7 @@ import { theme, icons } from './theme.js';
15
15
  import { UIUpdateCoordinator } from './orchestration/UIUpdateCoordinator.js';
16
16
  import { compactRenderer } from './compactRenderer.js';
17
17
  import { inPlaceUpdater } from './inPlaceUpdater.js';
18
+ import { formatTip } from './shortcutsHelp.js';
18
19
  export class ShellUIAdapter {
19
20
  uiController;
20
21
  display;
@@ -31,7 +32,9 @@ export class ShellUIAdapter {
31
32
  maxCompletedOps = 8;
32
33
  compactDisplayMode = true; // Enable compact same-line displays
33
34
  toolWarnings = new Map();
34
- recentWarnings = [];
35
+ // Tips display tracking - show tips periodically (Claude Code style)
36
+ toolResultCount = 0;
37
+ tipInterval = 5; // Show tip every N tool results
35
38
  constructor(writeStream, display, config = {}, updateCoordinator) {
36
39
  this.display = display;
37
40
  this.config = {
@@ -106,7 +109,7 @@ export class ShellUIAdapter {
106
109
  // Update status bar to show active tool
107
110
  if (this._toolStatusCallback) {
108
111
  const actionDesc = this.getToolActionDescription(call);
109
- this._toolStatusCallback({ text: actionDesc, stage: 'start' });
112
+ this._toolStatusCallback(actionDesc);
110
113
  }
111
114
  this.uiController.onToolStart(call);
112
115
  },
@@ -125,7 +128,7 @@ export class ShellUIAdapter {
125
128
  if (this._toolStatusCallback) {
126
129
  const description = this.getToolActionDescription(call, progress);
127
130
  if (description) {
128
- this._toolStatusCallback({ text: description, stage: 'progress' });
131
+ this._toolStatusCallback(description);
129
132
  }
130
133
  }
131
134
  // Show progress bar for file operations and long-running tools
@@ -137,14 +140,11 @@ export class ShellUIAdapter {
137
140
  const toolName = theme.tool(call.name);
138
141
  const warningText = this.formatToolWarning(warning);
139
142
  const line = `${theme.warning(icons.warning)} ${toolName} ${theme.ui.muted('preflight')} ${warningText}`;
140
- this.recordToolWarning(call.id, call.name, warningText);
143
+ this.recordToolWarning(call.id, warningText);
141
144
  // Use display.stream() to work with scroll regions
142
145
  this.display.stream(`\n${line}\n`);
143
146
  if (this._toolStatusCallback) {
144
- this._toolStatusCallback({
145
- text: `Warning: ${this.getToolActionDescription(call)}`,
146
- stage: 'progress',
147
- });
147
+ this._toolStatusCallback(`Warning: ${this.getToolActionDescription(call)}`);
148
148
  }
149
149
  },
150
150
  onToolResult: (call, output) => {
@@ -168,18 +168,24 @@ export class ShellUIAdapter {
168
168
  this.fileChangeCallback(fileChange.path, fileChange.type, fileChange.additions, fileChange.removals);
169
169
  }
170
170
  }
171
- // Render concise tool result + preview instead of verbose blocks
172
- this.displayToolResultSummary(call, output, true);
171
+ // Use compact display for quick single-result tools
172
+ if (this.compactDisplayMode && this.isCompactTool(call.name)) {
173
+ this.displayCompactResult(call, output, true);
174
+ }
175
+ else {
176
+ // Claude Code style: Display tool result with ⎿ prefix
177
+ this.displayToolResultSummary(call, output, true);
178
+ }
173
179
  // Surface any captured preflight warnings in a structured block
174
180
  this.flushToolWarnings(call.id, call.name);
181
+ // Show tip periodically (Claude Code style)
182
+ this.toolResultCount++;
183
+ if (this.toolResultCount % this.tipInterval === 0) {
184
+ this.display.stream(`${formatTip()}\n`);
185
+ }
175
186
  // Clear status bar after showing result
176
187
  if (this._toolStatusCallback) {
177
- const completed = this.getToolActionDescription(call);
178
- this._toolStatusCallback({
179
- text: completed ? `Completed ${completed}` : 'Tool complete',
180
- stage: 'result',
181
- });
182
- this._toolStatusCallback({ text: null, stage: 'complete' });
188
+ this._toolStatusCallback(null);
183
189
  }
184
190
  this.uiController.onToolComplete(call.id, output);
185
191
  },
@@ -193,17 +199,18 @@ export class ShellUIAdapter {
193
199
  this.pendingOperations.delete(call.id);
194
200
  this.completedOperations.push(op);
195
201
  }
196
- // Render concise error summary + preview instead of verbose blocks
197
- this.displayToolResultSummary(call, message, false);
202
+ // Use compact display for errors too
203
+ if (this.compactDisplayMode && this.isCompactTool(call.name)) {
204
+ this.displayCompactResult(call, message, false);
205
+ }
206
+ else {
207
+ // Claude Code style: Display error with ⎿ prefix (error color)
208
+ this.displayToolResultSummary(call, message, false);
209
+ }
198
210
  this.flushToolWarnings(call.id, call.name);
199
211
  // Clear status bar after showing error
200
212
  if (this._toolStatusCallback) {
201
- const failed = this.getToolActionDescription(call);
202
- this._toolStatusCallback({
203
- text: failed ? `Failed ${failed}` : 'Tool failed',
204
- stage: 'error',
205
- });
206
- this._toolStatusCallback({ text: null, stage: 'complete' });
213
+ this._toolStatusCallback(null);
207
214
  }
208
215
  this.uiController.onToolError(call.id, { message });
209
216
  },
@@ -224,20 +231,24 @@ export class ShellUIAdapter {
224
231
  const badge = compactRenderer.formatToolBadge(operation);
225
232
  this.display.stream(`${badge}\n`);
226
233
  }
227
- if (this._toolStatusCallback) {
228
- const cached = this.getToolActionDescription(call);
229
- this._toolStatusCallback({
230
- text: cached ? `Cached ${cached}` : 'Tool cache hit',
231
- stage: 'result',
232
- });
233
- this._toolStatusCallback({ text: null, stage: 'complete' });
234
- }
235
234
  this.flushToolWarnings(call.id, call.name);
236
235
  this.uiController.onToolStart(call);
237
236
  this.uiController.onToolComplete(call.id, 'cache-hit');
238
237
  },
239
238
  };
240
239
  }
240
+ /**
241
+ * Check if a tool should use compact (single-line) display
242
+ */
243
+ isCompactTool(toolName) {
244
+ const compactTools = new Set([
245
+ 'Read', 'read_file',
246
+ 'Glob', 'glob',
247
+ 'TodoWrite', 'todo_write',
248
+ 'WebFetch', 'web_fetch',
249
+ ]);
250
+ return compactTools.has(toolName);
251
+ }
241
252
  /**
242
253
  * Normalize preflight warnings for consistent display.
243
254
  */
@@ -252,15 +263,10 @@ export class ShellUIAdapter {
252
263
  /**
253
264
  * Track warnings for a tool call so we can show them after the result too.
254
265
  */
255
- recordToolWarning(callId, toolName, warningText) {
266
+ recordToolWarning(callId, warningText) {
256
267
  const existing = this.toolWarnings.get(callId) ?? [];
257
268
  existing.push(warningText);
258
269
  this.toolWarnings.set(callId, existing);
259
- this.recentWarnings.push({ tool: toolName, text: warningText, time: Date.now() });
260
- // Keep recent warnings list compact
261
- if (this.recentWarnings.length > 20) {
262
- this.recentWarnings.shift();
263
- }
264
270
  }
265
271
  /**
266
272
  * Render any captured warnings for the given tool call as a structured block.
@@ -276,14 +282,6 @@ export class ShellUIAdapter {
276
282
  const body = warnings.map(text => ` ${bullet} ${text}`).join('\n');
277
283
  this.display.stream(`\n${header}\n${body}\n`);
278
284
  }
279
- /**
280
- * Return preflight warnings captured since a timestamp.
281
- */
282
- getRecentWarnings(since) {
283
- return this.recentWarnings
284
- .filter((entry) => entry.time >= since)
285
- .map((entry) => ({ tool: entry.tool, text: entry.text }));
286
- }
287
285
  /**
288
286
  * Get a short summary for tool operation
289
287
  */
@@ -383,6 +381,21 @@ export class ShellUIAdapter {
383
381
  return 'done';
384
382
  }
385
383
  }
384
+ /**
385
+ * Display compact single-line result
386
+ */
387
+ displayCompactResult(call, output, success) {
388
+ const op = {
389
+ id: call.id,
390
+ name: call.name,
391
+ status: success ? 'success' : 'error',
392
+ summary: this.extractResultSummary(call, output),
393
+ startedAt: Date.now(),
394
+ };
395
+ const badge = compactRenderer.formatToolBadge(op);
396
+ // Add newline after result for visual separation
397
+ this.display.stream(`${badge}\n\n`);
398
+ }
386
399
  /**
387
400
  * Determine if a tool should show initial ⏺ display
388
401
  * Returns true for tools with streaming/progressive output
@@ -817,19 +830,6 @@ export class ShellUIAdapter {
817
830
  setToolStatusCallback(callback) {
818
831
  this._toolStatusCallback = callback;
819
832
  }
820
- /**
821
- * Expose a snapshot of tool operations for external summary displays.
822
- * Returns both completed and in-flight operations, optionally filtered by start time.
823
- */
824
- getToolOperationsSince(sinceMs) {
825
- const cutoff = sinceMs ?? 0;
826
- const completed = this.completedOperations.map(op => ({ ...op }));
827
- const pending = Array.from(this.pendingOperations.values()).map(op => ({ ...op }));
828
- const all = [...completed, ...pending];
829
- return all
830
- .filter(op => op.startedAt >= cutoff)
831
- .sort((a, b) => (a.startedAt || 0) - (b.startedAt || 0));
832
- }
833
833
  /**
834
834
  * Parse file changes from Edit/Write/NotebookEdit tool output
835
835
  */
@@ -874,283 +874,29 @@ export class ShellUIAdapter {
874
874
  };
875
875
  }
876
876
  /**
877
- * Display tool result summary in a compact, badge-driven line with an optional preview block.
878
- * Routes through display module to work with scroll regions while keeping output minimal.
877
+ * Display tool result summary using Claude Code style.
878
+ * Format: ⎿ Summary text (ctrl+o to expand)
879
+ * Routes through display module to work with scroll regions
879
880
  */
880
881
  displayToolResultSummary(call, output, success) {
881
- const summaryLine = this.formatCompactToolLine(call, output, success);
882
- const preview = this.formatToolPreview(call, output, success);
883
- if (!summaryLine && !preview) {
884
- return;
885
- }
886
- const blocks = [];
887
- if (summaryLine)
888
- blocks.push(summaryLine);
889
- if (preview)
890
- blocks.push(preview);
891
- // Add newline for separation while keeping output compact
892
- this.display.stream(`\n${blocks.join('\n')}\n\n`);
893
- }
894
- /**
895
- * Display full tool output directly under the summary block.
896
- * Now uses the same compact preview system to keep verbose tools readable.
897
- */
898
- displayFullToolOutput(call, output, success) {
899
- const normalized = typeof output === 'string' ? output.trimEnd() : '';
900
- if (!normalized) {
901
- return;
902
- }
903
- // Use the same preview builder to keep verbose output compact
904
- const preview = this.formatToolPreview(call, normalized, success, true);
905
- const summary = this.formatCompactToolLine(call, normalized, success);
906
- const parts = [];
907
- if (summary)
908
- parts.push(summary);
909
- if (preview)
910
- parts.push(preview);
911
- if (parts.length) {
912
- this.display.stream(`\n${parts.join('\n')}\n\n`);
913
- }
914
- }
915
- /**
916
- * Format tool result summary in Claude Code style
917
- * Returns compact summary like "Found 4 files" or "Read 50 lines"
918
- */
919
- formatCompactToolLine(call, output, success) {
920
- const { main, detail } = this.buildToolSummaryParts(call, output, success);
921
- const summary = main || this.getToolSummary(call) || call.name;
922
- return compactRenderer.formatInlineResult(call.name, success ? 'success' : 'error', summary, detail);
923
- }
924
- /**
925
- * Build compact summary + detail parts for a tool result line.
926
- * Keeps the main text meaningful (path/query) and pushes counts into detail.
927
- */
928
- buildToolSummaryParts(call, output, success) {
929
882
  const args = call.arguments || {};
930
- const lineCount = this.countOutputLines(output);
931
- switch (call.name) {
932
- case 'Read':
933
- case 'read_file': {
934
- const path = this.extractPath(args, ['file_path', 'path']);
935
- return {
936
- main: path ? theme.info(this.truncatePath(path, 60)) : 'Read',
937
- detail: `${lineCount} line${lineCount === 1 ? '' : 's'}`,
938
- };
939
- }
940
- case 'Write':
941
- case 'write_file': {
942
- const path = this.extractPath(args, ['file_path', 'path']);
943
- const content = args['content'] || output;
944
- const lines = this.countOutputLines(content);
945
- return {
946
- main: path ? theme.info(this.truncatePath(path, 60)) : 'Write',
947
- detail: `${lines} line${lines === 1 ? '' : 's'}`,
948
- };
949
- }
950
- case 'Edit':
951
- case 'edit_file':
952
- case 'NotebookEdit': {
953
- const change = this.parseFileChange(call, output);
954
- const path = change?.path || this.extractPath(args, ['file_path', 'path', 'notebook_path']);
955
- const detailParts = [];
956
- if (change) {
957
- detailParts.push(`+${change.additions}/-${change.removals}`);
958
- }
959
- else if (lineCount > 0) {
960
- detailParts.push(`${lineCount} line${lineCount === 1 ? '' : 's'}`);
961
- }
962
- const action = call.name === 'NotebookEdit' ? 'Notebook' : 'Edit';
963
- return {
964
- main: path ? `${action} ${theme.info(this.truncatePath(path, 60))}` : action,
965
- detail: detailParts.join(' · ') || undefined,
966
- };
967
- }
968
- case 'Grep':
969
- case 'grep': {
970
- const pattern = args['pattern'] || '';
971
- const path = this.extractPath(args, ['path', 'directory']);
972
- const matches = output.trim() ? output.trim().split('\n').filter(l => l.trim()).length : 0;
973
- const detailParts = [`${matches} match${matches === 1 ? '' : 'es'}`];
974
- if (path && path !== '.') {
975
- detailParts.push(`in ${this.truncatePath(path, 40)}`);
976
- }
977
- return {
978
- main: pattern ? `"${pattern.length > 40 ? `${pattern.slice(0, 37)}...` : pattern}"` : 'Grep',
979
- detail: detailParts.join(' · '),
980
- };
981
- }
982
- case 'Glob':
983
- case 'glob': {
984
- const pattern = args['pattern'] || '*';
985
- const files = output.trim() ? output.trim().split('\n').filter(f => f.trim()).length : 0;
986
- const path = this.extractPath(args, ['path', 'directory']);
987
- const detailParts = [`${files} file${files === 1 ? '' : 's'}`];
988
- if (path && path !== '.') {
989
- detailParts.push(`in ${this.truncatePath(path, 40)}`);
990
- }
991
- return {
992
- main: pattern ? theme.info(pattern) : 'Glob',
993
- detail: detailParts.join(' · '),
994
- };
995
- }
996
- case 'Bash':
997
- case 'bash': {
998
- const command = args['command'] || '';
999
- const shortCmd = command.split('\n')[0]?.trim() || command;
1000
- const main = shortCmd
1001
- ? `${theme.ui.muted('$')} ${shortCmd.length > 70 ? `${shortCmd.slice(0, 67)}...` : shortCmd}`
1002
- : 'Shell';
1003
- const detail = lineCount === 0 ? 'no output' : `${lineCount} line${lineCount === 1 ? '' : 's'}`;
1004
- return { main, detail };
1005
- }
1006
- case 'WebFetch':
1007
- case 'web_fetch': {
1008
- const url = args['url'] || '';
1009
- let host = url;
1010
- try {
1011
- host = new URL(url).hostname;
1012
- }
1013
- catch {
1014
- // Keep original
1015
- }
1016
- const sizeStr = output.length > 1024 ? `${(output.length / 1024).toFixed(1)}KB` : `${output.length}B`;
1017
- return { main: host ? `Fetch ${theme.info(host)}` : 'Fetch', detail: sizeStr };
1018
- }
1019
- case 'WebSearch':
1020
- case 'web_search': {
1021
- const query = args['query'] || '';
1022
- const queryDisplay = query.length > 50 ? `${query.slice(0, 47)}...` : query;
1023
- const resultMatches = output.match(/^\d+\./gm);
1024
- const count = resultMatches ? resultMatches.length : this.countOutputLines(output);
1025
- return { main: queryDisplay ? `Search "${queryDisplay}"` : 'Search', detail: `${count} result${count === 1 ? '' : 's'}` };
1026
- }
1027
- case 'Task':
1028
- case 'task': {
1029
- const desc = args['description'] || '';
1030
- const trimmed = desc.length > 60 ? `${desc.slice(0, 57)}...` : desc;
1031
- return { main: trimmed || 'Task', detail: success ? 'done' : 'incomplete' };
1032
- }
1033
- case 'TodoWrite':
1034
- case 'todo_write': {
1035
- const todos = args['todos'];
1036
- const total = todos?.length || 0;
1037
- return { main: 'Todos', detail: total ? `${total} item${total === 1 ? '' : 's'}` : undefined };
1038
- }
1039
- case 'run_tests': {
1040
- const pattern = (args['pattern'] || args['filter']);
1041
- const counts = this.parseTestCounts(output);
1042
- const detailParts = [];
1043
- if (counts.passed > 0)
1044
- detailParts.push(`${counts.passed} pass`);
1045
- if (counts.failed > 0)
1046
- detailParts.push(`${counts.failed} fail`);
1047
- if (counts.skipped > 0)
1048
- detailParts.push(`${counts.skipped} skip`);
1049
- if (detailParts.length === 0 && lineCount > 0) {
1050
- detailParts.push(`${lineCount} line${lineCount === 1 ? '' : 's'}`);
1051
- }
1052
- return {
1053
- main: pattern ? `Tests "${pattern}"` : 'Tests',
1054
- detail: detailParts.join(' · ') || (success ? 'all passed' : 'failed'),
1055
- };
1056
- }
1057
- case 'run_build': {
1058
- const target = (args['target'] || args['script']);
1059
- const errors = (output.match(/error/gi) || []).length;
1060
- const detail = errors > 0
1061
- ? `${errors} error${errors === 1 ? '' : 's'}`
1062
- : `${lineCount} line${lineCount === 1 ? '' : 's'}`;
1063
- return { main: target ? `Build ${target}` : 'Build', detail };
1064
- }
1065
- default: {
1066
- const summary = this.extractResultSummary(call, output);
1067
- if (summary) {
1068
- return { main: summary };
1069
- }
1070
- const claudeSummary = this.formatClaudeCodeResultSummary(call.name, args, output, success);
1071
- if (claudeSummary) {
1072
- return { main: claudeSummary };
1073
- }
1074
- return { main: call.name, detail: lineCount ? `${lineCount} line${lineCount === 1 ? '' : 's'}` : undefined };
1075
- }
883
+ // Get compact summary for the result
884
+ const summary = this.formatClaudeCodeResultSummary(call.name, args, output, success);
885
+ if (summary) {
886
+ // Claude Code style: ⎿ Summary (indented under tool call)
887
+ const prefix = success
888
+ ? theme.success(icons.subaction)
889
+ : theme.error(icons.subaction);
890
+ // Add newline after result for visual separation
891
+ this.display.stream(` ${prefix} ${summary}\n\n`);
1076
892
  }
1077
893
  }
1078
894
  /**
1079
- * Render a compact preview of tool output (first N lines) with truncation hints.
895
+ * Format tool result summary in Claude Code style
896
+ * Returns compact summary like "Found 4 files (ctrl+o to expand)" or "Read 50 lines"
1080
897
  */
1081
- formatToolPreview(call, output, success, force = false) {
1082
- const previewLines = this.buildPreviewLines(call, output, success, force);
1083
- if (!previewLines.length) {
1084
- return null;
1085
- }
1086
- const gutter = theme.ui.muted('│');
1087
- return previewLines.map(line => ` ${gutter} ${line}`).join('\n');
1088
- }
1089
- buildPreviewLines(call, output, success, force) {
1090
- const normalized = (output || '').trim();
1091
- const allLines = normalized ? normalized.split('\n').filter(l => l.trim()) : [];
1092
- const limit = this.getPreviewLineLimit(call.name, success);
1093
- if (limit <= 0 && !force) {
1094
- return [];
1095
- }
1096
- const maxLines = limit > 0 ? limit : force ? Math.min(1, allLines.length) : 0;
1097
- if (maxLines === 0 || allLines.length === 0) {
1098
- return [];
1099
- }
1100
- const preview = allLines.slice(0, maxLines).map(line => this.truncatePreviewLine(line));
1101
- const remaining = allLines.length - maxLines;
1102
- if (remaining > 0) {
1103
- preview.push(theme.ui.muted(`… +${remaining} more`));
1104
- }
1105
- return preview;
1106
- }
1107
- getPreviewLineLimit(toolName, success) {
1108
- switch (toolName) {
1109
- case 'Read':
1110
- case 'read_file':
1111
- return success ? 0 : 1;
1112
- case 'Glob':
1113
- case 'glob':
1114
- return 3;
1115
- case 'Grep':
1116
- case 'grep':
1117
- return 4;
1118
- case 'Bash':
1119
- case 'bash':
1120
- return success ? 3 : 4;
1121
- case 'run_tests':
1122
- return success ? 2 : 4;
1123
- case 'Edit':
1124
- case 'edit_file':
1125
- case 'NotebookEdit':
1126
- return success ? 30 : 4; // Show more diff context for successful edits
1127
- default:
1128
- return success ? 2 : 3;
1129
- }
1130
- }
1131
- truncatePreviewLine(line, maxLen = 100) {
1132
- const trimmed = line.trim();
1133
- if (trimmed.length <= maxLen) {
1134
- return theme.dim(trimmed);
1135
- }
1136
- return theme.dim(`${trimmed.slice(0, maxLen - 3)}...`);
1137
- }
1138
- countOutputLines(output) {
1139
- if (!output || !output.trim())
1140
- return 0;
1141
- return output.trimEnd().split('\n').length;
1142
- }
1143
- parseTestCounts(output) {
1144
- const passMatch = output.match(/(\d+)\s*(?:passing|passed|✓)/i);
1145
- const failMatch = output.match(/(\d+)\s*(?:failing|failed|✗)/i);
1146
- const skipMatch = output.match(/(\d+)\s*(?:skipped|pending)/i);
1147
- return {
1148
- passed: passMatch ? parseInt(passMatch[1] || '0', 10) : 0,
1149
- failed: failMatch ? parseInt(failMatch[1] || '0', 10) : 0,
1150
- skipped: skipMatch ? parseInt(skipMatch[1] || '0', 10) : 0,
1151
- };
1152
- }
1153
898
  formatClaudeCodeResultSummary(toolName, args, output, success) {
899
+ const expandHint = theme.ui.muted('(ctrl+o to expand)');
1154
900
  if (!success) {
1155
901
  // Error case - show error message
1156
902
  const errorMsg = output.length > 60 ? `${output.slice(0, 57)}...` : output;
@@ -1192,9 +938,9 @@ export class ShellUIAdapter {
1192
938
  return theme.ui.muted('No matches found');
1193
939
  }
1194
940
  if (outputMode === 'content') {
1195
- return `Found ${theme.info(String(count))} lines`;
941
+ return `Found ${theme.info(String(count))} lines ${expandHint}`;
1196
942
  }
1197
- return `Found ${theme.info(String(count))} files`;
943
+ return `Found ${theme.info(String(count))} files ${expandHint}`;
1198
944
  }
1199
945
  case 'Glob':
1200
946
  case 'glob': {
@@ -1203,7 +949,7 @@ export class ShellUIAdapter {
1203
949
  if (count === 0) {
1204
950
  return theme.ui.muted('No files found');
1205
951
  }
1206
- return `Found ${theme.info(String(count))} file${count === 1 ? '' : 's'}`;
952
+ return `Found ${theme.info(String(count))} file${count === 1 ? '' : 's'} ${expandHint}`;
1207
953
  }
1208
954
  case 'Bash':
1209
955
  case 'bash': {
@@ -1211,7 +957,7 @@ export class ShellUIAdapter {
1211
957
  if (lines === 0) {
1212
958
  return theme.ui.muted('Completed (no output)');
1213
959
  }
1214
- return `Output: ${theme.info(String(lines))} lines`;
960
+ return `Output: ${theme.info(String(lines))} lines ${expandHint}`;
1215
961
  }
1216
962
  case 'WebFetch':
1217
963
  case 'web_fetch': {
@@ -1223,7 +969,7 @@ export class ShellUIAdapter {
1223
969
  case 'web_search': {
1224
970
  const resultMatches = output.match(/^\d+\./gm);
1225
971
  const count = resultMatches ? resultMatches.length : 'multiple';
1226
- return `Found ${theme.info(String(count))} results`;
972
+ return `Found ${theme.info(String(count))} results ${expandHint}`;
1227
973
  }
1228
974
  case 'Task':
1229
975
  case 'task': {
@@ -1257,7 +1003,7 @@ export class ShellUIAdapter {
1257
1003
  if (lines <= 3) {
1258
1004
  return 'Completed';
1259
1005
  }
1260
- return `${theme.info(String(lines))} lines`;
1006
+ return `${theme.info(String(lines))} lines ${expandHint}`;
1261
1007
  }
1262
1008
  }
1263
1009
  }
@@ -1266,10 +1012,11 @@ export class ShellUIAdapter {
1266
1012
  * Example output:
1267
1013
  * Read 100 lines
1268
1014
  * Found 4 lines
1269
- * +31 more tool uses
1015
+ * +31 more tool uses (ctrl+o to expand)
1270
1016
  */
1271
1017
  formatAgentResultSummary(output) {
1272
1018
  const lines = [];
1019
+ const expandHint = theme.ui.muted('(ctrl+o to expand)');
1273
1020
  // Parse output for tool use summaries
1274
1021
  // Look for patterns like "Read X lines", "Found X files", "Output: X lines", etc.
1275
1022
  const toolPatterns = [
@@ -1302,13 +1049,13 @@ export class ShellUIAdapter {
1302
1049
  lines.push(use);
1303
1050
  }
1304
1051
  if (remaining > 0) {
1305
- lines.push(`+${remaining} more tool uses`);
1052
+ lines.push(`+${remaining} more tool uses ${expandHint}`);
1306
1053
  }
1307
1054
  else if (lines.length === 0) {
1308
1055
  // Fallback if no tool uses found
1309
1056
  const outputLines = output.trim().split('\n').filter(l => l.trim()).length;
1310
1057
  if (outputLines > 0) {
1311
- return `${theme.info(String(outputLines))} lines`;
1058
+ return `${theme.info(String(outputLines))} lines ${expandHint}`;
1312
1059
  }
1313
1060
  return 'Completed';
1314
1061
  }