Reuse OpenCode 2 HTTP/stdio clients with per-session read-only grants, native approval and sanitized owner-scoped MCP status. Narrow the environment inherited by trusted local MCP processes. Validated in an isolated checkout with bun run check and 20 focused tests.
35 lines
2.3 KiB
TypeScript
35 lines
2.3 KiB
TypeScript
import { describe, expect, it } from "bun:test";
|
|
import plugin from "../../.opencode/plugins/tjwater-tools.js";
|
|
|
|
describe("OpenCode 2 business tool registration", () => {
|
|
it("registers business tools for direct dispatch, forwards the native call ID and validates inputs", async () => {
|
|
const tools = new Map<string, any>();
|
|
const storage = new Map<string, unknown>();
|
|
let rpcList: (() => Promise<unknown>) | undefined;
|
|
await plugin.setup({
|
|
tool: { transform: async (fn: (editor: unknown) => void) => fn({ list: () => Array.from(tools, ([id, tool]) => ({ ...tool, id })), add: (tool: any) => tools.set(tool.name, tool), remove: (name: string) => tools.delete(name), update: () => {} }), list: async () => Array.from(tools, ([id, tool]) => ({ ...tool, id })) },
|
|
mcp: { transform: async (fn: (editor: unknown) => void) => fn({ list: () => [] }), list: async () => ({ data: [] }) },
|
|
shell: { hook: async () => {} },
|
|
permission: { hook: async () => {} },
|
|
session: { hook: async () => {} },
|
|
rpc: { register: async (_definition: unknown, handlers: { list: () => Promise<unknown> }) => { rpcList = handlers.list; } },
|
|
storage: { set: async (key: string, value: unknown) => storage.set(key, value), get: async (key: string) => storage.get(key) },
|
|
} as never);
|
|
expect(tools.get("render_scada_analysis").options).toEqual({ codemode: false, permission: "render_scada_analysis" });
|
|
const render = tools.get("render_scada_analysis");
|
|
await expect(render.execute({ reason: "test", items: [{ device_id: "x", level: "wrong" }] }, { sessionID: "s", id: "call-native" })).rejects.toThrow();
|
|
const todo = tools.get("todowrite");
|
|
const todos = [{ content: "check", status: "pending" }];
|
|
await todo.execute({ todos }, { sessionID: "s" });
|
|
expect(await tools.get("todoread").execute({}, { sessionID: "s" })).toEqual({ content: JSON.stringify(todos) });
|
|
expect(await tools.get("todoread").execute({}, { sessionID: "another" })).toEqual({ content: "[]" });
|
|
const discovery = await rpcList!();
|
|
expect(JSON.parse(JSON.stringify(discovery))).toEqual(discovery);
|
|
});
|
|
it("exports a single native plugin entrypoint", async () => {
|
|
const module = await import("../../.opencode/plugins/tjwater-tools.js");
|
|
expect(Object.keys(module)).toEqual(["default"]);
|
|
expect(module.default.id).toBe("tjwater.tools");
|
|
});
|
|
});
|