11import * as vscode from 'vscode' ;
22import { ProfileService } from '../services/profileService' ;
3- import { ProfileWithAPIKey , ProviderID } from '../types' ;
3+ import { ProfileWithAPIKey , ProviderConnection , ProviderID } from '../types' ;
44import { logger } from '../utils/logger' ;
55import { listModelsFromProviderConnection , providers } from '../providers/providers' ;
66
@@ -17,7 +17,7 @@ export class ProfileCommandProvider {
1717 public async createProfile ( ) : Promise < void > {
1818 try {
1919 // First, ask the user to select the provider.
20- const availableProviders : { label : string ; id : ProviderID } [ ] = providers . map ( provider => ( { label : provider . name , id : provider . id } ) ) ;
20+ const availableProviders : { label : string ; id : ProviderID } [ ] = providers . map ( provider => ( { label : provider . name , id : provider . id } ) ) ;
2121
2222 const selectedProvider = await vscode . window . showQuickPick ( availableProviders , {
2323 title : "Create New AI Profile - Step 1 of 5" ,
@@ -79,85 +79,19 @@ export class ProfileCommandProvider {
7979 apiKey = inputApiKey ;
8080 }
8181
82- // Load models for the selected provider.
83- const qp = vscode . window . createQuickPick ( ) ;
84- qp . title = 'Create New AI Profile - Step 4 of 5' ;
85- qp . placeholder = 'Loading available models from your provider...' ;
86- qp . items = [ {
87- label : '$(loading~spin) Loading models...' ,
88- description : 'This may take a few seconds' ,
89- detail : 'Connecting to your AI provider to fetch available models'
90- } ] ;
91- qp . ignoreFocusOut = true ;
92- qp . busy = true ;
93- qp . show ( ) ;
94-
95- let models : any [ ] = [ ] ;
96- try {
97- models = await listModelsFromProviderConnection ( {
82+ let selectedModelId = '' ;
83+ if ( selectedProvider . id === 'mistral-codestral' ) {
84+ selectedModelId = 'codestral-latest' ;
85+ } else {
86+ selectedModelId = await this . askForModel ( {
9887 id : selectedProvider . id ,
9988 baseURL,
10089 apiKey
10190 } ) ;
102- } catch ( error ) {
103- logger . error ( 'Error loading models:' , error ) ;
104- qp . items = [ {
105- label : '$(error) Connection Failed' ,
106- description : 'Could not connect to your AI provider' ,
107- detail : `Error: ${ error instanceof Error ? error . message : 'Unknown error' } `
108- } ] ;
109- qp . placeholder = 'Connection failed - please check your settings' ;
110- qp . busy = false ;
111-
112- // Wait for user acknowledgment before closing.
113- await new Promise < void > ( ( resolve ) => {
114- qp . onDidHide ( ( ) => {
115- qp . dispose ( ) ;
116- resolve ( ) ;
117- } ) ;
118- } ) ;
119- return ;
12091 }
12192
122- // Replace items as models are now loaded.
123- if ( models . length === 0 ) {
124- qp . items = [ {
125- label : '$(warning) No models found' ,
126- description : 'Your provider connection works, but no models are available' ,
127- detail : 'This might be normal for some providers. You can continue with a custom model ID.'
128- } ] ;
129- qp . placeholder = 'No models found - you may need to specify a model manually' ;
130- } else {
131- qp . items = models . map ( model => ( {
132- label : model . name ,
133- id : model . id ,
134- description : `Model ID: ${ model . id } ` ,
135- detail : 'Select this model for code completions'
136- } ) ) ;
137- qp . placeholder = `Choose from ${ models . length } available models` ;
138- }
139- qp . busy = false ;
140-
141- // Wait for user to select a model.
142- const modelId = await new Promise < string > ( ( resolve ) => {
143- qp . onDidAccept ( ( ) => {
144- const selectedItems = qp . selectedItems ;
145- if ( selectedItems . length > 0 ) {
146- const modelName = selectedItems [ 0 ] . label ;
147- const selectedModelId = models . find ( m => m . name === modelName ) ?. id || '' ;
148- qp . hide ( ) ;
149- resolve ( selectedModelId ) ;
150- }
151- } ) ;
152-
153- qp . onDidHide ( ( ) => {
154- qp . dispose ( ) ;
155- resolve ( '' ) ; // User cancelled or closed the picker
156- } ) ;
157- } ) ;
158-
159- if ( ! modelId ) {
160- return ; // User cancelled.
93+ if ( ! selectedModelId ) {
94+ return ;
16195 }
16296
16397 // Ask the user to set profile name.
@@ -224,7 +158,7 @@ export class ProfileCommandProvider {
224158 name : name . trim ( ) ,
225159 provider : selectedProvider . id ,
226160 baseURL : baseURL . trim ( ) ,
227- modelId : modelId . trim ( ) ,
161+ modelId : selectedModelId . trim ( ) ,
228162 apiKey : apiKey . trim ( )
229163 } ;
230164
@@ -234,7 +168,7 @@ export class ProfileCommandProvider {
234168 // Set as default if requested
235169 if ( shouldSetAsDefault ) {
236170 try {
237- await this . profileService . setActiveProfileId ( newProfile . id ) ;
171+ await this . profileService . setActiveProfileId ( newProfile . id ) ;
238172 logger . info ( `Profile set as default: ${ newProfile . name } ` ) ;
239173 vscode . window . showInformationMessage ( `Profile "${ newProfile . name } " created and activated! TabCoder is ready to use.` ) ;
240174 } catch ( error ) {
@@ -251,13 +185,89 @@ export class ProfileCommandProvider {
251185 'Try Again' ,
252186 'Cancel'
253187 ) ;
254-
188+
255189 if ( retry === 'Try Again' ) {
256190 await this . createProfile ( ) ;
257191 }
258192 }
259193 }
260194
195+ async askForModel ( conn : ProviderConnection ) : Promise < string > {
196+ // Load models for the selected provider.
197+ const qp = vscode . window . createQuickPick ( ) ;
198+ qp . title = 'Create New AI Profile - Step 4 of 5' ;
199+ qp . placeholder = 'Loading available models from your provider...' ;
200+ qp . items = [ {
201+ label : '$(loading~spin) Loading models...' ,
202+ description : 'This may take a few seconds' ,
203+ detail : 'Connecting to your AI provider to fetch available models'
204+ } ] ;
205+ qp . ignoreFocusOut = true ;
206+ qp . busy = true ;
207+ qp . show ( ) ;
208+
209+ let models : any [ ] = [ ] ;
210+ try {
211+ models = await listModelsFromProviderConnection ( conn ) ;
212+ } catch ( error ) {
213+ logger . error ( 'Error loading models:' , error ) ;
214+ qp . items = [ {
215+ label : '$(error) Connection Failed' ,
216+ description : 'Could not connect to your AI provider' ,
217+ detail : `Error: ${ error instanceof Error ? error . message : 'Unknown error' } `
218+ } ] ;
219+ qp . placeholder = 'Connection failed - please check your settings' ;
220+ qp . busy = false ;
221+
222+ // Wait for user acknowledgment before closing.
223+ await new Promise < void > ( ( resolve ) => {
224+ qp . onDidHide ( ( ) => {
225+ qp . dispose ( ) ;
226+ resolve ( ) ;
227+ } ) ;
228+ } ) ;
229+
230+ return '' ;
231+ }
232+
233+ // Replace items as models are now loaded.
234+ if ( models . length === 0 ) {
235+ qp . items = [ {
236+ label : '$(warning) No models found' ,
237+ description : 'Your provider connection works, but no models are available' ,
238+ detail : 'This might be normal for some providers. You can continue with a custom model ID.'
239+ } ] ;
240+ qp . placeholder = 'No models found - you may need to specify a model manually' ;
241+ } else {
242+ qp . items = models . map ( model => ( {
243+ label : model . name ,
244+ id : model . id ,
245+ description : `Model ID: ${ model . id } ` ,
246+ detail : 'Select this model for code completions'
247+ } ) ) ;
248+ qp . placeholder = `Choose from ${ models . length } available models` ;
249+ }
250+ qp . busy = false ;
251+
252+ // Wait for user to select a model.
253+ return await new Promise < string > ( ( resolve ) => {
254+ qp . onDidAccept ( ( ) => {
255+ const selectedItems = qp . selectedItems ;
256+ if ( selectedItems . length > 0 ) {
257+ const modelName = selectedItems [ 0 ] . label ;
258+ const selectedModelId = models . find ( m => m . name === modelName ) ?. id || '' ;
259+ qp . hide ( ) ;
260+ resolve ( selectedModelId ) ;
261+ }
262+ } ) ;
263+
264+ qp . onDidHide ( ( ) => {
265+ qp . dispose ( ) ;
266+ resolve ( '' ) ; // User cancelled or closed the picker
267+ } ) ;
268+ } ) ;
269+ }
270+
261271 /**
262272 * Command: Set active configuration profile
263273 */
@@ -278,7 +288,7 @@ export class ProfileCommandProvider {
278288 }
279289
280290 const currentActiveProfile = await this . profileService . getActiveProfile ( ) ;
281-
291+
282292 // Create quick pick items
283293 const profileItems = profiles . map ( profile => ( {
284294 label : `${ profile . id === currentActiveProfile ?. id ? '$(check) ' : '' } ${ profile . name } ` ,
@@ -336,7 +346,7 @@ export class ProfileCommandProvider {
336346 }
337347
338348 const currentActiveProfile = await this . profileService . getActiveProfile ( ) ;
339-
349+
340350 // Create quick pick items
341351 const profileItems = profiles . map ( profile => ( {
342352 label : `${ profile . id === currentActiveProfile ?. id ? '$(warning) ' : '' } ${ profile . name } ` ,
@@ -364,7 +374,7 @@ export class ProfileCommandProvider {
364374 const warningMessage = isActiveProfile
365375 ? `You are about to delete "${ profileName } ", which is currently your active profile.\n\nThis will:\n• Remove all configuration data\n• Disable TabCoder completions\n• Cannot be undone\n\nAre you sure?`
366376 : `Are you sure you want to delete the profile "${ profileName } "?\n\nThis action cannot be undone.` ;
367-
377+
368378 const result = await vscode . window . showWarningMessage (
369379 warningMessage ,
370380 { modal : true } ,
@@ -377,7 +387,7 @@ export class ProfileCommandProvider {
377387 }
378388
379389 await this . profileService . deleteProfile ( selectedItem . profileId ) ;
380-
390+
381391 if ( isActiveProfile ) {
382392 vscode . window . showInformationMessage ( `Profile "${ profileName } " deleted. TabCoder is now disabled.` ) ;
383393 } else {
0 commit comments