import { Plugin, Agent } from "@opencode/plugin/effect"; import { Rpc } from "@opencode/plugin/rpc"; import { Session } from "@opencode/schema/session"; import { SessionMessage } from "@opencode/schema/session-message"; import { Tool } from "@opencode/schema/tool"; import { Cause, Effect } from "effect"; import { z } from "zod"; import { appendFile } from "node:fs/promises"; import multiWork from "../../src/multi-work/multi-work.js"; const probe = Rpc.define({ id: "multi-work-test", events: {}, methods: { delegate: { input: z.object({ parent: z.string(), child: z.string().optional(), background: z.boolean(), }), output: z.string(), }, }, }); export default Plugin.define({ id: multiWork.id, effect: (context) => Effect.gen(function* () { yield* multiWork.effect(context); let delegate: Tool.Info | undefined; yield* context.tool.transform((editor) => { delegate = editor.get("subagent"); }); yield* context.session.hook("prompt", (event) => Effect.gen(function* () { const child = yield* context.session.get({ sessionID: event.sessionID }); yield* Effect.promise(() => appendFile( process.env["FIXTURE_TRACE"] ?? "", JSON.stringify({ id: child.id, parent: child.parentID, agent: child.agent, directory: child.location.directory, }) + "\n", ), ); }).pipe(Effect.orDie), ); yield* context.rpc .register(probe, { delegate: (input) => Effect.gen(function* () { if (!delegate) throw new Error("Native subagent missing"); const result = yield* delegate.execute( { agent: "coordinate", description: "native host proof", prompt: "Reply with FIXTURE_COMPLETE", background: input.background, ...(input.child !== undefined && input.child !== "" ? { sessionID: input.child } : { worktree: { base: "main", branch: "fix/native-host", label: "Fix native host", }, }), }, { sessionID: Session.ID.make(input.parent), agent: Agent.ID.make("multi-work"), messageID: SessionMessage.ID.create(), id: Tool.CallID.make(`call_${crypto.randomUUID()}`), progress: () => Effect.void, }, ); return JSON.stringify(result); }).pipe( Effect.catchCause((cause) => Cause.hasInterrupts(cause) ? Effect.interrupt : Effect.succeed( JSON.stringify({ failure: Cause.pretty(cause) }), ), ), ), }) .pipe(Effect.orDie); }), });