()
| 296 | } |
| 297 | |
| 298 | export async function collectModels(): Promise<{ models: LanguageModel[]; env: EnvVars }> { |
| 299 | const models: LanguageModel[] = []; |
| 300 | const env: EnvVars = {}; |
| 301 | |
| 302 | note( |
| 303 | [ |
| 304 | 'AI features include Ask, which lets you ask questions about your codebase', |
| 305 | 'in natural language and get answers grounded in your indexed code.', |
| 306 | ' https://docs.sourcebot.dev/docs/features/ask/ask-sourcebot', |
| 307 | '', |
| 308 | 'You\'ll need an API key from at least one supported provider', |
| 309 | '(Anthropic, OpenAI, Google, etc.) to enable these features.', |
| 310 | ].join('\n'), |
| 311 | 'AI features', |
| 312 | ); |
| 313 | |
| 314 | const wantsAI = await confirm({ |
| 315 | message: 'Would you like to configure AI features?', |
| 316 | default: true, |
| 317 | }); |
| 318 | |
| 319 | if (!wantsAI) { |
| 320 | return { models, env }; |
| 321 | } |
| 322 | |
| 323 | // eslint-disable-next-line no-constant-condition |
| 324 | while (true) { |
| 325 | const provider = await select<Provider>({ |
| 326 | message: 'Which AI provider?', |
| 327 | loop: false, |
| 328 | choices: [ |
| 329 | { value: 'anthropic', name: 'Anthropic' }, |
| 330 | { value: 'openai', name: 'OpenAI' }, |
| 331 | { value: 'openai-compatible', name: 'OpenAI-compatible', description: 'self-hosted / custom endpoint' }, |
| 332 | { value: 'amazon-bedrock', name: 'Amazon Bedrock' }, |
| 333 | { value: 'google-generative-ai', name: 'Google Gemini' }, |
| 334 | { value: 'google-vertex', name: 'Google Vertex AI', description: 'Gemini via Vertex' }, |
| 335 | { value: 'google-vertex-anthropic', name: 'Google Vertex AI (Anthropic)', description: 'Claude via Vertex' }, |
| 336 | { value: 'azure', name: 'Azure OpenAI' }, |
| 337 | { value: 'deepseek', name: 'DeepSeek' }, |
| 338 | { value: 'mistral', name: 'Mistral' }, |
| 339 | { value: 'openrouter', name: 'OpenRouter' }, |
| 340 | { value: 'xai', name: 'xAI', description: 'Grok' }, |
| 341 | ], |
| 342 | }); |
| 343 | |
| 344 | const modelOptions = provider === 'openai-compatible' |
| 345 | ? null |
| 346 | : await getModelOptionsForProvider(provider); |
| 347 | const model = modelOptions && modelOptions.length > 0 |
| 348 | ? await searchModel({ |
| 349 | message: 'Model name', |
| 350 | models: modelOptions, |
| 351 | }) |
| 352 | : await input({ |
| 353 | message: 'Model name', |
| 354 | validate: (v) => !v?.trim() ? 'Model name is required' : true, |
| 355 | }); |
no test coverage detected