gencode-ai 0.1.3 → 0.3.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/README.md +2 -1
- package/dist/agent/agent.d.ts +44 -2
- package/dist/agent/agent.d.ts.map +1 -1
- package/dist/agent/agent.js +130 -11
- package/dist/agent/agent.js.map +1 -1
- package/dist/agent/types.d.ts +11 -1
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/checkpointing/checkpoint-manager.d.ts +87 -0
- package/dist/checkpointing/checkpoint-manager.d.ts.map +1 -0
- package/dist/checkpointing/checkpoint-manager.js +281 -0
- package/dist/checkpointing/checkpoint-manager.js.map +1 -0
- package/dist/checkpointing/index.d.ts +29 -0
- package/dist/checkpointing/index.d.ts.map +1 -0
- package/dist/checkpointing/index.js +29 -0
- package/dist/checkpointing/index.js.map +1 -0
- package/dist/checkpointing/types.d.ts +98 -0
- package/dist/checkpointing/types.d.ts.map +1 -0
- package/dist/checkpointing/types.js +7 -0
- package/dist/checkpointing/types.js.map +1 -0
- package/dist/cli/components/App.d.ts.map +1 -1
- package/dist/cli/components/App.js +171 -14
- 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 +5 -0
- package/dist/cli/components/CommandSuggestions.js.map +1 -1
- package/dist/cli/components/Messages.d.ts +7 -1
- package/dist/cli/components/Messages.d.ts.map +1 -1
- package/dist/cli/components/Messages.js +12 -3
- package/dist/cli/components/Messages.js.map +1 -1
- package/dist/cli/components/ModeIndicator.d.ts +42 -0
- package/dist/cli/components/ModeIndicator.d.ts.map +1 -0
- package/dist/cli/components/ModeIndicator.js +52 -0
- package/dist/cli/components/ModeIndicator.js.map +1 -0
- package/dist/cli/components/ModelSelector.d.ts +4 -3
- package/dist/cli/components/ModelSelector.d.ts.map +1 -1
- package/dist/cli/components/ModelSelector.js +54 -37
- package/dist/cli/components/ModelSelector.js.map +1 -1
- package/dist/cli/components/PlanApproval.d.ts +36 -0
- package/dist/cli/components/PlanApproval.d.ts.map +1 -0
- package/dist/cli/components/PlanApproval.js +154 -0
- package/dist/cli/components/PlanApproval.js.map +1 -0
- package/dist/cli/components/ProviderManager.d.ts +2 -2
- package/dist/cli/components/ProviderManager.d.ts.map +1 -1
- package/dist/cli/components/ProviderManager.js +137 -156
- package/dist/cli/components/ProviderManager.js.map +1 -1
- package/dist/cli/components/theme.d.ts +2 -0
- package/dist/cli/components/theme.d.ts.map +1 -1
- package/dist/cli/components/theme.js +3 -0
- package/dist/cli/components/theme.js.map +1 -1
- package/dist/cli/index.js +30 -13
- package/dist/cli/index.js.map +1 -1
- package/dist/config/index.d.ts +2 -2
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +1 -1
- package/dist/config/index.js.map +1 -1
- package/dist/config/levels.d.ts +5 -5
- package/dist/config/levels.d.ts.map +1 -1
- package/dist/config/levels.js +20 -20
- package/dist/config/levels.js.map +1 -1
- package/dist/config/merger.js +1 -1
- package/dist/config/merger.js.map +1 -1
- package/dist/config/providers-config.d.ts +8 -5
- package/dist/config/providers-config.d.ts.map +1 -1
- package/dist/config/providers-config.js +19 -22
- package/dist/config/providers-config.js.map +1 -1
- package/dist/config/test-utils.d.ts +2 -2
- package/dist/config/test-utils.d.ts.map +1 -1
- package/dist/config/test-utils.js +4 -4
- package/dist/config/test-utils.js.map +1 -1
- package/dist/config/types.d.ts +23 -17
- package/dist/config/types.d.ts.map +1 -1
- package/dist/config/types.js +14 -14
- package/dist/config/types.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/memory/memory-manager.d.ts +25 -12
- package/dist/memory/memory-manager.d.ts.map +1 -1
- package/dist/memory/memory-manager.js +241 -112
- package/dist/memory/memory-manager.js.map +1 -1
- package/dist/memory/test-utils.d.ts +1 -1
- package/dist/memory/test-utils.d.ts.map +1 -1
- package/dist/memory/test-utils.js +3 -3
- package/dist/memory/test-utils.js.map +1 -1
- package/dist/memory/types.d.ts +20 -10
- package/dist/memory/types.d.ts.map +1 -1
- package/dist/memory/types.js +13 -13
- package/dist/memory/types.js.map +1 -1
- package/dist/migration/migrate.d.ts +24 -0
- package/dist/migration/migrate.d.ts.map +1 -0
- package/dist/migration/migrate.js +164 -0
- package/dist/migration/migrate.js.map +1 -0
- package/dist/permissions/persistence.d.ts +2 -2
- package/dist/permissions/persistence.js +4 -4
- package/dist/permissions/persistence.js.map +1 -1
- package/dist/planning/index.d.ts +13 -0
- package/dist/planning/index.d.ts.map +1 -0
- package/dist/planning/index.js +15 -0
- package/dist/planning/index.js.map +1 -0
- package/dist/planning/plan-file.d.ts +59 -0
- package/dist/planning/plan-file.d.ts.map +1 -0
- package/dist/planning/plan-file.js +278 -0
- package/dist/planning/plan-file.js.map +1 -0
- package/dist/planning/state.d.ts +127 -0
- package/dist/planning/state.d.ts.map +1 -0
- package/dist/planning/state.js +261 -0
- package/dist/planning/state.js.map +1 -0
- package/dist/planning/tools/enter-plan-mode.d.ts +25 -0
- package/dist/planning/tools/enter-plan-mode.d.ts.map +1 -0
- package/dist/planning/tools/enter-plan-mode.js +98 -0
- package/dist/planning/tools/enter-plan-mode.js.map +1 -0
- package/dist/planning/tools/exit-plan-mode.d.ts +24 -0
- package/dist/planning/tools/exit-plan-mode.d.ts.map +1 -0
- package/dist/planning/tools/exit-plan-mode.js +149 -0
- package/dist/planning/tools/exit-plan-mode.js.map +1 -0
- package/dist/planning/types.d.ts +100 -0
- package/dist/planning/types.d.ts.map +1 -0
- package/dist/planning/types.js +28 -0
- package/dist/planning/types.js.map +1 -0
- package/dist/pricing/calculator.d.ts +21 -0
- package/dist/pricing/calculator.d.ts.map +1 -0
- package/dist/pricing/calculator.js +59 -0
- package/dist/pricing/calculator.js.map +1 -0
- package/dist/pricing/index.d.ts +7 -0
- package/dist/pricing/index.d.ts.map +1 -0
- package/dist/pricing/index.js +7 -0
- package/dist/pricing/index.js.map +1 -0
- package/dist/pricing/models.d.ts +20 -0
- package/dist/pricing/models.d.ts.map +1 -0
- package/dist/pricing/models.js +322 -0
- package/dist/pricing/models.js.map +1 -0
- package/dist/pricing/types.d.ts +30 -0
- package/dist/pricing/types.d.ts.map +1 -0
- package/dist/pricing/types.js +5 -0
- package/dist/pricing/types.js.map +1 -0
- package/dist/prompts/index.d.ts +5 -4
- package/dist/prompts/index.d.ts.map +1 -1
- package/dist/prompts/index.js +11 -8
- package/dist/prompts/index.js.map +1 -1
- package/dist/providers/anthropic.d.ts +2 -1
- package/dist/providers/anthropic.d.ts.map +1 -1
- package/dist/providers/anthropic.js +24 -10
- package/dist/providers/anthropic.js.map +1 -1
- package/dist/providers/gemini.d.ts +2 -1
- package/dist/providers/gemini.d.ts.map +1 -1
- package/dist/providers/gemini.js +28 -14
- package/dist/providers/gemini.js.map +1 -1
- package/dist/providers/index.d.ts +20 -10
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/index.js +48 -24
- package/dist/providers/index.js.map +1 -1
- package/dist/providers/openai.d.ts +2 -1
- package/dist/providers/openai.d.ts.map +1 -1
- package/dist/providers/openai.js +19 -8
- package/dist/providers/openai.js.map +1 -1
- package/dist/providers/registry.d.ts +48 -34
- package/dist/providers/registry.d.ts.map +1 -1
- package/dist/providers/registry.js +72 -88
- package/dist/providers/registry.js.map +1 -1
- package/dist/providers/store.d.ts +43 -17
- package/dist/providers/store.d.ts.map +1 -1
- package/dist/providers/store.js +112 -19
- package/dist/providers/store.js.map +1 -1
- package/dist/providers/types.d.ts +25 -0
- package/dist/providers/types.d.ts.map +1 -1
- package/dist/providers/vertex-ai.d.ts +15 -7
- package/dist/providers/vertex-ai.d.ts.map +1 -1
- package/dist/providers/vertex-ai.js +63 -23
- package/dist/providers/vertex-ai.js.map +1 -1
- package/dist/session/manager.d.ts +4 -0
- package/dist/session/manager.d.ts.map +1 -1
- package/dist/session/manager.js +8 -0
- package/dist/session/manager.js.map +1 -1
- package/dist/session/types.js +1 -1
- package/dist/session/types.js.map +1 -1
- package/dist/tools/index.d.ts +7 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +7 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/registry.d.ts +13 -0
- package/dist/tools/registry.d.ts.map +1 -1
- package/dist/tools/registry.js +79 -2
- package/dist/tools/registry.js.map +1 -1
- package/docs/config-system-comparison.md +50 -50
- package/docs/cost-tracking-comparison.md +904 -0
- package/docs/memory-system.md +124 -31
- package/docs/operating-modes.md +96 -0
- package/docs/permissions.md +2 -2
- package/docs/proposals/0006-memory-system.md +4 -4
- package/docs/proposals/0008-checkpointing.md +109 -2
- package/docs/proposals/0011-custom-commands.md +2 -1
- package/docs/proposals/0021-skills-system.md +2 -1
- package/docs/proposals/0023-permission-enhancements.md +2 -2
- package/docs/proposals/0025-cost-tracking.md +60 -2
- package/docs/proposals/0033-enterprise-deployment.md +1 -1
- package/docs/proposals/0041-configuration-system.md +17 -19
- package/docs/proposals/0042-prompt-optimization.md +17 -9
- package/docs/proposals/README.md +6 -6
- package/docs/providers.md +94 -9
- package/examples/test-checkpointing.ts +121 -0
- package/examples/test-cost-tracking.ts +77 -0
- package/examples/test-interrupt-cleanup.ts +94 -0
- package/package.json +3 -2
- package/scripts/migrate.ts +449 -0
- package/src/agent/agent.ts +161 -12
- package/src/agent/types.ts +11 -1
- package/src/checkpointing/checkpoint-manager.ts +327 -0
- package/src/checkpointing/index.ts +45 -0
- package/src/checkpointing/types.ts +104 -0
- package/src/cli/components/App.tsx +221 -13
- package/src/cli/components/CommandSuggestions.tsx +5 -0
- package/src/cli/components/Messages.tsx +24 -5
- package/src/cli/components/ModeIndicator.tsx +174 -0
- package/src/cli/components/ModelSelector.tsx +62 -43
- package/src/cli/components/PlanApproval.tsx +327 -0
- package/src/cli/components/ProviderManager.tsx +278 -323
- package/src/cli/components/theme.ts +3 -0
- package/src/cli/index.tsx +36 -17
- package/src/config/index.ts +5 -3
- package/src/config/levels.test.ts +22 -22
- package/src/config/levels.ts +22 -22
- package/src/config/loader.test.ts +14 -14
- package/src/config/manager.test.ts +19 -19
- package/src/config/merger.test.ts +23 -23
- package/src/config/merger.ts +1 -1
- package/src/config/providers-config.ts +23 -21
- package/src/config/test-utils.ts +6 -6
- package/src/config/types.ts +30 -20
- package/src/index.ts +15 -0
- package/src/memory/memory-manager.test.ts +242 -24
- package/src/memory/memory-manager.ts +270 -141
- package/src/memory/test-utils.ts +4 -4
- package/src/memory/types.ts +28 -17
- package/src/permissions/persistence.ts +4 -4
- package/src/planning/index.ts +53 -0
- package/src/planning/plan-file.ts +326 -0
- package/src/planning/state.ts +305 -0
- package/src/planning/tools/enter-plan-mode.ts +111 -0
- package/src/planning/tools/exit-plan-mode.ts +170 -0
- package/src/planning/types.ts +150 -0
- package/src/pricing/calculator.ts +71 -0
- package/src/pricing/index.ts +7 -0
- package/src/pricing/models.ts +334 -0
- package/src/pricing/types.ts +32 -0
- package/src/prompts/index.ts +13 -9
- package/src/providers/anthropic.ts +30 -10
- package/src/providers/gemini.ts +34 -14
- package/src/providers/index.ts +76 -33
- package/src/providers/openai.ts +26 -8
- package/src/providers/registry.ts +116 -111
- package/src/providers/store.ts +130 -28
- package/src/providers/types.ts +36 -1
- package/src/providers/vertex-ai.ts +70 -23
- package/src/session/manager.ts +9 -0
- package/src/session/types.ts +1 -1
- package/src/tools/index.ts +8 -0
- package/src/tools/registry.ts +95 -2
- package/.gencode/settings.local.json +0 -7
- package/CLAUDE.md +0 -86
|
@@ -49,9 +49,7 @@ Claude Code supports extensive environment variables:
|
|
|
49
49
|
|
|
50
50
|
**Cloud Providers:**
|
|
51
51
|
- `CLAUDE_CODE_USE_BEDROCK` - Enable AWS Bedrock
|
|
52
|
-
- `CLAUDE_CODE_USE_VERTEX` - Enable Google Vertex AI
|
|
53
52
|
- `CLAUDE_CODE_SKIP_BEDROCK_AUTH` - Bypass AWS auth
|
|
54
|
-
- `CLAUDE_CODE_SKIP_VERTEX_AUTH` - Bypass Vertex auth
|
|
55
53
|
|
|
56
54
|
**Operational:**
|
|
57
55
|
- `CLAUDE_CODE_MAX_OUTPUT_TOKENS` - Token limit
|
|
@@ -121,7 +119,7 @@ OpenCode provides additional patterns worth adopting:
|
|
|
121
119
|
### Directory Structure
|
|
122
120
|
|
|
123
121
|
```
|
|
124
|
-
~/.
|
|
122
|
+
~/.gen/ # User-level configuration
|
|
125
123
|
├── settings.json # Main user config
|
|
126
124
|
├── settings.local.json # User local overrides (gitignored pattern)
|
|
127
125
|
├── GENCODE.md # User context (like CLAUDE.md)
|
|
@@ -135,7 +133,7 @@ OpenCode provides additional patterns worth adopting:
|
|
|
135
133
|
└── sessions/ # Session data
|
|
136
134
|
|
|
137
135
|
./gencode.json # Project config (like opencode.json)
|
|
138
|
-
./.
|
|
136
|
+
./.gen/ # Project directory
|
|
139
137
|
├── settings.local.json # Project local overrides (gitignored)
|
|
140
138
|
├── GENCODE.md # Project context
|
|
141
139
|
├── rules/ # Path-scoped rules
|
|
@@ -146,10 +144,10 @@ OpenCode provides additional patterns worth adopting:
|
|
|
146
144
|
|
|
147
145
|
1. **Environment variables** (`GENCODE_*`, provider API keys)
|
|
148
146
|
2. **CLI arguments** (`--model`, `--provider`)
|
|
149
|
-
3. **Project local** (`./.
|
|
147
|
+
3. **Project local** (`./.gen/settings.local.json`)
|
|
150
148
|
4. **Project shared** (`./gencode.json`)
|
|
151
|
-
5. **User local** (`~/.
|
|
152
|
-
6. **User global** (`~/.
|
|
149
|
+
5. **User local** (`~/.gen/settings.local.json`)
|
|
150
|
+
6. **User global** (`~/.gen/settings.json`)
|
|
153
151
|
7. **Defaults**
|
|
154
152
|
|
|
155
153
|
### API Design
|
|
@@ -227,8 +225,8 @@ interface EnvHandler {
|
|
|
227
225
|
### Environment Variables
|
|
228
226
|
|
|
229
227
|
**Provider Selection:**
|
|
230
|
-
- `
|
|
231
|
-
- `
|
|
228
|
+
- `GEN_PROVIDER` - Provider name (anthropic, openai, gemini, bedrock, vertex)
|
|
229
|
+
- `GEN_MODEL` - Model ID
|
|
232
230
|
- `GENCODE_CONFIG` - Custom config file path
|
|
233
231
|
|
|
234
232
|
**Provider API Keys (Auto-detect):**
|
|
@@ -300,7 +298,7 @@ const ConfigSchema = z.object({
|
|
|
300
298
|
});
|
|
301
299
|
|
|
302
300
|
export class ConfigLoader {
|
|
303
|
-
private userConfigDir = path.join(os.homedir(), '.
|
|
301
|
+
private userConfigDir = path.join(os.homedir(), '.gen');
|
|
304
302
|
|
|
305
303
|
async load(): Promise<GencodeConfig> {
|
|
306
304
|
const configs = await Promise.all([
|
|
@@ -349,7 +347,7 @@ export class EnvHandler {
|
|
|
349
347
|
};
|
|
350
348
|
|
|
351
349
|
getProviderFromEnv(): string | undefined {
|
|
352
|
-
return process.env.
|
|
350
|
+
return process.env.GEN_PROVIDER;
|
|
353
351
|
}
|
|
354
352
|
|
|
355
353
|
getApiKey(provider: string): string | undefined {
|
|
@@ -442,7 +440,7 @@ $ gencode
|
|
|
442
440
|
# Uses OpenAI automatically
|
|
443
441
|
|
|
444
442
|
# Or specify explicitly
|
|
445
|
-
$ export
|
|
443
|
+
$ export GEN_PROVIDER=anthropic
|
|
446
444
|
$ export ANTHROPIC_API_KEY=sk-ant-...
|
|
447
445
|
$ gencode
|
|
448
446
|
```
|
|
@@ -480,7 +478,7 @@ $ gencode config deny "Read(.env)"
|
|
|
480
478
|
|
|
481
479
|
### Single Config File
|
|
482
480
|
|
|
483
|
-
A single `~/.
|
|
481
|
+
A single `~/.genrc` file would be simpler but lacks:
|
|
484
482
|
- Project-specific overrides
|
|
485
483
|
- Team-shareable settings
|
|
486
484
|
- Local-only sensitive settings
|
|
@@ -526,7 +524,7 @@ Simpler implementation but:
|
|
|
526
524
|
|
|
527
525
|
## Migration Path
|
|
528
526
|
|
|
529
|
-
1. **From mycode**: Migrate `~/.mycode/` to `~/.
|
|
527
|
+
1. **From mycode**: Migrate `~/.mycode/` to `~/.gen/`
|
|
530
528
|
2. **Version Detection**: Check for legacy config locations and prompt migration
|
|
531
529
|
3. **Backward Compatibility**: Support reading old config format for one major version
|
|
532
530
|
|
|
@@ -570,9 +568,9 @@ Simpler implementation but:
|
|
|
570
568
|
|
|
571
569
|
### Key Implementation Details
|
|
572
570
|
|
|
573
|
-
1. **Multi-level Loading**: User (`~/.
|
|
571
|
+
1. **Multi-level Loading**: User (`~/.gen/`) → Project (`./.gen/`) with proper merge
|
|
574
572
|
2. **Claude Code Compatibility**: Supports both `GENCODE.md` and `CLAUDE.md` for memory files
|
|
575
|
-
3. **Environment Variables**: `
|
|
573
|
+
3. **Environment Variables**: `GEN_PROVIDER`, `GEN_MODEL`, and provider API key auto-detection
|
|
576
574
|
4. **Deep Merge**: Arrays concatenate, objects merge recursively
|
|
577
575
|
5. **JSONC Support**: Configuration files support comments and trailing commas
|
|
578
576
|
|
|
@@ -580,8 +578,8 @@ Simpler implementation but:
|
|
|
580
578
|
|
|
581
579
|
1. Environment variables (`GENCODE_*`)
|
|
582
580
|
2. CLI arguments
|
|
583
|
-
3. Project local (`./.
|
|
581
|
+
3. Project local (`./.gen/settings.local.json`)
|
|
584
582
|
4. Project shared (`./gencode.json`)
|
|
585
|
-
5. User local (`~/.
|
|
586
|
-
6. User global (`~/.
|
|
583
|
+
5. User local (`~/.gen/settings.local.json`)
|
|
584
|
+
6. User global (`~/.gen/settings.json`)
|
|
587
585
|
7. Defaults
|
|
@@ -199,7 +199,7 @@ src/prompts/
|
|
|
199
199
|
|
|
200
200
|
### 4.2 Prompt Loading Strategy
|
|
201
201
|
|
|
202
|
-
The prompt loading system uses a **model → provider → prompt** flow, leveraging the `~/.
|
|
202
|
+
The prompt loading system uses a **model → provider → prompt** flow, leveraging the `~/.gen/providers.json` configuration to automatically determine which prompt to use.
|
|
203
203
|
|
|
204
204
|
#### 4.2.1 Loading Flow
|
|
205
205
|
|
|
@@ -209,7 +209,7 @@ model ID (e.g., "claude-sonnet-4-5@20250929")
|
|
|
209
209
|
▼
|
|
210
210
|
┌─────────────────────────────────────┐
|
|
211
211
|
│ Look up provider in providers.json │
|
|
212
|
-
│ (search models
|
|
212
|
+
│ (search models[provider:*].list) │
|
|
213
213
|
└──────────────┬──────────────────────┘
|
|
214
214
|
│
|
|
215
215
|
┌──────────┴──────────┐
|
|
@@ -242,18 +242,26 @@ model ID (e.g., "claude-sonnet-4-5@20250929")
|
|
|
242
242
|
|
|
243
243
|
#### 4.2.2 Provider Lookup from providers.json
|
|
244
244
|
|
|
245
|
-
The `~/.
|
|
245
|
+
The `~/.gen/providers.json` file stores cached models for each provider using `"provider:authMethod"` keys:
|
|
246
246
|
|
|
247
247
|
```json
|
|
248
248
|
{
|
|
249
249
|
"models": {
|
|
250
|
-
"anthropic": {
|
|
250
|
+
"anthropic:api_key": {
|
|
251
|
+
"cachedAt": "2025-01-17T10:00:00Z",
|
|
251
252
|
"list": [
|
|
252
253
|
{ "id": "claude-sonnet-4-5@20250929", "name": "Claude Sonnet 4.5" },
|
|
253
254
|
{ "id": "claude-opus-4-1@20250805", "name": "Claude Opus 4.1" }
|
|
254
255
|
]
|
|
255
256
|
},
|
|
256
|
-
"
|
|
257
|
+
"anthropic:vertex": {
|
|
258
|
+
"cachedAt": "2025-01-17T09:00:00Z",
|
|
259
|
+
"list": [
|
|
260
|
+
{ "id": "claude-3-5-sonnet@20241022", "name": "Claude 3.5 Sonnet" }
|
|
261
|
+
]
|
|
262
|
+
},
|
|
263
|
+
"gemini:api_key": {
|
|
264
|
+
"cachedAt": "2025-01-17T08:00:00Z",
|
|
257
265
|
"list": [
|
|
258
266
|
{ "id": "gemini-2.5-pro", "name": "Gemini 2.5 Pro" }
|
|
259
267
|
]
|
|
@@ -262,7 +270,7 @@ The `~/.gencode/providers.json` file stores cached models for each connected pro
|
|
|
262
270
|
}
|
|
263
271
|
```
|
|
264
272
|
|
|
265
|
-
Given a model ID, the system searches through each provider's model list to find the owning provider.
|
|
273
|
+
Given a model ID, the system searches through each provider's model list to find the owning provider. The key format is `"provider:authMethod"` to support multiple authentication methods for the same provider.
|
|
266
274
|
|
|
267
275
|
#### 4.2.3 Provider to Prompt Type Mapping
|
|
268
276
|
|
|
@@ -293,7 +301,7 @@ This ensures the system always has a valid prompt to use.
|
|
|
293
301
|
// 5.1.1 Provider Type Definition
|
|
294
302
|
export type ProviderType = 'anthropic' | 'openai' | 'gemini' | 'generic';
|
|
295
303
|
|
|
296
|
-
// 5.1.2 Look up provider for a model from ~/.
|
|
304
|
+
// 5.1.2 Look up provider for a model from ~/.gen/providers.json
|
|
297
305
|
export function getProviderForModel(model: string): string | null {
|
|
298
306
|
const config = loadProvidersConfig();
|
|
299
307
|
if (!config?.models) return null;
|
|
@@ -462,7 +470,7 @@ User starts GenCode CLI
|
|
|
462
470
|
│
|
|
463
471
|
▼
|
|
464
472
|
┌─────────────────────┐ ┌─────────────────────────────┐
|
|
465
|
-
│ 3. Memory Loading │────▶│ Load ~/.
|
|
473
|
+
│ 3. Memory Loading │────▶│ Load ~/.gen/GENCODE.md │
|
|
466
474
|
│ (if exists) │ │ Load ./CLAUDE.md (fallback) │
|
|
467
475
|
└──────────┬──────────┘ └─────────────────────────────┘
|
|
468
476
|
│
|
|
@@ -480,7 +488,7 @@ User starts GenCode CLI
|
|
|
480
488
|
│ │
|
|
481
489
|
│ ┌─────────────────────────────────────────────────┐ │
|
|
482
490
|
│ │ a. getPromptTypeForModel(model, fallback) │ │
|
|
483
|
-
│ │ - Look up provider in ~/.
|
|
491
|
+
│ │ - Look up provider in ~/.gen/providers.json│
|
|
484
492
|
│ │ - Map provider → prompt type │ │
|
|
485
493
|
│ │ - Fallback to 'generic' if not found │ │
|
|
486
494
|
│ └─────────────────────────────────────────────────┘ │
|
package/docs/proposals/README.md
CHANGED
|
@@ -19,15 +19,14 @@ This directory contains enhancement proposals for the gencode project. Each prop
|
|
|
19
19
|
| [0001](./0001-web-fetch-tool.md) | WebFetch Tool | Implemented |
|
|
20
20
|
| [0002](./0002-web-search-tool.md) | WebSearch Tool | Implemented |
|
|
21
21
|
| [0003](./0003-task-subagents.md) | Task Tool & Subagents | Draft |
|
|
22
|
-
| [0004](./0004-plan-mode.md) | Plan Mode |
|
|
22
|
+
| [0004](./0004-plan-mode.md) | Plan Mode | Implemented |
|
|
23
23
|
| [0005](./0005-todo-system.md) | Todo System | Implemented |
|
|
24
24
|
| [0006](./0006-memory-system.md) | Memory System (MYCODE.md) | Implemented |
|
|
25
25
|
| [0007](./0007-context-management.md) | Context Management | Draft |
|
|
26
|
-
| [0008](./0008-checkpointing.md) | Checkpointing |
|
|
26
|
+
| [0008](./0008-checkpointing.md) | Checkpointing | Partially Implemented |
|
|
27
27
|
| [0009](./0009-hooks-system.md) | Hooks System | Draft |
|
|
28
28
|
| [0010](./0010-mcp-integration.md) | MCP Integration | Draft |
|
|
29
|
-
| [
|
|
30
|
-
| [0012](./0012-ask-user-question.md) | AskUserQuestion Tool | Implemented |
|
|
29
|
+
| [0021](./0021-skills-system.md) | Skills System | Draft |
|
|
31
30
|
| [0041](./0041-configuration-system.md) | Configuration System | Implemented |
|
|
32
31
|
| [0042](./0042-prompt-optimization.md) | Prompt System Optimization | Implemented |
|
|
33
32
|
|
|
@@ -35,6 +34,8 @@ This directory contains enhancement proposals for the gencode project. Each prop
|
|
|
35
34
|
|
|
36
35
|
| ID | Title | Status |
|
|
37
36
|
|----|-------|--------|
|
|
37
|
+
| [0011](./0011-custom-commands.md) | Custom Commands | Draft |
|
|
38
|
+
| [0012](./0012-ask-user-question.md) | AskUserQuestion Tool | Implemented |
|
|
38
39
|
| [0013](./0013-multi-edit-tool.md) | MultiEdit Tool | Draft |
|
|
39
40
|
| [0014](./0014-lsp-tool.md) | LSP Tool | Draft |
|
|
40
41
|
| [0015](./0015-ls-tool.md) | LS Tool | Draft |
|
|
@@ -43,11 +44,10 @@ This directory contains enhancement proposals for the gencode project. Each prop
|
|
|
43
44
|
| [0018](./0018-parallel-tool-execution.md) | Parallel Tool Execution | Draft |
|
|
44
45
|
| [0019](./0019-session-enhancements.md) | Session Enhancements | Draft |
|
|
45
46
|
| [0020](./0020-session-summarization.md) | Session Summarization | Draft |
|
|
46
|
-
| [0021](./0021-skills-system.md) | Skills System | Draft |
|
|
47
47
|
| [0022](./0022-plugin-system.md) | Plugin System | Draft |
|
|
48
48
|
| [0023](./0023-permission-enhancements.md) | Permission Enhancements | Draft |
|
|
49
49
|
| [0024](./0024-keyboard-shortcuts.md) | Keyboard Shortcuts | Draft |
|
|
50
|
-
| [0025](./0025-cost-tracking.md) | Cost Tracking |
|
|
50
|
+
| [0025](./0025-cost-tracking.md) | Cost Tracking | Implemented |
|
|
51
51
|
| [0026](./0026-git-integration.md) | Git Integration | Draft |
|
|
52
52
|
| [0027](./0027-enhanced-read-tool.md) | Enhanced Read Tool | Draft |
|
|
53
53
|
| [0028](./0028-enhanced-bash-tool.md) | Enhanced Bash Tool | Draft |
|
package/docs/providers.md
CHANGED
|
@@ -131,16 +131,25 @@ To use Claude models via Google Vertex AI:
|
|
|
131
131
|
### 1. Set Environment Variables
|
|
132
132
|
|
|
133
133
|
```bash
|
|
134
|
+
# Required: Enable Vertex AI
|
|
135
|
+
export CLAUDE_CODE_USE_VERTEX=1
|
|
136
|
+
|
|
134
137
|
# Required: Your GCP project ID
|
|
135
138
|
export ANTHROPIC_VERTEX_PROJECT_ID="your-project-id"
|
|
136
139
|
|
|
137
|
-
#
|
|
138
|
-
export
|
|
140
|
+
# Required: Region (use 'global' or specific region)
|
|
141
|
+
export CLOUD_ML_REGION=global
|
|
139
142
|
```
|
|
140
143
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
+
**Environment Variable Details:**
|
|
145
|
+
|
|
146
|
+
| Variable | Required | Default | Description |
|
|
147
|
+
|----------|----------|---------|-------------|
|
|
148
|
+
| `CLAUDE_CODE_USE_VERTEX` | Yes | - | Set to `1` to enable Vertex AI |
|
|
149
|
+
| `ANTHROPIC_VERTEX_PROJECT_ID` | Yes | - | Your GCP project ID (also accepts `GCLOUD_PROJECT` or `GOOGLE_CLOUD_PROJECT`) |
|
|
150
|
+
| `CLOUD_ML_REGION` | Yes | `us-east5` | Region (use `global` or specific region like `us-east5`) |
|
|
151
|
+
|
|
152
|
+
**Documentation:** https://code.claude.com/docs/en/google-vertex-ai
|
|
144
153
|
|
|
145
154
|
### 2. Authenticate with Google Cloud
|
|
146
155
|
|
|
@@ -169,12 +178,24 @@ gcloud services enable aiplatform.googleapis.com
|
|
|
169
178
|
# Press Enter to connect
|
|
170
179
|
```
|
|
171
180
|
|
|
181
|
+
## Architecture
|
|
182
|
+
|
|
183
|
+
GenCode uses a two-layer provider architecture:
|
|
184
|
+
|
|
185
|
+
- **Layer 1: Provider** (Semantic layer) - `anthropic` | `openai` | `gemini`
|
|
186
|
+
- **Layer 2: AuthMethod** (Implementation layer) - `api_key` | `vertex` | `bedrock` | `azure`
|
|
187
|
+
|
|
188
|
+
Each provider can support multiple authentication methods. For example, Anthropic supports:
|
|
189
|
+
- `api_key` - Direct API access
|
|
190
|
+
- `vertex` - Google Vertex AI
|
|
191
|
+
- `bedrock` - Amazon Bedrock (coming soon)
|
|
192
|
+
|
|
172
193
|
## Configuration Storage
|
|
173
194
|
|
|
174
195
|
Provider connections and cached models are stored in:
|
|
175
196
|
|
|
176
197
|
```
|
|
177
|
-
~/.
|
|
198
|
+
~/.gen/
|
|
178
199
|
├── settings.json # Current model and provider settings
|
|
179
200
|
└── providers.json # Provider connections and model cache
|
|
180
201
|
```
|
|
@@ -185,23 +206,87 @@ Provider connections and cached models are stored in:
|
|
|
185
206
|
{
|
|
186
207
|
"connections": {
|
|
187
208
|
"anthropic": {
|
|
188
|
-
"
|
|
209
|
+
"authMethod": "vertex",
|
|
210
|
+
"method": "Google Vertex AI",
|
|
189
211
|
"connectedAt": "2025-01-15T10:00:00Z"
|
|
212
|
+
},
|
|
213
|
+
"openai": {
|
|
214
|
+
"authMethod": "api_key",
|
|
215
|
+
"method": "Direct API",
|
|
216
|
+
"connectedAt": "2025-01-15T09:00:00Z"
|
|
190
217
|
}
|
|
191
218
|
},
|
|
192
219
|
"models": {
|
|
193
|
-
"anthropic": {
|
|
220
|
+
"anthropic:vertex": {
|
|
194
221
|
"cachedAt": "2025-01-15T10:00:00Z",
|
|
222
|
+
"list": [
|
|
223
|
+
{ "id": "claude-3-5-sonnet@20241022", "name": "Claude 3.5 Sonnet" }
|
|
224
|
+
]
|
|
225
|
+
},
|
|
226
|
+
"anthropic:api_key": {
|
|
227
|
+
"cachedAt": "2025-01-15T11:00:00Z",
|
|
195
228
|
"list": [
|
|
196
229
|
{ "id": "claude-sonnet-4-5@20250929", "name": "Claude Sonnet 4.5" }
|
|
197
230
|
]
|
|
231
|
+
},
|
|
232
|
+
"openai:api_key": {
|
|
233
|
+
"cachedAt": "2025-01-15T09:00:00Z",
|
|
234
|
+
"list": [
|
|
235
|
+
{ "id": "gpt-4", "name": "GPT-4" }
|
|
236
|
+
]
|
|
198
237
|
}
|
|
199
238
|
},
|
|
200
239
|
"searchProvider": "exa"
|
|
201
240
|
}
|
|
202
241
|
```
|
|
203
242
|
|
|
204
|
-
|
|
243
|
+
**Key points:**
|
|
244
|
+
- `connections` stores the active connection for each provider
|
|
245
|
+
- `authMethod` - Authentication method being used
|
|
246
|
+
- `method` - Display name (optional, legacy field)
|
|
247
|
+
- `models` uses `"provider:authMethod"` as the key
|
|
248
|
+
- Supports multiple auth methods for the same provider
|
|
249
|
+
- Each auth method has its own cached model list
|
|
250
|
+
- `searchProvider` - Selected search provider (`exa`, `serper`, `brave`)
|
|
251
|
+
|
|
252
|
+
### Migration from Old Format
|
|
253
|
+
|
|
254
|
+
If you're upgrading from an older version, run the migration script to update your configuration:
|
|
255
|
+
|
|
256
|
+
```bash
|
|
257
|
+
npm run migrate
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
The script will:
|
|
261
|
+
1. Convert old format models keys (e.g., `"anthropic"`) to new format (e.g., `"anthropic:vertex"`)
|
|
262
|
+
2. Add `authMethod` field to connections
|
|
263
|
+
3. Create a backup of your old configuration
|
|
264
|
+
|
|
265
|
+
**Old format:**
|
|
266
|
+
```json
|
|
267
|
+
{
|
|
268
|
+
"models": {
|
|
269
|
+
"anthropic": {
|
|
270
|
+
"provider": "anthropic",
|
|
271
|
+
"authMethod": "vertex",
|
|
272
|
+
"cachedAt": "...",
|
|
273
|
+
"list": [...]
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
**New format:**
|
|
280
|
+
```json
|
|
281
|
+
{
|
|
282
|
+
"models": {
|
|
283
|
+
"anthropic:vertex": {
|
|
284
|
+
"cachedAt": "...",
|
|
285
|
+
"list": [...]
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
```
|
|
205
290
|
|
|
206
291
|
## Troubleshooting
|
|
207
292
|
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test Checkpointing System
|
|
3
|
+
*
|
|
4
|
+
* This example demonstrates the automatic file change tracking and rewind capabilities.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { CheckpointManager } from '../src/checkpointing/index.js';
|
|
8
|
+
import * as fs from 'fs/promises';
|
|
9
|
+
import * as path from 'path';
|
|
10
|
+
import { fileURLToPath } from 'url';
|
|
11
|
+
|
|
12
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
13
|
+
const __dirname = path.dirname(__filename);
|
|
14
|
+
|
|
15
|
+
async function testCheckpointing() {
|
|
16
|
+
console.log('🧪 Testing Checkpointing System\n');
|
|
17
|
+
|
|
18
|
+
const manager = new CheckpointManager('test-session');
|
|
19
|
+
const testDir = path.join(__dirname, '../.test-checkpoints');
|
|
20
|
+
const testFile = path.join(testDir, 'example.txt');
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
// Create test directory
|
|
24
|
+
await fs.mkdir(testDir, { recursive: true });
|
|
25
|
+
|
|
26
|
+
console.log('1️⃣ Recording file creation...');
|
|
27
|
+
const originalContent = 'Hello, World!';
|
|
28
|
+
await fs.writeFile(testFile, originalContent, 'utf-8');
|
|
29
|
+
|
|
30
|
+
manager.recordChange({
|
|
31
|
+
path: testFile,
|
|
32
|
+
changeType: 'create',
|
|
33
|
+
previousContent: null,
|
|
34
|
+
newContent: originalContent,
|
|
35
|
+
toolName: 'Write',
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
console.log(' ✓ File created:', testFile);
|
|
39
|
+
console.log(' ✓ Checkpoint recorded\n');
|
|
40
|
+
|
|
41
|
+
console.log('2️⃣ Recording file modification...');
|
|
42
|
+
const modifiedContent = 'Hello, Checkpointing!';
|
|
43
|
+
await fs.writeFile(testFile, modifiedContent, 'utf-8');
|
|
44
|
+
|
|
45
|
+
manager.recordChange({
|
|
46
|
+
path: testFile,
|
|
47
|
+
changeType: 'modify',
|
|
48
|
+
previousContent: originalContent,
|
|
49
|
+
newContent: modifiedContent,
|
|
50
|
+
toolName: 'Edit',
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
console.log(' ✓ File modified');
|
|
54
|
+
console.log(' ✓ Checkpoint recorded\n');
|
|
55
|
+
|
|
56
|
+
console.log('3️⃣ Listing checkpoints...');
|
|
57
|
+
console.log(manager.formatCheckpointList(true));
|
|
58
|
+
console.log();
|
|
59
|
+
|
|
60
|
+
console.log('4️⃣ Getting summary...');
|
|
61
|
+
const summary = manager.getSummary();
|
|
62
|
+
console.log(` Created: ${summary.created}`);
|
|
63
|
+
console.log(` Modified: ${summary.modified}`);
|
|
64
|
+
console.log(` Deleted: ${summary.deleted}`);
|
|
65
|
+
console.log(` Total: ${summary.total}\n`);
|
|
66
|
+
|
|
67
|
+
console.log('5️⃣ Rewinding last change...');
|
|
68
|
+
const result = await manager.rewind({ count: 1 });
|
|
69
|
+
|
|
70
|
+
if (result.success) {
|
|
71
|
+
console.log(' ✓ Rewind successful');
|
|
72
|
+
result.revertedFiles.forEach((f) => {
|
|
73
|
+
console.log(` • ${path.basename(f.path)} (${f.action})`);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// Verify content was restored
|
|
77
|
+
const restoredContent = await fs.readFile(testFile, 'utf-8');
|
|
78
|
+
if (restoredContent === originalContent) {
|
|
79
|
+
console.log(' ✓ Content restored correctly\n');
|
|
80
|
+
} else {
|
|
81
|
+
console.log(' ✗ Content mismatch!\n');
|
|
82
|
+
}
|
|
83
|
+
} else {
|
|
84
|
+
console.log(' ✗ Rewind failed');
|
|
85
|
+
result.errors.forEach((e) => console.log(` ${e.error}`));
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
console.log('6️⃣ Rewinding all changes...');
|
|
89
|
+
const finalResult = await manager.rewind({ all: true });
|
|
90
|
+
|
|
91
|
+
if (finalResult.success) {
|
|
92
|
+
console.log(' ✓ All changes reverted');
|
|
93
|
+
finalResult.revertedFiles.forEach((f) => {
|
|
94
|
+
console.log(` • ${path.basename(f.path)} (${f.action})`);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
// Verify file was deleted
|
|
98
|
+
try {
|
|
99
|
+
await fs.access(testFile);
|
|
100
|
+
console.log(' ✗ File still exists!\n');
|
|
101
|
+
} catch {
|
|
102
|
+
console.log(' ✓ File was deleted as expected\n');
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
console.log('✅ All tests passed!\n');
|
|
107
|
+
} catch (error) {
|
|
108
|
+
console.error('❌ Test failed:', error);
|
|
109
|
+
} finally {
|
|
110
|
+
// Cleanup
|
|
111
|
+
try {
|
|
112
|
+
await fs.rm(testDir, { recursive: true, force: true });
|
|
113
|
+
console.log('🧹 Cleaned up test directory');
|
|
114
|
+
} catch {
|
|
115
|
+
// Ignore cleanup errors
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Run the test
|
|
121
|
+
testCheckpointing();
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test cost tracking functionality
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { createProvider } from '../src/providers/index.js';
|
|
6
|
+
import { calculateCost, formatCost, formatTokens } from '../src/pricing/calculator.js';
|
|
7
|
+
|
|
8
|
+
async function testCostTracking() {
|
|
9
|
+
console.log('='.repeat(60));
|
|
10
|
+
console.log('Testing Cost Tracking Feature');
|
|
11
|
+
console.log('='.repeat(60));
|
|
12
|
+
console.log();
|
|
13
|
+
|
|
14
|
+
// Test 1: Cost Calculation
|
|
15
|
+
console.log('Test 1: Cost Calculation');
|
|
16
|
+
console.log('-'.repeat(60));
|
|
17
|
+
|
|
18
|
+
const testCases = [
|
|
19
|
+
{ provider: 'anthropic', model: 'claude-sonnet-4', input: 1000, output: 500 },
|
|
20
|
+
{ provider: 'openai', model: 'gpt-4o', input: 1000, output: 500 },
|
|
21
|
+
{ provider: 'gemini', model: 'gemini-2.0-flash', input: 1000, output: 500 },
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
for (const test of testCases) {
|
|
25
|
+
const cost = calculateCost(test.provider, test.model, {
|
|
26
|
+
inputTokens: test.input,
|
|
27
|
+
outputTokens: test.output,
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
console.log(`\n${test.provider}/${test.model}:`);
|
|
31
|
+
console.log(` Input: ${formatTokens(test.input)} tokens`);
|
|
32
|
+
console.log(` Output: ${formatTokens(test.output)} tokens`);
|
|
33
|
+
console.log(` Cost: ${formatCost(cost.totalCost)}`);
|
|
34
|
+
console.log(` Breakdown: ${formatCost(cost.inputCost)} (input) + ${formatCost(cost.outputCost)} (output)`);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
console.log();
|
|
38
|
+
console.log('='.repeat(60));
|
|
39
|
+
console.log();
|
|
40
|
+
|
|
41
|
+
// Test 2: Real API Call (if env var is set)
|
|
42
|
+
if (process.env.ANTHROPIC_API_KEY) {
|
|
43
|
+
console.log('Test 2: Real API Call with Anthropic');
|
|
44
|
+
console.log('-'.repeat(60));
|
|
45
|
+
|
|
46
|
+
const provider = createProvider({ provider: 'anthropic', model: 'claude-haiku-3-5' });
|
|
47
|
+
|
|
48
|
+
const response = await provider.complete({
|
|
49
|
+
model: 'claude-haiku-3-5',
|
|
50
|
+
messages: [{ role: 'user', content: 'Say hello in one word' }],
|
|
51
|
+
maxTokens: 10,
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
console.log('\nResponse:', response.content[0]?.type === 'text' ? response.content[0].text : '');
|
|
55
|
+
|
|
56
|
+
if (response.usage) {
|
|
57
|
+
console.log(`\nToken Usage:`);
|
|
58
|
+
console.log(` Input: ${formatTokens(response.usage.inputTokens)}`);
|
|
59
|
+
console.log(` Output: ${formatTokens(response.usage.outputTokens)}`);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (response.cost) {
|
|
63
|
+
console.log(`\nCost Estimate:`);
|
|
64
|
+
console.log(` Total: ${formatCost(response.cost.totalCost)}`);
|
|
65
|
+
console.log(` Input: ${formatCost(response.cost.inputCost)}`);
|
|
66
|
+
console.log(` Output: ${formatCost(response.cost.outputCost)}`);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
console.log();
|
|
70
|
+
console.log('='.repeat(60));
|
|
71
|
+
} else {
|
|
72
|
+
console.log('Skipping API test (no ANTHROPIC_API_KEY)');
|
|
73
|
+
console.log('='.repeat(60));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
testCostTracking().catch(console.error);
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test Interrupt Cleanup
|
|
3
|
+
*
|
|
4
|
+
* Simulates the interrupt scenario and verifies cleanup works correctly
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { Agent } from '../src/agent/index.js';
|
|
8
|
+
import type { Message } from '../src/providers/types.js';
|
|
9
|
+
|
|
10
|
+
async function testInterruptCleanup() {
|
|
11
|
+
console.log('🧪 Testing Interrupt Cleanup\n');
|
|
12
|
+
|
|
13
|
+
const agent = new Agent({
|
|
14
|
+
provider: 'anthropic',
|
|
15
|
+
model: 'claude-3-5-sonnet-20241022',
|
|
16
|
+
cwd: process.cwd(),
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
try {
|
|
20
|
+
// Simulate incomplete tool_use message (what happens during interrupt)
|
|
21
|
+
console.log('1️⃣ Simulating incomplete tool_use message...');
|
|
22
|
+
|
|
23
|
+
// Access private messages array via getHistory and direct manipulation
|
|
24
|
+
const history = agent.getHistory();
|
|
25
|
+
console.log(` Initial history: ${history.length} messages`);
|
|
26
|
+
|
|
27
|
+
// Add a user message
|
|
28
|
+
(agent as any).messages.push({
|
|
29
|
+
role: 'user',
|
|
30
|
+
content: 'Create a file',
|
|
31
|
+
});
|
|
32
|
+
console.log(` After user message: ${agent.getHistory().length} messages`);
|
|
33
|
+
|
|
34
|
+
// Add an assistant message with tool_use (simulating interrupt point)
|
|
35
|
+
(agent as any).messages.push({
|
|
36
|
+
role: 'assistant',
|
|
37
|
+
content: [
|
|
38
|
+
{ type: 'text', text: 'I will create the file.' },
|
|
39
|
+
{
|
|
40
|
+
type: 'tool_use',
|
|
41
|
+
id: 'toolu_test_123',
|
|
42
|
+
name: 'Write',
|
|
43
|
+
input: { file_path: 'test.txt', content: 'hello' },
|
|
44
|
+
},
|
|
45
|
+
],
|
|
46
|
+
});
|
|
47
|
+
console.log(` After assistant+tool_use: ${agent.getHistory().length} messages`);
|
|
48
|
+
console.log(` Last message role: ${agent.getHistory()[agent.getHistory().length - 1].role}`);
|
|
49
|
+
|
|
50
|
+
// Verify incomplete state
|
|
51
|
+
const lastMessage = agent.getHistory()[agent.getHistory().length - 1];
|
|
52
|
+
const hasToolUse = Array.isArray(lastMessage.content) &&
|
|
53
|
+
lastMessage.content.some((c: any) => c.type === 'tool_use');
|
|
54
|
+
console.log(` Has incomplete tool_use: ${hasToolUse}\n`);
|
|
55
|
+
|
|
56
|
+
console.log('2️⃣ Calling cleanupIncompleteMessages()...');
|
|
57
|
+
agent.cleanupIncompleteMessages();
|
|
58
|
+
|
|
59
|
+
const afterCleanup = agent.getHistory();
|
|
60
|
+
console.log(` After cleanup: ${afterCleanup.length} messages`);
|
|
61
|
+
|
|
62
|
+
if (afterCleanup.length === 1 && afterCleanup[0].role === 'user') {
|
|
63
|
+
console.log(' ✓ Incomplete assistant message removed!\n');
|
|
64
|
+
} else {
|
|
65
|
+
console.log(' ✗ Cleanup failed!\n');
|
|
66
|
+
console.log(' Remaining messages:', JSON.stringify(afterCleanup, null, 2));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
console.log('3️⃣ Testing with complete messages (no tool_use)...');
|
|
70
|
+
|
|
71
|
+
// Add complete assistant message
|
|
72
|
+
(agent as any).messages.push({
|
|
73
|
+
role: 'assistant',
|
|
74
|
+
content: [{ type: 'text', text: 'Here is your answer.' }],
|
|
75
|
+
});
|
|
76
|
+
console.log(` Before cleanup: ${agent.getHistory().length} messages`);
|
|
77
|
+
|
|
78
|
+
agent.cleanupIncompleteMessages();
|
|
79
|
+
console.log(` After cleanup: ${agent.getHistory().length} messages`);
|
|
80
|
+
|
|
81
|
+
if (agent.getHistory().length === 2) {
|
|
82
|
+
console.log(' ✓ Complete messages preserved!\n');
|
|
83
|
+
} else {
|
|
84
|
+
console.log(' ✗ Complete message was incorrectly removed!\n');
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
console.log('✅ All tests passed!\n');
|
|
88
|
+
} catch (error) {
|
|
89
|
+
console.error('❌ Test failed:', error);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Run the test
|
|
94
|
+
testInterruptCleanup();
|