@@ -158,13 +158,45 @@ export class ProviderSettingsManager {
158158 * Preserves the ID from the input 'config' object if it exists,
159159 * otherwise generates a new one (for creation scenarios).
160160 */
161+ /**
162+ * Save a config with the given name.
163+ * Preserves the ID from the input 'config' object if it exists,
164+ * otherwise generates a new one (for creation scenarios).
165+ *
166+ * Note: Special care is taken to ensure boolean values (including `true`)
167+ * are properly preserved during serialization/deserialization.
168+ */
161169 public async saveConfig ( name : string , config : ProviderSettingsWithId ) {
162170 try {
163171 return await this . lock ( async ( ) => {
164172 const providerProfiles = await this . load ( )
165173 // Preserve the existing ID if this is an update to an existing config.
166174 const existingId = providerProfiles . apiConfigs [ name ] ?. id
167- providerProfiles . apiConfigs [ name ] = { ...config , id : config . id || existingId || this . generateId ( ) }
175+
176+ // Create a deep copy of the config to ensure all properties (including booleans) are preserved
177+ const configCopy = JSON . parse ( JSON . stringify ( config ) )
178+
179+ // Ensure apiConfigs exists
180+ if ( ! providerProfiles . apiConfigs ) {
181+ providerProfiles . apiConfigs = { }
182+ }
183+
184+ // Create a new apiConfigs object with both existing configs and the new/updated one
185+ providerProfiles . apiConfigs = {
186+ ...providerProfiles . apiConfigs ,
187+ [ name ] : {
188+ ...configCopy ,
189+ id : config . id || existingId || this . generateId ( ) ,
190+ } ,
191+ }
192+
193+ // Debug log to inspect providerProfiles before storing
194+ console . log ( "[saveConfig] providerProfiles before store:" , {
195+ currentApiConfigName : providerProfiles . currentApiConfigName ,
196+ apiConfigs : providerProfiles . apiConfigs ,
197+ modeApiConfigs : providerProfiles . modeApiConfigs ,
198+ } )
199+
168200 await this . store ( providerProfiles )
169201 } )
170202 } catch ( error ) {
@@ -321,7 +353,19 @@ export class ProviderSettingsManager {
321353 private async load ( ) : Promise < ProviderProfiles > {
322354 try {
323355 const content = await this . context . secrets . get ( this . secretsKey )
324- return content ? providerProfilesSchema . parse ( JSON . parse ( content ) ) : this . defaultProviderProfiles
356+
357+ if ( ! content ) {
358+ return this . defaultProviderProfiles
359+ }
360+
361+ // Parse the content with a reviver function to ensure boolean values are preserved
362+ const parsedContent = JSON . parse ( content , ( key , value ) => {
363+ // Return the value as is, ensuring booleans are preserved
364+ return value
365+ } )
366+
367+ // Validate the parsed content against the schema
368+ return providerProfilesSchema . parse ( parsedContent )
325369 } catch ( error ) {
326370 if ( error instanceof ZodError ) {
327371 telemetryService . captureSchemaValidationError ( { schemaName : "ProviderProfiles" , error } )
@@ -333,7 +377,16 @@ export class ProviderSettingsManager {
333377
334378 private async store ( providerProfiles : ProviderProfiles ) {
335379 try {
336- await this . context . secrets . store ( this . secretsKey , JSON . stringify ( providerProfiles , null , 2 ) )
380+ // Use a custom replacer function to ensure boolean values are preserved
381+ const replacer = ( key : string , value : any ) => {
382+ // Explicitly handle boolean values to ensure they're preserved
383+ if ( value === true || value === false ) {
384+ return value
385+ }
386+ return value
387+ }
388+
389+ await this . context . secrets . store ( this . secretsKey , JSON . stringify ( providerProfiles , replacer , 2 ) )
337390 } catch ( error ) {
338391 throw new Error ( `Failed to write provider profiles to secrets: ${ error } ` )
339392 }
0 commit comments