Skip to content
This repository was archived by the owner on May 15, 2026. It is now read-only.

Commit 5ae4d4d

Browse files
authored
Custom tool calling (#10083)
1 parent 78dc344 commit 5ae4d4d

76 files changed

Lines changed: 3514 additions & 37 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import type { CustomToolContext, TaskLike } from "@roo-code/types"
2+
3+
import systemTime from "../system-time.js"
4+
5+
const mockContext: CustomToolContext = {
6+
mode: "code",
7+
task: { taskId: "test-task-id" } as unknown as TaskLike,
8+
}
9+
10+
describe("system-time tool", () => {
11+
describe("execute", () => {
12+
it("should return a formatted date/time string", async () => {
13+
const result = await systemTime.execute({}, mockContext)
14+
expect(result).toMatch(/^The current date and time is:/)
15+
expect(result).toMatch(/(Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday)/)
16+
expect(result).toMatch(
17+
/(January|February|March|April|May|June|July|August|September|October|November|December)/,
18+
)
19+
expect(result).toMatch(/\d{1,2}:\d{2}:\d{2}/)
20+
})
21+
})
22+
})

.roo/tools/eslint.config.mjs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import { config } from "@roo-code/config-eslint/base"
2+
3+
/** @type {import("eslint").Linter.Config} */
4+
export default [...config]

.roo/tools/package.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"name": "@roo-code/custom-tools",
3+
"version": "0.0.0",
4+
"private": true,
5+
"type": "module",
6+
"description": "Custom tools for the Roo Code project itself",
7+
"scripts": {
8+
"lint": "eslint . --ext=ts --max-warnings=0",
9+
"check-types": "tsc --noEmit",
10+
"test": "vitest run"
11+
},
12+
"devDependencies": {
13+
"@roo-code/config-eslint": "workspace:^",
14+
"@roo-code/config-typescript": "workspace:^",
15+
"@roo-code/types": "workspace:^",
16+
"vitest": "^3.2.3"
17+
}
18+
}

.roo/tools/system-time.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { parametersSchema, defineCustomTool } from "@roo-code/types"
2+
3+
export default defineCustomTool({
4+
name: "system_time",
5+
description: "Returns the current system date and time in a friendly, human-readable format.",
6+
parameters: parametersSchema.object({}),
7+
async execute() {
8+
const systemTime = new Date().toLocaleString("en-US", {
9+
weekday: "long",
10+
year: "numeric",
11+
month: "long",
12+
day: "numeric",
13+
hour: "2-digit",
14+
minute: "2-digit",
15+
second: "2-digit",
16+
timeZoneName: "short",
17+
timeZone: "America/Los_Angeles",
18+
})
19+
20+
return `The current date and time is: ${systemTime}`
21+
},
22+
})

.roo/tools/tsconfig.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"extends": "@roo-code/config-typescript/base.json",
3+
"compilerOptions": {
4+
"noEmit": true,
5+
"types": ["vitest/globals"]
6+
},
7+
"include": ["*.ts", "__tests__/*.ts"],
8+
"exclude": ["node_modules"]
9+
}

.roo/tools/vitest.config.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { defineConfig } from "vitest/config"
2+
3+
export default defineConfig({
4+
test: {
5+
globals: true,
6+
environment: "node",
7+
watch: false,
8+
},
9+
})

packages/build/src/esbuild.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,58 @@ export function copyWasms(srcDir: string, distDir: string): void {
158158
})
159159

160160
console.log(`[copyWasms] Copied ${wasmFiles.length} tree-sitter language wasms to ${distDir}`)
161+
162+
// Copy esbuild-wasm files for custom tool transpilation (cross-platform).
163+
copyEsbuildWasmFiles(nodeModulesDir, distDir)
164+
}
165+
166+
/**
167+
* Copy esbuild-wasm files to the dist/bin directory.
168+
*
169+
* This function copies the esbuild-wasm CLI and WASM binary, which provides
170+
* a cross-platform esbuild implementation that works on all platforms.
171+
*
172+
* Files copied:
173+
* - bin/esbuild (Node.js CLI script)
174+
* - esbuild.wasm (WASM binary)
175+
* - wasm_exec_node.js (Go WASM runtime for Node.js)
176+
* - wasm_exec.js (Go WASM runtime dependency)
177+
*/
178+
function copyEsbuildWasmFiles(nodeModulesDir: string, distDir: string): void {
179+
const esbuildWasmDir = path.join(nodeModulesDir, "esbuild-wasm")
180+
181+
if (!fs.existsSync(esbuildWasmDir)) {
182+
throw new Error(`Directory does not exist: ${esbuildWasmDir}`)
183+
}
184+
185+
// Create bin directory in dist.
186+
const binDir = path.join(distDir, "bin")
187+
fs.mkdirSync(binDir, { recursive: true })
188+
189+
// Files to copy - the esbuild CLI script expects wasm_exec_node.js and esbuild.wasm
190+
// to be one directory level up from the bin directory (i.e., in distDir directly).
191+
// wasm_exec_node.js requires wasm_exec.js, so we need to copy that too.
192+
const filesToCopy = [
193+
{ src: path.join(esbuildWasmDir, "bin", "esbuild"), dest: path.join(binDir, "esbuild") },
194+
{ src: path.join(esbuildWasmDir, "esbuild.wasm"), dest: path.join(distDir, "esbuild.wasm") },
195+
{ src: path.join(esbuildWasmDir, "wasm_exec_node.js"), dest: path.join(distDir, "wasm_exec_node.js") },
196+
{ src: path.join(esbuildWasmDir, "wasm_exec.js"), dest: path.join(distDir, "wasm_exec.js") },
197+
]
198+
199+
for (const { src, dest } of filesToCopy) {
200+
fs.copyFileSync(src, dest)
201+
202+
// Make CLI executable.
203+
if (src.endsWith("esbuild")) {
204+
try {
205+
fs.chmodSync(dest, 0o755)
206+
} catch {
207+
// Ignore chmod errors on Windows.
208+
}
209+
}
210+
}
211+
212+
console.log(`[copyWasms] Copied ${filesToCopy.length} esbuild-wasm files to ${distDir}`)
161213
}
162214

163215
export function copyLocales(srcDir: string, distDir: string): void {

packages/core/eslint.config.mjs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import { config } from "@roo-code/config-eslint/base"
2+
3+
/** @type {import("eslint").Linter.Config} */
4+
export default [...config]

packages/core/package.json

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"name": "@roo-code/core",
3+
"description": "Platform agnostic core functionality for Roo Code.",
4+
"version": "0.0.0",
5+
"type": "module",
6+
"exports": "./src/index.ts",
7+
"scripts": {
8+
"lint": "eslint src --ext=ts --max-warnings=0",
9+
"check-types": "tsc --noEmit",
10+
"test": "vitest run",
11+
"clean": "rimraf .turbo"
12+
},
13+
"dependencies": {
14+
"@roo-code/types": "workspace:^",
15+
"esbuild": "^0.25.0",
16+
"execa": "^9.5.2",
17+
"openai": "^5.12.2",
18+
"zod": "^3.25.61"
19+
},
20+
"devDependencies": {
21+
"@roo-code/config-eslint": "workspace:^",
22+
"@roo-code/config-typescript": "workspace:^",
23+
"@types/node": "^24.1.0",
24+
"vitest": "^3.2.3"
25+
}
26+
}

0 commit comments

Comments
 (0)