@@ -36,13 +36,18 @@ const globalSettingsExportSchema = globalSettingsSchema.omit({
3636
3737export class ContextProxy {
3838 private readonly originalContext : vscode . ExtensionContext
39+ private readonly sessionId : string
3940
4041 private stateCache : GlobalState
4142 private secretCache : SecretState
4243 private _isInitialized = false
4344
4445 constructor ( context : vscode . ExtensionContext ) {
4546 this . originalContext = context
47+ // Use sessionId to isolate state between multiple VSCode windows
48+ // This ensures each window maintains its own independent state
49+ // Fallback to empty string if sessionId is not available (e.g., in tests)
50+ this . sessionId = vscode . env . sessionId || ""
4651 this . stateCache = { }
4752 this . secretCache = { }
4853 this . _isInitialized = false
@@ -55,8 +60,9 @@ export class ContextProxy {
5560 public async initialize ( ) {
5661 for ( const key of GLOBAL_STATE_KEYS ) {
5762 try {
58- // Revert to original assignment
59- this . stateCache [ key ] = this . originalContext . globalState . get ( key )
63+ // Use session-specific key for state isolation
64+ const sessionKey = this . getSessionKey ( key )
65+ this . stateCache [ key ] = this . originalContext . globalState . get ( sessionKey )
6066 } catch ( error ) {
6167 logger . error ( `Error loading global ${ key } : ${ error instanceof Error ? error . message : String ( error ) } ` )
6268 }
@@ -91,13 +97,38 @@ export class ContextProxy {
9197 this . _isInitialized = true
9298 }
9399
100+ /**
101+ * Creates a session-specific key by combining the base key with the session ID.
102+ * This ensures state isolation between multiple VSCode windows.
103+ *
104+ * @param key The base state key
105+ * @returns The session-specific key
106+ */
107+ private getSessionKey ( key : string ) : string {
108+ // For certain keys that should be shared across sessions (like API configs),
109+ // we don't add the session prefix
110+ const sharedKeys = [ "listApiConfigMeta" , "currentApiConfigName" , "apiProvider" ]
111+ if ( sharedKeys . includes ( key ) ) {
112+ return key
113+ }
114+
115+ // If no sessionId is available (e.g., in tests), use the key as-is
116+ if ( ! this . sessionId ) {
117+ return key
118+ }
119+
120+ // For all other keys, add session prefix to isolate state
121+ return `session_${ this . sessionId } _${ key } `
122+ }
123+
94124 /**
95125 * Migrates old nested openRouterImageGenerationSettings to the new flattened structure
96126 */
97127 private async migrateImageGenerationSettings ( ) {
98128 try {
99- // Check if there's an old nested structure
100- const oldNestedSettings = this . originalContext . globalState . get < any > ( "openRouterImageGenerationSettings" )
129+ // Check if there's an old nested structure (use session-specific key)
130+ const sessionKey = this . getSessionKey ( "openRouterImageGenerationSettings" )
131+ const oldNestedSettings = this . originalContext . globalState . get < any > ( sessionKey )
101132
102133 if ( oldNestedSettings && typeof oldNestedSettings === "object" ) {
103134 logger . info ( "Migrating old nested image generation settings to flattened structure" )
@@ -114,16 +145,14 @@ export class ContextProxy {
114145
115146 // Migrate the selected model if it exists and we don't already have one
116147 if ( oldNestedSettings . selectedModel && ! this . stateCache . openRouterImageGenerationSelectedModel ) {
117- await this . originalContext . globalState . update (
118- "openRouterImageGenerationSelectedModel" ,
119- oldNestedSettings . selectedModel ,
120- )
148+ const modelSessionKey = this . getSessionKey ( "openRouterImageGenerationSelectedModel" )
149+ await this . originalContext . globalState . update ( modelSessionKey , oldNestedSettings . selectedModel )
121150 this . stateCache . openRouterImageGenerationSelectedModel = oldNestedSettings . selectedModel
122151 logger . info ( "Migrated openRouterImageGenerationSelectedModel to global state" )
123152 }
124153
125154 // Clean up the old nested structure
126- await this . originalContext . globalState . update ( "openRouterImageGenerationSettings" , undefined )
155+ await this . originalContext . globalState . update ( sessionKey , undefined )
127156 logger . info ( "Removed old nested openRouterImageGenerationSettings" )
128157 }
129158 } catch ( error ) {
@@ -166,7 +195,9 @@ export class ContextProxy {
166195 getGlobalState < K extends GlobalStateKey > ( key : K , defaultValue : GlobalState [ K ] ) : GlobalState [ K ]
167196 getGlobalState < K extends GlobalStateKey > ( key : K , defaultValue ?: GlobalState [ K ] ) : GlobalState [ K ] {
168197 if ( isPassThroughStateKey ( key ) ) {
169- const value = this . originalContext . globalState . get < GlobalState [ K ] > ( key )
198+ // Use session-specific key for pass-through state as well
199+ const sessionKey = this . getSessionKey ( key )
200+ const value = this . originalContext . globalState . get < GlobalState [ K ] > ( sessionKey )
170201 return value === undefined || value === null ? defaultValue : value
171202 }
172203
@@ -175,12 +206,14 @@ export class ContextProxy {
175206 }
176207
177208 updateGlobalState < K extends GlobalStateKey > ( key : K , value : GlobalState [ K ] ) {
209+ const sessionKey = this . getSessionKey ( key )
210+
178211 if ( isPassThroughStateKey ( key ) ) {
179- return this . originalContext . globalState . update ( key , value )
212+ return this . originalContext . globalState . update ( sessionKey , value )
180213 }
181214
182215 this . stateCache [ key ] = value
183- return this . originalContext . globalState . update ( key , value )
216+ return this . originalContext . globalState . update ( sessionKey , value )
184217 }
185218
186219 private getAllGlobalState ( ) : GlobalState {
@@ -362,7 +395,10 @@ export class ContextProxy {
362395 this . secretCache = { }
363396
364397 await Promise . all ( [
365- ...GLOBAL_STATE_KEYS . map ( ( key ) => this . originalContext . globalState . update ( key , undefined ) ) ,
398+ ...GLOBAL_STATE_KEYS . map ( ( key ) => {
399+ const sessionKey = this . getSessionKey ( key )
400+ return this . originalContext . globalState . update ( sessionKey , undefined )
401+ } ) ,
366402 ...SECRET_STATE_KEYS . map ( ( key ) => this . originalContext . secrets . delete ( key ) ) ,
367403 ...GLOBAL_SECRET_KEYS . map ( ( key ) => this . originalContext . secrets . delete ( key ) ) ,
368404 ] )
0 commit comments