mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-09-05 08:10:14 +00:00
Rename ToolUse to ToolDirective
This commit is contained in:
parent
e6333785f3
commit
d08b0d300d
39 changed files with 355 additions and 336 deletions
|
|
@ -2,7 +2,8 @@ import { distance } from "fastest-levenshtein"
|
|||
import { ToolProgressStatus } from "@roo-code/types"
|
||||
|
||||
import { addLineNumbers, everyLineHasLineNumbers, stripLineNumbers } from "../../../integrations/misc/extract-text"
|
||||
import { ToolUse, DiffStrategy, DiffResult } from "../../../shared/tools"
|
||||
import { DiffStrategy, DiffResult } from "../../../shared/tools"
|
||||
import { ToolDirective } from "../../message-parsing/directives/"
|
||||
import { normalizeString } from "../../../utils/text-normalization"
|
||||
|
||||
const BUFFER_LINES = 40 // Number of extra context lines to show before and after matches
|
||||
|
|
@ -707,7 +708,7 @@ Each file requires its own path, start_line, and diff elements.
|
|||
}
|
||||
}
|
||||
|
||||
getProgressStatus(toolUse: ToolUse, result?: DiffResult): ToolProgressStatus {
|
||||
getProgressStatus(toolUse: ToolDirective, result?: DiffResult): ToolProgressStatus {
|
||||
const diffContent = toolUse.params.diff
|
||||
if (diffContent) {
|
||||
const icon = "diff-multiple"
|
||||
|
|
|
|||
|
|
@ -5,7 +5,8 @@ import { distance } from "fastest-levenshtein"
|
|||
import { ToolProgressStatus } from "@roo-code/types"
|
||||
|
||||
import { addLineNumbers, everyLineHasLineNumbers, stripLineNumbers } from "../../../integrations/misc/extract-text"
|
||||
import { ToolUse, DiffStrategy, DiffResult } from "../../../shared/tools"
|
||||
import { DiffStrategy, DiffResult } from "../../../shared/tools"
|
||||
import { ToolDirective } from "../../message-parsing/directives/"
|
||||
import { normalizeString } from "../../../utils/text-normalization"
|
||||
|
||||
const BUFFER_LINES = 40 // Number of extra context lines to show before and after matches
|
||||
|
|
@ -609,11 +610,11 @@ Only use a single line of '=======' between search and replacement content, beca
|
|||
}
|
||||
}
|
||||
|
||||
getProgressStatus(toolUse: ToolUse, result?: DiffResult): ToolProgressStatus {
|
||||
const diffContent = toolUse.params.diff
|
||||
getProgressStatus(ToolDirective: ToolDirective, result?: DiffResult): ToolProgressStatus {
|
||||
const diffContent = ToolDirective.params.diff
|
||||
if (diffContent) {
|
||||
const icon = "diff-multiple"
|
||||
if (toolUse.partial) {
|
||||
if (ToolDirective.partial) {
|
||||
if (Math.floor(diffContent.length / 10) % 10 === 0) {
|
||||
const searchBlockCount = (diffContent.match(/SEARCH/g) || []).length
|
||||
return { icon, text: `${searchBlockCount}` }
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import { Directive } from "./directives"
|
||||
import { Directive, ToolDirective } from "./directives"
|
||||
import { TextDirective, LogDirective } from "./directives"
|
||||
import { toolNames } from "@roo-code/types"
|
||||
import { ToolUse } from "../../shared/tools"
|
||||
|
||||
export class FallbackParser {
|
||||
static parse(assistantMessage: string): Directive[] {
|
||||
|
|
@ -76,14 +75,14 @@ export class FallbackParser {
|
|||
}
|
||||
}
|
||||
|
||||
const toolUse: ToolUse = {
|
||||
const ToolDirective: ToolDirective = {
|
||||
type: "tool_use",
|
||||
name: toolName as any,
|
||||
params,
|
||||
partial: !assistantMessage.includes(`</${toolName}>`),
|
||||
}
|
||||
|
||||
contentBlocks.push(toolUse)
|
||||
contentBlocks.push(ToolDirective)
|
||||
return contentBlocks
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import { suite, test, expect } from "vitest"
|
||||
import { DirectiveStreamingParser } from "../DirectiveStreamingParser"
|
||||
import { TextDirective, LogDirective } from "../directives"
|
||||
import { ToolUse } from "../../../shared/tools"
|
||||
import { ToolDirective, TextDirective, LogDirective } from "../directives"
|
||||
|
||||
suite("DirectiveStreamingParser", () => {
|
||||
test("should parse plain text content", () => {
|
||||
|
|
@ -51,7 +50,7 @@ suite("DirectiveStreamingParser", () => {
|
|||
name: "read_file",
|
||||
params: { path: "src/app.ts" },
|
||||
partial: false,
|
||||
} as ToolUse,
|
||||
} as ToolDirective,
|
||||
])
|
||||
})
|
||||
|
||||
|
|
@ -70,7 +69,7 @@ suite("DirectiveStreamingParser", () => {
|
|||
name: "apply_diff",
|
||||
params: { path: "src/file.ts", diff: "diff content" },
|
||||
partial: false,
|
||||
} as ToolUse,
|
||||
} as ToolDirective,
|
||||
{
|
||||
type: "text",
|
||||
content: "More text",
|
||||
|
|
@ -88,7 +87,7 @@ suite("DirectiveStreamingParser", () => {
|
|||
name: "write_to_file",
|
||||
params: { path: "src/newfile.ts", content: "Some content" },
|
||||
partial: true,
|
||||
} as ToolUse,
|
||||
} as ToolDirective,
|
||||
])
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import { suite, test, expect } from "vitest"
|
||||
import { DirectiveStreamingParser } from "../DirectiveStreamingParser"
|
||||
import { TextDirective, LogDirective } from "../directives"
|
||||
import { ToolUse } from "../../../shared/tools"
|
||||
import { ToolDirective, TextDirective, LogDirective } from "../directives"
|
||||
|
||||
suite("DirectiveStreamingParser", () => {
|
||||
test("should parse plain text content", () => {
|
||||
|
|
@ -51,7 +50,7 @@ suite("DirectiveStreamingParser", () => {
|
|||
name: "read_file",
|
||||
params: { path: "src/app.ts" },
|
||||
partial: false,
|
||||
} as ToolUse,
|
||||
} as ToolDirective,
|
||||
])
|
||||
})
|
||||
|
||||
|
|
@ -70,7 +69,7 @@ suite("DirectiveStreamingParser", () => {
|
|||
name: "apply_diff",
|
||||
params: { path: "src/file.ts", diff: "diff content" },
|
||||
partial: false,
|
||||
} as ToolUse,
|
||||
} as ToolDirective,
|
||||
{
|
||||
type: "text",
|
||||
content: "More text",
|
||||
|
|
@ -88,7 +87,7 @@ suite("DirectiveStreamingParser", () => {
|
|||
name: "write_to_file",
|
||||
params: { path: "src/newfile.ts", content: "Some content" },
|
||||
partial: true,
|
||||
} as ToolUse,
|
||||
} as ToolDirective,
|
||||
])
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
// npx jest src/core/assistant-message/__tests__/parseAssistantMessage.test.ts
|
||||
|
||||
import { TextDirective } from "../directives"
|
||||
import { ToolUse } from "../../../shared/tools"
|
||||
|
||||
import { TextDirective, ToolDirective } from "../directives"
|
||||
import { AssistantMessageContent, parseAssistantMessage as parseAssistantMessageV1 } from "../parseAssistantMessage"
|
||||
import { parseAssistantMessageV2 } from "../parseAssistantMessageV2"
|
||||
|
||||
|
|
@ -55,11 +53,11 @@ const isEmptyTextContent = (block: AssistantMessageContent) =>
|
|||
const result = parser(message).filter((block) => !isEmptyTextContent(block))
|
||||
|
||||
expect(result).toHaveLength(1)
|
||||
const toolUse = result[0] as ToolUse
|
||||
expect(toolUse.type).toBe("tool_use")
|
||||
expect(toolUse.name).toBe("read_file")
|
||||
expect(toolUse.params.path).toBe("src/file.ts")
|
||||
expect(toolUse.partial).toBe(false)
|
||||
const ToolDirective = result[0] as ToolDirective
|
||||
expect(ToolDirective.type).toBe("tool_use")
|
||||
expect(ToolDirective.name).toBe("read_file")
|
||||
expect(ToolDirective.params.path).toBe("src/file.ts")
|
||||
expect(ToolDirective.partial).toBe(false)
|
||||
})
|
||||
|
||||
it("should parse a tool use with multiple parameters", () => {
|
||||
|
|
@ -68,13 +66,13 @@ const isEmptyTextContent = (block: AssistantMessageContent) =>
|
|||
const result = parser(message).filter((block) => !isEmptyTextContent(block))
|
||||
|
||||
expect(result).toHaveLength(1)
|
||||
const toolUse = result[0] as ToolUse
|
||||
expect(toolUse.type).toBe("tool_use")
|
||||
expect(toolUse.name).toBe("read_file")
|
||||
expect(toolUse.params.path).toBe("src/file.ts")
|
||||
expect(toolUse.params.start_line).toBe("10")
|
||||
expect(toolUse.params.end_line).toBe("20")
|
||||
expect(toolUse.partial).toBe(false)
|
||||
const ToolDirective = result[0] as ToolDirective
|
||||
expect(ToolDirective.type).toBe("tool_use")
|
||||
expect(ToolDirective.name).toBe("read_file")
|
||||
expect(ToolDirective.params.path).toBe("src/file.ts")
|
||||
expect(ToolDirective.params.start_line).toBe("10")
|
||||
expect(ToolDirective.params.end_line).toBe("20")
|
||||
expect(ToolDirective.partial).toBe(false)
|
||||
})
|
||||
|
||||
it("should mark tool use as partial when it's not closed", () => {
|
||||
|
|
@ -82,11 +80,11 @@ const isEmptyTextContent = (block: AssistantMessageContent) =>
|
|||
const result = parser(message).filter((block) => !isEmptyTextContent(block))
|
||||
|
||||
expect(result).toHaveLength(1)
|
||||
const toolUse = result[0] as ToolUse
|
||||
expect(toolUse.type).toBe("tool_use")
|
||||
expect(toolUse.name).toBe("read_file")
|
||||
expect(toolUse.params.path).toBe("src/file.ts")
|
||||
expect(toolUse.partial).toBe(true)
|
||||
const ToolDirective = result[0] as ToolDirective
|
||||
expect(ToolDirective.type).toBe("tool_use")
|
||||
expect(ToolDirective.name).toBe("read_file")
|
||||
expect(ToolDirective.params.path).toBe("src/file.ts")
|
||||
expect(ToolDirective.partial).toBe(true)
|
||||
})
|
||||
|
||||
it("should handle a partial parameter in a tool use", () => {
|
||||
|
|
@ -94,11 +92,11 @@ const isEmptyTextContent = (block: AssistantMessageContent) =>
|
|||
const result = parser(message).filter((block) => !isEmptyTextContent(block))
|
||||
|
||||
expect(result).toHaveLength(1)
|
||||
const toolUse = result[0] as ToolUse
|
||||
expect(toolUse.type).toBe("tool_use")
|
||||
expect(toolUse.name).toBe("read_file")
|
||||
expect(toolUse.params.path).toBe("src/file.ts")
|
||||
expect(toolUse.partial).toBe(true)
|
||||
const ToolDirective = result[0] as ToolDirective
|
||||
expect(ToolDirective.type).toBe("tool_use")
|
||||
expect(ToolDirective.name).toBe("read_file")
|
||||
expect(ToolDirective.params.path).toBe("src/file.ts")
|
||||
expect(ToolDirective.partial).toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
|
|
@ -114,11 +112,11 @@ const isEmptyTextContent = (block: AssistantMessageContent) =>
|
|||
expect(textContent.content).toBe("Here's the file content:")
|
||||
expect(textContent.partial).toBe(false)
|
||||
|
||||
const toolUse = result[1] as ToolUse
|
||||
expect(toolUse.type).toBe("tool_use")
|
||||
expect(toolUse.name).toBe("read_file")
|
||||
expect(toolUse.params.path).toBe("src/file.ts")
|
||||
expect(toolUse.partial).toBe(false)
|
||||
const ToolDirective = result[1] as ToolDirective
|
||||
expect(ToolDirective.type).toBe("tool_use")
|
||||
expect(ToolDirective.name).toBe("read_file")
|
||||
expect(ToolDirective.params.path).toBe("src/file.ts")
|
||||
expect(ToolDirective.partial).toBe(false)
|
||||
})
|
||||
|
||||
it("should parse a tool use followed by text", () => {
|
||||
|
|
@ -127,11 +125,11 @@ const isEmptyTextContent = (block: AssistantMessageContent) =>
|
|||
|
||||
expect(result).toHaveLength(2)
|
||||
|
||||
const toolUse = result[0] as ToolUse
|
||||
expect(toolUse.type).toBe("tool_use")
|
||||
expect(toolUse.name).toBe("read_file")
|
||||
expect(toolUse.params.path).toBe("src/file.ts")
|
||||
expect(toolUse.partial).toBe(false)
|
||||
const ToolDirective = result[0] as ToolDirective
|
||||
expect(ToolDirective.type).toBe("tool_use")
|
||||
expect(ToolDirective.name).toBe("read_file")
|
||||
expect(ToolDirective.params.path).toBe("src/file.ts")
|
||||
expect(ToolDirective.partial).toBe(false)
|
||||
|
||||
const textContent = result[1] as TextDirective
|
||||
expect(textContent.type).toBe("text")
|
||||
|
|
@ -150,15 +148,15 @@ const isEmptyTextContent = (block: AssistantMessageContent) =>
|
|||
expect((result[0] as TextDirective).content).toBe("First file:")
|
||||
|
||||
expect(result[1].type).toBe("tool_use")
|
||||
expect((result[1] as ToolUse).name).toBe("read_file")
|
||||
expect((result[1] as ToolUse).params.path).toBe("src/file1.ts")
|
||||
expect((result[1] as ToolDirective).name).toBe("read_file")
|
||||
expect((result[1] as ToolDirective).params.path).toBe("src/file1.ts")
|
||||
|
||||
expect(result[2].type).toBe("text")
|
||||
expect((result[2] as TextDirective).content).toBe("Second file:")
|
||||
|
||||
expect(result[3].type).toBe("tool_use")
|
||||
expect((result[3] as ToolUse).name).toBe("read_file")
|
||||
expect((result[3] as ToolUse).params.path).toBe("src/file2.ts")
|
||||
expect((result[3] as ToolDirective).name).toBe("read_file")
|
||||
expect((result[3] as ToolDirective).params.path).toBe("src/file2.ts")
|
||||
})
|
||||
})
|
||||
|
||||
|
|
@ -174,15 +172,15 @@ const isEmptyTextContent = (block: AssistantMessageContent) =>
|
|||
const result = parser(message).filter((block) => !isEmptyTextContent(block))
|
||||
|
||||
expect(result).toHaveLength(1)
|
||||
const toolUse = result[0] as ToolUse
|
||||
expect(toolUse.type).toBe("tool_use")
|
||||
expect(toolUse.name).toBe("write_to_file")
|
||||
expect(toolUse.params.path).toBe("src/file.ts")
|
||||
expect(toolUse.params.line_count).toBe("5")
|
||||
expect(toolUse.params.content).toContain("function example()")
|
||||
expect(toolUse.params.content).toContain("// This has XML-like content: </content>")
|
||||
expect(toolUse.params.content).toContain("return true;")
|
||||
expect(toolUse.partial).toBe(false)
|
||||
const ToolDirective = result[0] as ToolDirective
|
||||
expect(ToolDirective.type).toBe("tool_use")
|
||||
expect(ToolDirective.name).toBe("write_to_file")
|
||||
expect(ToolDirective.params.path).toBe("src/file.ts")
|
||||
expect(ToolDirective.params.line_count).toBe("5")
|
||||
expect(ToolDirective.params.content).toContain("function example()")
|
||||
expect(ToolDirective.params.content).toContain("// This has XML-like content: </content>")
|
||||
expect(ToolDirective.params.content).toContain("return true;")
|
||||
expect(ToolDirective.partial).toBe(false)
|
||||
})
|
||||
|
||||
it("should handle empty messages", () => {
|
||||
|
|
@ -206,11 +204,11 @@ const isEmptyTextContent = (block: AssistantMessageContent) =>
|
|||
const result = parser(message).filter((block) => !isEmptyTextContent(block))
|
||||
|
||||
expect(result).toHaveLength(1)
|
||||
const toolUse = result[0] as ToolUse
|
||||
expect(toolUse.type).toBe("tool_use")
|
||||
expect(toolUse.name).toBe("browser_action")
|
||||
expect(Object.keys(toolUse.params).length).toBe(0)
|
||||
expect(toolUse.partial).toBe(false)
|
||||
const ToolDirective = result[0] as ToolDirective
|
||||
expect(ToolDirective.type).toBe("tool_use")
|
||||
expect(ToolDirective.name).toBe("browser_action")
|
||||
expect(Object.keys(ToolDirective.params).length).toBe(0)
|
||||
expect(ToolDirective.partial).toBe(false)
|
||||
})
|
||||
|
||||
it("should handle nested tool tags that aren't actually nested", () => {
|
||||
|
|
@ -220,11 +218,11 @@ const isEmptyTextContent = (block: AssistantMessageContent) =>
|
|||
const result = parser(message).filter((block) => !isEmptyTextContent(block))
|
||||
|
||||
expect(result).toHaveLength(1)
|
||||
const toolUse = result[0] as ToolUse
|
||||
expect(toolUse.type).toBe("tool_use")
|
||||
expect(toolUse.name).toBe("execute_command")
|
||||
expect(toolUse.params.command).toBe("echo '<read_file><path>test.txt</path></read_file>'")
|
||||
expect(toolUse.partial).toBe(false)
|
||||
const ToolDirective = result[0] as ToolDirective
|
||||
expect(ToolDirective.type).toBe("tool_use")
|
||||
expect(ToolDirective.name).toBe("execute_command")
|
||||
expect(ToolDirective.params.command).toBe("echo '<read_file><path>test.txt</path></read_file>'")
|
||||
expect(ToolDirective.partial).toBe(false)
|
||||
})
|
||||
|
||||
it("should handle a tool use with a parameter containing XML-like content", () => {
|
||||
|
|
@ -232,12 +230,12 @@ const isEmptyTextContent = (block: AssistantMessageContent) =>
|
|||
const result = parser(message).filter((block) => !isEmptyTextContent(block))
|
||||
|
||||
expect(result).toHaveLength(1)
|
||||
const toolUse = result[0] as ToolUse
|
||||
expect(toolUse.type).toBe("tool_use")
|
||||
expect(toolUse.name).toBe("search_files")
|
||||
expect(toolUse.params.regex).toBe("<div>.*</div>")
|
||||
expect(toolUse.params.path).toBe("src")
|
||||
expect(toolUse.partial).toBe(false)
|
||||
const ToolDirective = result[0] as ToolDirective
|
||||
expect(ToolDirective.type).toBe("tool_use")
|
||||
expect(ToolDirective.name).toBe("search_files")
|
||||
expect(ToolDirective.params.regex).toBe("<div>.*</div>")
|
||||
expect(ToolDirective.params.path).toBe("src")
|
||||
expect(ToolDirective.partial).toBe(false)
|
||||
})
|
||||
|
||||
it("should handle consecutive tool uses without text in between", () => {
|
||||
|
|
@ -247,17 +245,17 @@ const isEmptyTextContent = (block: AssistantMessageContent) =>
|
|||
|
||||
expect(result).toHaveLength(2)
|
||||
|
||||
const toolUse1 = result[0] as ToolUse
|
||||
expect(toolUse1.type).toBe("tool_use")
|
||||
expect(toolUse1.name).toBe("read_file")
|
||||
expect(toolUse1.params.path).toBe("file1.ts")
|
||||
expect(toolUse1.partial).toBe(false)
|
||||
const ToolDirective1 = result[0] as ToolDirective
|
||||
expect(ToolDirective1.type).toBe("tool_use")
|
||||
expect(ToolDirective1.name).toBe("read_file")
|
||||
expect(ToolDirective1.params.path).toBe("file1.ts")
|
||||
expect(ToolDirective1.partial).toBe(false)
|
||||
|
||||
const toolUse2 = result[1] as ToolUse
|
||||
expect(toolUse2.type).toBe("tool_use")
|
||||
expect(toolUse2.name).toBe("read_file")
|
||||
expect(toolUse2.params.path).toBe("file2.ts")
|
||||
expect(toolUse2.partial).toBe(false)
|
||||
const ToolDirective2 = result[1] as ToolDirective
|
||||
expect(ToolDirective2.type).toBe("tool_use")
|
||||
expect(ToolDirective2.name).toBe("read_file")
|
||||
expect(ToolDirective2.params.path).toBe("file2.ts")
|
||||
expect(ToolDirective2.partial).toBe(false)
|
||||
})
|
||||
|
||||
it("should handle whitespace in parameters", () => {
|
||||
|
|
@ -265,11 +263,11 @@ const isEmptyTextContent = (block: AssistantMessageContent) =>
|
|||
const result = parser(message).filter((block) => !isEmptyTextContent(block))
|
||||
|
||||
expect(result).toHaveLength(1)
|
||||
const toolUse = result[0] as ToolUse
|
||||
expect(toolUse.type).toBe("tool_use")
|
||||
expect(toolUse.name).toBe("read_file")
|
||||
expect(toolUse.params.path).toBe("src/file.ts")
|
||||
expect(toolUse.partial).toBe(false)
|
||||
const ToolDirective = result[0] as ToolDirective
|
||||
expect(ToolDirective.type).toBe("tool_use")
|
||||
expect(ToolDirective.name).toBe("read_file")
|
||||
expect(ToolDirective.params.path).toBe("src/file.ts")
|
||||
expect(ToolDirective.partial).toBe(false)
|
||||
})
|
||||
|
||||
it("should handle multi-line parameters", () => {
|
||||
|
|
@ -281,15 +279,15 @@ const isEmptyTextContent = (block: AssistantMessageContent) =>
|
|||
const result = parser(message).filter((block) => !isEmptyTextContent(block))
|
||||
|
||||
expect(result).toHaveLength(1)
|
||||
const toolUse = result[0] as ToolUse
|
||||
expect(toolUse.type).toBe("tool_use")
|
||||
expect(toolUse.name).toBe("write_to_file")
|
||||
expect(toolUse.params.path).toBe("file.ts")
|
||||
expect(toolUse.params.content).toContain("line 1")
|
||||
expect(toolUse.params.content).toContain("line 2")
|
||||
expect(toolUse.params.content).toContain("line 3")
|
||||
expect(toolUse.params.line_count).toBe("3")
|
||||
expect(toolUse.partial).toBe(false)
|
||||
const ToolDirective = result[0] as ToolDirective
|
||||
expect(ToolDirective.type).toBe("tool_use")
|
||||
expect(ToolDirective.name).toBe("write_to_file")
|
||||
expect(ToolDirective.params.path).toBe("file.ts")
|
||||
expect(ToolDirective.params.content).toContain("line 1")
|
||||
expect(ToolDirective.params.content).toContain("line 2")
|
||||
expect(ToolDirective.params.content).toContain("line 3")
|
||||
expect(ToolDirective.params.line_count).toBe("3")
|
||||
expect(ToolDirective.partial).toBe(false)
|
||||
})
|
||||
|
||||
it("should handle a complex message with multiple content types", () => {
|
||||
|
|
@ -318,7 +316,7 @@ const isEmptyTextContent = (block: AssistantMessageContent) =>
|
|||
|
||||
// First tool use (read_file)
|
||||
expect(result[1].type).toBe("tool_use")
|
||||
expect((result[1] as ToolUse).name).toBe("read_file")
|
||||
expect((result[1] as ToolDirective).name).toBe("read_file")
|
||||
|
||||
// Second text block
|
||||
expect(result[2].type).toBe("text")
|
||||
|
|
@ -326,7 +324,7 @@ const isEmptyTextContent = (block: AssistantMessageContent) =>
|
|||
|
||||
// Second tool use (write_to_file)
|
||||
expect(result[3].type).toBe("tool_use")
|
||||
expect((result[3] as ToolUse).name).toBe("write_to_file")
|
||||
expect((result[3] as ToolDirective).name).toBe("write_to_file")
|
||||
|
||||
// Third text block
|
||||
expect(result[4].type).toBe("text")
|
||||
|
|
@ -334,7 +332,7 @@ const isEmptyTextContent = (block: AssistantMessageContent) =>
|
|||
|
||||
// Third tool use (execute_command)
|
||||
expect(result[5].type).toBe("tool_use")
|
||||
expect((result[5] as ToolUse).name).toBe("execute_command")
|
||||
expect((result[5] as ToolDirective).name).toBe("execute_command")
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
|||
5
src/core/message-parsing/directives/Directive.ts
Normal file
5
src/core/message-parsing/directives/Directive.ts
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
import { LogDirective } from "./LogDirective"
|
||||
import { TextDirective } from "./TextDirective"
|
||||
import { ToolDirective } from "./ToolDirective"
|
||||
|
||||
export type Directive = TextDirective | ToolDirective | LogDirective
|
||||
10
src/core/message-parsing/directives/ToolDirective.ts
Normal file
10
src/core/message-parsing/directives/ToolDirective.ts
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
import { ToolName } from "@roo-code/types"
|
||||
import { ToolParamName } from "../../../shared/tools"
|
||||
|
||||
export interface ToolDirective {
|
||||
type: "tool_use"
|
||||
name: ToolName
|
||||
// params is a partial record, allowing only some or none of the possible parameters to be used
|
||||
params: Partial<Record<ToolParamName, string>>
|
||||
partial: boolean
|
||||
}
|
||||
|
|
@ -1,8 +1,4 @@
|
|||
import { TextDirective, LogDirective } from "../directives"
|
||||
import { ToolUse } from "../../../shared/tools"
|
||||
|
||||
export * from "./LogDirective"
|
||||
export * from "./TextDirective"
|
||||
|
||||
export type ToolDirective = ToolUse
|
||||
export type Directive = TextDirective | ToolDirective | LogDirective
|
||||
export type { Directive } from "./Directive"
|
||||
export type { TextDirective } from "./TextDirective"
|
||||
export type { ToolDirective } from "./ToolDirective"
|
||||
export type { LogDirective } from "./LogDirective"
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
import * as sax from "sax"
|
||||
import { BaseDirectiveHandler } from "./BaseDirectiveHandler"
|
||||
import { ParseContext } from "../ParseContext"
|
||||
import { ToolUse, ToolParamName } from "../../../shared/tools"
|
||||
import { ToolParamName } from "../../../shared/tools"
|
||||
import { ToolDirective } from "../directives"
|
||||
|
||||
export class ToolDirectiveHandler extends BaseDirectiveHandler {
|
||||
readonly tagName: string
|
||||
private currentToolUse?: ToolUse
|
||||
private currentToolDirective?: ToolDirective
|
||||
private currentParamName?: ToolParamName
|
||||
private currentParamValue = ""
|
||||
private currentContext: "param" | "none" = "none"
|
||||
|
|
@ -18,14 +19,14 @@ export class ToolDirectiveHandler extends BaseDirectiveHandler {
|
|||
override onOpenTag(node: sax.Tag, context: ParseContext): void {
|
||||
if (node.name === this.tagName) {
|
||||
this.flushCurrentText(context)
|
||||
this.currentToolUse = {
|
||||
this.currentToolDirective = {
|
||||
type: "tool_use",
|
||||
name: this.tagName as any,
|
||||
params: {},
|
||||
partial: true,
|
||||
}
|
||||
this.currentContext = "none"
|
||||
} else if (this.currentToolUse) {
|
||||
} else if (this.currentToolDirective) {
|
||||
this.currentParamName = node.name as ToolParamName
|
||||
this.currentParamValue = ""
|
||||
this.currentContext = "param"
|
||||
|
|
@ -33,13 +34,13 @@ export class ToolDirectiveHandler extends BaseDirectiveHandler {
|
|||
}
|
||||
|
||||
override onCloseTag(tagName: string, context: ParseContext): void {
|
||||
if (tagName === this.tagName && this.currentToolUse) {
|
||||
this.currentToolUse.partial =
|
||||
context.hasIncompleteXml || Object.keys(this.currentToolUse.params).length === 0
|
||||
context.contentBlocks.push(this.currentToolUse)
|
||||
this.currentToolUse = undefined
|
||||
} else if (this.currentToolUse && this.currentParamName && tagName === this.currentParamName) {
|
||||
;(this.currentToolUse.params as Record<string, string>)[this.currentParamName] =
|
||||
if (tagName === this.tagName && this.currentToolDirective) {
|
||||
this.currentToolDirective.partial =
|
||||
context.hasIncompleteXml || Object.keys(this.currentToolDirective.params).length === 0
|
||||
context.contentBlocks.push(this.currentToolDirective)
|
||||
this.currentToolDirective = undefined
|
||||
} else if (this.currentToolDirective && this.currentParamName && tagName === this.currentParamName) {
|
||||
;(this.currentToolDirective.params as Record<string, string>)[this.currentParamName] =
|
||||
this.currentParamValue.trim()
|
||||
this.currentParamName = undefined
|
||||
this.currentParamValue = ""
|
||||
|
|
@ -48,19 +49,19 @@ export class ToolDirectiveHandler extends BaseDirectiveHandler {
|
|||
}
|
||||
|
||||
override onText(text: string, context: ParseContext): void {
|
||||
if (this.currentContext === "param" && this.currentParamName && this.currentToolUse) {
|
||||
if (this.currentContext === "param" && this.currentParamName && this.currentToolDirective) {
|
||||
this.currentParamValue += text
|
||||
}
|
||||
}
|
||||
|
||||
override onEnd(context: ParseContext): void {
|
||||
if (this.currentToolUse) {
|
||||
if (this.currentToolDirective) {
|
||||
if (this.currentParamName && this.currentParamValue) {
|
||||
;(this.currentToolUse.params as Record<string, string>)[this.currentParamName] =
|
||||
;(this.currentToolDirective.params as Record<string, string>)[this.currentParamName] =
|
||||
this.currentParamValue.trim()
|
||||
}
|
||||
this.currentToolUse.partial = true
|
||||
context.contentBlocks.push(this.currentToolUse)
|
||||
this.currentToolDirective.partial = true
|
||||
context.contentBlocks.push(this.currentToolDirective)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { type ToolName, toolNames } from "@roo-code/types"
|
||||
import { TextDirective } from "./directives"
|
||||
import { ToolUse, ToolParamName, toolParamNames } from "../../shared/tools"
|
||||
import { TextDirective, ToolDirective } from "./directives"
|
||||
import { ToolParamName, toolParamNames } from "../../shared/tools"
|
||||
|
||||
export type AssistantMessageContent = TextDirective | ToolUse
|
||||
export type AssistantMessageContent = TextDirective | ToolDirective
|
||||
|
||||
/**
|
||||
* Parses an assistant message string potentially containing mixed text and tool
|
||||
|
|
@ -14,10 +14,10 @@ export type AssistantMessageContent = TextDirective | ToolUse
|
|||
* position, it checks if the substring *ending* at `i` matches any known
|
||||
* opening or closing tags for tools or parameters using `startsWith` with an
|
||||
* offset.
|
||||
* It uses pre-computed Maps (`toolUseOpenTags`, `toolParamOpenTags`) for quick
|
||||
* It uses pre-computed Maps (`ToolDirectiveOpenTags`, `toolParamOpenTags`) for quick
|
||||
* tag lookups.
|
||||
* State is managed using indices (`currentTextContentStart`,
|
||||
* `currentToolUseStart`, `currentParamValueStart`) pointing to the start of the
|
||||
* `currentToolDirectiveStart`, `currentParamValueStart`) pointing to the start of the
|
||||
* current block within the original `assistantMessage` string.
|
||||
*
|
||||
* Slicing is used to extract content only when a block (text, parameter, or
|
||||
|
|
@ -32,7 +32,7 @@ export type AssistantMessageContent = TextDirective | ToolUse
|
|||
*
|
||||
* @param assistantMessage The raw string output from the assistant.
|
||||
* @returns An array of `AssistantMessageContent` objects, which can be
|
||||
* `TextContent` or `ToolUse`. Blocks that were not fully closed by the
|
||||
* `TextContent` or `ToolDirective`. Blocks that were not fully closed by the
|
||||
* end of the input string will have their `partial` flag set to
|
||||
* `true`.
|
||||
*/
|
||||
|
|
@ -42,17 +42,17 @@ export function parseAssistantMessageV2(assistantMessage: string): AssistantMess
|
|||
|
||||
let currentTextContentStart = 0 // Index where the current text block started.
|
||||
let currentTextContent: TextDirective | undefined = undefined
|
||||
let currentToolUseStart = 0 // Index *after* the opening tag of the current tool use.
|
||||
let currentToolUse: ToolUse | undefined = undefined
|
||||
let currentToolDirectiveStart = 0 // Index *after* the opening tag of the current tool use.
|
||||
let currentToolDirective: ToolDirective | undefined = undefined
|
||||
let currentParamValueStart = 0 // Index *after* the opening tag of the current param.
|
||||
let currentParamName: ToolParamName | undefined = undefined
|
||||
|
||||
// Precompute tags for faster lookups.
|
||||
const toolUseOpenTags = new Map<string, ToolName>()
|
||||
const ToolDirectiveOpenTags = new Map<string, ToolName>()
|
||||
const toolParamOpenTags = new Map<string, ToolParamName>()
|
||||
|
||||
for (const name of toolNames) {
|
||||
toolUseOpenTags.set(`<${name}>`, name)
|
||||
ToolDirectiveOpenTags.set(`<${name}>`, name)
|
||||
}
|
||||
|
||||
for (const name of toolParamNames) {
|
||||
|
|
@ -65,7 +65,7 @@ export function parseAssistantMessageV2(assistantMessage: string): AssistantMess
|
|||
const currentCharIndex = i
|
||||
|
||||
// Parsing a tool parameter
|
||||
if (currentToolUse && currentParamName) {
|
||||
if (currentToolDirective && currentParamName) {
|
||||
const closeTag = `</${currentParamName}>`
|
||||
// Check if the string *ending* at index `i` matches the closing tag
|
||||
if (
|
||||
|
|
@ -82,7 +82,7 @@ export function parseAssistantMessageV2(assistantMessage: string): AssistantMess
|
|||
currentCharIndex - closeTag.length + 1, // End before the closing tag.
|
||||
)
|
||||
.trim()
|
||||
currentToolUse.params[currentParamName] = value
|
||||
currentToolDirective.params[currentParamName] = value
|
||||
currentParamName = undefined // Go back to parsing tool content.
|
||||
// We don't continue loop here, need to check for tool close or other params at index i.
|
||||
} else {
|
||||
|
|
@ -91,7 +91,7 @@ export function parseAssistantMessageV2(assistantMessage: string): AssistantMess
|
|||
}
|
||||
|
||||
// Parsing a tool use (but not a specific parameter).
|
||||
if (currentToolUse && !currentParamName) {
|
||||
if (currentToolDirective && !currentParamName) {
|
||||
// Ensure we are not inside a parameter already.
|
||||
// Check if starting a new parameter.
|
||||
let startedNewParam = false
|
||||
|
|
@ -113,7 +113,7 @@ export function parseAssistantMessageV2(assistantMessage: string): AssistantMess
|
|||
}
|
||||
|
||||
// Check if closing the current tool use.
|
||||
const toolCloseTag = `</${currentToolUse.name}>`
|
||||
const toolCloseTag = `</${currentToolDirective.name}>`
|
||||
|
||||
if (
|
||||
currentCharIndex >= toolCloseTag.length - 1 &&
|
||||
|
|
@ -123,7 +123,7 @@ export function parseAssistantMessageV2(assistantMessage: string): AssistantMess
|
|||
// Special handling for content params *before* finalizing the
|
||||
// tool.
|
||||
const toolContentSlice = assistantMessage.slice(
|
||||
currentToolUseStart, // From after the tool opening tag.
|
||||
currentToolDirectiveStart, // From after the tool opening tag.
|
||||
currentCharIndex - toolCloseTag.length + 1, // To before the tool closing tag.
|
||||
)
|
||||
|
||||
|
|
@ -134,8 +134,8 @@ export function parseAssistantMessageV2(assistantMessage: string): AssistantMess
|
|||
// empty or parsing logic prioritizes tool close).
|
||||
const contentParamName: ToolParamName = "content"
|
||||
if (
|
||||
currentToolUse.name === "write_to_file" /* || currentToolUse.name === "new_rule" */ &&
|
||||
// !(contentParamName in currentToolUse.params) && // Only if not already parsed.
|
||||
currentToolDirective.name === "write_to_file" /* || currentToolDirective.name === "new_rule" */ &&
|
||||
// !(contentParamName in currentToolDirective.params) && // Only if not already parsed.
|
||||
toolContentSlice.includes(`<${contentParamName}>`) // Check if tag exists.
|
||||
) {
|
||||
const contentStartTag = `<${contentParamName}>`
|
||||
|
|
@ -150,13 +150,13 @@ export function parseAssistantMessageV2(assistantMessage: string): AssistantMess
|
|||
.slice(contentStart + contentStartTag.length, contentEnd)
|
||||
.trim()
|
||||
|
||||
currentToolUse.params[contentParamName] = contentValue
|
||||
currentToolDirective.params[contentParamName] = contentValue
|
||||
}
|
||||
}
|
||||
|
||||
currentToolUse.partial = false // Mark as complete.
|
||||
contentBlocks.push(currentToolUse)
|
||||
currentToolUse = undefined // Reset state.
|
||||
currentToolDirective.partial = false // Mark as complete.
|
||||
contentBlocks.push(currentToolDirective)
|
||||
currentToolDirective = undefined // Reset state.
|
||||
currentTextContentStart = currentCharIndex + 1 // Potential text starts after this tag.
|
||||
continue // Move to next char.
|
||||
}
|
||||
|
|
@ -167,11 +167,11 @@ export function parseAssistantMessageV2(assistantMessage: string): AssistantMess
|
|||
}
|
||||
|
||||
// Parsing text / looking for tool start.
|
||||
if (!currentToolUse) {
|
||||
if (!currentToolDirective) {
|
||||
// Check if starting a new tool use.
|
||||
let startedNewTool = false
|
||||
|
||||
for (const [tag, toolName] of toolUseOpenTags.entries()) {
|
||||
for (const [tag, toolName] of ToolDirectiveOpenTags.entries()) {
|
||||
if (
|
||||
currentCharIndex >= tag.length - 1 &&
|
||||
assistantMessage.startsWith(tag, currentCharIndex - tag.length + 1)
|
||||
|
|
@ -211,14 +211,14 @@ export function parseAssistantMessageV2(assistantMessage: string): AssistantMess
|
|||
}
|
||||
|
||||
// Start the new tool use.
|
||||
currentToolUse = {
|
||||
currentToolDirective = {
|
||||
type: "tool_use",
|
||||
name: toolName,
|
||||
params: {},
|
||||
partial: true, // Assume partial until closing tag is found.
|
||||
}
|
||||
|
||||
currentToolUseStart = currentCharIndex + 1 // Tool content starts after the opening tag.
|
||||
currentToolDirectiveStart = currentCharIndex + 1 // Tool content starts after the opening tag.
|
||||
startedNewTool = true
|
||||
|
||||
break
|
||||
|
|
@ -250,17 +250,17 @@ export function parseAssistantMessageV2(assistantMessage: string): AssistantMess
|
|||
}
|
||||
|
||||
// Finalize any open parameter within an open tool use.
|
||||
if (currentToolUse && currentParamName) {
|
||||
currentToolUse.params[currentParamName] = assistantMessage
|
||||
if (currentToolDirective && currentParamName) {
|
||||
currentToolDirective.params[currentParamName] = assistantMessage
|
||||
.slice(currentParamValueStart) // From param start to end of string.
|
||||
.trim()
|
||||
// Tool use remains partial.
|
||||
}
|
||||
|
||||
// Finalize any open tool use (which might contain the finalized partial param).
|
||||
if (currentToolUse) {
|
||||
if (currentToolDirective) {
|
||||
// Tool use is partial because the loop finished before its closing tag.
|
||||
contentBlocks.push(currentToolUse)
|
||||
contentBlocks.push(currentToolDirective)
|
||||
}
|
||||
// Finalize any trailing text content.
|
||||
// Only possible if a tool use wasn't open at the very end.
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ import { SYSTEM_PROMPT } from "../prompts/system"
|
|||
import { ToolRepetitionDetector } from "../tools/ToolRepetitionDetector"
|
||||
import { FileContextTracker } from "../context-tracking/FileContextTracker"
|
||||
import { RooIgnoreController } from "../ignore/RooIgnoreController"
|
||||
import { presentAssistantMessage } from "../assistant-message"
|
||||
import { presentAssistantMessage } from "../message-parsing"
|
||||
import { truncateConversationIfNeeded } from "../sliding-window"
|
||||
import { ClineProvider } from "../webview/ClineProvider"
|
||||
import { MultiSearchReplaceDiffStrategy } from "../diff/strategies/multi-search-replace"
|
||||
|
|
@ -85,8 +85,7 @@ import { ApiMessage } from "../task-persistence/apiMessages"
|
|||
import { getMessagesSinceLastSummary, summarizeConversation } from "../condense"
|
||||
import { maybeRemoveImageBlocks } from "../../api/transform/image-cleaning"
|
||||
import { LogManager } from "../logging"
|
||||
import { Directive } from "../assistant-message"
|
||||
import { DirectiveStreamingParser } from "../assistant-message"
|
||||
import { Directive, DirectiveStreamingParser } from "../message-parsing"
|
||||
|
||||
export type ClineEvents = {
|
||||
message: [{ action: "created" | "updated"; message: ClineMessage }]
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { ToolUse } from "../../shared/tools"
|
||||
import { t } from "../../i18n"
|
||||
import { ToolDirective } from "../message-parsing/directives"
|
||||
|
||||
/**
|
||||
* Class for detecting consecutive identical tool calls
|
||||
|
|
@ -22,10 +22,10 @@ export class ToolRepetitionDetector {
|
|||
* Checks if the current tool call is identical to the previous one
|
||||
* and determines if execution should be allowed
|
||||
*
|
||||
* @param currentToolCallBlock ToolUse object representing the current tool call
|
||||
* @param currentToolCallBlock ToolDirective object representing the current tool call
|
||||
* @returns Object indicating if execution is allowed and a message to show if not
|
||||
*/
|
||||
public check(currentToolCallBlock: ToolUse): {
|
||||
public check(currentToolCallBlock: ToolDirective): {
|
||||
allowExecution: boolean
|
||||
askUser?: {
|
||||
messageKey: string
|
||||
|
|
@ -33,7 +33,7 @@ export class ToolRepetitionDetector {
|
|||
}
|
||||
} {
|
||||
// Serialize the block to a canonical JSON string for comparison
|
||||
const currentToolCallJson = this.serializeToolUse(currentToolCallBlock)
|
||||
const currentToolCallJson = this.serializeToolDirective(currentToolCallBlock)
|
||||
|
||||
// Compare with previous tool call
|
||||
if (this.previousToolCallJson === currentToolCallJson) {
|
||||
|
|
@ -64,28 +64,28 @@ export class ToolRepetitionDetector {
|
|||
}
|
||||
|
||||
/**
|
||||
* Serializes a ToolUse object into a canonical JSON string for comparison
|
||||
* Serializes a ToolDirective object into a canonical JSON string for comparison
|
||||
*
|
||||
* @param toolUse The ToolUse object to serialize
|
||||
* @param ToolDirective The ToolDirective object to serialize
|
||||
* @returns JSON string representation of the tool use with sorted parameter keys
|
||||
*/
|
||||
private serializeToolUse(toolUse: ToolUse): string {
|
||||
private serializeToolDirective(ToolDirective: ToolDirective): string {
|
||||
// Create a new parameters object with alphabetically sorted keys
|
||||
const sortedParams: Record<string, unknown> = {}
|
||||
|
||||
// Get parameter keys and sort them alphabetically
|
||||
const sortedKeys = Object.keys(toolUse.params).sort()
|
||||
const sortedKeys = Object.keys(ToolDirective.params).sort()
|
||||
|
||||
// Populate the sorted parameters object in a type-safe way
|
||||
for (const key of sortedKeys) {
|
||||
if (Object.prototype.hasOwnProperty.call(toolUse.params, key)) {
|
||||
sortedParams[key] = toolUse.params[key as keyof typeof toolUse.params]
|
||||
if (Object.prototype.hasOwnProperty.call(ToolDirective.params, key)) {
|
||||
sortedParams[key] = ToolDirective.params[key as keyof typeof ToolDirective.params]
|
||||
}
|
||||
}
|
||||
|
||||
// Create the object with the tool name and sorted parameters
|
||||
const toolObject = {
|
||||
name: toolUse.name,
|
||||
name: ToolDirective.name,
|
||||
parameters: sortedParams,
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,9 +3,8 @@
|
|||
import { vitest, describe, it, expect } from "vitest"
|
||||
import type { ToolName } from "@roo-code/types"
|
||||
|
||||
import type { ToolUse } from "../../../shared/tools"
|
||||
|
||||
import { ToolRepetitionDetector } from "../ToolRepetitionDetector"
|
||||
import { ToolDirective } from "../../message-parsing/directives"
|
||||
|
||||
vitest.mock("../../../i18n", () => ({
|
||||
t: vitest.fn((key, options) => {
|
||||
|
|
@ -17,7 +16,7 @@ vitest.mock("../../../i18n", () => ({
|
|||
}),
|
||||
}))
|
||||
|
||||
function createToolUse(name: string, displayName?: string, params: Record<string, string> = {}): ToolUse {
|
||||
function createToolDirective(name: string, displayName?: string, params: Record<string, string> = {}): ToolDirective {
|
||||
return {
|
||||
type: "tool_use",
|
||||
name: (displayName || name) as ToolName,
|
||||
|
|
@ -34,15 +33,15 @@ describe("ToolRepetitionDetector", () => {
|
|||
// We'll verify this through behavior in subsequent tests
|
||||
|
||||
// First call (counter = 1)
|
||||
const result1 = detector.check(createToolUse("test", "test-tool"))
|
||||
const result1 = detector.check(createToolDirective("test", "test-tool"))
|
||||
expect(result1.allowExecution).toBe(true)
|
||||
|
||||
// Second identical call (counter = 2)
|
||||
const result2 = detector.check(createToolUse("test", "test-tool"))
|
||||
const result2 = detector.check(createToolDirective("test", "test-tool"))
|
||||
expect(result2.allowExecution).toBe(true)
|
||||
|
||||
// Third identical call (counter = 3) reaches the default limit
|
||||
const result3 = detector.check(createToolUse("test", "test-tool"))
|
||||
const result3 = detector.check(createToolDirective("test", "test-tool"))
|
||||
expect(result3.allowExecution).toBe(false)
|
||||
})
|
||||
|
||||
|
|
@ -51,11 +50,11 @@ describe("ToolRepetitionDetector", () => {
|
|||
const detector = new ToolRepetitionDetector(customLimit)
|
||||
|
||||
// First call (counter = 1)
|
||||
const result1 = detector.check(createToolUse("test", "test-tool"))
|
||||
const result1 = detector.check(createToolDirective("test", "test-tool"))
|
||||
expect(result1.allowExecution).toBe(true)
|
||||
|
||||
// Second identical call (counter = 2) reaches the custom limit
|
||||
const result2 = detector.check(createToolUse("test", "test-tool"))
|
||||
const result2 = detector.check(createToolDirective("test", "test-tool"))
|
||||
expect(result2.allowExecution).toBe(false)
|
||||
})
|
||||
})
|
||||
|
|
@ -65,15 +64,15 @@ describe("ToolRepetitionDetector", () => {
|
|||
it("should allow execution for different tool calls", () => {
|
||||
const detector = new ToolRepetitionDetector()
|
||||
|
||||
const result1 = detector.check(createToolUse("first", "first-tool"))
|
||||
const result1 = detector.check(createToolDirective("first", "first-tool"))
|
||||
expect(result1.allowExecution).toBe(true)
|
||||
expect(result1.askUser).toBeUndefined()
|
||||
|
||||
const result2 = detector.check(createToolUse("second", "second-tool"))
|
||||
const result2 = detector.check(createToolDirective("second", "second-tool"))
|
||||
expect(result2.allowExecution).toBe(true)
|
||||
expect(result2.askUser).toBeUndefined()
|
||||
|
||||
const result3 = detector.check(createToolUse("third", "third-tool"))
|
||||
const result3 = detector.check(createToolDirective("third", "third-tool"))
|
||||
expect(result3.allowExecution).toBe(true)
|
||||
expect(result3.askUser).toBeUndefined()
|
||||
})
|
||||
|
|
@ -82,13 +81,13 @@ describe("ToolRepetitionDetector", () => {
|
|||
const detector = new ToolRepetitionDetector(2)
|
||||
|
||||
// First call
|
||||
detector.check(createToolUse("same", "same-tool"))
|
||||
detector.check(createToolDirective("same", "same-tool"))
|
||||
|
||||
// Second identical call would reach limit of 2, but we'll make a different call
|
||||
detector.check(createToolUse("different", "different-tool"))
|
||||
detector.check(createToolDirective("different", "different-tool"))
|
||||
|
||||
// Back to the first tool - should be allowed since counter was reset
|
||||
const result = detector.check(createToolUse("same", "same-tool"))
|
||||
const result = detector.check(createToolDirective("same", "same-tool"))
|
||||
expect(result.allowExecution).toBe(true)
|
||||
})
|
||||
})
|
||||
|
|
@ -99,15 +98,15 @@ describe("ToolRepetitionDetector", () => {
|
|||
const detector = new ToolRepetitionDetector(3)
|
||||
|
||||
// First call (counter = 1)
|
||||
const result1 = detector.check(createToolUse("repeat", "repeat-tool"))
|
||||
const result1 = detector.check(createToolDirective("repeat", "repeat-tool"))
|
||||
expect(result1.allowExecution).toBe(true)
|
||||
|
||||
// Second identical call (counter = 2)
|
||||
const result2 = detector.check(createToolUse("repeat", "repeat-tool"))
|
||||
const result2 = detector.check(createToolDirective("repeat", "repeat-tool"))
|
||||
expect(result2.allowExecution).toBe(true)
|
||||
|
||||
// Third identical call (counter = 3) reaches limit
|
||||
const result3 = detector.check(createToolUse("repeat", "repeat-tool"))
|
||||
const result3 = detector.check(createToolDirective("repeat", "repeat-tool"))
|
||||
expect(result3.allowExecution).toBe(false)
|
||||
})
|
||||
})
|
||||
|
|
@ -118,13 +117,13 @@ describe("ToolRepetitionDetector", () => {
|
|||
const detector = new ToolRepetitionDetector(3)
|
||||
|
||||
// First call (counter = 1)
|
||||
detector.check(createToolUse("repeat", "repeat-tool"))
|
||||
detector.check(createToolDirective("repeat", "repeat-tool"))
|
||||
|
||||
// Second identical call (counter = 2)
|
||||
detector.check(createToolUse("repeat", "repeat-tool"))
|
||||
detector.check(createToolDirective("repeat", "repeat-tool"))
|
||||
|
||||
// Third identical call (counter = 3) - should reach limit
|
||||
const result = detector.check(createToolUse("repeat", "repeat-tool"))
|
||||
const result = detector.check(createToolDirective("repeat", "repeat-tool"))
|
||||
|
||||
expect(result.allowExecution).toBe(false)
|
||||
expect(result.askUser).toBeDefined()
|
||||
|
|
@ -136,12 +135,12 @@ describe("ToolRepetitionDetector", () => {
|
|||
const detector = new ToolRepetitionDetector(2)
|
||||
|
||||
// Reach the limit
|
||||
detector.check(createToolUse("repeat", "repeat-tool"))
|
||||
const limitResult = detector.check(createToolUse("repeat", "repeat-tool")) // This reaches limit
|
||||
detector.check(createToolDirective("repeat", "repeat-tool"))
|
||||
const limitResult = detector.check(createToolDirective("repeat", "repeat-tool")) // This reaches limit
|
||||
expect(limitResult.allowExecution).toBe(false)
|
||||
|
||||
// Use a new tool call - should be allowed since state was reset
|
||||
const result = detector.check(createToolUse("new", "new-tool"))
|
||||
const result = detector.check(createToolDirective("new", "new-tool"))
|
||||
expect(result.allowExecution).toBe(true)
|
||||
})
|
||||
})
|
||||
|
|
@ -152,12 +151,12 @@ describe("ToolRepetitionDetector", () => {
|
|||
const detector = new ToolRepetitionDetector(2)
|
||||
|
||||
// Reach the limit with a specific tool
|
||||
detector.check(createToolUse("problem", "problem-tool"))
|
||||
const limitResult = detector.check(createToolUse("problem", "problem-tool")) // This reaches limit
|
||||
detector.check(createToolDirective("problem", "problem-tool"))
|
||||
const limitResult = detector.check(createToolDirective("problem", "problem-tool")) // This reaches limit
|
||||
expect(limitResult.allowExecution).toBe(false)
|
||||
|
||||
// The same tool that previously caused problems should now be allowed
|
||||
const result = detector.check(createToolUse("problem", "problem-tool"))
|
||||
const result = detector.check(createToolDirective("problem", "problem-tool"))
|
||||
expect(result.allowExecution).toBe(true)
|
||||
})
|
||||
|
||||
|
|
@ -165,15 +164,15 @@ describe("ToolRepetitionDetector", () => {
|
|||
const detector = new ToolRepetitionDetector(2)
|
||||
|
||||
// Reach the limit
|
||||
detector.check(createToolUse("repeat", "repeat-tool"))
|
||||
const limitResult = detector.check(createToolUse("repeat", "repeat-tool")) // This reaches limit
|
||||
detector.check(createToolDirective("repeat", "repeat-tool"))
|
||||
const limitResult = detector.check(createToolDirective("repeat", "repeat-tool")) // This reaches limit
|
||||
expect(limitResult.allowExecution).toBe(false)
|
||||
|
||||
// First call after reset
|
||||
detector.check(createToolUse("repeat", "repeat-tool"))
|
||||
detector.check(createToolDirective("repeat", "repeat-tool"))
|
||||
|
||||
// Second identical call (counter = 2) should reach limit again
|
||||
const result = detector.check(createToolUse("repeat", "repeat-tool"))
|
||||
const result = detector.check(createToolDirective("repeat", "repeat-tool"))
|
||||
expect(result.allowExecution).toBe(false)
|
||||
expect(result.askUser).toBeDefined()
|
||||
})
|
||||
|
|
@ -186,8 +185,8 @@ describe("ToolRepetitionDetector", () => {
|
|||
const toolName = "special-tool-name"
|
||||
|
||||
// Reach the limit
|
||||
detector.check(createToolUse("test", toolName))
|
||||
const result = detector.check(createToolUse("test", toolName))
|
||||
detector.check(createToolDirective("test", toolName))
|
||||
const result = detector.check(createToolDirective("test", toolName))
|
||||
|
||||
expect(result.allowExecution).toBe(false)
|
||||
expect(result.askUser?.messageDetail).toContain(toolName)
|
||||
|
|
@ -201,8 +200,8 @@ describe("ToolRepetitionDetector", () => {
|
|||
|
||||
// Create an empty tool call - a tool with no parameters
|
||||
// Use the empty tool directly in the check calls
|
||||
detector.check(createToolUse("empty-tool", "empty-tool"))
|
||||
const result = detector.check(createToolUse("empty-tool"))
|
||||
detector.check(createToolDirective("empty-tool", "empty-tool"))
|
||||
const result = detector.check(createToolDirective("empty-tool"))
|
||||
|
||||
expect(result.allowExecution).toBe(false)
|
||||
expect(result.askUser).toBeDefined()
|
||||
|
|
@ -212,28 +211,28 @@ describe("ToolRepetitionDetector", () => {
|
|||
const detector = new ToolRepetitionDetector(2)
|
||||
|
||||
// First, call with tool-name-1 twice to set up the counter
|
||||
const toolUse1 = createToolUse("tool-name-1", "tool-name-1", { param: "value" })
|
||||
detector.check(toolUse1)
|
||||
const ToolDirective1 = createToolDirective("tool-name-1", "tool-name-1", { param: "value" })
|
||||
detector.check(ToolDirective1)
|
||||
|
||||
// Create a tool that will serialize to the same JSON as toolUse1
|
||||
// We need to mock the serializeToolUse method to return the same value
|
||||
const toolUse2 = createToolUse("tool-name-2", "tool-name-2", { param: "value" })
|
||||
// Create a tool that will serialize to the same JSON as ToolDirective1
|
||||
// We need to mock the serializeToolDirective method to return the same value
|
||||
const ToolDirective2 = createToolDirective("tool-name-2", "tool-name-2", { param: "value" })
|
||||
|
||||
// Override the private method to force identical serialization
|
||||
const originalSerialize = (detector as any).serializeToolUse
|
||||
;(detector as any).serializeToolUse = (tool: ToolUse) => {
|
||||
const originalSerialize = (detector as any).serializeToolDirective
|
||||
;(detector as any).serializeToolDirective = (tool: ToolDirective) => {
|
||||
// Use string comparison for the name since it's technically an enum
|
||||
if (String(tool.name) === "tool-name-2") {
|
||||
return (detector as any).serializeToolUse(toolUse1) // Return the same JSON as toolUse1
|
||||
return (detector as any).serializeToolDirective(ToolDirective1) // Return the same JSON as ToolDirective1
|
||||
}
|
||||
return originalSerialize(tool)
|
||||
}
|
||||
|
||||
// This should detect as a repetition now
|
||||
const result = detector.check(toolUse2)
|
||||
const result = detector.check(ToolDirective2)
|
||||
|
||||
// Restore the original method
|
||||
;(detector as any).serializeToolUse = originalSerialize
|
||||
;(detector as any).serializeToolDirective = originalSerialize
|
||||
|
||||
// Since we're directly manipulating the internal state for testing,
|
||||
// we still expect it to consider this a repetition
|
||||
|
|
@ -245,14 +244,14 @@ describe("ToolRepetitionDetector", () => {
|
|||
const detector = new ToolRepetitionDetector(2)
|
||||
|
||||
// First call with parameters in one order
|
||||
const toolUse1 = createToolUse("same-tool", "same-tool", { a: "1", b: "2", c: "3" })
|
||||
detector.check(toolUse1)
|
||||
const ToolDirective1 = createToolDirective("same-tool", "same-tool", { a: "1", b: "2", c: "3" })
|
||||
detector.check(ToolDirective1)
|
||||
|
||||
// Create tool with same parameters but in different order
|
||||
const toolUse2 = createToolUse("same-tool", "same-tool", { c: "3", a: "1", b: "2" })
|
||||
const ToolDirective2 = createToolDirective("same-tool", "same-tool", { c: "3", a: "1", b: "2" })
|
||||
|
||||
// This should still detect as a repetition due to canonical JSON with sorted keys
|
||||
const result = detector.check(toolUse2)
|
||||
const result = detector.check(ToolDirective2)
|
||||
|
||||
// Since parameters are sorted alphabetically in the serialized JSON,
|
||||
// these should be considered identical
|
||||
|
|
@ -267,7 +266,7 @@ describe("ToolRepetitionDetector", () => {
|
|||
const detector = new ToolRepetitionDetector(1)
|
||||
|
||||
// First call (counter = 1) should be blocked
|
||||
const result = detector.check(createToolUse("tool", "tool-name"))
|
||||
const result = detector.check(createToolDirective("tool", "tool-name"))
|
||||
|
||||
expect(result.allowExecution).toBe(false)
|
||||
expect(result.askUser).toBeDefined()
|
||||
|
|
@ -277,11 +276,11 @@ describe("ToolRepetitionDetector", () => {
|
|||
const detector = new ToolRepetitionDetector(2)
|
||||
|
||||
// First call (counter = 1)
|
||||
const result1 = detector.check(createToolUse("tool", "tool-name"))
|
||||
const result1 = detector.check(createToolDirective("tool", "tool-name"))
|
||||
expect(result1.allowExecution).toBe(true)
|
||||
|
||||
// Second call (counter = 2) should be blocked
|
||||
const result2 = detector.check(createToolUse("tool", "tool-name"))
|
||||
const result2 = detector.check(createToolDirective("tool", "tool-name"))
|
||||
expect(result2.allowExecution).toBe(false)
|
||||
expect(result2.askUser).toBeDefined()
|
||||
})
|
||||
|
|
@ -290,15 +289,15 @@ describe("ToolRepetitionDetector", () => {
|
|||
const detector = new ToolRepetitionDetector(3)
|
||||
|
||||
// First call (counter = 1)
|
||||
const result1 = detector.check(createToolUse("tool", "tool-name"))
|
||||
const result1 = detector.check(createToolDirective("tool", "tool-name"))
|
||||
expect(result1.allowExecution).toBe(true)
|
||||
|
||||
// Second call (counter = 2)
|
||||
const result2 = detector.check(createToolUse("tool", "tool-name"))
|
||||
const result2 = detector.check(createToolDirective("tool", "tool-name"))
|
||||
expect(result2.allowExecution).toBe(true)
|
||||
|
||||
// Third call (counter = 3) should be blocked
|
||||
const result3 = detector.check(createToolUse("tool", "tool-name"))
|
||||
const result3 = detector.check(createToolDirective("tool", "tool-name"))
|
||||
expect(result3.allowExecution).toBe(false)
|
||||
expect(result3.askUser).toBeDefined()
|
||||
})
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import type { ToolUsage } from "@roo-code/types"
|
|||
|
||||
import { Task } from "../../task/Task"
|
||||
import { formatResponse } from "../../prompts/responses"
|
||||
import { ToolUse, AskApproval, HandleError, PushToolResult, RemoveClosingTag } from "../../../shared/tools"
|
||||
import { AskApproval, HandleError, PushToolResult, RemoveClosingTag } from "../../../shared/tools"
|
||||
import { unescapeHtmlEntities } from "../../../utils/text-normalization"
|
||||
|
||||
// Mock dependencies
|
||||
|
|
@ -27,6 +27,7 @@ vitest.mock("../executeCommandTool")
|
|||
|
||||
// Import after mocking
|
||||
import { executeCommandTool } from "../executeCommandTool"
|
||||
import { ToolDirective } from "../../message-parsing/directives"
|
||||
|
||||
// Now manually restore and mock the functions
|
||||
beforeEach(() => {
|
||||
|
|
@ -79,7 +80,7 @@ describe("executeCommandTool", () => {
|
|||
let mockHandleError: any
|
||||
let mockPushToolResult: any
|
||||
let mockRemoveClosingTag: any
|
||||
let mockToolUse: ToolUse
|
||||
let mockToolDirective: ToolDirective
|
||||
|
||||
beforeEach(() => {
|
||||
// Reset mocks
|
||||
|
|
@ -106,7 +107,7 @@ describe("executeCommandTool", () => {
|
|||
mockRemoveClosingTag = vitest.fn().mockReturnValue("command")
|
||||
|
||||
// Create a mock tool use object
|
||||
mockToolUse = {
|
||||
mockToolDirective = {
|
||||
type: "tool_use",
|
||||
name: "execute_command",
|
||||
params: {
|
||||
|
|
@ -150,12 +151,12 @@ describe("executeCommandTool", () => {
|
|||
describe("Basic functionality", () => {
|
||||
it("should execute a command normally", async () => {
|
||||
// Setup
|
||||
mockToolUse.params.command = "echo test"
|
||||
mockToolDirective.params.command = "echo test"
|
||||
|
||||
// Execute
|
||||
await executeCommandTool(
|
||||
mockCline as unknown as Task,
|
||||
mockToolUse,
|
||||
mockToolDirective,
|
||||
mockAskApproval as unknown as AskApproval,
|
||||
mockHandleError as unknown as HandleError,
|
||||
mockPushToolResult as unknown as PushToolResult,
|
||||
|
|
@ -170,13 +171,13 @@ describe("executeCommandTool", () => {
|
|||
|
||||
it("should pass along custom working directory if provided", async () => {
|
||||
// Setup
|
||||
mockToolUse.params.command = "echo test"
|
||||
mockToolUse.params.cwd = "/custom/path"
|
||||
mockToolDirective.params.command = "echo test"
|
||||
mockToolDirective.params.cwd = "/custom/path"
|
||||
|
||||
// Execute
|
||||
await executeCommandTool(
|
||||
mockCline as unknown as Task,
|
||||
mockToolUse,
|
||||
mockToolDirective,
|
||||
mockAskApproval as unknown as AskApproval,
|
||||
mockHandleError as unknown as HandleError,
|
||||
mockPushToolResult as unknown as PushToolResult,
|
||||
|
|
@ -194,12 +195,12 @@ describe("executeCommandTool", () => {
|
|||
describe("Error handling", () => {
|
||||
it("should handle missing command parameter", async () => {
|
||||
// Setup
|
||||
mockToolUse.params.command = undefined
|
||||
mockToolDirective.params.command = undefined
|
||||
|
||||
// Execute
|
||||
await executeCommandTool(
|
||||
mockCline as unknown as Task,
|
||||
mockToolUse,
|
||||
mockToolDirective,
|
||||
mockAskApproval as unknown as AskApproval,
|
||||
mockHandleError as unknown as HandleError,
|
||||
mockPushToolResult as unknown as PushToolResult,
|
||||
|
|
@ -216,13 +217,13 @@ describe("executeCommandTool", () => {
|
|||
|
||||
it("should handle command rejection", async () => {
|
||||
// Setup
|
||||
mockToolUse.params.command = "echo test"
|
||||
mockToolDirective.params.command = "echo test"
|
||||
mockAskApproval.mockResolvedValue(false)
|
||||
|
||||
// Execute
|
||||
await executeCommandTool(
|
||||
mockCline as unknown as Task,
|
||||
mockToolUse,
|
||||
mockToolDirective,
|
||||
mockAskApproval as unknown as AskApproval,
|
||||
mockHandleError as unknown as HandleError,
|
||||
mockPushToolResult as unknown as PushToolResult,
|
||||
|
|
@ -237,7 +238,7 @@ describe("executeCommandTool", () => {
|
|||
|
||||
it("should handle rooignore validation failures", async () => {
|
||||
// Setup
|
||||
mockToolUse.params.command = "cat .env"
|
||||
mockToolDirective.params.command = "cat .env"
|
||||
// Override the validateCommand mock to return a filename
|
||||
const validateCommandMock = vitest.fn().mockReturnValue(".env")
|
||||
mockCline.rooIgnoreController = {
|
||||
|
|
@ -251,7 +252,7 @@ describe("executeCommandTool", () => {
|
|||
// Execute
|
||||
await executeCommandTool(
|
||||
mockCline as unknown as Task,
|
||||
mockToolUse,
|
||||
mockToolDirective,
|
||||
mockAskApproval as unknown as AskApproval,
|
||||
mockHandleError as unknown as HandleError,
|
||||
mockPushToolResult as unknown as PushToolResult,
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ jest.mock("../../prompts/responses", () => ({
|
|||
|
||||
// Import the function to test AFTER mocks are set up
|
||||
import { newTaskTool } from "../newTaskTool"
|
||||
import type { ToolUse } from "../../../shared/tools"
|
||||
import { ToolDirective } from "../../message-parsing/directives"
|
||||
|
||||
describe("newTaskTool", () => {
|
||||
beforeEach(() => {
|
||||
|
|
@ -65,7 +65,7 @@ describe("newTaskTool", () => {
|
|||
})
|
||||
|
||||
it("should correctly un-escape \\\\@ to \\@ in the message passed to the new task", async () => {
|
||||
const block: ToolUse = {
|
||||
const block: ToolDirective = {
|
||||
type: "tool_use", // Add required 'type' property
|
||||
name: "new_task", // Correct property name
|
||||
params: {
|
||||
|
|
@ -102,7 +102,7 @@ describe("newTaskTool", () => {
|
|||
})
|
||||
|
||||
it("should not un-escape single escaped \@", async () => {
|
||||
const block: ToolUse = {
|
||||
const block: ToolDirective = {
|
||||
type: "tool_use", // Add required 'type' property
|
||||
name: "new_task", // Correct property name
|
||||
params: {
|
||||
|
|
@ -129,7 +129,7 @@ describe("newTaskTool", () => {
|
|||
})
|
||||
|
||||
it("should not un-escape non-escaped @", async () => {
|
||||
const block: ToolUse = {
|
||||
const block: ToolDirective = {
|
||||
type: "tool_use", // Add required 'type' property
|
||||
name: "new_task", // Correct property name
|
||||
params: {
|
||||
|
|
@ -156,7 +156,7 @@ describe("newTaskTool", () => {
|
|||
})
|
||||
|
||||
it("should handle mixed escaping scenarios", async () => {
|
||||
const block: ToolUse = {
|
||||
const block: ToolDirective = {
|
||||
type: "tool_use", // Add required 'type' property
|
||||
name: "new_task", // Correct property name
|
||||
params: {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import { readLines } from "../../../integrations/misc/read-lines"
|
|||
import { extractTextFromFile } from "../../../integrations/misc/extract-text"
|
||||
import { parseSourceCodeDefinitionsForFile } from "../../../services/tree-sitter"
|
||||
import { isBinaryFile } from "isbinaryfile"
|
||||
import { ReadFileToolUse, ToolParamName, ToolResponse } from "../../../shared/tools"
|
||||
import { ReadFileToolDirective, ToolParamName, ToolResponse } from "../../../shared/tools"
|
||||
import { readFileTool } from "../readFileTool"
|
||||
import { formatResponse } from "../../prompts/responses"
|
||||
|
||||
|
|
@ -144,7 +144,7 @@ describe("read_file tool with maxReadFileLine setting", () => {
|
|||
* Helper function to execute the read file tool with different maxReadFileLine settings
|
||||
*/
|
||||
async function executeReadFileTool(
|
||||
params: Partial<ReadFileToolUse["params"]> = {},
|
||||
params: Partial<ReadFileToolDirective["params"]> = {},
|
||||
options: {
|
||||
maxReadFileLine?: number
|
||||
totalLines?: number
|
||||
|
|
@ -172,7 +172,7 @@ describe("read_file tool with maxReadFileLine setting", () => {
|
|||
argsContent += `</file>`
|
||||
|
||||
// Create a tool use object
|
||||
const toolUse: ReadFileToolUse = {
|
||||
const toolUse: ReadFileToolDirective = {
|
||||
type: "tool_use",
|
||||
name: "read_file",
|
||||
params: { args: argsContent, ...params },
|
||||
|
|
@ -484,7 +484,7 @@ describe("read_file tool XML output structure", () => {
|
|||
argsContent += `</file>`
|
||||
|
||||
// Create a tool use object
|
||||
const toolUse: ReadFileToolUse = {
|
||||
const toolUse: ReadFileToolDirective = {
|
||||
type: "tool_use",
|
||||
name: "read_file",
|
||||
params: { args: argsContent, ...params },
|
||||
|
|
@ -898,7 +898,7 @@ describe("read_file tool XML output structure", () => {
|
|||
|
||||
it("should include error tag for invalid path", async () => {
|
||||
// Setup - missing path parameter
|
||||
const toolUse: ReadFileToolUse = {
|
||||
const toolUse: ReadFileToolDirective = {
|
||||
type: "tool_use",
|
||||
name: "read_file",
|
||||
params: {},
|
||||
|
|
@ -1167,7 +1167,7 @@ describe("read_file tool XML output structure", () => {
|
|||
const mockRemoveClosingTag = jest.fn((tag, content) => content)
|
||||
|
||||
// Create a tool use object directly
|
||||
const toolUse: ReadFileToolUse = {
|
||||
const toolUse: ReadFileToolDirective = {
|
||||
type: "tool_use",
|
||||
name: "read_file",
|
||||
params: {
|
||||
|
|
@ -1207,7 +1207,7 @@ describe("read_file tool XML output structure", () => {
|
|||
const mockRemoveClosingTag = jest.fn((tag, content) => content)
|
||||
|
||||
// Create a tool use object directly
|
||||
const toolUse: ReadFileToolUse = {
|
||||
const toolUse: ReadFileToolDirective = {
|
||||
type: "tool_use",
|
||||
name: "read_file",
|
||||
params: {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { useMcpToolTool } from "../useMcpToolTool"
|
||||
import { Task } from "../../task/Task"
|
||||
import { ToolUse } from "../../../shared/tools"
|
||||
import { formatResponse } from "../../prompts/responses"
|
||||
import { ToolDirective } from "../../message-parsing/directives"
|
||||
|
||||
// Mock dependencies
|
||||
jest.mock("../../prompts/responses", () => ({
|
||||
|
|
@ -57,7 +57,7 @@ describe("useMcpToolTool", () => {
|
|||
|
||||
describe("parameter validation", () => {
|
||||
it("should handle missing server_name", async () => {
|
||||
const block: ToolUse = {
|
||||
const block: ToolDirective = {
|
||||
type: "tool_use",
|
||||
name: "use_mcp_tool",
|
||||
params: {
|
||||
|
|
@ -85,7 +85,7 @@ describe("useMcpToolTool", () => {
|
|||
})
|
||||
|
||||
it("should handle missing tool_name", async () => {
|
||||
const block: ToolUse = {
|
||||
const block: ToolDirective = {
|
||||
type: "tool_use",
|
||||
name: "use_mcp_tool",
|
||||
params: {
|
||||
|
|
@ -113,7 +113,7 @@ describe("useMcpToolTool", () => {
|
|||
})
|
||||
|
||||
it("should handle invalid JSON arguments", async () => {
|
||||
const block: ToolUse = {
|
||||
const block: ToolDirective = {
|
||||
type: "tool_use",
|
||||
name: "use_mcp_tool",
|
||||
params: {
|
||||
|
|
@ -142,7 +142,7 @@ describe("useMcpToolTool", () => {
|
|||
|
||||
describe("partial requests", () => {
|
||||
it("should handle partial requests", async () => {
|
||||
const block: ToolUse = {
|
||||
const block: ToolDirective = {
|
||||
type: "tool_use",
|
||||
name: "use_mcp_tool",
|
||||
params: {
|
||||
|
|
@ -170,7 +170,7 @@ describe("useMcpToolTool", () => {
|
|||
|
||||
describe("successful execution", () => {
|
||||
it("should execute tool successfully with valid parameters", async () => {
|
||||
const block: ToolUse = {
|
||||
const block: ToolDirective = {
|
||||
type: "tool_use",
|
||||
name: "use_mcp_tool",
|
||||
params: {
|
||||
|
|
@ -212,7 +212,7 @@ describe("useMcpToolTool", () => {
|
|||
})
|
||||
|
||||
it("should handle user rejection", async () => {
|
||||
const block: ToolUse = {
|
||||
const block: ToolDirective = {
|
||||
type: "tool_use",
|
||||
name: "use_mcp_tool",
|
||||
params: {
|
||||
|
|
@ -241,7 +241,7 @@ describe("useMcpToolTool", () => {
|
|||
|
||||
describe("error handling", () => {
|
||||
it("should handle unexpected errors", async () => {
|
||||
const block: ToolUse = {
|
||||
const block: ToolDirective = {
|
||||
type: "tool_use",
|
||||
name: "use_mcp_tool",
|
||||
params: {
|
||||
|
|
|
|||
|
|
@ -6,8 +6,9 @@ import { isPathOutsideWorkspace } from "../../../utils/pathUtils"
|
|||
import { getReadablePath } from "../../../utils/path"
|
||||
import { unescapeHtmlEntities } from "../../../utils/text-normalization"
|
||||
import { everyLineHasLineNumbers, stripLineNumbers } from "../../../integrations/misc/extract-text"
|
||||
import { ToolUse, ToolResponse } from "../../../shared/tools"
|
||||
import { ToolResponse } from "../../../shared/tools"
|
||||
import { writeToFileTool } from "../writeToFileTool"
|
||||
import { ToolDirective } from "../../message-parsing/directives"
|
||||
|
||||
jest.mock("path", () => {
|
||||
const originalPath = jest.requireActual("path")
|
||||
|
|
@ -183,7 +184,7 @@ describe("writeToFileTool", () => {
|
|||
* Helper function to execute the write file tool with different parameters
|
||||
*/
|
||||
async function executeWriteFileTool(
|
||||
params: Partial<ToolUse["params"]> = {},
|
||||
params: Partial<ToolDirective["params"]> = {},
|
||||
options: {
|
||||
fileExists?: boolean
|
||||
isPartial?: boolean
|
||||
|
|
@ -199,7 +200,7 @@ describe("writeToFileTool", () => {
|
|||
mockCline.rooIgnoreController.validateAccess.mockReturnValue(accessAllowed)
|
||||
|
||||
// Create a tool use object
|
||||
const toolUse: ToolUse = {
|
||||
const ToolDirective: ToolDirective = {
|
||||
type: "tool_use",
|
||||
name: "write_to_file",
|
||||
params: {
|
||||
|
|
@ -213,7 +214,7 @@ describe("writeToFileTool", () => {
|
|||
|
||||
await writeToFileTool(
|
||||
mockCline,
|
||||
toolUse,
|
||||
ToolDirective,
|
||||
mockAskApproval,
|
||||
mockHandleError,
|
||||
(result: ToolResponse) => {
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
import { ClineAskUseMcpServer } from "../../shared/ExtensionMessage"
|
||||
import { ToolUse, RemoveClosingTag, AskApproval, HandleError, PushToolResult } from "../../shared/tools"
|
||||
import { RemoveClosingTag, AskApproval, HandleError, PushToolResult } from "../../shared/tools"
|
||||
import { Task } from "../task/Task"
|
||||
import { formatResponse } from "../prompts/responses"
|
||||
import { ToolDirective } from "../message-parsing/directives"
|
||||
|
||||
export async function accessMcpResourceTool(
|
||||
cline: Task,
|
||||
block: ToolUse,
|
||||
block: ToolDirective,
|
||||
askApproval: AskApproval,
|
||||
handleError: HandleError,
|
||||
pushToolResult: PushToolResult,
|
||||
|
|
|
|||
|
|
@ -6,15 +6,16 @@ import { TelemetryService } from "@roo-code/telemetry"
|
|||
import { ClineSayTool } from "../../shared/ExtensionMessage"
|
||||
import { getReadablePath } from "../../utils/path"
|
||||
import { Task } from "../task/Task"
|
||||
import { ToolUse, RemoveClosingTag, AskApproval, HandleError, PushToolResult } from "../../shared/tools"
|
||||
import { RemoveClosingTag, AskApproval, HandleError, PushToolResult } from "../../shared/tools"
|
||||
import { formatResponse } from "../prompts/responses"
|
||||
import { fileExistsAtPath } from "../../utils/fs"
|
||||
import { RecordSource } from "../context-tracking/FileContextTrackerTypes"
|
||||
import { unescapeHtmlEntities } from "../../utils/text-normalization"
|
||||
import { ToolDirective } from "../message-parsing/directives"
|
||||
|
||||
export async function applyDiffToolLegacy(
|
||||
cline: Task,
|
||||
block: ToolUse,
|
||||
block: ToolDirective,
|
||||
askApproval: AskApproval,
|
||||
handleError: HandleError,
|
||||
pushToolResult: PushToolResult,
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
import { Task } from "../task/Task"
|
||||
import { ToolUse, AskApproval, HandleError, PushToolResult, RemoveClosingTag } from "../../shared/tools"
|
||||
import { AskApproval, HandleError, PushToolResult, RemoveClosingTag } from "../../shared/tools"
|
||||
import { formatResponse } from "../prompts/responses"
|
||||
import { parseXml } from "../../utils/xml"
|
||||
import { ToolDirective } from "../message-parsing/directives"
|
||||
|
||||
export async function askFollowupQuestionTool(
|
||||
cline: Task,
|
||||
block: ToolUse,
|
||||
block: ToolDirective,
|
||||
askApproval: AskApproval,
|
||||
handleError: HandleError,
|
||||
pushToolResult: PushToolResult,
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import { TelemetryService } from "@roo-code/telemetry"
|
|||
import { Task } from "../task/Task"
|
||||
import {
|
||||
ToolResponse,
|
||||
ToolUse,
|
||||
AskApproval,
|
||||
HandleError,
|
||||
PushToolResult,
|
||||
|
|
@ -16,10 +15,11 @@ import {
|
|||
import { formatResponse } from "../prompts/responses"
|
||||
import { type ExecuteCommandOptions, executeCommand } from "./executeCommandTool"
|
||||
import { EXPERIMENT_IDS, experiments, experimentDefault } from "../../shared/experiments"
|
||||
import { ToolDirective } from "../message-parsing/directives"
|
||||
|
||||
export async function attemptCompletionTool(
|
||||
cline: Task,
|
||||
block: ToolUse,
|
||||
block: ToolDirective,
|
||||
askApproval: AskApproval,
|
||||
handleError: HandleError,
|
||||
pushToolResult: PushToolResult,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { Task } from "../task/Task"
|
||||
import { ToolUse, AskApproval, HandleError, PushToolResult, RemoveClosingTag } from "../../shared/tools"
|
||||
import { AskApproval, HandleError, PushToolResult, RemoveClosingTag } from "../../shared/tools"
|
||||
import {
|
||||
BrowserAction,
|
||||
BrowserActionResult,
|
||||
|
|
@ -7,10 +7,11 @@ import {
|
|||
ClineSayBrowserAction,
|
||||
} from "../../shared/ExtensionMessage"
|
||||
import { formatResponse } from "../prompts/responses"
|
||||
import { ToolDirective } from "../message-parsing/directives"
|
||||
|
||||
export async function browserActionTool(
|
||||
cline: Task,
|
||||
block: ToolUse,
|
||||
block: ToolDirective,
|
||||
askApproval: AskApproval,
|
||||
handleError: HandleError,
|
||||
pushToolResult: PushToolResult,
|
||||
|
|
|
|||
|
|
@ -5,12 +5,13 @@ import { CodeIndexManager } from "../../services/code-index/manager"
|
|||
import { getWorkspacePath } from "../../utils/path"
|
||||
import { formatResponse } from "../prompts/responses"
|
||||
import { VectorStoreSearchResult } from "../../services/code-index/interfaces"
|
||||
import { AskApproval, HandleError, PushToolResult, RemoveClosingTag, ToolUse } from "../../shared/tools"
|
||||
import { AskApproval, HandleError, PushToolResult, RemoveClosingTag } from "../../shared/tools"
|
||||
import { ToolDirective } from "../message-parsing/directives"
|
||||
import path from "path"
|
||||
|
||||
export async function codebaseSearchTool(
|
||||
cline: Task,
|
||||
block: ToolUse,
|
||||
block: ToolDirective,
|
||||
askApproval: AskApproval,
|
||||
handleError: HandleError,
|
||||
pushToolResult: PushToolResult,
|
||||
|
|
|
|||
|
|
@ -8,18 +8,19 @@ import { TelemetryService } from "@roo-code/telemetry"
|
|||
|
||||
import { Task } from "../task/Task"
|
||||
|
||||
import { ToolUse, AskApproval, HandleError, PushToolResult, RemoveClosingTag, ToolResponse } from "../../shared/tools"
|
||||
import { AskApproval, HandleError, PushToolResult, RemoveClosingTag, ToolResponse } from "../../shared/tools"
|
||||
import { formatResponse } from "../prompts/responses"
|
||||
import { unescapeHtmlEntities } from "../../utils/text-normalization"
|
||||
import { ExitCodeDetails, RooTerminalCallbacks, RooTerminalProcess } from "../../integrations/terminal/types"
|
||||
import { TerminalRegistry } from "../../integrations/terminal/TerminalRegistry"
|
||||
import { Terminal } from "../../integrations/terminal/Terminal"
|
||||
import { ToolDirective } from "../message-parsing/directives"
|
||||
|
||||
class ShellIntegrationError extends Error {}
|
||||
|
||||
export async function executeCommandTool(
|
||||
cline: Task,
|
||||
block: ToolUse,
|
||||
block: ToolDirective,
|
||||
askApproval: AskApproval,
|
||||
handleError: HandleError,
|
||||
pushToolResult: PushToolResult,
|
||||
|
|
|
|||
|
|
@ -2,11 +2,12 @@ import { Task } from "../task/Task"
|
|||
import { fetchInstructions } from "../prompts/instructions/instructions"
|
||||
import { ClineSayTool } from "../../shared/ExtensionMessage"
|
||||
import { formatResponse } from "../prompts/responses"
|
||||
import { ToolUse, AskApproval, HandleError, PushToolResult } from "../../shared/tools"
|
||||
import { AskApproval, HandleError, PushToolResult } from "../../shared/tools"
|
||||
import { ToolDirective } from "../message-parsing/directives"
|
||||
|
||||
export async function fetchInstructionsTool(
|
||||
cline: Task,
|
||||
block: ToolUse,
|
||||
block: ToolDirective,
|
||||
askApproval: AskApproval,
|
||||
handleError: HandleError,
|
||||
pushToolResult: PushToolResult,
|
||||
|
|
|
|||
|
|
@ -4,16 +4,17 @@ import path from "path"
|
|||
|
||||
import { getReadablePath } from "../../utils/path"
|
||||
import { Task } from "../task/Task"
|
||||
import { ToolUse, AskApproval, HandleError, PushToolResult, RemoveClosingTag } from "../../shared/tools"
|
||||
import { AskApproval, HandleError, PushToolResult, RemoveClosingTag } from "../../shared/tools"
|
||||
import { formatResponse } from "../prompts/responses"
|
||||
import { ClineSayTool } from "../../shared/ExtensionMessage"
|
||||
import { RecordSource } from "../context-tracking/FileContextTrackerTypes"
|
||||
import { fileExistsAtPath } from "../../utils/fs"
|
||||
import { insertGroups } from "../diff/insert-groups"
|
||||
import { ToolDirective } from "../message-parsing/directives"
|
||||
|
||||
export async function insertContentTool(
|
||||
cline: Task,
|
||||
block: ToolUse,
|
||||
block: ToolDirective,
|
||||
askApproval: AskApproval,
|
||||
handleError: HandleError,
|
||||
pushToolResult: PushToolResult,
|
||||
|
|
|
|||
|
|
@ -1,16 +1,17 @@
|
|||
import path from "path"
|
||||
import fs from "fs/promises"
|
||||
|
||||
import { ToolUse, AskApproval, HandleError, PushToolResult, RemoveClosingTag } from "../../shared/tools"
|
||||
import { AskApproval, HandleError, PushToolResult, RemoveClosingTag } from "../../shared/tools"
|
||||
import { Task } from "../task/Task"
|
||||
import { ClineSayTool } from "../../shared/ExtensionMessage"
|
||||
import { getReadablePath } from "../../utils/path"
|
||||
import { parseSourceCodeForDefinitionsTopLevel, parseSourceCodeDefinitionsForFile } from "../../services/tree-sitter"
|
||||
import { RecordSource } from "../context-tracking/FileContextTrackerTypes"
|
||||
import { ToolDirective } from "../message-parsing/directives"
|
||||
|
||||
export async function listCodeDefinitionNamesTool(
|
||||
cline: Task,
|
||||
block: ToolUse,
|
||||
block: ToolDirective,
|
||||
askApproval: AskApproval,
|
||||
handleError: HandleError,
|
||||
pushToolResult: PushToolResult,
|
||||
|
|
|
|||
|
|
@ -5,7 +5,8 @@ import { ClineSayTool } from "../../shared/ExtensionMessage"
|
|||
import { formatResponse } from "../prompts/responses"
|
||||
import { listFiles } from "../../services/glob/list-files"
|
||||
import { getReadablePath } from "../../utils/path"
|
||||
import { ToolUse, AskApproval, HandleError, PushToolResult, RemoveClosingTag } from "../../shared/tools"
|
||||
import { AskApproval, HandleError, PushToolResult, RemoveClosingTag } from "../../shared/tools"
|
||||
import { ToolDirective } from "../message-parsing/directives"
|
||||
|
||||
/**
|
||||
* Implements the list_files tool.
|
||||
|
|
@ -24,7 +25,7 @@ import { ToolUse, AskApproval, HandleError, PushToolResult, RemoveClosingTag } f
|
|||
|
||||
export async function listFilesTool(
|
||||
cline: Task,
|
||||
block: ToolUse,
|
||||
block: ToolDirective,
|
||||
askApproval: AskApproval,
|
||||
handleError: HandleError,
|
||||
pushToolResult: PushToolResult,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import { TelemetryService } from "@roo-code/telemetry"
|
|||
import { ClineSayTool } from "../../shared/ExtensionMessage"
|
||||
import { getReadablePath } from "../../utils/path"
|
||||
import { Task } from "../task/Task"
|
||||
import { ToolUse, RemoveClosingTag, AskApproval, HandleError, PushToolResult } from "../../shared/tools"
|
||||
import { RemoveClosingTag, AskApproval, HandleError, PushToolResult } from "../../shared/tools"
|
||||
import { formatResponse } from "../prompts/responses"
|
||||
import { fileExistsAtPath } from "../../utils/fs"
|
||||
import { RecordSource } from "../context-tracking/FileContextTrackerTypes"
|
||||
|
|
@ -14,6 +14,7 @@ import { unescapeHtmlEntities } from "../../utils/text-normalization"
|
|||
import { parseXml } from "../../utils/xml"
|
||||
import { EXPERIMENT_IDS, experiments } from "../../shared/experiments"
|
||||
import { applyDiffToolLegacy } from "./applyDiffTool"
|
||||
import { ToolDirective } from "../message-parsing/directives"
|
||||
|
||||
interface DiffOperation {
|
||||
path: string
|
||||
|
|
@ -51,7 +52,7 @@ interface ParsedXmlResult {
|
|||
|
||||
export async function applyDiffTool(
|
||||
cline: Task,
|
||||
block: ToolUse,
|
||||
block: ToolDirective,
|
||||
askApproval: AskApproval,
|
||||
handleError: HandleError,
|
||||
pushToolResult: PushToolResult,
|
||||
|
|
@ -161,7 +162,6 @@ Expected structure:
|
|||
Original error: ${errorMessage}`
|
||||
throw new Error(detailedError)
|
||||
}
|
||||
|
||||
} else if (legacyPath && typeof legacyDiffContent === "string") {
|
||||
// Handle legacy parameters (old way)
|
||||
usingLegacyParams = true
|
||||
|
|
|
|||
|
|
@ -1,13 +1,14 @@
|
|||
import delay from "delay"
|
||||
|
||||
import { ToolUse, AskApproval, HandleError, PushToolResult, RemoveClosingTag } from "../../shared/tools"
|
||||
import { AskApproval, HandleError, PushToolResult, RemoveClosingTag } from "../../shared/tools"
|
||||
import { Task } from "../task/Task"
|
||||
import { defaultModeSlug, getModeBySlug } from "../../shared/modes"
|
||||
import { formatResponse } from "../prompts/responses"
|
||||
import { ToolDirective } from "../message-parsing/directives"
|
||||
|
||||
export async function newTaskTool(
|
||||
cline: Task,
|
||||
block: ToolUse,
|
||||
block: ToolDirective,
|
||||
askApproval: AskApproval,
|
||||
handleError: HandleError,
|
||||
pushToolResult: PushToolResult,
|
||||
|
|
@ -43,7 +44,7 @@ export async function newTaskTool(
|
|||
|
||||
cline.consecutiveMistakeCount = 0
|
||||
// Un-escape one level of backslashes before '@' for hierarchical subtasks
|
||||
// Un-escape one level: \\@ -> \@ (removes one backslash for hierarchical subtasks)
|
||||
// Un-escape one level: \\@ -> \@ (removes one backslash for hierarchical subtasks)
|
||||
const unescapedMessage = message.replace(/\\\\@/g, "\\@")
|
||||
|
||||
// Verify the mode exists
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { Task } from "../task/Task"
|
|||
import { ClineSayTool } from "../../shared/ExtensionMessage"
|
||||
import { formatResponse } from "../prompts/responses"
|
||||
import { t } from "../../i18n"
|
||||
import { ToolUse, AskApproval, HandleError, PushToolResult, RemoveClosingTag } from "../../shared/tools"
|
||||
import { AskApproval, HandleError, PushToolResult, RemoveClosingTag } from "../../shared/tools"
|
||||
import { RecordSource } from "../context-tracking/FileContextTrackerTypes"
|
||||
import { isPathOutsideWorkspace } from "../../utils/pathUtils"
|
||||
import { getReadablePath } from "../../utils/path"
|
||||
|
|
@ -14,6 +14,7 @@ import { readLines } from "../../integrations/misc/read-lines"
|
|||
import { extractTextFromFile, addLineNumbers, getSupportedBinaryFormats } from "../../integrations/misc/extract-text"
|
||||
import { parseSourceCodeDefinitionsForFile } from "../../services/tree-sitter"
|
||||
import { parseXml } from "../../utils/xml"
|
||||
import { ToolDirective } from "../message-parsing/directives"
|
||||
|
||||
export function getReadFileToolDescription(blockName: string, blockParams: any): string {
|
||||
// Handle both single path and multiple files via args
|
||||
|
|
@ -72,7 +73,7 @@ interface FileResult {
|
|||
|
||||
export async function readFileTool(
|
||||
cline: Task,
|
||||
block: ToolUse,
|
||||
block: ToolDirective,
|
||||
askApproval: AskApproval,
|
||||
handleError: HandleError,
|
||||
pushToolResult: PushToolResult,
|
||||
|
|
|
|||
|
|
@ -5,12 +5,13 @@ import delay from "delay"
|
|||
|
||||
// Internal imports
|
||||
import { Task } from "../task/Task"
|
||||
import { AskApproval, HandleError, PushToolResult, RemoveClosingTag, ToolUse } from "../../shared/tools"
|
||||
import { AskApproval, HandleError, PushToolResult, RemoveClosingTag } from "../../shared/tools"
|
||||
import { formatResponse } from "../prompts/responses"
|
||||
import { ClineSayTool } from "../../shared/ExtensionMessage"
|
||||
import { getReadablePath } from "../../utils/path"
|
||||
import { fileExistsAtPath } from "../../utils/fs"
|
||||
import { RecordSource } from "../context-tracking/FileContextTrackerTypes"
|
||||
import { ToolDirective } from "../message-parsing/directives"
|
||||
|
||||
/**
|
||||
* Tool for performing search and replace operations on files
|
||||
|
|
@ -62,7 +63,7 @@ async function validateParams(
|
|||
*/
|
||||
export async function searchAndReplaceTool(
|
||||
cline: Task,
|
||||
block: ToolUse,
|
||||
block: ToolDirective,
|
||||
askApproval: AskApproval,
|
||||
handleError: HandleError,
|
||||
pushToolResult: PushToolResult,
|
||||
|
|
|
|||
|
|
@ -1,14 +1,15 @@
|
|||
import path from "path"
|
||||
|
||||
import { Task } from "../task/Task"
|
||||
import { ToolUse, AskApproval, HandleError, PushToolResult, RemoveClosingTag } from "../../shared/tools"
|
||||
import { AskApproval, HandleError, PushToolResult, RemoveClosingTag } from "../../shared/tools"
|
||||
import { ClineSayTool } from "../../shared/ExtensionMessage"
|
||||
import { getReadablePath } from "../../utils/path"
|
||||
import { regexSearchFiles } from "../../services/ripgrep"
|
||||
import { ToolDirective } from "../message-parsing/directives"
|
||||
|
||||
export async function searchFilesTool(
|
||||
cline: Task,
|
||||
block: ToolUse,
|
||||
block: ToolDirective,
|
||||
askApproval: AskApproval,
|
||||
handleError: HandleError,
|
||||
pushToolResult: PushToolResult,
|
||||
|
|
|
|||
|
|
@ -1,13 +1,14 @@
|
|||
import delay from "delay"
|
||||
|
||||
import { Task } from "../task/Task"
|
||||
import { ToolUse, AskApproval, HandleError, PushToolResult, RemoveClosingTag } from "../../shared/tools"
|
||||
import { AskApproval, HandleError, PushToolResult, RemoveClosingTag } from "../../shared/tools"
|
||||
import { formatResponse } from "../prompts/responses"
|
||||
import { defaultModeSlug, getModeBySlug } from "../../shared/modes"
|
||||
import { ToolDirective } from "../message-parsing/directives"
|
||||
|
||||
export async function switchModeTool(
|
||||
cline: Task,
|
||||
block: ToolUse,
|
||||
block: ToolDirective,
|
||||
askApproval: AskApproval,
|
||||
handleError: HandleError,
|
||||
pushToolResult: PushToolResult,
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
import { Task } from "../task/Task"
|
||||
import { ToolUse, AskApproval, HandleError, PushToolResult, RemoveClosingTag } from "../../shared/tools"
|
||||
import { AskApproval, HandleError, PushToolResult, RemoveClosingTag } from "../../shared/tools"
|
||||
import { formatResponse } from "../prompts/responses"
|
||||
import { ClineAskUseMcpServer } from "../../shared/ExtensionMessage"
|
||||
import { McpExecutionStatus } from "@roo-code/types"
|
||||
import { t } from "../../i18n"
|
||||
import { ToolDirective } from "../message-parsing/directives"
|
||||
|
||||
interface McpToolParams {
|
||||
server_name?: string
|
||||
|
|
@ -166,7 +167,7 @@ async function executeToolAndProcessResult(
|
|||
|
||||
export async function useMcpToolTool(
|
||||
cline: Task,
|
||||
block: ToolUse,
|
||||
block: ToolDirective,
|
||||
askApproval: AskApproval,
|
||||
handleError: HandleError,
|
||||
pushToolResult: PushToolResult,
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import * as vscode from "vscode"
|
|||
import { Task } from "../task/Task"
|
||||
import { ClineSayTool } from "../../shared/ExtensionMessage"
|
||||
import { formatResponse } from "../prompts/responses"
|
||||
import { ToolUse, AskApproval, HandleError, PushToolResult, RemoveClosingTag } from "../../shared/tools"
|
||||
import { AskApproval, HandleError, PushToolResult, RemoveClosingTag } from "../../shared/tools"
|
||||
import { RecordSource } from "../context-tracking/FileContextTrackerTypes"
|
||||
import { fileExistsAtPath } from "../../utils/fs"
|
||||
import { stripLineNumbers, everyLineHasLineNumbers } from "../../integrations/misc/extract-text"
|
||||
|
|
@ -13,10 +13,11 @@ import { getReadablePath } from "../../utils/path"
|
|||
import { isPathOutsideWorkspace } from "../../utils/pathUtils"
|
||||
import { detectCodeOmission } from "../../integrations/editor/detect-omission"
|
||||
import { unescapeHtmlEntities } from "../../utils/text-normalization"
|
||||
import { ToolDirective } from "../message-parsing/directives"
|
||||
|
||||
export async function writeToFileTool(
|
||||
cline: Task,
|
||||
block: ToolUse,
|
||||
block: ToolDirective,
|
||||
askApproval: AskApproval,
|
||||
handleError: HandleError,
|
||||
pushToolResult: PushToolResult,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { Anthropic } from "@anthropic-ai/sdk"
|
||||
|
||||
import type { ClineAsk, ToolProgressStatus, ToolGroup, ToolName } from "@roo-code/types"
|
||||
import { ToolDirective } from "../core/message-parsing/directives/"
|
||||
|
||||
export type ToolResponse = string | Array<Anthropic.TextBlockParam | Anthropic.ImageBlockParam>
|
||||
|
||||
|
|
@ -61,96 +62,88 @@ export const toolParamNames = [
|
|||
|
||||
export type ToolParamName = (typeof toolParamNames)[number]
|
||||
|
||||
export interface ToolUse {
|
||||
type: "tool_use"
|
||||
name: ToolName
|
||||
// params is a partial record, allowing only some or none of the possible parameters to be used
|
||||
params: Partial<Record<ToolParamName, string>>
|
||||
partial: boolean
|
||||
}
|
||||
|
||||
export interface ExecuteCommandToolUse extends ToolUse {
|
||||
export interface ExecuteCommandToolDirective extends ToolDirective {
|
||||
name: "execute_command"
|
||||
// Pick<Record<ToolParamName, string>, "command"> makes "command" required, but Partial<> makes it optional
|
||||
params: Partial<Pick<Record<ToolParamName, string>, "command" | "cwd">>
|
||||
}
|
||||
|
||||
export interface ReadFileToolUse extends ToolUse {
|
||||
export interface ReadFileToolDirective extends ToolDirective {
|
||||
name: "read_file"
|
||||
params: Partial<Pick<Record<ToolParamName, string>, "args" | "path" | "start_line" | "end_line">>
|
||||
}
|
||||
|
||||
export interface FetchInstructionsToolUse extends ToolUse {
|
||||
export interface FetchInstructionsToolDirective extends ToolDirective {
|
||||
name: "fetch_instructions"
|
||||
params: Partial<Pick<Record<ToolParamName, string>, "task">>
|
||||
}
|
||||
|
||||
export interface WriteToFileToolUse extends ToolUse {
|
||||
export interface WriteToFileToolDirective extends ToolDirective {
|
||||
name: "write_to_file"
|
||||
params: Partial<Pick<Record<ToolParamName, string>, "path" | "content" | "line_count">>
|
||||
}
|
||||
|
||||
export interface InsertCodeBlockToolUse extends ToolUse {
|
||||
export interface InsertCodeBlockToolDirective extends ToolDirective {
|
||||
name: "insert_content"
|
||||
params: Partial<Pick<Record<ToolParamName, string>, "path" | "line" | "content">>
|
||||
}
|
||||
|
||||
export interface CodebaseSearchToolUse extends ToolUse {
|
||||
export interface CodebaseSearchToolDirective extends ToolDirective {
|
||||
name: "codebase_search"
|
||||
params: Partial<Pick<Record<ToolParamName, string>, "query" | "path">>
|
||||
}
|
||||
|
||||
export interface SearchFilesToolUse extends ToolUse {
|
||||
export interface SearchFilesToolDirective extends ToolDirective {
|
||||
name: "search_files"
|
||||
params: Partial<Pick<Record<ToolParamName, string>, "path" | "regex" | "file_pattern">>
|
||||
}
|
||||
|
||||
export interface ListFilesToolUse extends ToolUse {
|
||||
export interface ListFilesToolDirective extends ToolDirective {
|
||||
name: "list_files"
|
||||
params: Partial<Pick<Record<ToolParamName, string>, "path" | "recursive">>
|
||||
}
|
||||
|
||||
export interface ListCodeDefinitionNamesToolUse extends ToolUse {
|
||||
export interface ListCodeDefinitionNamesToolDirective extends ToolDirective {
|
||||
name: "list_code_definition_names"
|
||||
params: Partial<Pick<Record<ToolParamName, string>, "path">>
|
||||
}
|
||||
|
||||
export interface BrowserActionToolUse extends ToolUse {
|
||||
export interface BrowserActionToolDirective extends ToolDirective {
|
||||
name: "browser_action"
|
||||
params: Partial<Pick<Record<ToolParamName, string>, "action" | "url" | "coordinate" | "text" | "size">>
|
||||
}
|
||||
|
||||
export interface UseMcpToolToolUse extends ToolUse {
|
||||
export interface UseMcpToolToolDirective extends ToolDirective {
|
||||
name: "use_mcp_tool"
|
||||
params: Partial<Pick<Record<ToolParamName, string>, "server_name" | "tool_name" | "arguments">>
|
||||
}
|
||||
|
||||
export interface AccessMcpResourceToolUse extends ToolUse {
|
||||
export interface AccessMcpResourceToolDirective extends ToolDirective {
|
||||
name: "access_mcp_resource"
|
||||
params: Partial<Pick<Record<ToolParamName, string>, "server_name" | "uri">>
|
||||
}
|
||||
|
||||
export interface AskFollowupQuestionToolUse extends ToolUse {
|
||||
export interface AskFollowupQuestionToolDirective extends ToolDirective {
|
||||
name: "ask_followup_question"
|
||||
params: Partial<Pick<Record<ToolParamName, string>, "question" | "follow_up">>
|
||||
}
|
||||
|
||||
export interface AttemptCompletionToolUse extends ToolUse {
|
||||
export interface AttemptCompletionToolDirective extends ToolDirective {
|
||||
name: "attempt_completion"
|
||||
params: Partial<Pick<Record<ToolParamName, string>, "result" | "command">>
|
||||
}
|
||||
|
||||
export interface SwitchModeToolUse extends ToolUse {
|
||||
export interface SwitchModeToolDirective extends ToolDirective {
|
||||
name: "switch_mode"
|
||||
params: Partial<Pick<Record<ToolParamName, string>, "mode_slug" | "reason">>
|
||||
}
|
||||
|
||||
export interface NewTaskToolUse extends ToolUse {
|
||||
export interface NewTaskToolDirective extends ToolDirective {
|
||||
name: "new_task"
|
||||
params: Partial<Pick<Record<ToolParamName, string>, "mode" | "message">>
|
||||
}
|
||||
|
||||
export interface SearchAndReplaceToolUse extends ToolUse {
|
||||
export interface SearchAndReplaceToolDirective extends ToolDirective {
|
||||
name: "search_and_replace"
|
||||
params: Required<Pick<Record<ToolParamName, string>, "path" | "search" | "replace">> &
|
||||
Partial<Pick<Record<ToolParamName, string>, "use_regex" | "ignore_case" | "start_line" | "end_line">>
|
||||
|
|
@ -270,5 +263,5 @@ export interface DiffStrategy {
|
|||
endLine?: number,
|
||||
): Promise<DiffResult>
|
||||
|
||||
getProgressStatus?(toolUse: ToolUse, result?: any): ToolProgressStatus
|
||||
getProgressStatus?(ToolDirective: ToolDirective, result?: any): ToolProgressStatus
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue