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.
- package/bin/aegis.js +165 -0
- package/package.json +18 -86
- package/LICENSE +0 -21
- package/README.md +0 -394
- package/dist/main.js +0 -2171
- package/gui/run-gui.cjs +0 -13
- package/src/agent/Agent.ts +0 -903
- package/src/agent/SimpleAgent.ts +0 -48
- package/src/agent/index.ts +0 -54
- package/src/agent/orchestrator/AppBuilder.ts +0 -443
- package/src/agent/orchestrator/CouncilAgent.ts +0 -310
- package/src/agent/orchestrator/DiscussionRoom.ts +0 -462
- package/src/agent/orchestrator/OrchestratorAgent.ts +0 -637
- package/src/agent/orchestrator/index.ts +0 -38
- package/src/agent/orchestrator/utils.ts +0 -397
- package/src/agent/pricing.ts +0 -115
- package/src/agent/router.ts +0 -74
- package/src/agent/routerStats.ts +0 -121
- package/src/agent/types.ts +0 -318
- package/src/auth/login.ts +0 -383
- package/src/cli/config.ts +0 -189
- package/src/cli/index.ts +0 -17
- package/src/cli/middleware.ts +0 -119
- package/src/cli/types.ts +0 -75
- package/src/config/ConfigManager.ts +0 -587
- package/src/config/index.ts +0 -7
- package/src/config/types.ts +0 -584
- package/src/context/CompactionService.ts +0 -300
- package/src/context/ContextManager.ts +0 -450
- package/src/context/FileAnalyzer.ts +0 -267
- package/src/context/TokenCounter.ts +0 -265
- package/src/context/index.ts +0 -27
- package/src/context/storage/CacheStore.ts +0 -176
- package/src/context/storage/JSONLStore.ts +0 -201
- package/src/context/storage/MemoryStore.ts +0 -205
- package/src/context/storage/PersistentStore.ts +0 -327
- package/src/context/storage/index.ts +0 -9
- package/src/context/storage/pathUtils.ts +0 -114
- package/src/context/test.ts +0 -309
- package/src/context/types.ts +0 -268
- package/src/hooks/HookExecutor.ts +0 -434
- package/src/hooks/HookManager.ts +0 -596
- package/src/hooks/HookService.ts +0 -269
- package/src/hooks/Matcher.ts +0 -157
- package/src/hooks/index.ts +0 -63
- package/src/hooks/types.ts +0 -424
- package/src/main.tsx +0 -596
- package/src/mcp/HealthMonitor.ts +0 -150
- package/src/mcp/McpClient.ts +0 -491
- package/src/mcp/McpRegistry.ts +0 -321
- package/src/mcp/createMcpTool.ts +0 -251
- package/src/mcp/index.ts +0 -15
- package/src/mcp/server.ts +0 -334
- package/src/mcp/test-server.ts +0 -88
- package/src/mcp/test.ts +0 -372
- package/src/mcp/types.ts +0 -247
- package/src/memory/AgentMemoryBus.ts +0 -432
- package/src/memory/CloudSync.ts +0 -99
- package/src/memory/DriveSync.ts +0 -106
- package/src/memory/SharedMemory.ts +0 -951
- package/src/memory/index.ts +0 -14
- package/src/memory/machineFingerprint.ts +0 -40
- package/src/orchestrator/SubAgentMetadata.ts +0 -136
- package/src/prompts/builder.ts +0 -213
- package/src/prompts/default.ts +0 -144
- package/src/prompts/index.ts +0 -16
- package/src/prompts/plan.ts +0 -64
- package/src/prompts/test.ts +0 -78
- package/src/services/AnthropicChatService.ts +0 -341
- package/src/services/ChatService.ts +0 -347
- package/src/services/ClaudeCliChatService.ts +0 -256
- package/src/services/CloudSync.ts +0 -168
- package/src/services/CostLedger.ts +0 -211
- package/src/services/Heartbeat.ts +0 -135
- package/src/services/LearningCollector.ts +0 -291
- package/src/services/OllamaInstaller.ts +0 -342
- package/src/services/VersionChecker.ts +0 -445
- package/src/services/index.ts +0 -57
- package/src/services/streaming/OpenAIEventAdapter.ts +0 -126
- package/src/services/streaming/RenderingProfile.ts +0 -90
- package/src/services/streaming/StreamEventParser.ts +0 -181
- package/src/services/streaming/ThrottledRenderer.ts +0 -139
- package/src/services/streaming/TranscriptBuffer.ts +0 -574
- package/src/services/streaming/eventStatusMap.ts +0 -52
- package/src/services/streaming/index.ts +0 -46
- package/src/services/streaming/renderFormatting.ts +0 -79
- package/src/services/streaming/types.ts +0 -234
- package/src/skills/SkillLoader.ts +0 -126
- package/src/skills/SkillRegistry.ts +0 -366
- package/src/skills/index.ts +0 -48
- package/src/skills/types.ts +0 -146
- package/src/slash-commands/billing.ts +0 -70
- package/src/slash-commands/build.ts +0 -413
- package/src/slash-commands/builtinCommands.ts +0 -2733
- package/src/slash-commands/clone.ts +0 -242
- package/src/slash-commands/council.ts +0 -125
- package/src/slash-commands/custom/CustomCommandExecutor.ts +0 -143
- package/src/slash-commands/custom/CustomCommandLoader.ts +0 -251
- package/src/slash-commands/custom/CustomCommandRegistry.ts +0 -144
- package/src/slash-commands/custom/index.ts +0 -7
- package/src/slash-commands/debate.ts +0 -254
- package/src/slash-commands/gmail.ts +0 -105
- package/src/slash-commands/index.ts +0 -388
- package/src/slash-commands/mcpCommand.ts +0 -205
- package/src/slash-commands/types.ts +0 -201
- package/src/store/index.ts +0 -76
- package/src/store/selectors.ts +0 -246
- package/src/store/slices/appSlice.ts +0 -205
- package/src/store/slices/commandSlice.ts +0 -115
- package/src/store/slices/configSlice.ts +0 -46
- package/src/store/slices/focusSlice.ts +0 -64
- package/src/store/slices/index.ts +0 -9
- package/src/store/slices/sessionSlice.ts +0 -424
- package/src/store/streaming-buffer.ts +0 -425
- package/src/store/test.ts +0 -296
- package/src/store/types.ts +0 -274
- package/src/store/vanilla.ts +0 -186
- package/src/tools/builtin/bash.ts +0 -236
- package/src/tools/builtin/council.ts +0 -105
- package/src/tools/builtin/edit.ts +0 -213
- package/src/tools/builtin/glob.ts +0 -136
- package/src/tools/builtin/grep.ts +0 -263
- package/src/tools/builtin/index.ts +0 -61
- package/src/tools/builtin/memory.ts +0 -66
- package/src/tools/builtin/read.ts +0 -168
- package/src/tools/builtin/skill.ts +0 -97
- package/src/tools/builtin/snapshot.ts +0 -40
- package/src/tools/builtin/task.ts +0 -106
- package/src/tools/builtin/write.ts +0 -134
- package/src/tools/createTool.ts +0 -221
- package/src/tools/execution/ExecutionPipeline.ts +0 -263
- package/src/tools/execution/index.ts +0 -40
- package/src/tools/execution/stages/CacheStage.ts +0 -131
- package/src/tools/execution/stages/ConfirmationStage.ts +0 -203
- package/src/tools/execution/stages/DiscoveryStage.ts +0 -46
- package/src/tools/execution/stages/ExecutionStage.ts +0 -48
- package/src/tools/execution/stages/FormattingStage.ts +0 -44
- package/src/tools/execution/stages/HookStage.ts +0 -72
- package/src/tools/execution/stages/PermissionStage.ts +0 -287
- package/src/tools/execution/stages/PostHookStage.ts +0 -71
- package/src/tools/execution/stages/index.ts +0 -12
- package/src/tools/execution/test.ts +0 -266
- package/src/tools/execution/types.ts +0 -273
- package/src/tools/index.ts +0 -81
- package/src/tools/registry.ts +0 -304
- package/src/tools/schemas.ts +0 -109
- package/src/tools/test.ts +0 -220
- package/src/tools/types.ts +0 -175
- package/src/tools/validation/PermissionChecker.ts +0 -242
- package/src/tools/validation/SensitiveFileDetector.ts +0 -210
- package/src/tools/validation/index.ts +0 -11
- package/src/ui/App.tsx +0 -166
- package/src/ui/components/AegisInterface.tsx +0 -484
- package/src/ui/components/common/ChatSearch.tsx +0 -150
- package/src/ui/components/common/ErrorBoundary.tsx +0 -82
- package/src/ui/components/common/ExitMessage.tsx +0 -120
- package/src/ui/components/common/LoadingIndicator.tsx +0 -49
- package/src/ui/components/common/index.ts +0 -6
- package/src/ui/components/dialog/ConfirmationPrompt.tsx +0 -208
- package/src/ui/components/dialog/InteractiveSelector.tsx +0 -149
- package/src/ui/components/dialog/SetupWizard.tsx +0 -297
- package/src/ui/components/dialog/UpdatePrompt.tsx +0 -155
- package/src/ui/components/dialog/index.ts +0 -8
- package/src/ui/components/index.ts +0 -28
- package/src/ui/components/input/CommandSuggestions.tsx +0 -139
- package/src/ui/components/input/CustomTextInput.tsx +0 -220
- package/src/ui/components/input/InputArea.tsx +0 -361
- package/src/ui/components/input/PromptSuggestions.tsx +0 -66
- package/src/ui/components/input/index.ts +0 -6
- package/src/ui/components/layout/ChatStatusBar.tsx +0 -90
- package/src/ui/components/layout/ContextBar.tsx +0 -79
- package/src/ui/components/layout/MessageArea.tsx +0 -96
- package/src/ui/components/layout/MessageList.tsx +0 -647
- package/src/ui/components/layout/MessageSeparator.tsx +0 -26
- package/src/ui/components/layout/WelcomeMessage.tsx +0 -93
- package/src/ui/components/layout/index.ts +0 -7
- package/src/ui/components/markdown/CodeHighlighter.tsx +0 -292
- package/src/ui/components/markdown/MessageRenderer.tsx +0 -1211
- package/src/ui/components/markdown/index.ts +0 -8
- package/src/ui/components/markdown/parser.ts +0 -336
- package/src/ui/components/markdown/types.ts +0 -66
- package/src/ui/focus/FocusManager.ts +0 -137
- package/src/ui/focus/index.ts +0 -13
- package/src/ui/focus/types.ts +0 -54
- package/src/ui/focus/useFocus.ts +0 -75
- package/src/ui/hooks/index.ts +0 -11
- package/src/ui/hooks/useAgent.ts +0 -284
- package/src/ui/hooks/useCommandHistory.ts +0 -87
- package/src/ui/hooks/useCommandProcessor.ts +0 -443
- package/src/ui/hooks/useConfirmation.ts +0 -99
- package/src/ui/hooks/useCtrlCHandler.ts +0 -100
- package/src/ui/hooks/useInputBuffer.ts +0 -122
- package/src/ui/hooks/useTerminalSize.ts +0 -68
- package/src/ui/hooks/useTerminalWidth.ts +0 -5
- package/src/ui/hooks/useWindowedList.ts +0 -118
- package/src/ui/render-debugger.ts +0 -621
- package/src/ui/test.ts +0 -189
- package/src/ui/themes/ThemeManager.ts +0 -332
- package/src/ui/themes/aegisTheme.ts +0 -87
- package/src/ui/themes/darkTheme.ts +0 -87
- package/src/ui/themes/defaultTheme.ts +0 -85
- package/src/ui/themes/index.ts +0 -10
- package/src/ui/themes/lightTheme.ts +0 -89
- package/src/ui/themes/popularThemes.ts +0 -187
- package/src/ui/themes/types.ts +0 -130
- package/src/utils/clipboard.ts +0 -48
- package/src/utils/debug.ts +0 -43
- package/src/utils/environment.ts +0 -68
- 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';
|