gencode-ai 0.1.3 → 0.2.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 (151) hide show
  1. package/README.md +2 -1
  2. package/dist/agent/agent.d.ts +35 -0
  3. package/dist/agent/agent.d.ts.map +1 -1
  4. package/dist/agent/agent.js +93 -3
  5. package/dist/agent/agent.js.map +1 -1
  6. package/dist/agent/types.d.ts +6 -0
  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 +157 -6
  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 +11 -2
  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/PlanApproval.d.ts +36 -0
  35. package/dist/cli/components/PlanApproval.d.ts.map +1 -0
  36. package/dist/cli/components/PlanApproval.js +154 -0
  37. package/dist/cli/components/PlanApproval.js.map +1 -0
  38. package/dist/cli/components/theme.d.ts +2 -0
  39. package/dist/cli/components/theme.d.ts.map +1 -1
  40. package/dist/cli/components/theme.js +3 -0
  41. package/dist/cli/components/theme.js.map +1 -1
  42. package/dist/index.d.ts +1 -0
  43. package/dist/index.d.ts.map +1 -1
  44. package/dist/index.js +2 -0
  45. package/dist/index.js.map +1 -1
  46. package/dist/planning/index.d.ts +13 -0
  47. package/dist/planning/index.d.ts.map +1 -0
  48. package/dist/planning/index.js +15 -0
  49. package/dist/planning/index.js.map +1 -0
  50. package/dist/planning/plan-file.d.ts +59 -0
  51. package/dist/planning/plan-file.d.ts.map +1 -0
  52. package/dist/planning/plan-file.js +278 -0
  53. package/dist/planning/plan-file.js.map +1 -0
  54. package/dist/planning/state.d.ts +127 -0
  55. package/dist/planning/state.d.ts.map +1 -0
  56. package/dist/planning/state.js +261 -0
  57. package/dist/planning/state.js.map +1 -0
  58. package/dist/planning/tools/enter-plan-mode.d.ts +25 -0
  59. package/dist/planning/tools/enter-plan-mode.d.ts.map +1 -0
  60. package/dist/planning/tools/enter-plan-mode.js +98 -0
  61. package/dist/planning/tools/enter-plan-mode.js.map +1 -0
  62. package/dist/planning/tools/exit-plan-mode.d.ts +24 -0
  63. package/dist/planning/tools/exit-plan-mode.d.ts.map +1 -0
  64. package/dist/planning/tools/exit-plan-mode.js +149 -0
  65. package/dist/planning/tools/exit-plan-mode.js.map +1 -0
  66. package/dist/planning/types.d.ts +100 -0
  67. package/dist/planning/types.d.ts.map +1 -0
  68. package/dist/planning/types.js +28 -0
  69. package/dist/planning/types.js.map +1 -0
  70. package/dist/pricing/calculator.d.ts +21 -0
  71. package/dist/pricing/calculator.d.ts.map +1 -0
  72. package/dist/pricing/calculator.js +59 -0
  73. package/dist/pricing/calculator.js.map +1 -0
  74. package/dist/pricing/index.d.ts +7 -0
  75. package/dist/pricing/index.d.ts.map +1 -0
  76. package/dist/pricing/index.js +7 -0
  77. package/dist/pricing/index.js.map +1 -0
  78. package/dist/pricing/models.d.ts +20 -0
  79. package/dist/pricing/models.d.ts.map +1 -0
  80. package/dist/pricing/models.js +322 -0
  81. package/dist/pricing/models.js.map +1 -0
  82. package/dist/pricing/types.d.ts +30 -0
  83. package/dist/pricing/types.d.ts.map +1 -0
  84. package/dist/pricing/types.js +5 -0
  85. package/dist/pricing/types.js.map +1 -0
  86. package/dist/providers/anthropic.d.ts.map +1 -1
  87. package/dist/providers/anthropic.js +17 -10
  88. package/dist/providers/anthropic.js.map +1 -1
  89. package/dist/providers/gemini.d.ts.map +1 -1
  90. package/dist/providers/gemini.js +21 -14
  91. package/dist/providers/gemini.js.map +1 -1
  92. package/dist/providers/openai.d.ts.map +1 -1
  93. package/dist/providers/openai.js +12 -8
  94. package/dist/providers/openai.js.map +1 -1
  95. package/dist/providers/types.d.ts +2 -0
  96. package/dist/providers/types.d.ts.map +1 -1
  97. package/dist/providers/vertex-ai.d.ts.map +1 -1
  98. package/dist/providers/vertex-ai.js +17 -10
  99. package/dist/providers/vertex-ai.js.map +1 -1
  100. package/dist/session/manager.d.ts +4 -0
  101. package/dist/session/manager.d.ts.map +1 -1
  102. package/dist/session/manager.js +8 -0
  103. package/dist/session/manager.js.map +1 -1
  104. package/dist/tools/index.d.ts +7 -1
  105. package/dist/tools/index.d.ts.map +1 -1
  106. package/dist/tools/index.js +7 -0
  107. package/dist/tools/index.js.map +1 -1
  108. package/dist/tools/registry.d.ts +13 -0
  109. package/dist/tools/registry.d.ts.map +1 -1
  110. package/dist/tools/registry.js +79 -2
  111. package/dist/tools/registry.js.map +1 -1
  112. package/docs/cost-tracking-comparison.md +904 -0
  113. package/docs/operating-modes.md +96 -0
  114. package/docs/proposals/0025-cost-tracking.md +60 -2
  115. package/docs/proposals/README.md +1 -1
  116. package/examples/test-checkpointing.ts +121 -0
  117. package/examples/test-cost-tracking.ts +77 -0
  118. package/examples/test-interrupt-cleanup.ts +94 -0
  119. package/package.json +1 -1
  120. package/src/agent/agent.ts +110 -3
  121. package/src/agent/types.ts +6 -0
  122. package/src/checkpointing/checkpoint-manager.ts +327 -0
  123. package/src/checkpointing/index.ts +45 -0
  124. package/src/checkpointing/types.ts +104 -0
  125. package/src/cli/components/App.tsx +204 -5
  126. package/src/cli/components/CommandSuggestions.tsx +5 -0
  127. package/src/cli/components/Messages.tsx +23 -4
  128. package/src/cli/components/ModeIndicator.tsx +174 -0
  129. package/src/cli/components/PlanApproval.tsx +327 -0
  130. package/src/cli/components/theme.ts +3 -0
  131. package/src/index.ts +15 -0
  132. package/src/planning/index.ts +53 -0
  133. package/src/planning/plan-file.ts +326 -0
  134. package/src/planning/state.ts +305 -0
  135. package/src/planning/tools/enter-plan-mode.ts +111 -0
  136. package/src/planning/tools/exit-plan-mode.ts +170 -0
  137. package/src/planning/types.ts +150 -0
  138. package/src/pricing/calculator.ts +71 -0
  139. package/src/pricing/index.ts +7 -0
  140. package/src/pricing/models.ts +334 -0
  141. package/src/pricing/types.ts +32 -0
  142. package/src/providers/anthropic.ts +21 -10
  143. package/src/providers/gemini.ts +25 -14
  144. package/src/providers/openai.ts +17 -8
  145. package/src/providers/types.ts +3 -0
  146. package/src/providers/vertex-ai.ts +21 -10
  147. package/src/session/manager.ts +9 -0
  148. package/src/tools/index.ts +8 -0
  149. package/src/tools/registry.ts +95 -2
  150. package/.gencode/settings.local.json +0 -7
  151. package/CLAUDE.md +0 -86
@@ -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