| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152 |
- import { afterEach, describe, expect } from "bun:test"
- import path from "path"
- import fs from "fs/promises"
- import { Effect, Layer } from "effect"
- import { Instance } from "../../src/project/instance"
- import * as CrossSpawnSpawner from "../../src/effect/cross-spawn-spawner"
- import { ToolRegistry } from "../../src/tool"
- import { provideTmpdirInstance } from "../fixture/fixture"
- import { testEffect } from "../lib/effect"
- const node = CrossSpawnSpawner.defaultLayer
- const it = testEffect(Layer.mergeAll(ToolRegistry.defaultLayer, node))
- afterEach(async () => {
- await Instance.disposeAll()
- })
- describe("tool.registry", () => {
- it.live("loads tools from .opencode/tool (singular)", () =>
- provideTmpdirInstance((dir) =>
- Effect.gen(function* () {
- const opencode = path.join(dir, ".opencode")
- const tool = path.join(opencode, "tool")
- yield* Effect.promise(() => fs.mkdir(tool, { recursive: true }))
- yield* Effect.promise(() =>
- Bun.write(
- path.join(tool, "hello.ts"),
- [
- "export default {",
- " description: 'hello tool',",
- " args: {},",
- " execute: async () => {",
- " return 'hello world'",
- " },",
- "}",
- "",
- ].join("\n"),
- ),
- )
- const registry = yield* ToolRegistry.Service
- const ids = yield* registry.ids()
- expect(ids).toContain("hello")
- }),
- ),
- )
- it.live("loads tools from .opencode/tools (plural)", () =>
- provideTmpdirInstance((dir) =>
- Effect.gen(function* () {
- const opencode = path.join(dir, ".opencode")
- const tools = path.join(opencode, "tools")
- yield* Effect.promise(() => fs.mkdir(tools, { recursive: true }))
- yield* Effect.promise(() =>
- Bun.write(
- path.join(tools, "hello.ts"),
- [
- "export default {",
- " description: 'hello tool',",
- " args: {},",
- " execute: async () => {",
- " return 'hello world'",
- " },",
- "}",
- "",
- ].join("\n"),
- ),
- )
- const registry = yield* ToolRegistry.Service
- const ids = yield* registry.ids()
- expect(ids).toContain("hello")
- }),
- ),
- )
- it.live("loads tools with external dependencies without crashing", () =>
- provideTmpdirInstance((dir) =>
- Effect.gen(function* () {
- const opencode = path.join(dir, ".opencode")
- const tools = path.join(opencode, "tools")
- yield* Effect.promise(() => fs.mkdir(tools, { recursive: true }))
- yield* Effect.promise(() =>
- Bun.write(
- path.join(opencode, "package.json"),
- JSON.stringify({
- name: "custom-tools",
- dependencies: {
- "@opencode-ai/plugin": "^0.0.0",
- cowsay: "^1.6.0",
- },
- }),
- ),
- )
- yield* Effect.promise(() =>
- Bun.write(
- path.join(opencode, "package-lock.json"),
- JSON.stringify({
- name: "custom-tools",
- lockfileVersion: 3,
- packages: {
- "": {
- dependencies: {
- "@opencode-ai/plugin": "^0.0.0",
- cowsay: "^1.6.0",
- },
- },
- },
- }),
- ),
- )
- const cowsay = path.join(opencode, "node_modules", "cowsay")
- yield* Effect.promise(() => fs.mkdir(cowsay, { recursive: true }))
- yield* Effect.promise(() =>
- Bun.write(
- path.join(cowsay, "package.json"),
- JSON.stringify({
- name: "cowsay",
- type: "module",
- exports: "./index.js",
- }),
- ),
- )
- yield* Effect.promise(() =>
- Bun.write(
- path.join(cowsay, "index.js"),
- ["export function say({ text }) {", " return `moo ${text}`", "}", ""].join("\n"),
- ),
- )
- yield* Effect.promise(() =>
- Bun.write(
- path.join(tools, "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"),
- ),
- )
- const registry = yield* ToolRegistry.Service
- const ids = yield* registry.ids()
- expect(ids).toContain("cowsay")
- }),
- ),
- )
- })
|