diff --git a/packages/core/src/custom-tools/__tests__/__snapshots__/format-native.spec.ts.snap b/packages/core/src/custom-tools/__tests__/__snapshots__/format-native.spec.ts.snap
index d734e60baf9..d4ca0b16832 100644
--- a/packages/core/src/custom-tools/__tests__/__snapshots__/format-native.spec.ts.snap
+++ b/packages/core/src/custom-tools/__tests__/__snapshots__/format-native.spec.ts.snap
@@ -11,6 +11,7 @@ exports[`Native Protocol snapshots > should generate correct native definition f
"required": [],
"type": "object",
},
+ "source": undefined,
"strict": true,
},
"type": "function",
@@ -35,6 +36,7 @@ exports[`Native Protocol snapshots > should generate correct native definition f
],
"type": "object",
},
+ "source": undefined,
"strict": true,
},
"type": "function",
@@ -52,6 +54,7 @@ exports[`Native Protocol snapshots > should generate correct native definition f
"required": [],
"type": "object",
},
+ "source": undefined,
"strict": true,
},
"type": "function",
@@ -76,6 +79,7 @@ exports[`Native Protocol snapshots > should generate correct native definition f
],
"type": "object",
},
+ "source": undefined,
"strict": true,
},
"type": "function",
@@ -101,6 +105,7 @@ exports[`Native Protocol snapshots > should generate correct native definitions
],
"type": "object",
},
+ "source": undefined,
"strict": true,
},
"type": "function",
@@ -115,6 +120,7 @@ exports[`Native Protocol snapshots > should generate correct native definitions
"required": [],
"type": "object",
},
+ "source": undefined,
"strict": true,
},
"type": "function",
@@ -136,6 +142,7 @@ exports[`Native Protocol snapshots > should generate correct native definitions
],
"type": "object",
},
+ "source": undefined,
"strict": true,
},
"type": "function",
@@ -150,6 +157,7 @@ exports[`Native Protocol snapshots > should generate correct native definitions
"required": [],
"type": "object",
},
+ "source": undefined,
"strict": true,
},
"type": "function",
@@ -164,6 +172,7 @@ exports[`Native Protocol snapshots > should generate correct native definitions
"required": [],
"type": "object",
},
+ "source": undefined,
"strict": true,
},
"type": "function",
@@ -178,6 +187,7 @@ exports[`Native Protocol snapshots > should generate correct native definitions
"required": [],
"type": "object",
},
+ "source": undefined,
"strict": true,
},
"type": "function",
@@ -197,6 +207,7 @@ exports[`Native Protocol snapshots > should generate correct native definitions
"required": [],
"type": "object",
},
+ "source": undefined,
"strict": true,
},
"type": "function",
@@ -211,6 +222,7 @@ exports[`Native Protocol snapshots > should generate correct native definitions
"required": [],
"type": "object",
},
+ "source": undefined,
"strict": true,
},
"type": "function",
diff --git a/packages/core/src/custom-tools/__tests__/__snapshots__/serialize.spec.ts.snap b/packages/core/src/custom-tools/__tests__/__snapshots__/serialize.spec.ts.snap
index 6b55c3f8e17..6da6a93e9c1 100644
--- a/packages/core/src/custom-tools/__tests__/__snapshots__/serialize.spec.ts.snap
+++ b/packages/core/src/custom-tools/__tests__/__snapshots__/serialize.spec.ts.snap
@@ -19,6 +19,7 @@ exports[`Serialization snapshots > should correctly serialize all fixtures 1`] =
],
"type": "object",
},
+ "source": undefined,
},
{
"description": "Cached tool",
@@ -29,6 +30,7 @@ exports[`Serialization snapshots > should correctly serialize all fixtures 1`] =
"properties": {},
"type": "object",
},
+ "source": undefined,
},
{
"description": "Legacy tool using args",
@@ -47,6 +49,7 @@ exports[`Serialization snapshots > should correctly serialize all fixtures 1`] =
],
"type": "object",
},
+ "source": undefined,
},
{
"description": "Tool A",
@@ -57,6 +60,7 @@ exports[`Serialization snapshots > should correctly serialize all fixtures 1`] =
"properties": {},
"type": "object",
},
+ "source": undefined,
},
{
"description": "Tool B",
@@ -67,6 +71,7 @@ exports[`Serialization snapshots > should correctly serialize all fixtures 1`] =
"properties": {},
"type": "object",
},
+ "source": undefined,
},
{
"description": "Valid",
@@ -77,6 +82,7 @@ exports[`Serialization snapshots > should correctly serialize all fixtures 1`] =
"properties": {},
"type": "object",
},
+ "source": undefined,
},
]
`;
@@ -91,6 +97,7 @@ exports[`Serialization snapshots > should correctly serialize cached tool 1`] =
"properties": {},
"type": "object",
},
+ "source": undefined,
}
`;
@@ -112,6 +119,7 @@ exports[`Serialization snapshots > should correctly serialize legacy tool (using
],
"type": "object",
},
+ "source": undefined,
}
`;
@@ -133,5 +141,6 @@ exports[`Serialization snapshots > should correctly serialize simple tool 1`] =
],
"type": "object",
},
+ "source": undefined,
}
`;
diff --git a/packages/core/src/custom-tools/__tests__/custom-tool-registry.spec.ts b/packages/core/src/custom-tools/__tests__/custom-tool-registry.spec.ts
index 27265db3098..967ae2e8df7 100644
--- a/packages/core/src/custom-tools/__tests__/custom-tool-registry.spec.ts
+++ b/packages/core/src/custom-tools/__tests__/custom-tool-registry.spec.ts
@@ -10,6 +10,7 @@ import { CustomToolRegistry } from "../custom-tool-registry.js"
const __dirname = path.dirname(fileURLToPath(import.meta.url))
const TEST_FIXTURES_DIR = path.join(__dirname, "fixtures")
+const TEST_FIXTURES_OVERRIDE_DIR = path.join(__dirname, "fixtures-override")
describe("CustomToolRegistry", () => {
let registry: CustomToolRegistry
@@ -282,4 +283,99 @@ describe("CustomToolRegistry", () => {
expect(result.loaded).toContain("cached")
}, 30000)
})
+
+ describe.sequential("loadFromDirectories", () => {
+ it("should load tools from multiple directories", async () => {
+ const result = await registry.loadFromDirectories([TEST_FIXTURES_DIR, TEST_FIXTURES_OVERRIDE_DIR])
+
+ // Should load tools from both directories.
+ expect(result.loaded).toContain("simple") // From both directories (override wins).
+ expect(result.loaded).toContain("unique_override") // Only in override directory.
+ expect(result.loaded).toContain("multi_toolA") // Only in fixtures directory.
+ }, 60000)
+
+ it("should allow later directories to override earlier ones", async () => {
+ await registry.loadFromDirectories([TEST_FIXTURES_DIR, TEST_FIXTURES_OVERRIDE_DIR])
+
+ // The simple tool should have the overridden description.
+ const simpleTool = registry.get("simple")
+ expect(simpleTool).toBeDefined()
+ expect(simpleTool?.description).toBe("Simple tool - OVERRIDDEN")
+ }, 60000)
+
+ it("should preserve order: first directory loaded first, second overrides", async () => {
+ // Load in reverse order: override first, then fixtures.
+ await registry.loadFromDirectories([TEST_FIXTURES_OVERRIDE_DIR, TEST_FIXTURES_DIR])
+
+ // Now the original fixtures directory should win.
+ const simpleTool = registry.get("simple")
+ expect(simpleTool).toBeDefined()
+ expect(simpleTool?.description).toBe("Simple tool") // Original wins when loaded second.
+ }, 60000)
+
+ it("should handle non-existent directories in the array", async () => {
+ const result = await registry.loadFromDirectories([
+ "/nonexistent/path",
+ TEST_FIXTURES_DIR,
+ "/another/nonexistent",
+ ])
+
+ // Should still load from the existing directory.
+ expect(result.loaded).toContain("simple")
+ expect(result.failed).toHaveLength(1) // Only the invalid.ts from fixtures.
+ }, 60000)
+
+ it("should handle empty array", async () => {
+ const result = await registry.loadFromDirectories([])
+
+ expect(result.loaded).toHaveLength(0)
+ expect(result.failed).toHaveLength(0)
+ })
+
+ it("should combine results from all directories", async () => {
+ const result = await registry.loadFromDirectories([TEST_FIXTURES_DIR, TEST_FIXTURES_OVERRIDE_DIR])
+
+ // Loaded should include tools from both (with duplicates since simple is loaded twice).
+ // The "simple" tool is loaded from both directories.
+ const simpleCount = result.loaded.filter((name) => name === "simple").length
+ expect(simpleCount).toBe(2) // Listed twice in loaded results.
+ }, 60000)
+ })
+
+ describe.sequential("loadFromDirectoriesIfStale", () => {
+ it("should load tools from multiple directories when stale", async () => {
+ const result = await registry.loadFromDirectoriesIfStale([TEST_FIXTURES_DIR, TEST_FIXTURES_OVERRIDE_DIR])
+
+ expect(result.loaded).toContain("simple")
+ expect(result.loaded).toContain("unique_override")
+ }, 60000)
+
+ it("should not reload if directories are not stale", async () => {
+ // First load.
+ await registry.loadFromDirectoriesIfStale([TEST_FIXTURES_DIR])
+
+ // Clear tools but keep staleness tracking.
+ // (firstLoadSize is captured to document that tools were loaded, then cleared).
+ const _firstLoadSize = registry.size
+ registry.clear()
+
+ // Second load - should return cached tool names without reloading.
+ const result = await registry.loadFromDirectoriesIfStale([TEST_FIXTURES_DIR])
+
+ // Registry was cleared, not stale so no reload.
+ expect(result.loaded).toEqual([])
+ }, 30000)
+
+ it("should handle mixed stale and non-stale directories", async () => {
+ // Load from fixtures first.
+ await registry.loadFromDirectoriesIfStale([TEST_FIXTURES_DIR])
+
+ // Load from both - fixtures is not stale, override is new (stale).
+ const result = await registry.loadFromDirectoriesIfStale([TEST_FIXTURES_DIR, TEST_FIXTURES_OVERRIDE_DIR])
+
+ // Override directory tools should be loaded (it's stale/new).
+ expect(result.loaded).toContain("simple") // From override (stale).
+ expect(result.loaded).toContain("unique_override") // From override (stale).
+ }, 60000)
+ })
})
diff --git a/packages/core/src/custom-tools/__tests__/fixtures-override/simple.ts b/packages/core/src/custom-tools/__tests__/fixtures-override/simple.ts
new file mode 100644
index 00000000000..9235f4e3337
--- /dev/null
+++ b/packages/core/src/custom-tools/__tests__/fixtures-override/simple.ts
@@ -0,0 +1,11 @@
+import { parametersSchema, defineCustomTool } from "@roo-code/types"
+
+// This tool has the same name as the one in fixtures/ to test override behavior.
+export default defineCustomTool({
+ name: "simple",
+ description: "Simple tool - OVERRIDDEN",
+ parameters: parametersSchema.object({ value: parametersSchema.string().describe("The input value") }),
+ async execute(args: { value: string }) {
+ return "Overridden Result: " + args.value
+ },
+})
diff --git a/packages/core/src/custom-tools/__tests__/fixtures-override/unique.ts b/packages/core/src/custom-tools/__tests__/fixtures-override/unique.ts
new file mode 100644
index 00000000000..867d2446499
--- /dev/null
+++ b/packages/core/src/custom-tools/__tests__/fixtures-override/unique.ts
@@ -0,0 +1,11 @@
+import { parametersSchema, defineCustomTool } from "@roo-code/types"
+
+// This tool only exists in fixtures-override/ to test combined loading.
+export default defineCustomTool({
+ name: "unique_override",
+ description: "A unique tool only in override directory",
+ parameters: parametersSchema.object({ input: parametersSchema.string().describe("The input") }),
+ async execute(args: { input: string }) {
+ return "Unique: " + args.input
+ },
+})
diff --git a/packages/core/src/custom-tools/custom-tool-registry.ts b/packages/core/src/custom-tools/custom-tool-registry.ts
index a9b2b1e8e12..ee72f68d8e5 100644
--- a/packages/core/src/custom-tools/custom-tool-registry.ts
+++ b/packages/core/src/custom-tools/custom-tool-registry.ts
@@ -15,14 +15,10 @@ import os from "os"
import type { CustomToolDefinition, SerializedCustomToolDefinition, CustomToolParametersSchema } from "@roo-code/types"
+import type { StoredCustomTool, LoadResult } from "./types.js"
import { serializeCustomTool } from "./serialize.js"
import { runEsbuild } from "./esbuild-runner.js"
-export interface LoadResult {
- loaded: string[]
- failed: Array<{ file: string; error: string }>
-}
-
export interface RegistryOptions {
/** Directory for caching compiled TypeScript files. */
cacheDir?: string
@@ -33,7 +29,7 @@ export interface RegistryOptions {
}
export class CustomToolRegistry {
- private tools = new Map()
+ private tools = new Map()
private tsCache = new Map()
private cacheDir: string
private nodePaths: string[]
@@ -78,7 +74,7 @@ export class CustomToolRegistry {
continue
}
- this.tools.set(def.name, def)
+ this.tools.set(def.name, { ...def, source: filePath })
console.log(`[CustomToolRegistry] loaded tool ${def.name} from ${filePath}`)
result.loaded.push(def.name)
}
@@ -113,10 +109,49 @@ export class CustomToolRegistry {
return { loaded: this.list(), failed: [] }
}
+ /**
+ * Load all tools from multiple directories.
+ * Directories are processed in order, so later directories can override tools from earlier ones.
+ * Supports both .ts and .js files.
+ *
+ * @param toolDirs - Array of absolute paths to tools directories
+ * @returns LoadResult with lists of loaded and failed tools from all directories
+ */
+ async loadFromDirectories(toolDirs: string[]): Promise {
+ const result: LoadResult = { loaded: [], failed: [] }
+
+ for (const toolDir of toolDirs) {
+ const dirResult = await this.loadFromDirectory(toolDir)
+ result.loaded.push(...dirResult.loaded)
+ result.failed.push(...dirResult.failed)
+ }
+
+ return result
+ }
+
+ /**
+ * Load all tools from multiple directories if any has become stale.
+ * Directories are processed in order, so later directories can override tools from earlier ones.
+ *
+ * @param toolDirs - Array of absolute paths to tools directories
+ * @returns LoadResult with lists of loaded and failed tools
+ */
+ async loadFromDirectoriesIfStale(toolDirs: string[]): Promise {
+ const result: LoadResult = { loaded: [], failed: [] }
+
+ for (const toolDir of toolDirs) {
+ const dirResult = await this.loadFromDirectoryIfStale(toolDir)
+ result.loaded.push(...dirResult.loaded)
+ result.failed.push(...dirResult.failed)
+ }
+
+ return result
+ }
+
/**
* Register a tool directly (without loading from file).
*/
- register(definition: CustomToolDefinition): void {
+ register(definition: CustomToolDefinition, source?: string): void {
const { name: id } = definition
const validated = this.validate(id, definition)
@@ -124,7 +159,8 @@ export class CustomToolRegistry {
throw new Error(`Invalid tool definition for '${id}'`)
}
- this.tools.set(id, validated)
+ const storedTool: StoredCustomTool = source ? { ...validated, source } : validated
+ this.tools.set(id, storedTool)
}
/**
diff --git a/packages/core/src/custom-tools/serialize.ts b/packages/core/src/custom-tools/serialize.ts
index dc4eceb87e5..c347bf0be12 100644
--- a/packages/core/src/custom-tools/serialize.ts
+++ b/packages/core/src/custom-tools/serialize.ts
@@ -1,17 +1,21 @@
-import { type CustomToolDefinition, type SerializedCustomToolDefinition, parametersSchema } from "@roo-code/types"
+import { type SerializedCustomToolDefinition, parametersSchema } from "@roo-code/types"
+
+import type { StoredCustomTool } from "./types.js"
export function serializeCustomTool({
name,
description,
parameters,
-}: CustomToolDefinition): SerializedCustomToolDefinition {
+ source,
+}: StoredCustomTool): SerializedCustomToolDefinition {
return {
name,
description,
parameters: parameters ? parametersSchema.toJSONSchema(parameters) : undefined,
+ source,
}
}
-export function serializeCustomTools(tools: CustomToolDefinition[]): SerializedCustomToolDefinition[] {
+export function serializeCustomTools(tools: StoredCustomTool[]): SerializedCustomToolDefinition[] {
return tools.map(serializeCustomTool)
}
diff --git a/packages/core/src/custom-tools/types.ts b/packages/core/src/custom-tools/types.ts
new file mode 100644
index 00000000000..fbe871e7893
--- /dev/null
+++ b/packages/core/src/custom-tools/types.ts
@@ -0,0 +1,8 @@
+import { type CustomToolDefinition } from "@roo-code/types"
+
+export type StoredCustomTool = CustomToolDefinition & { source?: string }
+
+export interface LoadResult {
+ loaded: string[]
+ failed: Array<{ file: string; error: string }>
+}
diff --git a/packages/types/src/custom-tool.ts b/packages/types/src/custom-tool.ts
index 2ad40c4d234..ba0bff1c908 100644
--- a/packages/types/src/custom-tool.ts
+++ b/packages/types/src/custom-tool.ts
@@ -59,6 +59,7 @@ export interface SerializedCustomToolDefinition {
name: string
description: string
parameters?: SerializedCustomToolParameters
+ source?: string
}
/**
diff --git a/src/core/task/build-tools.ts b/src/core/task/build-tools.ts
index b636052341f..8eea4ace82c 100644
--- a/src/core/task/build-tools.ts
+++ b/src/core/task/build-tools.ts
@@ -6,6 +6,7 @@ import type { ProviderSettings, ModeConfig, ModelInfo } from "@roo-code/types"
import { customToolRegistry, formatNative } from "@roo-code/core"
import type { ClineProvider } from "../webview/ClineProvider"
+import { getRooDirectoriesForCwd } from "../../services/roo-config/index.js"
import { getNativeTools, getMcpServerTools } from "../prompts/tools/native-tools"
import { filterNativeToolsForMode, filterMcpToolsForMode } from "../prompts/tools/filter-tools-for-mode"
@@ -83,7 +84,8 @@ export async function buildNativeToolsArray(options: BuildToolsOptions): Promise
let nativeCustomTools: OpenAI.Chat.ChatCompletionFunctionTool[] = []
if (experiments?.customTools) {
- await customToolRegistry.loadFromDirectoryIfStale(path.join(cwd, ".roo", "tools"))
+ const toolDirs = getRooDirectoriesForCwd(cwd).map((dir) => path.join(dir, "tools"))
+ await customToolRegistry.loadFromDirectoriesIfStale(toolDirs)
const customTools = customToolRegistry.getAllSerialized()
if (customTools.length > 0) {
diff --git a/src/core/webview/webviewMessageHandler.ts b/src/core/webview/webviewMessageHandler.ts
index e042c5c1c67..be8e5291df1 100644
--- a/src/core/webview/webviewMessageHandler.ts
+++ b/src/core/webview/webviewMessageHandler.ts
@@ -2,6 +2,7 @@ import { safeWriteJson } from "../../utils/safeWriteJson"
import * as path from "path"
import * as os from "os"
import * as fs from "fs/promises"
+import { getRooDirectoriesForCwd } from "../../services/roo-config/index.js"
import pWaitFor from "p-wait-for"
import * as vscode from "vscode"
@@ -13,7 +14,6 @@ import {
type UserSettingsConfig,
TelemetryEventName,
RooCodeSettings,
- Experiments,
ExperimentId,
} from "@roo-code/types"
import { customToolRegistry } from "@roo-code/core"
@@ -1728,7 +1728,8 @@ export const webviewMessageHandler = async (
}
case "refreshCustomTools": {
try {
- await customToolRegistry.loadFromDirectory(path.join(getCurrentCwd(), ".roo", "tools"))
+ const toolDirs = getRooDirectoriesForCwd(getCurrentCwd()).map((dir) => path.join(dir, "tools"))
+ await customToolRegistry.loadFromDirectories(toolDirs)
await provider.postMessageToWebview({
type: "customToolsResult",
diff --git a/webview-ui/src/components/settings/CustomToolsSettings.tsx b/webview-ui/src/components/settings/CustomToolsSettings.tsx
index 176272734cd..03bff7fc8a4 100644
--- a/webview-ui/src/components/settings/CustomToolsSettings.tsx
+++ b/webview-ui/src/components/settings/CustomToolsSettings.tsx
@@ -1,7 +1,7 @@
import { useState, useEffect, useCallback, useMemo } from "react"
import { useEvent } from "react-use"
import { VSCodeCheckbox } from "@vscode/webview-ui-toolkit/react"
-import { RefreshCw, Loader2 } from "lucide-react"
+import { RefreshCw, Loader2, FileCode } from "lucide-react"
import type { SerializedCustomToolDefinition } from "@roo-code/types"
@@ -22,6 +22,7 @@ interface ProcessedTool {
name: string
description: string
parameters: ToolParameter[]
+ source?: string
}
interface CustomToolsSettingsProps {
@@ -69,6 +70,7 @@ export const CustomToolsSettings = ({ enabled, onChange }: CustomToolsSettingsPr
return {
name: tool.name,
description: tool.description,
+ source: tool.source,
parameters: Object.entries(properties).map(([name, def]) => ({
name,
type: def.type ?? "any",
@@ -124,47 +126,55 @@ export const CustomToolsSettings = ({ enabled, onChange }: CustomToolsSettingsPr
{t("settings:experimental.CUSTOM_TOOLS.noTools")}
) : (
-
- {processedTools.map((tool) => (
-
+ processedTools.map((tool) => (
+
+
{tool.name}
-
{tool.description}
- {tool.parameters.length > 0 && (
-
-
- {t("settings:experimental.CUSTOM_TOOLS.toolParameters")}:
-
-
- {tool.parameters.map((param) => (
-
-
- {param.name}
-
-
- ({param.type})
-
- {param.required && (
-
- required
-
- )}
- {param.description && (
-
- — {param.description}
-
- )}
-
- ))}
-
+ {tool.source && (
+
+
+
+ {tool.source}
+
)}
- ))}
-
+
{tool.description}
+ {tool.parameters.length > 0 && (
+
+
+ {t("settings:experimental.CUSTOM_TOOLS.toolParameters")}:
+
+
+ {tool.parameters.map((param) => (
+
+
+ {param.name}
+
+
+ ({param.type})
+
+ {param.required && (
+
+ required
+
+ )}
+ {param.description && (
+
+ — {param.description}
+
+ )}
+
+ ))}
+
+
+ )}
+
+ ))
)}
)}
diff --git a/webview-ui/src/i18n/locales/ca/settings.json b/webview-ui/src/i18n/locales/ca/settings.json
index abcfb3d4c4a..c64dccde8f1 100644
--- a/webview-ui/src/i18n/locales/ca/settings.json
+++ b/webview-ui/src/i18n/locales/ca/settings.json
@@ -827,9 +827,9 @@
},
"CUSTOM_TOOLS": {
"name": "Habilitar eines personalitzades",
- "description": "Quan està habilitat, Roo pot carregar i utilitzar eines TypeScript/JavaScript personalitzades des del directori .roo/tools del vostre projecte.",
+ "description": "Quan està habilitat, Roo pot carregar i utilitzar eines TypeScript/JavaScript personalitzades des del directori .roo/tools del vostre projecte o ~/.roo/tools per a eines globals. Nota: aquestes eines s'aprovaran automàticament.",
"toolsHeader": "Eines personalitzades disponibles",
- "noTools": "No s'han carregat eines personalitzades. Afegiu fitxers .ts o .js al directori .roo/tools del vostre projecte.",
+ "noTools": "No s'han carregat eines personalitzades. Afegiu fitxers .ts o .js al directori .roo/tools del vostre projecte o ~/.roo/tools per a eines globals.",
"refreshButton": "Actualitzar",
"refreshing": "Actualitzant...",
"refreshSuccess": "Eines actualitzades correctament",
diff --git a/webview-ui/src/i18n/locales/de/settings.json b/webview-ui/src/i18n/locales/de/settings.json
index 7d9e211b1c6..ced4a8b428e 100644
--- a/webview-ui/src/i18n/locales/de/settings.json
+++ b/webview-ui/src/i18n/locales/de/settings.json
@@ -827,9 +827,9 @@
},
"CUSTOM_TOOLS": {
"name": "Benutzerdefinierte Tools aktivieren",
- "description": "Wenn aktiviert, kann Roo benutzerdefinierte TypeScript/JavaScript-Tools aus dem .roo/tools-Verzeichnis deines Projekts laden und verwenden.",
+ "description": "Wenn aktiviert, kann Roo benutzerdefinierte TypeScript/JavaScript-Tools aus dem .roo/tools-Verzeichnis deines Projekts oder ~/.roo/tools für globale Tools laden und verwenden. Hinweis: Diese Tools werden automatisch genehmigt.",
"toolsHeader": "Verfügbare benutzerdefinierte Tools",
- "noTools": "Keine benutzerdefinierten Tools geladen. Füge .ts- oder .js-Dateien zum .roo/tools-Verzeichnis deines Projekts hinzu.",
+ "noTools": "Keine benutzerdefinierten Tools geladen. Füge .ts- oder .js-Dateien zum .roo/tools-Verzeichnis deines Projekts oder ~/.roo/tools für globale Tools hinzu.",
"refreshButton": "Aktualisieren",
"refreshing": "Aktualisieren...",
"refreshSuccess": "Tools erfolgreich aktualisiert",
diff --git a/webview-ui/src/i18n/locales/en/settings.json b/webview-ui/src/i18n/locales/en/settings.json
index 32a401cd0d6..a4aeea1ae63 100644
--- a/webview-ui/src/i18n/locales/en/settings.json
+++ b/webview-ui/src/i18n/locales/en/settings.json
@@ -836,9 +836,9 @@
},
"CUSTOM_TOOLS": {
"name": "Enable custom tools",
- "description": "When enabled, Roo can load and use custom TypeScript/JavaScript tools from your project's .roo/tools directory. Note: these tools will automatically be auto-approved.",
+ "description": "When enabled, Roo can load and use custom TypeScript/JavaScript tools from your project's .roo/tools directory or ~/.roo/tools for global tools. Note: these tools will automatically be auto-approved.",
"toolsHeader": "Available Custom Tools",
- "noTools": "No custom tools loaded. Add .ts or .js files to your project's .roo/tools directory.",
+ "noTools": "No custom tools loaded. Add .ts or .js files to your project's .roo/tools directory or ~/.roo/tools for global tools.",
"refreshButton": "Refresh",
"refreshing": "Refreshing...",
"refreshSuccess": "Tools refreshed successfully",
diff --git a/webview-ui/src/i18n/locales/es/settings.json b/webview-ui/src/i18n/locales/es/settings.json
index 3a83c21a23e..e0e1881d177 100644
--- a/webview-ui/src/i18n/locales/es/settings.json
+++ b/webview-ui/src/i18n/locales/es/settings.json
@@ -827,9 +827,9 @@
},
"CUSTOM_TOOLS": {
"name": "Habilitar herramientas personalizadas",
- "description": "Cuando está habilitado, Roo puede cargar y usar herramientas TypeScript/JavaScript personalizadas desde el directorio .roo/tools de tu proyecto.",
+ "description": "Cuando está habilitado, Roo puede cargar y usar herramientas TypeScript/JavaScript personalizadas desde el directorio .roo/tools de tu proyecto o ~/.roo/tools para herramientas globales. Nota: estas herramientas se aprobarán automáticamente.",
"toolsHeader": "Herramientas personalizadas disponibles",
- "noTools": "No hay herramientas personalizadas cargadas. Añade archivos .ts o .js al directorio .roo/tools de tu proyecto.",
+ "noTools": "No hay herramientas personalizadas cargadas. Añade archivos .ts o .js al directorio .roo/tools de tu proyecto o ~/.roo/tools para herramientas globales.",
"refreshButton": "Actualizar",
"refreshing": "Actualizando...",
"refreshSuccess": "Herramientas actualizadas correctamente",
diff --git a/webview-ui/src/i18n/locales/fr/settings.json b/webview-ui/src/i18n/locales/fr/settings.json
index 99f0406f66b..6ff29c77a45 100644
--- a/webview-ui/src/i18n/locales/fr/settings.json
+++ b/webview-ui/src/i18n/locales/fr/settings.json
@@ -827,9 +827,9 @@
},
"CUSTOM_TOOLS": {
"name": "Activer les outils personnalisés",
- "description": "Lorsqu'activé, Roo peut charger et utiliser des outils TypeScript/JavaScript personnalisés à partir du répertoire .roo/tools de votre projet.",
+ "description": "Lorsqu'activé, Roo peut charger et utiliser des outils TypeScript/JavaScript personnalisés à partir du répertoire .roo/tools de votre projet ou ~/.roo/tools pour des outils globaux. Remarque : ces outils seront automatiquement approuvés.",
"toolsHeader": "Outils personnalisés disponibles",
- "noTools": "Aucun outil personnalisé chargé. Ajoutez des fichiers .ts ou .js au répertoire .roo/tools de votre projet.",
+ "noTools": "Aucun outil personnalisé chargé. Ajoutez des fichiers .ts ou .js au répertoire .roo/tools de votre projet ou ~/.roo/tools pour des outils globaux.",
"refreshButton": "Actualiser",
"refreshing": "Actualisation...",
"refreshSuccess": "Outils actualisés avec succès",
diff --git a/webview-ui/src/i18n/locales/hi/settings.json b/webview-ui/src/i18n/locales/hi/settings.json
index 65cbee91caf..06efbf63243 100644
--- a/webview-ui/src/i18n/locales/hi/settings.json
+++ b/webview-ui/src/i18n/locales/hi/settings.json
@@ -828,9 +828,9 @@
},
"CUSTOM_TOOLS": {
"name": "कस्टम टूल्स सक्षम करें",
- "description": "सक्षम होने पर, Roo आपके प्रोजेक्ट की .roo/tools निर्देशिका से कस्टम TypeScript/JavaScript टूल्स लोड और उपयोग कर सकता है।",
+ "description": "सक्षम होने पर, Roo आपके प्रोजेक्ट की .roo/tools निर्देशिका या वैश्विक टूल्स के लिए ~/.roo/tools से कस्टम TypeScript/JavaScript टूल्स लोड और उपयोग कर सकता है। नोट: ये टूल्स स्वचालित रूप से स्वत:-अनुमोदित होंगे।",
"toolsHeader": "उपलब्ध कस्टम टूल्स",
- "noTools": "कोई कस्टम टूल लोड नहीं हुआ। अपने प्रोजेक्ट की .roo/tools निर्देशिका में .ts या .js फ़ाइलें जोड़ें।",
+ "noTools": "कोई कस्टम टूल लोड नहीं हुआ। अपने प्रोजेक्ट की .roo/tools निर्देशिका या वैश्विक टूल्स के लिए ~/.roo/tools में .ts या .js फ़ाइलें जोड़ें।",
"refreshButton": "रिफ्रेश करें",
"refreshing": "रिफ्रेश हो रहा है...",
"refreshSuccess": "टूल्स सफलतापूर्वक रिफ्रेश हुए",
diff --git a/webview-ui/src/i18n/locales/id/settings.json b/webview-ui/src/i18n/locales/id/settings.json
index 8cfcbb8f1c7..6cae436f089 100644
--- a/webview-ui/src/i18n/locales/id/settings.json
+++ b/webview-ui/src/i18n/locales/id/settings.json
@@ -857,9 +857,9 @@
},
"CUSTOM_TOOLS": {
"name": "Aktifkan tool kustom",
- "description": "Ketika diaktifkan, Roo dapat memuat dan menggunakan tool TypeScript/JavaScript kustom dari direktori .roo/tools proyek Anda.",
+ "description": "Ketika diaktifkan, Roo dapat memuat dan menggunakan tool TypeScript/JavaScript kustom dari direktori .roo/tools proyek Anda atau ~/.roo/tools untuk tool global. Catatan: tool ini akan disetujui otomatis.",
"toolsHeader": "Tool Kustom yang Tersedia",
- "noTools": "Tidak ada tool kustom yang dimuat. Tambahkan file .ts atau .js ke direktori .roo/tools proyek Anda.",
+ "noTools": "Tidak ada tool kustom yang dimuat. Tambahkan file .ts atau .js ke direktori .roo/tools proyek Anda atau ~/.roo/tools untuk tool global.",
"refreshButton": "Refresh",
"refreshing": "Merefresh...",
"refreshSuccess": "Tool berhasil direfresh",
diff --git a/webview-ui/src/i18n/locales/it/settings.json b/webview-ui/src/i18n/locales/it/settings.json
index 6967ba6d0c9..aebc6d9aa22 100644
--- a/webview-ui/src/i18n/locales/it/settings.json
+++ b/webview-ui/src/i18n/locales/it/settings.json
@@ -828,9 +828,9 @@
},
"CUSTOM_TOOLS": {
"name": "Abilita strumenti personalizzati",
- "description": "Quando abilitato, Roo può caricare e utilizzare strumenti TypeScript/JavaScript personalizzati dalla directory .roo/tools del tuo progetto.",
+ "description": "Quando abilitato, Roo può caricare e utilizzare strumenti TypeScript/JavaScript personalizzati dalla directory .roo/tools del tuo progetto o ~/.roo/tools per strumenti globali. Nota: questi strumenti saranno automaticamente approvati.",
"toolsHeader": "Strumenti personalizzati disponibili",
- "noTools": "Nessuno strumento personalizzato caricato. Aggiungi file .ts o .js alla directory .roo/tools del tuo progetto.",
+ "noTools": "Nessuno strumento personalizzato caricato. Aggiungi file .ts o .js alla directory .roo/tools del tuo progetto o ~/.roo/tools per strumenti globali.",
"refreshButton": "Aggiorna",
"refreshing": "Aggiornamento...",
"refreshSuccess": "Strumenti aggiornati con successo",
diff --git a/webview-ui/src/i18n/locales/ja/settings.json b/webview-ui/src/i18n/locales/ja/settings.json
index 36fc3e3bf72..44a1da4dc4c 100644
--- a/webview-ui/src/i18n/locales/ja/settings.json
+++ b/webview-ui/src/i18n/locales/ja/settings.json
@@ -828,9 +828,9 @@
},
"CUSTOM_TOOLS": {
"name": "カスタムツールを有効化",
- "description": "有効にすると、Rooはプロジェクトの.roo/toolsディレクトリからカスタムTypeScript/JavaScriptツールを読み込んで使用できます。",
+ "description": "有効にすると、Rooはプロジェクトの.roo/toolsディレクトリまたはグローバルツール用の~/.roo/toolsからカスタムTypeScript/JavaScriptツールを読み込んで使用できます。注意:これらのツールは自動的に承認されます。",
"toolsHeader": "利用可能なカスタムツール",
- "noTools": "カスタムツールが読み込まれていません。プロジェクトの.roo/toolsディレクトリに.tsまたは.jsファイルを追加してください。",
+ "noTools": "カスタムツールが読み込まれていません。プロジェクトの.roo/toolsディレクトリまたはグローバルツール用の~/.roo/toolsに.tsまたは.jsファイルを追加してください。",
"refreshButton": "更新",
"refreshing": "更新中...",
"refreshSuccess": "ツールが正常に更新されました",
diff --git a/webview-ui/src/i18n/locales/ko/settings.json b/webview-ui/src/i18n/locales/ko/settings.json
index 32c5a4df84f..a810a6162cb 100644
--- a/webview-ui/src/i18n/locales/ko/settings.json
+++ b/webview-ui/src/i18n/locales/ko/settings.json
@@ -828,9 +828,9 @@
},
"CUSTOM_TOOLS": {
"name": "사용자 정의 도구 활성화",
- "description": "활성화하면 Roo가 프로젝트의 .roo/tools 디렉터리에서 사용자 정의 TypeScript/JavaScript 도구를 로드하고 사용할 수 있습니다.",
+ "description": "활성화하면 Roo가 프로젝트의 .roo/tools 디렉터리 또는 전역 도구를 위한 ~/.roo/tools에서 사용자 정의 TypeScript/JavaScript 도구를 로드하고 사용할 수 있습니다. 참고: 이러한 도구는 자동으로 자동 승인됩니다.",
"toolsHeader": "사용 가능한 사용자 정의 도구",
- "noTools": "로드된 사용자 정의 도구가 없습니다. 프로젝트의 .roo/tools 디렉터리에 .ts 또는 .js 파일을 추가하세요.",
+ "noTools": "로드된 사용자 정의 도구가 없습니다. 프로젝트의 .roo/tools 디렉터리 또는 전역 도구를 위한 ~/.roo/tools에 .ts 또는 .js 파일을 추가하세요.",
"refreshButton": "새로고침",
"refreshing": "새로고침 중...",
"refreshSuccess": "도구가 성공적으로 새로고침되었습니다",
diff --git a/webview-ui/src/i18n/locales/nl/settings.json b/webview-ui/src/i18n/locales/nl/settings.json
index fe93eea35c1..10f14ae49de 100644
--- a/webview-ui/src/i18n/locales/nl/settings.json
+++ b/webview-ui/src/i18n/locales/nl/settings.json
@@ -828,9 +828,9 @@
},
"CUSTOM_TOOLS": {
"name": "Aangepaste tools inschakelen",
- "description": "Indien ingeschakeld kan Roo aangepaste TypeScript/JavaScript-tools laden en gebruiken uit de map .roo/tools van je project.",
+ "description": "Indien ingeschakeld kan Roo aangepaste TypeScript/JavaScript-tools laden en gebruiken uit de map .roo/tools van je project of ~/.roo/tools voor globale tools. Opmerking: deze tools worden automatisch goedgekeurd.",
"toolsHeader": "Beschikbare aangepaste tools",
- "noTools": "Geen aangepaste tools geladen. Voeg .ts- of .js-bestanden toe aan de map .roo/tools van je project.",
+ "noTools": "Geen aangepaste tools geladen. Voeg .ts- of .js-bestanden toe aan de map .roo/tools van je project of ~/.roo/tools voor globale tools.",
"refreshButton": "Vernieuwen",
"refreshing": "Vernieuwen...",
"refreshSuccess": "Tools succesvol vernieuwd",
diff --git a/webview-ui/src/i18n/locales/pl/settings.json b/webview-ui/src/i18n/locales/pl/settings.json
index c1563f2e23f..c958a6e2895 100644
--- a/webview-ui/src/i18n/locales/pl/settings.json
+++ b/webview-ui/src/i18n/locales/pl/settings.json
@@ -828,9 +828,9 @@
},
"CUSTOM_TOOLS": {
"name": "Włącz niestandardowe narzędzia",
- "description": "Gdy włączone, Roo może ładować i używać niestandardowych narzędzi TypeScript/JavaScript z katalogu .roo/tools Twojego projektu.",
+ "description": "Gdy włączone, Roo może ładować i używać niestandardowych narzędzi TypeScript/JavaScript z katalogu .roo/tools Twojego projektu lub ~/.roo/tools dla narzędzi globalnych. Uwaga: te narzędzia będą automatycznie zatwierdzane.",
"toolsHeader": "Dostępne niestandardowe narzędzia",
- "noTools": "Nie załadowano niestandardowych narzędzi. Dodaj pliki .ts lub .js do katalogu .roo/tools swojego projektu.",
+ "noTools": "Nie załadowano niestandardowych narzędzi. Dodaj pliki .ts lub .js do katalogu .roo/tools swojego projektu lub ~/.roo/tools dla narzędzi globalnych.",
"refreshButton": "Odśwież",
"refreshing": "Odświeżanie...",
"refreshSuccess": "Narzędzia odświeżone pomyślnie",
diff --git a/webview-ui/src/i18n/locales/pt-BR/settings.json b/webview-ui/src/i18n/locales/pt-BR/settings.json
index 4df36d14dff..062079ad7e3 100644
--- a/webview-ui/src/i18n/locales/pt-BR/settings.json
+++ b/webview-ui/src/i18n/locales/pt-BR/settings.json
@@ -828,9 +828,9 @@
},
"CUSTOM_TOOLS": {
"name": "Ativar ferramentas personalizadas",
- "description": "Quando habilitado, o Roo pode carregar e usar ferramentas TypeScript/JavaScript personalizadas do diretório .roo/tools do seu projeto.",
+ "description": "Quando habilitado, o Roo pode carregar e usar ferramentas TypeScript/JavaScript personalizadas do diretório .roo/tools do seu projeto ou ~/.roo/tools para ferramentas globais. Nota: estas ferramentas serão aprovadas automaticamente.",
"toolsHeader": "Ferramentas personalizadas disponíveis",
- "noTools": "Nenhuma ferramenta personalizada carregada. Adicione arquivos .ts ou .js ao diretório .roo/tools do seu projeto.",
+ "noTools": "Nenhuma ferramenta personalizada carregada. Adicione arquivos .ts ou .js ao diretório .roo/tools do seu projeto ou ~/.roo/tools para ferramentas globais.",
"refreshButton": "Atualizar",
"refreshing": "Atualizando...",
"refreshSuccess": "Ferramentas atualizadas com sucesso",
diff --git a/webview-ui/src/i18n/locales/ru/settings.json b/webview-ui/src/i18n/locales/ru/settings.json
index 1057c86115d..a908bc2ddf6 100644
--- a/webview-ui/src/i18n/locales/ru/settings.json
+++ b/webview-ui/src/i18n/locales/ru/settings.json
@@ -828,9 +828,9 @@
},
"CUSTOM_TOOLS": {
"name": "Включить пользовательские инструменты",
- "description": "Если включено, Roo сможет загружать и использовать пользовательские инструменты TypeScript/JavaScript из каталога .roo/tools вашего проекта.",
+ "description": "Если включено, Roo сможет загружать и использовать пользовательские инструменты TypeScript/JavaScript из каталога .roo/tools вашего проекта или ~/.roo/tools для глобальных инструментов. Примечание: эти инструменты будут одобрены автоматически.",
"toolsHeader": "Доступные пользовательские инструменты",
- "noTools": "Пользовательские инструменты не загружены. Добавьте файлы .ts или .js в каталог .roo/tools вашего проекта.",
+ "noTools": "Пользовательские инструменты не загружены. Добавьте файлы .ts или .js в каталог .roo/tools вашего проекта или ~/.roo/tools для глобальных инструментов.",
"refreshButton": "Обновить",
"refreshing": "Обновление...",
"refreshSuccess": "Инструменты успешно обновлены",
diff --git a/webview-ui/src/i18n/locales/tr/settings.json b/webview-ui/src/i18n/locales/tr/settings.json
index c8bd9888ffe..26d433e0af7 100644
--- a/webview-ui/src/i18n/locales/tr/settings.json
+++ b/webview-ui/src/i18n/locales/tr/settings.json
@@ -828,9 +828,9 @@
},
"CUSTOM_TOOLS": {
"name": "Özel araçları etkinleştir",
- "description": "Etkinleştirildiğinde, Roo projenizin .roo/tools dizininden özel TypeScript/JavaScript araçlarını yükleyebilir ve kullanabilir.",
+ "description": "Etkinleştirildiğinde, Roo projenizin .roo/tools dizininden veya global araçlar için ~/.roo/tools dizininden özel TypeScript/JavaScript araçlarını yükleyebilir ve kullanabilir. Not: Bu araçlar otomatik olarak onaylanacaktır.",
"toolsHeader": "Kullanılabilir Özel Araçlar",
- "noTools": "Özel araç yüklenmedi. Projenizin .roo/tools dizinine .ts veya .js dosyaları ekleyin.",
+ "noTools": "Özel araç yüklenmedi. Projenizin .roo/tools dizinine veya global araçlar için ~/.roo/tools dizinine .ts veya .js dosyaları ekleyin.",
"refreshButton": "Yenile",
"refreshing": "Yenileniyor...",
"refreshSuccess": "Araçlar başarıyla yenilendi",
diff --git a/webview-ui/src/i18n/locales/vi/settings.json b/webview-ui/src/i18n/locales/vi/settings.json
index 4f1a38157d5..77d3fe7e2a2 100644
--- a/webview-ui/src/i18n/locales/vi/settings.json
+++ b/webview-ui/src/i18n/locales/vi/settings.json
@@ -828,9 +828,9 @@
},
"CUSTOM_TOOLS": {
"name": "Bật công cụ tùy chỉnh",
- "description": "Khi được bật, Roo có thể tải và sử dụng các công cụ TypeScript/JavaScript tùy chỉnh từ thư mục .roo/tools của dự án của bạn.",
+ "description": "Khi được bật, Roo có thể tải và sử dụng các công cụ TypeScript/JavaScript tùy chỉnh từ thư mục .roo/tools của dự án hoặc ~/.roo/tools cho các công cụ toàn cục. Lưu ý: các công cụ này sẽ được tự động phê duyệt.",
"toolsHeader": "Công cụ tùy chỉnh có sẵn",
- "noTools": "Không có công cụ tùy chỉnh nào được tải. Thêm tệp .ts hoặc .js vào thư mục .roo/tools của dự án của bạn.",
+ "noTools": "Không có công cụ tùy chỉnh nào được tải. Thêm tệp .ts hoặc .js vào thư mục .roo/tools của dự án hoặc ~/.roo/tools cho các công cụ toàn cục.",
"refreshButton": "Làm mới",
"refreshing": "Đang làm mới...",
"refreshSuccess": "Làm mới công cụ thành công",
diff --git a/webview-ui/src/i18n/locales/zh-CN/settings.json b/webview-ui/src/i18n/locales/zh-CN/settings.json
index dd88c8fd20b..5a70cfd10de 100644
--- a/webview-ui/src/i18n/locales/zh-CN/settings.json
+++ b/webview-ui/src/i18n/locales/zh-CN/settings.json
@@ -828,9 +828,9 @@
},
"CUSTOM_TOOLS": {
"name": "启用自定义工具",
- "description": "启用后,Roo 可以从项目中的 .roo/tools 目录加载并使用自定义 TypeScript/JavaScript 工具。",
+ "description": "启用后 Roo 可从项目中的 .roo/tools 目录或全局工具目录 ~/.roo/tools 加载并使用自定义 TypeScript/JavaScript 工具。注意:这些工具将自动获批。",
"toolsHeader": "可用自定义工具",
- "noTools": "未加载自定义工具。请向项目的 .roo/tools 目录添加 .ts 或 .js 文件。",
+ "noTools": "未加载自定义工具。请向项目的 .roo/tools 目录或全局工具目录 ~/.roo/tools 添加 .ts 或 .js 文件。",
"refreshButton": "刷新",
"refreshing": "正在刷新...",
"refreshSuccess": "工具刷新成功",
diff --git a/webview-ui/src/i18n/locales/zh-TW/settings.json b/webview-ui/src/i18n/locales/zh-TW/settings.json
index 221ad881a5b..88ab5a2c094 100644
--- a/webview-ui/src/i18n/locales/zh-TW/settings.json
+++ b/webview-ui/src/i18n/locales/zh-TW/settings.json
@@ -828,9 +828,9 @@
},
"CUSTOM_TOOLS": {
"name": "啟用自訂工具",
- "description": "啟用後,Roo 可以從專案中的 .roo/tools 目錄載入並使用自訂 TypeScript/JavaScript 工具。",
+ "description": "啟用後,Roo 可以從專案中的 .roo/tools 目錄或全域工具目錄 ~/.roo/tools 載入並使用自訂 TypeScript/JavaScript 工具。注意:這些工具將自動獲得核准。",
"toolsHeader": "可用自訂工具",
- "noTools": "未載入自訂工具。請向專案的 .roo/tools 目錄新增 .ts 或 .js 檔案。",
+ "noTools": "未載入自訂工具。請向專案的 .roo/tools 目錄或全域工具目錄 ~/.roo/tools 新增 .ts 或 .js 檔案。",
"refreshButton": "重新整理",
"refreshing": "正在重新整理...",
"refreshSuccess": "工具重新整理成功",