Skip to content

Commit 59414bd

Browse files
committed
fix(task): scope profile updates to the focused task
1 parent 1e5ba45 commit 59414bd

2 files changed

Lines changed: 76 additions & 0 deletions

File tree

src/core/task/Task.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -703,6 +703,10 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
703703
}
704704

705705
this.providerProfileChangeListener = async () => {
706+
if (provider.getCurrentTask()?.taskId !== this.taskId) {
707+
return
708+
}
709+
706710
try {
707711
const newState = await provider.getState()
708712
if (newState?.apiConfiguration) {
@@ -1537,6 +1541,8 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
15371541
if (provider) {
15381542
if (mode) {
15391543
await provider.setMode(mode)
1544+
await this.waitForModeInitialization()
1545+
this._taskMode = mode
15401546
}
15411547

15421548
if (providerProfile) {

src/core/task/__tests__/Task.spec.ts

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { Anthropic } from "@anthropic-ai/sdk"
88

99
import {
1010
providerIdentifiers,
11+
RooCodeEventName,
1112
type GlobalState,
1213
type ProviderSettings,
1314
type ModelInfo,
@@ -526,6 +527,48 @@ describe("Cline", () => {
526527
const metadata = requireDefined(createMessage.mock.calls[0])[2]
527528
expect(metadata?.mode).toBe("ask")
528529
})
530+
531+
it("only applies profile changes to the focused task", async () => {
532+
const parentConfiguration: ProviderSettings = {
533+
...mockApiConfig,
534+
apiModelId: "parent-model",
535+
rateLimitSeconds: 4,
536+
}
537+
const childConfiguration: ProviderSettings = {
538+
...mockApiConfig,
539+
apiModelId: "child-model",
540+
rateLimitSeconds: 8,
541+
}
542+
const activeConfiguration: ProviderSettings = {
543+
...mockApiConfig,
544+
apiModelId: "active-model",
545+
rateLimitSeconds: 12,
546+
}
547+
const parent = new Task({
548+
provider: mockProvider,
549+
apiConfiguration: parentConfiguration,
550+
taskId: "parent-task",
551+
task: "parent task",
552+
startTask: false,
553+
})
554+
const child = new Task({
555+
provider: mockProvider,
556+
apiConfiguration: childConfiguration,
557+
taskId: "child-task",
558+
task: "child task",
559+
startTask: false,
560+
})
561+
vi.spyOn(mockProvider, "getCurrentTask").mockReturnValue(child)
562+
vi.spyOn(mockProvider, "getState").mockResolvedValue({ apiConfiguration: activeConfiguration })
563+
564+
mockProvider.emit(RooCodeEventName.ProviderProfileChanged, {
565+
name: "active-profile",
566+
provider: activeConfiguration.apiProvider,
567+
})
568+
569+
await vi.waitFor(() => expect(child.apiConfiguration).toEqual(activeConfiguration))
570+
expect(parent.apiConfiguration).toEqual(parentConfiguration)
571+
})
529572
})
530573

531574
describe("sayAndCreateMissingParamError", () => {
@@ -1655,6 +1698,33 @@ describe("Cline", () => {
16551698
expect(mockProvider.postMessageToWebview).not.toHaveBeenCalled()
16561699
})
16571700

1701+
it("uses a mode selected through submitUserMessage in the next API request", async () => {
1702+
vi.spyOn(mockProvider, "getState").mockResolvedValue({ mode: "ask", mcpEnabled: false })
1703+
vi.spyOn(mockProvider, "setMode").mockResolvedValue(undefined)
1704+
const task = new Task({
1705+
provider: mockProvider,
1706+
apiConfiguration: mockApiConfig,
1707+
task: "initial task",
1708+
startTask: false,
1709+
})
1710+
vi.spyOn(task, "handleWebviewAskResponse").mockImplementation(() => {})
1711+
1712+
await task.submitUserMessage("switch modes", undefined, "code")
1713+
vi.spyOn(getTaskTestAccess(task), "getSystemPrompt").mockResolvedValue("mock system prompt")
1714+
const stream = (async function* () {
1715+
yield { type: "text", text: "response" } as ApiStreamChunk
1716+
})()
1717+
const createMessage = vi.spyOn(task.api, "createMessage").mockReturnValue(stream)
1718+
task.apiConversationHistory = [
1719+
{ role: "user", content: [{ type: "text", text: "test message" }], ts: Date.now() },
1720+
]
1721+
1722+
await task.attemptApiRequest().next()
1723+
1724+
expect(mockProvider.setMode).toHaveBeenCalledWith("code")
1725+
expect(requireDefined(createMessage.mock.calls[0])[2]?.mode).toBe("code")
1726+
})
1727+
16581728
it("should handle empty messages gracefully", async () => {
16591729
const task = new Task({
16601730
provider: mockProvider,

0 commit comments

Comments
 (0)