diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts index 178501d446..314554b22b 100644 --- a/packages/opencode/src/config/config.ts +++ b/packages/opencode/src/config/config.ts @@ -288,7 +288,6 @@ export namespace Config { // Install any additional dependencies defined in the package.json // This allows local plugins and custom tools to use external packages await Npm.install(dir).catch((err: any) => { - console.log(err) log.warn("failed to install dependencies", { dir, error: err.message }) }) } diff --git a/packages/opencode/src/storage/db.ts b/packages/opencode/src/storage/db.ts index 72c6916d0f..dcf0942e12 100644 --- a/packages/opencode/src/storage/db.ts +++ b/packages/opencode/src/storage/db.ts @@ -109,6 +109,7 @@ export namespace Database { export function close() { Client().$client.close() + Client.reset() } export type TxOrDb = Transaction | Client diff --git a/packages/opencode/test/tool/registry.test.ts b/packages/opencode/test/tool/registry.test.ts index 65cd31fecb..706a9e12ca 100644 --- a/packages/opencode/test/tool/registry.test.ts +++ b/packages/opencode/test/tool/registry.test.ts @@ -5,48 +5,118 @@ import { tmpdir } from "../fixture/fixture" import { Instance } from "../../src/project/instance" import { ToolRegistry } from "../../src/tool/registry" -test("loads tools with external dependencies without crashing", async () => { - await using tmp = await tmpdir({ - init: async (dir) => { - const opencodeDir = path.join(dir, ".opencode") - await fs.mkdir(opencodeDir, { recursive: true }) +describe("tool.registry", () => { + test("loads tools from .opencode/tool (singular)", async () => { + await using tmp = await tmpdir({ + init: async (dir) => { + const opencodeDir = path.join(dir, ".opencode") + await fs.mkdir(opencodeDir, { recursive: true }) - const toolsDir = path.join(opencodeDir, "tools") - await fs.mkdir(toolsDir, { recursive: true }) + const toolDir = path.join(opencodeDir, "tool") + await fs.mkdir(toolDir, { recursive: true }) - await Bun.write( - path.join(opencodeDir, "package.json"), - JSON.stringify({ - name: "custom-tools", - dependencies: { - "@opencode-ai/plugin": "^0.0.0", - cowsay: "^1.6.0", - }, - }), - ) + await Bun.write( + path.join(toolDir, "hello.ts"), + [ + "export default {", + " description: 'hello tool',", + " args: {},", + " execute: async () => {", + " return 'hello world'", + " },", + "}", + "", + ].join("\n"), + ) + }, + }) - await Bun.write( - path.join(toolsDir, "cowsay.ts"), - [ - "import { say } from 'cowsay'", - "export default {", - " description: 'tool that imports cowsay at top level',", - " args: { text: { type: 'string' } },", - " execute: async ({ text }: { text: string }) => {", - " return say({ text })", - " },", - "}", - "", - ].join("\n"), - ) - }, + await Instance.provide({ + directory: tmp.path, + fn: async () => { + const ids = await ToolRegistry.ids() + expect(ids).toContain("hello") + }, + }) }) - await Instance.provide({ - directory: tmp.path, - fn: async () => { - const ids = await ToolRegistry.ids() - expect(ids).toContain("cowsay") - }, + test("loads tools from .opencode/tools (plural)", async () => { + await using tmp = await tmpdir({ + init: async (dir) => { + const opencodeDir = path.join(dir, ".opencode") + await fs.mkdir(opencodeDir, { recursive: true }) + + const toolsDir = path.join(opencodeDir, "tools") + await fs.mkdir(toolsDir, { recursive: true }) + + await Bun.write( + path.join(toolsDir, "hello.ts"), + [ + "export default {", + " description: 'hello tool',", + " args: {},", + " execute: async () => {", + " return 'hello world'", + " },", + "}", + "", + ].join("\n"), + ) + }, + }) + + await Instance.provide({ + directory: tmp.path, + fn: async () => { + const ids = await ToolRegistry.ids() + expect(ids).toContain("hello") + }, + }) + }) + + test("loads tools with external dependencies without crashing", async () => { + await using tmp = await tmpdir({ + init: async (dir) => { + const opencodeDir = path.join(dir, ".opencode") + await fs.mkdir(opencodeDir, { recursive: true }) + + const toolsDir = path.join(opencodeDir, "tools") + await fs.mkdir(toolsDir, { recursive: true }) + + await Bun.write( + path.join(opencodeDir, "package.json"), + JSON.stringify({ + name: "custom-tools", + dependencies: { + "@opencode-ai/plugin": "^0.0.0", + cowsay: "^1.6.0", + }, + }), + ) + + await Bun.write( + path.join(toolsDir, "cowsay.ts"), + [ + "import { say } from 'cowsay'", + "export default {", + " description: 'tool that imports cowsay at top level',", + " args: { text: { type: 'string' } },", + " execute: async ({ text }: { text: string }) => {", + " return say({ text })", + " },", + "}", + "", + ].join("\n"), + ) + }, + }) + + await Instance.provide({ + directory: tmp.path, + fn: async () => { + const ids = await ToolRegistry.ids() + expect(ids).toContain("cowsay") + }, + }) }) })