gencode-ai 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +11 -0
- package/CLAUDE.md +70 -0
- package/LICENSE +21 -0
- package/README.md +117 -0
- package/dist/agent/agent.d.ts +84 -0
- package/dist/agent/agent.d.ts.map +1 -0
- package/dist/agent/agent.js +233 -0
- package/dist/agent/agent.js.map +1 -0
- package/dist/agent/index.d.ts +6 -0
- package/dist/agent/index.d.ts.map +1 -0
- package/dist/agent/index.js +6 -0
- package/dist/agent/index.js.map +1 -0
- package/dist/agent/types.d.ts +47 -0
- package/dist/agent/types.d.ts.map +1 -0
- package/dist/agent/types.js +5 -0
- package/dist/agent/types.js.map +1 -0
- package/dist/cli/components/App.d.ts +14 -0
- package/dist/cli/components/App.d.ts.map +1 -0
- package/dist/cli/components/App.js +395 -0
- package/dist/cli/components/App.js.map +1 -0
- package/dist/cli/components/CommandSuggestions.d.ts +13 -0
- package/dist/cli/components/CommandSuggestions.d.ts.map +1 -0
- package/dist/cli/components/CommandSuggestions.js +32 -0
- package/dist/cli/components/CommandSuggestions.js.map +1 -0
- package/dist/cli/components/Header.d.ts +9 -0
- package/dist/cli/components/Header.d.ts.map +1 -0
- package/dist/cli/components/Header.js +13 -0
- package/dist/cli/components/Header.js.map +1 -0
- package/dist/cli/components/Input.d.ts +13 -0
- package/dist/cli/components/Input.d.ts.map +1 -0
- package/dist/cli/components/Input.js +27 -0
- package/dist/cli/components/Input.js.map +1 -0
- package/dist/cli/components/Logo.d.ts +2 -0
- package/dist/cli/components/Logo.d.ts.map +1 -0
- package/dist/cli/components/Logo.js +8 -0
- package/dist/cli/components/Logo.js.map +1 -0
- package/dist/cli/components/Messages.d.ts +37 -0
- package/dist/cli/components/Messages.d.ts.map +1 -0
- package/dist/cli/components/Messages.js +106 -0
- package/dist/cli/components/Messages.js.map +1 -0
- package/dist/cli/components/ModelSelector.d.ts +13 -0
- package/dist/cli/components/ModelSelector.d.ts.map +1 -0
- package/dist/cli/components/ModelSelector.js +72 -0
- package/dist/cli/components/ModelSelector.js.map +1 -0
- package/dist/cli/components/Spinner.d.ts +12 -0
- package/dist/cli/components/Spinner.d.ts.map +1 -0
- package/dist/cli/components/Spinner.js +45 -0
- package/dist/cli/components/Spinner.js.map +1 -0
- package/dist/cli/components/index.d.ts +12 -0
- package/dist/cli/components/index.d.ts.map +1 -0
- package/dist/cli/components/index.js +12 -0
- package/dist/cli/components/index.js.map +1 -0
- package/dist/cli/components/theme.d.ts +31 -0
- package/dist/cli/components/theme.d.ts.map +1 -0
- package/dist/cli/components/theme.js +36 -0
- package/dist/cli/components/theme.js.map +1 -0
- package/dist/cli/index-legacy.d.ts +7 -0
- package/dist/cli/index-legacy.d.ts.map +1 -0
- package/dist/cli/index-legacy.js +431 -0
- package/dist/cli/index-legacy.js.map +1 -0
- package/dist/cli/index.d.ts +7 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +116 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/ink-cli.d.ts +7 -0
- package/dist/cli/ink-cli.d.ts.map +1 -0
- package/dist/cli/ink-cli.js +105 -0
- package/dist/cli/ink-cli.js.map +1 -0
- package/dist/cli/session-picker.d.ts +16 -0
- package/dist/cli/session-picker.d.ts.map +1 -0
- package/dist/cli/session-picker.js +280 -0
- package/dist/cli/session-picker.js.map +1 -0
- package/dist/cli/ui.d.ts +61 -0
- package/dist/cli/ui.d.ts.map +1 -0
- package/dist/cli/ui.js +364 -0
- package/dist/cli/ui.js.map +1 -0
- package/dist/config/index.d.ts +7 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +6 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/manager.d.ts +31 -0
- package/dist/config/manager.d.ts.map +1 -0
- package/dist/config/manager.js +65 -0
- package/dist/config/manager.js.map +1 -0
- package/dist/config/types.d.ts +22 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +6 -0
- package/dist/config/types.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/memory/index.d.ts +10 -0
- package/dist/memory/index.d.ts.map +1 -0
- package/dist/memory/index.js +9 -0
- package/dist/memory/index.js.map +1 -0
- package/dist/memory/init.d.ts +20 -0
- package/dist/memory/init.d.ts.map +1 -0
- package/dist/memory/init.js +332 -0
- package/dist/memory/init.js.map +1 -0
- package/dist/memory/manager.d.ts +85 -0
- package/dist/memory/manager.d.ts.map +1 -0
- package/dist/memory/manager.js +234 -0
- package/dist/memory/manager.js.map +1 -0
- package/dist/memory/types.d.ts +74 -0
- package/dist/memory/types.d.ts.map +1 -0
- package/dist/memory/types.js +6 -0
- package/dist/memory/types.js.map +1 -0
- package/dist/permissions/index.d.ts +7 -0
- package/dist/permissions/index.d.ts.map +1 -0
- package/dist/permissions/index.js +6 -0
- package/dist/permissions/index.js.map +1 -0
- package/dist/permissions/manager.d.ts +32 -0
- package/dist/permissions/manager.d.ts.map +1 -0
- package/dist/permissions/manager.js +79 -0
- package/dist/permissions/manager.js.map +1 -0
- package/dist/permissions/types.d.ts +14 -0
- package/dist/permissions/types.d.ts.map +1 -0
- package/dist/permissions/types.js +17 -0
- package/dist/permissions/types.js.map +1 -0
- package/dist/providers/anthropic.d.ts +20 -0
- package/dist/providers/anthropic.d.ts.map +1 -0
- package/dist/providers/anthropic.js +185 -0
- package/dist/providers/anthropic.js.map +1 -0
- package/dist/providers/gemini.d.ts +21 -0
- package/dist/providers/gemini.d.ts.map +1 -0
- package/dist/providers/gemini.js +241 -0
- package/dist/providers/gemini.js.map +1 -0
- package/dist/providers/index.d.ts +34 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +72 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/openai.d.ts +19 -0
- package/dist/providers/openai.d.ts.map +1 -0
- package/dist/providers/openai.js +221 -0
- package/dist/providers/openai.js.map +1 -0
- package/dist/providers/types.d.ts +125 -0
- package/dist/providers/types.d.ts.map +1 -0
- package/dist/providers/types.js +6 -0
- package/dist/providers/types.js.map +1 -0
- package/dist/session/index.d.ts +6 -0
- package/dist/session/index.d.ts.map +1 -0
- package/dist/session/index.js +6 -0
- package/dist/session/index.js.map +1 -0
- package/dist/session/manager.d.ts +101 -0
- package/dist/session/manager.d.ts.map +1 -0
- package/dist/session/manager.js +295 -0
- package/dist/session/manager.js.map +1 -0
- package/dist/session/types.d.ts +39 -0
- package/dist/session/types.d.ts.map +1 -0
- package/dist/session/types.js +10 -0
- package/dist/session/types.js.map +1 -0
- package/dist/tools/builtin/bash.d.ts +7 -0
- package/dist/tools/builtin/bash.d.ts.map +1 -0
- package/dist/tools/builtin/bash.js +80 -0
- package/dist/tools/builtin/bash.js.map +1 -0
- package/dist/tools/builtin/edit.d.ts +7 -0
- package/dist/tools/builtin/edit.d.ts.map +1 -0
- package/dist/tools/builtin/edit.js +32 -0
- package/dist/tools/builtin/edit.js.map +1 -0
- package/dist/tools/builtin/glob.d.ts +7 -0
- package/dist/tools/builtin/glob.d.ts.map +1 -0
- package/dist/tools/builtin/glob.js +36 -0
- package/dist/tools/builtin/glob.js.map +1 -0
- package/dist/tools/builtin/grep.d.ts +7 -0
- package/dist/tools/builtin/grep.d.ts.map +1 -0
- package/dist/tools/builtin/grep.js +59 -0
- package/dist/tools/builtin/grep.js.map +1 -0
- package/dist/tools/builtin/read.d.ts +7 -0
- package/dist/tools/builtin/read.d.ts.map +1 -0
- package/dist/tools/builtin/read.js +29 -0
- package/dist/tools/builtin/read.js.map +1 -0
- package/dist/tools/builtin/write.d.ts +7 -0
- package/dist/tools/builtin/write.d.ts.map +1 -0
- package/dist/tools/builtin/write.js +24 -0
- package/dist/tools/builtin/write.js.map +1 -0
- package/dist/tools/index.d.ts +38 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +32 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/registry.d.ts +22 -0
- package/dist/tools/registry.d.ts.map +1 -0
- package/dist/tools/registry.js +71 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/types.d.ts +62 -0
- package/dist/tools/types.d.ts.map +1 -0
- package/dist/tools/types.js +126 -0
- package/dist/tools/types.js.map +1 -0
- package/docs/README.md +16 -0
- package/docs/proposals/0001-web-fetch-tool.md +293 -0
- package/docs/proposals/0002-web-search-tool.md +306 -0
- package/docs/proposals/0003-task-subagents.md +333 -0
- package/docs/proposals/0004-plan-mode.md +338 -0
- package/docs/proposals/0005-todo-system.md +299 -0
- package/docs/proposals/0006-memory-system.md +539 -0
- package/docs/proposals/0007-context-management.md +429 -0
- package/docs/proposals/0008-checkpointing.md +327 -0
- package/docs/proposals/0009-hooks-system.md +343 -0
- package/docs/proposals/0010-mcp-integration.md +382 -0
- package/docs/proposals/0011-custom-commands.md +374 -0
- package/docs/proposals/0012-ask-user-question.md +317 -0
- package/docs/proposals/0013-multi-edit-tool.md +345 -0
- package/docs/proposals/0014-lsp-tool.md +478 -0
- package/docs/proposals/0015-ls-tool.md +407 -0
- package/docs/proposals/0016-kill-shell-tool.md +455 -0
- package/docs/proposals/0017-background-tasks.md +489 -0
- package/docs/proposals/0018-parallel-tool-execution.md +415 -0
- package/docs/proposals/0019-session-enhancements.md +462 -0
- package/docs/proposals/0020-session-summarization.md +447 -0
- package/docs/proposals/0021-skills-system.md +409 -0
- package/docs/proposals/0022-plugin-system.md +467 -0
- package/docs/proposals/0023-permission-enhancements.md +470 -0
- package/docs/proposals/0024-keyboard-shortcuts.md +443 -0
- package/docs/proposals/0025-cost-tracking.md +447 -0
- package/docs/proposals/0026-git-integration.md +475 -0
- package/docs/proposals/0027-enhanced-read-tool.md +514 -0
- package/docs/proposals/0028-enhanced-bash-tool.md +511 -0
- package/docs/proposals/0029-notebook-edit-tool.md +413 -0
- package/docs/proposals/0030-plugin-marketplace.md +360 -0
- package/docs/proposals/0031-command-suggestions.md +295 -0
- package/docs/proposals/0032-ide-integrations.md +328 -0
- package/docs/proposals/0033-enterprise-deployment.md +221 -0
- package/docs/proposals/0034-sandboxing.md +273 -0
- package/docs/proposals/0035-auto-updater.md +311 -0
- package/docs/proposals/0036-enhanced-glob-tool.md +267 -0
- package/docs/proposals/0037-enhanced-grep-tool.md +360 -0
- package/docs/proposals/0038-interactive-cli-ui.md +373 -0
- package/docs/proposals/0039-streaming-enhancements.md +359 -0
- package/docs/proposals/0040-multi-provider-enhancements.md +369 -0
- package/docs/proposals/README.md +84 -0
- package/docs/proposals/TEMPLATE.md +57 -0
- package/docs/proposals/research/claude-code-research.md +307 -0
- package/examples/agent-demo.ts +115 -0
- package/examples/basic.ts +166 -0
- package/package.json +50 -0
- package/src/agent/agent.ts +276 -0
- package/src/agent/index.ts +6 -0
- package/src/agent/types.ts +62 -0
- package/src/cli/components/App.tsx +565 -0
- package/src/cli/components/CommandSuggestions.tsx +58 -0
- package/src/cli/components/Header.tsx +36 -0
- package/src/cli/components/Input.tsx +60 -0
- package/src/cli/components/Logo.tsx +16 -0
- package/src/cli/components/Messages.tsx +210 -0
- package/src/cli/components/ModelSelector.tsx +135 -0
- package/src/cli/components/Spinner.tsx +72 -0
- package/src/cli/components/index.ts +21 -0
- package/src/cli/components/theme.ts +36 -0
- package/src/cli/index.tsx +136 -0
- package/src/config/index.ts +7 -0
- package/src/config/manager.ts +77 -0
- package/src/config/types.ts +25 -0
- package/src/index.ts +86 -0
- package/src/permissions/index.ts +7 -0
- package/src/permissions/manager.ts +97 -0
- package/src/permissions/types.ts +29 -0
- package/src/providers/anthropic.ts +224 -0
- package/src/providers/gemini.ts +295 -0
- package/src/providers/index.ts +97 -0
- package/src/providers/openai.ts +261 -0
- package/src/providers/types.ts +181 -0
- package/src/session/index.ts +6 -0
- package/src/session/manager.ts +354 -0
- package/src/session/types.ts +49 -0
- package/src/tools/builtin/bash.ts +92 -0
- package/src/tools/builtin/edit.ts +37 -0
- package/src/tools/builtin/glob.ts +42 -0
- package/src/tools/builtin/grep.ts +67 -0
- package/src/tools/builtin/read.ts +34 -0
- package/src/tools/builtin/write.ts +27 -0
- package/src/tools/index.ts +36 -0
- package/src/tools/registry.ts +83 -0
- package/src/tools/types.ts +172 -0
- package/tsconfig.json +21 -0
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
# Proposal: Streaming Enhancements
|
|
2
|
+
|
|
3
|
+
- **Proposal ID**: 0039
|
|
4
|
+
- **Author**: mycode team
|
|
5
|
+
- **Status**: Draft
|
|
6
|
+
- **Created**: 2025-01-15
|
|
7
|
+
- **Updated**: 2025-01-15
|
|
8
|
+
|
|
9
|
+
## Summary
|
|
10
|
+
|
|
11
|
+
Implement enhanced streaming capabilities for real-time LLM output, progressive tool results, and thinking blocks display, providing immediate feedback during long operations.
|
|
12
|
+
|
|
13
|
+
## Motivation
|
|
14
|
+
|
|
15
|
+
Current output is batch-based:
|
|
16
|
+
|
|
17
|
+
1. **Wait for completion**: No partial results
|
|
18
|
+
2. **No thinking visibility**: Can't see reasoning
|
|
19
|
+
3. **Tool output delayed**: Results only after completion
|
|
20
|
+
4. **Poor latency perception**: Feels slower than it is
|
|
21
|
+
5. **No progressive rendering**: All or nothing
|
|
22
|
+
|
|
23
|
+
Streaming provides real-time feedback and better UX.
|
|
24
|
+
|
|
25
|
+
## Claude Code Reference
|
|
26
|
+
|
|
27
|
+
Claude Code streams responses in real-time:
|
|
28
|
+
|
|
29
|
+
### Observed Features
|
|
30
|
+
- Character-by-character text streaming
|
|
31
|
+
- Thinking blocks display
|
|
32
|
+
- Tool execution progress
|
|
33
|
+
- Progressive code output
|
|
34
|
+
|
|
35
|
+
## Detailed Design
|
|
36
|
+
|
|
37
|
+
### API Design
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
// src/streaming/types.ts
|
|
41
|
+
type StreamEventType =
|
|
42
|
+
| 'text_start'
|
|
43
|
+
| 'text_delta'
|
|
44
|
+
| 'text_end'
|
|
45
|
+
| 'thinking_start'
|
|
46
|
+
| 'thinking_delta'
|
|
47
|
+
| 'thinking_end'
|
|
48
|
+
| 'tool_start'
|
|
49
|
+
| 'tool_progress'
|
|
50
|
+
| 'tool_end'
|
|
51
|
+
| 'code_block_start'
|
|
52
|
+
| 'code_block_delta'
|
|
53
|
+
| 'code_block_end'
|
|
54
|
+
| 'error'
|
|
55
|
+
| 'done';
|
|
56
|
+
|
|
57
|
+
interface StreamEvent {
|
|
58
|
+
type: StreamEventType;
|
|
59
|
+
timestamp: number;
|
|
60
|
+
data: unknown;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
interface TextDeltaEvent extends StreamEvent {
|
|
64
|
+
type: 'text_delta';
|
|
65
|
+
data: {
|
|
66
|
+
text: string;
|
|
67
|
+
index: number;
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
interface ThinkingDeltaEvent extends StreamEvent {
|
|
72
|
+
type: 'thinking_delta';
|
|
73
|
+
data: {
|
|
74
|
+
text: string;
|
|
75
|
+
summary?: string;
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
interface ToolProgressEvent extends StreamEvent {
|
|
80
|
+
type: 'tool_progress';
|
|
81
|
+
data: {
|
|
82
|
+
toolName: string;
|
|
83
|
+
progress: number; // 0-100
|
|
84
|
+
message: string;
|
|
85
|
+
output?: string; // Partial output
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
interface StreamConfig {
|
|
90
|
+
showThinking: boolean;
|
|
91
|
+
thinkingCollapsed: boolean;
|
|
92
|
+
smoothScroll: boolean;
|
|
93
|
+
bufferSize: number;
|
|
94
|
+
renderDelay: number; // ms between renders
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Stream Renderer
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
// src/streaming/renderer.ts
|
|
102
|
+
class StreamRenderer {
|
|
103
|
+
private config: StreamConfig;
|
|
104
|
+
private buffer: string = '';
|
|
105
|
+
private currentBlock: BlockType | null = null;
|
|
106
|
+
private thinkingVisible: boolean = false;
|
|
107
|
+
|
|
108
|
+
constructor(config?: Partial<StreamConfig>) {
|
|
109
|
+
this.config = {
|
|
110
|
+
showThinking: true,
|
|
111
|
+
thinkingCollapsed: true,
|
|
112
|
+
smoothScroll: true,
|
|
113
|
+
bufferSize: 100,
|
|
114
|
+
renderDelay: 16, // ~60fps
|
|
115
|
+
...config
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
async *render(events: AsyncGenerator<StreamEvent>): AsyncGenerator<string> {
|
|
120
|
+
for await (const event of events) {
|
|
121
|
+
yield* this.processEvent(event);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Flush remaining buffer
|
|
125
|
+
if (this.buffer) {
|
|
126
|
+
yield this.buffer;
|
|
127
|
+
this.buffer = '';
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
private *processEvent(event: StreamEvent): Generator<string> {
|
|
132
|
+
switch (event.type) {
|
|
133
|
+
case 'text_delta':
|
|
134
|
+
yield* this.renderTextDelta(event as TextDeltaEvent);
|
|
135
|
+
break;
|
|
136
|
+
|
|
137
|
+
case 'thinking_start':
|
|
138
|
+
yield* this.renderThinkingStart();
|
|
139
|
+
break;
|
|
140
|
+
|
|
141
|
+
case 'thinking_delta':
|
|
142
|
+
yield* this.renderThinkingDelta(event as ThinkingDeltaEvent);
|
|
143
|
+
break;
|
|
144
|
+
|
|
145
|
+
case 'thinking_end':
|
|
146
|
+
yield* this.renderThinkingEnd();
|
|
147
|
+
break;
|
|
148
|
+
|
|
149
|
+
case 'tool_start':
|
|
150
|
+
yield* this.renderToolStart(event);
|
|
151
|
+
break;
|
|
152
|
+
|
|
153
|
+
case 'tool_progress':
|
|
154
|
+
yield* this.renderToolProgress(event as ToolProgressEvent);
|
|
155
|
+
break;
|
|
156
|
+
|
|
157
|
+
case 'tool_end':
|
|
158
|
+
yield* this.renderToolEnd(event);
|
|
159
|
+
break;
|
|
160
|
+
|
|
161
|
+
case 'code_block_start':
|
|
162
|
+
yield* this.renderCodeBlockStart(event);
|
|
163
|
+
break;
|
|
164
|
+
|
|
165
|
+
case 'code_block_delta':
|
|
166
|
+
yield* this.renderCodeBlockDelta(event);
|
|
167
|
+
break;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
private *renderTextDelta(event: TextDeltaEvent): Generator<string> {
|
|
172
|
+
this.buffer += event.data.text;
|
|
173
|
+
|
|
174
|
+
// Flush buffer at word boundaries or when large
|
|
175
|
+
if (this.buffer.includes(' ') || this.buffer.length > this.config.bufferSize) {
|
|
176
|
+
const lastSpace = this.buffer.lastIndexOf(' ');
|
|
177
|
+
const toRender = lastSpace > 0
|
|
178
|
+
? this.buffer.slice(0, lastSpace + 1)
|
|
179
|
+
: this.buffer;
|
|
180
|
+
this.buffer = lastSpace > 0
|
|
181
|
+
? this.buffer.slice(lastSpace + 1)
|
|
182
|
+
: '';
|
|
183
|
+
yield toRender;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
private *renderThinkingStart(): Generator<string> {
|
|
188
|
+
if (!this.config.showThinking) return;
|
|
189
|
+
|
|
190
|
+
this.thinkingVisible = true;
|
|
191
|
+
if (this.config.thinkingCollapsed) {
|
|
192
|
+
yield chalk.gray('💭 Thinking...\n');
|
|
193
|
+
} else {
|
|
194
|
+
yield chalk.gray('┌─ Thinking ─────────────────────────────\n');
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
private *renderThinkingDelta(event: ThinkingDeltaEvent): Generator<string> {
|
|
199
|
+
if (!this.config.showThinking || this.config.thinkingCollapsed) return;
|
|
200
|
+
|
|
201
|
+
yield chalk.gray(`│ ${event.data.text}`);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
private *renderThinkingEnd(): Generator<string> {
|
|
205
|
+
if (!this.config.showThinking) return;
|
|
206
|
+
|
|
207
|
+
this.thinkingVisible = false;
|
|
208
|
+
if (!this.config.thinkingCollapsed) {
|
|
209
|
+
yield chalk.gray('└────────────────────────────────────────\n');
|
|
210
|
+
}
|
|
211
|
+
yield '\n';
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
private *renderToolProgress(event: ToolProgressEvent): Generator<string> {
|
|
215
|
+
const { toolName, progress, message, output } = event.data;
|
|
216
|
+
|
|
217
|
+
// Clear previous progress line and redraw
|
|
218
|
+
yield '\r\x1b[K'; // Clear line
|
|
219
|
+
|
|
220
|
+
const bar = this.progressBar(progress, 20);
|
|
221
|
+
yield chalk.cyan(`[${toolName}] ${bar} ${progress}% ${message}`);
|
|
222
|
+
|
|
223
|
+
if (output) {
|
|
224
|
+
yield '\n' + chalk.gray(output);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
private progressBar(percent: number, width: number): string {
|
|
229
|
+
const filled = Math.round((percent / 100) * width);
|
|
230
|
+
const empty = width - filled;
|
|
231
|
+
return chalk.green('█'.repeat(filled)) + chalk.gray('░'.repeat(empty));
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
export const streamRenderer = new StreamRenderer();
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### Provider Streaming Integration
|
|
239
|
+
|
|
240
|
+
```typescript
|
|
241
|
+
// Update to src/providers/types.ts
|
|
242
|
+
interface LLMProvider {
|
|
243
|
+
name: string;
|
|
244
|
+
complete(request: CompletionRequest): Promise<CompletionResponse>;
|
|
245
|
+
stream(request: CompletionRequest): AsyncGenerator<StreamEvent>;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// Example Anthropic streaming
|
|
249
|
+
async function* streamAnthropic(request: CompletionRequest): AsyncGenerator<StreamEvent> {
|
|
250
|
+
const response = await anthropic.messages.create({
|
|
251
|
+
...request,
|
|
252
|
+
stream: true
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
for await (const event of response) {
|
|
256
|
+
switch (event.type) {
|
|
257
|
+
case 'content_block_start':
|
|
258
|
+
if (event.content_block.type === 'thinking') {
|
|
259
|
+
yield { type: 'thinking_start', timestamp: Date.now(), data: {} };
|
|
260
|
+
}
|
|
261
|
+
break;
|
|
262
|
+
|
|
263
|
+
case 'content_block_delta':
|
|
264
|
+
if (event.delta.type === 'thinking_delta') {
|
|
265
|
+
yield {
|
|
266
|
+
type: 'thinking_delta',
|
|
267
|
+
timestamp: Date.now(),
|
|
268
|
+
data: { text: event.delta.thinking }
|
|
269
|
+
};
|
|
270
|
+
} else if (event.delta.type === 'text_delta') {
|
|
271
|
+
yield {
|
|
272
|
+
type: 'text_delta',
|
|
273
|
+
timestamp: Date.now(),
|
|
274
|
+
data: { text: event.delta.text, index: 0 }
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
break;
|
|
278
|
+
|
|
279
|
+
case 'content_block_stop':
|
|
280
|
+
if (currentBlock === 'thinking') {
|
|
281
|
+
yield { type: 'thinking_end', timestamp: Date.now(), data: {} };
|
|
282
|
+
}
|
|
283
|
+
break;
|
|
284
|
+
|
|
285
|
+
case 'message_stop':
|
|
286
|
+
yield { type: 'done', timestamp: Date.now(), data: {} };
|
|
287
|
+
break;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
### File Changes
|
|
294
|
+
|
|
295
|
+
| File | Action | Description |
|
|
296
|
+
|------|--------|-------------|
|
|
297
|
+
| `src/streaming/types.ts` | Create | Type definitions |
|
|
298
|
+
| `src/streaming/renderer.ts` | Create | Stream rendering |
|
|
299
|
+
| `src/streaming/buffer.ts` | Create | Output buffering |
|
|
300
|
+
| `src/streaming/index.ts` | Create | Module exports |
|
|
301
|
+
| `src/providers/*.ts` | Modify | Add streaming support |
|
|
302
|
+
| `src/agent/agent.ts` | Modify | Use streaming |
|
|
303
|
+
| `src/cli/index.ts` | Modify | Render streams |
|
|
304
|
+
|
|
305
|
+
## User Experience
|
|
306
|
+
|
|
307
|
+
### Real-time Text Streaming
|
|
308
|
+
```
|
|
309
|
+
Agent: Let me analyze this code to understand
|
|
310
|
+
the authentication flow. The AuthService
|
|
311
|
+
class handles token validation and...█
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
### Thinking Block Display
|
|
315
|
+
```
|
|
316
|
+
💭 Thinking...
|
|
317
|
+
|
|
318
|
+
Agent: Based on my analysis, here are the key points...
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
### Expanded Thinking
|
|
322
|
+
```
|
|
323
|
+
┌─ Thinking ─────────────────────────────
|
|
324
|
+
│ First, I need to understand the current
|
|
325
|
+
│ authentication implementation. Looking at
|
|
326
|
+
│ the AuthService class...
|
|
327
|
+
│
|
|
328
|
+
│ The token validation uses JWT with HS256.
|
|
329
|
+
│ This could be improved by using RS256...
|
|
330
|
+
└────────────────────────────────────────
|
|
331
|
+
|
|
332
|
+
Agent: Based on my analysis...
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
### Tool Progress
|
|
336
|
+
```
|
|
337
|
+
[Bash] ████████░░░░░░░░░░░░ 40% Installing dependencies...
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
## Security Considerations
|
|
341
|
+
|
|
342
|
+
1. Buffer overflow prevention
|
|
343
|
+
2. Rate limiting output
|
|
344
|
+
3. Terminal escape sequence sanitization
|
|
345
|
+
4. Memory management for long streams
|
|
346
|
+
|
|
347
|
+
## Migration Path
|
|
348
|
+
|
|
349
|
+
1. **Phase 1**: Basic text streaming
|
|
350
|
+
2. **Phase 2**: Tool progress
|
|
351
|
+
3. **Phase 3**: Thinking blocks
|
|
352
|
+
4. **Phase 4**: Code block highlighting
|
|
353
|
+
5. **Phase 5**: Performance optimization
|
|
354
|
+
|
|
355
|
+
## References
|
|
356
|
+
|
|
357
|
+
- [Anthropic Streaming API](https://docs.anthropic.com/claude/reference/messages-streaming)
|
|
358
|
+
- [OpenAI Streaming](https://platform.openai.com/docs/api-reference/streaming)
|
|
359
|
+
- [Terminal Control Sequences](https://en.wikipedia.org/wiki/ANSI_escape_code)
|