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,23 +1,128 @@
1
1
  /**
2
- * Provider Registry - Provider definitions with connection options
2
+ * Provider Registry - Provider class registry with metadata
3
3
  */
4
4
 
5
- import type { ProviderName } from './index.js';
5
+ import type { Provider, AuthMethod, ProviderClassMeta, LLMProvider } from './types.js';
6
6
  import type { SearchProviderName } from './search/types.js';
7
+ import { AnthropicProvider } from './anthropic.js';
8
+ import { AnthropicVertexProvider } from './vertex-ai.js';
9
+ import { OpenAIProvider } from './openai.js';
10
+ import { GeminiProvider } from './gemini.js';
7
11
 
8
- export interface ConnectionOption {
9
- method: string;
12
+ // ============================================================================
13
+ // LLM Provider Classes
14
+ // ============================================================================
15
+
16
+ export type ProviderClass = {
17
+ new (config?: any): LLMProvider;
18
+ meta: ProviderClassMeta;
19
+ };
20
+
21
+ /**
22
+ * All registered provider classes
23
+ * Each class has static metadata describing which provider and auth method it implements
24
+ */
25
+ export const PROVIDER_CLASSES: ProviderClass[] = [
26
+ AnthropicProvider,
27
+ AnthropicVertexProvider,
28
+ OpenAIProvider,
29
+ GeminiProvider,
30
+ ];
31
+
32
+ /**
33
+ * Provider metadata (for UI display)
34
+ */
35
+ export interface ProviderMeta {
36
+ id: Provider;
10
37
  name: string;
11
- envVars: string[];
12
- description?: string;
13
- providerImpl?: ProviderName; // Override provider implementation (e.g., vertex-ai for Anthropic via GCP)
38
+ popularity: number; // Lower = more popular
39
+ }
40
+
41
+ export const PROVIDER_METADATA: ProviderMeta[] = [
42
+ { id: 'anthropic', name: 'Anthropic', popularity: 1 },
43
+ { id: 'openai', name: 'OpenAI', popularity: 2 },
44
+ { id: 'gemini', name: 'Google Gemini', popularity: 3 },
45
+ ];
46
+
47
+ // ============================================================================
48
+ // Helper Functions
49
+ // ============================================================================
50
+
51
+ /**
52
+ * Get a specific provider class by provider and auth method
53
+ */
54
+ export function getProviderClass(
55
+ provider: Provider,
56
+ authMethod: AuthMethod
57
+ ): ProviderClass | undefined {
58
+ return PROVIDER_CLASSES.find(
59
+ (cls) => cls.meta.provider === provider && cls.meta.authMethod === authMethod
60
+ );
14
61
  }
15
62
 
16
- export interface ProviderDefinition {
17
- id: ProviderName;
63
+ /**
64
+ * Get all provider classes for a given provider
65
+ */
66
+ export function getProviderClasses(provider: Provider): ProviderClass[] {
67
+ return PROVIDER_CLASSES.filter((cls) => cls.meta.provider === provider);
68
+ }
69
+
70
+ /**
71
+ * Check if a provider class is ready (has required env vars)
72
+ */
73
+ export function isProviderReady(providerClass: ProviderClass): boolean {
74
+ // Special case for Vertex AI: requires explicit opt-in
75
+ if (providerClass.meta.authMethod === 'vertex') {
76
+ const useVertex = process.env.CLAUDE_CODE_USE_VERTEX === '1' || process.env.CLAUDE_CODE_USE_VERTEX === 'true';
77
+ const hasProject = !!(
78
+ process.env.ANTHROPIC_VERTEX_PROJECT_ID ||
79
+ process.env.GCLOUD_PROJECT ||
80
+ process.env.GOOGLE_CLOUD_PROJECT
81
+ );
82
+ return useVertex && hasProject;
83
+ }
84
+
85
+ // For other providers: check if any required env var is set
86
+ return providerClass.meta.envVars.some((v) => !!process.env[v]);
87
+ }
88
+
89
+ /**
90
+ * Get provider metadata by ID
91
+ */
92
+ export function getProviderMeta(id: Provider): ProviderMeta | undefined {
93
+ return PROVIDER_METADATA.find((p) => p.id === id);
94
+ }
95
+
96
+ /**
97
+ * Get all providers sorted by popularity
98
+ */
99
+ export function getProvidersSorted(): ProviderMeta[] {
100
+ return [...PROVIDER_METADATA].sort((a, b) => a.popularity - b.popularity);
101
+ }
102
+
103
+ /**
104
+ * Get the first available (ready) provider class for a provider
105
+ */
106
+ export function getAvailableProviderClass(provider: Provider): ProviderClass | undefined {
107
+ const classes = getProviderClasses(provider);
108
+ return classes.find((cls) => isProviderReady(cls));
109
+ }
110
+
111
+ /**
112
+ * Get all available (ready) provider classes for a provider
113
+ */
114
+ export function getAvailableProviderClasses(provider: Provider): ProviderClass[] {
115
+ return getProviderClasses(provider).filter((cls) => isProviderReady(cls));
116
+ }
117
+
118
+ // ============================================================================
119
+ // Legacy Support (for backward compatibility with search providers)
120
+ // ============================================================================
121
+
122
+ export interface ConnectionOption {
18
123
  name: string;
19
- popularity: number; // Lower = more popular, used for sorting
20
- connections: ConnectionOption[];
124
+ envVars: string[];
125
+ description?: string;
21
126
  }
22
127
 
23
128
  export interface SearchProviderDefinition {
@@ -28,64 +133,6 @@ export interface SearchProviderDefinition {
28
133
  requiresKey: boolean;
29
134
  }
30
135
 
31
- /**
32
- * All supported providers with their connection options
33
- */
34
- export const PROVIDERS: ProviderDefinition[] = [
35
- {
36
- id: 'anthropic',
37
- name: 'Anthropic',
38
- popularity: 1,
39
- connections: [
40
- {
41
- method: 'api_key',
42
- name: 'API Key',
43
- envVars: ['ANTHROPIC_API_KEY'],
44
- description: 'Direct API access',
45
- },
46
- {
47
- method: 'vertex',
48
- name: 'Google Vertex AI',
49
- envVars: ['ANTHROPIC_VERTEX_PROJECT_ID', 'GOOGLE_CLOUD_PROJECT'],
50
- description: 'Claude via GCP',
51
- providerImpl: 'vertex-ai',
52
- },
53
- {
54
- method: 'bedrock',
55
- name: 'Amazon Bedrock',
56
- envVars: ['AWS_ACCESS_KEY_ID', 'AWS_PROFILE'],
57
- description: 'Claude via AWS (coming soon)',
58
- },
59
- ],
60
- },
61
- {
62
- id: 'openai',
63
- name: 'OpenAI',
64
- popularity: 2,
65
- connections: [
66
- {
67
- method: 'api_key',
68
- name: 'API Key',
69
- envVars: ['OPENAI_API_KEY'],
70
- description: 'Direct API access',
71
- },
72
- ],
73
- },
74
- {
75
- id: 'gemini',
76
- name: 'Google Gemini',
77
- popularity: 3,
78
- connections: [
79
- {
80
- method: 'api_key',
81
- name: 'API Key',
82
- envVars: ['GOOGLE_API_KEY', 'GEMINI_API_KEY'],
83
- description: 'Direct API access',
84
- },
85
- ],
86
- },
87
- ];
88
-
89
136
  /**
90
137
  * All supported search providers
91
138
  */
@@ -96,7 +143,6 @@ export const SEARCH_PROVIDERS: SearchProviderDefinition[] = [
96
143
  popularity: 1,
97
144
  connections: [
98
145
  {
99
- method: 'public',
100
146
  name: 'Public API',
101
147
  envVars: [],
102
148
  description: 'No API key required',
@@ -110,7 +156,6 @@ export const SEARCH_PROVIDERS: SearchProviderDefinition[] = [
110
156
  popularity: 2,
111
157
  connections: [
112
158
  {
113
- method: 'api_key',
114
159
  name: 'API Key',
115
160
  envVars: ['SERPER_API_KEY'],
116
161
  description: 'Google Search via Serper',
@@ -124,7 +169,6 @@ export const SEARCH_PROVIDERS: SearchProviderDefinition[] = [
124
169
  popularity: 3,
125
170
  connections: [
126
171
  {
127
- method: 'api_key',
128
172
  name: 'API Key',
129
173
  envVars: ['BRAVE_API_KEY'],
130
174
  description: 'Privacy-focused search',
@@ -134,13 +178,6 @@ export const SEARCH_PROVIDERS: SearchProviderDefinition[] = [
134
178
  },
135
179
  ];
136
180
 
137
- /**
138
- * Get provider definition by ID
139
- */
140
- export function getProvider(id: ProviderName): ProviderDefinition | undefined {
141
- return PROVIDERS.find((p) => p.id === id);
142
- }
143
-
144
181
  /**
145
182
  * Get search provider definition by ID
146
183
  */
@@ -155,44 +192,12 @@ export function getSearchProvidersSorted(): SearchProviderDefinition[] {
155
192
  return [...SEARCH_PROVIDERS].sort((a, b) => a.popularity - b.popularity);
156
193
  }
157
194
 
158
- /**
159
- * Get all providers sorted by popularity
160
- */
161
- export function getProvidersSorted(): ProviderDefinition[] {
162
- return [...PROVIDERS].sort((a, b) => a.popularity - b.popularity);
163
- }
164
-
165
195
  // Helper: check if any env var in the list is set
166
196
  const hasAnyEnvVar = (envVars: string[]) => envVars.some((v) => !!process.env[v]);
167
197
 
168
- /**
169
- * Check if any of the provider's env vars are set
170
- */
171
- export function hasEnvVars(provider: ProviderDefinition): boolean {
172
- return provider.connections.some((conn) => hasAnyEnvVar(conn.envVars));
173
- }
174
-
175
- /**
176
- * Get the first available connection method (where env vars are set)
177
- */
178
- export function getAvailableConnection(
179
- provider: ProviderDefinition
180
- ): ConnectionOption | undefined {
181
- return provider.connections.find((conn) => hasAnyEnvVar(conn.envVars));
182
- }
183
-
184
198
  /**
185
199
  * Check if a specific connection option has its env vars set
186
200
  */
187
201
  export function isConnectionReady(conn: ConnectionOption): boolean {
188
202
  return hasAnyEnvVar(conn.envVars);
189
203
  }
190
-
191
- /**
192
- * Get all available (ready) connections for a provider
193
- */
194
- export function getAvailableConnections(
195
- provider: ProviderDefinition
196
- ): ConnectionOption[] {
197
- return provider.connections.filter((conn) => hasAnyEnvVar(conn.envVars));
198
- }
@@ -1,13 +1,13 @@
1
1
  /**
2
2
  * Provider Store - Manages provider connections and model cache
3
3
  *
4
- * Storage location: ~/.gencode/providers.json
4
+ * Storage location: ~/.gen/providers.json
5
5
  */
6
6
 
7
7
  import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
8
8
  import { join } from 'path';
9
9
  import { homedir } from 'os';
10
- import type { ProviderName } from './index.js';
10
+ import type { Provider, AuthMethod } from './types.js';
11
11
  import type { SearchProviderName } from './search/types.js';
12
12
 
13
13
  export interface ModelInfo {
@@ -16,7 +16,8 @@ export interface ModelInfo {
16
16
  }
17
17
 
18
18
  export interface ProviderConnection {
19
- method: string;
19
+ authMethod: AuthMethod; // Authentication method
20
+ method?: string; // Legacy: Connection name (e.g., "Direct API", "Google Vertex AI")
20
21
  connectedAt: string;
21
22
  }
22
23
 
@@ -31,9 +32,28 @@ export interface ProvidersConfig {
31
32
  searchProvider?: SearchProviderName;
32
33
  }
33
34
 
34
- const CONFIG_DIR = join(homedir(), '.gencode');
35
+ const CONFIG_DIR = join(homedir(), '.gen');
35
36
  const CONFIG_FILE = join(CONFIG_DIR, 'providers.json');
36
37
 
38
+ /**
39
+ * Generate model cache key from provider and authMethod
40
+ */
41
+ export function getModelCacheKey(provider: Provider, authMethod: AuthMethod): string {
42
+ return `${provider}:${authMethod}`;
43
+ }
44
+
45
+ /**
46
+ * Parse model cache key to extract provider and authMethod
47
+ */
48
+ export function parseModelCacheKey(key: string): { provider: Provider; authMethod: AuthMethod } | null {
49
+ const parts = key.split(':');
50
+ if (parts.length !== 2) return null;
51
+ return {
52
+ provider: parts[0] as Provider,
53
+ authMethod: parts[1] as AuthMethod,
54
+ };
55
+ }
56
+
37
57
  /**
38
58
  * Provider Store - manages connection state and model cache
39
59
  */
@@ -76,67 +96,93 @@ export class ProviderStore {
76
96
  /**
77
97
  * Check if a provider is connected
78
98
  */
79
- isConnected(providerId: ProviderName): boolean {
99
+ isConnected(providerId: Provider): boolean {
80
100
  return !!this.config.connections[providerId];
81
101
  }
82
102
 
83
103
  /**
84
104
  * Get connection info for a provider
85
105
  */
86
- getConnection(providerId: ProviderName): ProviderConnection | undefined {
106
+ getConnection(providerId: Provider): ProviderConnection | undefined {
87
107
  return this.config.connections[providerId];
88
108
  }
89
109
 
90
110
  /**
91
111
  * Get all connected provider IDs
92
112
  */
93
- getConnectedProviders(): ProviderName[] {
94
- return Object.keys(this.config.connections) as ProviderName[];
113
+ getConnectedProviders(): Provider[] {
114
+ return Object.keys(this.config.connections) as Provider[];
95
115
  }
96
116
 
97
117
  /**
98
- * Connect a provider
118
+ * Connect a provider with auth method
99
119
  */
100
- connect(providerId: ProviderName, method: string): void {
120
+ connect(providerId: Provider, authMethod: AuthMethod, displayName?: string): void {
101
121
  this.config.connections[providerId] = {
102
- method,
122
+ authMethod,
123
+ method: displayName, // Optional legacy field for display
103
124
  connectedAt: new Date().toISOString(),
104
125
  };
105
126
  this.save();
106
127
  }
107
128
 
108
129
  /**
109
- * Disconnect a provider
130
+ * Disconnect a provider and clear all its model caches
110
131
  */
111
- disconnect(providerId: ProviderName): void {
132
+ disconnect(providerId: Provider): void {
112
133
  delete this.config.connections[providerId];
113
- delete this.config.models[providerId];
134
+
135
+ // Remove all model caches for this provider (across all authMethods)
136
+ for (const key of Object.keys(this.config.models)) {
137
+ const parsed = parseModelCacheKey(key);
138
+ if (parsed && parsed.provider === providerId) {
139
+ delete this.config.models[key];
140
+ }
141
+ }
142
+
114
143
  this.save();
115
144
  }
116
145
 
117
146
  /**
118
147
  * Get cached models for a provider
148
+ * @param providerId Provider ID
149
+ * @param authMethod Optional: specific auth method. If not provided, returns all models for the provider
119
150
  */
120
- getModels(providerId: ProviderName): ModelInfo[] {
121
- return this.config.models[providerId]?.list ?? [];
151
+ getModels(providerId: Provider, authMethod?: AuthMethod): ModelInfo[] {
152
+ if (authMethod) {
153
+ // Get models for specific authMethod
154
+ const key = getModelCacheKey(providerId, authMethod);
155
+ return this.config.models[key]?.list ?? [];
156
+ }
157
+
158
+ // Get all models for this provider (across all authMethods)
159
+ const allModels: ModelInfo[] = [];
160
+ for (const [key, cache] of Object.entries(this.config.models)) {
161
+ const parsed = parseModelCacheKey(key);
162
+ if (parsed && parsed.provider === providerId) {
163
+ allModels.push(...cache.list);
164
+ }
165
+ }
166
+ return allModels;
122
167
  }
123
168
 
124
169
  /**
125
170
  * Get all cached models grouped by provider
126
171
  */
127
- getAllModels(): Record<ProviderName, ModelInfo[]> {
172
+ getAllModels(): Record<Provider, ModelInfo[]> {
128
173
  const result: Record<string, ModelInfo[]> = {};
129
174
  for (const [providerId, cache] of Object.entries(this.config.models)) {
130
175
  result[providerId] = cache.list;
131
176
  }
132
- return result as Record<ProviderName, ModelInfo[]>;
177
+ return result as Record<Provider, ModelInfo[]>;
133
178
  }
134
179
 
135
180
  /**
136
- * Cache models for a provider
181
+ * Cache models for a provider with auth method
137
182
  */
138
- cacheModels(providerId: ProviderName, models: ModelInfo[]): void {
139
- this.config.models[providerId] = {
183
+ cacheModels(providerId: Provider, authMethod: AuthMethod, models: ModelInfo[]): void {
184
+ const key = getModelCacheKey(providerId, authMethod);
185
+ this.config.models[key] = {
140
186
  cachedAt: new Date().toISOString(),
141
187
  list: models,
142
188
  };
@@ -145,17 +191,37 @@ export class ProviderStore {
145
191
 
146
192
  /**
147
193
  * Get cache timestamp for a provider
194
+ * @param providerId Provider ID
195
+ * @param authMethod Optional: specific auth method. If not provided, returns latest cache time
148
196
  */
149
- getCacheTime(providerId: ProviderName): Date | undefined {
150
- const cache = this.config.models[providerId];
151
- return cache ? new Date(cache.cachedAt) : undefined;
197
+ getCacheTime(providerId: Provider, authMethod?: AuthMethod): Date | undefined {
198
+ if (authMethod) {
199
+ const key = getModelCacheKey(providerId, authMethod);
200
+ const cache = this.config.models[key];
201
+ return cache ? new Date(cache.cachedAt) : undefined;
202
+ }
203
+
204
+ // Get latest cache time across all authMethods for this provider
205
+ let latestTime: Date | undefined;
206
+ for (const [key, cache] of Object.entries(this.config.models)) {
207
+ const parsed = parseModelCacheKey(key);
208
+ if (parsed && parsed.provider === providerId) {
209
+ const cacheTime = new Date(cache.cachedAt);
210
+ if (!latestTime || cacheTime > latestTime) {
211
+ latestTime = cacheTime;
212
+ }
213
+ }
214
+ }
215
+ return latestTime;
152
216
  }
153
217
 
154
218
  /**
155
219
  * Check if model cache is stale (older than 24 hours)
220
+ * @param providerId Provider ID
221
+ * @param authMethod Optional: specific auth method. If not provided, checks if any cache is fresh
156
222
  */
157
- isCacheStale(providerId: ProviderName): boolean {
158
- const cacheTime = this.getCacheTime(providerId);
223
+ isCacheStale(providerId: Provider, authMethod?: AuthMethod): boolean {
224
+ const cacheTime = this.getCacheTime(providerId, authMethod);
159
225
  if (!cacheTime) return true;
160
226
  const hoursSinceCache = (Date.now() - cacheTime.getTime()) / (1000 * 60 * 60);
161
227
  return hoursSinceCache > 24;
@@ -173,9 +239,45 @@ export class ProviderStore {
173
239
 
174
240
  /**
175
241
  * Get model count for a specific provider
242
+ * @param providerId Provider ID
243
+ * @param authMethod Optional: specific auth method. If not provided, counts all models for the provider
244
+ */
245
+ getModelCount(providerId: Provider, authMethod?: AuthMethod): number {
246
+ if (authMethod) {
247
+ const key = getModelCacheKey(providerId, authMethod);
248
+ return this.config.models[key]?.list.length ?? 0;
249
+ }
250
+
251
+ // Count all models for this provider (across all authMethods)
252
+ let count = 0;
253
+ for (const [key, cache] of Object.entries(this.config.models)) {
254
+ const parsed = parseModelCacheKey(key);
255
+ if (parsed && parsed.provider === providerId) {
256
+ count += cache.list.length;
257
+ }
258
+ }
259
+ return count;
260
+ }
261
+
262
+ /**
263
+ * Get the model cache info
264
+ * @param providerId Provider ID
265
+ * @param authMethod Optional: specific auth method
176
266
  */
177
- getModelCount(providerId: ProviderName): number {
178
- return this.config.models[providerId]?.list.length ?? 0;
267
+ getModelCache(providerId: Provider, authMethod?: AuthMethod): ModelCache | undefined {
268
+ if (authMethod) {
269
+ const key = getModelCacheKey(providerId, authMethod);
270
+ return this.config.models[key];
271
+ }
272
+
273
+ // If no authMethod specified, try to find any cache for this provider
274
+ for (const [key, cache] of Object.entries(this.config.models)) {
275
+ const parsed = parseModelCacheKey(key);
276
+ if (parsed && parsed.provider === providerId) {
277
+ return cache;
278
+ }
279
+ }
280
+ return undefined;
179
281
  }
180
282
 
181
283
  /**
@@ -3,6 +3,38 @@
3
3
  * Abstracts differences between OpenAI, Anthropic, and Gemini APIs
4
4
  */
5
5
 
6
+ import type { CostEstimate } from '../pricing/types.js';
7
+
8
+ // ============================================================================
9
+ // Provider Types
10
+ // ============================================================================
11
+
12
+ /**
13
+ * Provider - Semantic layer (only 3 providers)
14
+ */
15
+ export type Provider = 'anthropic' | 'openai' | 'gemini';
16
+
17
+ /**
18
+ * Authentication method for providers
19
+ */
20
+ export type AuthMethod = 'api_key' | 'vertex' | 'bedrock' | 'azure' | 'oauth';
21
+
22
+ /**
23
+ * Provider class metadata (static property on each provider implementation)
24
+ */
25
+ export interface ProviderClassMeta {
26
+ /** Which provider this class implements */
27
+ provider: Provider;
28
+ /** Authentication method */
29
+ authMethod: AuthMethod;
30
+ /** Environment variables required for this auth method */
31
+ envVars: string[];
32
+ /** Display name for UI */
33
+ displayName: string;
34
+ /** Optional description */
35
+ description?: string;
36
+ }
37
+
6
38
  // ============================================================================
7
39
  // Message Types
8
40
  // ============================================================================
@@ -92,6 +124,7 @@ export interface CompletionResponse {
92
124
  inputTokens: number;
93
125
  outputTokens: number;
94
126
  };
127
+ cost?: CostEstimate;
95
128
  }
96
129
 
97
130
  // ============================================================================
@@ -101,7 +134,9 @@ export interface CompletionResponse {
101
134
  export interface StreamChunkText {
102
135
  type: 'text';
103
136
  text: string;
104
- }
137
+ }/* The above code appears to be a comment block in TypeScript. It includes a placeholder
138
+ text "ANTHROPIC_VERTEX_PROJECT_ID" and " */
139
+
105
140
 
106
141
  export interface StreamChunkToolStart {
107
142
  type: 'tool_start';