Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/wise-spies-type.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"roo-cline": patch
---

Clean up types related to tools
74 changes: 45 additions & 29 deletions src/core/Cline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,14 @@ import getFolderSize from "get-folder-size"
import { serializeError } from "serialize-error"
import * as vscode from "vscode"

// schemas
import { TokenUsage } from "../schemas"

// api
import { ApiHandler, buildApiHandler } from "../api"
import { ApiStream } from "../api/transform/stream"
import { DIFF_VIEW_URI_SCHEME, DiffViewProvider } from "../integrations/editor/DiffViewProvider"
import { CheckpointServiceOptions, RepoPerTaskCheckpointService } from "../services/checkpoints"
import { findToolName, formatContentBlockToMarkdown } from "../integrations/misc/export-markdown"
import { fetchInstructionsTool } from "./tools/fetchInstructionsTool"
import { listFilesTool } from "./tools/listFilesTool"
import { readFileTool } from "./tools/readFileTool"
import { ExitCodeDetails, TerminalProcess } from "../integrations/terminal/TerminalProcess"
import { Terminal } from "../integrations/terminal/Terminal"
import { TerminalRegistry } from "../integrations/terminal/TerminalRegistry"
import { UrlContentFetcher } from "../services/browser/UrlContentFetcher"
import { listFiles } from "../services/glob/list-files"

// shared
import { ApiConfiguration } from "../shared/api"
import { findLastIndex } from "../shared/array"
import { combineApiRequests } from "../shared/combineApiRequests"
Expand All @@ -42,26 +36,35 @@ import { getApiMetrics } from "../shared/getApiMetrics"
import { HistoryItem } from "../shared/HistoryItem"
import { ClineAskResponse } from "../shared/WebviewMessage"
import { GlobalFileNames } from "../shared/globalFileNames"
import { defaultModeSlug, getModeBySlug, getFullModeDetails } from "../shared/modes"
import { defaultModeSlug, getModeBySlug, getFullModeDetails, isToolAllowedForMode } from "../shared/modes"
import { EXPERIMENT_IDS, experiments as Experiments, ExperimentId } from "../shared/experiments"
import { calculateApiCostAnthropic } from "../utils/cost"
import { fileExistsAtPath } from "../utils/fs"
import { arePathsEqual } from "../utils/path"
import { parseMentions } from "./mentions"
import { FileContextTracker } from "./context-tracking/FileContextTracker"
import { RooIgnoreController } from "./ignore/RooIgnoreController"
import { AssistantMessageContent, parseAssistantMessage, ToolParamName, ToolUseName } from "./assistant-message"
import { formatResponse } from "./prompts/responses"
import { SYSTEM_PROMPT } from "./prompts/system"
import { truncateConversationIfNeeded } from "./sliding-window"
import { ClineProvider } from "./webview/ClineProvider"
import { BrowserSession } from "../services/browser/BrowserSession"
import { formatLanguage } from "../shared/language"
import { ToolParamName, ToolName, ToolResponse } from "../shared/tools"

// services
import { UrlContentFetcher } from "../services/browser/UrlContentFetcher"
import { listFiles } from "../services/glob/list-files"
import { BrowserSession } from "../services/browser/BrowserSession"
import { McpHub } from "../services/mcp/McpHub"
import { DiffStrategy, getDiffStrategy } from "./diff/DiffStrategy"
import { telemetryService } from "../services/telemetry/TelemetryService"
import { validateToolUse, isToolAllowedForMode, ToolName } from "./mode-validator"
import { getWorkspacePath } from "../utils/path"
import { CheckpointServiceOptions, RepoPerTaskCheckpointService } from "../services/checkpoints"

// integrations
import { DIFF_VIEW_URI_SCHEME, DiffViewProvider } from "../integrations/editor/DiffViewProvider"
import { findToolName, formatContentBlockToMarkdown } from "../integrations/misc/export-markdown"
import { ExitCodeDetails, TerminalProcess } from "../integrations/terminal/TerminalProcess"
import { Terminal } from "../integrations/terminal/Terminal"
import { TerminalRegistry } from "../integrations/terminal/TerminalRegistry"

// utils
import { calculateApiCostAnthropic } from "../utils/cost"
import { fileExistsAtPath } from "../utils/fs"
import { arePathsEqual, getWorkspacePath } from "../utils/path"

// tools
import { fetchInstructionsTool } from "./tools/fetchInstructionsTool"
import { listFilesTool } from "./tools/listFilesTool"
import { readFileTool } from "./tools/readFileTool"
import { writeToFileTool } from "./tools/writeToFileTool"
import { applyDiffTool } from "./tools/applyDiffTool"
import { insertContentTool } from "./tools/insertContentTool"
Expand All @@ -77,7 +80,20 @@ import { switchModeTool } from "./tools/switchModeTool"
import { attemptCompletionTool } from "./tools/attemptCompletionTool"
import { newTaskTool } from "./tools/newTaskTool"

export type ToolResponse = string | Array<Anthropic.TextBlockParam | Anthropic.ImageBlockParam>
// prompts
import { formatResponse } from "./prompts/responses"
import { SYSTEM_PROMPT } from "./prompts/system"

// ... everything else
import { parseMentions } from "./mentions"
import { FileContextTracker } from "./context-tracking/FileContextTracker"
import { RooIgnoreController } from "./ignore/RooIgnoreController"
import { type AssistantMessageContent, parseAssistantMessage } from "./assistant-message"
import { truncateConversationIfNeeded } from "./sliding-window"
import { ClineProvider } from "./webview/ClineProvider"
import { DiffStrategy, getDiffStrategy } from "./diff/DiffStrategy"
import { validateToolUse } from "./mode-validator"

type UserContent = Array<Anthropic.Messages.ContentBlockParam>

export type ClineEvents = {
Expand Down Expand Up @@ -572,7 +588,7 @@ export class Cline extends EventEmitter<ClineEvents> {
}
}

async sayAndCreateMissingParamError(toolName: ToolUseName, paramName: string, relPath?: string) {
async sayAndCreateMissingParamError(toolName: ToolName, paramName: string, relPath?: string) {
await this.say(
"error",
`Roo tried to use ${toolName}${
Expand Down
2 changes: 1 addition & 1 deletion src/core/__tests__/mode-validator.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { isToolAllowedForMode, getModeConfig, modes, ModeConfig } from "../../shared/modes"
import { TOOL_GROUPS } from "../../shared/tool-groups"
import { TOOL_GROUPS } from "../../shared/tools"
import { validateToolUse } from "../mode-validator"

const [codeMode, architectMode, askMode] = modes.map((mode) => mode.slug)
Expand Down
4 changes: 2 additions & 2 deletions src/core/__tests__/read-file-maxReadFileLine.test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import * as path from "path"

import { countFileLines } from "../../integrations/misc/line-counter"
import { readLines } from "../../integrations/misc/read-lines"
import { extractTextFromFile, addLineNumbers } from "../../integrations/misc/extract-text"
import { parseSourceCodeDefinitionsForFile } from "../../services/tree-sitter"
import { isBinaryFile } from "isbinaryfile"
import { ReadFileToolUse } from "../assistant-message"
import { Cline } from "../Cline"
import { ReadFileToolUse } from "../../shared/tools"

// Mock dependencies
jest.mock("../../integrations/misc/line-counter")
Expand Down
6 changes: 3 additions & 3 deletions src/core/__tests__/read-file-xml.test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import * as path from "path"

import { countFileLines } from "../../integrations/misc/line-counter"
import { readLines } from "../../integrations/misc/read-lines"
import { extractTextFromFile, addLineNumbers } from "../../integrations/misc/extract-text"
import { extractTextFromFile } from "../../integrations/misc/extract-text"
import { parseSourceCodeDefinitionsForFile } from "../../services/tree-sitter"
import { isBinaryFile } from "isbinaryfile"
import { ReadFileToolUse } from "../assistant-message"
import { Cline } from "../Cline"
import { ReadFileToolUse } from "../../shared/tools"

// Mock dependencies
jest.mock("../../integrations/misc/line-counter")
Expand Down
151 changes: 1 addition & 150 deletions src/core/assistant-message/index.ts
Original file line number Diff line number Diff line change
@@ -1,150 +1 @@
export type AssistantMessageContent = TextContent | ToolUse

export { parseAssistantMessage } from "./parse-assistant-message"

export interface TextContent {
type: "text"
content: string
partial: boolean
}

export const toolUseNames = [
"execute_command",
"read_file",
"write_to_file",
"apply_diff",
"insert_content",
"search_and_replace",
"search_files",
"list_files",
"list_code_definition_names",
"browser_action",
"use_mcp_tool",
"access_mcp_resource",
"ask_followup_question",
"attempt_completion",
"switch_mode",
"new_task",
"fetch_instructions",
] as const

// Converts array of tool call names into a union type ("execute_command" | "read_file" | ...)
export type ToolUseName = (typeof toolUseNames)[number]

export const toolParamNames = [
"command",
"path",
"content",
"line_count",
"regex",
"file_pattern",
"recursive",
"action",
"url",
"coordinate",
"text",
"server_name",
"tool_name",
"arguments",
"uri",
"question",
"result",
"diff",
"start_line",
"end_line",
"mode_slug",
"reason",
"operations",
"mode",
"message",
"cwd",
"follow_up",
"task",
"size",
] as const

export type ToolParamName = (typeof toolParamNames)[number]

export interface ToolUse {
type: "tool_use"
name: ToolUseName
// 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 {
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 {
name: "read_file"
params: Partial<Pick<Record<ToolParamName, string>, "path" | "start_line" | "end_line">>
}

export interface FetchInstructionsToolUse extends ToolUse {
name: "fetch_instructions"
params: Partial<Pick<Record<ToolParamName, string>, "task">>
}

export interface WriteToFileToolUse extends ToolUse {
name: "write_to_file"
params: Partial<Pick<Record<ToolParamName, string>, "path" | "content" | "line_count">>
}

export interface InsertCodeBlockToolUse extends ToolUse {
name: "insert_content"
params: Partial<Pick<Record<ToolParamName, string>, "path" | "operations">>
}

export interface SearchFilesToolUse extends ToolUse {
name: "search_files"
params: Partial<Pick<Record<ToolParamName, string>, "path" | "regex" | "file_pattern">>
}

export interface ListFilesToolUse extends ToolUse {
name: "list_files"
params: Partial<Pick<Record<ToolParamName, string>, "path" | "recursive">>
}

export interface ListCodeDefinitionNamesToolUse extends ToolUse {
name: "list_code_definition_names"
params: Partial<Pick<Record<ToolParamName, string>, "path">>
}

export interface BrowserActionToolUse extends ToolUse {
name: "browser_action"
params: Partial<Pick<Record<ToolParamName, string>, "action" | "url" | "coordinate" | "text" | "size">>
}

export interface UseMcpToolToolUse extends ToolUse {
name: "use_mcp_tool"
params: Partial<Pick<Record<ToolParamName, string>, "server_name" | "tool_name" | "arguments">>
}

export interface AccessMcpResourceToolUse extends ToolUse {
name: "access_mcp_resource"
params: Partial<Pick<Record<ToolParamName, string>, "server_name" | "uri">>
}

export interface AskFollowupQuestionToolUse extends ToolUse {
name: "ask_followup_question"
params: Partial<Pick<Record<ToolParamName, string>, "question" | "follow_up">>
}

export interface AttemptCompletionToolUse extends ToolUse {
name: "attempt_completion"
params: Partial<Pick<Record<ToolParamName, string>, "result" | "command">>
}

export interface SwitchModeToolUse extends ToolUse {
name: "switch_mode"
params: Partial<Pick<Record<ToolParamName, string>, "mode_slug" | "reason">>
}

export interface NewTaskToolUse extends ToolUse {
name: "new_task"
params: Partial<Pick<Record<ToolParamName, string>, "mode" | "message">>
}
export { type AssistantMessageContent, parseAssistantMessage } from "./parse-assistant-message"
16 changes: 5 additions & 11 deletions src/core/assistant-message/parse-assistant-message.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
import {
AssistantMessageContent,
TextContent,
ToolUse,
ToolParamName,
toolParamNames,
toolUseNames,
ToolUseName,
} from "."
import { TextContent, ToolUse, ToolParamName, toolParamNames, toolNames, ToolName } from "../../shared/tools"

export type AssistantMessageContent = TextContent | ToolUse

export function parseAssistantMessage(assistantMessage: string) {
let contentBlocks: AssistantMessageContent[] = []
Expand Down Expand Up @@ -84,13 +78,13 @@ export function parseAssistantMessage(assistantMessage: string) {
// no currentToolUse

let didStartToolUse = false
const possibleToolUseOpeningTags = toolUseNames.map((name) => `<${name}>`)
const possibleToolUseOpeningTags = toolNames.map((name) => `<${name}>`)
for (const toolUseOpeningTag of possibleToolUseOpeningTags) {
if (accumulator.endsWith(toolUseOpeningTag)) {
// start of a new tool use
currentToolUse = {
type: "tool_use",
name: toolUseOpeningTag.slice(1, -1) as ToolUseName,
name: toolUseOpeningTag.slice(1, -1) as ToolName,
params: {},
partial: true,
}
Expand Down
5 changes: 3 additions & 2 deletions src/core/diff/strategies/multi-search-replace.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { distance } from "fastest-levenshtein"

import { DiffStrategy, DiffResult } from "../types"
import { addLineNumbers, everyLineHasLineNumbers, stripLineNumbers } from "../../../integrations/misc/extract-text"
import { distance } from "fastest-levenshtein"
import { ToolProgressStatus } from "../../../shared/ExtensionMessage"
import { ToolUse } from "../../assistant-message"
import { ToolUse } from "../../../shared/tools"
import { normalizeString } from "../../../utils/text-normalization"

const BUFFER_LINES = 40 // Number of extra context lines to show before and after matches
Expand Down
2 changes: 1 addition & 1 deletion src/core/diff/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
* Interface for implementing different diff strategies
*/

import { ToolUse } from "../../shared/tools"
import { ToolProgressStatus } from "../../shared/ExtensionMessage"
import { ToolUse } from "../assistant-message"

export type DiffResult =
| { success: true; content: string; failParts?: DiffResult[] }
Expand Down
5 changes: 1 addition & 4 deletions src/core/mode-validator.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
import { ToolName } from "../shared/tools"
import { Mode, isToolAllowedForMode, ModeConfig } from "../shared/modes"
import { ToolName } from "../shared/tool-groups"

export { isToolAllowedForMode }
export type { ToolName }

export function validateToolUse(
toolName: ToolName,
Expand Down
2 changes: 1 addition & 1 deletion src/core/prompts/tools/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { getNewTaskDescription } from "./new-task"
import { DiffStrategy } from "../../diff/DiffStrategy"
import { McpHub } from "../../../services/mcp/McpHub"
import { Mode, ModeConfig, getModeConfig, isToolAllowedForMode, getGroupName } from "../../../shared/modes"
import { ToolName, TOOL_GROUPS, ALWAYS_AVAILABLE_TOOLS } from "../../../shared/tool-groups"
import { ToolName, TOOL_GROUPS, ALWAYS_AVAILABLE_TOOLS } from "../../../shared/tools"
import { ToolArgs } from "./types"

// Map of tool names to their description functions
Expand Down
5 changes: 2 additions & 3 deletions src/core/tools/__tests__/executeCommandTool.test.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
// npx jest src/core/tools/__tests__/executeCommandTool.test.ts

import { describe, expect, it, jest, beforeEach } from "@jest/globals"

import { executeCommandTool } from "../executeCommandTool"
import { Cline } from "../../Cline"
import { ToolUse } from "../../assistant-message"
import { formatResponse } from "../../prompts/responses"
import { AskApproval, HandleError, PushToolResult, RemoveClosingTag } from "../types"
import { ClineAsk } from "../../../schemas"
import { ToolUse, AskApproval, HandleError, PushToolResult, RemoveClosingTag } from "../../../shared/tools"

// Mock dependencies
jest.mock("../../Cline")
Expand Down
4 changes: 1 addition & 3 deletions src/core/tools/accessMcpResourceTool.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import { ClineAskUseMcpServer } from "../../shared/ExtensionMessage"
import { RemoveClosingTag } from "./types"
import { ToolUse } from "../assistant-message"
import { AskApproval, HandleError, PushToolResult } from "./types"
import { ToolUse, RemoveClosingTag, AskApproval, HandleError, PushToolResult } from "../../shared/tools"
import { Cline } from "../Cline"
import { formatResponse } from "../prompts/responses"

Expand Down
Loading