import { Type } from "typebox"; import { FINALIZE_TOOL_NAME } from "./constants.ts"; import type { PromptConfig, SubagentFinalizePayload } from "./types.ts"; import { FinalizeStatus } from "./types.ts"; // Resolve Tools - Use exactly one permission mode. approved_tools/allowed_tools // is a whitelist; denied_tools is a blacklist over the currently active tools. export function resolveTools( agent: PromptConfig, activeTools: string[], ): string[] { const withoutDelegationTools = (tools: string[]) => tools.filter((tool) => tool !== "subagent" && tool !== FINALIZE_TOOL_NAME); const resolved = agent.approvedTools.length > 0 ? withoutDelegationTools([...new Set(agent.approvedTools)]) : withoutDelegationTools( [...new Set(activeTools)].filter( (tool) => !new Set(agent.deniedTools).has(tool), ), ); return [...new Set([...resolved, FINALIZE_TOOL_NAME])]; } // Validate Finalize Payload - Keep the parent contract strict and small. export function validateFinalizePayload( value: unknown, ): SubagentFinalizePayload | null { if (!value || typeof value !== "object") return null; const payload = value as Record; if (payload.status === FinalizeStatus.SUCCESS) { return typeof payload.result === "string" && payload.result.trim() ? { status: FinalizeStatus.SUCCESS, result: payload.result } : null; } if (payload.status === FinalizeStatus.ERROR) { const result = typeof payload.result === "string" ? payload.result : undefined; return typeof payload.error === "string" && payload.error.trim() ? { status: FinalizeStatus.ERROR, error: payload.error, result } : null; } return null; } export const SubagentParams = Type.Object({ agent: Type.String({ description: "Name of the prompt-defined subagent to invoke", }), task: Type.String({ description: "Task to delegate to the subagent" }), sessionId: Type.Optional( Type.String({ description: "Optional sticky subagent session id. Reuse to continue a previous subagent context.", }), ), cwd: Type.Optional( Type.String({ description: "Working directory for the subagent process. Defaults to current cwd.", }), ), });