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.
Files changed (116) hide show
  1. package/RELEASE_NOTES_v0.4.0.md +140 -0
  2. package/dist/agent/agent.d.ts +17 -2
  3. package/dist/agent/agent.d.ts.map +1 -1
  4. package/dist/agent/agent.js +279 -49
  5. package/dist/agent/agent.js.map +1 -1
  6. package/dist/agent/types.d.ts +15 -1
  7. package/dist/agent/types.d.ts.map +1 -1
  8. package/dist/checkpointing/checkpoint-manager.d.ts +24 -0
  9. package/dist/checkpointing/checkpoint-manager.d.ts.map +1 -1
  10. package/dist/checkpointing/checkpoint-manager.js +28 -0
  11. package/dist/checkpointing/checkpoint-manager.js.map +1 -1
  12. package/dist/cli/components/App.d.ts +8 -0
  13. package/dist/cli/components/App.d.ts.map +1 -1
  14. package/dist/cli/components/App.js +478 -36
  15. package/dist/cli/components/App.js.map +1 -1
  16. package/dist/cli/components/CommandSuggestions.d.ts.map +1 -1
  17. package/dist/cli/components/CommandSuggestions.js +2 -0
  18. package/dist/cli/components/CommandSuggestions.js.map +1 -1
  19. package/dist/cli/components/Header.d.ts +6 -1
  20. package/dist/cli/components/Header.d.ts.map +1 -1
  21. package/dist/cli/components/Header.js +3 -3
  22. package/dist/cli/components/Header.js.map +1 -1
  23. package/dist/cli/components/Messages.d.ts.map +1 -1
  24. package/dist/cli/components/Messages.js +7 -9
  25. package/dist/cli/components/Messages.js.map +1 -1
  26. package/dist/cli/index.js +3 -2
  27. package/dist/cli/index.js.map +1 -1
  28. package/dist/config/types.d.ts +20 -1
  29. package/dist/config/types.d.ts.map +1 -1
  30. package/dist/config/types.js.map +1 -1
  31. package/dist/index.d.ts +2 -2
  32. package/dist/index.js +2 -2
  33. package/dist/input/history-manager.d.ts +78 -0
  34. package/dist/input/history-manager.d.ts.map +1 -0
  35. package/dist/input/history-manager.js +224 -0
  36. package/dist/input/history-manager.js.map +1 -0
  37. package/dist/input/index.d.ts +6 -0
  38. package/dist/input/index.d.ts.map +1 -0
  39. package/dist/input/index.js +5 -0
  40. package/dist/input/index.js.map +1 -0
  41. package/dist/prompts/index.js +3 -3
  42. package/dist/prompts/index.js.map +1 -1
  43. package/dist/providers/gemini.d.ts.map +1 -1
  44. package/dist/providers/gemini.js +33 -2
  45. package/dist/providers/gemini.js.map +1 -1
  46. package/dist/providers/google.d.ts +22 -0
  47. package/dist/providers/google.d.ts.map +1 -0
  48. package/dist/providers/google.js +297 -0
  49. package/dist/providers/google.js.map +1 -0
  50. package/dist/providers/index.d.ts +4 -4
  51. package/dist/providers/index.js +11 -11
  52. package/dist/providers/index.js.map +1 -1
  53. package/dist/providers/openai.d.ts.map +1 -1
  54. package/dist/providers/openai.js +6 -0
  55. package/dist/providers/openai.js.map +1 -1
  56. package/dist/providers/registry.js +3 -3
  57. package/dist/providers/registry.js.map +1 -1
  58. package/dist/providers/types.d.ts +30 -4
  59. package/dist/providers/types.d.ts.map +1 -1
  60. package/dist/session/compression/engine.d.ts +109 -0
  61. package/dist/session/compression/engine.d.ts.map +1 -0
  62. package/dist/session/compression/engine.js +311 -0
  63. package/dist/session/compression/engine.js.map +1 -0
  64. package/dist/session/compression/index.d.ts +12 -0
  65. package/dist/session/compression/index.d.ts.map +1 -0
  66. package/dist/session/compression/index.js +11 -0
  67. package/dist/session/compression/index.js.map +1 -0
  68. package/dist/session/compression/types.d.ts +90 -0
  69. package/dist/session/compression/types.d.ts.map +1 -0
  70. package/dist/session/compression/types.js +17 -0
  71. package/dist/session/compression/types.js.map +1 -0
  72. package/dist/session/manager.d.ts +64 -3
  73. package/dist/session/manager.d.ts.map +1 -1
  74. package/dist/session/manager.js +254 -2
  75. package/dist/session/manager.js.map +1 -1
  76. package/dist/session/types.d.ts +16 -0
  77. package/dist/session/types.d.ts.map +1 -1
  78. package/dist/session/types.js.map +1 -1
  79. package/docs/README.md +1 -0
  80. package/docs/diagrams/compression-decision.mmd +30 -0
  81. package/docs/diagrams/compression-workflow.mmd +54 -0
  82. package/docs/diagrams/layer1-pruning.mmd +45 -0
  83. package/docs/diagrams/layer2-compaction.mmd +42 -0
  84. package/docs/proposals/0007-context-management.md +252 -2
  85. package/docs/proposals/README.md +4 -3
  86. package/docs/providers.md +3 -3
  87. package/docs/session-compression.md +695 -0
  88. package/examples/agent-demo.ts +23 -1
  89. package/examples/basic.ts +3 -3
  90. package/package.json +3 -4
  91. package/src/agent/agent.ts +314 -52
  92. package/src/agent/types.ts +19 -1
  93. package/src/checkpointing/checkpoint-manager.ts +48 -0
  94. package/src/cli/components/App.tsx +553 -34
  95. package/src/cli/components/CommandSuggestions.tsx +2 -0
  96. package/src/cli/components/Header.tsx +16 -1
  97. package/src/cli/components/Messages.tsx +20 -14
  98. package/src/cli/index.tsx +3 -2
  99. package/src/config/types.ts +26 -1
  100. package/src/index.ts +3 -3
  101. package/src/input/history-manager.ts +289 -0
  102. package/src/input/index.ts +6 -0
  103. package/src/prompts/index.test.ts +2 -1
  104. package/src/prompts/index.ts +3 -3
  105. package/src/providers/{gemini.ts → google.ts} +69 -18
  106. package/src/providers/index.ts +14 -14
  107. package/src/providers/openai.ts +7 -0
  108. package/src/providers/registry.ts +3 -3
  109. package/src/providers/types.ts +33 -3
  110. package/src/session/compression/engine.ts +406 -0
  111. package/src/session/compression/index.ts +18 -0
  112. package/src/session/compression/types.ts +102 -0
  113. package/src/session/manager.ts +326 -3
  114. package/src/session/types.ts +21 -0
  115. package/tests/input-history-manager.test.ts +335 -0
  116. 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)
@@ -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":"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"}
1
+ {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/agent/agent.ts"],"names":[],"mappings":"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"}
@@ -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.messages = [];
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
- this.messages = session.messages;
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
- this.messages = session.messages;
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
- if (!this.sessionId) {
315
- await this.startSession();
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
- // Load memory if not already loaded
318
- if (!this.loadedMemory) {
319
- await this.loadMemory();
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
- this.messages.push(userMessage);
324
- await this.sessionManager.addMessage(userMessage);
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
- response = await this.provider.complete({
343
- model: this.config.model,
344
- messages: this.messages,
345
- tools: toolDefs,
346
- systemPrompt,
347
- maxTokens: 4096,
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
- yield { type: 'text', text: content.text };
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
- this.messages.push({ role: 'assistant', content: response.content });
368
- await this.sessionManager.addMessage({ role: 'assistant', content: response.content });
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
- const allowed = await this.permissions.requestPermission(call.name, call.input);
384
- const result = allowed
385
- ? await this.registry.execute(call.name, call.input, toolContext)
386
- : { success: false, output: '', error: 'Permission denied by user' };
387
- yield { type: 'tool_result', id: call.id, name: call.name, result };
388
- toolResults.push({
389
- type: 'tool_result',
390
- toolUseId: call.id,
391
- content: result.success ? result.output : (result.error ?? 'Unknown error'),
392
- isError: !result.success,
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
- this.messages.push({ role: 'user', content: toolResults });
397
- await this.sessionManager.addMessage({ role: 'user', content: toolResults });
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
- if (this.messages.length === 0)
642
+ const messages = this.sessionManager.getMessages();
643
+ if (messages.length === 0)
414
644
  return;
415
- const lastMessage = this.messages[this.messages.length - 1];
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.messages.pop();
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 [...this.messages];
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