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
@@ -0,0 +1,327 @@
1
+ /**
2
+ * Checkpoint Manager - Core checkpointing logic
3
+ *
4
+ * Tracks file changes and provides rewind capabilities.
5
+ */
6
+
7
+ import * as fs from 'fs/promises';
8
+ import * as path from 'path';
9
+ import type {
10
+ FileCheckpoint,
11
+ CheckpointSession,
12
+ RewindOptions,
13
+ RewindResult,
14
+ CheckpointSummary,
15
+ RecordChangeInput,
16
+ } from './types.js';
17
+
18
+ /**
19
+ * Generates a unique ID for checkpoints
20
+ */
21
+ function generateId(): string {
22
+ return `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
23
+ }
24
+
25
+ /**
26
+ * CheckpointManager manages file change tracking and rewind operations.
27
+ *
28
+ * Usage:
29
+ * const manager = new CheckpointManager('session-123');
30
+ * manager.recordChange({ path: '/path/to/file', changeType: 'modify', ... });
31
+ * await manager.rewind({ all: true });
32
+ */
33
+ export class CheckpointManager {
34
+ private session: CheckpointSession;
35
+
36
+ constructor(sessionId: string = 'default') {
37
+ this.session = {
38
+ sessionId,
39
+ checkpoints: [],
40
+ createdAt: new Date(),
41
+ };
42
+ }
43
+
44
+ /**
45
+ * Get the session ID
46
+ */
47
+ getSessionId(): string {
48
+ return this.session.sessionId;
49
+ }
50
+
51
+ /**
52
+ * Record a file change as a checkpoint
53
+ */
54
+ recordChange(input: RecordChangeInput): FileCheckpoint {
55
+ const checkpoint: FileCheckpoint = {
56
+ id: generateId(),
57
+ path: input.path,
58
+ changeType: input.changeType,
59
+ timestamp: new Date(),
60
+ previousContent: input.previousContent,
61
+ newContent: input.newContent,
62
+ toolName: input.toolName,
63
+ };
64
+
65
+ this.session.checkpoints.push(checkpoint);
66
+ return checkpoint;
67
+ }
68
+
69
+ /**
70
+ * Get all checkpoints
71
+ */
72
+ getCheckpoints(): FileCheckpoint[] {
73
+ return [...this.session.checkpoints];
74
+ }
75
+
76
+ /**
77
+ * Get checkpoints for a specific file
78
+ */
79
+ getFileHistory(filePath: string): FileCheckpoint[] {
80
+ return this.session.checkpoints.filter((cp) => cp.path === filePath);
81
+ }
82
+
83
+ /**
84
+ * Get a summary of all changes
85
+ */
86
+ getSummary(): CheckpointSummary {
87
+ const summary: CheckpointSummary = {
88
+ created: 0,
89
+ modified: 0,
90
+ deleted: 0,
91
+ total: this.session.checkpoints.length,
92
+ };
93
+
94
+ for (const cp of this.session.checkpoints) {
95
+ switch (cp.changeType) {
96
+ case 'create':
97
+ summary.created++;
98
+ break;
99
+ case 'modify':
100
+ summary.modified++;
101
+ break;
102
+ case 'delete':
103
+ summary.deleted++;
104
+ break;
105
+ }
106
+ }
107
+
108
+ return summary;
109
+ }
110
+
111
+ /**
112
+ * Check if there are any checkpoints
113
+ */
114
+ hasCheckpoints(): boolean {
115
+ return this.session.checkpoints.length > 0;
116
+ }
117
+
118
+ /**
119
+ * Get the number of checkpoints
120
+ */
121
+ getCheckpointCount(): number {
122
+ return this.session.checkpoints.length;
123
+ }
124
+
125
+ /**
126
+ * Rewind changes based on options
127
+ */
128
+ async rewind(options: RewindOptions): Promise<RewindResult> {
129
+ const result: RewindResult = {
130
+ success: true,
131
+ revertedFiles: [],
132
+ errors: [],
133
+ };
134
+
135
+ // Determine which checkpoints to rewind
136
+ let checkpointsToRewind: FileCheckpoint[] = [];
137
+
138
+ if (options.checkpointId) {
139
+ // Rewind specific checkpoint
140
+ const cp = this.session.checkpoints.find((c) => c.id === options.checkpointId);
141
+ if (cp) {
142
+ checkpointsToRewind = [cp];
143
+ }
144
+ } else if (options.path) {
145
+ // Rewind all changes to a specific file (in reverse order)
146
+ checkpointsToRewind = this.session.checkpoints
147
+ .filter((c) => c.path === options.path)
148
+ .reverse();
149
+ } else if (options.count) {
150
+ // Rewind last N changes (in reverse order)
151
+ checkpointsToRewind = this.session.checkpoints.slice(-options.count).reverse();
152
+ } else if (options.all) {
153
+ // Rewind all changes (in reverse order)
154
+ checkpointsToRewind = [...this.session.checkpoints].reverse();
155
+ }
156
+
157
+ // Apply reverts
158
+ for (const checkpoint of checkpointsToRewind) {
159
+ try {
160
+ await this.revertCheckpoint(checkpoint);
161
+ result.revertedFiles.push({
162
+ path: checkpoint.path,
163
+ action: this.getRevertAction(checkpoint),
164
+ });
165
+
166
+ // Remove the checkpoint from session
167
+ const index = this.session.checkpoints.findIndex((c) => c.id === checkpoint.id);
168
+ if (index !== -1) {
169
+ this.session.checkpoints.splice(index, 1);
170
+ }
171
+ } catch (error) {
172
+ result.success = false;
173
+ result.errors.push({
174
+ path: checkpoint.path,
175
+ error: error instanceof Error ? error.message : String(error),
176
+ });
177
+ }
178
+ }
179
+
180
+ return result;
181
+ }
182
+
183
+ /**
184
+ * Revert a single checkpoint
185
+ */
186
+ private async revertCheckpoint(checkpoint: FileCheckpoint): Promise<void> {
187
+ switch (checkpoint.changeType) {
188
+ case 'create':
189
+ // File was created, delete it to revert
190
+ await fs.unlink(checkpoint.path);
191
+ break;
192
+
193
+ case 'modify':
194
+ // File was modified, restore previous content
195
+ if (checkpoint.previousContent !== null) {
196
+ await fs.writeFile(checkpoint.path, checkpoint.previousContent, 'utf-8');
197
+ }
198
+ break;
199
+
200
+ case 'delete':
201
+ // File was deleted, recreate it with previous content
202
+ if (checkpoint.previousContent !== null) {
203
+ await fs.mkdir(path.dirname(checkpoint.path), { recursive: true });
204
+ await fs.writeFile(checkpoint.path, checkpoint.previousContent, 'utf-8');
205
+ }
206
+ break;
207
+ }
208
+ }
209
+
210
+ /**
211
+ * Get the action that will be taken to revert a checkpoint
212
+ */
213
+ private getRevertAction(checkpoint: FileCheckpoint): 'restored' | 'deleted' | 'recreated' {
214
+ switch (checkpoint.changeType) {
215
+ case 'create':
216
+ return 'deleted';
217
+ case 'modify':
218
+ return 'restored';
219
+ case 'delete':
220
+ return 'recreated';
221
+ }
222
+ }
223
+
224
+ /**
225
+ * Clear all checkpoints
226
+ */
227
+ clearCheckpoints(): void {
228
+ this.session.checkpoints = [];
229
+ }
230
+
231
+ /**
232
+ * Format checkpoints for display
233
+ */
234
+ formatCheckpointList(includeUsage: boolean = false): string {
235
+ if (this.session.checkpoints.length === 0) {
236
+ return 'No file changes in this session.';
237
+ }
238
+
239
+ const lines: string[] = [];
240
+
241
+ this.session.checkpoints.forEach((cp, index) => {
242
+ const timeAgo = this.formatTimeAgo(cp.timestamp);
243
+ const action = this.formatChangeType(cp.changeType);
244
+ const fileName = cp.path.split('/').pop() || cp.path;
245
+ lines.push(` [${index + 1}] ${timeAgo.padEnd(8)} ${fileName.padEnd(30)} (${action})`);
246
+ });
247
+
248
+ const summary = this.getSummary();
249
+ lines.push('');
250
+ lines.push(
251
+ `Total: ${summary.created} created, ${summary.modified} modified, ${summary.deleted} deleted`
252
+ );
253
+
254
+ if (includeUsage) {
255
+ lines.push('');
256
+ lines.push('Usage: /rewind [n] to revert change #n, /rewind all to revert all');
257
+ }
258
+
259
+ return lines.join('\n');
260
+ }
261
+
262
+ /**
263
+ * Format a change type for display
264
+ */
265
+ private formatChangeType(changeType: string): string {
266
+ switch (changeType) {
267
+ case 'create':
268
+ return 'created';
269
+ case 'modify':
270
+ return 'modified';
271
+ case 'delete':
272
+ return 'deleted';
273
+ default:
274
+ return changeType;
275
+ }
276
+ }
277
+
278
+ /**
279
+ * Format a timestamp as relative time
280
+ */
281
+ private formatTimeAgo(date: Date): string {
282
+ const seconds = Math.floor((Date.now() - date.getTime()) / 1000);
283
+
284
+ if (seconds < 60) {
285
+ return `${seconds}s ago`;
286
+ }
287
+
288
+ const minutes = Math.floor(seconds / 60);
289
+ if (minutes < 60) {
290
+ return `${minutes}m ago`;
291
+ }
292
+
293
+ const hours = Math.floor(minutes / 60);
294
+ return `${hours}h ago`;
295
+ }
296
+ }
297
+
298
+ // ============================================================================
299
+ // Singleton Instance
300
+ // ============================================================================
301
+
302
+ let globalCheckpointManager: CheckpointManager | null = null;
303
+
304
+ /**
305
+ * Get the global checkpoint manager instance
306
+ */
307
+ export function getCheckpointManager(): CheckpointManager {
308
+ if (!globalCheckpointManager) {
309
+ globalCheckpointManager = new CheckpointManager();
310
+ }
311
+ return globalCheckpointManager;
312
+ }
313
+
314
+ /**
315
+ * Initialize checkpoint manager with a session ID
316
+ */
317
+ export function initCheckpointManager(sessionId: string): CheckpointManager {
318
+ globalCheckpointManager = new CheckpointManager(sessionId);
319
+ return globalCheckpointManager;
320
+ }
321
+
322
+ /**
323
+ * Reset the global checkpoint manager (for testing)
324
+ */
325
+ export function resetCheckpointManager(): void {
326
+ globalCheckpointManager = null;
327
+ }
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Checkpointing Module
3
+ *
4
+ * Provides automatic tracking of file changes with undo/rewind capabilities.
5
+ *
6
+ * Usage:
7
+ * import { getCheckpointManager, initCheckpointManager } from './checkpointing';
8
+ *
9
+ * // Initialize at session start
10
+ * const manager = initCheckpointManager('session-123');
11
+ *
12
+ * // Record changes (done automatically by ToolRegistry)
13
+ * manager.recordChange({
14
+ * path: '/path/to/file.ts',
15
+ * changeType: 'modify',
16
+ * previousContent: 'old content',
17
+ * newContent: 'new content',
18
+ * toolName: 'Edit'
19
+ * });
20
+ *
21
+ * // List changes
22
+ * console.log(manager.formatCheckpointList());
23
+ *
24
+ * // Rewind changes
25
+ * await manager.rewind({ all: true });
26
+ */
27
+
28
+ // Type exports
29
+ export type {
30
+ ChangeType,
31
+ FileCheckpoint,
32
+ CheckpointSession,
33
+ RewindOptions,
34
+ RewindResult,
35
+ CheckpointSummary,
36
+ RecordChangeInput,
37
+ } from './types.js';
38
+
39
+ // Manager exports
40
+ export {
41
+ CheckpointManager,
42
+ getCheckpointManager,
43
+ initCheckpointManager,
44
+ resetCheckpointManager,
45
+ } from './checkpoint-manager.js';
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Checkpointing System Type Definitions
3
+ *
4
+ * Provides automatic tracking of file changes with undo/rewind capabilities.
5
+ */
6
+
7
+ /**
8
+ * Type of file change
9
+ */
10
+ export type ChangeType = 'create' | 'modify' | 'delete';
11
+
12
+ /**
13
+ * A single file checkpoint recording a change
14
+ */
15
+ export interface FileCheckpoint {
16
+ /** Unique identifier for this checkpoint */
17
+ id: string;
18
+ /** Path to the file that was changed */
19
+ path: string;
20
+ /** Type of change made */
21
+ changeType: ChangeType;
22
+ /** When the change was made */
23
+ timestamp: Date;
24
+ /** File content before the change (null for create) */
25
+ previousContent: string | null;
26
+ /** File content after the change (null for delete) */
27
+ newContent: string | null;
28
+ /** Which tool made the change */
29
+ toolName: string;
30
+ }
31
+
32
+ /**
33
+ * A checkpoint session containing all checkpoints for a session
34
+ */
35
+ export interface CheckpointSession {
36
+ /** Session ID this checkpoint session belongs to */
37
+ sessionId: string;
38
+ /** All checkpoints in order */
39
+ checkpoints: FileCheckpoint[];
40
+ /** When this checkpoint session was created */
41
+ createdAt: Date;
42
+ }
43
+
44
+ /**
45
+ * Options for rewinding changes
46
+ */
47
+ export interface RewindOptions {
48
+ /** Rewind a specific checkpoint by ID */
49
+ checkpointId?: string;
50
+ /** Rewind changes to a specific file path */
51
+ path?: string;
52
+ /** Rewind all changes */
53
+ all?: boolean;
54
+ /** Rewind the last N changes */
55
+ count?: number;
56
+ }
57
+
58
+ /**
59
+ * Result of a rewind operation
60
+ */
61
+ export interface RewindResult {
62
+ /** Whether the rewind was successful */
63
+ success: boolean;
64
+ /** Files that were successfully reverted */
65
+ revertedFiles: Array<{
66
+ path: string;
67
+ action: 'restored' | 'deleted' | 'recreated';
68
+ }>;
69
+ /** Any errors that occurred during rewind */
70
+ errors: Array<{
71
+ path: string;
72
+ error: string;
73
+ }>;
74
+ }
75
+
76
+ /**
77
+ * Summary of changes in a checkpoint session
78
+ */
79
+ export interface CheckpointSummary {
80
+ /** Number of files created */
81
+ created: number;
82
+ /** Number of files modified */
83
+ modified: number;
84
+ /** Number of files deleted */
85
+ deleted: number;
86
+ /** Total number of checkpoints */
87
+ total: number;
88
+ }
89
+
90
+ /**
91
+ * Input for recording a file change
92
+ */
93
+ export interface RecordChangeInput {
94
+ /** Path to the file */
95
+ path: string;
96
+ /** Type of change */
97
+ changeType: ChangeType;
98
+ /** Content before change (null for create) */
99
+ previousContent: string | null;
100
+ /** Content after change (null for delete) */
101
+ newContent: string | null;
102
+ /** Tool that made the change */
103
+ toolName: string;
104
+ }