gencode-ai 0.3.0 → 0.4.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/RELEASE_NOTES_v0.4.0.md +140 -0
- package/dist/agent/agent.d.ts +17 -2
- package/dist/agent/agent.d.ts.map +1 -1
- package/dist/agent/agent.js +279 -49
- package/dist/agent/agent.js.map +1 -1
- package/dist/agent/types.d.ts +15 -1
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/checkpointing/checkpoint-manager.d.ts +24 -0
- package/dist/checkpointing/checkpoint-manager.d.ts.map +1 -1
- package/dist/checkpointing/checkpoint-manager.js +28 -0
- package/dist/checkpointing/checkpoint-manager.js.map +1 -1
- package/dist/cli/components/App.d.ts +8 -0
- package/dist/cli/components/App.d.ts.map +1 -1
- package/dist/cli/components/App.js +478 -36
- package/dist/cli/components/App.js.map +1 -1
- package/dist/cli/components/CommandSuggestions.d.ts.map +1 -1
- package/dist/cli/components/CommandSuggestions.js +2 -0
- package/dist/cli/components/CommandSuggestions.js.map +1 -1
- package/dist/cli/components/Header.d.ts +6 -1
- package/dist/cli/components/Header.d.ts.map +1 -1
- package/dist/cli/components/Header.js +3 -3
- package/dist/cli/components/Header.js.map +1 -1
- package/dist/cli/components/Messages.d.ts.map +1 -1
- package/dist/cli/components/Messages.js +7 -9
- package/dist/cli/components/Messages.js.map +1 -1
- package/dist/cli/index.js +3 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/config/types.d.ts +20 -1
- package/dist/config/types.d.ts.map +1 -1
- package/dist/config/types.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/input/history-manager.d.ts +78 -0
- package/dist/input/history-manager.d.ts.map +1 -0
- package/dist/input/history-manager.js +224 -0
- package/dist/input/history-manager.js.map +1 -0
- package/dist/input/index.d.ts +6 -0
- package/dist/input/index.d.ts.map +1 -0
- package/dist/input/index.js +5 -0
- package/dist/input/index.js.map +1 -0
- package/dist/prompts/index.js +3 -3
- package/dist/prompts/index.js.map +1 -1
- package/dist/providers/gemini.d.ts.map +1 -1
- package/dist/providers/gemini.js +33 -2
- package/dist/providers/gemini.js.map +1 -1
- package/dist/providers/google.d.ts +22 -0
- package/dist/providers/google.d.ts.map +1 -0
- package/dist/providers/google.js +297 -0
- package/dist/providers/google.js.map +1 -0
- package/dist/providers/index.d.ts +4 -4
- package/dist/providers/index.js +11 -11
- package/dist/providers/index.js.map +1 -1
- package/dist/providers/openai.d.ts.map +1 -1
- package/dist/providers/openai.js +6 -0
- package/dist/providers/openai.js.map +1 -1
- package/dist/providers/registry.js +3 -3
- package/dist/providers/registry.js.map +1 -1
- package/dist/providers/types.d.ts +30 -4
- package/dist/providers/types.d.ts.map +1 -1
- package/dist/session/compression/engine.d.ts +109 -0
- package/dist/session/compression/engine.d.ts.map +1 -0
- package/dist/session/compression/engine.js +311 -0
- package/dist/session/compression/engine.js.map +1 -0
- package/dist/session/compression/index.d.ts +12 -0
- package/dist/session/compression/index.d.ts.map +1 -0
- package/dist/session/compression/index.js +11 -0
- package/dist/session/compression/index.js.map +1 -0
- package/dist/session/compression/types.d.ts +90 -0
- package/dist/session/compression/types.d.ts.map +1 -0
- package/dist/session/compression/types.js +17 -0
- package/dist/session/compression/types.js.map +1 -0
- package/dist/session/manager.d.ts +64 -3
- package/dist/session/manager.d.ts.map +1 -1
- package/dist/session/manager.js +254 -2
- package/dist/session/manager.js.map +1 -1
- package/dist/session/types.d.ts +16 -0
- package/dist/session/types.d.ts.map +1 -1
- package/dist/session/types.js.map +1 -1
- package/docs/README.md +1 -0
- package/docs/diagrams/compression-decision.mmd +30 -0
- package/docs/diagrams/compression-workflow.mmd +54 -0
- package/docs/diagrams/layer1-pruning.mmd +45 -0
- package/docs/diagrams/layer2-compaction.mmd +42 -0
- package/docs/proposals/0007-context-management.md +252 -2
- package/docs/proposals/README.md +4 -3
- package/docs/providers.md +3 -3
- package/docs/session-compression.md +695 -0
- package/examples/agent-demo.ts +23 -1
- package/examples/basic.ts +3 -3
- package/package.json +3 -4
- package/src/agent/agent.ts +314 -52
- package/src/agent/types.ts +19 -1
- package/src/checkpointing/checkpoint-manager.ts +48 -0
- package/src/cli/components/App.tsx +553 -34
- package/src/cli/components/CommandSuggestions.tsx +2 -0
- package/src/cli/components/Header.tsx +16 -1
- package/src/cli/components/Messages.tsx +20 -14
- package/src/cli/index.tsx +3 -2
- package/src/config/types.ts +26 -1
- package/src/index.ts +3 -3
- package/src/input/history-manager.ts +289 -0
- package/src/input/index.ts +6 -0
- package/src/prompts/index.test.ts +2 -1
- package/src/prompts/index.ts +3 -3
- package/src/providers/{gemini.ts → google.ts} +69 -18
- package/src/providers/index.ts +14 -14
- package/src/providers/openai.ts +7 -0
- package/src/providers/registry.ts +3 -3
- package/src/providers/types.ts +33 -3
- package/src/session/compression/engine.ts +406 -0
- package/src/session/compression/index.ts +18 -0
- package/src/session/compression/types.ts +102 -0
- package/src/session/manager.ts +326 -3
- package/src/session/types.ts +21 -0
- package/tests/input-history-manager.test.ts +335 -0
- package/tests/session-checkpoint-persistence.test.ts +198 -0
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# Release Notes - v0.4.0
|
|
2
|
+
|
|
3
|
+
## 🔄 Breaking Changes
|
|
4
|
+
|
|
5
|
+
### Provider Rename: Gemini → Google
|
|
6
|
+
|
|
7
|
+
We've renamed the "Gemini" provider to "Google" for better naming consistency.
|
|
8
|
+
|
|
9
|
+
**Rationale:**
|
|
10
|
+
- Provider = Company (Google, OpenAI, Anthropic)
|
|
11
|
+
- Model = Product (Gemini, GPT, Claude)
|
|
12
|
+
- Aligns with industry naming patterns
|
|
13
|
+
|
|
14
|
+
**Changes:**
|
|
15
|
+
- Provider ID: `'gemini'` → `'google'`
|
|
16
|
+
- TypeScript: `GeminiProvider` → `GoogleProvider`, `GeminiConfig` → `GoogleConfig`
|
|
17
|
+
|
|
18
|
+
**Unchanged:**
|
|
19
|
+
- ✅ Model names: `gemini-2.0-flash`, `gemini-1.5-pro`, etc.
|
|
20
|
+
- ✅ Environment variables: `GOOGLE_API_KEY` and `GEMINI_API_KEY` both supported
|
|
21
|
+
- ✅ All functionality identical
|
|
22
|
+
|
|
23
|
+
### Migration Required
|
|
24
|
+
|
|
25
|
+
**Automatic Migration (Recommended):**
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
# macOS
|
|
29
|
+
sed -i '' 's/"gemini":/"google":/g' ~/.gen/providers.json
|
|
30
|
+
sed -i '' 's/"gemini:/"google:/g' ~/.gen/providers.json
|
|
31
|
+
sed -i '' 's/"provider": "gemini"/"provider": "google"/g' ~/.gen/settings.json
|
|
32
|
+
|
|
33
|
+
# Linux
|
|
34
|
+
sed -i 's/"gemini":/"google":/g' ~/.gen/providers.json
|
|
35
|
+
sed -i 's/"gemini:/"google:/g' ~/.gen/providers.json
|
|
36
|
+
sed -i 's/"provider": "gemini"/"provider": "google"/g' ~/.gen/settings.json
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
**Manual Migration:**
|
|
40
|
+
|
|
41
|
+
1. **`~/.gen/settings.json`**: Change `"provider": "gemini"` → `"provider": "google"`
|
|
42
|
+
2. **`~/.gen/providers.json`**:
|
|
43
|
+
- Rename connection: `"gemini": {...}` → `"google": {...}`
|
|
44
|
+
- Rename model cache: `"gemini:api_key": {...}` → `"google:api_key": {...}`
|
|
45
|
+
|
|
46
|
+
**For SDK Users:**
|
|
47
|
+
|
|
48
|
+
```typescript
|
|
49
|
+
// Before
|
|
50
|
+
import { GeminiProvider, type GeminiConfig } from 'gencode-ai';
|
|
51
|
+
const provider = new GeminiProvider();
|
|
52
|
+
|
|
53
|
+
// After
|
|
54
|
+
import { GoogleProvider, type GoogleConfig } from 'gencode-ai';
|
|
55
|
+
const provider = new GoogleProvider();
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## ✨ New Features
|
|
61
|
+
|
|
62
|
+
### Context Management (Proposal 0007)
|
|
63
|
+
Manual control over conversation context with new CLI commands:
|
|
64
|
+
|
|
65
|
+
- **`/compact`** - Trigger conversation compaction manually
|
|
66
|
+
- Summarizes older messages to reduce context
|
|
67
|
+
- Shows before/after statistics
|
|
68
|
+
|
|
69
|
+
- **`/context`** - View context usage statistics
|
|
70
|
+
- Active vs total messages
|
|
71
|
+
- Compression status
|
|
72
|
+
- Visual progress indicator
|
|
73
|
+
|
|
74
|
+
### Checkpoint Persistence (Proposal 0008)
|
|
75
|
+
Fixed critical persistence bug:
|
|
76
|
+
|
|
77
|
+
- ✅ Checkpoints saved to disk with sessions
|
|
78
|
+
- ✅ Restored when resuming sessions
|
|
79
|
+
- ✅ Preserved when forking sessions
|
|
80
|
+
- ✅ Session compression works across restarts
|
|
81
|
+
|
|
82
|
+
### Gemini 3+ Thinking Support
|
|
83
|
+
Added support for Gemini 3+ model reasoning:
|
|
84
|
+
|
|
85
|
+
- Captures `thoughtSignature` from Gemini 3+ models
|
|
86
|
+
- Streams reasoning chunks with `type: 'reasoning'`
|
|
87
|
+
- Preserves thinking process in tool calls
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## 🐛 Bug Fixes
|
|
92
|
+
|
|
93
|
+
- Fixed checkpoint data not persisting across session restarts
|
|
94
|
+
- Fixed provider display name for Google in registry
|
|
95
|
+
- Improved error messages for unknown provider IDs
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## 📚 Documentation
|
|
100
|
+
|
|
101
|
+
- Added session compression implementation guide with flowcharts
|
|
102
|
+
- Updated provider documentation for Google rename
|
|
103
|
+
- Added migration guide for breaking changes
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## 🧹 Housekeeping
|
|
108
|
+
|
|
109
|
+
- Removed temporary test scripts and documentation
|
|
110
|
+
- Cleaned up code comments and logging
|
|
111
|
+
- Improved checkpoint serialization logic
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## 📦 Installation
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
# New installation
|
|
119
|
+
npm install -g gencode-ai@0.4.0
|
|
120
|
+
|
|
121
|
+
# Update from v0.3.x
|
|
122
|
+
npm update -g gencode-ai
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## ⚠️ Important Notes
|
|
128
|
+
|
|
129
|
+
- **Breaking changes** - Follow migration guide above
|
|
130
|
+
- **Backup recommended** - Back up `~/.gen/` before upgrading
|
|
131
|
+
- **Config update required** - Use migration script or update manually
|
|
132
|
+
- **SDK users** - Update imports from `GeminiProvider` to `GoogleProvider`
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## 🔗 Links
|
|
137
|
+
|
|
138
|
+
- [Full Changelog](https://github.com/your-repo/gencode/compare/v0.3.0...v0.4.0)
|
|
139
|
+
- [Documentation](https://github.com/your-repo/gencode/docs)
|
|
140
|
+
- [Report Issues](https://github.com/your-repo/gencode/issues)
|
package/dist/agent/agent.d.ts
CHANGED
|
@@ -17,7 +17,6 @@ export declare class Agent {
|
|
|
17
17
|
private memoryManager;
|
|
18
18
|
private planModeManager;
|
|
19
19
|
private config;
|
|
20
|
-
private messages;
|
|
21
20
|
private sessionId;
|
|
22
21
|
private loadedMemory;
|
|
23
22
|
private askUserCallback;
|
|
@@ -119,6 +118,13 @@ export declare class Agent {
|
|
|
119
118
|
* Get current provider
|
|
120
119
|
*/
|
|
121
120
|
getProvider(): Provider;
|
|
121
|
+
/**
|
|
122
|
+
* Get model information for compression
|
|
123
|
+
*/
|
|
124
|
+
getModelInfo(): {
|
|
125
|
+
contextWindow: number;
|
|
126
|
+
outputLimit?: number;
|
|
127
|
+
};
|
|
122
128
|
/**
|
|
123
129
|
* List available models from the provider API
|
|
124
130
|
*/
|
|
@@ -157,7 +163,7 @@ export declare class Agent {
|
|
|
157
163
|
/**
|
|
158
164
|
* Run a single query through the agent
|
|
159
165
|
*/
|
|
160
|
-
run(prompt: string): AsyncGenerator<AgentEvent, void, unknown>;
|
|
166
|
+
run(prompt: string, signal?: AbortSignal): AsyncGenerator<AgentEvent, void, unknown>;
|
|
161
167
|
/**
|
|
162
168
|
* Clear conversation history
|
|
163
169
|
*/
|
|
@@ -171,5 +177,14 @@ export declare class Agent {
|
|
|
171
177
|
* Get conversation history
|
|
172
178
|
*/
|
|
173
179
|
getHistory(): Message[];
|
|
180
|
+
/**
|
|
181
|
+
* Get compression statistics
|
|
182
|
+
*/
|
|
183
|
+
getCompressionStats(): {
|
|
184
|
+
totalMessages: number;
|
|
185
|
+
activeMessages: number;
|
|
186
|
+
summaryCount: number;
|
|
187
|
+
compressionRatio: number;
|
|
188
|
+
} | null;
|
|
174
189
|
}
|
|
175
190
|
//# sourceMappingURL=agent.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/agent/agent.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAe,OAAO,EAAqB,QAAQ,EAAc,MAAM,uBAAuB,CAAC;AAG3G,OAAO,EACL,iBAAiB,EACjB,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACxB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACtE,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE1D,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAClE,OAAO,EAEL,KAAK,eAAe,EACpB,KAAK,QAAQ,EACb,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/agent/agent.ts"],"names":[],"mappings":"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"}
|
package/dist/agent/agent.js
CHANGED
|
@@ -8,6 +8,7 @@ import { SessionManager } from '../session/index.js';
|
|
|
8
8
|
import { MemoryManager } from '../memory/index.js';
|
|
9
9
|
import { buildSystemPromptForModel, debugPromptLoading } from '../prompts/index.js';
|
|
10
10
|
import { getPlanModeManager, } from '../planning/index.js';
|
|
11
|
+
import { initCheckpointManager } from '../checkpointing/index.js';
|
|
11
12
|
export class Agent {
|
|
12
13
|
provider;
|
|
13
14
|
registry;
|
|
@@ -16,7 +17,6 @@ export class Agent {
|
|
|
16
17
|
memoryManager;
|
|
17
18
|
planModeManager;
|
|
18
19
|
config;
|
|
19
|
-
messages = [];
|
|
20
20
|
sessionId = null;
|
|
21
21
|
loadedMemory = null;
|
|
22
22
|
askUserCallback = null;
|
|
@@ -35,9 +35,13 @@ export class Agent {
|
|
|
35
35
|
config: config.permissions,
|
|
36
36
|
projectPath: config.cwd,
|
|
37
37
|
});
|
|
38
|
-
this.sessionManager = new SessionManager(
|
|
38
|
+
this.sessionManager = new SessionManager({
|
|
39
|
+
compression: config.compression,
|
|
40
|
+
});
|
|
39
41
|
this.memoryManager = new MemoryManager();
|
|
40
42
|
this.planModeManager = getPlanModeManager();
|
|
43
|
+
// Set compression engine with current model
|
|
44
|
+
this.sessionManager.setCompressionEngine(this.provider, this.config.model);
|
|
41
45
|
}
|
|
42
46
|
/**
|
|
43
47
|
* Initialize permission system (load persisted rules)
|
|
@@ -215,6 +219,8 @@ export class Agent {
|
|
|
215
219
|
provider: newProvider,
|
|
216
220
|
authMethod: newAuthMethod,
|
|
217
221
|
});
|
|
222
|
+
// Update compression engine with new provider and model
|
|
223
|
+
this.sessionManager.setCompressionEngine(this.provider, model);
|
|
218
224
|
}
|
|
219
225
|
}
|
|
220
226
|
/**
|
|
@@ -229,6 +235,32 @@ export class Agent {
|
|
|
229
235
|
getProvider() {
|
|
230
236
|
return this.config.provider;
|
|
231
237
|
}
|
|
238
|
+
/**
|
|
239
|
+
* Get model information for compression
|
|
240
|
+
*/
|
|
241
|
+
getModelInfo() {
|
|
242
|
+
// Try to get from provider if available
|
|
243
|
+
if (this.provider.getModelInfo) {
|
|
244
|
+
const info = this.provider.getModelInfo(this.config.model);
|
|
245
|
+
if (info.contextWindow) {
|
|
246
|
+
return { contextWindow: info.contextWindow, outputLimit: info.outputLimit };
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
// Fallback: rough estimates based on model name
|
|
250
|
+
// These should eventually be moved to provider implementations
|
|
251
|
+
const model = this.config.model.toLowerCase();
|
|
252
|
+
if (model.includes('claude')) {
|
|
253
|
+
return { contextWindow: 200_000, outputLimit: 8192 };
|
|
254
|
+
}
|
|
255
|
+
if (model.includes('gpt-4') || model.includes('gpt-3.5')) {
|
|
256
|
+
return { contextWindow: 128_000, outputLimit: 4096 };
|
|
257
|
+
}
|
|
258
|
+
if (model.includes('gemini')) {
|
|
259
|
+
return { contextWindow: 1_000_000, outputLimit: 8192 };
|
|
260
|
+
}
|
|
261
|
+
// Default fallback
|
|
262
|
+
return { contextWindow: 128_000, outputLimit: 4096 };
|
|
263
|
+
}
|
|
232
264
|
/**
|
|
233
265
|
* List available models from the provider API
|
|
234
266
|
*/
|
|
@@ -246,7 +278,8 @@ export class Agent {
|
|
|
246
278
|
title,
|
|
247
279
|
});
|
|
248
280
|
this.sessionId = session.metadata.id;
|
|
249
|
-
this
|
|
281
|
+
// Initialize checkpoint manager for this session
|
|
282
|
+
initCheckpointManager(this.sessionId);
|
|
250
283
|
return this.sessionId;
|
|
251
284
|
}
|
|
252
285
|
/**
|
|
@@ -258,7 +291,8 @@ export class Agent {
|
|
|
258
291
|
return false;
|
|
259
292
|
}
|
|
260
293
|
this.sessionId = session.metadata.id;
|
|
261
|
-
|
|
294
|
+
// CheckpointManager already restored by SessionManager.load()
|
|
295
|
+
// No need to call initCheckpointManager again
|
|
262
296
|
return true;
|
|
263
297
|
}
|
|
264
298
|
/**
|
|
@@ -270,7 +304,8 @@ export class Agent {
|
|
|
270
304
|
return false;
|
|
271
305
|
}
|
|
272
306
|
this.sessionId = session.metadata.id;
|
|
273
|
-
|
|
307
|
+
// CheckpointManager already restored by SessionManager.load()
|
|
308
|
+
// No need to call initCheckpointManager again
|
|
274
309
|
return true;
|
|
275
310
|
}
|
|
276
311
|
/**
|
|
@@ -302,26 +337,47 @@ export class Agent {
|
|
|
302
337
|
async saveSession() {
|
|
303
338
|
const current = this.sessionManager.getCurrent();
|
|
304
339
|
if (current) {
|
|
305
|
-
current.messages = this.messages;
|
|
306
340
|
await this.sessionManager.save(current);
|
|
307
341
|
}
|
|
308
342
|
}
|
|
309
343
|
/**
|
|
310
344
|
* Run a single query through the agent
|
|
311
345
|
*/
|
|
312
|
-
async *run(prompt) {
|
|
346
|
+
async *run(prompt, signal) {
|
|
347
|
+
// Check for abort before starting
|
|
348
|
+
if (signal?.aborted) {
|
|
349
|
+
yield { type: 'error', error: new Error('Operation cancelled') };
|
|
350
|
+
return;
|
|
351
|
+
}
|
|
313
352
|
// Auto-create session if none exists
|
|
314
|
-
|
|
315
|
-
|
|
353
|
+
try {
|
|
354
|
+
if (!this.sessionId) {
|
|
355
|
+
await this.startSession();
|
|
356
|
+
}
|
|
357
|
+
// Load memory if not already loaded
|
|
358
|
+
if (!this.loadedMemory) {
|
|
359
|
+
await this.loadMemory();
|
|
360
|
+
}
|
|
316
361
|
}
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
362
|
+
catch (error) {
|
|
363
|
+
yield {
|
|
364
|
+
type: 'error',
|
|
365
|
+
error: error instanceof Error ? error : new Error(String(error))
|
|
366
|
+
};
|
|
367
|
+
return;
|
|
320
368
|
}
|
|
321
369
|
// Add user message
|
|
322
370
|
const userMessage = { role: 'user', content: prompt };
|
|
323
|
-
|
|
324
|
-
|
|
371
|
+
try {
|
|
372
|
+
await this.sessionManager.addMessage(userMessage, this.getModelInfo());
|
|
373
|
+
}
|
|
374
|
+
catch (error) {
|
|
375
|
+
yield {
|
|
376
|
+
type: 'error',
|
|
377
|
+
error: new Error(`Failed to save user message: ${error instanceof Error ? error.message : String(error)}`)
|
|
378
|
+
};
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
325
381
|
let turns = 0;
|
|
326
382
|
const maxTurns = this.config.maxTurns ?? 10;
|
|
327
383
|
while (turns < maxTurns) {
|
|
@@ -330,6 +386,9 @@ export class Agent {
|
|
|
330
386
|
const toolDefs = this.registry.getFilteredDefinitions(this.config.tools);
|
|
331
387
|
// Call LLM
|
|
332
388
|
let response;
|
|
389
|
+
const processingStartTime = Date.now();
|
|
390
|
+
// Determine if streaming is enabled
|
|
391
|
+
const useStreaming = process.env.GEN_STREAM === '1' || this.config.streaming;
|
|
333
392
|
try {
|
|
334
393
|
// Debug prompt loading (enabled with GENCODE_DEBUG_PROMPTS=1)
|
|
335
394
|
debugPromptLoading(this.config.model, this.config.provider);
|
|
@@ -339,35 +398,179 @@ export class Agent {
|
|
|
339
398
|
buildSystemPromptForModel(this.config.model, this.config.cwd ?? process.cwd(), true, // Assume git repo for now
|
|
340
399
|
this.loadedMemory?.context, this.config.provider // Fallback provider if model lookup fails
|
|
341
400
|
);
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
401
|
+
if (useStreaming) {
|
|
402
|
+
// === STREAMING PATH ===
|
|
403
|
+
// Build response incrementally from stream chunks
|
|
404
|
+
const responseBuilder = {
|
|
405
|
+
content: [],
|
|
406
|
+
textBuffer: '',
|
|
407
|
+
toolCalls: new Map(),
|
|
408
|
+
stopReason: 'end_turn',
|
|
409
|
+
usage: undefined,
|
|
410
|
+
cost: undefined,
|
|
411
|
+
};
|
|
412
|
+
// Process stream chunks
|
|
413
|
+
for await (const chunk of this.provider.stream({
|
|
414
|
+
model: this.config.model,
|
|
415
|
+
messages: this.sessionManager.getMessagesForLLM(),
|
|
416
|
+
tools: toolDefs,
|
|
417
|
+
systemPrompt,
|
|
418
|
+
maxTokens: 4096,
|
|
419
|
+
signal, // Pass abort signal for cancellation
|
|
420
|
+
})) {
|
|
421
|
+
// Check for abort
|
|
422
|
+
if (signal?.aborted) {
|
|
423
|
+
yield { type: 'error', error: new Error('Operation cancelled by user') };
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
426
|
+
switch (chunk.type) {
|
|
427
|
+
case 'text':
|
|
428
|
+
// Accumulate text and yield immediately for real-time display
|
|
429
|
+
responseBuilder.textBuffer += chunk.text;
|
|
430
|
+
yield { type: 'text', text: chunk.text };
|
|
431
|
+
break;
|
|
432
|
+
case 'reasoning':
|
|
433
|
+
// Forward reasoning content (o1/o3/Gemini 3+ thinking)
|
|
434
|
+
yield { type: 'reasoning_delta', text: chunk.text };
|
|
435
|
+
break;
|
|
436
|
+
case 'tool_start':
|
|
437
|
+
// Initialize tool call tracking
|
|
438
|
+
responseBuilder.toolCalls.set(chunk.id, {
|
|
439
|
+
id: chunk.id,
|
|
440
|
+
name: chunk.name,
|
|
441
|
+
inputBuffer: '',
|
|
442
|
+
});
|
|
443
|
+
break;
|
|
444
|
+
case 'tool_input':
|
|
445
|
+
// Accumulate incremental JSON input and forward delta
|
|
446
|
+
const tool = responseBuilder.toolCalls.get(chunk.id);
|
|
447
|
+
if (tool) {
|
|
448
|
+
tool.inputBuffer += chunk.input;
|
|
449
|
+
// Emit incremental tool input for progressive display
|
|
450
|
+
yield { type: 'tool_input_delta', id: chunk.id, delta: chunk.input };
|
|
451
|
+
}
|
|
452
|
+
break;
|
|
453
|
+
case 'done':
|
|
454
|
+
// Save final metadata
|
|
455
|
+
responseBuilder.stopReason = chunk.response.stopReason;
|
|
456
|
+
responseBuilder.usage = chunk.response.usage;
|
|
457
|
+
responseBuilder.cost = chunk.response.cost;
|
|
458
|
+
break;
|
|
459
|
+
case 'error':
|
|
460
|
+
yield { type: 'error', error: chunk.error };
|
|
461
|
+
return;
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
// Build complete response from accumulated data
|
|
465
|
+
if (responseBuilder.textBuffer) {
|
|
466
|
+
responseBuilder.content.push({
|
|
467
|
+
type: 'text',
|
|
468
|
+
text: responseBuilder.textBuffer,
|
|
469
|
+
});
|
|
470
|
+
}
|
|
471
|
+
for (const [_id, tool] of responseBuilder.toolCalls) {
|
|
472
|
+
try {
|
|
473
|
+
responseBuilder.content.push({
|
|
474
|
+
type: 'tool_use',
|
|
475
|
+
id: tool.id,
|
|
476
|
+
name: tool.name,
|
|
477
|
+
input: JSON.parse(tool.inputBuffer || '{}'),
|
|
478
|
+
});
|
|
479
|
+
}
|
|
480
|
+
catch (error) {
|
|
481
|
+
// If JSON parsing fails, treat as malformed tool call
|
|
482
|
+
yield {
|
|
483
|
+
type: 'error',
|
|
484
|
+
error: new Error(`Failed to parse tool input for ${tool.name}: ${error instanceof Error ? error.message : String(error)}`),
|
|
485
|
+
};
|
|
486
|
+
return;
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
response = {
|
|
490
|
+
content: responseBuilder.content,
|
|
491
|
+
stopReason: responseBuilder.stopReason,
|
|
492
|
+
usage: responseBuilder.usage,
|
|
493
|
+
cost: responseBuilder.cost,
|
|
494
|
+
};
|
|
495
|
+
}
|
|
496
|
+
else {
|
|
497
|
+
// === TRADITIONAL PATH (COMPLETE) ===
|
|
498
|
+
response = await this.provider.complete({
|
|
499
|
+
model: this.config.model,
|
|
500
|
+
messages: this.sessionManager.getMessagesForLLM(),
|
|
501
|
+
tools: toolDefs,
|
|
502
|
+
systemPrompt,
|
|
503
|
+
maxTokens: 4096,
|
|
504
|
+
});
|
|
505
|
+
}
|
|
349
506
|
}
|
|
350
507
|
catch (error) {
|
|
351
508
|
yield { type: 'error', error: error };
|
|
352
509
|
return;
|
|
353
510
|
}
|
|
511
|
+
// Validate response completeness
|
|
512
|
+
if (!response || !response.content) {
|
|
513
|
+
yield {
|
|
514
|
+
type: 'error',
|
|
515
|
+
error: new Error('Provider returned null or undefined response')
|
|
516
|
+
};
|
|
517
|
+
return;
|
|
518
|
+
}
|
|
519
|
+
// Validate content is not empty (excluding max_tokens case)
|
|
520
|
+
if (response.content.length === 0 && response.stopReason !== 'max_tokens') {
|
|
521
|
+
yield {
|
|
522
|
+
type: 'error',
|
|
523
|
+
error: new Error(`Provider returned empty content (stopReason: ${response.stopReason}, ` +
|
|
524
|
+
`usage: ${JSON.stringify(response.usage)})`)
|
|
525
|
+
};
|
|
526
|
+
return;
|
|
527
|
+
}
|
|
354
528
|
// Process response content
|
|
355
529
|
const toolCalls = [];
|
|
356
530
|
let textContent = '';
|
|
357
531
|
for (const content of response.content) {
|
|
358
532
|
if (content.type === 'text') {
|
|
359
533
|
textContent += content.text;
|
|
360
|
-
|
|
534
|
+
// Only yield text if not in streaming mode (streaming already yielded chunks)
|
|
535
|
+
if (!useStreaming) {
|
|
536
|
+
yield { type: 'text', text: content.text };
|
|
537
|
+
}
|
|
361
538
|
}
|
|
362
539
|
else if (content.type === 'tool_use') {
|
|
363
540
|
toolCalls.push({ id: content.id, name: content.name, input: content.input });
|
|
364
541
|
}
|
|
365
542
|
}
|
|
366
543
|
// Add assistant message and check if done
|
|
367
|
-
|
|
368
|
-
|
|
544
|
+
try {
|
|
545
|
+
await this.sessionManager.addMessage({ role: 'assistant', content: response.content }, this.getModelInfo());
|
|
546
|
+
}
|
|
547
|
+
catch (error) {
|
|
548
|
+
yield {
|
|
549
|
+
type: 'error',
|
|
550
|
+
error: new Error(`Failed to save assistant message: ${error instanceof Error ? error.message : String(error)}`)
|
|
551
|
+
};
|
|
552
|
+
return;
|
|
553
|
+
}
|
|
369
554
|
if (response.stopReason !== 'tool_use' || toolCalls.length === 0) {
|
|
370
555
|
yield { type: 'done', text: textContent, usage: response.usage, cost: response.cost };
|
|
556
|
+
// Save completion metadata for UI restoration
|
|
557
|
+
if (response.usage || response.cost) {
|
|
558
|
+
const current = this.sessionManager.getCurrent();
|
|
559
|
+
if (current) {
|
|
560
|
+
if (!current.metadata.completions) {
|
|
561
|
+
current.metadata.completions = [];
|
|
562
|
+
}
|
|
563
|
+
current.metadata.completions.push({
|
|
564
|
+
afterMessageIndex: current.messages.length - 1,
|
|
565
|
+
durationMs: Date.now() - processingStartTime,
|
|
566
|
+
usage: response.usage ? {
|
|
567
|
+
inputTokens: response.usage.inputTokens,
|
|
568
|
+
outputTokens: response.usage.outputTokens,
|
|
569
|
+
} : undefined,
|
|
570
|
+
cost: response.cost,
|
|
571
|
+
});
|
|
572
|
+
}
|
|
573
|
+
}
|
|
371
574
|
return;
|
|
372
575
|
}
|
|
373
576
|
// Execute tool calls
|
|
@@ -380,21 +583,48 @@ export class Agent {
|
|
|
380
583
|
};
|
|
381
584
|
for (const call of toolCalls) {
|
|
382
585
|
yield { type: 'tool_start', id: call.id, name: call.name, input: call.input };
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
type: 'tool_result',
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
586
|
+
try {
|
|
587
|
+
// Protect permission check and tool execution
|
|
588
|
+
const allowed = await this.permissions.requestPermission(call.name, call.input);
|
|
589
|
+
const result = allowed
|
|
590
|
+
? await this.registry.execute(call.name, call.input, toolContext)
|
|
591
|
+
: { success: false, output: '', error: 'Permission denied by user' };
|
|
592
|
+
yield { type: 'tool_result', id: call.id, name: call.name, result };
|
|
593
|
+
toolResults.push({
|
|
594
|
+
type: 'tool_result',
|
|
595
|
+
toolUseId: call.id,
|
|
596
|
+
content: result.success ? result.output : (result.error ?? 'Unknown error'),
|
|
597
|
+
isError: !result.success,
|
|
598
|
+
});
|
|
599
|
+
}
|
|
600
|
+
catch (error) {
|
|
601
|
+
// Catch permission check or tool execution errors
|
|
602
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
603
|
+
const errorResult = {
|
|
604
|
+
success: false,
|
|
605
|
+
output: '',
|
|
606
|
+
error: `Tool execution error: ${errorMsg}`
|
|
607
|
+
};
|
|
608
|
+
yield { type: 'tool_result', id: call.id, name: call.name, result: errorResult };
|
|
609
|
+
toolResults.push({
|
|
610
|
+
type: 'tool_result',
|
|
611
|
+
toolUseId: call.id,
|
|
612
|
+
content: errorMsg,
|
|
613
|
+
isError: true,
|
|
614
|
+
});
|
|
615
|
+
}
|
|
394
616
|
}
|
|
395
617
|
// Add tool results as user message
|
|
396
|
-
|
|
397
|
-
|
|
618
|
+
try {
|
|
619
|
+
await this.sessionManager.addMessage({ role: 'user', content: toolResults }, this.getModelInfo());
|
|
620
|
+
}
|
|
621
|
+
catch (error) {
|
|
622
|
+
yield {
|
|
623
|
+
type: 'error',
|
|
624
|
+
error: new Error(`Failed to save tool results: ${error instanceof Error ? error.message : String(error)}`)
|
|
625
|
+
};
|
|
626
|
+
return;
|
|
627
|
+
}
|
|
398
628
|
}
|
|
399
629
|
yield { type: 'error', error: new Error(`Max turns (${maxTurns}) exceeded`) };
|
|
400
630
|
}
|
|
@@ -402,7 +632,6 @@ export class Agent {
|
|
|
402
632
|
* Clear conversation history
|
|
403
633
|
*/
|
|
404
634
|
clearHistory() {
|
|
405
|
-
this.messages = [];
|
|
406
635
|
this.sessionManager.clearMessages();
|
|
407
636
|
}
|
|
408
637
|
/**
|
|
@@ -410,21 +639,16 @@ export class Agent {
|
|
|
410
639
|
* Removes the last assistant message if it contains tool_use without corresponding tool_result
|
|
411
640
|
*/
|
|
412
641
|
cleanupIncompleteMessages() {
|
|
413
|
-
|
|
642
|
+
const messages = this.sessionManager.getMessages();
|
|
643
|
+
if (messages.length === 0)
|
|
414
644
|
return;
|
|
415
|
-
const lastMessage =
|
|
645
|
+
const lastMessage = messages[messages.length - 1];
|
|
416
646
|
// Check if last message is an assistant message with tool_use
|
|
417
647
|
if (lastMessage.role === 'assistant' && Array.isArray(lastMessage.content)) {
|
|
418
648
|
const hasToolUse = lastMessage.content.some((c) => c.type === 'tool_use');
|
|
419
649
|
if (hasToolUse) {
|
|
420
|
-
// Remove the incomplete assistant message
|
|
421
|
-
this.
|
|
422
|
-
// Also remove from session manager
|
|
423
|
-
// Note: SessionManager should have corresponding cleanup method
|
|
424
|
-
const messages = this.sessionManager.getMessages();
|
|
425
|
-
if (messages.length > 0 && messages[messages.length - 1].role === 'assistant') {
|
|
426
|
-
this.sessionManager.removeLastMessage();
|
|
427
|
-
}
|
|
650
|
+
// Remove the incomplete assistant message from session manager
|
|
651
|
+
this.sessionManager.removeLastMessage();
|
|
428
652
|
}
|
|
429
653
|
}
|
|
430
654
|
}
|
|
@@ -432,7 +656,13 @@ export class Agent {
|
|
|
432
656
|
* Get conversation history
|
|
433
657
|
*/
|
|
434
658
|
getHistory() {
|
|
435
|
-
return
|
|
659
|
+
return this.sessionManager.getMessages();
|
|
660
|
+
}
|
|
661
|
+
/**
|
|
662
|
+
* Get compression statistics
|
|
663
|
+
*/
|
|
664
|
+
getCompressionStats() {
|
|
665
|
+
return this.sessionManager.getCompressionStats();
|
|
436
666
|
}
|
|
437
667
|
}
|
|
438
668
|
//# sourceMappingURL=agent.js.map
|