mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-09-07 08:26:51 +00:00
Merge pull request #1139 from RooVetGit/cte/cline-options
Add a ClineOptions type
This commit is contained in:
commit
91ca35ddc8
4 changed files with 124 additions and 156 deletions
|
|
@ -73,6 +73,20 @@ type UserContent = Array<
|
|||
Anthropic.TextBlockParam | Anthropic.ImageBlockParam | Anthropic.ToolUseBlockParam | Anthropic.ToolResultBlockParam
|
||||
>
|
||||
|
||||
export type ClineOptions = {
|
||||
provider: ClineProvider
|
||||
apiConfiguration: ApiConfiguration
|
||||
customInstructions?: string
|
||||
enableDiff?: boolean
|
||||
enableCheckpoints?: boolean
|
||||
fuzzyMatchThreshold?: number
|
||||
task?: string
|
||||
images?: string[]
|
||||
historyItem?: HistoryItem
|
||||
experiments?: Record<string, boolean>
|
||||
startTask?: boolean
|
||||
}
|
||||
|
||||
export class Cline {
|
||||
readonly taskId: string
|
||||
api: ApiHandler
|
||||
|
|
@ -118,19 +132,19 @@ export class Cline {
|
|||
private didAlreadyUseTool = false
|
||||
private didCompleteReadingStream = false
|
||||
|
||||
constructor(
|
||||
provider: ClineProvider,
|
||||
apiConfiguration: ApiConfiguration,
|
||||
customInstructions?: string,
|
||||
enableDiff?: boolean,
|
||||
enableCheckpoints?: boolean,
|
||||
fuzzyMatchThreshold?: number,
|
||||
task?: string | undefined,
|
||||
images?: string[] | undefined,
|
||||
historyItem?: HistoryItem | undefined,
|
||||
experiments?: Record<string, boolean>,
|
||||
constructor({
|
||||
provider,
|
||||
apiConfiguration,
|
||||
customInstructions,
|
||||
enableDiff,
|
||||
enableCheckpoints,
|
||||
fuzzyMatchThreshold,
|
||||
task,
|
||||
images,
|
||||
historyItem,
|
||||
experiments,
|
||||
startTask = true,
|
||||
) {
|
||||
}: ClineOptions) {
|
||||
if (startTask && !task && !images && !historyItem) {
|
||||
throw new Error("Either historyItem or task/images must be provided")
|
||||
}
|
||||
|
|
@ -165,21 +179,20 @@ export class Cline {
|
|||
}
|
||||
}
|
||||
|
||||
static create(...args: ConstructorParameters<typeof Cline>): [Cline, Promise<void>] {
|
||||
args[10] = false // startTask
|
||||
const instance = new Cline(...args)
|
||||
static create(options: ClineOptions): [Cline, Promise<void>] {
|
||||
const instance = new Cline({ ...options, startTask: false })
|
||||
const { images, task, historyItem } = options
|
||||
let promise
|
||||
|
||||
let task
|
||||
|
||||
if (args[6] || args[7]) {
|
||||
task = instance.startTask(args[6], args[7])
|
||||
} else if (args[8]) {
|
||||
task = instance.resumeTaskFromHistory()
|
||||
if (images || task) {
|
||||
promise = instance.startTask(task, images)
|
||||
} else if (historyItem) {
|
||||
promise = instance.resumeTaskFromHistory()
|
||||
} else {
|
||||
throw new Error("Either historyItem or task/images must be provided")
|
||||
}
|
||||
|
||||
return [instance, task]
|
||||
return [instance, promise]
|
||||
}
|
||||
|
||||
// Add method to update diffStrategy
|
||||
|
|
|
|||
|
|
@ -327,15 +327,13 @@ describe("Cline", () => {
|
|||
|
||||
describe("constructor", () => {
|
||||
it("should respect provided settings", async () => {
|
||||
const [cline, task] = Cline.create(
|
||||
mockProvider,
|
||||
mockApiConfig,
|
||||
"custom instructions",
|
||||
false,
|
||||
false,
|
||||
0.95, // 95% threshold
|
||||
"test task",
|
||||
)
|
||||
const [cline, task] = Cline.create({
|
||||
provider: mockProvider,
|
||||
apiConfiguration: mockApiConfig,
|
||||
customInstructions: "custom instructions",
|
||||
fuzzyMatchThreshold: 0.95,
|
||||
task: "test task",
|
||||
})
|
||||
|
||||
expect(cline.customInstructions).toBe("custom instructions")
|
||||
expect(cline.diffEnabled).toBe(false)
|
||||
|
|
@ -345,15 +343,14 @@ describe("Cline", () => {
|
|||
})
|
||||
|
||||
it("should use default fuzzy match threshold when not provided", async () => {
|
||||
const [cline, task] = await Cline.create(
|
||||
mockProvider,
|
||||
mockApiConfig,
|
||||
"custom instructions",
|
||||
true,
|
||||
false,
|
||||
undefined,
|
||||
"test task",
|
||||
)
|
||||
const [cline, task] = await Cline.create({
|
||||
provider: mockProvider,
|
||||
apiConfiguration: mockApiConfig,
|
||||
customInstructions: "custom instructions",
|
||||
enableDiff: true,
|
||||
fuzzyMatchThreshold: 0.95,
|
||||
task: "test task",
|
||||
})
|
||||
|
||||
expect(cline.diffEnabled).toBe(true)
|
||||
// The diff strategy should be created with default threshold (1.0)
|
||||
|
|
@ -366,15 +363,14 @@ describe("Cline", () => {
|
|||
it("should use provided fuzzy match threshold", async () => {
|
||||
const getDiffStrategySpy = jest.spyOn(require("../diff/DiffStrategy"), "getDiffStrategy")
|
||||
|
||||
const [cline, task] = Cline.create(
|
||||
mockProvider,
|
||||
mockApiConfig,
|
||||
"custom instructions",
|
||||
true,
|
||||
false,
|
||||
0.9, // 90% threshold
|
||||
"test task",
|
||||
)
|
||||
const [cline, task] = await Cline.create({
|
||||
provider: mockProvider,
|
||||
apiConfiguration: mockApiConfig,
|
||||
customInstructions: "custom instructions",
|
||||
enableDiff: true,
|
||||
fuzzyMatchThreshold: 0.9,
|
||||
task: "test task",
|
||||
})
|
||||
|
||||
expect(cline.diffEnabled).toBe(true)
|
||||
expect(cline.diffStrategy).toBeDefined()
|
||||
|
|
@ -389,15 +385,13 @@ describe("Cline", () => {
|
|||
it("should pass default threshold to diff strategy when not provided", async () => {
|
||||
const getDiffStrategySpy = jest.spyOn(require("../diff/DiffStrategy"), "getDiffStrategy")
|
||||
|
||||
const [cline, task] = Cline.create(
|
||||
mockProvider,
|
||||
mockApiConfig,
|
||||
"custom instructions",
|
||||
true,
|
||||
false,
|
||||
undefined,
|
||||
"test task",
|
||||
)
|
||||
const [cline, task] = Cline.create({
|
||||
provider: mockProvider,
|
||||
apiConfiguration: mockApiConfig,
|
||||
customInstructions: "custom instructions",
|
||||
enableDiff: true,
|
||||
task: "test task",
|
||||
})
|
||||
|
||||
expect(cline.diffEnabled).toBe(true)
|
||||
expect(cline.diffStrategy).toBeDefined()
|
||||
|
|
@ -411,15 +405,7 @@ describe("Cline", () => {
|
|||
|
||||
it("should require either task or historyItem", () => {
|
||||
expect(() => {
|
||||
new Cline(
|
||||
mockProvider,
|
||||
mockApiConfig,
|
||||
undefined, // customInstructions
|
||||
false, // diffEnabled
|
||||
false, // checkpointsEnabled
|
||||
undefined, // fuzzyMatchThreshold
|
||||
undefined, // task
|
||||
)
|
||||
new Cline({ provider: mockProvider, apiConfiguration: mockApiConfig })
|
||||
}).toThrow("Either historyItem or task/images must be provided")
|
||||
})
|
||||
})
|
||||
|
|
@ -469,15 +455,11 @@ describe("Cline", () => {
|
|||
})
|
||||
|
||||
it("should include timezone information in environment details", async () => {
|
||||
const [cline, task] = Cline.create(
|
||||
mockProvider,
|
||||
mockApiConfig,
|
||||
undefined,
|
||||
false,
|
||||
false,
|
||||
undefined,
|
||||
"test task",
|
||||
)
|
||||
const [cline, task] = Cline.create({
|
||||
provider: mockProvider,
|
||||
apiConfiguration: mockApiConfig,
|
||||
task: "test task",
|
||||
})
|
||||
|
||||
const details = await cline["getEnvironmentDetails"](false)
|
||||
|
||||
|
|
@ -493,15 +475,12 @@ describe("Cline", () => {
|
|||
|
||||
describe("API conversation handling", () => {
|
||||
it("should clean conversation history before sending to API", async () => {
|
||||
const [cline, task] = Cline.create(
|
||||
mockProvider,
|
||||
mockApiConfig,
|
||||
undefined,
|
||||
false,
|
||||
false,
|
||||
undefined,
|
||||
"test task",
|
||||
)
|
||||
const [cline, task] = Cline.create({
|
||||
provider: mockProvider,
|
||||
apiConfiguration: mockApiConfig,
|
||||
task: "test task",
|
||||
})
|
||||
|
||||
cline.abandoned = true
|
||||
await task
|
||||
|
||||
|
|
@ -611,15 +590,11 @@ describe("Cline", () => {
|
|||
]
|
||||
|
||||
// Test with model that supports images
|
||||
const [clineWithImages, taskWithImages] = Cline.create(
|
||||
mockProvider,
|
||||
configWithImages,
|
||||
undefined,
|
||||
false,
|
||||
false,
|
||||
undefined,
|
||||
"test task",
|
||||
)
|
||||
const [clineWithImages, taskWithImages] = Cline.create({
|
||||
provider: mockProvider,
|
||||
apiConfiguration: configWithImages,
|
||||
task: "test task",
|
||||
})
|
||||
|
||||
// Mock the model info to indicate image support
|
||||
jest.spyOn(clineWithImages.api, "getModel").mockReturnValue({
|
||||
|
|
@ -638,15 +613,11 @@ describe("Cline", () => {
|
|||
clineWithImages.apiConversationHistory = conversationHistory
|
||||
|
||||
// Test with model that doesn't support images
|
||||
const [clineWithoutImages, taskWithoutImages] = Cline.create(
|
||||
mockProvider,
|
||||
configWithoutImages,
|
||||
undefined,
|
||||
false,
|
||||
false,
|
||||
undefined,
|
||||
"test task",
|
||||
)
|
||||
const [clineWithoutImages, taskWithoutImages] = Cline.create({
|
||||
provider: mockProvider,
|
||||
apiConfiguration: configWithoutImages,
|
||||
task: "test task",
|
||||
})
|
||||
|
||||
// Mock the model info to indicate no image support
|
||||
jest.spyOn(clineWithoutImages.api, "getModel").mockReturnValue({
|
||||
|
|
@ -742,15 +713,11 @@ describe("Cline", () => {
|
|||
})
|
||||
|
||||
it.skip("should handle API retry with countdown", async () => {
|
||||
const [cline, task] = Cline.create(
|
||||
mockProvider,
|
||||
mockApiConfig,
|
||||
undefined,
|
||||
false,
|
||||
false,
|
||||
undefined,
|
||||
"test task",
|
||||
)
|
||||
const [cline, task] = Cline.create({
|
||||
provider: mockProvider,
|
||||
apiConfiguration: mockApiConfig,
|
||||
task: "test task",
|
||||
})
|
||||
|
||||
// Mock delay to track countdown timing
|
||||
const mockDelay = jest.fn().mockResolvedValue(undefined)
|
||||
|
|
@ -870,15 +837,11 @@ describe("Cline", () => {
|
|||
})
|
||||
|
||||
it.skip("should not apply retry delay twice", async () => {
|
||||
const [cline, task] = Cline.create(
|
||||
mockProvider,
|
||||
mockApiConfig,
|
||||
undefined,
|
||||
false,
|
||||
false,
|
||||
undefined,
|
||||
"test task",
|
||||
)
|
||||
const [cline, task] = Cline.create({
|
||||
provider: mockProvider,
|
||||
apiConfiguration: mockApiConfig,
|
||||
task: "test task",
|
||||
})
|
||||
|
||||
// Mock delay to track countdown timing
|
||||
const mockDelay = jest.fn().mockResolvedValue(undefined)
|
||||
|
|
@ -998,15 +961,11 @@ describe("Cline", () => {
|
|||
|
||||
describe("loadContext", () => {
|
||||
it("should process mentions in task and feedback tags", async () => {
|
||||
const [cline, task] = Cline.create(
|
||||
mockProvider,
|
||||
mockApiConfig,
|
||||
undefined,
|
||||
false,
|
||||
false,
|
||||
undefined,
|
||||
"test task",
|
||||
)
|
||||
const [cline, task] = Cline.create({
|
||||
provider: mockProvider,
|
||||
apiConfiguration: mockApiConfig,
|
||||
task: "test task",
|
||||
})
|
||||
|
||||
// Mock parseMentions to track calls
|
||||
const mockParseMentions = jest.fn().mockImplementation((text) => `processed: ${text}`)
|
||||
|
|
|
|||
|
|
@ -413,18 +413,17 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
|||
const modePrompt = customModePrompts?.[mode] as PromptComponent
|
||||
const effectiveInstructions = [globalInstructions, modePrompt?.customInstructions].filter(Boolean).join("\n\n")
|
||||
|
||||
this.cline = new Cline(
|
||||
this,
|
||||
this.cline = new Cline({
|
||||
provider: this,
|
||||
apiConfiguration,
|
||||
effectiveInstructions,
|
||||
diffEnabled,
|
||||
checkpointsEnabled,
|
||||
customInstructions: effectiveInstructions,
|
||||
enableDiff: diffEnabled,
|
||||
enableCheckpoints: checkpointsEnabled,
|
||||
fuzzyMatchThreshold,
|
||||
task,
|
||||
images,
|
||||
undefined,
|
||||
experiments,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
public async initClineWithHistoryItem(historyItem: HistoryItem) {
|
||||
|
|
@ -444,18 +443,16 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
|||
const modePrompt = customModePrompts?.[mode] as PromptComponent
|
||||
const effectiveInstructions = [globalInstructions, modePrompt?.customInstructions].filter(Boolean).join("\n\n")
|
||||
|
||||
this.cline = new Cline(
|
||||
this,
|
||||
this.cline = new Cline({
|
||||
provider: this,
|
||||
apiConfiguration,
|
||||
effectiveInstructions,
|
||||
diffEnabled,
|
||||
checkpointsEnabled,
|
||||
customInstructions: effectiveInstructions,
|
||||
enableDiff: diffEnabled,
|
||||
enableCheckpoints: checkpointsEnabled,
|
||||
fuzzyMatchThreshold,
|
||||
undefined,
|
||||
undefined,
|
||||
historyItem,
|
||||
experiments,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
public async postMessageToWebview(message: ExtensionMessage) {
|
||||
|
|
|
|||
|
|
@ -690,19 +690,18 @@ describe("ClineProvider", () => {
|
|||
await provider.initClineWithTask("Test task")
|
||||
|
||||
// Verify Cline was initialized with mode-specific instructions
|
||||
expect(Cline).toHaveBeenCalledWith(
|
||||
expect(Cline).toHaveBeenCalledWith({
|
||||
provider,
|
||||
mockApiConfig,
|
||||
modeCustomInstructions,
|
||||
true,
|
||||
false,
|
||||
1.0,
|
||||
"Test task",
|
||||
undefined,
|
||||
undefined,
|
||||
experimentDefault,
|
||||
)
|
||||
apiConfiguration: mockApiConfig,
|
||||
customInstructions: modeCustomInstructions,
|
||||
enableDiff: true,
|
||||
enableCheckpoints: false,
|
||||
fuzzyMatchThreshold: 1.0,
|
||||
task: "Test task",
|
||||
experiments: experimentDefault,
|
||||
})
|
||||
})
|
||||
|
||||
test("handles mode-specific custom instructions updates", async () => {
|
||||
await provider.resolveWebviewView(mockWebviewView)
|
||||
const messageHandler = (mockWebviewView.webview.onDidReceiveMessage as jest.Mock).mock.calls[0][0]
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue