11#!/usr/bin/env node
2- import { confirm , input , password , select } from '@inquirer/prompts' ;
2+ import { confirm , select } from '@inquirer/prompts' ;
33import chalk from 'chalk' ;
44import ora from 'ora' ;
55import { existsSync , writeFileSync } from 'fs' ;
@@ -12,6 +12,7 @@ import { collectGiteaConfig } from './gitea.js';
1212import { collectGitHubConfig } from './github.js' ;
1313import { collectGitLabConfig } from './gitlab.js' ;
1414import { collectLocalReposConfig } from './localRepos.js' ;
15+ import { collectModels , PROVIDER_ENV_KEYS } from './models.js' ;
1516import {
1617 type CollectResult ,
1718 type ConnectionConfig ,
@@ -25,162 +26,6 @@ import {
2526const DOCKER_COMPOSE_BRANCH = 'bkellam/setup-wizard' ;
2627const DOCKER_COMPOSE_URL = `https://raw.githubusercontent.com/sourcebot-dev/sourcebot/${ DOCKER_COMPOSE_BRANCH } /docker-compose.yml` ;
2728
28- type ModelConfig = Record < string , unknown > ;
29-
30- const PROVIDER_DEFAULT_MODELS : Record < string , string > = {
31- 'anthropic' : 'claude-sonnet-4-6' ,
32- 'openai' : 'gpt-4o' ,
33- 'google-generative-ai' : 'gemini-2.0-flash' ,
34- 'deepseek' : 'deepseek-chat' ,
35- 'mistral' : 'mistral-large-latest' ,
36- 'xai' : 'grok-2-latest' ,
37- } ;
38-
39- const PROVIDER_ENV_KEYS : Record < string , string > = {
40- 'anthropic' : 'ANTHROPIC_API_KEY' ,
41- 'openai' : 'OPENAI_API_KEY' ,
42- 'google-generative-ai' : 'GOOGLE_GENERATIVE_AI_API_KEY' ,
43- 'deepseek' : 'DEEPSEEK_API_KEY' ,
44- 'mistral' : 'MISTRAL_API_KEY' ,
45- 'xai' : 'XAI_API_KEY' ,
46- 'openrouter' : 'OPENROUTER_API_KEY' ,
47- 'openai-compatible' : 'OPENAI_COMPATIBLE_API_KEY' ,
48- 'azure' : 'AZURE_OPENAI_API_KEY' ,
49- } ;
50-
51- async function collectModels ( ) : Promise < { models: ModelConfig [ ] ; env: EnvVars } > {
52- const models : ModelConfig [ ] = [ ] ;
53- const env : EnvVars = { } ;
54-
55- const wantsAI = await confirm ( {
56- message : 'Would you like to configure AI features?' ,
57- default : true ,
58- } ) ;
59-
60- if ( ! wantsAI ) {
61- return { models, env } ;
62- }
63-
64- // eslint-disable-next-line no-constant-condition
65- while ( true ) {
66- const provider = await select < string > ( {
67- message : 'Which AI provider?' ,
68- choices : [
69- { value : 'anthropic' , name : 'Anthropic' , description : 'Claude' } ,
70- { value : 'openai' , name : 'OpenAI' , description : 'GPT-4o, o1' } ,
71- { value : 'google-generative-ai' , name : 'Google Gemini' } ,
72- { value : 'deepseek' , name : 'DeepSeek' } ,
73- { value : 'mistral' , name : 'Mistral' } ,
74- { value : 'xai' , name : 'xAI' , description : 'Grok' } ,
75- { value : 'openrouter' , name : 'OpenRouter' } ,
76- { value : 'openai-compatible' , name : 'OpenAI-compatible' , description : 'self-hosted / custom endpoint' } ,
77- { value : 'amazon-bedrock' , name : 'Amazon Bedrock' } ,
78- { value : 'azure' , name : 'Azure OpenAI' } ,
79- ] ,
80- } ) ;
81-
82- const modelConfig : ModelConfig = { provider } ;
83-
84- const defaultModel = PROVIDER_DEFAULT_MODELS [ provider ] ;
85- const model = await input ( {
86- message : 'Model name' ,
87- default : defaultModel ?? '' ,
88- validate : ( v ) => ! v ?. trim ( ) ? 'Model name is required' : true ,
89- } ) ;
90- modelConfig . model = model ;
91-
92- if ( provider === 'openai-compatible' ) {
93- const baseUrl = await input ( {
94- message : 'Base URL (e.g. https://your-endpoint.example.com/v1)' ,
95- validate : ( v ) => {
96- if ( ! v ?. trim ( ) ) {
97- return 'Base URL is required' ;
98- }
99- if ( ! / ^ h t t p s ? : \/ \/ / . test ( v ) ) {
100- return 'Must start with http:// or https://' ;
101- }
102- return true ;
103- } ,
104- } ) ;
105- modelConfig . baseUrl = baseUrl ;
106- }
107-
108- if ( provider === 'azure' ) {
109- const resourceName = await input ( {
110- message : 'Azure resource name' ,
111- validate : ( v ) => ! v ?. trim ( ) ? 'Resource name is required' : true ,
112- } ) ;
113- modelConfig . resourceName = resourceName ;
114-
115- const apiVersion = await input ( {
116- message : 'API version' ,
117- default : '2024-08-01-preview' ,
118- validate : ( v ) => ! v ?. trim ( ) ? 'API version is required' : true ,
119- } ) ;
120- modelConfig . apiVersion = apiVersion ;
121- }
122-
123- if ( provider === 'amazon-bedrock' ) {
124- const useDefaultChain = await confirm ( {
125- message : 'Use the default AWS credential chain? (No to provide Access Key ID and Secret explicitly)' ,
126- default : true ,
127- } ) ;
128-
129- if ( ! useDefaultChain ) {
130- if ( ! env [ 'AWS_ACCESS_KEY_ID' ] ) {
131- const keyId = await input ( {
132- message : 'AWS Access Key ID (stored as AWS_ACCESS_KEY_ID)' ,
133- validate : ( v ) => ! v ?. trim ( ) ? 'Access Key ID is required' : true ,
134- } ) ;
135- env [ 'AWS_ACCESS_KEY_ID' ] = keyId ;
136- }
137- modelConfig . accessKeyId = { env : 'AWS_ACCESS_KEY_ID' } ;
138-
139- if ( ! env [ 'AWS_SECRET_ACCESS_KEY' ] ) {
140- const secret = await password ( {
141- message : 'AWS Secret Access Key (stored as AWS_SECRET_ACCESS_KEY)' ,
142- mask : true ,
143- validate : ( v ) => ! v ?. trim ( ) ? 'Secret Access Key is required' : true ,
144- } ) ;
145- env [ 'AWS_SECRET_ACCESS_KEY' ] = secret ;
146- }
147- modelConfig . accessKeySecret = { env : 'AWS_SECRET_ACCESS_KEY' } ;
148- }
149-
150- const region = await input ( {
151- message : 'AWS region' ,
152- default : 'us-east-1' ,
153- validate : ( v ) => ! v ?. trim ( ) ? 'Region is required' : true ,
154- } ) ;
155- modelConfig . region = region ;
156- } else {
157- const envKey = PROVIDER_ENV_KEYS [ provider ] ?? `${ provider . toUpperCase ( ) . replace ( / - / g, '_' ) } _API_KEY` ;
158- if ( ! env [ envKey ] ) {
159- const apiKey = await password ( {
160- message : `API key (stored as ${ envKey } )` ,
161- mask : true ,
162- validate : ( v ) => ! v ?. trim ( ) ? 'API key is required' : true ,
163- } ) ;
164- env [ envKey ] = apiKey ;
165- }
166- modelConfig . token = { env : envKey } ;
167- }
168-
169- models . push ( modelConfig ) ;
170-
171- const addAnother = await confirm ( {
172- message : 'Add another model?' ,
173- default : false ,
174- } ) ;
175-
176- if ( ! addAnother ) {
177- break ;
178- }
179- }
180-
181- return { models, env } ;
182- }
183-
18429const PLATFORM_LABELS : Record < string , string > = {
18530 github : 'GitHub' ,
18631 gitlab : 'GitLab' ,
0 commit comments