mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-08-28 05:27:24 +00:00
Remove preferredLanguage and just rely on VSCode language
This commit is contained in:
parent
ae6903b26c
commit
baa346dc46
22 changed files with 1666 additions and 386 deletions
|
|
@ -1,4 +1,13 @@
|
|||
const vscode = {
|
||||
env: {
|
||||
language: "en", // Default language for tests
|
||||
appName: "Visual Studio Code Test",
|
||||
appHost: "desktop",
|
||||
appRoot: "/test/path",
|
||||
machineId: "test-machine-id",
|
||||
sessionId: "test-session-id",
|
||||
shell: "/bin/zsh",
|
||||
},
|
||||
window: {
|
||||
showInformationMessage: jest.fn(),
|
||||
showErrorMessage: jest.fn(),
|
||||
|
|
|
|||
|
|
@ -1102,7 +1102,6 @@ export class Cline {
|
|||
browserViewportSize,
|
||||
mode,
|
||||
customModePrompts,
|
||||
preferredLanguage,
|
||||
experiments,
|
||||
enableMcpServerCreation,
|
||||
browserToolEnabled,
|
||||
|
|
@ -1124,7 +1123,6 @@ export class Cline {
|
|||
customModePrompts,
|
||||
customModes,
|
||||
this.customInstructions,
|
||||
preferredLanguage,
|
||||
this.diffEnabled,
|
||||
experiments,
|
||||
enableMcpServerCreation,
|
||||
|
|
@ -3665,13 +3663,12 @@ export class Cline {
|
|||
customModePrompts,
|
||||
experiments = {} as Record<ExperimentId, boolean>,
|
||||
customInstructions: globalCustomInstructions,
|
||||
preferredLanguage,
|
||||
} = (await this.providerRef.deref()?.getState()) ?? {}
|
||||
const currentMode = mode ?? defaultModeSlug
|
||||
const modeDetails = await getFullModeDetails(currentMode, customModes, customModePrompts, {
|
||||
cwd,
|
||||
globalCustomInstructions,
|
||||
preferredLanguage,
|
||||
vscodeLanguage: vscode.env.language,
|
||||
})
|
||||
details += `\n\n# Current Mode\n`
|
||||
details += `<slug>${currentMode}</slug>\n`
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -46,8 +46,6 @@ const mockContext = {
|
|||
} as unknown as vscode.ExtensionContext
|
||||
|
||||
describe("File-Based Custom System Prompt", () => {
|
||||
const experiments = {}
|
||||
|
||||
beforeEach(() => {
|
||||
// Reset mocks before each test
|
||||
jest.clearAllMocks()
|
||||
|
|
@ -66,18 +64,17 @@ describe("File-Based Custom System Prompt", () => {
|
|||
const prompt = await SYSTEM_PROMPT(
|
||||
mockContext,
|
||||
"test/path", // Using a relative path without leading slash
|
||||
false,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
defaultModeSlug,
|
||||
customModePrompts,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
experiments,
|
||||
true,
|
||||
false, // supportsComputerUse
|
||||
undefined, // mcpHub
|
||||
undefined, // diffStrategy
|
||||
undefined, // browserViewportSize
|
||||
defaultModeSlug, // mode
|
||||
customModePrompts, // customModePrompts
|
||||
undefined, // customModes
|
||||
undefined, // globalCustomInstructions
|
||||
undefined, // diffEnabled
|
||||
undefined, // experiments
|
||||
true, // enableMcpServerCreation
|
||||
)
|
||||
|
||||
// Should contain default sections
|
||||
|
|
@ -101,18 +98,17 @@ describe("File-Based Custom System Prompt", () => {
|
|||
const prompt = await SYSTEM_PROMPT(
|
||||
mockContext,
|
||||
"test/path", // Using a relative path without leading slash
|
||||
false,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
defaultModeSlug,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
experiments,
|
||||
true,
|
||||
false, // supportsComputerUse
|
||||
undefined, // mcpHub
|
||||
undefined, // diffStrategy
|
||||
undefined, // browserViewportSize
|
||||
defaultModeSlug, // mode
|
||||
undefined, // customModePrompts
|
||||
undefined, // customModes
|
||||
undefined, // globalCustomInstructions
|
||||
undefined, // diffEnabled
|
||||
undefined, // experiments
|
||||
true, // enableMcpServerCreation
|
||||
)
|
||||
|
||||
// Should contain role definition and file-based system prompt
|
||||
|
|
@ -120,7 +116,6 @@ describe("File-Based Custom System Prompt", () => {
|
|||
expect(prompt).toContain(fileCustomSystemPrompt)
|
||||
|
||||
// Should not contain any of the default sections
|
||||
expect(prompt).not.toContain("TOOL USE")
|
||||
expect(prompt).not.toContain("CAPABILITIES")
|
||||
expect(prompt).not.toContain("MODES")
|
||||
})
|
||||
|
|
@ -146,18 +141,17 @@ describe("File-Based Custom System Prompt", () => {
|
|||
const prompt = await SYSTEM_PROMPT(
|
||||
mockContext,
|
||||
"test/path", // Using a relative path without leading slash
|
||||
false,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
defaultModeSlug,
|
||||
customModePrompts,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
experiments,
|
||||
true,
|
||||
false, // supportsComputerUse
|
||||
undefined, // mcpHub
|
||||
undefined, // diffStrategy
|
||||
undefined, // browserViewportSize
|
||||
defaultModeSlug, // mode
|
||||
customModePrompts, // customModePrompts
|
||||
undefined, // customModes
|
||||
undefined, // globalCustomInstructions
|
||||
undefined, // diffEnabled
|
||||
undefined, // experiments
|
||||
true, // enableMcpServerCreation
|
||||
)
|
||||
|
||||
// Should contain custom role definition and file-based system prompt
|
||||
|
|
@ -165,7 +159,6 @@ describe("File-Based Custom System Prompt", () => {
|
|||
expect(prompt).toContain(fileCustomSystemPrompt)
|
||||
|
||||
// Should not contain any of the default sections
|
||||
expect(prompt).not.toContain("TOOL USE")
|
||||
expect(prompt).not.toContain("CAPABILITIES")
|
||||
expect(prompt).not.toContain("MODES")
|
||||
})
|
||||
|
|
|
|||
|
|
@ -3,20 +3,20 @@ import { getCapabilitiesSection } from "../sections/capabilities"
|
|||
import { DiffStrategy, DiffResult } from "../../diff/types"
|
||||
|
||||
describe("addCustomInstructions", () => {
|
||||
test("adds preferred language to custom instructions", async () => {
|
||||
test("adds vscode language to custom instructions", async () => {
|
||||
const result = await addCustomInstructions(
|
||||
"mode instructions",
|
||||
"global instructions",
|
||||
"/test/path",
|
||||
"test-mode",
|
||||
{ preferredLanguage: "French" },
|
||||
{ vscodeLanguage: "fr" },
|
||||
)
|
||||
|
||||
expect(result).toContain("Language Preference:")
|
||||
expect(result).toContain("You should always speak and think in the French language")
|
||||
expect(result).toContain('You should always speak and think in the "fr" language')
|
||||
})
|
||||
|
||||
test("works without preferred language", async () => {
|
||||
test("works without vscode language", async () => {
|
||||
const result = await addCustomInstructions(
|
||||
"mode instructions",
|
||||
"global instructions",
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import { SearchReplaceDiffStrategy } from "../../../core/diff/strategies/search-
|
|||
import * as vscode from "vscode"
|
||||
import fs from "fs/promises"
|
||||
import os from "os"
|
||||
import { defaultModeSlug, modes } from "../../../shared/modes"
|
||||
import { defaultModeSlug, modes, Mode, isToolAllowedForMode } from "../../../shared/modes"
|
||||
// Import path utils to get access to toPosix string extension
|
||||
import "../../../utils/path"
|
||||
import { addCustomInstructions } from "../sections/custom-instructions"
|
||||
|
|
@ -18,46 +18,63 @@ jest.mock("../sections/modes", () => ({
|
|||
getModesSection: jest.fn().mockImplementation(async () => `====\n\nMODES\n\n- Test modes section`),
|
||||
}))
|
||||
|
||||
jest.mock("../sections/custom-instructions", () => ({
|
||||
addCustomInstructions: jest
|
||||
.fn()
|
||||
.mockImplementation(async (modeCustomInstructions, globalCustomInstructions, cwd, mode, options) => {
|
||||
const sections = []
|
||||
// Mock the custom instructions
|
||||
jest.mock("../sections/custom-instructions", () => {
|
||||
const addCustomInstructions = jest.fn()
|
||||
return {
|
||||
addCustomInstructions,
|
||||
__setMockImplementation: (impl: any) => {
|
||||
addCustomInstructions.mockImplementation(impl)
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
// Add language preference if provided
|
||||
if (options?.preferredLanguage) {
|
||||
sections.push(
|
||||
`Language Preference:\nYou should always speak and think in the ${options.preferredLanguage} language.`,
|
||||
)
|
||||
}
|
||||
// Set up default mock implementation
|
||||
const { __setMockImplementation } = jest.requireMock("../sections/custom-instructions")
|
||||
__setMockImplementation(
|
||||
async (
|
||||
modeCustomInstructions: string,
|
||||
globalCustomInstructions: string,
|
||||
cwd: string,
|
||||
mode: string,
|
||||
options?: { vscodeLanguage?: string },
|
||||
) => {
|
||||
const sections = []
|
||||
|
||||
// Add global instructions first
|
||||
if (globalCustomInstructions?.trim()) {
|
||||
sections.push(`Global Instructions:\n${globalCustomInstructions.trim()}`)
|
||||
}
|
||||
// Add language preference if provided
|
||||
if (options?.vscodeLanguage) {
|
||||
sections.push(
|
||||
`Language Preference:\nYou should always speak and think in the "${options.vscodeLanguage}" language.`,
|
||||
)
|
||||
}
|
||||
|
||||
// Add mode-specific instructions after
|
||||
if (modeCustomInstructions?.trim()) {
|
||||
sections.push(`Mode-specific Instructions:\n${modeCustomInstructions}`)
|
||||
}
|
||||
// Add global instructions first
|
||||
if (globalCustomInstructions?.trim()) {
|
||||
sections.push(`Global Instructions:\n${globalCustomInstructions.trim()}`)
|
||||
}
|
||||
|
||||
// Add rules
|
||||
const rules = []
|
||||
if (mode) {
|
||||
rules.push(`# Rules from .clinerules-${mode}:\nMock mode-specific rules`)
|
||||
}
|
||||
rules.push(`# Rules from .clinerules:\nMock generic rules`)
|
||||
// Add mode-specific instructions after
|
||||
if (modeCustomInstructions?.trim()) {
|
||||
sections.push(`Mode-specific Instructions:\n${modeCustomInstructions}`)
|
||||
}
|
||||
|
||||
if (rules.length > 0) {
|
||||
sections.push(`Rules:\n${rules.join("\n")}`)
|
||||
}
|
||||
// Add rules
|
||||
const rules = []
|
||||
if (mode) {
|
||||
rules.push(`# Rules from .clinerules-${mode}:\nMock mode-specific rules`)
|
||||
}
|
||||
rules.push(`# Rules from .clinerules:\nMock generic rules`)
|
||||
|
||||
const joinedSections = sections.join("\n\n")
|
||||
return joinedSections
|
||||
? `\n====\n\nUSER'S CUSTOM INSTRUCTIONS\n\nThe following additional instructions are provided by the user, and should be followed to the best of your ability without interfering with the TOOL USE guidelines.\n\n${joinedSections}`
|
||||
: ""
|
||||
}),
|
||||
}))
|
||||
if (rules.length > 0) {
|
||||
sections.push(`Rules:\n${rules.join("\n")}`)
|
||||
}
|
||||
|
||||
const joinedSections = sections.join("\n\n")
|
||||
return joinedSections
|
||||
? `\n====\n\nUSER'S CUSTOM INSTRUCTIONS\n\nThe following additional instructions are provided by the user, and should be followed to the best of your ability without interfering with the TOOL USE guidelines.\n\n${joinedSections}`
|
||||
: ""
|
||||
},
|
||||
)
|
||||
|
||||
// Mock environment-specific values for consistent tests
|
||||
jest.mock("os", () => ({
|
||||
|
|
@ -69,6 +86,13 @@ jest.mock("default-shell", () => "/bin/zsh")
|
|||
|
||||
jest.mock("os-name", () => () => "Linux")
|
||||
|
||||
// Mock vscode language
|
||||
jest.mock("vscode", () => ({
|
||||
env: {
|
||||
language: "en",
|
||||
},
|
||||
}))
|
||||
|
||||
jest.mock("../../../utils/shell", () => ({
|
||||
getShell: () => "/bin/zsh",
|
||||
}))
|
||||
|
|
@ -126,7 +150,7 @@ const createMockMcpHub = (): McpHub =>
|
|||
|
||||
describe("SYSTEM_PROMPT", () => {
|
||||
let mockMcpHub: McpHub
|
||||
let experiments: Record<string, boolean>
|
||||
let experiments: Record<string, boolean> | undefined
|
||||
|
||||
beforeAll(() => {
|
||||
// Ensure fs mock is properly initialized
|
||||
|
|
@ -146,6 +170,10 @@ describe("SYSTEM_PROMPT", () => {
|
|||
"/mock/mcp/path",
|
||||
]
|
||||
dirs.forEach((dir) => mockFs._mockDirectories.add(dir))
|
||||
})
|
||||
|
||||
beforeEach(() => {
|
||||
// Reset experiments before each test to ensure they're disabled by default
|
||||
experiments = {
|
||||
[EXPERIMENT_IDS.SEARCH_AND_REPLACE]: false,
|
||||
[EXPERIMENT_IDS.INSERT_BLOCK]: false,
|
||||
|
|
@ -175,7 +203,6 @@ describe("SYSTEM_PROMPT", () => {
|
|||
undefined, // customModePrompts
|
||||
undefined, // customModes
|
||||
undefined, // globalCustomInstructions
|
||||
undefined, // preferredLanguage
|
||||
undefined, // diffEnabled
|
||||
experiments,
|
||||
true, // enableMcpServerCreation
|
||||
|
|
@ -196,7 +223,6 @@ describe("SYSTEM_PROMPT", () => {
|
|||
undefined, // customModePrompts
|
||||
undefined, // customModes,
|
||||
undefined, // globalCustomInstructions
|
||||
undefined, // preferredLanguage
|
||||
undefined, // diffEnabled
|
||||
experiments,
|
||||
true, // enableMcpServerCreation
|
||||
|
|
@ -219,7 +245,6 @@ describe("SYSTEM_PROMPT", () => {
|
|||
undefined, // customModePrompts
|
||||
undefined, // customModes,
|
||||
undefined, // globalCustomInstructions
|
||||
undefined, // preferredLanguage
|
||||
undefined, // diffEnabled
|
||||
experiments,
|
||||
true, // enableMcpServerCreation
|
||||
|
|
@ -240,7 +265,6 @@ describe("SYSTEM_PROMPT", () => {
|
|||
undefined, // customModePrompts
|
||||
undefined, // customModes,
|
||||
undefined, // globalCustomInstructions
|
||||
undefined, // preferredLanguage
|
||||
undefined, // diffEnabled
|
||||
experiments,
|
||||
true, // enableMcpServerCreation
|
||||
|
|
@ -261,7 +285,6 @@ describe("SYSTEM_PROMPT", () => {
|
|||
undefined, // customModePrompts
|
||||
undefined, // customModes,
|
||||
undefined, // globalCustomInstructions
|
||||
undefined, // preferredLanguage
|
||||
undefined, // diffEnabled
|
||||
experiments,
|
||||
true, // enableMcpServerCreation
|
||||
|
|
@ -282,7 +305,6 @@ describe("SYSTEM_PROMPT", () => {
|
|||
undefined, // customModePrompts
|
||||
undefined, // customModes
|
||||
undefined, // globalCustomInstructions
|
||||
undefined, // preferredLanguage
|
||||
true, // diffEnabled
|
||||
experiments,
|
||||
true, // enableMcpServerCreation
|
||||
|
|
@ -304,7 +326,6 @@ describe("SYSTEM_PROMPT", () => {
|
|||
undefined, // customModePrompts
|
||||
undefined, // customModes
|
||||
undefined, // globalCustomInstructions
|
||||
undefined, // preferredLanguage
|
||||
false, // diffEnabled
|
||||
experiments,
|
||||
true, // enableMcpServerCreation
|
||||
|
|
@ -326,7 +347,6 @@ describe("SYSTEM_PROMPT", () => {
|
|||
undefined, // customModePrompts
|
||||
undefined, // customModes
|
||||
undefined, // globalCustomInstructions
|
||||
undefined, // preferredLanguage
|
||||
undefined, // diffEnabled
|
||||
experiments,
|
||||
true, // enableMcpServerCreation
|
||||
|
|
@ -336,7 +356,11 @@ describe("SYSTEM_PROMPT", () => {
|
|||
expect(prompt).toMatchSnapshot()
|
||||
})
|
||||
|
||||
it("should include preferred language in custom instructions", async () => {
|
||||
it("should include vscode language in custom instructions", async () => {
|
||||
// Mock vscode.env.language
|
||||
const vscode = jest.requireMock("vscode")
|
||||
vscode.env = { language: "es" }
|
||||
|
||||
const prompt = await SYSTEM_PROMPT(
|
||||
mockContext,
|
||||
"/test/path",
|
||||
|
|
@ -348,14 +372,16 @@ describe("SYSTEM_PROMPT", () => {
|
|||
undefined, // customModePrompts
|
||||
undefined, // customModes
|
||||
undefined, // globalCustomInstructions
|
||||
"Spanish", // preferredLanguage
|
||||
undefined, // diffEnabled
|
||||
experiments,
|
||||
undefined, // experiments
|
||||
true, // enableMcpServerCreation
|
||||
)
|
||||
|
||||
expect(prompt).toContain("Language Preference:")
|
||||
expect(prompt).toContain("You should always speak and think in the Spanish language")
|
||||
expect(prompt).toContain('You should always speak and think in the "es" language')
|
||||
|
||||
// Reset mock
|
||||
vscode.env = { language: "en" }
|
||||
})
|
||||
|
||||
it("should include custom mode role definition at top and instructions at bottom", async () => {
|
||||
|
|
@ -381,7 +407,6 @@ describe("SYSTEM_PROMPT", () => {
|
|||
undefined, // customModePrompts
|
||||
customModes, // customModes
|
||||
"Global instructions", // globalCustomInstructions
|
||||
undefined, // preferredLanguage
|
||||
undefined, // diffEnabled
|
||||
experiments,
|
||||
true, // enableMcpServerCreation
|
||||
|
|
@ -409,18 +434,17 @@ describe("SYSTEM_PROMPT", () => {
|
|||
const prompt = await SYSTEM_PROMPT(
|
||||
mockContext,
|
||||
"/test/path",
|
||||
false,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
defaultModeSlug,
|
||||
customModePrompts,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
experiments,
|
||||
true, // enableMcpServerCreation
|
||||
false, // supportsComputerUse
|
||||
undefined, // mcpHub
|
||||
undefined, // diffStrategy
|
||||
undefined, // browserViewportSize
|
||||
defaultModeSlug as Mode, // mode
|
||||
customModePrompts, // customModePrompts
|
||||
undefined, // customModes
|
||||
undefined, // globalCustomInstructions
|
||||
undefined, // diffEnabled
|
||||
undefined, // experiments
|
||||
false, // enableMcpServerCreation
|
||||
)
|
||||
|
||||
// Role definition from promptComponent should be at the top
|
||||
|
|
@ -440,18 +464,17 @@ describe("SYSTEM_PROMPT", () => {
|
|||
const prompt = await SYSTEM_PROMPT(
|
||||
mockContext,
|
||||
"/test/path",
|
||||
false,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
defaultModeSlug,
|
||||
customModePrompts,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
experiments,
|
||||
true, // enableMcpServerCreation
|
||||
false, // supportsComputerUse
|
||||
undefined, // mcpHub
|
||||
undefined, // diffStrategy
|
||||
undefined, // browserViewportSize
|
||||
defaultModeSlug as Mode, // mode
|
||||
customModePrompts, // customModePrompts
|
||||
undefined, // customModes
|
||||
undefined, // globalCustomInstructions
|
||||
undefined, // diffEnabled
|
||||
undefined, // experiments
|
||||
false, // enableMcpServerCreation
|
||||
)
|
||||
|
||||
// Should use the default mode's role definition
|
||||
|
|
@ -460,6 +483,15 @@ describe("SYSTEM_PROMPT", () => {
|
|||
|
||||
describe("experimental tools", () => {
|
||||
it("should disable experimental tools by default", async () => {
|
||||
// Set experiments to explicitly disable experimental tools
|
||||
const experimentsConfig = {
|
||||
[EXPERIMENT_IDS.SEARCH_AND_REPLACE]: false,
|
||||
[EXPERIMENT_IDS.INSERT_BLOCK]: false,
|
||||
}
|
||||
|
||||
// Reset experiments
|
||||
experiments = experimentsConfig
|
||||
|
||||
const prompt = await SYSTEM_PROMPT(
|
||||
mockContext,
|
||||
"/test/path",
|
||||
|
|
@ -471,23 +503,29 @@ describe("SYSTEM_PROMPT", () => {
|
|||
undefined, // customModePrompts
|
||||
undefined, // customModes
|
||||
undefined, // globalCustomInstructions
|
||||
undefined, // preferredLanguage
|
||||
undefined, // diffEnabled
|
||||
experiments, // experiments - undefined should disable all experimental tools
|
||||
experimentsConfig, // Explicitly disable experimental tools
|
||||
true, // enableMcpServerCreation
|
||||
)
|
||||
|
||||
// Verify experimental tools are not included in the prompt
|
||||
expect(prompt).not.toContain(EXPERIMENT_IDS.SEARCH_AND_REPLACE)
|
||||
expect(prompt).not.toContain(EXPERIMENT_IDS.INSERT_BLOCK)
|
||||
// Check that experimental tool sections are not included
|
||||
const toolSections = prompt.split("\n## ").slice(1)
|
||||
const toolNames = toolSections.map((section) => section.split("\n")[0].trim())
|
||||
expect(toolNames).not.toContain("search_and_replace")
|
||||
expect(toolNames).not.toContain("insert_content")
|
||||
expect(prompt).toMatchSnapshot()
|
||||
})
|
||||
|
||||
it("should enable experimental tools when explicitly enabled", async () => {
|
||||
const experiments = {
|
||||
// Set experiments for testing experimental features
|
||||
const experimentsEnabled = {
|
||||
[EXPERIMENT_IDS.SEARCH_AND_REPLACE]: true,
|
||||
[EXPERIMENT_IDS.INSERT_BLOCK]: true,
|
||||
}
|
||||
|
||||
// Reset default experiments
|
||||
experiments = undefined
|
||||
|
||||
const prompt = await SYSTEM_PROMPT(
|
||||
mockContext,
|
||||
"/test/path",
|
||||
|
|
@ -499,23 +537,31 @@ describe("SYSTEM_PROMPT", () => {
|
|||
undefined, // customModePrompts
|
||||
undefined, // customModes
|
||||
undefined, // globalCustomInstructions
|
||||
undefined, // preferredLanguage
|
||||
undefined, // diffEnabled
|
||||
experiments,
|
||||
experimentsEnabled, // Use the enabled experiments
|
||||
true, // enableMcpServerCreation
|
||||
)
|
||||
|
||||
// Get all tool sections
|
||||
const toolSections = prompt.split("## ").slice(1) // Split by section headers and remove first non-tool part
|
||||
const toolNames = toolSections.map((section) => section.split("\n")[0].trim())
|
||||
|
||||
// Verify experimental tools are included in the prompt when enabled
|
||||
expect(prompt).toContain(EXPERIMENT_IDS.SEARCH_AND_REPLACE)
|
||||
expect(prompt).toContain(EXPERIMENT_IDS.INSERT_BLOCK)
|
||||
expect(toolNames).toContain("search_and_replace")
|
||||
expect(toolNames).toContain("insert_content")
|
||||
expect(prompt).toMatchSnapshot()
|
||||
})
|
||||
|
||||
it("should selectively enable experimental tools", async () => {
|
||||
const experiments = {
|
||||
// Set experiments for testing selective enabling
|
||||
const experimentsSelective = {
|
||||
[EXPERIMENT_IDS.SEARCH_AND_REPLACE]: true,
|
||||
[EXPERIMENT_IDS.INSERT_BLOCK]: false,
|
||||
}
|
||||
|
||||
// Reset default experiments
|
||||
experiments = undefined
|
||||
|
||||
const prompt = await SYSTEM_PROMPT(
|
||||
mockContext,
|
||||
"/test/path",
|
||||
|
|
@ -527,15 +573,19 @@ describe("SYSTEM_PROMPT", () => {
|
|||
undefined, // customModePrompts
|
||||
undefined, // customModes
|
||||
undefined, // globalCustomInstructions
|
||||
undefined, // preferredLanguage
|
||||
undefined, // diffEnabled
|
||||
experiments,
|
||||
experimentsSelective, // Use the selective experiments
|
||||
true, // enableMcpServerCreation
|
||||
)
|
||||
|
||||
// Get all tool sections
|
||||
const toolSections = prompt.split("## ").slice(1) // Split by section headers and remove first non-tool part
|
||||
const toolNames = toolSections.map((section) => section.split("\n")[0].trim())
|
||||
|
||||
// Verify only enabled experimental tools are included
|
||||
expect(prompt).toContain(EXPERIMENT_IDS.SEARCH_AND_REPLACE)
|
||||
expect(prompt).not.toContain(EXPERIMENT_IDS.INSERT_BLOCK)
|
||||
expect(toolNames).toContain("search_and_replace")
|
||||
expect(toolNames).not.toContain("insert_content")
|
||||
expect(prompt).toMatchSnapshot()
|
||||
})
|
||||
|
||||
it("should list all available editing tools in base instruction", async () => {
|
||||
|
|
@ -555,9 +605,8 @@ describe("SYSTEM_PROMPT", () => {
|
|||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
true, // diffEnabled
|
||||
experiments,
|
||||
experiments, // experiments
|
||||
true, // enableMcpServerCreation
|
||||
)
|
||||
|
||||
|
|
@ -567,7 +616,6 @@ describe("SYSTEM_PROMPT", () => {
|
|||
expect(prompt).toContain("insert_content (for adding lines to existing files)")
|
||||
expect(prompt).toContain("search_and_replace (for finding and replacing individual pieces of text)")
|
||||
})
|
||||
|
||||
it("should provide detailed instructions for each enabled tool", async () => {
|
||||
const experiments = {
|
||||
[EXPERIMENT_IDS.SEARCH_AND_REPLACE]: true,
|
||||
|
|
@ -585,8 +633,7 @@ describe("SYSTEM_PROMPT", () => {
|
|||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
true,
|
||||
true, // diffEnabled
|
||||
experiments,
|
||||
true, // enableMcpServerCreation
|
||||
)
|
||||
|
|
@ -606,7 +653,7 @@ describe("SYSTEM_PROMPT", () => {
|
|||
})
|
||||
|
||||
describe("addCustomInstructions", () => {
|
||||
let experiments: Record<string, boolean>
|
||||
let experiments: Record<string, boolean> | undefined
|
||||
beforeAll(() => {
|
||||
// Ensure fs mock is properly initialized
|
||||
const mockFs = jest.requireMock("fs/promises")
|
||||
|
|
@ -619,10 +666,8 @@ describe("addCustomInstructions", () => {
|
|||
throw new Error(`ENOENT: no such file or directory, mkdir '${path}'`)
|
||||
})
|
||||
|
||||
experiments = {
|
||||
[EXPERIMENT_IDS.SEARCH_AND_REPLACE]: false,
|
||||
[EXPERIMENT_IDS.INSERT_BLOCK]: false,
|
||||
}
|
||||
// Initialize experiments as undefined by default
|
||||
experiments = undefined
|
||||
})
|
||||
|
||||
beforeEach(() => {
|
||||
|
|
@ -640,10 +685,9 @@ describe("addCustomInstructions", () => {
|
|||
"architect", // mode
|
||||
undefined, // customModePrompts
|
||||
undefined, // customModes
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
experiments,
|
||||
undefined, // globalCustomInstructions
|
||||
undefined, // diffEnabled
|
||||
undefined, // experiments
|
||||
true, // enableMcpServerCreation
|
||||
)
|
||||
|
||||
|
|
@ -661,10 +705,9 @@ describe("addCustomInstructions", () => {
|
|||
"ask", // mode
|
||||
undefined, // customModePrompts
|
||||
undefined, // customModes
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
experiments,
|
||||
undefined, // globalCustomInstructions
|
||||
undefined, // diffEnabled
|
||||
undefined, // experiments
|
||||
true, // enableMcpServerCreation
|
||||
)
|
||||
|
||||
|
|
@ -685,9 +728,8 @@ describe("addCustomInstructions", () => {
|
|||
undefined, // customModePrompts
|
||||
undefined, // customModes,
|
||||
undefined, // globalCustomInstructions
|
||||
undefined, // preferredLanguage
|
||||
undefined, // diffEnabled
|
||||
experiments,
|
||||
undefined, // experiments
|
||||
true, // enableMcpServerCreation
|
||||
)
|
||||
|
||||
|
|
@ -709,9 +751,8 @@ describe("addCustomInstructions", () => {
|
|||
undefined, // customModePrompts
|
||||
undefined, // customModes,
|
||||
undefined, // globalCustomInstructions
|
||||
undefined, // preferredLanguage
|
||||
undefined, // diffEnabled
|
||||
experiments,
|
||||
undefined, // experiments
|
||||
false, // enableMcpServerCreation
|
||||
)
|
||||
|
||||
|
|
@ -751,7 +792,7 @@ describe("addCustomInstructions", () => {
|
|||
|
||||
it("should include preferred language when provided", async () => {
|
||||
const instructions = await addCustomInstructions("", "", "/test/path", defaultModeSlug, {
|
||||
preferredLanguage: "Spanish",
|
||||
vscodeLanguage: "es",
|
||||
})
|
||||
expect(instructions).toMatchSnapshot()
|
||||
})
|
||||
|
|
@ -767,7 +808,7 @@ describe("addCustomInstructions", () => {
|
|||
"",
|
||||
"/test/path",
|
||||
defaultModeSlug,
|
||||
{ preferredLanguage: "French" },
|
||||
{ vscodeLanguage: "fr" },
|
||||
)
|
||||
expect(instructions).toMatchSnapshot()
|
||||
})
|
||||
|
|
|
|||
|
|
@ -113,11 +113,11 @@ describe("addCustomInstructions", () => {
|
|||
"global instructions",
|
||||
"/fake/path",
|
||||
"test-mode",
|
||||
{ preferredLanguage: "Spanish" },
|
||||
{ vscodeLanguage: "es" },
|
||||
)
|
||||
|
||||
expect(result).toContain("Language Preference:")
|
||||
expect(result).toContain("Spanish")
|
||||
expect(result).toContain("es")
|
||||
expect(result).toContain("Global Instructions:\nglobal instructions")
|
||||
expect(result).toContain("Mode-specific Instructions:\nmode instructions")
|
||||
expect(result).toContain("Rules from .clinerules-test-mode:\nmode specific rules")
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import fs from "fs/promises"
|
||||
import path from "path"
|
||||
import * as vscode from "vscode"
|
||||
|
||||
async function safeReadFile(filePath: string): Promise<string> {
|
||||
try {
|
||||
|
|
@ -33,7 +34,7 @@ export async function addCustomInstructions(
|
|||
globalCustomInstructions: string,
|
||||
cwd: string,
|
||||
mode: string,
|
||||
options: { preferredLanguage?: string; rooIgnoreInstructions?: string } = {},
|
||||
options: { vscodeLanguage?: string; rooIgnoreInstructions?: string } = {},
|
||||
): Promise<string> {
|
||||
const sections = []
|
||||
|
||||
|
|
@ -45,9 +46,9 @@ export async function addCustomInstructions(
|
|||
}
|
||||
|
||||
// Add language preference if provided
|
||||
if (options.preferredLanguage) {
|
||||
if (options.vscodeLanguage) {
|
||||
sections.push(
|
||||
`Language Preference:\nYou should always speak and think in the ${options.preferredLanguage} language.`,
|
||||
`Language Preference:\nYou should always speak and think in the "${options.vscodeLanguage}" language.`,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ function getEditingInstructions(diffStrategy?: DiffStrategy, experiments?: Recor
|
|||
} else {
|
||||
availableTools.push("write_to_file (for creating new files or complete file rewrites)")
|
||||
}
|
||||
|
||||
if (experiments?.["insert_content"]) {
|
||||
availableTools.push("insert_content (for adding lines to existing files)")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,9 +37,8 @@ async function generatePrompt(
|
|||
promptComponent?: PromptComponent,
|
||||
customModeConfigs?: ModeConfig[],
|
||||
globalCustomInstructions?: string,
|
||||
preferredLanguage?: string,
|
||||
diffEnabled?: boolean,
|
||||
experiments?: Record<string, boolean>,
|
||||
experiments?: Record<string, boolean> | boolean | undefined,
|
||||
enableMcpServerCreation?: boolean,
|
||||
rooIgnoreInstructions?: string,
|
||||
): Promise<string> {
|
||||
|
|
@ -61,6 +60,12 @@ async function generatePrompt(
|
|||
: Promise.resolve(""),
|
||||
])
|
||||
|
||||
// Convert experiments to an object if it's a boolean
|
||||
const experimentSettings =
|
||||
typeof experiments === "boolean"
|
||||
? {} // Empty object if experiments is just a boolean
|
||||
: (experiments ?? {})
|
||||
|
||||
const basePrompt = `${roleDefinition}
|
||||
|
||||
${getSharedToolUseSection()}
|
||||
|
|
@ -73,7 +78,7 @@ ${getToolDescriptionsForMode(
|
|||
browserViewportSize,
|
||||
mcpHub,
|
||||
customModeConfigs,
|
||||
experiments,
|
||||
experimentSettings,
|
||||
)}
|
||||
|
||||
${getToolUseGuidelinesSection()}
|
||||
|
|
@ -84,13 +89,13 @@ ${getCapabilitiesSection(cwd, supportsComputerUse, mcpHub, effectiveDiffStrategy
|
|||
|
||||
${modesSection}
|
||||
|
||||
${getRulesSection(cwd, supportsComputerUse, effectiveDiffStrategy, experiments)}
|
||||
${getRulesSection(cwd, supportsComputerUse, effectiveDiffStrategy, experimentSettings)}
|
||||
|
||||
${getSystemInfoSection(cwd, mode, customModeConfigs)}
|
||||
|
||||
${getObjectiveSection()}
|
||||
|
||||
${await addCustomInstructions(promptComponent?.customInstructions || modeConfig.customInstructions || "", globalCustomInstructions || "", cwd, mode, { preferredLanguage, rooIgnoreInstructions })}`
|
||||
${await addCustomInstructions(promptComponent?.customInstructions || modeConfig.customInstructions || "", globalCustomInstructions || "", cwd, mode, { vscodeLanguage: vscode.env.language, rooIgnoreInstructions })}`
|
||||
|
||||
return basePrompt
|
||||
}
|
||||
|
|
@ -106,9 +111,8 @@ export const SYSTEM_PROMPT = async (
|
|||
customModePrompts?: CustomModePrompts,
|
||||
customModes?: ModeConfig[],
|
||||
globalCustomInstructions?: string,
|
||||
preferredLanguage?: string,
|
||||
diffEnabled?: boolean,
|
||||
experiments?: Record<string, boolean>,
|
||||
experiments?: Record<string, boolean> | boolean | undefined,
|
||||
enableMcpServerCreation?: boolean,
|
||||
rooIgnoreInstructions?: string,
|
||||
): Promise<string> => {
|
||||
|
|
@ -135,15 +139,28 @@ export const SYSTEM_PROMPT = async (
|
|||
// If a file-based custom system prompt exists, use it
|
||||
if (fileCustomSystemPrompt) {
|
||||
const roleDefinition = promptComponent?.roleDefinition || currentMode.roleDefinition
|
||||
const customInstructions = await addCustomInstructions(
|
||||
promptComponent?.customInstructions || currentMode.customInstructions || "",
|
||||
globalCustomInstructions || "",
|
||||
cwd,
|
||||
mode,
|
||||
{ vscodeLanguage: vscode.env.language, rooIgnoreInstructions },
|
||||
)
|
||||
// For file-based prompts, don't include the tool sections
|
||||
return `${roleDefinition}
|
||||
|
||||
${fileCustomSystemPrompt}
|
||||
|
||||
${await addCustomInstructions(promptComponent?.customInstructions || currentMode.customInstructions || "", globalCustomInstructions || "", cwd, mode, { preferredLanguage, rooIgnoreInstructions })}`
|
||||
${customInstructions}`
|
||||
}
|
||||
|
||||
// If diff is disabled, don't pass the diffStrategy
|
||||
const effectiveDiffStrategy = diffEnabled ? diffStrategy : undefined
|
||||
// Convert experiments to an object if it's a boolean
|
||||
const experimentSettings =
|
||||
typeof experiments === "boolean"
|
||||
? {} // Empty object if experiments is just a boolean
|
||||
: (experiments ?? {})
|
||||
|
||||
return generatePrompt(
|
||||
context,
|
||||
|
|
@ -156,9 +173,8 @@ ${await addCustomInstructions(promptComponent?.customInstructions || currentMode
|
|||
promptComponent,
|
||||
customModes,
|
||||
globalCustomInstructions,
|
||||
preferredLanguage,
|
||||
diffEnabled,
|
||||
experiments,
|
||||
experimentSettings,
|
||||
enableMcpServerCreation,
|
||||
rooIgnoreInstructions,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -61,13 +61,15 @@ export function getToolDescriptionsForMode(
|
|||
|
||||
const tools = new Set<string>()
|
||||
|
||||
const experimentSettings = experiments ?? {}
|
||||
|
||||
// Add tools from mode's groups
|
||||
config.groups.forEach((groupEntry) => {
|
||||
const groupName = getGroupName(groupEntry)
|
||||
const toolGroup = TOOL_GROUPS[groupName]
|
||||
if (toolGroup) {
|
||||
toolGroup.tools.forEach((tool) => {
|
||||
if (isToolAllowedForMode(tool as ToolName, mode, customModes ?? [], experiments ?? {})) {
|
||||
if (isToolAllowedForMode(tool as ToolName, mode, customModes ?? [], experimentSettings)) {
|
||||
tools.add(tool)
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1389,10 +1389,6 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
|||
await this.updateGlobalState("rateLimitSeconds", message.value ?? 0)
|
||||
await this.postStateToWebview()
|
||||
break
|
||||
case "preferredLanguage":
|
||||
await this.updateGlobalState("preferredLanguage", message.text)
|
||||
await this.postStateToWebview()
|
||||
break
|
||||
case "writeDelayMs":
|
||||
await this.updateGlobalState("writeDelayMs", message.value)
|
||||
await this.postStateToWebview()
|
||||
|
|
@ -1930,7 +1926,6 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
|||
apiConfiguration,
|
||||
customModePrompts,
|
||||
customInstructions,
|
||||
preferredLanguage,
|
||||
browserViewportSize,
|
||||
diffEnabled,
|
||||
mcpEnabled,
|
||||
|
|
@ -1968,7 +1963,6 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
|||
customModePrompts,
|
||||
customModes,
|
||||
customInstructions,
|
||||
preferredLanguage,
|
||||
diffEnabled,
|
||||
experiments,
|
||||
enableMcpServerCreation,
|
||||
|
|
@ -2344,7 +2338,6 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
|||
screenshotQuality,
|
||||
remoteBrowserHost,
|
||||
remoteBrowserEnabled,
|
||||
preferredLanguage,
|
||||
writeDelayMs,
|
||||
terminalOutputLineLimit,
|
||||
fuzzyMatchThreshold,
|
||||
|
|
@ -2404,7 +2397,6 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
|||
screenshotQuality: screenshotQuality ?? 75,
|
||||
remoteBrowserHost,
|
||||
remoteBrowserEnabled: remoteBrowserEnabled ?? false,
|
||||
preferredLanguage: preferredLanguage ?? "English",
|
||||
writeDelayMs: writeDelayMs ?? 1000,
|
||||
terminalOutputLineLimit: terminalOutputLineLimit ?? 500,
|
||||
fuzzyMatchThreshold: fuzzyMatchThreshold ?? 1.0,
|
||||
|
|
@ -2563,37 +2555,8 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
|||
writeDelayMs: stateValues.writeDelayMs ?? 1000,
|
||||
terminalOutputLineLimit: stateValues.terminalOutputLineLimit ?? 500,
|
||||
mode: stateValues.mode ?? defaultModeSlug,
|
||||
preferredLanguage:
|
||||
stateValues.preferredLanguage ??
|
||||
(() => {
|
||||
// Get VSCode's locale setting
|
||||
const vscodeLang = vscode.env.language
|
||||
// Map VSCode locale to our supported languages
|
||||
const langMap: { [key: string]: string } = {
|
||||
en: "English",
|
||||
ar: "Arabic",
|
||||
"pt-br": "Brazilian Portuguese",
|
||||
ca: "Catalan",
|
||||
cs: "Czech",
|
||||
fr: "French",
|
||||
de: "German",
|
||||
hi: "Hindi",
|
||||
hu: "Hungarian",
|
||||
it: "Italian",
|
||||
ja: "Japanese",
|
||||
ko: "Korean",
|
||||
pl: "Polish",
|
||||
pt: "Portuguese",
|
||||
ru: "Russian",
|
||||
zh: "Simplified Chinese",
|
||||
"zh-cn": "Simplified Chinese",
|
||||
es: "Spanish",
|
||||
"zh-tw": "Traditional Chinese",
|
||||
tr: "Turkish",
|
||||
}
|
||||
// Return mapped language or default to English
|
||||
return langMap[vscodeLang] ?? langMap[vscodeLang.split("-")[0]] ?? "English"
|
||||
})(),
|
||||
// Pass the VSCode language code directly
|
||||
vscodeLanguage: vscode.env.language,
|
||||
mcpEnabled: stateValues.mcpEnabled ?? true,
|
||||
enableMcpServerCreation: stateValues.enableMcpServerCreation ?? true,
|
||||
alwaysApproveResubmit: stateValues.alwaysApproveResubmit ?? false,
|
||||
|
|
|
|||
|
|
@ -420,7 +420,6 @@ describe("ClineProvider", () => {
|
|||
|
||||
const mockState: ExtensionState = {
|
||||
version: "1.0.0",
|
||||
preferredLanguage: "English",
|
||||
clineMessages: [],
|
||||
taskHistory: [],
|
||||
shouldShowAnnouncement: false,
|
||||
|
|
@ -535,20 +534,12 @@ describe("ClineProvider", () => {
|
|||
expect(state).toHaveProperty("writeDelayMs")
|
||||
})
|
||||
|
||||
test("preferredLanguage defaults to VSCode language when not set", async () => {
|
||||
test("vscodeLanguage is set to VSCode language", async () => {
|
||||
// Mock VSCode language as Spanish
|
||||
;(vscode.env as any).language = "es-ES"
|
||||
|
||||
const state = await provider.getState()
|
||||
expect(state.preferredLanguage).toBe("Spanish")
|
||||
})
|
||||
|
||||
test("preferredLanguage defaults to English for unsupported VSCode language", async () => {
|
||||
// Mock VSCode language as an unsupported language
|
||||
;(vscode.env as any).language = "unsupported-LANG"
|
||||
|
||||
const state = await provider.getState()
|
||||
expect(state.preferredLanguage).toBe("English")
|
||||
expect(state.vscodeLanguage).toBe("es-ES")
|
||||
})
|
||||
|
||||
test("diffEnabled defaults to true when not set", async () => {
|
||||
|
|
@ -1216,7 +1207,7 @@ describe("ClineProvider", () => {
|
|||
expect(callArgs[4]).toHaveProperty("getToolDescription") // diffStrategy
|
||||
expect(callArgs[5]).toBe("900x600") // browserViewportSize
|
||||
expect(callArgs[6]).toBe("code") // mode
|
||||
expect(callArgs[11]).toBe(true) // diffEnabled
|
||||
expect(callArgs[10]).toBe(true) // diffEnabled
|
||||
|
||||
// Run the test again to verify it's consistent
|
||||
await handler({ type: "getSystemPrompt", mode: "code" })
|
||||
|
|
@ -1274,7 +1265,7 @@ describe("ClineProvider", () => {
|
|||
expect(callArgs[4]).toHaveProperty("getToolDescription") // diffStrategy
|
||||
expect(callArgs[5]).toBe("900x600") // browserViewportSize
|
||||
expect(callArgs[6]).toBe("code") // mode
|
||||
expect(callArgs[11]).toBe(false) // diffEnabled should be false
|
||||
expect(callArgs[10]).toBe(false) // diffEnabled should be false
|
||||
})
|
||||
|
||||
test("uses correct mode-specific instructions when mode is specified", async () => {
|
||||
|
|
|
|||
1
src/exports/roo-code.d.ts
vendored
1
src/exports/roo-code.d.ts
vendored
|
|
@ -164,7 +164,6 @@ export type GlobalStateKey =
|
|||
| "screenshotQuality"
|
||||
| "remoteBrowserHost"
|
||||
| "fuzzyMatchThreshold"
|
||||
| "preferredLanguage" // Language setting for Cline's communication
|
||||
| "writeDelayMs"
|
||||
| "terminalOutputLineLimit"
|
||||
| "mcpEnabled"
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ export interface ExtensionState {
|
|||
remoteBrowserHost?: string
|
||||
remoteBrowserEnabled?: boolean
|
||||
fuzzyMatchThreshold?: number
|
||||
preferredLanguage: string
|
||||
vscodeLanguage?: string
|
||||
writeDelayMs: number
|
||||
terminalOutputLineLimit?: number
|
||||
mcpEnabled: boolean
|
||||
|
|
|
|||
|
|
@ -64,7 +64,6 @@ export interface WebviewMessage {
|
|||
| "toggleMcpServer"
|
||||
| "updateMcpTimeout"
|
||||
| "fuzzyMatchThreshold"
|
||||
| "preferredLanguage"
|
||||
| "writeDelayMs"
|
||||
| "enhancePrompt"
|
||||
| "enhancedPrompt"
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ jest.mock("../../core/prompts/sections/custom-instructions", () => ({
|
|||
}))
|
||||
|
||||
import { isToolAllowedForMode, FileRestrictionError, ModeConfig, getFullModeDetails, modes } from "../modes"
|
||||
import * as vscode from "vscode"
|
||||
import { addCustomInstructions } from "../../core/prompts/sections/custom-instructions"
|
||||
|
||||
describe("isToolAllowedForMode", () => {
|
||||
|
|
@ -402,7 +401,7 @@ describe("FileRestrictionError", () => {
|
|||
const options = {
|
||||
cwd: "/test/path",
|
||||
globalCustomInstructions: "Global instructions",
|
||||
preferredLanguage: "en",
|
||||
vscodeLanguage: "en",
|
||||
}
|
||||
|
||||
await getFullModeDetails("debug", undefined, undefined, options)
|
||||
|
|
@ -412,7 +411,7 @@ describe("FileRestrictionError", () => {
|
|||
"Global instructions",
|
||||
"/test/path",
|
||||
"debug",
|
||||
{ preferredLanguage: "en" },
|
||||
{ vscodeLanguage: "en" },
|
||||
)
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -82,7 +82,6 @@ export const GLOBAL_STATE_KEYS = [
|
|||
"screenshotQuality",
|
||||
"remoteBrowserHost",
|
||||
"fuzzyMatchThreshold",
|
||||
"preferredLanguage", // Language setting for Cline's communication.
|
||||
"writeDelayMs",
|
||||
"terminalOutputLineLimit",
|
||||
"mcpEnabled",
|
||||
|
|
|
|||
|
|
@ -195,10 +195,13 @@ export function isToolAllowedForMode(
|
|||
}
|
||||
|
||||
// Check tool requirements if any exist
|
||||
if (toolRequirements && tool in toolRequirements) {
|
||||
if (!toolRequirements[tool]) {
|
||||
if (toolRequirements && typeof toolRequirements === "object") {
|
||||
if (tool in toolRequirements && !toolRequirements[tool]) {
|
||||
return false
|
||||
}
|
||||
} else if (toolRequirements === false) {
|
||||
// If toolRequirements is a boolean false, all tools are disabled
|
||||
return false
|
||||
}
|
||||
|
||||
const mode = getModeBySlug(modeSlug, customModes)
|
||||
|
|
@ -275,7 +278,7 @@ export async function getFullModeDetails(
|
|||
options?: {
|
||||
cwd?: string
|
||||
globalCustomInstructions?: string
|
||||
preferredLanguage?: string
|
||||
vscodeLanguage?: string
|
||||
},
|
||||
): Promise<ModeConfig> {
|
||||
// First get the base mode config from custom modes or built-in modes
|
||||
|
|
@ -295,7 +298,7 @@ export async function getFullModeDetails(
|
|||
options.globalCustomInstructions || "",
|
||||
options.cwd,
|
||||
modeSlug,
|
||||
{ preferredLanguage: options.preferredLanguage },
|
||||
{ vscodeLanguage: options.vscodeLanguage },
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,19 +9,6 @@ import {
|
|||
VSCodeRadioGroup,
|
||||
VSCodeRadio,
|
||||
} from "@vscode/webview-ui-toolkit/react"
|
||||
import { CaretSortIcon, CheckIcon } from "@radix-ui/react-icons"
|
||||
import {
|
||||
Button,
|
||||
Command,
|
||||
CommandGroup,
|
||||
CommandInput,
|
||||
CommandItem,
|
||||
CommandList,
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
} from "@/components/ui"
|
||||
import { cn } from "@/lib/utils"
|
||||
import { useExtensionState } from "../../context/ExtensionStateContext"
|
||||
import {
|
||||
Mode,
|
||||
|
|
@ -69,8 +56,6 @@ const PromptsView = ({ onDone }: PromptsViewProps) => {
|
|||
mode,
|
||||
customInstructions,
|
||||
setCustomInstructions,
|
||||
preferredLanguage,
|
||||
setPreferredLanguage,
|
||||
customModes,
|
||||
enableCustomModeCreation,
|
||||
setEnableCustomModeCreation,
|
||||
|
|
@ -82,9 +67,6 @@ const PromptsView = ({ onDone }: PromptsViewProps) => {
|
|||
const [testPrompt, setTestPrompt] = useState("")
|
||||
const [isEnhancing, setIsEnhancing] = useState(false)
|
||||
const [isDialogOpen, setIsDialogOpen] = useState(false)
|
||||
const [open, setOpen] = useState(false)
|
||||
const [isCustomLanguage, setIsCustomLanguage] = useState(false)
|
||||
const [customLanguage, setCustomLanguage] = useState("")
|
||||
const [selectedPromptContent, setSelectedPromptContent] = useState("")
|
||||
const [selectedPromptTitle, setSelectedPromptTitle] = useState("")
|
||||
const [isToolsEditMode, setIsToolsEditMode] = useState(false)
|
||||
|
|
@ -428,93 +410,6 @@ const PromptsView = ({ onDone }: PromptsViewProps) => {
|
|||
|
||||
<TabContent>
|
||||
<div className="pb-5 border-b border-vscode-input-border">
|
||||
<div className="mb-5">
|
||||
<div className="font-bold mb-1">Preferred Language</div>
|
||||
<Popover open={open} onOpenChange={setOpen}>
|
||||
<PopoverTrigger asChild>
|
||||
<Button
|
||||
variant="combobox"
|
||||
role="combobox"
|
||||
aria-expanded={open}
|
||||
className="w-full justify-between">
|
||||
{preferredLanguage ?? "Select language..."}
|
||||
<CaretSortIcon className="opacity-50" />
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent align="start" className="p-0">
|
||||
<Command>
|
||||
<CommandInput placeholder="Search language..." className="h-9" />
|
||||
<CommandList>
|
||||
<CommandGroup>
|
||||
{[
|
||||
{ value: "English", label: "English" },
|
||||
{ value: "Arabic", label: "Arabic - العربية" },
|
||||
{
|
||||
value: "Brazilian Portuguese",
|
||||
label: "Portuguese - Português (Brasil)",
|
||||
},
|
||||
{ value: "Catalan", label: "Catalan - Català" },
|
||||
{ value: "Czech", label: "Czech - Čeština" },
|
||||
{ value: "French", label: "French - Français" },
|
||||
{ value: "German", label: "German - Deutsch" },
|
||||
{ value: "Hindi", label: "Hindi - हिन्दी" },
|
||||
{ value: "Hungarian", label: "Hungarian - Magyar" },
|
||||
{ value: "Italian", label: "Italian - Italiano" },
|
||||
{ value: "Japanese", label: "Japanese - 日本語" },
|
||||
{ value: "Korean", label: "Korean - 한국어" },
|
||||
{ value: "Polish", label: "Polish - Polski" },
|
||||
{ value: "Portuguese", label: "Portuguese - Português (Portugal)" },
|
||||
{ value: "Russian", label: "Russian - Русский" },
|
||||
{ value: "Simplified Chinese", label: "Simplified Chinese - 简体中文" },
|
||||
{ value: "Spanish", label: "Spanish - Español" },
|
||||
{
|
||||
value: "Traditional Chinese",
|
||||
label: "Traditional Chinese - 繁體中文",
|
||||
},
|
||||
{ value: "Turkish", label: "Turkish - Türkçe" },
|
||||
].map((language) => (
|
||||
<CommandItem
|
||||
key={language.value}
|
||||
value={language.value}
|
||||
onSelect={(value) => {
|
||||
setPreferredLanguage(value)
|
||||
vscode.postMessage({
|
||||
type: "preferredLanguage",
|
||||
text: value,
|
||||
})
|
||||
setOpen(false)
|
||||
}}>
|
||||
{language.label}
|
||||
<CheckIcon
|
||||
className={cn(
|
||||
"ml-auto",
|
||||
preferredLanguage === language.value
|
||||
? "opacity-100"
|
||||
: "opacity-0",
|
||||
)}
|
||||
/>
|
||||
</CommandItem>
|
||||
))}
|
||||
</CommandGroup>
|
||||
</CommandList>
|
||||
</Command>
|
||||
<div className="border-t border-[var(--vscode-input-border)]">
|
||||
<button
|
||||
className="w-full px-2 py-1.5 text-sm text-left hover:bg-[var(--vscode-list-hoverBackground)]"
|
||||
onClick={() => {
|
||||
setIsCustomLanguage(true)
|
||||
setOpen(false)
|
||||
}}>
|
||||
+ Choose another language
|
||||
</button>
|
||||
</div>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
<p className="text-xs mt-1.5 text-vscode-descriptionForeground">
|
||||
Select the language that Roo should use for communication.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="font-bold mb-1">Custom Instructions for All Modes</div>
|
||||
<div className="text-sm text-vscode-descriptionForeground mb-2">
|
||||
These instructions apply to all modes. They provide a base set of behaviors that can be enhanced
|
||||
|
|
@ -1509,41 +1404,6 @@ const PromptsView = ({ onDone }: PromptsViewProps) => {
|
|||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{isCustomLanguage && (
|
||||
<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50">
|
||||
<div className="bg-[var(--vscode-editor-background)] p-6 rounded-lg w-96">
|
||||
<h3 className="text-lg font-semibold mb-4">Add Custom Language</h3>
|
||||
<input
|
||||
type="text"
|
||||
className="w-full p-2 mb-4 bg-[var(--vscode-input-background)] text-[var(--vscode-input-foreground)] border border-[var(--vscode-input-border)] rounded"
|
||||
placeholder="Enter language name"
|
||||
value={customLanguage}
|
||||
onChange={(e) => setCustomLanguage(e.target.value)}
|
||||
/>
|
||||
<div className="flex justify-end gap-2">
|
||||
<Button variant="secondary" onClick={() => setIsCustomLanguage(false)}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => {
|
||||
if (customLanguage.trim()) {
|
||||
setPreferredLanguage(customLanguage.trim())
|
||||
vscode.postMessage({
|
||||
type: "preferredLanguage",
|
||||
text: customLanguage.trim(),
|
||||
})
|
||||
setIsCustomLanguage(false)
|
||||
setCustomLanguage("")
|
||||
}
|
||||
}}
|
||||
disabled={!customLanguage.trim()}>
|
||||
Add
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</Tab>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,8 +39,6 @@ export interface ExtensionStateContextType extends ExtensionState {
|
|||
setEnableCheckpoints: (value: boolean) => void
|
||||
setBrowserViewportSize: (value: string) => void
|
||||
setFuzzyMatchThreshold: (value: number) => void
|
||||
preferredLanguage: string
|
||||
setPreferredLanguage: (value: string) => void
|
||||
setWriteDelayMs: (value: number) => void
|
||||
screenshotQuality?: number
|
||||
setScreenshotQuality: (value: number) => void
|
||||
|
|
@ -118,7 +116,7 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
|
|||
enableCheckpoints: true,
|
||||
checkpointStorage: "task",
|
||||
fuzzyMatchThreshold: 1.0,
|
||||
preferredLanguage: "English",
|
||||
vscodeLanguage: "en", // Default language code
|
||||
enableCustomModeCreation: true,
|
||||
writeDelayMs: 1000,
|
||||
browserViewportSize: "900x600",
|
||||
|
|
@ -260,7 +258,6 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
|
|||
setBrowserViewportSize: (value: string) =>
|
||||
setState((prevState) => ({ ...prevState, browserViewportSize: value })),
|
||||
setFuzzyMatchThreshold: (value) => setState((prevState) => ({ ...prevState, fuzzyMatchThreshold: value })),
|
||||
setPreferredLanguage: (value) => setState((prevState) => ({ ...prevState, preferredLanguage: value })),
|
||||
setWriteDelayMs: (value) => setState((prevState) => ({ ...prevState, writeDelayMs: value })),
|
||||
setScreenshotQuality: (value) => setState((prevState) => ({ ...prevState, screenshotQuality: value })),
|
||||
setTerminalOutputLineLimit: (value) =>
|
||||
|
|
|
|||
|
|
@ -109,7 +109,6 @@ describe("mergeExtensionState", () => {
|
|||
shouldShowAnnouncement: false,
|
||||
enableCheckpoints: true,
|
||||
checkpointStorage: "task",
|
||||
preferredLanguage: "English",
|
||||
writeDelayMs: 1000,
|
||||
requestDelaySeconds: 5,
|
||||
rateLimitSeconds: 0,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue