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": "工具重新整理成功",