erosolar-cli 1.7.410 → 1.7.412

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 (202) 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/askUserCapability.d.ts.map +1 -1
  11. package/dist/capabilities/askUserCapability.js +64 -10
  12. package/dist/capabilities/askUserCapability.js.map +1 -1
  13. package/dist/capabilities/toolRegistry.d.ts +2 -0
  14. package/dist/capabilities/toolRegistry.d.ts.map +1 -1
  15. package/dist/capabilities/toolRegistry.js +40 -5
  16. package/dist/capabilities/toolRegistry.js.map +1 -1
  17. package/dist/contracts/agent-profiles.schema.json +5 -5
  18. package/dist/contracts/agent-schemas.json +6 -16
  19. package/dist/contracts/schemas/agent.schema.json +1 -5
  20. package/dist/contracts/schemas/tool-selection.schema.json +1 -7
  21. package/dist/contracts/tools.schema.json +80 -207
  22. package/dist/contracts/unified-schema.json +4 -5
  23. package/dist/contracts/v1/agent.d.ts +0 -3
  24. package/dist/contracts/v1/agent.d.ts.map +1 -1
  25. package/dist/contracts/v1/provider.d.ts +1 -2
  26. package/dist/contracts/v1/provider.d.ts.map +1 -1
  27. package/dist/contracts/v1/toolAccess.d.ts +1 -1
  28. package/dist/contracts/v1/toolAccess.d.ts.map +1 -1
  29. package/dist/core/agent.d.ts +1 -7
  30. package/dist/core/agent.d.ts.map +1 -1
  31. package/dist/core/agent.js +2 -131
  32. package/dist/core/agent.js.map +1 -1
  33. package/dist/core/alphaZeroEngine.d.ts +0 -8
  34. package/dist/core/alphaZeroEngine.d.ts.map +1 -1
  35. package/dist/core/alphaZeroEngine.js +35 -149
  36. package/dist/core/alphaZeroEngine.js.map +1 -1
  37. package/dist/core/alphaZeroOrchestrator.d.ts +0 -17
  38. package/dist/core/alphaZeroOrchestrator.d.ts.map +1 -1
  39. package/dist/core/alphaZeroOrchestrator.js +8 -95
  40. package/dist/core/alphaZeroOrchestrator.js.map +1 -1
  41. package/dist/core/claudeCodeFeatures.d.ts +2 -1
  42. package/dist/core/claudeCodeFeatures.d.ts.map +1 -1
  43. package/dist/core/claudeCodeFeatures.js +2 -1
  44. package/dist/core/claudeCodeFeatures.js.map +1 -1
  45. package/dist/core/cliTestHarness.d.ts +0 -5
  46. package/dist/core/cliTestHarness.d.ts.map +1 -1
  47. package/dist/core/cliTestHarness.js +3 -14
  48. package/dist/core/cliTestHarness.js.map +1 -1
  49. package/dist/core/contextManager.d.ts +0 -30
  50. package/dist/core/contextManager.d.ts.map +1 -1
  51. package/dist/core/contextManager.js +5 -87
  52. package/dist/core/contextManager.js.map +1 -1
  53. package/dist/core/contextWindow.d.ts +4 -4
  54. package/dist/core/contextWindow.js +9 -9
  55. package/dist/core/contextWindow.js.map +1 -1
  56. package/dist/core/modelDiscovery.js +3 -3
  57. package/dist/core/modelDiscovery.js.map +1 -1
  58. package/dist/core/preferences.d.ts +2 -3
  59. package/dist/core/preferences.d.ts.map +1 -1
  60. package/dist/core/preferences.js +11 -18
  61. package/dist/core/preferences.js.map +1 -1
  62. package/dist/core/secretStore.d.ts.map +1 -1
  63. package/dist/core/secretStore.js +31 -0
  64. package/dist/core/secretStore.js.map +1 -1
  65. package/dist/core/toolPreconditions.d.ts +1 -0
  66. package/dist/core/toolPreconditions.d.ts.map +1 -1
  67. package/dist/core/toolPreconditions.js +13 -64
  68. package/dist/core/toolPreconditions.js.map +1 -1
  69. package/dist/core/toolRuntime.d.ts.map +1 -1
  70. package/dist/core/toolRuntime.js +0 -17
  71. package/dist/core/toolRuntime.js.map +1 -1
  72. package/dist/core/types.d.ts +1 -1
  73. package/dist/core/types.d.ts.map +1 -1
  74. package/dist/headless/headlessApp.d.ts.map +1 -1
  75. package/dist/headless/headlessApp.js +6 -22
  76. package/dist/headless/headlessApp.js.map +1 -1
  77. package/dist/plugins/providers/google/index.js +3 -2
  78. package/dist/plugins/providers/google/index.js.map +1 -1
  79. package/dist/providers/openaiChatCompletionsProvider.d.ts.map +1 -1
  80. package/dist/providers/openaiChatCompletionsProvider.js +6 -60
  81. package/dist/providers/openaiChatCompletionsProvider.js.map +1 -1
  82. package/dist/runtime/agentController.d.ts.map +1 -1
  83. package/dist/runtime/agentController.js +6 -27
  84. package/dist/runtime/agentController.js.map +1 -1
  85. package/dist/shell/interactiveShell.d.ts +32 -98
  86. package/dist/shell/interactiveShell.d.ts.map +1 -1
  87. package/dist/shell/interactiveShell.js +733 -1645
  88. package/dist/shell/interactiveShell.js.map +1 -1
  89. package/dist/shell/shellApp.d.ts.map +1 -1
  90. package/dist/shell/shellApp.js +41 -15
  91. package/dist/shell/shellApp.js.map +1 -1
  92. package/dist/shell/systemPrompt.d.ts.map +1 -1
  93. package/dist/shell/systemPrompt.js +0 -1
  94. package/dist/shell/systemPrompt.js.map +1 -1
  95. package/dist/shell/terminalInput.d.ts +21 -85
  96. package/dist/shell/terminalInput.d.ts.map +1 -1
  97. package/dist/shell/terminalInput.js +62 -519
  98. package/dist/shell/terminalInput.js.map +1 -1
  99. package/dist/shell/terminalInputAdapter.d.ts +16 -37
  100. package/dist/shell/terminalInputAdapter.d.ts.map +1 -1
  101. package/dist/shell/terminalInputAdapter.js +22 -44
  102. package/dist/shell/terminalInputAdapter.js.map +1 -1
  103. package/dist/shell/updateManager.d.ts.map +1 -1
  104. package/dist/shell/updateManager.js +17 -1
  105. package/dist/shell/updateManager.js.map +1 -1
  106. package/dist/tools/buildTools.d.ts.map +1 -1
  107. package/dist/tools/buildTools.js +76 -19
  108. package/dist/tools/buildTools.js.map +1 -1
  109. package/dist/tools/editTools.js +1 -1
  110. package/dist/tools/editTools.js.map +1 -1
  111. package/dist/tools/enhancedCodeIntelligenceTools.js +2 -1
  112. package/dist/tools/enhancedCodeIntelligenceTools.js.map +1 -1
  113. package/dist/tools/fileTools.js +0 -3
  114. package/dist/tools/fileTools.js.map +1 -1
  115. package/dist/tools/frontendTestingTools.js +1 -1
  116. package/dist/tools/frontendTestingTools.js.map +1 -1
  117. package/dist/tools/interactionTools.d.ts.map +1 -1
  118. package/dist/tools/interactionTools.js +82 -15
  119. package/dist/tools/interactionTools.js.map +1 -1
  120. package/dist/tools/learnTools.d.ts +0 -2
  121. package/dist/tools/learnTools.d.ts.map +1 -1
  122. package/dist/tools/learnTools.js +81 -29
  123. package/dist/tools/learnTools.js.map +1 -1
  124. package/dist/tools/localExplore.d.ts.map +1 -1
  125. package/dist/tools/localExplore.js +1 -0
  126. package/dist/tools/localExplore.js.map +1 -1
  127. package/dist/tools/notebookEditTools.js.map +1 -1
  128. package/dist/tools/repoChecksTools.js +3 -4
  129. package/dist/tools/repoChecksTools.js.map +1 -1
  130. package/dist/tools/searchTools.js +0 -4
  131. package/dist/tools/searchTools.js.map +1 -1
  132. package/dist/tools/softwareEngineeringTools.d.ts.map +1 -1
  133. package/dist/tools/softwareEngineeringTools.js +0 -1
  134. package/dist/tools/softwareEngineeringTools.js.map +1 -1
  135. package/dist/tools/webTools.d.ts.map +1 -1
  136. package/dist/tools/webTools.js.map +1 -1
  137. package/dist/ui/ShellUIAdapter.d.ts +13 -52
  138. package/dist/ui/ShellUIAdapter.d.ts.map +1 -1
  139. package/dist/ui/ShellUIAdapter.js +72 -373
  140. package/dist/ui/ShellUIAdapter.js.map +1 -1
  141. package/dist/ui/display.d.ts +38 -19
  142. package/dist/ui/display.d.ts.map +1 -1
  143. package/dist/ui/display.js +310 -96
  144. package/dist/ui/display.js.map +1 -1
  145. package/dist/ui/orchestration/UIUpdateCoordinator.d.ts.map +1 -1
  146. package/dist/ui/orchestration/UIUpdateCoordinator.js +3 -5
  147. package/dist/ui/orchestration/UIUpdateCoordinator.js.map +1 -1
  148. package/dist/ui/shortcutsHelp.d.ts +1 -1
  149. package/dist/ui/shortcutsHelp.d.ts.map +1 -1
  150. package/dist/ui/shortcutsHelp.js +6 -11
  151. package/dist/ui/shortcutsHelp.js.map +1 -1
  152. package/dist/ui/streamingFormatter.d.ts +17 -0
  153. package/dist/ui/streamingFormatter.d.ts.map +1 -0
  154. package/dist/ui/streamingFormatter.js +71 -0
  155. package/dist/ui/streamingFormatter.js.map +1 -0
  156. package/dist/ui/theme.d.ts +100 -100
  157. package/dist/ui/theme.d.ts.map +1 -1
  158. package/dist/ui/theme.js.map +1 -1
  159. package/dist/ui/toolDisplay.d.ts.map +1 -1
  160. package/dist/ui/toolDisplay.js +1 -7
  161. package/dist/ui/toolDisplay.js.map +1 -1
  162. package/dist/ui/unified/index.d.ts +3 -2
  163. package/dist/ui/unified/index.d.ts.map +1 -1
  164. package/dist/ui/unified/index.js +1 -0
  165. package/dist/ui/unified/index.js.map +1 -1
  166. package/dist/ui/unified/layout.d.ts +0 -14
  167. package/dist/ui/unified/layout.d.ts.map +1 -1
  168. package/dist/ui/unified/layout.js +1 -67
  169. package/dist/ui/unified/layout.js.map +1 -1
  170. package/package.json +24 -37
  171. package/dist/core/alphaZeroConfig.d.ts +0 -11
  172. package/dist/core/alphaZeroConfig.d.ts.map +0 -1
  173. package/dist/core/alphaZeroConfig.js +0 -59
  174. package/dist/core/alphaZeroConfig.js.map +0 -1
  175. package/dist/core/alphaZeroEnhanced.d.ts +0 -125
  176. package/dist/core/alphaZeroEnhanced.d.ts.map +0 -1
  177. package/dist/core/alphaZeroEnhanced.js +0 -386
  178. package/dist/core/alphaZeroEnhanced.js.map +0 -1
  179. package/dist/core/autonomousVerification.d.ts +0 -103
  180. package/dist/core/autonomousVerification.d.ts.map +0 -1
  181. package/dist/core/autonomousVerification.js +0 -583
  182. package/dist/core/autonomousVerification.js.map +0 -1
  183. package/dist/core/offsecAlphaZeroEnhanced.d.ts +0 -98
  184. package/dist/core/offsecAlphaZeroEnhanced.d.ts.map +0 -1
  185. package/dist/core/offsecAlphaZeroEnhanced.js +0 -441
  186. package/dist/core/offsecAlphaZeroEnhanced.js.map +0 -1
  187. package/dist/core/parallelAgentOrchestrator.d.ts +0 -171
  188. package/dist/core/parallelAgentOrchestrator.d.ts.map +0 -1
  189. package/dist/core/parallelAgentOrchestrator.js +0 -459
  190. package/dist/core/parallelAgentOrchestrator.js.map +0 -1
  191. package/dist/index.d.ts +0 -5
  192. package/dist/index.d.ts.map +0 -1
  193. package/dist/index.js +0 -3
  194. package/dist/index.js.map +0 -1
  195. package/dist/tools/detectCommands.d.ts +0 -8
  196. package/dist/tools/detectCommands.d.ts.map +0 -1
  197. package/dist/tools/detectCommands.js +0 -183
  198. package/dist/tools/detectCommands.js.map +0 -1
  199. package/dist/ui/assistantBlockRenderer.d.ts +0 -30
  200. package/dist/ui/assistantBlockRenderer.d.ts.map +0 -1
  201. package/dist/ui/assistantBlockRenderer.js +0 -121
  202. package/dist/ui/assistantBlockRenderer.js.map +0 -1
@@ -4,7 +4,7 @@
4
4
  *
5
5
  * Advanced UI Features:
6
6
  * - Compact same-line tool displays
7
- * - Streaming progress updates (no redraw)
7
+ * - In-place progress updates
8
8
  * - Grouped operation summaries
9
9
  * - Dynamic status badges
10
10
  */
@@ -14,6 +14,7 @@ import { getTerminalColumns } from './layout.js';
14
14
  import { theme, icons } from './theme.js';
15
15
  import { UIUpdateCoordinator } from './orchestration/UIUpdateCoordinator.js';
16
16
  import { compactRenderer } from './compactRenderer.js';
17
+ import { inPlaceUpdater } from './inPlaceUpdater.js';
17
18
  export class ShellUIAdapter {
18
19
  uiController;
19
20
  display;
@@ -30,8 +31,6 @@ export class ShellUIAdapter {
30
31
  maxCompletedOps = 8;
31
32
  compactDisplayMode = true; // Enable compact same-line displays
32
33
  toolWarnings = new Map();
33
- recentWarnings = [];
34
- toolProgressState = new Map();
35
34
  constructor(writeStream, display, config = {}, updateCoordinator) {
36
35
  this.display = display;
37
36
  this.config = {
@@ -106,7 +105,7 @@ export class ShellUIAdapter {
106
105
  // Update status bar to show active tool
107
106
  if (this._toolStatusCallback) {
108
107
  const actionDesc = this.getToolActionDescription(call);
109
- this._toolStatusCallback({ text: actionDesc, stage: 'start' });
108
+ this._toolStatusCallback(actionDesc);
110
109
  }
111
110
  this.uiController.onToolStart(call);
112
111
  },
@@ -121,34 +120,23 @@ export class ShellUIAdapter {
121
120
  total: progress.total ?? progress.current,
122
121
  message: progress.message,
123
122
  });
124
- // Update status bar with progress
123
+ // Update status bar with progress - use in-place update for supported terminals
125
124
  if (this._toolStatusCallback) {
126
125
  const description = this.getToolActionDescription(call, progress);
127
126
  if (description) {
128
- this._toolStatusCallback({ text: description, stage: 'progress' });
127
+ this._toolStatusCallback(description);
129
128
  }
130
129
  }
131
- // Stream progress updates instead of in-place redraws
132
- if (progress.total && progress.total > 1) {
133
- const progressLine = this.formatStreamingProgress(call, progress);
134
- this.streamProgressUpdate(call.id, progressLine);
135
- }
136
- else if (progress.message) {
137
- this.streamProgressUpdate(call.id, `${theme.info(icons.action)} ${theme.tool(call.name)} ${progress.message}`);
130
+ // Show progress bar for file operations and long-running tools
131
+ if (inPlaceUpdater.hasTTY && progress.total && progress.total > 1) {
132
+ inPlaceUpdater.showToolProgress(call.name, progress.message || '', { current: progress.current, total: progress.total });
138
133
  }
139
134
  },
140
135
  onToolWarning: (call, warning) => {
141
- const toolName = theme.tool(call.name);
142
136
  const warningText = this.formatToolWarning(warning);
143
- const line = `${theme.warning(icons.warning)} ${toolName} ${theme.ui.muted('preflight')} ${warningText}`;
144
- this.recordToolWarning(call.id, call.name, warningText);
145
- // Use display.stream() to work with scroll regions
146
- this.display.stream(`\n${line}\n`);
137
+ this.recordToolWarning(call.id, warningText);
147
138
  if (this._toolStatusCallback) {
148
- this._toolStatusCallback({
149
- text: `Warning: ${this.getToolActionDescription(call)}`,
150
- stage: 'progress',
151
- });
139
+ this._toolStatusCallback(`Warning: ${this.getToolActionDescription(call)}`);
152
140
  }
153
141
  },
154
142
  onToolResult: (call, output) => {
@@ -172,21 +160,21 @@ export class ShellUIAdapter {
172
160
  this.fileChangeCallback(fileChange.path, fileChange.type, fileChange.additions, fileChange.removals);
173
161
  }
174
162
  }
175
- // Render concise tool result + preview instead of verbose blocks
176
- this.displayToolResultSummary(call, output, true);
163
+ // Use compact display for quick single-result tools
164
+ if (this.compactDisplayMode && this.isCompactTool(call.name)) {
165
+ this.displayCompactResult(call, output, true);
166
+ }
167
+ else {
168
+ // Claude Code style: Display tool result with ⎿ prefix
169
+ this.displayToolResultSummary(call, output, true);
170
+ }
177
171
  // Surface any captured preflight warnings in a structured block
178
172
  this.flushToolWarnings(call.id, call.name);
179
173
  // Clear status bar after showing result
180
174
  if (this._toolStatusCallback) {
181
- const completed = this.getToolActionDescription(call);
182
- this._toolStatusCallback({
183
- text: completed ? `Completed ${completed}` : 'Tool complete',
184
- stage: 'result',
185
- });
186
- this._toolStatusCallback({ text: null, stage: 'complete' });
175
+ this._toolStatusCallback(null);
187
176
  }
188
177
  this.uiController.onToolComplete(call.id, output);
189
- this.toolProgressState.delete(call.id);
190
178
  },
191
179
  onToolError: (call, message) => {
192
180
  // Complete the operation tracking with error
@@ -198,20 +186,20 @@ export class ShellUIAdapter {
198
186
  this.pendingOperations.delete(call.id);
199
187
  this.completedOperations.push(op);
200
188
  }
201
- // Render concise error summary + preview instead of verbose blocks
202
- this.displayToolResultSummary(call, message, false);
189
+ // Use compact display for errors too
190
+ if (this.compactDisplayMode && this.isCompactTool(call.name)) {
191
+ this.displayCompactResult(call, message, false);
192
+ }
193
+ else {
194
+ // Claude Code style: Display error with ⎿ prefix (error color)
195
+ this.displayToolResultSummary(call, message, false);
196
+ }
203
197
  this.flushToolWarnings(call.id, call.name);
204
198
  // Clear status bar after showing error
205
199
  if (this._toolStatusCallback) {
206
- const failed = this.getToolActionDescription(call);
207
- this._toolStatusCallback({
208
- text: failed ? `Failed ${failed}` : 'Tool failed',
209
- stage: 'error',
210
- });
211
- this._toolStatusCallback({ text: null, stage: 'complete' });
200
+ this._toolStatusCallback(null);
212
201
  }
213
202
  this.uiController.onToolError(call.id, { message });
214
- this.toolProgressState.delete(call.id);
215
203
  },
216
204
  onCacheHit: (call) => {
217
205
  // Track as cached operation
@@ -230,21 +218,24 @@ export class ShellUIAdapter {
230
218
  const badge = compactRenderer.formatToolBadge(operation);
231
219
  this.display.stream(`${badge}\n`);
232
220
  }
233
- if (this._toolStatusCallback) {
234
- const cached = this.getToolActionDescription(call);
235
- this._toolStatusCallback({
236
- text: cached ? `Cached ${cached}` : 'Tool cache hit',
237
- stage: 'result',
238
- });
239
- this._toolStatusCallback({ text: null, stage: 'complete' });
240
- }
241
221
  this.flushToolWarnings(call.id, call.name);
242
222
  this.uiController.onToolStart(call);
243
223
  this.uiController.onToolComplete(call.id, 'cache-hit');
244
- this.toolProgressState.delete(call.id);
245
224
  },
246
225
  };
247
226
  }
227
+ /**
228
+ * Check if a tool should use compact (single-line) display
229
+ */
230
+ isCompactTool(toolName) {
231
+ const compactTools = new Set([
232
+ 'Read', 'read_file',
233
+ 'Glob', 'glob',
234
+ 'TodoWrite', 'todo_write',
235
+ 'WebFetch', 'web_fetch',
236
+ ]);
237
+ return compactTools.has(toolName);
238
+ }
248
239
  /**
249
240
  * Normalize preflight warnings for consistent display.
250
241
  */
@@ -259,14 +250,11 @@ export class ShellUIAdapter {
259
250
  /**
260
251
  * Track warnings for a tool call so we can show them after the result too.
261
252
  */
262
- recordToolWarning(callId, toolName, warningText) {
253
+ recordToolWarning(callId, warningText) {
263
254
  const existing = this.toolWarnings.get(callId) ?? [];
264
- existing.push(warningText);
265
- this.toolWarnings.set(callId, existing);
266
- this.recentWarnings.push({ tool: toolName, text: warningText, time: Date.now() });
267
- // Keep recent warnings list compact
268
- if (this.recentWarnings.length > 20) {
269
- this.recentWarnings.shift();
255
+ if (!existing.includes(warningText)) {
256
+ existing.push(warningText);
257
+ this.toolWarnings.set(callId, existing);
270
258
  }
271
259
  }
272
260
  /**
@@ -283,42 +271,6 @@ export class ShellUIAdapter {
283
271
  const body = warnings.map(text => ` ${bullet} ${text}`).join('\n');
284
272
  this.display.stream(`\n${header}\n${body}\n`);
285
273
  }
286
- /**
287
- * Render progress updates as streaming lines rather than in-place redraws.
288
- */
289
- formatStreamingProgress(call, progress) {
290
- const pct = progress.total ? Math.round((progress.current / progress.total) * 100) : null;
291
- const parts = [];
292
- parts.push(theme.info(icons.action));
293
- parts.push(theme.tool(call.name));
294
- if (pct !== null && Number.isFinite(pct)) {
295
- parts.push(theme.progress.percentage(`${pct}%`));
296
- parts.push(theme.ui.muted(`(${progress.current}/${progress.total})`));
297
- }
298
- if (progress.message) {
299
- parts.push(progress.message);
300
- }
301
- return parts.join(' ');
302
- }
303
- /**
304
- * Only stream distinct progress updates to avoid noisy duplicates.
305
- */
306
- streamProgressUpdate(callId, line) {
307
- const previous = this.toolProgressState.get(callId);
308
- if (previous === line) {
309
- return;
310
- }
311
- this.toolProgressState.set(callId, line);
312
- this.display.stream(`${line}\n`);
313
- }
314
- /**
315
- * Return preflight warnings captured since a timestamp.
316
- */
317
- getRecentWarnings(since) {
318
- return this.recentWarnings
319
- .filter((entry) => entry.time >= since)
320
- .map((entry) => ({ tool: entry.tool, text: entry.text }));
321
- }
322
274
  /**
323
275
  * Get a short summary for tool operation
324
276
  */
@@ -418,6 +370,21 @@ export class ShellUIAdapter {
418
370
  return 'done';
419
371
  }
420
372
  }
373
+ /**
374
+ * Display compact single-line result
375
+ */
376
+ displayCompactResult(call, output, success) {
377
+ const op = {
378
+ id: call.id,
379
+ name: call.name,
380
+ status: success ? 'success' : 'error',
381
+ summary: this.extractResultSummary(call, output),
382
+ startedAt: Date.now(),
383
+ };
384
+ const badge = compactRenderer.formatToolBadge(op);
385
+ // Add newline after result for visual separation
386
+ this.display.stream(`${badge}\n\n`);
387
+ }
421
388
  /**
422
389
  * Determine if a tool should show initial ⏺ display
423
390
  * Returns true for tools with streaming/progressive output
@@ -852,19 +819,6 @@ export class ShellUIAdapter {
852
819
  setToolStatusCallback(callback) {
853
820
  this._toolStatusCallback = callback;
854
821
  }
855
- /**
856
- * Expose a snapshot of tool operations for external summary displays.
857
- * Returns both completed and in-flight operations, optionally filtered by start time.
858
- */
859
- getToolOperationsSince(sinceMs) {
860
- const cutoff = sinceMs ?? 0;
861
- const completed = this.completedOperations.map(op => ({ ...op }));
862
- const pending = Array.from(this.pendingOperations.values()).map(op => ({ ...op }));
863
- const all = [...completed, ...pending];
864
- return all
865
- .filter(op => op.startedAt >= cutoff)
866
- .sort((a, b) => (a.startedAt || 0) - (b.startedAt || 0));
867
- }
868
822
  /**
869
823
  * Parse file changes from Edit/Write/NotebookEdit tool output
870
824
  */
@@ -909,282 +863,27 @@ export class ShellUIAdapter {
909
863
  };
910
864
  }
911
865
  /**
912
- * Display tool result summary in a compact, badge-driven line with an optional preview block.
913
- * Routes through display module to work with scroll regions while keeping output minimal.
866
+ * Display tool result summary using Claude Code style.
867
+ * Format: ⎿ Summary text
868
+ * Routes through display module to work with scroll regions
914
869
  */
915
870
  displayToolResultSummary(call, output, success) {
916
- const summaryLine = this.formatCompactToolLine(call, output, success);
917
- const preview = this.formatToolPreview(call, output, success);
918
- if (!summaryLine && !preview) {
919
- return;
920
- }
921
- const blocks = [];
922
- if (summaryLine)
923
- blocks.push(summaryLine);
924
- if (preview)
925
- blocks.push(preview);
926
- // Add newline for separation while keeping output compact
927
- this.display.stream(`\n${blocks.join('\n')}\n\n`);
928
- }
929
- /**
930
- * Display full tool output directly under the summary block.
931
- * Now uses the same compact preview system to keep verbose tools readable.
932
- */
933
- displayFullToolOutput(call, output, success) {
934
- const normalized = typeof output === 'string' ? output.trimEnd() : '';
935
- if (!normalized) {
936
- return;
937
- }
938
- // Use the same preview builder to keep verbose output compact
939
- const preview = this.formatToolPreview(call, normalized, success, true);
940
- const summary = this.formatCompactToolLine(call, normalized, success);
941
- const parts = [];
942
- if (summary)
943
- parts.push(summary);
944
- if (preview)
945
- parts.push(preview);
946
- if (parts.length) {
947
- this.display.stream(`\n${parts.join('\n')}\n\n`);
871
+ const args = call.arguments || {};
872
+ // Get compact summary for the result
873
+ const summary = this.formatClaudeCodeResultSummary(call.name, args, output, success);
874
+ if (summary) {
875
+ // Claude Code style: ⎿ Summary (indented under tool call)
876
+ const prefix = success
877
+ ? theme.success(icons.subaction)
878
+ : theme.error(icons.subaction);
879
+ // Add newline after result for visual separation
880
+ this.display.stream(` ${prefix} ${summary}\n\n`);
948
881
  }
949
882
  }
950
883
  /**
951
884
  * Format tool result summary in Claude Code style
952
885
  * Returns compact summary like "Found 4 files" or "Read 50 lines"
953
886
  */
954
- formatCompactToolLine(call, output, success) {
955
- const { main, detail } = this.buildToolSummaryParts(call, output, success);
956
- const summary = main || this.getToolSummary(call) || call.name;
957
- return compactRenderer.formatInlineResult(call.name, success ? 'success' : 'error', summary, detail);
958
- }
959
- /**
960
- * Build compact summary + detail parts for a tool result line.
961
- * Keeps the main text meaningful (path/query) and pushes counts into detail.
962
- */
963
- buildToolSummaryParts(call, output, success) {
964
- const args = call.arguments || {};
965
- const lineCount = this.countOutputLines(output);
966
- switch (call.name) {
967
- case 'Read':
968
- case 'read_file': {
969
- const path = this.extractPath(args, ['file_path', 'path']);
970
- return {
971
- main: path ? theme.info(this.truncatePath(path, 60)) : 'Read',
972
- detail: `${lineCount} line${lineCount === 1 ? '' : 's'}`,
973
- };
974
- }
975
- case 'Write':
976
- case 'write_file': {
977
- const path = this.extractPath(args, ['file_path', 'path']);
978
- const content = args['content'] || output;
979
- const lines = this.countOutputLines(content);
980
- return {
981
- main: path ? theme.info(this.truncatePath(path, 60)) : 'Write',
982
- detail: `${lines} line${lines === 1 ? '' : 's'}`,
983
- };
984
- }
985
- case 'Edit':
986
- case 'edit_file':
987
- case 'NotebookEdit': {
988
- const change = this.parseFileChange(call, output);
989
- const path = change?.path || this.extractPath(args, ['file_path', 'path', 'notebook_path']);
990
- const detailParts = [];
991
- if (change) {
992
- detailParts.push(`+${change.additions}/-${change.removals}`);
993
- }
994
- else if (lineCount > 0) {
995
- detailParts.push(`${lineCount} line${lineCount === 1 ? '' : 's'}`);
996
- }
997
- const action = call.name === 'NotebookEdit' ? 'Notebook' : 'Edit';
998
- return {
999
- main: path ? `${action} ${theme.info(this.truncatePath(path, 60))}` : action,
1000
- detail: detailParts.join(' · ') || undefined,
1001
- };
1002
- }
1003
- case 'Grep':
1004
- case 'grep': {
1005
- const pattern = args['pattern'] || '';
1006
- const path = this.extractPath(args, ['path', 'directory']);
1007
- const matches = output.trim() ? output.trim().split('\n').filter(l => l.trim()).length : 0;
1008
- const detailParts = [`${matches} match${matches === 1 ? '' : 'es'}`];
1009
- if (path && path !== '.') {
1010
- detailParts.push(`in ${this.truncatePath(path, 40)}`);
1011
- }
1012
- return {
1013
- main: pattern ? `"${pattern.length > 40 ? `${pattern.slice(0, 37)}...` : pattern}"` : 'Grep',
1014
- detail: detailParts.join(' · '),
1015
- };
1016
- }
1017
- case 'Glob':
1018
- case 'glob': {
1019
- const pattern = args['pattern'] || '*';
1020
- const files = output.trim() ? output.trim().split('\n').filter(f => f.trim()).length : 0;
1021
- const path = this.extractPath(args, ['path', 'directory']);
1022
- const detailParts = [`${files} file${files === 1 ? '' : 's'}`];
1023
- if (path && path !== '.') {
1024
- detailParts.push(`in ${this.truncatePath(path, 40)}`);
1025
- }
1026
- return {
1027
- main: pattern ? theme.info(pattern) : 'Glob',
1028
- detail: detailParts.join(' · '),
1029
- };
1030
- }
1031
- case 'Bash':
1032
- case 'bash': {
1033
- const command = args['command'] || '';
1034
- const shortCmd = command.split('\n')[0]?.trim() || command;
1035
- const main = shortCmd
1036
- ? `${theme.ui.muted('$')} ${shortCmd.length > 70 ? `${shortCmd.slice(0, 67)}...` : shortCmd}`
1037
- : 'Shell';
1038
- const detail = lineCount === 0 ? 'no output' : `${lineCount} line${lineCount === 1 ? '' : 's'}`;
1039
- return { main, detail };
1040
- }
1041
- case 'WebFetch':
1042
- case 'web_fetch': {
1043
- const url = args['url'] || '';
1044
- let host = url;
1045
- try {
1046
- host = new URL(url).hostname;
1047
- }
1048
- catch {
1049
- // Keep original
1050
- }
1051
- const sizeStr = output.length > 1024 ? `${(output.length / 1024).toFixed(1)}KB` : `${output.length}B`;
1052
- return { main: host ? `Fetch ${theme.info(host)}` : 'Fetch', detail: sizeStr };
1053
- }
1054
- case 'WebSearch':
1055
- case 'web_search': {
1056
- const query = args['query'] || '';
1057
- const queryDisplay = query.length > 50 ? `${query.slice(0, 47)}...` : query;
1058
- const resultMatches = output.match(/^\d+\./gm);
1059
- const count = resultMatches ? resultMatches.length : this.countOutputLines(output);
1060
- return { main: queryDisplay ? `Search "${queryDisplay}"` : 'Search', detail: `${count} result${count === 1 ? '' : 's'}` };
1061
- }
1062
- case 'Task':
1063
- case 'task': {
1064
- const desc = args['description'] || '';
1065
- const trimmed = desc.length > 60 ? `${desc.slice(0, 57)}...` : desc;
1066
- return { main: trimmed || 'Task', detail: success ? 'done' : 'incomplete' };
1067
- }
1068
- case 'TodoWrite':
1069
- case 'todo_write': {
1070
- const todos = args['todos'];
1071
- const total = todos?.length || 0;
1072
- return { main: 'Todos', detail: total ? `${total} item${total === 1 ? '' : 's'}` : undefined };
1073
- }
1074
- case 'run_tests': {
1075
- const pattern = (args['pattern'] || args['filter']);
1076
- const counts = this.parseTestCounts(output);
1077
- const detailParts = [];
1078
- if (counts.passed > 0)
1079
- detailParts.push(`${counts.passed} pass`);
1080
- if (counts.failed > 0)
1081
- detailParts.push(`${counts.failed} fail`);
1082
- if (counts.skipped > 0)
1083
- detailParts.push(`${counts.skipped} skip`);
1084
- if (detailParts.length === 0 && lineCount > 0) {
1085
- detailParts.push(`${lineCount} line${lineCount === 1 ? '' : 's'}`);
1086
- }
1087
- return {
1088
- main: pattern ? `Tests "${pattern}"` : 'Tests',
1089
- detail: detailParts.join(' · ') || (success ? 'all passed' : 'failed'),
1090
- };
1091
- }
1092
- case 'run_build': {
1093
- const target = (args['target'] || args['script']);
1094
- const errors = (output.match(/error/gi) || []).length;
1095
- const detail = errors > 0
1096
- ? `${errors} error${errors === 1 ? '' : 's'}`
1097
- : `${lineCount} line${lineCount === 1 ? '' : 's'}`;
1098
- return { main: target ? `Build ${target}` : 'Build', detail };
1099
- }
1100
- default: {
1101
- const summary = this.extractResultSummary(call, output);
1102
- if (summary) {
1103
- return { main: summary };
1104
- }
1105
- const claudeSummary = this.formatClaudeCodeResultSummary(call.name, args, output, success);
1106
- if (claudeSummary) {
1107
- return { main: claudeSummary };
1108
- }
1109
- return { main: call.name, detail: lineCount ? `${lineCount} line${lineCount === 1 ? '' : 's'}` : undefined };
1110
- }
1111
- }
1112
- }
1113
- /**
1114
- * Render a compact preview of tool output (first N lines) with truncation hints.
1115
- */
1116
- formatToolPreview(call, output, success, force = false) {
1117
- const previewLines = this.buildPreviewLines(call, output, success, force);
1118
- if (!previewLines.length) {
1119
- return null;
1120
- }
1121
- const gutter = theme.ui.muted('│');
1122
- return previewLines.map(line => ` ${gutter} ${line}`).join('\n');
1123
- }
1124
- buildPreviewLines(call, output, success, force) {
1125
- const normalized = (output || '').trim();
1126
- const allLines = normalized ? normalized.split('\n').filter(l => l.trim()) : [];
1127
- const limit = this.getPreviewLineLimit(call.name, success);
1128
- if (limit <= 0 && !force) {
1129
- return [];
1130
- }
1131
- const maxLines = limit > 0 ? limit : force ? Math.min(1, allLines.length) : 0;
1132
- if (maxLines === 0 || allLines.length === 0) {
1133
- return [];
1134
- }
1135
- const preview = allLines.slice(0, maxLines).map(line => this.truncatePreviewLine(line));
1136
- const remaining = allLines.length - maxLines;
1137
- if (remaining > 0) {
1138
- preview.push(theme.ui.muted(`… +${remaining} more`));
1139
- }
1140
- return preview;
1141
- }
1142
- getPreviewLineLimit(toolName, success) {
1143
- switch (toolName) {
1144
- case 'Read':
1145
- case 'read_file':
1146
- return success ? 0 : 1;
1147
- case 'Glob':
1148
- case 'glob':
1149
- return 3;
1150
- case 'Grep':
1151
- case 'grep':
1152
- return 4;
1153
- case 'Bash':
1154
- case 'bash':
1155
- return success ? 3 : 4;
1156
- case 'run_tests':
1157
- return success ? 2 : 4;
1158
- case 'Edit':
1159
- case 'edit_file':
1160
- case 'NotebookEdit':
1161
- return success ? 30 : 4; // Show more diff context for successful edits
1162
- default:
1163
- return success ? 2 : 3;
1164
- }
1165
- }
1166
- truncatePreviewLine(line, maxLen = 100) {
1167
- const trimmed = line.trim();
1168
- if (trimmed.length <= maxLen) {
1169
- return theme.dim(trimmed);
1170
- }
1171
- return theme.dim(`${trimmed.slice(0, maxLen - 3)}...`);
1172
- }
1173
- countOutputLines(output) {
1174
- if (!output || !output.trim())
1175
- return 0;
1176
- return output.trimEnd().split('\n').length;
1177
- }
1178
- parseTestCounts(output) {
1179
- const passMatch = output.match(/(\d+)\s*(?:passing|passed|✓)/i);
1180
- const failMatch = output.match(/(\d+)\s*(?:failing|failed|✗)/i);
1181
- const skipMatch = output.match(/(\d+)\s*(?:skipped|pending)/i);
1182
- return {
1183
- passed: passMatch ? parseInt(passMatch[1] || '0', 10) : 0,
1184
- failed: failMatch ? parseInt(failMatch[1] || '0', 10) : 0,
1185
- skipped: skipMatch ? parseInt(skipMatch[1] || '0', 10) : 0,
1186
- };
1187
- }
1188
887
  formatClaudeCodeResultSummary(toolName, args, output, success) {
1189
888
  if (!success) {
1190
889
  // Error case - show error message