@sylphx/flow 1.0.2 → 1.0.4

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 (229) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/package.json +10 -9
  3. package/src/commands/codebase-command.ts +168 -0
  4. package/src/commands/flow-command.ts +1137 -0
  5. package/src/commands/flow-orchestrator.ts +296 -0
  6. package/src/commands/hook-command.ts +444 -0
  7. package/src/commands/init-command.ts +92 -0
  8. package/src/commands/init-core.ts +322 -0
  9. package/src/commands/knowledge-command.ts +161 -0
  10. package/src/commands/run-command.ts +120 -0
  11. package/src/components/benchmark-monitor.tsx +331 -0
  12. package/src/components/reindex-progress.tsx +261 -0
  13. package/src/composables/functional/index.ts +14 -0
  14. package/src/composables/functional/useEnvironment.ts +171 -0
  15. package/src/composables/functional/useFileSystem.ts +139 -0
  16. package/src/composables/index.ts +5 -0
  17. package/src/composables/useEnv.ts +13 -0
  18. package/src/composables/useRuntimeConfig.ts +27 -0
  19. package/src/composables/useTargetConfig.ts +45 -0
  20. package/src/config/ai-config.ts +376 -0
  21. package/src/config/constants.ts +35 -0
  22. package/src/config/index.ts +27 -0
  23. package/src/config/rules.ts +43 -0
  24. package/src/config/servers.ts +371 -0
  25. package/src/config/targets.ts +126 -0
  26. package/src/core/agent-loader.ts +141 -0
  27. package/src/core/agent-manager.ts +174 -0
  28. package/src/core/ai-sdk.ts +603 -0
  29. package/src/core/app-factory.ts +381 -0
  30. package/src/core/builtin-agents.ts +9 -0
  31. package/src/core/command-system.ts +550 -0
  32. package/src/core/config-system.ts +550 -0
  33. package/src/core/connection-pool.ts +390 -0
  34. package/src/core/di-container.ts +155 -0
  35. package/src/core/error-handling.ts +519 -0
  36. package/src/core/formatting/bytes.test.ts +115 -0
  37. package/src/core/formatting/bytes.ts +64 -0
  38. package/src/core/functional/async.ts +313 -0
  39. package/src/core/functional/either.ts +109 -0
  40. package/src/core/functional/error-handler.ts +135 -0
  41. package/src/core/functional/error-types.ts +311 -0
  42. package/src/core/functional/index.ts +19 -0
  43. package/src/core/functional/option.ts +142 -0
  44. package/src/core/functional/pipe.ts +189 -0
  45. package/src/core/functional/result.ts +204 -0
  46. package/src/core/functional/validation.ts +138 -0
  47. package/src/core/headless-display.ts +96 -0
  48. package/src/core/index.ts +6 -0
  49. package/src/core/installers/file-installer.ts +303 -0
  50. package/src/core/installers/mcp-installer.ts +213 -0
  51. package/src/core/interfaces/index.ts +22 -0
  52. package/src/core/interfaces/repository.interface.ts +91 -0
  53. package/src/core/interfaces/service.interface.ts +133 -0
  54. package/src/core/interfaces.ts +129 -0
  55. package/src/core/loop-controller.ts +200 -0
  56. package/src/core/result.ts +351 -0
  57. package/src/core/rule-loader.ts +147 -0
  58. package/src/core/rule-manager.ts +240 -0
  59. package/src/core/service-config.ts +252 -0
  60. package/src/core/session-service.ts +121 -0
  61. package/src/core/state-detector.ts +393 -0
  62. package/src/core/storage-factory.ts +115 -0
  63. package/src/core/stream-handler.ts +288 -0
  64. package/src/core/target-manager.ts +161 -0
  65. package/src/core/type-utils.ts +427 -0
  66. package/src/core/unified-storage.ts +456 -0
  67. package/src/core/upgrade-manager.ts +300 -0
  68. package/src/core/validation/limit.test.ts +155 -0
  69. package/src/core/validation/limit.ts +46 -0
  70. package/src/core/validation/query.test.ts +44 -0
  71. package/src/core/validation/query.ts +20 -0
  72. package/src/db/auto-migrate.ts +322 -0
  73. package/src/db/base-database-client.ts +144 -0
  74. package/src/db/cache-db.ts +218 -0
  75. package/src/db/cache-schema.ts +75 -0
  76. package/src/db/database.ts +70 -0
  77. package/src/db/index.ts +252 -0
  78. package/src/db/memory-db.ts +153 -0
  79. package/src/db/memory-schema.ts +29 -0
  80. package/src/db/schema.ts +289 -0
  81. package/src/db/session-repository.ts +733 -0
  82. package/src/domains/codebase/index.ts +5 -0
  83. package/src/domains/codebase/tools.ts +139 -0
  84. package/src/domains/index.ts +8 -0
  85. package/src/domains/knowledge/index.ts +10 -0
  86. package/src/domains/knowledge/resources.ts +537 -0
  87. package/src/domains/knowledge/tools.ts +174 -0
  88. package/src/domains/utilities/index.ts +6 -0
  89. package/src/domains/utilities/time/index.ts +5 -0
  90. package/src/domains/utilities/time/tools.ts +291 -0
  91. package/src/index.ts +211 -0
  92. package/src/services/agent-service.ts +273 -0
  93. package/src/services/claude-config-service.ts +252 -0
  94. package/src/services/config-service.ts +258 -0
  95. package/src/services/evaluation-service.ts +271 -0
  96. package/src/services/functional/evaluation-logic.ts +296 -0
  97. package/src/services/functional/file-processor.ts +273 -0
  98. package/src/services/functional/index.ts +12 -0
  99. package/src/services/index.ts +13 -0
  100. package/src/services/mcp-service.ts +432 -0
  101. package/src/services/memory.service.ts +476 -0
  102. package/src/services/search/base-indexer.ts +156 -0
  103. package/src/services/search/codebase-indexer-types.ts +38 -0
  104. package/src/services/search/codebase-indexer.ts +647 -0
  105. package/src/services/search/embeddings-provider.ts +455 -0
  106. package/src/services/search/embeddings.ts +316 -0
  107. package/src/services/search/functional-indexer.ts +323 -0
  108. package/src/services/search/index.ts +27 -0
  109. package/src/services/search/indexer.ts +380 -0
  110. package/src/services/search/knowledge-indexer.ts +422 -0
  111. package/src/services/search/semantic-search.ts +244 -0
  112. package/src/services/search/tfidf.ts +559 -0
  113. package/src/services/search/unified-search-service.ts +888 -0
  114. package/src/services/smart-config-service.ts +385 -0
  115. package/src/services/storage/cache-storage.ts +487 -0
  116. package/src/services/storage/drizzle-storage.ts +581 -0
  117. package/src/services/storage/index.ts +15 -0
  118. package/src/services/storage/lancedb-vector-storage.ts +494 -0
  119. package/src/services/storage/memory-storage.ts +268 -0
  120. package/src/services/storage/separated-storage.ts +467 -0
  121. package/src/services/storage/vector-storage.ts +13 -0
  122. package/src/shared/agents/index.ts +63 -0
  123. package/src/shared/files/index.ts +99 -0
  124. package/src/shared/index.ts +32 -0
  125. package/src/shared/logging/index.ts +24 -0
  126. package/src/shared/processing/index.ts +153 -0
  127. package/src/shared/types/index.ts +25 -0
  128. package/src/targets/claude-code.ts +574 -0
  129. package/src/targets/functional/claude-code-logic.ts +185 -0
  130. package/src/targets/functional/index.ts +6 -0
  131. package/src/targets/opencode.ts +529 -0
  132. package/src/types/agent.types.ts +32 -0
  133. package/src/types/api/batch.ts +108 -0
  134. package/src/types/api/errors.ts +118 -0
  135. package/src/types/api/index.ts +55 -0
  136. package/src/types/api/requests.ts +76 -0
  137. package/src/types/api/responses.ts +180 -0
  138. package/src/types/api/websockets.ts +85 -0
  139. package/src/types/api.types.ts +9 -0
  140. package/src/types/benchmark.ts +49 -0
  141. package/src/types/cli.types.ts +87 -0
  142. package/src/types/common.types.ts +35 -0
  143. package/src/types/database.types.ts +510 -0
  144. package/src/types/mcp-config.types.ts +448 -0
  145. package/src/types/mcp.types.ts +69 -0
  146. package/src/types/memory-types.ts +63 -0
  147. package/src/types/provider.types.ts +28 -0
  148. package/src/types/rule.types.ts +24 -0
  149. package/src/types/session.types.ts +214 -0
  150. package/src/types/target-config.types.ts +295 -0
  151. package/src/types/target.types.ts +140 -0
  152. package/src/types/todo.types.ts +25 -0
  153. package/src/types.ts +40 -0
  154. package/src/utils/advanced-tokenizer.ts +191 -0
  155. package/src/utils/agent-enhancer.ts +114 -0
  156. package/src/utils/ai-model-fetcher.ts +19 -0
  157. package/src/utils/async-file-operations.ts +516 -0
  158. package/src/utils/audio-player.ts +345 -0
  159. package/src/utils/cli-output.ts +266 -0
  160. package/src/utils/codebase-helpers.ts +211 -0
  161. package/src/utils/console-ui.ts +79 -0
  162. package/src/utils/database-errors.ts +140 -0
  163. package/src/utils/debug-logger.ts +49 -0
  164. package/src/utils/error-handler.ts +53 -0
  165. package/src/utils/file-operations.ts +310 -0
  166. package/src/utils/file-scanner.ts +259 -0
  167. package/src/utils/functional/array.ts +355 -0
  168. package/src/utils/functional/index.ts +15 -0
  169. package/src/utils/functional/object.ts +279 -0
  170. package/src/utils/functional/string.ts +281 -0
  171. package/src/utils/functional.ts +543 -0
  172. package/src/utils/help.ts +20 -0
  173. package/src/utils/immutable-cache.ts +106 -0
  174. package/src/utils/index.ts +78 -0
  175. package/src/utils/jsonc.ts +158 -0
  176. package/src/utils/logger.ts +396 -0
  177. package/src/utils/mcp-config.ts +249 -0
  178. package/src/utils/memory-tui.ts +414 -0
  179. package/src/utils/models-dev.ts +91 -0
  180. package/src/utils/notifications.ts +169 -0
  181. package/src/utils/object-utils.ts +51 -0
  182. package/src/utils/parallel-operations.ts +487 -0
  183. package/src/utils/paths.ts +143 -0
  184. package/src/utils/process-manager.ts +155 -0
  185. package/src/utils/prompts.ts +120 -0
  186. package/src/utils/search-tool-builder.ts +214 -0
  187. package/src/utils/secret-utils.ts +179 -0
  188. package/src/utils/security.ts +537 -0
  189. package/src/utils/session-manager.ts +168 -0
  190. package/src/utils/session-title.ts +87 -0
  191. package/src/utils/settings.ts +182 -0
  192. package/src/utils/simplified-errors.ts +410 -0
  193. package/src/utils/sync-utils.ts +159 -0
  194. package/src/utils/target-config.ts +570 -0
  195. package/src/utils/target-utils.ts +394 -0
  196. package/src/utils/template-engine.ts +94 -0
  197. package/src/utils/test-audio.ts +71 -0
  198. package/src/utils/todo-context.ts +46 -0
  199. package/src/utils/token-counter.ts +288 -0
  200. package/dist/index.d.ts +0 -10
  201. package/dist/index.js +0 -59554
  202. package/dist/lancedb.linux-x64-gnu-b7f0jgsz.node +0 -0
  203. package/dist/lancedb.linux-x64-musl-tgcv22rx.node +0 -0
  204. package/dist/shared/chunk-25dwp0dp.js +0 -89
  205. package/dist/shared/chunk-3pjb6063.js +0 -208
  206. package/dist/shared/chunk-4d6ydpw7.js +0 -2854
  207. package/dist/shared/chunk-4wjcadjk.js +0 -225
  208. package/dist/shared/chunk-5j4w74t6.js +0 -30
  209. package/dist/shared/chunk-5j8m3dh3.js +0 -58
  210. package/dist/shared/chunk-5thh3qem.js +0 -91
  211. package/dist/shared/chunk-6g9xy73m.js +0 -252
  212. package/dist/shared/chunk-7eq34c42.js +0 -23
  213. package/dist/shared/chunk-c2gwgx3r.js +0 -115
  214. package/dist/shared/chunk-cjd3mk4c.js +0 -1320
  215. package/dist/shared/chunk-g5cv6703.js +0 -368
  216. package/dist/shared/chunk-hpkhykhq.js +0 -574
  217. package/dist/shared/chunk-m2322pdk.js +0 -122
  218. package/dist/shared/chunk-nd5fdvaq.js +0 -26
  219. package/dist/shared/chunk-pgd3m6zf.js +0 -108
  220. package/dist/shared/chunk-qk8n91hw.js +0 -494
  221. package/dist/shared/chunk-rkkn8szp.js +0 -16855
  222. package/dist/shared/chunk-t16rfxh0.js +0 -61
  223. package/dist/shared/chunk-t4fbfa5v.js +0 -19
  224. package/dist/shared/chunk-t77h86w6.js +0 -276
  225. package/dist/shared/chunk-v0ez4aef.js +0 -71
  226. package/dist/shared/chunk-v29j2r3s.js +0 -32051
  227. package/dist/shared/chunk-vfbc6ew5.js +0 -765
  228. package/dist/shared/chunk-vmeqwm1c.js +0 -204
  229. package/dist/shared/chunk-x66eh37x.js +0 -137
@@ -0,0 +1,385 @@
1
+ /**
2
+ * Smart Configuration Service
3
+ * Handles intelligent provider and agent selection with user preferences
4
+ */
5
+
6
+ import inquirer from 'inquirer';
7
+ import chalk from 'chalk';
8
+ import { ConfigService, UserSettings, RuntimeChoices } from './config-service.js';
9
+ import { loadAllAgents } from '../core/agent-loader.js';
10
+
11
+ export interface SmartConfigOptions {
12
+ selectProvider?: boolean;
13
+ selectAgent?: boolean;
14
+ useDefaults?: boolean;
15
+ provider?: string;
16
+ agent?: string;
17
+ }
18
+
19
+ export class SmartConfigService {
20
+ /**
21
+ * Initial setup - configure API keys once
22
+ */
23
+ static async initialSetup(): Promise<void> {
24
+ console.log(chalk.cyan.bold('šŸ”‘ Initial Setup - Configure API Keys\n'));
25
+
26
+ const userSettings = await ConfigService.loadHomeSettings();
27
+ const apiKeys = userSettings.apiKeys || {};
28
+
29
+ // Configure providers
30
+ const providers = [
31
+ { id: 'kimi', name: 'Kimi', hasKey: !!apiKeys.kimi },
32
+ { id: 'z.ai', name: 'Z.ai (Recommended)', hasKey: !!apiKeys['z.ai'] },
33
+ ];
34
+
35
+ const missingProviders = providers.filter(p => !p.hasKey);
36
+ const existingProviders = providers.filter(p => p.hasKey);
37
+
38
+ // Ask which providers to configure
39
+ console.log(chalk.cyan('Available providers:\n'));
40
+ console.log(chalk.dim(' • Default (uses Claude Code configuration)'));
41
+ providers.forEach(p => {
42
+ const status = p.hasKey ? chalk.green('āœ“') : chalk.yellow('ā—‹');
43
+ console.log(` ${status} ${p.name}`);
44
+ });
45
+ console.log('');
46
+
47
+ const { selectedProvider } = await inquirer.prompt([
48
+ {
49
+ type: 'list',
50
+ name: 'selectedProvider',
51
+ message: 'Select provider:',
52
+ choices: [
53
+ {
54
+ name: 'Default (Use Claude Code configuration)',
55
+ value: 'default',
56
+ },
57
+ {
58
+ name: 'Kimi',
59
+ value: 'kimi',
60
+ },
61
+ {
62
+ name: 'Z.ai (Recommended)',
63
+ value: 'z.ai',
64
+ },
65
+ ],
66
+ },
67
+ ]);
68
+
69
+ if (selectedProvider !== 'default') {
70
+ await this.configureSelectedProviders([selectedProvider], apiKeys);
71
+ } else {
72
+ console.log(chalk.dim('Using Claude Code default configuration.'));
73
+ }
74
+
75
+ if (existingProviders.length > 0) {
76
+ console.log(chalk.green('\nāœ… Already configured:'));
77
+ existingProviders.forEach(p => {
78
+ console.log(chalk.dim(` • ${p.name}`));
79
+ });
80
+ }
81
+
82
+ // Mark setup as completed (no need for default preferences prompt)
83
+ await ConfigService.saveHomeSettings({ hasCompletedSetup: true });
84
+ console.log(chalk.green('\nāœ“ Setup complete!\n'));
85
+ }
86
+
87
+ /**
88
+ * Configure selected providers
89
+ */
90
+ private static async configureSelectedProviders(
91
+ selectedProviders: string[],
92
+ existingApiKeys: any
93
+ ): Promise<void> {
94
+ for (const providerId of selectedProviders) {
95
+ const providerName = providerId === 'kimi' ? 'Kimi' : 'Z.ai';
96
+ console.log(chalk.cyan(`\nšŸ“‹ Configure ${providerName}\n`));
97
+
98
+ const { apiKey } = await inquirer.prompt([
99
+ {
100
+ type: 'password',
101
+ name: 'apiKey',
102
+ message: `Enter API Key for ${providerName}:`,
103
+ mask: '*',
104
+ validate: (input) => input.length > 10 || 'API Key appears too short',
105
+ },
106
+ ]);
107
+
108
+ existingApiKeys[providerId] = apiKey;
109
+ console.log(chalk.green(`āœ“ API Key configured for ${providerName}`));
110
+ }
111
+
112
+ // Save all API keys
113
+ await ConfigService.saveHomeSettings({ apiKeys: existingApiKeys });
114
+ }
115
+
116
+ /**
117
+ * Setup default preferences
118
+ */
119
+ private static async setupDefaultPreferences(): Promise<void> {
120
+ console.log(chalk.cyan('āš™ļø Setup Default Preferences\n'));
121
+
122
+ const userSettings = await ConfigService.loadHomeSettings();
123
+ const availableProviders = ConfigService.getAvailableProviders(userSettings);
124
+
125
+ if (availableProviders.length === 0) {
126
+ console.log(chalk.yellow('⚠ No API keys configured yet. Skipping preferences setup.'));
127
+ return;
128
+ }
129
+
130
+ const { setupDefaults } = await inquirer.prompt([
131
+ {
132
+ type: 'confirm',
133
+ name: 'setupDefaults',
134
+ message: 'Set up default preferences?',
135
+ default: true,
136
+ },
137
+ ]);
138
+
139
+ if (!setupDefaults) {
140
+ console.log(chalk.dim('Skipping preferences setup.'));
141
+ return;
142
+ }
143
+
144
+ // Select default provider
145
+ if (availableProviders.length > 1) {
146
+ const { defaultProvider } = await inquirer.prompt([
147
+ {
148
+ type: 'list',
149
+ name: 'defaultProvider',
150
+ message: 'Select default provider:',
151
+ choices: availableProviders.map(p => ({
152
+ name: p.charAt(0).toUpperCase() + p.slice(1),
153
+ value: p,
154
+ })),
155
+ default: userSettings.defaultProvider || availableProviders[0],
156
+ },
157
+ ]);
158
+
159
+ userSettings.defaultProvider = defaultProvider;
160
+ }
161
+
162
+ // Set default agent (will use dynamic loading)
163
+ const { useDefaultAgent } = await inquirer.prompt([
164
+ {
165
+ type: 'confirm',
166
+ name: 'useDefaultAgent',
167
+ message: 'Set default agent?',
168
+ default: true,
169
+ },
170
+ ]);
171
+
172
+ if (useDefaultAgent) {
173
+ try {
174
+ const agents = await loadAllAgents(process.cwd());
175
+ if (agents.length > 0) {
176
+ const { defaultAgent } = await inquirer.prompt([
177
+ {
178
+ type: 'list',
179
+ name: 'defaultAgent',
180
+ message: 'Select default agent:',
181
+ choices: agents.map(a => ({
182
+ name: a.metadata.name || a.id,
183
+ value: a.id,
184
+ })),
185
+ default: userSettings.defaultAgent || (agents.find(a => a.id === 'coder')?.id || agents[0].id),
186
+ },
187
+ ]);
188
+
189
+ userSettings.defaultAgent = defaultAgent;
190
+ }
191
+ } catch (error) {
192
+ console.log(chalk.yellow('⚠ Could not load agents, using "coder" as default'));
193
+ userSettings.defaultAgent = 'coder';
194
+ }
195
+ }
196
+
197
+ await ConfigService.saveHomeSettings(userSettings);
198
+ console.log(chalk.green('āœ“ Default preferences saved'));
199
+ }
200
+
201
+ /**
202
+ * Runtime selection - choose provider and agent for this run
203
+ *
204
+ * DESIGN PRINCIPLE: Smart Defaults
205
+ * - Has saved default → Use it (no prompt)
206
+ * - No saved default → Prompt user
207
+ * - Explicit flag (--select-provider/--select-agent) → Force prompt (override)
208
+ * - Explicit option (--provider/--agent) → Use specified value
209
+ */
210
+ static async selectRuntimeChoices(options: SmartConfigOptions): Promise<RuntimeChoices> {
211
+ const config = await ConfigService.loadConfiguration();
212
+ const choices: RuntimeChoices = {};
213
+
214
+ // Handle provider selection
215
+ if (options.provider) {
216
+ // 1. Explicit option provided
217
+ choices.provider = options.provider;
218
+ } else if (options.selectProvider) {
219
+ // 2. Force selection (override defaults)
220
+ choices.provider = await this.selectProvider(config.user);
221
+ } else if (config.user.defaultProvider) {
222
+ // 3. Use saved default (SMART DEFAULT - no prompt needed)
223
+ choices.provider = config.user.defaultProvider;
224
+ console.log(chalk.dim(` āœ“ Provider: ${choices.provider}`));
225
+ } else {
226
+ // 4. No default saved, must prompt
227
+ choices.provider = await this.selectProvider(config.user);
228
+ }
229
+
230
+ // Handle agent selection
231
+ if (options.agent) {
232
+ // 1. Explicit option provided
233
+ choices.agent = options.agent;
234
+ } else if (options.selectAgent) {
235
+ // 2. Force selection (override defaults)
236
+ choices.agent = await this.selectAgent(config.user.defaultAgent);
237
+ } else if (config.user.defaultAgent) {
238
+ // 3. Use saved default (SMART DEFAULT - no prompt needed)
239
+ choices.agent = config.user.defaultAgent;
240
+ console.log(chalk.dim(` āœ“ Agent: ${choices.agent}`));
241
+ } else {
242
+ // 4. No default saved, must prompt
243
+ choices.agent = await this.selectAgent(config.user.defaultAgent);
244
+ }
245
+
246
+ // Save choices for next time
247
+ await ConfigService.saveHomeSettings({
248
+ defaultProvider: choices.provider,
249
+ defaultAgent: choices.agent,
250
+ });
251
+
252
+ return choices;
253
+ }
254
+
255
+ /**
256
+ * Select provider for this run
257
+ */
258
+ private static async selectProvider(userSettings: UserSettings): Promise<string> {
259
+ const apiKeys = userSettings.apiKeys || {};
260
+
261
+ // Always show all 3 providers
262
+ const allProviders = [
263
+ { id: 'default', name: 'Default (Claude Code configuration)', hasKey: true },
264
+ { id: 'kimi', name: 'Kimi', hasKey: !!apiKeys.kimi },
265
+ { id: 'z.ai', name: 'Z.ai (Recommended)', hasKey: !!apiKeys['z.ai'] },
266
+ ];
267
+
268
+ // Show last used provider hint
269
+ const lastUsed = userSettings.defaultProvider;
270
+ const message = lastUsed
271
+ ? `Select provider (last used: ${lastUsed}):`
272
+ : 'Select provider:';
273
+
274
+ const { provider } = await inquirer.prompt([
275
+ {
276
+ type: 'list',
277
+ name: 'provider',
278
+ message,
279
+ choices: allProviders.map(p => ({
280
+ name: p.hasKey ? p.name : `${p.name} (Need API key)`,
281
+ value: p.id,
282
+ })),
283
+ default: lastUsed || 'default',
284
+ },
285
+ ]);
286
+
287
+ // If user selected a provider without API key, prompt for it
288
+ if (provider !== 'default' && !apiKeys[provider]) {
289
+ console.log(chalk.cyan(`\nšŸ”‘ Configure ${provider} API key:\n`));
290
+ const { apiKey } = await inquirer.prompt([
291
+ {
292
+ type: 'password',
293
+ name: 'apiKey',
294
+ message: `Enter API Key for ${provider}:`,
295
+ mask: '*',
296
+ validate: (input) => input.length > 10 || 'API Key appears too short',
297
+ },
298
+ ]);
299
+
300
+ // Save the API key
301
+ apiKeys[provider] = apiKey;
302
+ await ConfigService.saveHomeSettings({ apiKeys });
303
+ console.log(chalk.green(`āœ“ API Key saved for ${provider}\n`));
304
+ }
305
+
306
+ return provider;
307
+ }
308
+
309
+ /**
310
+ * Select agent for this run
311
+ */
312
+ private static async selectAgent(lastUsed?: string): Promise<string> {
313
+ try {
314
+ const agents = await loadAllAgents(process.cwd());
315
+
316
+ if (agents.length === 0) {
317
+ console.log(chalk.yellow('⚠ No agents found, using "coder"'));
318
+ return 'coder';
319
+ }
320
+
321
+ // Build message with last used hint
322
+ const message = lastUsed
323
+ ? `Select agent (last used: ${lastUsed}):`
324
+ : 'Select agent:';
325
+
326
+ const { agent } = await inquirer.prompt([
327
+ {
328
+ type: 'list',
329
+ name: 'agent',
330
+ message,
331
+ choices: agents.map(a => ({
332
+ name: a.metadata.name || a.id,
333
+ value: a.id,
334
+ })),
335
+ default: lastUsed || agents.find(a => a.id === 'coder')?.id || agents[0].id,
336
+ },
337
+ ]);
338
+
339
+ return agent;
340
+ } catch (error) {
341
+ console.log(chalk.yellow('⚠ Could not load agents, using "coder"'));
342
+ return 'coder';
343
+ }
344
+ }
345
+
346
+ /**
347
+ * Setup environment variables based on runtime choices
348
+ */
349
+ static async setupEnvironment(provider: string): Promise<void> {
350
+ const userSettings = await ConfigService.loadHomeSettings();
351
+ const apiKeys = userSettings.apiKeys || {};
352
+
353
+ if (provider !== 'default' && !apiKeys[provider]) {
354
+ throw new Error(`No API key configured for provider: ${provider}`);
355
+ }
356
+
357
+ const providerConfigs = {
358
+ default: {
359
+ description: 'Default (No Override)',
360
+ },
361
+ kimi: {
362
+ ANTHROPIC_BASE_URL: 'https://api.kimi.com/coding/',
363
+ description: 'Kimi',
364
+ },
365
+ 'z.ai': {
366
+ ANTHROPIC_BASE_URL: 'https://api.z.ai/api/anthropic',
367
+ description: 'Z.ai Proxy',
368
+ },
369
+ };
370
+
371
+ // Setup environment based on provider
372
+ if (provider === 'default') {
373
+ // Don't override anything - use user's existing Claude Code configuration
374
+ console.log(chalk.dim(' āœ“ Using Claude Code default configuration'));
375
+ return;
376
+ }
377
+
378
+ const config = providerConfigs[provider as keyof typeof providerConfigs];
379
+ process.env.ANTHROPIC_BASE_URL = config.ANTHROPIC_BASE_URL;
380
+ process.env.ANTHROPIC_AUTH_TOKEN = apiKeys[provider]; // Claude Code uses ANTHROPIC_AUTH_TOKEN, not ANTHROPIC_API_KEY
381
+
382
+ // Success message
383
+ console.log(chalk.green(` āœ“ Environment configured for ${provider}`));
384
+ }
385
+ }