import type { Plugin } from "@opencode-ai/plugin" import { createEnforcer } from "./enforcer.ts" import { readState, writeState, loadConfig, resolveWorktree, debugLog } from "./state-io.ts" import { ORCHESTRATOR_PROMPT, PLANNER_PROMPT, CODER_PROMPT, CODER_HARD_PROMPT, ADVERSARY_PROMPT, } from "./agents.ts" import stateTool from "./tools/state.ts" import dagTool from "./tools/dag.ts" import triageTool from "./tools/triage.ts" import compressTool from "./tools/compress.ts" import reviewGateTool from "./tools/review-gate.ts" import memoryTool from "./tools/memory.ts" import { getMemoryManager } from "./memory/index.ts" export const AgenTeam: Plugin = async ({ worktree }) => { const enforce = createEnforcer(worktree) return { "tool.execute.before": async (input, output) => { await enforce(input, output) }, "tool.execute.after": async (input) => { if (input.tool === "agenteam_triage") { try { const wt = resolveWorktree(worktree) const config = loadConfig(wt) if (config.memory.enabled && config.memory.auto_inject_on_triage) { const mm = getMemoryManager(wt) await mm.init(wt, config.memory) const triageRequest = input.args?.request as string | undefined if (triageRequest) { const summary = await mm.getSummary(triageRequest, config.memory.max_auto_tokens) if (summary) { const memState = readState(wt) writeState(wt, { ...memState, memory_context: summary }) debugLog("plugin", "memory.auto_injected", { chars: summary.length, lines: summary.split("\n").length, }) } } } } catch (err) { debugLog("plugin", "memory.auto_inject_failed", { error: String(err) }) } } }, tool: { agenteam_state: stateTool, agenteam_dag: dagTool, agenteam_triage: triageTool, agenteam_compress: compressTool, agenteam_review_gate: reviewGateTool, agenteam_memory: memoryTool, }, config: async (cfg) => { const ac = loadConfig(worktree) if (!cfg.agent) cfg.agent = {} const agents: Record = { orchestrator: { model: ac.models.smart, description: "Manages development team. Never writes code. Dispatches tasks via strict workflow.", mode: "primary", temperature: 0.1, prompt: ORCHESTRATOR_PROMPT, permission: { edit: "deny", bash: "deny", task: { "*": "deny", planner: "allow", coder: "allow", "coder-hard": "allow", adversary: "allow" }, }, }, planner: { model: ac.models.smart, description: "Analyzes complex requests and generates task DAGs. Read-only.", mode: "subagent", hidden: true, temperature: 0.1, prompt: PLANNER_PROMPT, permission: { edit: "deny", bash: { "*": "deny", "wc -l *": "allow", "find * -name *": "allow" }, }, }, coder: { model: ac.models.cheap, description: "Executes simple coding tasks efficiently.", mode: "subagent", hidden: true, steps: 20, prompt: CODER_PROMPT, permission: { edit: "allow", bash: { "*": "allow", "rm -rf *": "deny", "git push*": "deny" }, }, }, "coder-hard": { model: ac.models.smart, description: "Executes complex coding tasks requiring deep reasoning.", mode: "subagent", hidden: true, steps: 30, prompt: CODER_HARD_PROMPT, permission: { edit: "allow", bash: { "*": "allow", "rm -rf *": "deny", "git push*": "deny" }, }, }, adversary: { model: ac.models[ac.adversary_model as keyof typeof ac.models] ?? ac.models.smart, description: "Reviews code changes adversarially. Finds bugs, not confirms correctness.", mode: "subagent", hidden: true, temperature: 0.0, prompt: ADVERSARY_PROMPT, permission: { edit: "deny", bash: { "*": "deny", "git diff*": "allow", "git log*": "allow", "grep *": "allow", "rg *": "allow" }, }, }, } for (const [name, def] of Object.entries(agents)) { if ((cfg.agent as any)[name] === undefined) { ;(cfg.agent as any)[name] = def } } }, } }