1
1
// Copyright 2025 The Chromium Authors. All rights reserved.
2
2
// Use of this source code is governed by a BSD-style license that can be
3
3
// found in the LICENSE file.
4
- // Cache break: 2025-09-18T18:30 :00Z - Add skipCredentialChecks parameter for AUTOMATED_MODE
4
+ // Cache break: 2025-09-18T19:00 :00Z - Add skipCredentialChecks + preserve credentials + secure logging
5
5
6
6
import { createLogger } from './Logger.js' ;
7
7
import type { LLMProvider } from '../LLM/LLMTypes.js' ;
@@ -294,38 +294,42 @@ export class LLMConfigurationManager {
294
294
295
295
/**
296
296
* Save provider-specific settings to localStorage
297
+ * Only modifies settings for the active provider, preserving other providers' credentials
297
298
*/
298
299
private saveProviderSpecificSettings ( config : LLMConfig ) : void {
299
- // Clear all provider-specific keys first
300
- localStorage . removeItem ( STORAGE_KEYS . OPENAI_API_KEY ) ;
301
- localStorage . removeItem ( STORAGE_KEYS . LITELLM_API_KEY ) ;
302
- localStorage . removeItem ( STORAGE_KEYS . LITELLM_ENDPOINT ) ;
303
- localStorage . removeItem ( STORAGE_KEYS . GROQ_API_KEY ) ;
304
- localStorage . removeItem ( STORAGE_KEYS . OPENROUTER_API_KEY ) ;
305
-
306
- // Save current provider's settings
300
+ // Save current provider's settings only (do not clear others)
307
301
switch ( config . provider ) {
308
302
case 'openai' :
309
303
if ( config . apiKey ) {
310
304
localStorage . setItem ( STORAGE_KEYS . OPENAI_API_KEY , config . apiKey ) ;
305
+ } else {
306
+ localStorage . removeItem ( STORAGE_KEYS . OPENAI_API_KEY ) ;
311
307
}
312
308
break ;
313
309
case 'litellm' :
314
310
if ( config . endpoint ) {
315
311
localStorage . setItem ( STORAGE_KEYS . LITELLM_ENDPOINT , config . endpoint ) ;
312
+ } else {
313
+ localStorage . removeItem ( STORAGE_KEYS . LITELLM_ENDPOINT ) ;
316
314
}
317
315
if ( config . apiKey ) {
318
316
localStorage . setItem ( STORAGE_KEYS . LITELLM_API_KEY , config . apiKey ) ;
317
+ } else {
318
+ localStorage . removeItem ( STORAGE_KEYS . LITELLM_API_KEY ) ;
319
319
}
320
320
break ;
321
321
case 'groq' :
322
322
if ( config . apiKey ) {
323
323
localStorage . setItem ( STORAGE_KEYS . GROQ_API_KEY , config . apiKey ) ;
324
+ } else {
325
+ localStorage . removeItem ( STORAGE_KEYS . GROQ_API_KEY ) ;
324
326
}
325
327
break ;
326
328
case 'openrouter' :
327
329
if ( config . apiKey ) {
328
330
localStorage . setItem ( STORAGE_KEYS . OPENROUTER_API_KEY , config . apiKey ) ;
331
+ } else {
332
+ localStorage . removeItem ( STORAGE_KEYS . OPENROUTER_API_KEY ) ;
329
333
}
330
334
break ;
331
335
}
@@ -336,9 +340,18 @@ export class LLMConfigurationManager {
336
340
*/
337
341
private handleStorageChange ( event : StorageEvent ) : void {
338
342
if ( event . key && Object . values ( STORAGE_KEYS ) . includes ( event . key as any ) ) {
343
+ const sensitiveKeys = new Set ( [
344
+ STORAGE_KEYS . OPENAI_API_KEY ,
345
+ STORAGE_KEYS . LITELLM_API_KEY ,
346
+ STORAGE_KEYS . GROQ_API_KEY ,
347
+ STORAGE_KEYS . OPENROUTER_API_KEY ,
348
+ ] ) ;
349
+ const redacted =
350
+ sensitiveKeys . has ( event . key as any ) ? '(redacted)' :
351
+ ( event . newValue ? `${ event . newValue . slice ( 0 , 8 ) } …` : null ) ;
339
352
logger . debug ( 'Configuration changed in another tab' , {
340
353
key : event . key ,
341
- newValue : event . newValue
354
+ newValue : redacted
342
355
} ) ;
343
356
this . notifyListeners ( ) ;
344
357
}
@@ -361,10 +374,15 @@ export class LLMConfigurationManager {
361
374
* Get debug information about current configuration state
362
375
*/
363
376
getDebugInfo ( ) : Record < string , any > {
377
+ const redact = ( cfg ?: Partial < LLMConfig > ) => cfg ? {
378
+ ...cfg ,
379
+ apiKey : cfg . apiKey ? '(redacted)' : undefined
380
+ } : undefined ;
381
+
364
382
return {
365
383
hasOverride : this . hasOverride ( ) ,
366
- overrideConfig : this . overrideConfig ,
367
- currentConfig : this . getConfiguration ( ) ,
384
+ overrideConfig : redact ( this . overrideConfig ) ,
385
+ currentConfig : redact ( this . getConfiguration ( ) ) ,
368
386
validation : this . validateConfiguration ( ) ,
369
387
listenerCount : this . changeListeners . length ,
370
388
} ;
0 commit comments