This commit is contained in:
+67
-2
@@ -3,7 +3,9 @@ import { Tool } from "@opencode/schema/tool";
|
||||
import { Session } from "@opencode/schema/session";
|
||||
import { AbsolutePath } from "@opencode/schema/schema";
|
||||
import type { Context } from "@opencode/plugin/effect/plugin";
|
||||
import { Cause, Effect, Schedule } from "effect";
|
||||
import { Plugin } from "@opencode/plugin/effect";
|
||||
import { AgentsRpc } from "./agents-rpc.js";
|
||||
import { Cause, Effect, Schedule, Stream } from "effect";
|
||||
import { z } from "zod";
|
||||
import { randomUUID } from "node:crypto";
|
||||
import { Herdr, rootSchema } from "./herdr.js";
|
||||
@@ -97,7 +99,7 @@ export const installMultiWork = (
|
||||
agent.system = `${agent.system ?? ""}\n${childProtocol}`;
|
||||
});
|
||||
if (!eligible) return;
|
||||
// The base plugin captures the final registry after late configuration
|
||||
// Agents captures the final registry after late configuration
|
||||
// transforms and reloads when it changes. Editor.build is too early.
|
||||
const inherited = buildPermissions();
|
||||
editor.update("multi-work", (agent) => {
|
||||
@@ -156,6 +158,34 @@ export const installMultiWork = (
|
||||
return binding;
|
||||
});
|
||||
|
||||
// Commands can create children without going through the subagent tool.
|
||||
yield* context.session.hook("prompt", (event) =>
|
||||
Effect.gen(function* () {
|
||||
const child = yield* context.session.get({ sessionID: event.sessionID });
|
||||
if (!child.parentID) return;
|
||||
if (child.agent === "multi-work") throw new Error("multi-work is primary only");
|
||||
const parent = yield* context.session.get({ sessionID: child.parentID });
|
||||
if (child.agent === "coordinate") yield* validate(event.sessionID);
|
||||
if (
|
||||
parent.agent === "multi-work" &&
|
||||
child.agent !== "coordinate" &&
|
||||
(child.agent !== "fast-lo" ||
|
||||
child.location.directory !== parent.location.directory)
|
||||
)
|
||||
throw new Error(
|
||||
"multi-work may delegate only to local fast-lo or a bound coordinate child",
|
||||
);
|
||||
}).pipe(Effect.orDie),
|
||||
);
|
||||
yield* context.tool.hook("execute.before", (event) => {
|
||||
if (
|
||||
event.tool === "subagent" &&
|
||||
z.object({ agent: z.string() }).parse(event.input).agent === "multi-work"
|
||||
)
|
||||
return Effect.fail(new Tool.Error({ message: "multi-work is primary only" }));
|
||||
return Effect.void;
|
||||
});
|
||||
|
||||
yield* context.session.hook("context", (event) =>
|
||||
Effect.gen(function* () {
|
||||
const session = yield* context.session.get({ sessionID: event.sessionID });
|
||||
@@ -489,3 +519,38 @@ export const installMultiWork = (
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
export default Plugin.define({
|
||||
id: "stanp-opencode.multi-work",
|
||||
effect: (context) =>
|
||||
Effect.gen(function* () {
|
||||
const agents = context.rpc(AgentsRpc);
|
||||
let inherited = yield* agents
|
||||
.permissions({})
|
||||
.pipe(
|
||||
Effect.catch(() =>
|
||||
Effect.die(new Error("Multi-work requires Agents loaded before it")),
|
||||
),
|
||||
);
|
||||
yield* context.event.subscribe().pipe(
|
||||
Stream.filter(
|
||||
(event) =>
|
||||
event.type === "agent.updated" &&
|
||||
(!event.location ||
|
||||
(event.location.directory === context.location.directory &&
|
||||
event.location.workspaceID === context.location.workspaceID)),
|
||||
),
|
||||
Stream.runForEach(() =>
|
||||
Effect.gen(function* () {
|
||||
const next = yield* agents.permissions({});
|
||||
if (JSON.stringify(next) === JSON.stringify(inherited)) return;
|
||||
inherited = next;
|
||||
yield* context.agent.reload();
|
||||
}),
|
||||
),
|
||||
Effect.orDie,
|
||||
Effect.forkScoped,
|
||||
);
|
||||
yield* installMultiWork(context, () => inherited);
|
||||
}).pipe(Effect.orDie),
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user