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.
Files changed (260) hide show
  1. package/README.md +2 -1
  2. package/dist/agent/agent.d.ts +44 -2
  3. package/dist/agent/agent.d.ts.map +1 -1
  4. package/dist/agent/agent.js +130 -11
  5. package/dist/agent/agent.js.map +1 -1
  6. package/dist/agent/types.d.ts +11 -1
  7. package/dist/agent/types.d.ts.map +1 -1
  8. package/dist/checkpointing/checkpoint-manager.d.ts +87 -0
  9. package/dist/checkpointing/checkpoint-manager.d.ts.map +1 -0
  10. package/dist/checkpointing/checkpoint-manager.js +281 -0
  11. package/dist/checkpointing/checkpoint-manager.js.map +1 -0
  12. package/dist/checkpointing/index.d.ts +29 -0
  13. package/dist/checkpointing/index.d.ts.map +1 -0
  14. package/dist/checkpointing/index.js +29 -0
  15. package/dist/checkpointing/index.js.map +1 -0
  16. package/dist/checkpointing/types.d.ts +98 -0
  17. package/dist/checkpointing/types.d.ts.map +1 -0
  18. package/dist/checkpointing/types.js +7 -0
  19. package/dist/checkpointing/types.js.map +1 -0
  20. package/dist/cli/components/App.d.ts.map +1 -1
  21. package/dist/cli/components/App.js +171 -14
  22. package/dist/cli/components/App.js.map +1 -1
  23. package/dist/cli/components/CommandSuggestions.d.ts.map +1 -1
  24. package/dist/cli/components/CommandSuggestions.js +5 -0
  25. package/dist/cli/components/CommandSuggestions.js.map +1 -1
  26. package/dist/cli/components/Messages.d.ts +7 -1
  27. package/dist/cli/components/Messages.d.ts.map +1 -1
  28. package/dist/cli/components/Messages.js +12 -3
  29. package/dist/cli/components/Messages.js.map +1 -1
  30. package/dist/cli/components/ModeIndicator.d.ts +42 -0
  31. package/dist/cli/components/ModeIndicator.d.ts.map +1 -0
  32. package/dist/cli/components/ModeIndicator.js +52 -0
  33. package/dist/cli/components/ModeIndicator.js.map +1 -0
  34. package/dist/cli/components/ModelSelector.d.ts +4 -3
  35. package/dist/cli/components/ModelSelector.d.ts.map +1 -1
  36. package/dist/cli/components/ModelSelector.js +54 -37
  37. package/dist/cli/components/ModelSelector.js.map +1 -1
  38. package/dist/cli/components/PlanApproval.d.ts +36 -0
  39. package/dist/cli/components/PlanApproval.d.ts.map +1 -0
  40. package/dist/cli/components/PlanApproval.js +154 -0
  41. package/dist/cli/components/PlanApproval.js.map +1 -0
  42. package/dist/cli/components/ProviderManager.d.ts +2 -2
  43. package/dist/cli/components/ProviderManager.d.ts.map +1 -1
  44. package/dist/cli/components/ProviderManager.js +137 -156
  45. package/dist/cli/components/ProviderManager.js.map +1 -1
  46. package/dist/cli/components/theme.d.ts +2 -0
  47. package/dist/cli/components/theme.d.ts.map +1 -1
  48. package/dist/cli/components/theme.js +3 -0
  49. package/dist/cli/components/theme.js.map +1 -1
  50. package/dist/cli/index.js +30 -13
  51. package/dist/cli/index.js.map +1 -1
  52. package/dist/config/index.d.ts +2 -2
  53. package/dist/config/index.d.ts.map +1 -1
  54. package/dist/config/index.js +1 -1
  55. package/dist/config/index.js.map +1 -1
  56. package/dist/config/levels.d.ts +5 -5
  57. package/dist/config/levels.d.ts.map +1 -1
  58. package/dist/config/levels.js +20 -20
  59. package/dist/config/levels.js.map +1 -1
  60. package/dist/config/merger.js +1 -1
  61. package/dist/config/merger.js.map +1 -1
  62. package/dist/config/providers-config.d.ts +8 -5
  63. package/dist/config/providers-config.d.ts.map +1 -1
  64. package/dist/config/providers-config.js +19 -22
  65. package/dist/config/providers-config.js.map +1 -1
  66. package/dist/config/test-utils.d.ts +2 -2
  67. package/dist/config/test-utils.d.ts.map +1 -1
  68. package/dist/config/test-utils.js +4 -4
  69. package/dist/config/test-utils.js.map +1 -1
  70. package/dist/config/types.d.ts +23 -17
  71. package/dist/config/types.d.ts.map +1 -1
  72. package/dist/config/types.js +14 -14
  73. package/dist/config/types.js.map +1 -1
  74. package/dist/index.d.ts +1 -0
  75. package/dist/index.d.ts.map +1 -1
  76. package/dist/index.js +2 -0
  77. package/dist/index.js.map +1 -1
  78. package/dist/memory/memory-manager.d.ts +25 -12
  79. package/dist/memory/memory-manager.d.ts.map +1 -1
  80. package/dist/memory/memory-manager.js +241 -112
  81. package/dist/memory/memory-manager.js.map +1 -1
  82. package/dist/memory/test-utils.d.ts +1 -1
  83. package/dist/memory/test-utils.d.ts.map +1 -1
  84. package/dist/memory/test-utils.js +3 -3
  85. package/dist/memory/test-utils.js.map +1 -1
  86. package/dist/memory/types.d.ts +20 -10
  87. package/dist/memory/types.d.ts.map +1 -1
  88. package/dist/memory/types.js +13 -13
  89. package/dist/memory/types.js.map +1 -1
  90. package/dist/migration/migrate.d.ts +24 -0
  91. package/dist/migration/migrate.d.ts.map +1 -0
  92. package/dist/migration/migrate.js +164 -0
  93. package/dist/migration/migrate.js.map +1 -0
  94. package/dist/permissions/persistence.d.ts +2 -2
  95. package/dist/permissions/persistence.js +4 -4
  96. package/dist/permissions/persistence.js.map +1 -1
  97. package/dist/planning/index.d.ts +13 -0
  98. package/dist/planning/index.d.ts.map +1 -0
  99. package/dist/planning/index.js +15 -0
  100. package/dist/planning/index.js.map +1 -0
  101. package/dist/planning/plan-file.d.ts +59 -0
  102. package/dist/planning/plan-file.d.ts.map +1 -0
  103. package/dist/planning/plan-file.js +278 -0
  104. package/dist/planning/plan-file.js.map +1 -0
  105. package/dist/planning/state.d.ts +127 -0
  106. package/dist/planning/state.d.ts.map +1 -0
  107. package/dist/planning/state.js +261 -0
  108. package/dist/planning/state.js.map +1 -0
  109. package/dist/planning/tools/enter-plan-mode.d.ts +25 -0
  110. package/dist/planning/tools/enter-plan-mode.d.ts.map +1 -0
  111. package/dist/planning/tools/enter-plan-mode.js +98 -0
  112. package/dist/planning/tools/enter-plan-mode.js.map +1 -0
  113. package/dist/planning/tools/exit-plan-mode.d.ts +24 -0
  114. package/dist/planning/tools/exit-plan-mode.d.ts.map +1 -0
  115. package/dist/planning/tools/exit-plan-mode.js +149 -0
  116. package/dist/planning/tools/exit-plan-mode.js.map +1 -0
  117. package/dist/planning/types.d.ts +100 -0
  118. package/dist/planning/types.d.ts.map +1 -0
  119. package/dist/planning/types.js +28 -0
  120. package/dist/planning/types.js.map +1 -0
  121. package/dist/pricing/calculator.d.ts +21 -0
  122. package/dist/pricing/calculator.d.ts.map +1 -0
  123. package/dist/pricing/calculator.js +59 -0
  124. package/dist/pricing/calculator.js.map +1 -0
  125. package/dist/pricing/index.d.ts +7 -0
  126. package/dist/pricing/index.d.ts.map +1 -0
  127. package/dist/pricing/index.js +7 -0
  128. package/dist/pricing/index.js.map +1 -0
  129. package/dist/pricing/models.d.ts +20 -0
  130. package/dist/pricing/models.d.ts.map +1 -0
  131. package/dist/pricing/models.js +322 -0
  132. package/dist/pricing/models.js.map +1 -0
  133. package/dist/pricing/types.d.ts +30 -0
  134. package/dist/pricing/types.d.ts.map +1 -0
  135. package/dist/pricing/types.js +5 -0
  136. package/dist/pricing/types.js.map +1 -0
  137. package/dist/prompts/index.d.ts +5 -4
  138. package/dist/prompts/index.d.ts.map +1 -1
  139. package/dist/prompts/index.js +11 -8
  140. package/dist/prompts/index.js.map +1 -1
  141. package/dist/providers/anthropic.d.ts +2 -1
  142. package/dist/providers/anthropic.d.ts.map +1 -1
  143. package/dist/providers/anthropic.js +24 -10
  144. package/dist/providers/anthropic.js.map +1 -1
  145. package/dist/providers/gemini.d.ts +2 -1
  146. package/dist/providers/gemini.d.ts.map +1 -1
  147. package/dist/providers/gemini.js +28 -14
  148. package/dist/providers/gemini.js.map +1 -1
  149. package/dist/providers/index.d.ts +20 -10
  150. package/dist/providers/index.d.ts.map +1 -1
  151. package/dist/providers/index.js +48 -24
  152. package/dist/providers/index.js.map +1 -1
  153. package/dist/providers/openai.d.ts +2 -1
  154. package/dist/providers/openai.d.ts.map +1 -1
  155. package/dist/providers/openai.js +19 -8
  156. package/dist/providers/openai.js.map +1 -1
  157. package/dist/providers/registry.d.ts +48 -34
  158. package/dist/providers/registry.d.ts.map +1 -1
  159. package/dist/providers/registry.js +72 -88
  160. package/dist/providers/registry.js.map +1 -1
  161. package/dist/providers/store.d.ts +43 -17
  162. package/dist/providers/store.d.ts.map +1 -1
  163. package/dist/providers/store.js +112 -19
  164. package/dist/providers/store.js.map +1 -1
  165. package/dist/providers/types.d.ts +25 -0
  166. package/dist/providers/types.d.ts.map +1 -1
  167. package/dist/providers/vertex-ai.d.ts +15 -7
  168. package/dist/providers/vertex-ai.d.ts.map +1 -1
  169. package/dist/providers/vertex-ai.js +63 -23
  170. package/dist/providers/vertex-ai.js.map +1 -1
  171. package/dist/session/manager.d.ts +4 -0
  172. package/dist/session/manager.d.ts.map +1 -1
  173. package/dist/session/manager.js +8 -0
  174. package/dist/session/manager.js.map +1 -1
  175. package/dist/session/types.js +1 -1
  176. package/dist/session/types.js.map +1 -1
  177. package/dist/tools/index.d.ts +7 -1
  178. package/dist/tools/index.d.ts.map +1 -1
  179. package/dist/tools/index.js +7 -0
  180. package/dist/tools/index.js.map +1 -1
  181. package/dist/tools/registry.d.ts +13 -0
  182. package/dist/tools/registry.d.ts.map +1 -1
  183. package/dist/tools/registry.js +79 -2
  184. package/dist/tools/registry.js.map +1 -1
  185. package/docs/config-system-comparison.md +50 -50
  186. package/docs/cost-tracking-comparison.md +904 -0
  187. package/docs/memory-system.md +124 -31
  188. package/docs/operating-modes.md +96 -0
  189. package/docs/permissions.md +2 -2
  190. package/docs/proposals/0006-memory-system.md +4 -4
  191. package/docs/proposals/0008-checkpointing.md +109 -2
  192. package/docs/proposals/0011-custom-commands.md +2 -1
  193. package/docs/proposals/0021-skills-system.md +2 -1
  194. package/docs/proposals/0023-permission-enhancements.md +2 -2
  195. package/docs/proposals/0025-cost-tracking.md +60 -2
  196. package/docs/proposals/0033-enterprise-deployment.md +1 -1
  197. package/docs/proposals/0041-configuration-system.md +17 -19
  198. package/docs/proposals/0042-prompt-optimization.md +17 -9
  199. package/docs/proposals/README.md +6 -6
  200. package/docs/providers.md +94 -9
  201. package/examples/test-checkpointing.ts +121 -0
  202. package/examples/test-cost-tracking.ts +77 -0
  203. package/examples/test-interrupt-cleanup.ts +94 -0
  204. package/package.json +3 -2
  205. package/scripts/migrate.ts +449 -0
  206. package/src/agent/agent.ts +161 -12
  207. package/src/agent/types.ts +11 -1
  208. package/src/checkpointing/checkpoint-manager.ts +327 -0
  209. package/src/checkpointing/index.ts +45 -0
  210. package/src/checkpointing/types.ts +104 -0
  211. package/src/cli/components/App.tsx +221 -13
  212. package/src/cli/components/CommandSuggestions.tsx +5 -0
  213. package/src/cli/components/Messages.tsx +24 -5
  214. package/src/cli/components/ModeIndicator.tsx +174 -0
  215. package/src/cli/components/ModelSelector.tsx +62 -43
  216. package/src/cli/components/PlanApproval.tsx +327 -0
  217. package/src/cli/components/ProviderManager.tsx +278 -323
  218. package/src/cli/components/theme.ts +3 -0
  219. package/src/cli/index.tsx +36 -17
  220. package/src/config/index.ts +5 -3
  221. package/src/config/levels.test.ts +22 -22
  222. package/src/config/levels.ts +22 -22
  223. package/src/config/loader.test.ts +14 -14
  224. package/src/config/manager.test.ts +19 -19
  225. package/src/config/merger.test.ts +23 -23
  226. package/src/config/merger.ts +1 -1
  227. package/src/config/providers-config.ts +23 -21
  228. package/src/config/test-utils.ts +6 -6
  229. package/src/config/types.ts +30 -20
  230. package/src/index.ts +15 -0
  231. package/src/memory/memory-manager.test.ts +242 -24
  232. package/src/memory/memory-manager.ts +270 -141
  233. package/src/memory/test-utils.ts +4 -4
  234. package/src/memory/types.ts +28 -17
  235. package/src/permissions/persistence.ts +4 -4
  236. package/src/planning/index.ts +53 -0
  237. package/src/planning/plan-file.ts +326 -0
  238. package/src/planning/state.ts +305 -0
  239. package/src/planning/tools/enter-plan-mode.ts +111 -0
  240. package/src/planning/tools/exit-plan-mode.ts +170 -0
  241. package/src/planning/types.ts +150 -0
  242. package/src/pricing/calculator.ts +71 -0
  243. package/src/pricing/index.ts +7 -0
  244. package/src/pricing/models.ts +334 -0
  245. package/src/pricing/types.ts +32 -0
  246. package/src/prompts/index.ts +13 -9
  247. package/src/providers/anthropic.ts +30 -10
  248. package/src/providers/gemini.ts +34 -14
  249. package/src/providers/index.ts +76 -33
  250. package/src/providers/openai.ts +26 -8
  251. package/src/providers/registry.ts +116 -111
  252. package/src/providers/store.ts +130 -28
  253. package/src/providers/types.ts +36 -1
  254. package/src/providers/vertex-ai.ts +70 -23
  255. package/src/session/manager.ts +9 -0
  256. package/src/session/types.ts +1 -1
  257. package/src/tools/index.ts +8 -0
  258. package/src/tools/registry.ts +95 -2
  259. package/.gencode/settings.local.json +0 -7
  260. package/CLAUDE.md +0 -86
@@ -1,16 +1,25 @@
1
1
  /**
2
- * Google Vertex AI Provider Implementation
3
- * Supports Claude models deployed on Google Cloud Vertex AI
2
+ * Anthropic Vertex AI Provider
3
+ * Supports Claude models via Google Cloud Vertex AI
4
+ *
5
+ * Documentation: https://code.claude.com/docs/en/google-vertex-ai
6
+ *
7
+ * Required environment variables:
8
+ * - CLAUDE_CODE_USE_VERTEX=1
9
+ * - ANTHROPIC_VERTEX_PROJECT_ID=your-project-id
10
+ * - CLOUD_ML_REGION=global (or specific region like us-east5)
4
11
  *
5
12
  * Authentication uses Google Cloud's default credential chain:
6
- * 1. GOOGLE_APPLICATION_CREDENTIALS (service account JSON)
7
- * 2. gcloud auth application-default login (ADC)
13
+ * 1. gcloud auth application-default login (recommended)
14
+ * 2. GOOGLE_APPLICATION_CREDENTIALS (service account JSON)
8
15
  * 3. GCE/GKE metadata service (when running on GCP)
9
16
  */
10
17
 
11
18
  import { GoogleAuth } from 'google-auth-library';
19
+ import { calculateCost } from '../pricing/calculator.js';
12
20
  import type {
13
21
  LLMProvider,
22
+ ProviderClassMeta,
14
23
  CompletionOptions,
15
24
  CompletionResponse,
16
25
  StreamChunk,
@@ -128,23 +137,40 @@ type StreamEvent =
128
137
  | { type: 'message_stop' }
129
138
  | { type: 'ping' };
130
139
 
131
- export class VertexAIProvider implements LLMProvider {
132
- readonly name = 'vertex-ai';
140
+ export class AnthropicVertexProvider implements LLMProvider {
141
+ static readonly meta: ProviderClassMeta = {
142
+ provider: 'anthropic',
143
+ authMethod: 'vertex',
144
+ envVars: [
145
+ 'CLAUDE_CODE_USE_VERTEX',
146
+ 'ANTHROPIC_VERTEX_PROJECT_ID',
147
+ 'CLOUD_ML_REGION',
148
+ ],
149
+ displayName: 'Google Vertex AI',
150
+ description: 'Claude via Google Cloud Platform',
151
+ };
152
+
153
+ readonly name = 'anthropic-vertex';
133
154
  private projectId: string;
134
155
  private region: string;
135
156
  private auth: GoogleAuth;
136
157
  private accessToken?: string;
137
158
 
138
159
  constructor(config: VertexAIConfig = {}) {
160
+ // Project ID priority (per Claude Code docs):
161
+ // 1. config.projectId
162
+ // 2. ANTHROPIC_VERTEX_PROJECT_ID
163
+ // 3. GCLOUD_PROJECT
164
+ // 4. GOOGLE_CLOUD_PROJECT
139
165
  this.projectId =
140
166
  config.projectId ??
141
167
  process.env.ANTHROPIC_VERTEX_PROJECT_ID ??
168
+ process.env.GCLOUD_PROJECT ??
142
169
  process.env.GOOGLE_CLOUD_PROJECT ??
143
170
  '';
144
171
 
145
172
  this.region =
146
173
  config.region ??
147
- process.env.ANTHROPIC_VERTEX_REGION ??
148
174
  process.env.CLOUD_ML_REGION ??
149
175
  'us-east5';
150
176
 
@@ -152,7 +178,7 @@ export class VertexAIProvider implements LLMProvider {
152
178
 
153
179
  if (!this.projectId) {
154
180
  throw new Error(
155
- 'Vertex AI requires a project ID. Set ANTHROPIC_VERTEX_PROJECT_ID environment variable.'
181
+ 'Vertex AI requires a project ID. Set one of: ANTHROPIC_VERTEX_PROJECT_ID, GCLOUD_PROJECT, or GOOGLE_CLOUD_PROJECT'
156
182
  );
157
183
  }
158
184
 
@@ -166,12 +192,23 @@ export class VertexAIProvider implements LLMProvider {
166
192
  return this.accessToken;
167
193
  }
168
194
 
169
- const client = await this.auth.getClient();
170
- const tokenResponse = await client.getAccessToken();
171
- if (!tokenResponse.token) {
172
- throw new Error('Failed to get access token from Google Cloud');
195
+ try {
196
+ const client = await this.auth.getClient();
197
+ const tokenResponse = await client.getAccessToken();
198
+ if (!tokenResponse.token) {
199
+ throw new Error('Failed to get access token from Google Cloud');
200
+ }
201
+ return tokenResponse.token;
202
+ } catch (error) {
203
+ const message = error instanceof Error ? error.message : String(error);
204
+ throw new Error(
205
+ `Failed to authenticate with Google Cloud. Please ensure you have:\n` +
206
+ `1. Run: gcloud auth application-default login\n` +
207
+ `2. Set ANTHROPIC_VERTEX_PROJECT_ID or GOOGLE_CLOUD_PROJECT\n` +
208
+ `3. Enabled Vertex AI API in your GCP project\n` +
209
+ `Original error: ${message}`
210
+ );
173
211
  }
174
- return tokenResponse.token;
175
212
  }
176
213
 
177
214
  private getEndpoint(model: string, stream: boolean = false): string {
@@ -210,7 +247,7 @@ export class VertexAIProvider implements LLMProvider {
210
247
  }
211
248
 
212
249
  const data = (await response.json()) as VertexAIResponse;
213
- return this.convertResponse(data);
250
+ return this.convertResponse(data, options.model);
214
251
  }
215
252
 
216
253
  async *stream(options: CompletionOptions): AsyncGenerator<StreamChunk, void, unknown> {
@@ -337,15 +374,20 @@ export class VertexAIProvider implements LLMProvider {
337
374
  // Build final response
338
375
  const content = this.buildFinalContent(contentBlocks, toolInputBuffers);
339
376
 
377
+ const usage = {
378
+ inputTokens,
379
+ outputTokens,
380
+ };
381
+
382
+ const cost = calculateCost(this.name, options.model, usage);
383
+
340
384
  yield {
341
385
  type: 'done',
342
386
  response: {
343
387
  content,
344
388
  stopReason,
345
- usage: {
346
- inputTokens,
347
- outputTokens,
348
- },
389
+ usage,
390
+ cost,
349
391
  },
350
392
  };
351
393
  }
@@ -449,14 +491,19 @@ export class VertexAIProvider implements LLMProvider {
449
491
  }));
450
492
  }
451
493
 
452
- private convertResponse(response: VertexAIResponse): CompletionResponse {
494
+ private convertResponse(response: VertexAIResponse, model: string): CompletionResponse {
495
+ const usage = {
496
+ inputTokens: response.usage.input_tokens,
497
+ outputTokens: response.usage.output_tokens,
498
+ };
499
+
500
+ const cost = calculateCost(this.name, model, usage);
501
+
453
502
  return {
454
503
  content: this.convertContent(response.content),
455
504
  stopReason: this.convertStopReason(response.stop_reason),
456
- usage: {
457
- inputTokens: response.usage.input_tokens,
458
- outputTokens: response.usage.output_tokens,
459
- },
505
+ usage,
506
+ cost,
460
507
  };
461
508
  }
462
509
 
@@ -326,6 +326,15 @@ export class SessionManager {
326
326
  }
327
327
  }
328
328
 
329
+ /**
330
+ * Remove the last message from current session
331
+ */
332
+ removeLastMessage(): void {
333
+ if (this.currentSession && this.currentSession.messages.length > 0) {
334
+ this.currentSession.messages.pop();
335
+ }
336
+ }
337
+
329
338
  /**
330
339
  * Export session to JSON
331
340
  */
@@ -42,7 +42,7 @@ export interface SessionConfig {
42
42
  }
43
43
 
44
44
  export const DEFAULT_SESSION_CONFIG: SessionConfig = {
45
- storageDir: '~/.gencode/sessions',
45
+ storageDir: '~/.gen/sessions',
46
46
  maxSessions: 50,
47
47
  maxAge: 30,
48
48
  autoSave: true,
@@ -28,6 +28,9 @@ export type {
28
28
  AskUserQuestionResult,
29
29
  } from './builtin/ask-user.js';
30
30
 
31
+ // Plan mode tools
32
+ export { enterPlanModeTool, exitPlanModeTool } from '../planning/index.js';
33
+
31
34
  import { ToolRegistry } from './registry.js';
32
35
  import { readTool } from './builtin/read.js';
33
36
  import { writeTool } from './builtin/write.js';
@@ -39,6 +42,7 @@ import { webfetchTool } from './builtin/webfetch.js';
39
42
  import { websearchTool } from './builtin/websearch.js';
40
43
  import { todowriteTool } from './builtin/todowrite.js';
41
44
  import { askUserQuestionTool } from './builtin/ask-user.js';
45
+ import { enterPlanModeTool, exitPlanModeTool } from '../planning/index.js';
42
46
 
43
47
  /**
44
48
  * Create a registry with all built-in tools
@@ -56,6 +60,8 @@ export function createDefaultRegistry(): ToolRegistry {
56
60
  websearchTool,
57
61
  todowriteTool,
58
62
  askUserQuestionTool,
63
+ enterPlanModeTool,
64
+ exitPlanModeTool,
59
65
  ]);
60
66
  return registry;
61
67
  }
@@ -74,4 +80,6 @@ export const builtinTools = [
74
80
  websearchTool,
75
81
  todowriteTool,
76
82
  askUserQuestionTool,
83
+ enterPlanModeTool,
84
+ exitPlanModeTool,
77
85
  ];
@@ -2,9 +2,16 @@
2
2
  * Tool Registry - Manages available tools
3
3
  */
4
4
 
5
+ import * as fs from 'fs/promises';
5
6
  import type { Tool, ToolContext, ToolResult } from './types.js';
6
- import { zodToJsonSchema, getErrorMessage } from './types.js';
7
+ import { zodToJsonSchema, getErrorMessage, resolvePath } from './types.js';
7
8
  import type { ToolDefinition } from '../providers/types.js';
9
+ import { getPlanModeManager } from '../planning/index.js';
10
+ import { getCheckpointManager } from '../checkpointing/index.js';
11
+ import type { ChangeType } from '../checkpointing/index.js';
12
+
13
+ // Tools that modify files and should be tracked for checkpointing
14
+ const CHECKPOINT_TOOLS = ['Write', 'Edit'];
8
15
 
9
16
  export class ToolRegistry {
10
17
  private tools: Map<string, Tool> = new Map();
@@ -50,6 +57,20 @@ export class ToolRegistry {
50
57
  .filter((t): t is ToolDefinition => t !== null);
51
58
  }
52
59
 
60
+ /**
61
+ * Get tool definitions filtered by plan mode
62
+ * In plan mode, only read-only tools are returned
63
+ */
64
+ getFilteredDefinitions(toolNames?: string[]): ToolDefinition[] {
65
+ const planManager = getPlanModeManager();
66
+ const names = toolNames ?? this.list();
67
+
68
+ // Filter tools based on plan mode state
69
+ const filteredNames = planManager.filterTools(names);
70
+
71
+ return this.getDefinitions(filteredNames);
72
+ }
73
+
53
74
  /**
54
75
  * Execute a tool by name
55
76
  */
@@ -75,9 +96,81 @@ export class ToolRegistry {
75
96
  };
76
97
  }
77
98
 
78
- return await tool.execute(parsed.data, context);
99
+ // Capture pre-execution state for checkpointing
100
+ let preState: { filePath: string; content: string | null; existed: boolean } | null = null;
101
+ if (CHECKPOINT_TOOLS.includes(name) && parsed.data && typeof parsed.data === 'object') {
102
+ const filePath = (parsed.data as { file_path?: string }).file_path;
103
+ if (filePath) {
104
+ preState = await this.captureFileState(filePath, context.cwd);
105
+ }
106
+ }
107
+
108
+ // Execute the tool
109
+ const result = await tool.execute(parsed.data, context);
110
+
111
+ // Record checkpoint on successful file modification
112
+ if (result.success && preState) {
113
+ await this.recordCheckpoint(name, preState, context.cwd);
114
+ }
115
+
116
+ return result;
79
117
  } catch (error) {
80
118
  return { success: false, output: '', error: `Tool execution failed: ${getErrorMessage(error)}` };
81
119
  }
82
120
  }
121
+
122
+ /**
123
+ * Capture file state before modification
124
+ */
125
+ private async captureFileState(
126
+ filePath: string,
127
+ cwd: string
128
+ ): Promise<{ filePath: string; content: string | null; existed: boolean }> {
129
+ const resolvedPath = resolvePath(filePath, cwd);
130
+ try {
131
+ const content = await fs.readFile(resolvedPath, 'utf-8');
132
+ return { filePath: resolvedPath, content, existed: true };
133
+ } catch {
134
+ // File doesn't exist
135
+ return { filePath: resolvedPath, content: null, existed: false };
136
+ }
137
+ }
138
+
139
+ /**
140
+ * Record a checkpoint after file modification
141
+ */
142
+ private async recordCheckpoint(
143
+ toolName: string,
144
+ preState: { filePath: string; content: string | null; existed: boolean },
145
+ cwd: string
146
+ ): Promise<void> {
147
+ const checkpointManager = getCheckpointManager();
148
+
149
+ // Read current file content
150
+ let newContent: string | null = null;
151
+ try {
152
+ newContent = await fs.readFile(preState.filePath, 'utf-8');
153
+ } catch {
154
+ // File was deleted or doesn't exist
155
+ }
156
+
157
+ // Determine change type
158
+ let changeType: ChangeType;
159
+ if (!preState.existed && newContent !== null) {
160
+ changeType = 'create';
161
+ } else if (preState.existed && newContent === null) {
162
+ changeType = 'delete';
163
+ } else {
164
+ changeType = 'modify';
165
+ }
166
+
167
+ // Record the change
168
+ checkpointManager.recordChange({
169
+ path: preState.filePath,
170
+ changeType,
171
+ previousContent: preState.content,
172
+ newContent,
173
+ toolName,
174
+ });
175
+ }
83
176
  }
@@ -1,7 +0,0 @@
1
- {
2
- "permissions": {
3
- "allow": [
4
- "Bash(cd /Users/myan/Workspace/ideas/gencode:*)"
5
- ]
6
- }
7
- }
package/CLAUDE.md DELETED
@@ -1,86 +0,0 @@
1
- # CLAUDE.md
2
-
3
- This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
-
5
- ## Project Overview
6
-
7
- **GenCode** (npm: `gencode-ai`) is an open-source AI assistant for the terminal. Extensible tools, customizable prompts, multi-provider support.
8
-
9
- ## Build & Run Commands
10
-
11
- ```bash
12
- npm install # Install dependencies
13
- npm run build # Compile TypeScript to dist/
14
- npm run dev # Watch mode compilation
15
- npm start # Run CLI directly via tsx
16
- npm run example # Run examples/basic.ts
17
- ```
18
-
19
- ## Architecture
20
-
21
- ### Provider Abstraction Layer (`src/providers/`)
22
-
23
- Unified `LLMProvider` interface abstracts API differences:
24
- - `complete()` - Non-streaming completion
25
- - `stream()` - Streaming completion (AsyncGenerator)
26
-
27
- Each provider (OpenAI, Anthropic, Gemini) translates the unified message format to its native API format and back. The `createProvider()` factory instantiates providers by name.
28
-
29
- ### Tool System (`src/tools/`)
30
-
31
- Tools are defined with Zod schemas for input validation:
32
- ```typescript
33
- interface Tool<TInput> {
34
- name: string;
35
- description: string;
36
- parameters: z.ZodSchema<TInput>;
37
- execute(input: TInput, context: ToolContext): Promise<ToolResult>;
38
- }
39
- ```
40
-
41
- `ToolRegistry` manages tools and converts Zod schemas to JSON Schema for LLM consumption via `zodToJsonSchema()`.
42
-
43
- ### Agent Loop (`src/agent/agent.ts`)
44
-
45
- The `Agent` class implements the core conversation loop:
46
- 1. User message → LLM with tools
47
- 2. If `stopReason === 'tool_use'`: execute tools, append results, loop back
48
- 3. If `stopReason !== 'tool_use'`: done
49
-
50
- Events are yielded as `AgentEvent` (text, tool_start, tool_result, done, error).
51
-
52
- ### Session Management (`src/session/`)
53
-
54
- Sessions persist conversation history to `~/.gencode/sessions/` as JSON files. Supports resume, fork, list, and delete operations.
55
-
56
- ## Configuration
57
-
58
- Provider/model selection priority:
59
- 1. `GENCODE_PROVIDER` / `GENCODE_MODEL` env vars
60
- 2. Auto-detect from available API keys (ANTHROPIC_API_KEY → OPENAI_API_KEY → GOOGLE_API_KEY)
61
- 3. Default: Gemini
62
-
63
- Proxy: Set `HTTP_PROXY` or `HTTPS_PROXY` for network proxy support.
64
-
65
- ## Key Patterns
66
-
67
- - All file paths in tools should be resolved relative to `ToolContext.cwd`
68
- - Tool input validation uses Zod; errors returned as `ToolResult.error`
69
- - Provider implementations handle message format conversion internally
70
- - CLI commands start with `/` (e.g., `/sessions`, `/resume`, `/help`)
71
-
72
- ## Reference Projects
73
-
74
- Similar projects for learning and reference:
75
-
76
- | Project | Path | Description |
77
- |---------|------|-------------|
78
- | OpenCode | `/Users/myan/Workspace/opencode` | Go-based AI coding assistant with TUI, multi-provider support |
79
- | System Prompts Collection | `/Users/myan/Workspace/ideas/system-prompts-and-models-of-ai-tools` | Collection of system prompts from various AI tools (Claude Code, Cursor, etc.) |
80
- | Learn Claude Code | `/Users/myan/Workspace/ideas/learn-claude-code` | Educational resources for understanding Claude Code internals |
81
-
82
- ### Key Learnings from References
83
-
84
- - **OpenCode**: Go implementation with Ink-based TUI, LSP integration, conversation sessions
85
- - **System Prompts**: Study prompt engineering patterns used by production AI tools
86
- - **Learn Claude Code**: Understand Claude Code's tool system, agent loop, and UX patterns