From 86896a8865bf1222a546a60d2857f2efb9191841 Mon Sep 17 00:00:00 2001 From: Matt Rubens Date: Sun, 23 Feb 2025 21:31:37 -0600 Subject: [PATCH] Include the original task in the power steering content --- .changeset/weak-swans-study.md | 5 ++ src/core/Cline.ts | 24 +++++-- src/core/__tests__/Cline.test.ts | 84 ++++++++++++++++++++++++ src/shared/__tests__/experiments.test.ts | 2 +- src/shared/experiments.ts | 2 +- 5 files changed, 110 insertions(+), 7 deletions(-) create mode 100644 .changeset/weak-swans-study.md diff --git a/.changeset/weak-swans-study.md b/.changeset/weak-swans-study.md new file mode 100644 index 00000000000..82997382145 --- /dev/null +++ b/.changeset/weak-swans-study.md @@ -0,0 +1,5 @@ +--- +"roo-cline": patch +--- + +Include the original task in the power steering content diff --git a/src/core/Cline.ts b/src/core/Cline.ts index 94bc6126924..4bf94e5fabb 100644 --- a/src/core/Cline.ts +++ b/src/core/Cline.ts @@ -3243,6 +3243,9 @@ export class Cline { customInstructions: globalCustomInstructions, preferredLanguage, } = (await this.providerRef.deref()?.getState()) ?? {} + + const powerSteering = Experiments.isEnabled(experiments ?? {}, EXPERIMENT_IDS.POWER_STEERING) + const currentMode = mode ?? defaultModeSlug const modeDetails = await getFullModeDetails(currentMode, customModes, customModePrompts, { cwd, @@ -3252,11 +3255,8 @@ export class Cline { details += `\n\n# Current Mode\n` details += `${currentMode}\n` details += `${modeDetails.name}\n` - if (Experiments.isEnabled(experiments ?? {}, EXPERIMENT_IDS.POWER_STEERING)) { + if (powerSteering) { details += `${modeDetails.roleDefinition}\n` - if (modeDetails.customInstructions) { - details += `${modeDetails.customInstructions}\n` - } } // Add warning if not in code mode @@ -3268,7 +3268,21 @@ export class Cline { ) { const currentModeName = getModeBySlug(currentMode, customModes)?.name ?? currentMode const defaultModeName = getModeBySlug(defaultModeSlug, customModes)?.name ?? defaultModeSlug - details += `\n\nNOTE: You are currently in '${currentModeName}' mode which only allows read-only operations. To write files or execute commands, the user will need to switch to '${defaultModeName}' mode. Note that only the user can switch modes.` + details += `\n\nNOTE: You are currently in '${currentModeName}' mode which only allows read-only operations. To write files or execute commands, the user will need to switch to '${defaultModeName}' mode or another mode with these capabilities. Note that only the user can switch modes.` + } + + if (powerSteering) { + if (modeDetails.customInstructions) { + details += `\n\n# Custom Instructions\n` + details += `${modeDetails.customInstructions}\n` + } + + const taskMessage = this.clineMessages[0]?.text ?? "" + + if (taskMessage) { + details += `\n\n# Current Task\n\n` + details += `${taskMessage}\n` + } } if (includeFileDetails) { diff --git a/src/core/__tests__/Cline.test.ts b/src/core/__tests__/Cline.test.ts index 2eb9ab83f30..e55a9037948 100644 --- a/src/core/__tests__/Cline.test.ts +++ b/src/core/__tests__/Cline.test.ts @@ -466,6 +466,90 @@ describe("Cline", () => { expect(details).toMatch(/1\/1\/2024.*5:00:00 AM.*\(America\/Los_Angeles, UTC-7:00\)/) // Full time string format }) + it("should maintain correct section order with context size before file listing", async () => { + const cline = new Cline(mockProvider, mockApiConfig, undefined, false, false, undefined, "test task") + + const details = await cline["getEnvironmentDetails"](true) + + const contextSizeIndex = details.indexOf("# Current Context Size") + const fileListingIndex = details.indexOf("# Current Working Directory") + + expect(contextSizeIndex).toBeGreaterThan(-1) + expect(fileListingIndex).toBeGreaterThan(-1) + expect(contextSizeIndex).toBeLessThan(fileListingIndex) + }) + + it("should include power steering content when experiment is enabled", async () => { + // Mock provider state + mockProvider.getState = jest.fn().mockResolvedValue({ + customInstructions: "test instructions", + mode: "code", + customModes: [], + customModePrompts: {}, + preferredLanguage: "en", + }) + + const cline = new Cline( + mockProvider, + mockApiConfig, + "test instructions", + false, + false, + undefined, + "test task", + ) + + // Mock experiments module + const { experiments, EXPERIMENT_IDS } = require("../../shared/experiments") + jest.spyOn(experiments, "isEnabled").mockImplementation((config, id) => { + return id === EXPERIMENT_IDS.POWER_STEERING ? true : false + }) + + const details = await cline["getEnvironmentDetails"](false) + + // Verify sections are present + expect(details).toContain("# Custom Instructions") + expect(details).toContain("# Current Task") + + // Verify task content + expect(details).toContain("test task") + }) + + it("should exclude power steering content when experiment is disabled", async () => { + // Mock provider state + mockProvider.getState = jest.fn().mockResolvedValue({ + customInstructions: "test instructions", + mode: "code", + customModes: [], + customModePrompts: {}, + preferredLanguage: "en", + }) + + const cline = new Cline( + mockProvider, + mockApiConfig, + "test instructions", + false, + false, + undefined, + "test task", + ) + + // Mock experiments module + const { experiments, EXPERIMENT_IDS } = require("../../shared/experiments") + jest.spyOn(experiments, "isEnabled").mockImplementation((config, id) => { + return id === EXPERIMENT_IDS.POWER_STEERING ? false : true + }) + + const details = await cline["getEnvironmentDetails"](false) + + // Verify sections are not present + expect(details).not.toContain("# Custom Instructions") + expect(details).not.toContain("") + expect(details).not.toContain("# Current Task") + expect(details).not.toContain("") + }) + describe("API conversation handling", () => { it("should clean conversation history before sending to API", async () => { const cline = new Cline(mockProvider, mockApiConfig, undefined, false, false, undefined, "test task") diff --git a/src/shared/__tests__/experiments.test.ts b/src/shared/__tests__/experiments.test.ts index c5b999a1a33..d759d9b7535 100644 --- a/src/shared/__tests__/experiments.test.ts +++ b/src/shared/__tests__/experiments.test.ts @@ -7,7 +7,7 @@ describe("experiments", () => { expect(experimentConfigsMap.POWER_STEERING).toMatchObject({ name: 'Use experimental "power steering" mode', description: - "When enabled, Roo will remind the model about the details of its current mode definition more frequently. This will lead to stronger adherence to role definitions and custom instructions, but will use more tokens per message.", + "When enabled, Roo will remind the model about the details of the original task and its current mode definition more frequently. This will lead to stronger adherence to its instructions, but will use more tokens per message.", enabled: false, }) }) diff --git a/src/shared/experiments.ts b/src/shared/experiments.ts index 2f946283c0d..cfde5641461 100644 --- a/src/shared/experiments.ts +++ b/src/shared/experiments.ts @@ -39,7 +39,7 @@ export const experimentConfigsMap: Record = { POWER_STEERING: { name: 'Use experimental "power steering" mode', description: - "When enabled, Roo will remind the model about the details of its current mode definition more frequently. This will lead to stronger adherence to role definitions and custom instructions, but will use more tokens per message.", + "When enabled, Roo will remind the model about the details of the original task and its current mode definition more frequently. This will lead to stronger adherence to its instructions, but will use more tokens per message.", enabled: false, }, }