mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-09-07 08:26:51 +00:00
This commit is contained in:
parent
6e6341346e
commit
2c917243d1
2 changed files with 84 additions and 18 deletions
|
|
@ -1298,27 +1298,28 @@ export class ClineProvider
|
|||
|
||||
/**
|
||||
* Updates the current task's API handler if the provider or model has changed.
|
||||
* This prevents unnecessary context condensing when only non-model settings change.
|
||||
* Also synchronizes the task.apiConfiguration so subsequent comparisons and logic
|
||||
* (protocol selection, reasoning display, model metadata) use the latest profile.
|
||||
* @param providerSettings The new provider settings to apply
|
||||
*/
|
||||
private updateTaskApiHandlerIfNeeded(providerSettings: ProviderSettings): void {
|
||||
const task = this.getCurrentTask()
|
||||
if (!task) return
|
||||
|
||||
if (task && task.apiConfiguration) {
|
||||
// Only rebuild API handler if provider or model actually changed
|
||||
// to avoid triggering unnecessary context condensing
|
||||
const currentProvider = task.apiConfiguration.apiProvider
|
||||
const newProvider = providerSettings.apiProvider
|
||||
const currentModelId = getModelId(task.apiConfiguration)
|
||||
const newModelId = getModelId(providerSettings)
|
||||
// Determine if we need to rebuild using the previous configuration snapshot
|
||||
const prevConfig = task.apiConfiguration
|
||||
const prevProvider = prevConfig?.apiProvider
|
||||
const prevModelId = prevConfig ? getModelId(prevConfig) : undefined
|
||||
const newProvider = providerSettings.apiProvider
|
||||
const newModelId = getModelId(providerSettings)
|
||||
|
||||
if (currentProvider !== newProvider || currentModelId !== newModelId) {
|
||||
task.api = buildApiHandler(providerSettings)
|
||||
}
|
||||
} else if (task) {
|
||||
// Fallback: rebuild if apiConfiguration is not available
|
||||
if (prevProvider !== newProvider || prevModelId !== newModelId) {
|
||||
task.api = buildApiHandler(providerSettings)
|
||||
}
|
||||
|
||||
// Always sync the task's apiConfiguration with the latest provider settings.
|
||||
// Note: Task.apiConfiguration is declared readonly in types, so we cast to any for runtime update.
|
||||
;(task as any).apiConfiguration = providerSettings
|
||||
}
|
||||
|
||||
getProviderProfileEntries(): ProviderSettingsEntry[] {
|
||||
|
|
|
|||
|
|
@ -250,7 +250,7 @@ describe("ClineProvider - API Handler Rebuild Guard", () => {
|
|||
})
|
||||
|
||||
describe("upsertProviderProfile", () => {
|
||||
test("does NOT rebuild API handler when provider and model unchanged", async () => {
|
||||
test("does NOT rebuild API handler when provider and model unchanged, but task.apiConfiguration is synced", async () => {
|
||||
// Create a task with the current config
|
||||
const mockTask = new Task({
|
||||
...defaultTaskOptions,
|
||||
|
|
@ -289,6 +289,10 @@ describe("ClineProvider - API Handler Rebuild Guard", () => {
|
|||
expect(buildApiHandlerMock).not.toHaveBeenCalled()
|
||||
// Verify the task's api property was NOT reassigned (still same reference)
|
||||
expect(mockTask.api).toBe(originalApi)
|
||||
// Verify task.apiConfiguration was synchronized with non-model fields
|
||||
expect((mockTask as any).apiConfiguration.openRouterModelId).toBe("openai/gpt-4")
|
||||
expect((mockTask as any).apiConfiguration.rateLimitSeconds).toBe(5)
|
||||
expect((mockTask as any).apiConfiguration.modelTemperature).toBe(0.7)
|
||||
})
|
||||
|
||||
test("rebuilds API handler when provider changes", async () => {
|
||||
|
|
@ -386,12 +390,13 @@ describe("ClineProvider - API Handler Rebuild Guard", () => {
|
|||
})
|
||||
|
||||
describe("activateProviderProfile", () => {
|
||||
test("does NOT rebuild API handler when provider and model unchanged", async () => {
|
||||
test("does NOT rebuild API handler when provider and model unchanged, but task.apiConfiguration is synced", async () => {
|
||||
const mockTask = new Task({
|
||||
...defaultTaskOptions,
|
||||
apiConfiguration: {
|
||||
apiProvider: "openrouter",
|
||||
openRouterModelId: "openai/gpt-4",
|
||||
modelTemperature: 0.3,
|
||||
},
|
||||
})
|
||||
const originalApi = {
|
||||
|
|
@ -406,12 +411,14 @@ describe("ClineProvider - API Handler Rebuild Guard", () => {
|
|||
|
||||
buildApiHandlerMock.mockClear()
|
||||
|
||||
// Mock activateProfile to return same provider/model
|
||||
// Mock activateProfile to return same provider/model but different non-model setting
|
||||
;(provider as any).providerSettingsManager.activateProfile = vi.fn().mockResolvedValue({
|
||||
name: "test-config",
|
||||
id: "test-id",
|
||||
apiProvider: "openrouter",
|
||||
openRouterModelId: "openai/gpt-4",
|
||||
modelTemperature: 0.9,
|
||||
rateLimitSeconds: 7,
|
||||
})
|
||||
|
||||
await provider.activateProviderProfile({ name: "test-config" })
|
||||
|
|
@ -420,9 +427,13 @@ describe("ClineProvider - API Handler Rebuild Guard", () => {
|
|||
expect(buildApiHandlerMock).not.toHaveBeenCalled()
|
||||
// Verify the API reference wasn't changed
|
||||
expect(mockTask.api).toBe(originalApi)
|
||||
// Verify task.apiConfiguration was synchronized
|
||||
expect((mockTask as any).apiConfiguration.openRouterModelId).toBe("openai/gpt-4")
|
||||
expect((mockTask as any).apiConfiguration.modelTemperature).toBe(0.9)
|
||||
expect((mockTask as any).apiConfiguration.rateLimitSeconds).toBe(7)
|
||||
})
|
||||
|
||||
test("rebuilds API handler when provider changes", async () => {
|
||||
test("rebuilds API handler when provider changes and syncs task.apiConfiguration", async () => {
|
||||
const mockTask = new Task({
|
||||
...defaultTaskOptions,
|
||||
apiConfiguration: {
|
||||
|
|
@ -458,9 +469,12 @@ describe("ClineProvider - API Handler Rebuild Guard", () => {
|
|||
apiModelId: "claude-3-5-sonnet-20241022",
|
||||
}),
|
||||
)
|
||||
// And task.apiConfiguration synced
|
||||
expect((mockTask as any).apiConfiguration.apiProvider).toBe("anthropic")
|
||||
expect((mockTask as any).apiConfiguration.apiModelId).toBe("claude-3-5-sonnet-20241022")
|
||||
})
|
||||
|
||||
test("rebuilds API handler when model changes", async () => {
|
||||
test("rebuilds API handler when model changes and syncs task.apiConfiguration", async () => {
|
||||
const mockTask = new Task({
|
||||
...defaultTaskOptions,
|
||||
apiConfiguration: {
|
||||
|
|
@ -496,6 +510,57 @@ describe("ClineProvider - API Handler Rebuild Guard", () => {
|
|||
openRouterModelId: "anthropic/claude-3-5-sonnet-20241022",
|
||||
}),
|
||||
)
|
||||
// And task.apiConfiguration synced
|
||||
expect((mockTask as any).apiConfiguration.apiProvider).toBe("openrouter")
|
||||
expect((mockTask as any).apiConfiguration.openRouterModelId).toBe("anthropic/claude-3-5-sonnet-20241022")
|
||||
})
|
||||
})
|
||||
|
||||
describe("profile switching sequence", () => {
|
||||
test("A -> B -> A updates task.apiConfiguration each time", async () => {
|
||||
const mockTask = new Task({
|
||||
...defaultTaskOptions,
|
||||
apiConfiguration: {
|
||||
apiProvider: "openrouter",
|
||||
openRouterModelId: "openai/gpt-4",
|
||||
},
|
||||
})
|
||||
mockTask.api = {
|
||||
getModel: vi.fn().mockReturnValue({
|
||||
id: "openai/gpt-4",
|
||||
info: { contextWindow: 128000 },
|
||||
}),
|
||||
} as any
|
||||
|
||||
await provider.addClineToStack(mockTask)
|
||||
|
||||
// First switch: A -> B (openrouter -> anthropic)
|
||||
buildApiHandlerMock.mockClear()
|
||||
;(provider as any).providerSettingsManager.activateProfile = vi.fn().mockResolvedValue({
|
||||
name: "anthropic-config",
|
||||
id: "anthropic-id",
|
||||
apiProvider: "anthropic",
|
||||
apiModelId: "claude-3-5-sonnet-20241022",
|
||||
})
|
||||
await provider.activateProviderProfile({ name: "anthropic-config" })
|
||||
|
||||
expect(buildApiHandlerMock).toHaveBeenCalled()
|
||||
expect((mockTask as any).apiConfiguration.apiProvider).toBe("anthropic")
|
||||
expect((mockTask as any).apiConfiguration.apiModelId).toBe("claude-3-5-sonnet-20241022")
|
||||
|
||||
// Second switch: B -> A (anthropic -> openrouter gpt-4)
|
||||
buildApiHandlerMock.mockClear()
|
||||
;(provider as any).providerSettingsManager.activateProfile = vi.fn().mockResolvedValue({
|
||||
name: "test-config",
|
||||
id: "test-id",
|
||||
apiProvider: "openrouter",
|
||||
openRouterModelId: "openai/gpt-4",
|
||||
})
|
||||
await provider.activateProviderProfile({ name: "test-config" })
|
||||
|
||||
// API handler may or may not rebuild depending on mock model id, but apiConfiguration must be updated
|
||||
expect((mockTask as any).apiConfiguration.apiProvider).toBe("openrouter")
|
||||
expect((mockTask as any).apiConfiguration.openRouterModelId).toBe("openai/gpt-4")
|
||||
})
|
||||
})
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue