import { Tool } from "@opencode/schema/tool" import type { Agent } from "@opencode/schema/agent" import type { Session } from "@opencode/schema/session" import type { SessionMessage } from "@opencode/schema/session-message" import type { Effect, Types } from "effect" import type { Hooks, Transform } from "./registration.js" export interface ToolEditor { list(): readonly (Tool.Info & { readonly id: string })[] get(id: string): (Tool.Info & { readonly id: string }) | undefined namespace(namespace: Tool.Namespace): void add, Output extends Tool.ValueSchema | undefined>( tool: Tool.Info, ): void /** Updates an existing tool; missing IDs are ignored. */ update(id: string, update: (tool: Types.Mutable) => void): void remove(id: string): void } export interface ToolHooks { readonly "execute.before": { tool: string readonly sessionID: Session.ID readonly agent: Agent.ID readonly messageID: SessionMessage.ID readonly id: Tool.CallID input: unknown } readonly "execute.after": { readonly tool: string readonly sessionID: Session.ID readonly agent: Agent.ID readonly messageID: SessionMessage.ID readonly id: Tool.CallID readonly input: unknown } & ( | { readonly status: "completed" result: Tool.Result } | { readonly status: "error" error: Tool.Error } ) } // Only execute.before may fail: a Tool.Error rejects the call before the tool runs. export interface ToolFailures extends Record { readonly "execute.before": Tool.Error readonly "execute.after": never } export interface ToolDomain { readonly transform: Transform readonly reload: () => Effect.Effect /** Currently registered tools, after every transform, keyed by effective name. */ readonly list: () => Effect.Effect readonly hook: Hooks }