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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gencode-ai",
3
- "version": "0.1.3",
3
+ "version": "0.3.0",
4
4
  "description": "An open-source AI assistant for your terminal",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -14,7 +14,8 @@
14
14
  "start": "node dist/cli/index.js",
15
15
  "start:dev": "npx tsx src/cli/index.tsx",
16
16
  "test": "node --experimental-vm-modules node_modules/jest/bin/jest.js",
17
- "example": "npx tsx examples/basic.ts"
17
+ "example": "npx tsx examples/basic.ts",
18
+ "migrate": "npx tsx scripts/migrate.ts"
18
19
  },
19
20
  "keywords": [
20
21
  "agent",
@@ -0,0 +1,449 @@
1
+ #!/usr/bin/env tsx
2
+ /**
3
+ * Migration Script: .gencode → .gen
4
+ *
5
+ * Migrates GenCode configuration from old naming to new:
6
+ * - ~/.gencode/ → ~/.gen/
7
+ * - ./.gencode/ → ./.gen/
8
+ * - AGENT.md → GEN.md
9
+ * - AGENT.local.md → GEN.local.md
10
+ * - providers.json: Old format → New format (provider:authMethod keys)
11
+ *
12
+ * Usage:
13
+ * npm run migrate # Run migration
14
+ * tsx scripts/migrate.ts # Direct execution
15
+ */
16
+
17
+ import * as fs from 'fs/promises';
18
+ import * as path from 'path';
19
+ import * as os from 'os';
20
+ import * as readline from 'readline';
21
+
22
+ interface MigrationResult {
23
+ success: boolean;
24
+ migratedPaths: string[];
25
+ errors: string[];
26
+ warnings: string[];
27
+ }
28
+
29
+ /**
30
+ * Check if a path exists
31
+ */
32
+ async function pathExists(p: string): Promise<boolean> {
33
+ try {
34
+ await fs.access(p);
35
+ return true;
36
+ } catch {
37
+ return false;
38
+ }
39
+ }
40
+
41
+ /**
42
+ * Rename files within a directory (AGENT.md → GEN.md, AGENT.local.md → GEN.local.md)
43
+ */
44
+ async function renameFilesInDir(dir: string): Promise<string[]> {
45
+ const renamed: string[] = [];
46
+
47
+ // Rename AGENT.md → GEN.md
48
+ const agentPath = path.join(dir, 'AGENT.md');
49
+ const genPath = path.join(dir, 'GEN.md');
50
+
51
+ if (await pathExists(agentPath)) {
52
+ if (await pathExists(genPath)) {
53
+ console.log(` āš ļø Skipping ${agentPath} (${genPath} already exists)`);
54
+ } else {
55
+ try {
56
+ await fs.rename(agentPath, genPath);
57
+ renamed.push(`${agentPath} → ${genPath}`);
58
+ } catch (error) {
59
+ throw new Error(`Failed to rename ${agentPath}: ${error instanceof Error ? error.message : String(error)}`);
60
+ }
61
+ }
62
+ }
63
+
64
+ // Rename AGENT.local.md → GEN.local.md
65
+ const agentLocalPath = path.join(dir, 'AGENT.local.md');
66
+ const genLocalPath = path.join(dir, 'GEN.local.md');
67
+
68
+ if (await pathExists(agentLocalPath)) {
69
+ if (await pathExists(genLocalPath)) {
70
+ console.log(` āš ļø Skipping ${agentLocalPath} (${genLocalPath} already exists)`);
71
+ } else {
72
+ try {
73
+ await fs.rename(agentLocalPath, genLocalPath);
74
+ renamed.push(`${agentLocalPath} → ${genLocalPath}`);
75
+ } catch (error) {
76
+ throw new Error(`Failed to rename ${agentLocalPath}: ${error instanceof Error ? error.message : String(error)}`);
77
+ }
78
+ }
79
+ }
80
+
81
+ return renamed;
82
+ }
83
+
84
+ /**
85
+ * Migrate providers.json from old format to new format
86
+ * Old format: models[provider] = { provider, authMethod, cachedAt, list }
87
+ * New format: models["provider:authMethod"] = { cachedAt, list }
88
+ */
89
+ async function migrateProvidersJson(dryRun = false): Promise<MigrationResult> {
90
+ const result: MigrationResult = {
91
+ success: true,
92
+ migratedPaths: [],
93
+ errors: [],
94
+ warnings: [],
95
+ };
96
+
97
+ const providersPath = path.join(os.homedir(), '.gen', 'providers.json');
98
+
99
+ // Check if providers.json exists
100
+ if (!(await pathExists(providersPath))) {
101
+ return result; // Nothing to migrate
102
+ }
103
+
104
+ try {
105
+ // Read current config
106
+ const content = await fs.readFile(providersPath, 'utf-8');
107
+ const config = JSON.parse(content);
108
+
109
+ // Check if migration is needed
110
+ let needsMigration = false;
111
+ const newModels: Record<string, any> = {};
112
+
113
+ if (config.models) {
114
+ for (const [key, value] of Object.entries(config.models)) {
115
+ // Detect old format: key doesn't contain ':' AND value has provider/authMethod fields
116
+ if (
117
+ !key.includes(':') &&
118
+ typeof value === 'object' &&
119
+ value !== null &&
120
+ 'provider' in value &&
121
+ 'authMethod' in value
122
+ ) {
123
+ needsMigration = true;
124
+ const oldCache = value as any;
125
+ const newKey = `${oldCache.provider}:${oldCache.authMethod}`;
126
+ newModels[newKey] = {
127
+ cachedAt: oldCache.cachedAt,
128
+ list: oldCache.list,
129
+ };
130
+ } else {
131
+ // Already new format
132
+ newModels[key] = value;
133
+ }
134
+ }
135
+ }
136
+
137
+ if (!needsMigration) {
138
+ return result; // Already in new format
139
+ }
140
+
141
+ if (dryRun) {
142
+ result.migratedPaths.push(`[DRY RUN] providers.json: Old format → New format (provider:authMethod keys)`);
143
+ const oldKeys = Object.keys(config.models || {}).filter(k => !k.includes(':'));
144
+ const newKeys = Object.keys(newModels).filter(k => k.includes(':'));
145
+ result.migratedPaths.push(` Old keys: ${oldKeys.join(', ') || 'none'}`);
146
+ result.migratedPaths.push(` New keys: ${newKeys.join(', ') || 'none'}`);
147
+ } else {
148
+ // Backup old config
149
+ const backupPath = `${providersPath}.backup`;
150
+ await fs.copyFile(providersPath, backupPath);
151
+
152
+ // Update config with new format
153
+ config.models = newModels;
154
+
155
+ // Also update connections to ensure authMethod is set
156
+ if (config.connections) {
157
+ for (const [provider, connection] of Object.entries(config.connections)) {
158
+ if (typeof connection === 'object' && connection !== null && !('authMethod' in connection)) {
159
+ // Try to infer authMethod from connection method name
160
+ const method = (connection as any).method;
161
+ if (method?.includes('Vertex')) {
162
+ (connection as any).authMethod = 'vertex';
163
+ } else if (method?.includes('Bedrock')) {
164
+ (connection as any).authMethod = 'bedrock';
165
+ } else if (method?.includes('Azure')) {
166
+ (connection as any).authMethod = 'azure';
167
+ } else {
168
+ (connection as any).authMethod = 'api_key';
169
+ }
170
+ }
171
+ }
172
+ }
173
+
174
+ // Write new config
175
+ await fs.writeFile(providersPath, JSON.stringify(config, null, 2));
176
+
177
+ result.migratedPaths.push(`providers.json: Migrated to new format`);
178
+ result.migratedPaths.push(` Backup saved: ${backupPath}`);
179
+ }
180
+ } catch (error) {
181
+ result.errors.push(`Failed to migrate providers.json: ${error instanceof Error ? error.message : String(error)}`);
182
+ result.success = false;
183
+ }
184
+
185
+ return result;
186
+ }
187
+
188
+ /**
189
+ * Migrate .gencode to .gen
190
+ */
191
+ async function migrateToGen(dryRun = false): Promise<MigrationResult> {
192
+ const result: MigrationResult = {
193
+ success: true,
194
+ migratedPaths: [],
195
+ errors: [],
196
+ warnings: [],
197
+ };
198
+
199
+ // 1. Migrate user directory (~/.gencode → ~/.gen)
200
+ const homeGencodePath = path.join(os.homedir(), '.gencode');
201
+ const homeGenPath = path.join(os.homedir(), '.gen');
202
+
203
+ if (await pathExists(homeGencodePath)) {
204
+ if (await pathExists(homeGenPath)) {
205
+ result.errors.push(`~/.gen already exists! Please manually merge ~/.gencode into it.`);
206
+ result.success = false;
207
+ } else {
208
+ if (!dryRun) {
209
+ try {
210
+ await fs.rename(homeGencodePath, homeGenPath);
211
+ const renamedFiles = await renameFilesInDir(homeGenPath);
212
+ result.migratedPaths.push(`${homeGencodePath} → ${homeGenPath}`);
213
+ result.migratedPaths.push(...renamedFiles);
214
+ } catch (error) {
215
+ result.errors.push(`Failed to migrate ${homeGencodePath}: ${error instanceof Error ? error.message : String(error)}`);
216
+ result.success = false;
217
+ }
218
+ } else {
219
+ result.migratedPaths.push(`[DRY RUN] ${homeGencodePath} → ${homeGenPath}`);
220
+ result.migratedPaths.push(`[DRY RUN] Will rename AGENT.md → GEN.md in ${homeGenPath}`);
221
+ result.migratedPaths.push(`[DRY RUN] Will rename AGENT.local.md → GEN.local.md in ${homeGenPath}`);
222
+ }
223
+ }
224
+ }
225
+
226
+ // 2. Migrate project directory (./.gencode → ./.gen)
227
+ const cwd = process.cwd();
228
+ const projectGencodePath = path.join(cwd, '.gencode');
229
+ const projectGenPath = path.join(cwd, '.gen');
230
+
231
+ if (await pathExists(projectGencodePath)) {
232
+ if (await pathExists(projectGenPath)) {
233
+ result.errors.push(`./.gen already exists! Please manually merge ./.gencode into it.`);
234
+ result.success = false;
235
+ } else {
236
+ if (!dryRun) {
237
+ try {
238
+ await fs.rename(projectGencodePath, projectGenPath);
239
+ const renamedFiles = await renameFilesInDir(projectGenPath);
240
+ result.migratedPaths.push(`${projectGencodePath} → ${projectGenPath}`);
241
+ result.migratedPaths.push(...renamedFiles);
242
+ } catch (error) {
243
+ result.errors.push(`Failed to migrate ${projectGencodePath}: ${error instanceof Error ? error.message : String(error)}`);
244
+ result.success = false;
245
+ }
246
+ } else {
247
+ result.migratedPaths.push(`[DRY RUN] ${projectGencodePath} → ${projectGenPath}`);
248
+ result.migratedPaths.push(`[DRY RUN] Will rename AGENT.md → GEN.md in ${projectGenPath}`);
249
+ result.migratedPaths.push(`[DRY RUN] Will rename AGENT.local.md → GEN.local.md in ${projectGenPath}`);
250
+ }
251
+ }
252
+ }
253
+
254
+ // 3. Migrate root-level files (./AGENT.md → ./GEN.md)
255
+ const rootAgentPath = path.join(cwd, 'AGENT.md');
256
+ const rootGenPath = path.join(cwd, 'GEN.md');
257
+
258
+ if (await pathExists(rootAgentPath)) {
259
+ if (await pathExists(rootGenPath)) {
260
+ result.warnings.push(`./GEN.md already exists! Skipping ./AGENT.md migration.`);
261
+ } else {
262
+ if (!dryRun) {
263
+ try {
264
+ await fs.rename(rootAgentPath, rootGenPath);
265
+ result.migratedPaths.push(`${rootAgentPath} → ${rootGenPath}`);
266
+ } catch (error) {
267
+ result.errors.push(`Failed to migrate ${rootAgentPath}: ${error instanceof Error ? error.message : String(error)}`);
268
+ result.success = false;
269
+ }
270
+ } else {
271
+ result.migratedPaths.push(`[DRY RUN] ${rootAgentPath} → ${rootGenPath}`);
272
+ }
273
+ }
274
+ }
275
+
276
+ // 4. Migrate root-level local files (./AGENT.local.md → ./GEN.local.md)
277
+ const rootAgentLocalPath = path.join(cwd, 'AGENT.local.md');
278
+ const rootGenLocalPath = path.join(cwd, 'GEN.local.md');
279
+
280
+ if (await pathExists(rootAgentLocalPath)) {
281
+ if (await pathExists(rootGenLocalPath)) {
282
+ result.warnings.push(`./GEN.local.md already exists! Skipping ./AGENT.local.md migration.`);
283
+ } else {
284
+ if (!dryRun) {
285
+ try {
286
+ await fs.rename(rootAgentLocalPath, rootGenLocalPath);
287
+ result.migratedPaths.push(`${rootAgentLocalPath} → ${rootGenLocalPath}`);
288
+ } catch (error) {
289
+ result.errors.push(`Failed to migrate ${rootAgentLocalPath}: ${error instanceof Error ? error.message : String(error)}`);
290
+ result.success = false;
291
+ }
292
+ } else {
293
+ result.migratedPaths.push(`[DRY RUN] ${rootAgentLocalPath} → ${rootGenLocalPath}`);
294
+ }
295
+ }
296
+ }
297
+
298
+ // If no migrations needed
299
+ if (result.migratedPaths.length === 0 && result.errors.length === 0) {
300
+ result.warnings.push('No .gencode directories or AGENT.md files found. Already using .gen?');
301
+ }
302
+
303
+ return result;
304
+ }
305
+
306
+ /**
307
+ * Check if migration is needed
308
+ */
309
+ async function needsMigration(): Promise<boolean> {
310
+ const homeGencodePath = path.join(os.homedir(), '.gencode');
311
+ const projectGencodePath = path.join(process.cwd(), '.gencode');
312
+ const rootAgentPath = path.join(process.cwd(), 'AGENT.md');
313
+ const rootAgentLocalPath = path.join(process.cwd(), 'AGENT.local.md');
314
+
315
+ return (
316
+ (await pathExists(homeGencodePath)) ||
317
+ (await pathExists(projectGencodePath)) ||
318
+ (await pathExists(rootAgentPath)) ||
319
+ (await pathExists(rootAgentLocalPath))
320
+ );
321
+ }
322
+
323
+ /**
324
+ * Prompt user for confirmation
325
+ */
326
+ async function confirm(message: string): Promise<boolean> {
327
+ const rl = readline.createInterface({
328
+ input: process.stdin,
329
+ output: process.stdout,
330
+ });
331
+
332
+ return new Promise((resolve) => {
333
+ rl.question(`${message} (y/N): `, (answer) => {
334
+ rl.close();
335
+ resolve(answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes');
336
+ });
337
+ });
338
+ }
339
+
340
+ /**
341
+ * Main migration flow
342
+ */
343
+ async function main() {
344
+ console.log('šŸ”„ GenCode Migration: .gencode → .gen\n');
345
+
346
+ // Check if migration is needed
347
+ const needs = await needsMigration();
348
+ if (!needs) {
349
+ console.log('āœ… No .gencode directories or AGENT.md files found.');
350
+ console.log(' Already using .gen? Nothing to migrate.\n');
351
+ }
352
+
353
+ // Always check providers.json migration (even if .gencode migration not needed)
354
+ console.log('šŸ“‹ Scanning for files to migrate...\n');
355
+
356
+ // Perform dry run for providers.json
357
+ const providersResult = await migrateProvidersJson(true);
358
+
359
+ // Perform dry run for .gencode
360
+ const dryRunResult = await migrateToGen(true);
361
+
362
+ // Merge results
363
+ const allMigrations = [...providersResult.migratedPaths, ...dryRunResult.migratedPaths];
364
+ const allErrors = [...providersResult.errors, ...dryRunResult.errors];
365
+ const allWarnings = [...providersResult.warnings, ...dryRunResult.warnings];
366
+
367
+ if (allMigrations.length === 0 && allErrors.length === 0) {
368
+ console.log('āœ… All configurations are up to date. Nothing to migrate.\n');
369
+ return;
370
+ }
371
+
372
+ if (allMigrations.length > 0) {
373
+ console.log('šŸ“¦ Migration Plan:\n');
374
+ for (const path of allMigrations) {
375
+ console.log(` āœ“ ${path}`);
376
+ }
377
+ console.log('');
378
+ }
379
+
380
+ if (allErrors.length > 0) {
381
+ console.log('āŒ Errors:\n');
382
+ for (const error of allErrors) {
383
+ console.log(` āœ— ${error}`);
384
+ }
385
+ console.log('\nāš ļø Migration aborted. Please resolve conflicts manually.\n');
386
+ process.exit(1);
387
+ }
388
+
389
+ if (allWarnings.length > 0) {
390
+ console.log('āš ļø Warnings:\n');
391
+ for (const warning of allWarnings) {
392
+ console.log(` • ${warning}`);
393
+ }
394
+ console.log('');
395
+ }
396
+
397
+ // Ask for confirmation
398
+ const confirmed = await confirm('Proceed with migration?');
399
+ if (!confirmed) {
400
+ console.log('\nāŒ Migration cancelled.\n');
401
+ return;
402
+ }
403
+
404
+ // Execute migration
405
+ console.log('\nšŸš€ Executing migration...\n');
406
+
407
+ // Migrate providers.json first
408
+ const providersExecResult = await migrateProvidersJson(false);
409
+
410
+ // Then migrate .gencode
411
+ const result = await migrateToGen(false);
412
+
413
+ const allSuccess = providersExecResult.success && result.success;
414
+ const allMigratedPaths = [...providersExecResult.migratedPaths, ...result.migratedPaths];
415
+ const allExecErrors = [...providersExecResult.errors, ...result.errors];
416
+
417
+ if (allSuccess) {
418
+ console.log('āœ… Migration completed successfully!\n');
419
+ if (allMigratedPaths.length > 0) {
420
+ console.log('Migrated paths:\n');
421
+ for (const path of allMigratedPaths) {
422
+ console.log(` āœ“ ${path}`);
423
+ }
424
+ console.log('');
425
+ }
426
+ console.log('šŸ“ Next steps:\n');
427
+ console.log(' 1. Update environment variables: GENCODE_* → GEN_*');
428
+ console.log(' - GENCODE_PROVIDER → GEN_PROVIDER');
429
+ console.log(' - GENCODE_MODEL → GEN_MODEL');
430
+ console.log(' - GENCODE_CONFIG_DIRS → GEN_CONFIG\n');
431
+ console.log(' 2. Update any scripts or CI/CD configs\n');
432
+ console.log(' 3. Restart GenCode to load from .gen directories\n');
433
+ } else {
434
+ console.log('āŒ Migration failed!\n');
435
+ if (allExecErrors.length > 0) {
436
+ console.log('Errors:\n');
437
+ for (const error of allExecErrors) {
438
+ console.log(` āœ— ${error}`);
439
+ }
440
+ console.log('');
441
+ }
442
+ process.exit(1);
443
+ }
444
+ }
445
+
446
+ main().catch((error) => {
447
+ console.error('āŒ Unexpected error:', error);
448
+ process.exit(1);
449
+ });