Skip to content
Closed
Show file tree
Hide file tree
Changes from all 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
68 changes: 68 additions & 0 deletions ToolExtensions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
## Extension Tool API

Roo now provides an API for VSCode extensions to register custom tools that can be used by Roo. This allows other extensions to extend Roo's capabilities without modifying the Roo codebase.

### Using the Extension Tool API

To use the Extension Tool API, your extension needs to:

1. Add `RooVeterinaryInc.roo-cline` as an extension dependency in your `package.json`.
2. Get the Roo extension API and access the `extensionTools` property.
3. Register your tools using the `registerTool` method.

Here's a simple example:

```typescript
// Access the Roo extension
const rooExtension = vscode.extensions.getExtension<RooAPI>("RooVeterinaryInc.roo-cline")

if (rooExtension && rooExtension.exports.extensionTools) {
// Register a tool
rooExtension.exports.extensionTools.registerTool(context.extension.id, {
name: "my_tool",
description: "Description of what the tool does",
inputSchema: {
// Optional JSON schema for tool arguments
type: "object",
properties: {
myArg: {
type: "string",
description: "Description of the argument",
},
},
},
execute: async (args) => {
// Implement your tool functionality
return {
content: [
{
type: "text",
text: "Result of the tool execution",
},
],
}
},
})
}
```

### Tool Response Format

Tools return responses in the same format as MCP tools:

```typescript
{
content: [
{
type: 'text',
text: 'Text content'
}
// Can also include resources
],
isError?: boolean // Optional flag to indicate if the tool execution failed
}
```

### Example Extension

See the [Roo-NB](https://github.com/RooVeterinaryInc/Roo-NB) extension for a complete example of a tool provider extension.
2 changes: 2 additions & 0 deletions evals/packages/types/src/roo-code.ts
Original file line number Diff line number Diff line change
Expand Up @@ -743,6 +743,7 @@ export const globalSettingsSchema = z.object({
alwaysApproveResubmit: z.boolean().optional(),
requestDelaySeconds: z.number().optional(),
alwaysAllowMcp: z.boolean().optional(),
alwaysAllowExtTools: z.boolean().optional(),
alwaysAllowModeSwitch: z.boolean().optional(),
alwaysAllowSubtasks: z.boolean().optional(),
alwaysAllowExecute: z.boolean().optional(),
Expand Down Expand Up @@ -822,6 +823,7 @@ const globalSettingsRecord: GlobalSettingsRecord = {
alwaysApproveResubmit: undefined,
requestDelaySeconds: undefined,
alwaysAllowMcp: undefined,
alwaysAllowExtTools: undefined,
alwaysAllowModeSwitch: undefined,
alwaysAllowSubtasks: undefined,
alwaysAllowExecute: undefined,
Expand Down
6 changes: 6 additions & 0 deletions src/core/assistant-message/presentAssistantMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import { askFollowupQuestionTool } from "../tools/askFollowupQuestionTool"
import { switchModeTool } from "../tools/switchModeTool"
import { attemptCompletionTool } from "../tools/attemptCompletionTool"
import { newTaskTool } from "../tools/newTaskTool"
import { useExtToolTool } from "../tools/useExtToolTool"

import { checkpointSave } from "../checkpoints"

Expand Down Expand Up @@ -180,6 +181,8 @@ export async function presentAssistantMessage(cline: Task) {
return `[${block.name} for '${block.params.server_name}']`
case "access_mcp_resource":
return `[${block.name} for '${block.params.server_name}']`
case "use_ext_tool":
return `[${block.name} for '${block.params.extension_id}']`
case "ask_followup_question":
return `[${block.name} for '${block.params.question}']`
case "attempt_completion":
Expand Down Expand Up @@ -440,6 +443,9 @@ export async function presentAssistantMessage(cline: Task) {
removeClosingTag,
)
break
case "use_ext_tool":
await useExtToolTool(cline, block, askApproval, handleError, pushToolResult, removeClosingTag)
break
case "ask_followup_question":
await askFollowupQuestionTool(
cline,
Expand Down
3 changes: 3 additions & 0 deletions src/core/prompts/__tests__/custom-system-prompt.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ describe("File-Based Custom System Prompt", () => {
"test/path", // Using a relative path without leading slash
false, // supportsComputerUse
undefined, // mcpHub
undefined, // extensionToolManager
undefined, // diffStrategy
undefined, // browserViewportSize
defaultModeSlug, // mode
Expand Down Expand Up @@ -101,6 +102,7 @@ describe("File-Based Custom System Prompt", () => {
"test/path", // Using a relative path without leading slash
false, // supportsComputerUse
undefined, // mcpHub
undefined, // extensionToolManager
undefined, // diffStrategy
undefined, // browserViewportSize
defaultModeSlug, // mode
Expand Down Expand Up @@ -144,6 +146,7 @@ describe("File-Based Custom System Prompt", () => {
"test/path", // Using a relative path without leading slash
false, // supportsComputerUse
undefined, // mcpHub
undefined, // extensionToolManager
undefined, // diffStrategy
undefined, // browserViewportSize
defaultModeSlug, // mode
Expand Down
16 changes: 16 additions & 0 deletions src/core/prompts/__tests__/system.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ describe("SYSTEM_PROMPT", () => {
"/test/path",
false, // supportsComputerUse
undefined, // mcpHub
undefined, // extensionToolManager
undefined, // diffStrategy
undefined, // browserViewportSize
defaultModeSlug, // mode
Expand All @@ -222,6 +223,7 @@ describe("SYSTEM_PROMPT", () => {
"/test/path",
true, // supportsComputerUse
undefined, // mcpHub
undefined, // extensionToolManager
undefined, // diffStrategy
"1280x800", // browserViewportSize
defaultModeSlug, // mode
Expand All @@ -244,6 +246,7 @@ describe("SYSTEM_PROMPT", () => {
"/test/path",
false, // supportsComputerUse
mockMcpHub, // mcpHub
undefined, // extensionToolManager
undefined, // diffStrategy
undefined, // browserViewportSize
defaultModeSlug, // mode
Expand All @@ -264,6 +267,7 @@ describe("SYSTEM_PROMPT", () => {
"/test/path",
false, // supportsComputerUse
undefined, // explicitly undefined mcpHub
undefined, // extensionToolManager
undefined, // diffStrategy
undefined, // browserViewportSize
defaultModeSlug, // mode
Expand All @@ -284,6 +288,7 @@ describe("SYSTEM_PROMPT", () => {
"/test/path",
true, // supportsComputerUse
undefined, // mcpHub
undefined, // extensionToolManager
undefined, // diffStrategy
"900x600", // different viewport size
defaultModeSlug, // mode
Expand All @@ -304,6 +309,7 @@ describe("SYSTEM_PROMPT", () => {
"/test/path",
false, // supportsComputerUse
undefined, // mcpHub
undefined, // extensionToolManager
new MultiSearchReplaceDiffStrategy(), // Use actual diff strategy from the codebase
undefined, // browserViewportSize
defaultModeSlug, // mode
Expand All @@ -325,6 +331,7 @@ describe("SYSTEM_PROMPT", () => {
"/test/path",
false, // supportsComputerUse
undefined, // mcpHub
undefined, // extensionToolManager
new MultiSearchReplaceDiffStrategy(), // Use actual diff strategy from the codebase
undefined, // browserViewportSize
defaultModeSlug, // mode
Expand All @@ -346,6 +353,7 @@ describe("SYSTEM_PROMPT", () => {
"/test/path",
false, // supportsComputerUse
undefined, // mcpHub
undefined, // extensionToolManager
new MultiSearchReplaceDiffStrategy(), // Use actual diff strategy from the codebase
undefined, // browserViewportSize
defaultModeSlug, // mode
Expand Down Expand Up @@ -394,6 +402,7 @@ describe("SYSTEM_PROMPT", () => {
"/test/path",
false, // supportsComputerUse
undefined, // mcpHub
undefined, // extensionToolManager
undefined, // diffStrategy
undefined, // browserViewportSize
defaultModeSlug, // mode
Expand Down Expand Up @@ -452,6 +461,7 @@ describe("SYSTEM_PROMPT", () => {
"/test/path",
false, // supportsComputerUse
undefined, // mcpHub
undefined, // extensionToolManager
undefined, // diffStrategy
undefined, // browserViewportSize
"custom-mode", // mode
Expand Down Expand Up @@ -487,6 +497,7 @@ describe("SYSTEM_PROMPT", () => {
"/test/path",
false, // supportsComputerUse
undefined, // mcpHub
undefined, // extensionToolManager
undefined, // diffStrategy
undefined, // browserViewportSize
defaultModeSlug as Mode, // mode
Expand Down Expand Up @@ -517,6 +528,7 @@ describe("SYSTEM_PROMPT", () => {
"/test/path",
false, // supportsComputerUse
undefined, // mcpHub
undefined, // extensionToolManager
undefined, // diffStrategy
undefined, // browserViewportSize
defaultModeSlug as Mode, // mode
Expand Down Expand Up @@ -561,6 +573,7 @@ describe("addCustomInstructions", () => {
"/test/path",
false, // supportsComputerUse
undefined, // mcpHub
undefined, // extensionToolManager
undefined, // diffStrategy
undefined, // browserViewportSize
"architect", // mode
Expand All @@ -581,6 +594,7 @@ describe("addCustomInstructions", () => {
"/test/path",
false, // supportsComputerUse
undefined, // mcpHub
undefined, // extensionToolManager
undefined, // diffStrategy
undefined, // browserViewportSize
"ask", // mode
Expand All @@ -603,6 +617,7 @@ describe("addCustomInstructions", () => {
"/test/path",
false, // supportsComputerUse
mockMcpHub, // mcpHub
undefined, // extensionToolManager
undefined, // diffStrategy
undefined, // browserViewportSize
defaultModeSlug, // mode
Expand All @@ -626,6 +641,7 @@ describe("addCustomInstructions", () => {
"/test/path",
false, // supportsComputerUse
mockMcpHub, // mcpHub
undefined, // extensionToolManager
undefined, // diffStrategy
undefined, // browserViewportSize
defaultModeSlug, // mode
Expand Down
3 changes: 3 additions & 0 deletions src/core/prompts/responses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ Otherwise, if you have not completed the task and do not need additional informa
invalidMcpToolArgumentError: (serverName: string, toolName: string) =>
`Invalid JSON argument used with ${serverName} for ${toolName}. Please retry with a properly formatted JSON argument.`,

invalidExtToolArgumentError: (extensionId: string, toolName: string) =>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This error message formatter duplicates the existing invalidMcpToolArgumentError. Consider consolidating these into a single function.

This comment was generated because it violated a code review rule: mrule_fYE6mUdYYxZL58YF.

`Invalid JSON argument used with ${extensionId} for ${toolName}. Please retry with a properly formatted JSON argument.`,

toolResult: (
text: string,
images?: string[],
Expand Down
48 changes: 48 additions & 0 deletions src/core/prompts/sections/ext-tools.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { ExtensionToolManager } from "../../../services/extensions/ExtensionToolManager"

/**
* Generates the section of the system prompt that describes available extension tools
*/
export async function getExtToolsSection(extensionToolManager?: ExtensionToolManager): Promise<string> {
// If no manager is provided, get the singleton instance
if (!extensionToolManager) {
try {
extensionToolManager = await ExtensionToolManager.getInstance()
} catch (error) {
console.error("Failed to get ExtensionToolManager:", error)
return ""
}
}

// Get all registered tools
const allTools = extensionToolManager.getAllTools()

if (allTools.length === 0) {
return ""
}

// Group tools by extension
const extensionTools: Record<string, string[]> = {}

for (const { extensionId, tool } of allTools) {
if (!extensionTools[extensionId]) {
extensionTools[extensionId] = []
}

extensionTools[extensionId].push(`${tool.name}: ${tool.description}`)
}

let result = "# Available Extension Tools\n\n"

for (const [extensionId, tools] of Object.entries(extensionTools)) {
result += `## Extension: ${extensionId}\n\n`

for (const toolDesc of tools) {
result += `- ${toolDesc}\n`
}

result += "\n"
}

return result
}
1 change: 1 addition & 0 deletions src/core/prompts/sections/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export { getObjectiveSection } from "./objective"
export { addCustomInstructions } from "./custom-instructions"
export { getSharedToolUseSection } from "./tool-use"
export { getMcpServersSection } from "./mcp-servers"
export { getExtToolsSection } from "./ext-tools"
export { getToolUseGuidelinesSection } from "./tool-use-guidelines"
export { getCapabilitiesSection } from "./capabilities"
export { getModesSection } from "./modes"
Expand Down
Loading
Loading