aegiscode 3.1.10 → 3.4.2

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 (209) hide show
  1. package/bin/aegis.js +165 -0
  2. package/package.json +18 -86
  3. package/LICENSE +0 -21
  4. package/README.md +0 -394
  5. package/dist/main.js +0 -2171
  6. package/gui/run-gui.cjs +0 -13
  7. package/src/agent/Agent.ts +0 -903
  8. package/src/agent/SimpleAgent.ts +0 -48
  9. package/src/agent/index.ts +0 -54
  10. package/src/agent/orchestrator/AppBuilder.ts +0 -443
  11. package/src/agent/orchestrator/CouncilAgent.ts +0 -310
  12. package/src/agent/orchestrator/DiscussionRoom.ts +0 -462
  13. package/src/agent/orchestrator/OrchestratorAgent.ts +0 -637
  14. package/src/agent/orchestrator/index.ts +0 -38
  15. package/src/agent/orchestrator/utils.ts +0 -397
  16. package/src/agent/pricing.ts +0 -115
  17. package/src/agent/router.ts +0 -74
  18. package/src/agent/routerStats.ts +0 -121
  19. package/src/agent/types.ts +0 -318
  20. package/src/auth/login.ts +0 -383
  21. package/src/cli/config.ts +0 -189
  22. package/src/cli/index.ts +0 -17
  23. package/src/cli/middleware.ts +0 -119
  24. package/src/cli/types.ts +0 -75
  25. package/src/config/ConfigManager.ts +0 -587
  26. package/src/config/index.ts +0 -7
  27. package/src/config/types.ts +0 -584
  28. package/src/context/CompactionService.ts +0 -300
  29. package/src/context/ContextManager.ts +0 -450
  30. package/src/context/FileAnalyzer.ts +0 -267
  31. package/src/context/TokenCounter.ts +0 -265
  32. package/src/context/index.ts +0 -27
  33. package/src/context/storage/CacheStore.ts +0 -176
  34. package/src/context/storage/JSONLStore.ts +0 -201
  35. package/src/context/storage/MemoryStore.ts +0 -205
  36. package/src/context/storage/PersistentStore.ts +0 -327
  37. package/src/context/storage/index.ts +0 -9
  38. package/src/context/storage/pathUtils.ts +0 -114
  39. package/src/context/test.ts +0 -309
  40. package/src/context/types.ts +0 -268
  41. package/src/hooks/HookExecutor.ts +0 -434
  42. package/src/hooks/HookManager.ts +0 -596
  43. package/src/hooks/HookService.ts +0 -269
  44. package/src/hooks/Matcher.ts +0 -157
  45. package/src/hooks/index.ts +0 -63
  46. package/src/hooks/types.ts +0 -424
  47. package/src/main.tsx +0 -596
  48. package/src/mcp/HealthMonitor.ts +0 -150
  49. package/src/mcp/McpClient.ts +0 -491
  50. package/src/mcp/McpRegistry.ts +0 -321
  51. package/src/mcp/createMcpTool.ts +0 -251
  52. package/src/mcp/index.ts +0 -15
  53. package/src/mcp/server.ts +0 -334
  54. package/src/mcp/test-server.ts +0 -88
  55. package/src/mcp/test.ts +0 -372
  56. package/src/mcp/types.ts +0 -247
  57. package/src/memory/AgentMemoryBus.ts +0 -432
  58. package/src/memory/CloudSync.ts +0 -99
  59. package/src/memory/DriveSync.ts +0 -106
  60. package/src/memory/SharedMemory.ts +0 -951
  61. package/src/memory/index.ts +0 -14
  62. package/src/memory/machineFingerprint.ts +0 -40
  63. package/src/orchestrator/SubAgentMetadata.ts +0 -136
  64. package/src/prompts/builder.ts +0 -213
  65. package/src/prompts/default.ts +0 -144
  66. package/src/prompts/index.ts +0 -16
  67. package/src/prompts/plan.ts +0 -64
  68. package/src/prompts/test.ts +0 -78
  69. package/src/services/AnthropicChatService.ts +0 -341
  70. package/src/services/ChatService.ts +0 -347
  71. package/src/services/ClaudeCliChatService.ts +0 -256
  72. package/src/services/CloudSync.ts +0 -168
  73. package/src/services/CostLedger.ts +0 -211
  74. package/src/services/Heartbeat.ts +0 -135
  75. package/src/services/LearningCollector.ts +0 -291
  76. package/src/services/OllamaInstaller.ts +0 -342
  77. package/src/services/VersionChecker.ts +0 -445
  78. package/src/services/index.ts +0 -57
  79. package/src/services/streaming/OpenAIEventAdapter.ts +0 -126
  80. package/src/services/streaming/RenderingProfile.ts +0 -90
  81. package/src/services/streaming/StreamEventParser.ts +0 -181
  82. package/src/services/streaming/ThrottledRenderer.ts +0 -139
  83. package/src/services/streaming/TranscriptBuffer.ts +0 -574
  84. package/src/services/streaming/eventStatusMap.ts +0 -52
  85. package/src/services/streaming/index.ts +0 -46
  86. package/src/services/streaming/renderFormatting.ts +0 -79
  87. package/src/services/streaming/types.ts +0 -234
  88. package/src/skills/SkillLoader.ts +0 -126
  89. package/src/skills/SkillRegistry.ts +0 -366
  90. package/src/skills/index.ts +0 -48
  91. package/src/skills/types.ts +0 -146
  92. package/src/slash-commands/billing.ts +0 -70
  93. package/src/slash-commands/build.ts +0 -413
  94. package/src/slash-commands/builtinCommands.ts +0 -2733
  95. package/src/slash-commands/clone.ts +0 -242
  96. package/src/slash-commands/council.ts +0 -125
  97. package/src/slash-commands/custom/CustomCommandExecutor.ts +0 -143
  98. package/src/slash-commands/custom/CustomCommandLoader.ts +0 -251
  99. package/src/slash-commands/custom/CustomCommandRegistry.ts +0 -144
  100. package/src/slash-commands/custom/index.ts +0 -7
  101. package/src/slash-commands/debate.ts +0 -254
  102. package/src/slash-commands/gmail.ts +0 -105
  103. package/src/slash-commands/index.ts +0 -388
  104. package/src/slash-commands/mcpCommand.ts +0 -205
  105. package/src/slash-commands/types.ts +0 -201
  106. package/src/store/index.ts +0 -76
  107. package/src/store/selectors.ts +0 -246
  108. package/src/store/slices/appSlice.ts +0 -205
  109. package/src/store/slices/commandSlice.ts +0 -115
  110. package/src/store/slices/configSlice.ts +0 -46
  111. package/src/store/slices/focusSlice.ts +0 -64
  112. package/src/store/slices/index.ts +0 -9
  113. package/src/store/slices/sessionSlice.ts +0 -424
  114. package/src/store/streaming-buffer.ts +0 -425
  115. package/src/store/test.ts +0 -296
  116. package/src/store/types.ts +0 -274
  117. package/src/store/vanilla.ts +0 -186
  118. package/src/tools/builtin/bash.ts +0 -236
  119. package/src/tools/builtin/council.ts +0 -105
  120. package/src/tools/builtin/edit.ts +0 -213
  121. package/src/tools/builtin/glob.ts +0 -136
  122. package/src/tools/builtin/grep.ts +0 -263
  123. package/src/tools/builtin/index.ts +0 -61
  124. package/src/tools/builtin/memory.ts +0 -66
  125. package/src/tools/builtin/read.ts +0 -168
  126. package/src/tools/builtin/skill.ts +0 -97
  127. package/src/tools/builtin/snapshot.ts +0 -40
  128. package/src/tools/builtin/task.ts +0 -106
  129. package/src/tools/builtin/write.ts +0 -134
  130. package/src/tools/createTool.ts +0 -221
  131. package/src/tools/execution/ExecutionPipeline.ts +0 -263
  132. package/src/tools/execution/index.ts +0 -40
  133. package/src/tools/execution/stages/CacheStage.ts +0 -131
  134. package/src/tools/execution/stages/ConfirmationStage.ts +0 -203
  135. package/src/tools/execution/stages/DiscoveryStage.ts +0 -46
  136. package/src/tools/execution/stages/ExecutionStage.ts +0 -48
  137. package/src/tools/execution/stages/FormattingStage.ts +0 -44
  138. package/src/tools/execution/stages/HookStage.ts +0 -72
  139. package/src/tools/execution/stages/PermissionStage.ts +0 -287
  140. package/src/tools/execution/stages/PostHookStage.ts +0 -71
  141. package/src/tools/execution/stages/index.ts +0 -12
  142. package/src/tools/execution/test.ts +0 -266
  143. package/src/tools/execution/types.ts +0 -273
  144. package/src/tools/index.ts +0 -81
  145. package/src/tools/registry.ts +0 -304
  146. package/src/tools/schemas.ts +0 -109
  147. package/src/tools/test.ts +0 -220
  148. package/src/tools/types.ts +0 -175
  149. package/src/tools/validation/PermissionChecker.ts +0 -242
  150. package/src/tools/validation/SensitiveFileDetector.ts +0 -210
  151. package/src/tools/validation/index.ts +0 -11
  152. package/src/ui/App.tsx +0 -166
  153. package/src/ui/components/AegisInterface.tsx +0 -484
  154. package/src/ui/components/common/ChatSearch.tsx +0 -150
  155. package/src/ui/components/common/ErrorBoundary.tsx +0 -82
  156. package/src/ui/components/common/ExitMessage.tsx +0 -120
  157. package/src/ui/components/common/LoadingIndicator.tsx +0 -49
  158. package/src/ui/components/common/index.ts +0 -6
  159. package/src/ui/components/dialog/ConfirmationPrompt.tsx +0 -208
  160. package/src/ui/components/dialog/InteractiveSelector.tsx +0 -149
  161. package/src/ui/components/dialog/SetupWizard.tsx +0 -297
  162. package/src/ui/components/dialog/UpdatePrompt.tsx +0 -155
  163. package/src/ui/components/dialog/index.ts +0 -8
  164. package/src/ui/components/index.ts +0 -28
  165. package/src/ui/components/input/CommandSuggestions.tsx +0 -139
  166. package/src/ui/components/input/CustomTextInput.tsx +0 -220
  167. package/src/ui/components/input/InputArea.tsx +0 -361
  168. package/src/ui/components/input/PromptSuggestions.tsx +0 -66
  169. package/src/ui/components/input/index.ts +0 -6
  170. package/src/ui/components/layout/ChatStatusBar.tsx +0 -90
  171. package/src/ui/components/layout/ContextBar.tsx +0 -79
  172. package/src/ui/components/layout/MessageArea.tsx +0 -96
  173. package/src/ui/components/layout/MessageList.tsx +0 -647
  174. package/src/ui/components/layout/MessageSeparator.tsx +0 -26
  175. package/src/ui/components/layout/WelcomeMessage.tsx +0 -93
  176. package/src/ui/components/layout/index.ts +0 -7
  177. package/src/ui/components/markdown/CodeHighlighter.tsx +0 -292
  178. package/src/ui/components/markdown/MessageRenderer.tsx +0 -1211
  179. package/src/ui/components/markdown/index.ts +0 -8
  180. package/src/ui/components/markdown/parser.ts +0 -336
  181. package/src/ui/components/markdown/types.ts +0 -66
  182. package/src/ui/focus/FocusManager.ts +0 -137
  183. package/src/ui/focus/index.ts +0 -13
  184. package/src/ui/focus/types.ts +0 -54
  185. package/src/ui/focus/useFocus.ts +0 -75
  186. package/src/ui/hooks/index.ts +0 -11
  187. package/src/ui/hooks/useAgent.ts +0 -284
  188. package/src/ui/hooks/useCommandHistory.ts +0 -87
  189. package/src/ui/hooks/useCommandProcessor.ts +0 -443
  190. package/src/ui/hooks/useConfirmation.ts +0 -99
  191. package/src/ui/hooks/useCtrlCHandler.ts +0 -100
  192. package/src/ui/hooks/useInputBuffer.ts +0 -122
  193. package/src/ui/hooks/useTerminalSize.ts +0 -68
  194. package/src/ui/hooks/useTerminalWidth.ts +0 -5
  195. package/src/ui/hooks/useWindowedList.ts +0 -118
  196. package/src/ui/render-debugger.ts +0 -621
  197. package/src/ui/test.ts +0 -189
  198. package/src/ui/themes/ThemeManager.ts +0 -332
  199. package/src/ui/themes/aegisTheme.ts +0 -87
  200. package/src/ui/themes/darkTheme.ts +0 -87
  201. package/src/ui/themes/defaultTheme.ts +0 -85
  202. package/src/ui/themes/index.ts +0 -10
  203. package/src/ui/themes/lightTheme.ts +0 -89
  204. package/src/ui/themes/popularThemes.ts +0 -187
  205. package/src/ui/themes/types.ts +0 -130
  206. package/src/utils/clipboard.ts +0 -48
  207. package/src/utils/debug.ts +0 -43
  208. package/src/utils/environment.ts +0 -68
  209. package/src/utils/index.ts +0 -10
@@ -1,574 +0,0 @@
1
- /**
2
- * TranscriptBuffer — replicates Claude Code's transcript.py
3
- *
4
- * Maintains an ordered list of segments (thinking, text, tool calls, tool results,
5
- * subagents, errors) that represent what the user should see in the transcript.
6
- *
7
- * Key features:
8
- * - Content block lifecycle: start/delta/stop tracked by index
9
- * - Subagent nesting via Task tool stack
10
- * - Ordered render with tail-truncation when over limit
11
- * - Thread-safe segment accumulation
12
- */
13
-
14
- import type { ParsedEvent, ParsedEventType, StreamSegment, RenderContext } from './types.js';
15
-
16
- /**
17
- * TranscriptBuffer — ordered, truncatable transcript of streaming events.
18
- */
19
- export class TranscriptBuffer {
20
- private _segments: StreamSegment[] = [];
21
-
22
- /** content_block index → open thinking segment */
23
- private _openThinkingByIndex: Map<number, StreamSegment> = new Map();
24
- /** content_block index → open text segment */
25
- private _openTextByIndex: Map<number, StreamSegment> = new Map();
26
- /** content_block index → open tool call segment */
27
- private _openToolsByIndex: Map<number, StreamSegment> = new Map();
28
- /** tool_use_id → tool name (for labeling tool results) */
29
- private _toolNameById: Map<string, string> = new Map();
30
-
31
- /** Subagent stack — each entry is the Task tool_use_id */
32
- private _subagentStack: string[] = [];
33
- /** Parallel subagent segment stack */
34
- private _subagentSegments: StreamSegment[] = [];
35
-
36
- private _showToolResults: boolean;
37
-
38
- constructor(options?: { showToolResults?: boolean }) {
39
- this._showToolResults = options?.showToolResults ?? true;
40
- }
41
-
42
- /** Current segments (read-only snapshot) */
43
- get segments(): readonly StreamSegment[] {
44
- return this._segments;
45
- }
46
-
47
- /** Whether we're inside a subagent context */
48
- private get _inSubagent(): boolean {
49
- return this._subagentStack.length > 0;
50
- }
51
-
52
- private get _currentSubagent(): StreamSegment | undefined {
53
- return this._subagentSegments.length > 0
54
- ? this._subagentSegments[this._subagentSegments.length - 1]
55
- : undefined;
56
- }
57
-
58
- /**
59
- * Apply a parsed event to the transcript.
60
- * This is the core method — replicates transcript.py's apply().
61
- */
62
- apply(event: ParsedEvent): void {
63
- // Inside a subagent, suppress thinking/text content (only show tool calls)
64
- if (this._inSubagent && isThinkingOrTextEvent(event)) {
65
- return;
66
- }
67
-
68
- switch (event.type) {
69
- case 'thinking_start':
70
- this._handleThinkingStart(event);
71
- break;
72
- case 'thinking_delta':
73
- case 'thinking_chunk':
74
- this._handleThinkingDelta(event);
75
- break;
76
- case 'thinking_stop':
77
- this._handleThinkingStop(event);
78
- break;
79
-
80
- case 'text_start':
81
- this._handleTextStart(event);
82
- break;
83
- case 'text_delta':
84
- case 'text_chunk':
85
- this._handleTextDelta(event);
86
- break;
87
- case 'text_stop':
88
- this._handleTextStop(event);
89
- break;
90
-
91
- case 'tool_use_start':
92
- this._handleToolUseStart(event);
93
- break;
94
- case 'tool_use_delta':
95
- // Track open tool for close events — no visible output
96
- break;
97
- case 'tool_use_stop':
98
- this._handleToolUseStop(event);
99
- break;
100
-
101
- case 'tool_use':
102
- this._handleToolUse(event);
103
- break;
104
-
105
- case 'tool_result':
106
- this._handleToolResult(event);
107
- break;
108
-
109
- case 'block_stop':
110
- this._handleBlockStop(event);
111
- break;
112
-
113
- case 'error':
114
- this._segments.push({
115
- kind: 'error',
116
- text: event.message || 'Unknown error',
117
- });
118
- break;
119
-
120
- case 'complete':
121
- // No-op for transcript — signals end of stream
122
- break;
123
- }
124
- }
125
-
126
- /**
127
- * Reset the buffer to initial state.
128
- */
129
- clear(): void {
130
- this._segments = [];
131
- this._openThinkingByIndex.clear();
132
- this._openTextByIndex.clear();
133
- this._openToolsByIndex.clear();
134
- this._toolNameById.clear();
135
- this._subagentStack = [];
136
- this._subagentSegments = [];
137
- }
138
-
139
- /**
140
- * Render transcript with optional truncation (drops oldest segments)
141
- * and optional status line appended at the bottom.
142
- *
143
- * Replicates transcript.py's render() method with status + tail truncation.
144
- */
145
- render(ctx: RenderContext, status?: string): string {
146
- const parts: string[] = [];
147
-
148
- for (const seg of this._segments) {
149
- const rendered = this._renderSegment(seg, ctx);
150
- if (rendered) {
151
- parts.push(rendered);
152
- }
153
- }
154
-
155
- const statusText = status ? `\n\n${status}` : '';
156
- const prefixMarker = ctx.formatting.escapeText('... (truncated)\n');
157
-
158
- const joinParts = (segments: string[], addMarker: boolean): string => {
159
- const body = segments.join('\n');
160
- const text = addMarker && body ? prefixMarker + body : body;
161
- return text || statusText ? text + statusText : '';
162
- };
163
-
164
- // Fast path
165
- const candidate = joinParts(parts, false);
166
- if (candidate.length <= ctx.limitChars) {
167
- return candidate;
168
- }
169
-
170
- // Drop oldest segments until under limit (keep the tail)
171
- const dropped: string[] = [];
172
- let remaining = [...parts];
173
- while (remaining.length > 0) {
174
- const candidate_ = joinParts(remaining, true);
175
- if (candidate_.length <= ctx.limitChars) {
176
- return candidate_;
177
- }
178
- dropped.push(remaining.shift()!);
179
- }
180
-
181
- // Nothing fits — preserve tail of last segment instead of only marker+status
182
- if (dropped.length > 0) {
183
- const lastPart = dropped[dropped.length - 1];
184
- const budget = ctx.limitChars - prefixMarker.length - statusText.length;
185
- if (budget > 20 && lastPart) {
186
- const tail = lastPart.length > budget
187
- ? '...' + lastPart.slice(-(budget - 3))
188
- : lastPart;
189
- return prefixMarker + tail + statusText;
190
- }
191
- }
192
-
193
- // Fallback: marker + status only
194
- if (dropped.length > 0) {
195
- const minimal = prefixMarker + statusText.replace(/^\n+/, '');
196
- if (minimal.length <= ctx.limitChars) {
197
- return minimal;
198
- }
199
- }
200
-
201
- return status || '';
202
- }
203
-
204
- // ==================== Private Event Handlers ====================
205
-
206
- private _ensureSegment(index: number, map: Map<number, StreamSegment>, seg: StreamSegment): StreamSegment {
207
- const existing = map.get(index);
208
- if (existing) return existing;
209
- map.set(index, seg);
210
- this._segments.push(seg);
211
- return seg;
212
- }
213
-
214
- private _handleThinkingStart(event: ParsedEvent): void {
215
- const idx = event.index ?? -1;
216
- if (idx >= 0) {
217
- // Close any previous open block at this index
218
- this._handleBlockStop({ type: 'block_stop', index: idx });
219
- }
220
- const seg: StreamSegment = { kind: 'thinking', text: '' };
221
- this._segments.push(seg);
222
- if (idx >= 0) {
223
- this._openThinkingByIndex.set(idx, seg);
224
- }
225
- }
226
-
227
- private _handleThinkingDelta(event: ParsedEvent): void {
228
- const idx = event.index ?? -1;
229
- let seg = this._openThinkingByIndex.get(idx);
230
- if (!seg) {
231
- seg = { kind: 'thinking', text: '' };
232
- this._segments.push(seg);
233
- if (idx >= 0) {
234
- this._openThinkingByIndex.set(idx, seg);
235
- }
236
- }
237
- seg.text += event.text || '';
238
- }
239
-
240
- private _handleThinkingStop(event: ParsedEvent): void {
241
- const idx = event.index ?? -1;
242
- if (idx >= 0) {
243
- this._openThinkingByIndex.delete(idx);
244
- }
245
- }
246
-
247
- private _handleTextStart(event: ParsedEvent): void {
248
- const idx = event.index ?? -1;
249
- if (idx >= 0) {
250
- this._handleBlockStop({ type: 'block_stop', index: idx });
251
- }
252
- const seg: StreamSegment = { kind: 'text', text: '' };
253
- this._segments.push(seg);
254
- if (idx >= 0) {
255
- this._openTextByIndex.set(idx, seg);
256
- }
257
- }
258
-
259
- private _handleTextDelta(event: ParsedEvent): void {
260
- const idx = event.index ?? -1;
261
- let seg = this._openTextByIndex.get(idx);
262
- if (!seg) {
263
- seg = { kind: 'text', text: '' };
264
- this._segments.push(seg);
265
- if (idx >= 0) {
266
- this._openTextByIndex.set(idx, seg);
267
- }
268
- }
269
- seg.text += event.text || '';
270
- }
271
-
272
- private _handleTextStop(event: ParsedEvent): void {
273
- const idx = event.index ?? -1;
274
- if (idx >= 0) {
275
- this._openTextByIndex.delete(idx);
276
- }
277
- }
278
-
279
- private _handleToolUseStart(event: ParsedEvent): void {
280
- const idx = event.index ?? -1;
281
- if (idx >= 0) {
282
- this._handleBlockStop({ type: 'block_stop', index: idx });
283
- }
284
-
285
- const toolId = (event.id || '').trim();
286
- const name = event.name || 'tool';
287
- if (toolId) {
288
- this._toolNameById.set(toolId, name);
289
- }
290
-
291
- // Task tool indicates subagent
292
- if (name === 'Task') {
293
- const description = this._taskHeadingFromInput(event.input);
294
- const seg: StreamSegment = {
295
- kind: 'subagent',
296
- text: '',
297
- description,
298
- toolCalls: 0,
299
- toolsUsed: new Set(),
300
- };
301
- this._segments.push(seg);
302
- this._subagentStack.push(toolId || `__task_${this._subagentStack.length + 1}`);
303
- this._subagentSegments.push(seg);
304
- return;
305
- }
306
-
307
- // Normal tool call
308
- const seg: StreamSegment = {
309
- kind: 'tool_call',
310
- id: toolId,
311
- name,
312
- text: '',
313
- closed: false,
314
- indentLevel: this._inSubagent ? 1 : 0,
315
- };
316
-
317
- if (this._inSubagent) {
318
- const parent = this._currentSubagent;
319
- if (parent) {
320
- parent.toolCalls = (parent.toolCalls || 0) + 1;
321
- if (name && parent.toolsUsed) {
322
- parent.toolsUsed.add(name);
323
- }
324
- }
325
- }
326
-
327
- this._segments.push(seg);
328
- if (idx >= 0) {
329
- this._openToolsByIndex.set(idx, seg);
330
- }
331
- }
332
-
333
- private _handleToolUseStop(event: ParsedEvent): void {
334
- const idx = event.index ?? -1;
335
- const seg = this._openToolsByIndex.get(idx);
336
- if (seg) {
337
- seg.closed = true;
338
- this._openToolsByIndex.delete(idx);
339
- }
340
- }
341
-
342
- private _handleToolUse(event: ParsedEvent): void {
343
- const toolId = (event.id || '').trim();
344
- const name = event.name || 'tool';
345
- if (toolId) {
346
- this._toolNameById.set(toolId, name);
347
- }
348
-
349
- if (name === 'Task') {
350
- const description = this._taskHeadingFromInput(event.input);
351
- const seg: StreamSegment = {
352
- kind: 'subagent',
353
- text: '',
354
- description,
355
- toolCalls: 0,
356
- toolsUsed: new Set(),
357
- };
358
- this._segments.push(seg);
359
- this._subagentStack.push(toolId || `__task_${this._subagentStack.length + 1}`);
360
- this._subagentSegments.push(seg);
361
- return;
362
- }
363
-
364
- const seg: StreamSegment = {
365
- kind: 'tool_call',
366
- id: toolId,
367
- name,
368
- text: '',
369
- closed: true,
370
- indentLevel: this._inSubagent ? 1 : 0,
371
- };
372
-
373
- if (this._inSubagent) {
374
- const parent = this._currentSubagent;
375
- if (parent) {
376
- parent.toolCalls = (parent.toolCalls || 0) + 1;
377
- if (name && parent.toolsUsed) {
378
- parent.toolsUsed.add(name);
379
- }
380
- }
381
- }
382
-
383
- this._segments.push(seg);
384
- }
385
-
386
- private _handleToolResult(event: ParsedEvent): void {
387
- const toolId = (event.tool_use_id || '').trim();
388
- const name = this._toolNameById.get(toolId);
389
-
390
- // If this was a Task tool result, close subagent context
391
- if (this._subagentStack.length > 0) {
392
- this._subagentPop(toolId);
393
- }
394
-
395
- if (!this._showToolResults) return;
396
-
397
- const contentStr = typeof event.content === 'string'
398
- ? event.content
399
- : event.content !== undefined
400
- ? safeStringify(event.content)
401
- : '';
402
-
403
- this._segments.push({
404
- kind: 'tool_result',
405
- id: toolId,
406
- name,
407
- text: contentStr,
408
- isError: Boolean(event.is_error),
409
- });
410
- }
411
-
412
- private _handleBlockStop(event: ParsedEvent): void {
413
- const idx = event.index ?? -1;
414
- if (idx < 0) return;
415
-
416
- if (this._openToolsByIndex.has(idx)) {
417
- this._handleToolUseStop({ type: 'tool_use_stop', index: idx });
418
- return;
419
- }
420
- if (this._openThinkingByIndex.has(idx)) {
421
- this._handleThinkingStop({ type: 'thinking_stop', index: idx });
422
- return;
423
- }
424
- if (this._openTextByIndex.has(idx)) {
425
- this._handleTextStop({ type: 'text_stop', index: idx });
426
- return;
427
- }
428
- }
429
-
430
- // ==================== Subagent Stack Management ====================
431
-
432
- private _taskHeadingFromInput(input: unknown): string {
433
- if (typeof input === 'object' && input !== null) {
434
- const obj = input as Record<string, unknown>;
435
- const desc = String(obj.description || '').trim();
436
- if (desc) return desc;
437
- const subType = String(obj.subagent_type || '').trim();
438
- if (subType) return subType;
439
- const typ = String(obj.type || '').trim();
440
- if (typ) return typ;
441
- }
442
- return 'Subagent';
443
- }
444
-
445
- private _subagentPop(toolId: string): boolean {
446
- const id = String(toolId || '').trim();
447
-
448
- if (!id) {
449
- // No id — only close if top is synthetic
450
- if (this._subagentStack.length > 0 && this._subagentStack[this._subagentStack.length - 1].startsWith('__task_')) {
451
- this._subagentStack.pop();
452
- if (this._subagentSegments.length > 0) this._subagentSegments.pop();
453
- return true;
454
- }
455
- return false;
456
- }
457
-
458
- // Common case: LIFO — top matches
459
- if (this._subagentStack.length > 0) {
460
- const top = this._subagentStack[this._subagentStack.length - 1];
461
- if (top === id || top.startsWith(id) || id.startsWith(top)) {
462
- this._subagentStack.pop();
463
- if (this._subagentSegments.length > 0) this._subagentSegments.pop();
464
- return true;
465
- }
466
- }
467
-
468
- // Search from top
469
- for (let i = this._subagentStack.length - 1; i >= 0; i--) {
470
- const stackId = this._subagentStack[i];
471
- if (stackId === id || stackId.startsWith(id) || id.startsWith(stackId)) {
472
- this._subagentStack.splice(i);
473
- this._subagentSegments.splice(i);
474
- return true;
475
- }
476
- }
477
-
478
- return false;
479
- }
480
-
481
- // ==================== Rendering ====================
482
-
483
- private _renderSegment(seg: StreamSegment, ctx: RenderContext): string {
484
- switch (seg.kind) {
485
- case 'thinking':
486
- return this._renderThinking(seg, ctx);
487
- case 'text':
488
- return this._renderText(seg, ctx);
489
- case 'tool_call':
490
- return this._renderToolCall(seg);
491
- case 'tool_result':
492
- return this._renderToolResult(seg, ctx);
493
- case 'subagent':
494
- return this._renderSubagent(seg, ctx);
495
- case 'error':
496
- return `⚠️ ${ctx.formatting.bold('Error:')} \`${seg.text}\``;
497
- default:
498
- return '';
499
- }
500
- }
501
-
502
- private _renderThinking(seg: StreamSegment, ctx: RenderContext): string {
503
- let raw = seg.text || '';
504
- if (ctx.thinkingTailMax !== undefined && raw.length > ctx.thinkingTailMax) {
505
- raw = '...' + raw.slice(-(ctx.thinkingTailMax - 3));
506
- }
507
- const inner = ctx.formatting.escapeCode(raw);
508
- return `💭 ${ctx.formatting.bold('Thinking')}\n\`\`\`\n${inner}\n\`\`\``;
509
- }
510
-
511
- private _renderText(seg: StreamSegment, ctx: RenderContext): string {
512
- let raw = seg.text || '';
513
- if (ctx.textTailMax !== undefined && raw.length > ctx.textTailMax) {
514
- raw = '...' + raw.slice(-(ctx.textTailMax - 3));
515
- }
516
- return ctx.formatting.renderMarkdown(raw);
517
- }
518
-
519
- private _renderToolCall(seg: StreamSegment): string {
520
- const prefix = ' '.repeat(seg.indentLevel || 0);
521
- const name = `\`${seg.name}\``;
522
- return `${prefix}🛠 **Tool call:** ${name}`;
523
- }
524
-
525
- private _renderToolResult(seg: StreamSegment, ctx: RenderContext): string {
526
- let raw = seg.text || '';
527
- if (ctx.toolOutputTailMax !== undefined && raw.length > ctx.toolOutputTailMax) {
528
- raw = '...' + raw.slice(-(ctx.toolOutputTailMax - 3));
529
- }
530
- const inner = ctx.formatting.escapeCode(raw);
531
- const label = seg.isError ? 'Tool error:' : 'Tool result:';
532
- const namePart = seg.name ? ` \`${seg.name}\`` : '';
533
- return `📤 **${label}**${namePart}\n\`\`\`\n${inner}\n\`\`\``;
534
- }
535
-
536
- private _renderSubagent(seg: StreamSegment, ctx: RenderContext): string {
537
- const desc = seg.description || 'Subagent';
538
- const toolsUsed = seg.toolsUsed ? [...seg.toolsUsed].sort() : [];
539
- const toolCalls = seg.toolCalls ?? 0;
540
-
541
- const parts: string[] = [
542
- `🤖 **Subagent:** \`${desc}\``,
543
- ];
544
-
545
- if (toolsUsed.length > 0) {
546
- const toolsSet = `{${toolsUsed.join(', ')}}`;
547
- parts.push(` **Tools used:** \`${toolsSet}\``);
548
- }
549
- parts.push(` **Tool calls:** \`${toolCalls}\``);
550
-
551
- return parts.join('\n');
552
- }
553
- }
554
-
555
- // ==================== Helpers ====================
556
-
557
- function isThinkingOrTextEvent(event: ParsedEvent): boolean {
558
- return ([
559
- 'thinking_start',
560
- 'thinking_delta',
561
- 'thinking_chunk',
562
- 'text_start',
563
- 'text_delta',
564
- 'text_chunk',
565
- ] as ParsedEventType[]).includes(event.type);
566
- }
567
-
568
- function safeStringify(obj: unknown): string {
569
- try {
570
- return JSON.stringify(obj, null, 2);
571
- } catch {
572
- return String(obj);
573
- }
574
- }
@@ -1,52 +0,0 @@
1
- /**
2
- * Event type → status mapping for streaming UI updates.
3
- *
4
- * Replicates free-claude-code's messaging/cli_event_constants.py.
5
- * Maps parsed event types to emoji + label pairs that get formatted
6
- * into status lines shown below the transcript.
7
- */
8
-
9
- import type { ParsedEventType } from './types.js';
10
-
11
- type StatusFormatter = (emoji: string, label: string, suffix?: string) => string;
12
-
13
- /** Event type → (emoji, label) for status updates */
14
- const EVENT_STATUS_MAP: Record<string, [string, string]> = {
15
- thinking_start: ['🧠', 'Claude is thinking...'],
16
- thinking_delta: ['🧠', 'Claude is thinking...'],
17
- thinking_chunk: ['🧠', 'Claude is thinking...'],
18
- text_start: ['🧠', 'Claude is working...'],
19
- text_delta: ['🧠', 'Claude is working...'],
20
- text_chunk: ['🧠', 'Claude is working...'],
21
- tool_result: ['⏳', 'Executing tools...'],
22
- };
23
-
24
- /**
25
- * Get status string for a parsed event type.
26
- * Returns null if no status update is needed for this event type.
27
- */
28
- export function getStatusForEvent(
29
- eventType: ParsedEventType,
30
- name: string | undefined,
31
- formatStatus: StatusFormatter,
32
- ): string | null {
33
- const entry = EVENT_STATUS_MAP[eventType];
34
- if (entry) {
35
- const [emoji, label] = entry;
36
- return formatStatus(emoji, label);
37
- }
38
-
39
- if (eventType === 'tool_use_start' || eventType === 'tool_use_delta' || eventType === 'tool_use') {
40
- if (name === 'Task') {
41
- return formatStatus('🤖', 'Subagent working...');
42
- }
43
- return formatStatus('⏳', 'Executing tools...');
44
- }
45
-
46
- return null;
47
- }
48
-
49
- /** Status message prefixes used to filter echo of our own messages */
50
- export const STATUS_MESSAGE_PREFIXES = [
51
- '⏳', '💭', '🔧', '✅', '❌', '🚀', '🤖', '📋', '📊', '🔄',
52
- ];
@@ -1,46 +0,0 @@
1
- /**
2
- * Streaming module exports — Claude Code-style content block streaming + rendering.
3
- *
4
- * Provides:
5
- * - StreamEventParser: Parse Anthropic content_block_start/delta/stop events
6
- * - TranscriptBuffer: Ordered, truncatable transcript with segment management
7
- * - ThrottledRenderer: Rate-limited transcript rendering with status lines
8
- * - RenderingProfile: Platform-specific rendering configuration
9
- * - Render formatting functions for terminal/plain output
10
- * - Event → status mapping for live UI updates
11
- * - Type definitions for all streaming events, segments, and rendering
12
- */
13
-
14
- export { parseStreamEvent } from './StreamEventParser.js';
15
- export { TranscriptBuffer } from './TranscriptBuffer.js';
16
- export { ThrottledRenderer } from './ThrottledRenderer.js';
17
- export {
18
- TERMINAL_FORMATTING,
19
- PLAIN_TEXT_FORMATTING,
20
- buildRenderContext,
21
- } from './renderFormatting.js';
22
- export {
23
- TERMINAL_PROFILE,
24
- PLAIN_TEXT_PROFILE,
25
- COMPACT_TERMINAL_PROFILE,
26
- buildRenderingProfile,
27
- } from './RenderingProfile.js';
28
- export { getStatusForEvent, STATUS_MESSAGE_PREFIXES } from './eventStatusMap.js';
29
- export { OpenAIEventAdapter } from './OpenAIEventAdapter.js';
30
- export type {
31
- AnthropicStreamEvent,
32
- ContentBlockStartEvent,
33
- ContentBlockDeltaEvent,
34
- ContentBlockStopEvent,
35
- MessageStartEvent,
36
- MessageDeltaEvent,
37
- MessageStopEvent,
38
- ParsedEvent,
39
- ParsedEventType,
40
- StreamSegment,
41
- SegmentKind,
42
- RenderContext,
43
- RenderFormatting,
44
- RenderingProfile,
45
- } from './types.js';
46
- export { TRANSCRIPT_EVENT_TYPES } from './types.js';