import { tool, type ToolDefinition } from "@opencode-ai/plugin/tool" import type { BackgroundManager } from "../../features/background-agent" import { validateAgentName, validateTeamName } from "./name-validation" import { TeamForceKillInputSchema, TeamProcessShutdownInputSchema, TeamSpawnInputSchema, TeamToolContext, isTeammateMember, } from "./types" import { getTeamMember, readTeamConfigOrThrow, removeTeammate, updateTeamConfig, writeTeamConfig } from "./team-config-store" import { cancelTeammateRun, spawnTeammate } from "./teammate-runtime" import { resetOwnerTasks } from "./team-task-store" export function createSpawnTeammateTool(manager: BackgroundManager): ToolDefinition { return tool({ description: "Spawn a teammate using native internal agent execution.", args: { team_name: tool.schema.string().describe("Team name"), name: tool.schema.string().describe("Teammate name"), prompt: tool.schema.string().describe("Initial teammate prompt"), subagent_type: tool.schema.string().optional().describe("Agent name to run (default: sisyphus-junior)"), model: tool.schema.string().optional().describe("Optional model override in provider/model format"), plan_mode_required: tool.schema.boolean().optional().describe("Enable plan mode flag in teammate metadata"), }, execute: async (args: Record, context: TeamToolContext): Promise => { try { const input = TeamSpawnInputSchema.parse(args) const teamError = validateTeamName(input.team_name) if (teamError) { return JSON.stringify({ error: teamError }) } const agentError = validateAgentName(input.name) if (agentError) { return JSON.stringify({ error: agentError }) } const teammate = await spawnTeammate({ teamName: input.team_name, name: input.name, prompt: input.prompt, subagentType: input.subagent_type ?? "sisyphus-junior", model: input.model, planModeRequired: input.plan_mode_required ?? false, context, manager, }) return JSON.stringify({ agent_id: teammate.agentId, name: teammate.name, team_name: input.team_name, session_id: teammate.sessionID, task_id: teammate.backgroundTaskID, }) } catch (error) { return JSON.stringify({ error: error instanceof Error ? error.message : "spawn_teammate_failed" }) } }, }) } export function createForceKillTeammateTool(manager: BackgroundManager): ToolDefinition { return tool({ description: "Force stop a teammate and clean up ownership state.", args: { team_name: tool.schema.string().describe("Team name"), agent_name: tool.schema.string().describe("Teammate name"), }, execute: async (args: Record): Promise => { try { const input = TeamForceKillInputSchema.parse(args) const teamError = validateTeamName(input.team_name) if (teamError) { return JSON.stringify({ error: teamError }) } const agentError = validateAgentName(input.agent_name) if (agentError) { return JSON.stringify({ error: agentError }) } const config = readTeamConfigOrThrow(input.team_name) const member = getTeamMember(config, input.agent_name) if (!member || !isTeammateMember(member)) { return JSON.stringify({ error: "teammate_not_found" }) } await cancelTeammateRun(manager, member) const refreshedConfig = readTeamConfigOrThrow(input.team_name) const refreshedMember = getTeamMember(refreshedConfig, input.agent_name) if (refreshedMember && isTeammateMember(refreshedMember)) { writeTeamConfig(input.team_name, removeTeammate(refreshedConfig, input.agent_name)) } resetOwnerTasks(input.team_name, input.agent_name) return JSON.stringify({ success: true, message: `${input.agent_name} stopped` }) } catch (error) { return JSON.stringify({ error: error instanceof Error ? error.message : "force_kill_teammate_failed" }) } }, }) } export function createProcessShutdownTool(manager: BackgroundManager): ToolDefinition { return tool({ description: "Finalize an approved shutdown by removing teammate and resetting owned tasks.", args: { team_name: tool.schema.string().describe("Team name"), agent_name: tool.schema.string().describe("Teammate name"), }, execute: async (args: Record): Promise => { try { const input = TeamProcessShutdownInputSchema.parse(args) const teamError = validateTeamName(input.team_name) if (teamError) { return JSON.stringify({ error: teamError }) } if (input.agent_name === "team-lead") { return JSON.stringify({ error: "cannot_shutdown_team_lead" }) } const agentError = validateAgentName(input.agent_name) if (agentError) { return JSON.stringify({ error: agentError }) } const config = readTeamConfigOrThrow(input.team_name) const member = getTeamMember(config, input.agent_name) if (!member || !isTeammateMember(member)) { return JSON.stringify({ error: "teammate_not_found" }) } await cancelTeammateRun(manager, member) updateTeamConfig(input.team_name, (current) => { const refreshedMember = getTeamMember(current, input.agent_name) if (!refreshedMember || !isTeammateMember(refreshedMember)) { return current } return removeTeammate(current, input.agent_name) }) resetOwnerTasks(input.team_name, input.agent_name) return JSON.stringify({ success: true, message: `${input.agent_name} removed` }) } catch (error) { return JSON.stringify({ error: error instanceof Error ? error.message : "process_shutdown_failed" }) } }, }) }