mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-08-28 05:27:24 +00:00
fix: implement tab-specific mode/model state management
- Add tab-specific state properties to ClineProvider (tabSpecificMode, tabSpecificApiConfigName) - Create activateProviderProfileForTab method for tab-specific profile activation - Update handleModeSwitch to use tab-specific mode instead of global state - Modify getState methods to prioritize tab-specific state over global state - Update webview message handlers to use tab-specific methods when available This ensures each Roo tab maintains its own independent mode and model selection, fixing the issue where changing mode/model in one tab affected all other tabs. Fixes #8044
This commit is contained in:
parent
2263d86a20
commit
bb529ead01
2 changed files with 58 additions and 9 deletions
|
|
@ -139,6 +139,11 @@ export class ClineProvider
|
|||
private pendingOperations: Map<string, PendingEditOperation> = new Map()
|
||||
private static readonly PENDING_OPERATION_TIMEOUT_MS = 30000 // 30 seconds
|
||||
|
||||
// Tab-specific state for mode and model
|
||||
private tabSpecificMode?: Mode
|
||||
private tabSpecificApiConfigName?: string
|
||||
private readonly instanceId: string = Math.random().toString(36).substring(7)
|
||||
|
||||
public isViewLaunched = false
|
||||
public settingsImportedAt?: number
|
||||
public readonly latestAnnouncementId = "sep-2025-roo-code-cloud" // Roo Code Cloud announcement
|
||||
|
|
@ -1161,7 +1166,8 @@ export class ClineProvider
|
|||
}
|
||||
}
|
||||
|
||||
await this.updateGlobalState("mode", newMode)
|
||||
// Update tab-specific mode instead of global state
|
||||
this.tabSpecificMode = newMode
|
||||
|
||||
this.emit(RooCodeEventName.ModeChanged, newMode)
|
||||
|
||||
|
|
@ -1177,11 +1183,11 @@ export class ClineProvider
|
|||
const profile = listApiConfig.find(({ id }) => id === savedConfigId)
|
||||
|
||||
if (profile?.name) {
|
||||
await this.activateProviderProfile({ name: profile.name })
|
||||
await this.activateProviderProfileForTab({ name: profile.name })
|
||||
}
|
||||
} else {
|
||||
// If no saved config for this mode, save current config as default.
|
||||
const currentApiConfigName = this.getGlobalState("currentApiConfigName")
|
||||
const currentApiConfigName = this.tabSpecificApiConfigName || this.getGlobalState("currentApiConfigName")
|
||||
|
||||
if (currentApiConfigName) {
|
||||
const config = listApiConfig.find((c) => c.name === currentApiConfigName)
|
||||
|
|
@ -1318,6 +1324,39 @@ export class ClineProvider
|
|||
}
|
||||
}
|
||||
|
||||
// New method for tab-specific provider profile activation
|
||||
async activateProviderProfileForTab(args: { name: string } | { id: string }) {
|
||||
const { name, id, ...providerSettings } = await this.providerSettingsManager.activateProfile(args)
|
||||
|
||||
// Update tab-specific API config name
|
||||
this.tabSpecificApiConfigName = name
|
||||
|
||||
// Update list metadata globally (this is fine to share)
|
||||
await this.contextProxy.setValue("listApiConfigMeta", await this.providerSettingsManager.listConfig())
|
||||
|
||||
// Store provider settings in context for this tab's use
|
||||
// Note: We don't update global currentApiConfigName to avoid affecting other tabs
|
||||
|
||||
const mode = this.tabSpecificMode || this.getGlobalState("mode") || defaultModeSlug
|
||||
|
||||
if (id) {
|
||||
await this.providerSettingsManager.setModeConfig(mode, id)
|
||||
}
|
||||
|
||||
// Change the provider for the current task.
|
||||
const task = this.getCurrentTask()
|
||||
|
||||
if (task) {
|
||||
task.api = buildApiHandler(providerSettings)
|
||||
}
|
||||
|
||||
await this.postStateToWebview()
|
||||
|
||||
if (providerSettings.apiProvider) {
|
||||
this.emit(RooCodeEventName.ProviderProfileChanged, { name, provider: providerSettings.apiProvider })
|
||||
}
|
||||
}
|
||||
|
||||
async updateCustomInstructions(instructions?: string) {
|
||||
// User may be clearing the field.
|
||||
await this.updateGlobalState("customInstructions", instructions || undefined)
|
||||
|
|
@ -1855,10 +1894,10 @@ export class ClineProvider
|
|||
enableMcpServerCreation: enableMcpServerCreation ?? true,
|
||||
alwaysApproveResubmit: alwaysApproveResubmit ?? false,
|
||||
requestDelaySeconds: requestDelaySeconds ?? 10,
|
||||
currentApiConfigName: currentApiConfigName ?? "default",
|
||||
currentApiConfigName: this.tabSpecificApiConfigName ?? currentApiConfigName ?? "default",
|
||||
listApiConfigMeta: listApiConfigMeta ?? [],
|
||||
pinnedApiConfigs: pinnedApiConfigs ?? {},
|
||||
mode: mode ?? defaultModeSlug,
|
||||
mode: this.tabSpecificMode ?? mode ?? defaultModeSlug,
|
||||
customModePrompts: customModePrompts ?? {},
|
||||
customSupportPrompts: customSupportPrompts ?? {},
|
||||
enhancementApiConfigId,
|
||||
|
|
@ -2070,13 +2109,13 @@ export class ClineProvider
|
|||
terminalZshP10k: stateValues.terminalZshP10k ?? false,
|
||||
terminalZdotdir: stateValues.terminalZdotdir ?? false,
|
||||
terminalCompressProgressBar: stateValues.terminalCompressProgressBar ?? true,
|
||||
mode: stateValues.mode ?? defaultModeSlug,
|
||||
mode: this.tabSpecificMode ?? stateValues.mode ?? defaultModeSlug,
|
||||
language: stateValues.language ?? formatLanguage(vscode.env.language),
|
||||
mcpEnabled: stateValues.mcpEnabled ?? true,
|
||||
enableMcpServerCreation: stateValues.enableMcpServerCreation ?? true,
|
||||
alwaysApproveResubmit: stateValues.alwaysApproveResubmit ?? false,
|
||||
requestDelaySeconds: Math.max(5, stateValues.requestDelaySeconds ?? 10),
|
||||
currentApiConfigName: stateValues.currentApiConfigName ?? "default",
|
||||
currentApiConfigName: this.tabSpecificApiConfigName ?? stateValues.currentApiConfigName ?? "default",
|
||||
listApiConfigMeta: stateValues.listApiConfigMeta ?? [],
|
||||
pinnedApiConfigs: stateValues.pinnedApiConfigs ?? {},
|
||||
modeApiConfigs: stateValues.modeApiConfigs ?? ({} as Record<Mode, string>),
|
||||
|
|
|
|||
|
|
@ -1848,7 +1848,12 @@ export const webviewMessageHandler = async (
|
|||
case "loadApiConfiguration":
|
||||
if (message.text) {
|
||||
try {
|
||||
await provider.activateProviderProfile({ name: message.text })
|
||||
// Use tab-specific activation method if available
|
||||
if (typeof provider.activateProviderProfileForTab === "function") {
|
||||
await provider.activateProviderProfileForTab({ name: message.text })
|
||||
} else {
|
||||
await provider.activateProviderProfile({ name: message.text })
|
||||
}
|
||||
} catch (error) {
|
||||
provider.log(
|
||||
`Error load api configuration: ${JSON.stringify(error, Object.getOwnPropertyNames(error), 2)}`,
|
||||
|
|
@ -1860,7 +1865,12 @@ export const webviewMessageHandler = async (
|
|||
case "loadApiConfigurationById":
|
||||
if (message.text) {
|
||||
try {
|
||||
await provider.activateProviderProfile({ id: message.text })
|
||||
// Use tab-specific activation method if available
|
||||
if (typeof provider.activateProviderProfileForTab === "function") {
|
||||
await provider.activateProviderProfileForTab({ id: message.text })
|
||||
} else {
|
||||
await provider.activateProviderProfile({ id: message.text })
|
||||
}
|
||||
} catch (error) {
|
||||
provider.log(
|
||||
`Error load api configuration by ID: ${JSON.stringify(error, Object.getOwnPropertyNames(error), 2)}`,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue