import { writeArtifact } from "../../features/artifact-store/index.js";
import { assertLabMeetingAllowsInternalWork } from "../../features/lab-meeting/index.js";
import { appendAgentCall, appendEvent } from "../../features/observability/index.js";
import { claimIdempotencyKey, completeIdempotencyKey } from "../../features/idempotency/index.js";
import { compactModelRoute, currentModelFromRun, resolveModelRoute } from "../../features/model-routing/index.js";
import { assertRunBudgetAllowsDelegation, recordRunBudgetUsage } from "../../features/run-budget/index.js";
import { recordHelperLaunch } from "../../features/agent-thread/index.js";
import { createMcpInventory, loadSeedSkill, recommendSeedSkills, skillRoots, } from "../../features/skill-loader/index.js";
import { addTeamMemberToRuntime, appendTeamConversationEntry, loadTeamRuntime, recordTeamMemberLaunch, resolveTeamActor, } from "../../features/team-mode/index.js";
import { createId, nowIso, sanitizeText } from "../../shared/index.js";
import { jsonToolOutput, requireSeedRun } from "./common.js";
import { LAB_REPRESENTATIVE_AGENT } from "../../agents/identity.js";
async function currentSeedActor(store, runId, context) {
    return resolveTeamActor(store, runId, {
        sessionId: context.sessionID,
        fallbackAgent: context.agent ?? store.config.default_run_agent ?? LAB_REPRESENTATIVE_AGENT,
    });
}
export async function executeDelegate(store, args, context, mode, runtime) {
    const run = await requireSeedRun(store, context, args.run_id);
    const actor = await currentSeedActor(store, run.run_id, context);
    const gate = await assertLabMeetingAllowsInternalWork(store, run.run_id, `seed_delegate ${mode}`);
    if (!gate.allowed) {
        await appendEvent(store, run.run_id, {
            type: "lab_meeting_internal_work_blocked",
            actor,
            session_id: context.sessionID,
            summary: gate.reason,
            metadata: { action: `seed_delegate ${mode}`, meeting_path: gate.meeting_path },
        });
        return jsonToolOutput("SEED delegation paused for Lab Meeting", {
            run_id: run.run_id,
            status: "blocked",
            reason: gate.reason,
            meeting_path: gate.meeting_path,
        });
    }
    const budgetGate = await assertRunBudgetAllowsDelegation(store, run.run_id);
    if (!budgetGate.allowed) {
        await appendEvent(store, run.run_id, {
            type: "run_budget_delegation_blocked",
            actor,
            session_id: context.sessionID,
            summary: budgetGate.reason,
            metadata: { mode, target_agent: args.target_agent, evaluation: budgetGate.evaluation },
        });
        return jsonToolOutput("SEED delegation blocked by run budget", {
            run_id: run.run_id,
            status: "blocked",
            reason: budgetGate.reason,
            budget: budgetGate.state,
        });
    }
    const agentCallId = createId("agent_call");
    const start = nowIso();
    const requestedTargetAgent = normalizeDelegationTarget(args.target_agent);
    const openCodeAgent = LAB_REPRESENTATIVE_AGENT;
    const teamMember = await ensureDelegationMember(store, run.run_id, {
        targetAgent: requestedTargetAgent,
        parentSessionId: context.sessionID,
        actor,
    });
    const sessionTools = teamMember ? sessionToolsForTeamMember(teamMember) : undefined;
    const idempotencyKey = args.idempotency_key;
    if (idempotencyKey) {
        const claim = await claimIdempotencyKey(store, run.run_id, {
            key: idempotencyKey,
            scope: "delegation",
            action: mode,
            actor,
            metadata: { agent_call_id: agentCallId, target_agent: requestedTargetAgent, task_id: args.task_id },
        });
        if (!claim.claimed) {
            return jsonToolOutput("SEED delegation deduplicated", {
                run_id: run.run_id,
                status: "deduplicated",
                idempotency: claim.record,
            });
        }
    }
    const modelRoute = resolveModelRoute(store.config, openCodeAgent, currentModelFromRun(run));
    const autoSkillRecommendations = args.auto_skills === true
        ? await recommendSkillsForDelegation(store, run.run_id, requestedTargetAgent, args.prompt, args.prompt_summary)
        : [];
    const requestedSkills = uniqueStrings([
        ...(args.skills ?? []),
        ...autoSkillRecommendations.filter((recommendation) => recommendation.status === "ready").map((recommendation) => recommendation.name),
    ]);
    if (args.auto_skills === true) {
        await appendEvent(store, run.run_id, {
            type: "delegation_skill_recommendations_used",
            actor,
            session_id: context.sessionID,
            summary: `${requestedTargetAgent}: ${autoSkillRecommendations.length} skill recommendation(s) considered`,
            related_agent_call_id: agentCallId,
            related_task_id: args.task_id,
            metadata: {
                recommendations: autoSkillRecommendations.map(compactSkillRecommendation),
                selected_skills: requestedSkills,
            },
        });
    }
    const skillContext = await buildDelegationSkillContext(store, store.config, run.run_id, requestedSkills, context, agentCallId);
    if (skillContext.status === "blocked") {
        if (idempotencyKey) {
            await completeIdempotencyKey(store, run.run_id, idempotencyKey, {
                status: "failed",
                result_ref: agentCallId,
                metadata: { reason: skillContext.reason },
            });
        }
        await appendEvent(store, run.run_id, {
            type: "delegation_skill_context_blocked",
            actor,
            session_id: context.sessionID,
            summary: `${requestedTargetAgent}: skill context blocked delegation`,
            related_agent_call_id: agentCallId,
            related_task_id: args.task_id,
            metadata: skillContext,
        });
        return jsonToolOutput("SEED delegation blocked", {
            run_id: run.run_id,
            agent_call_id: agentCallId,
            target_agent: requestedTargetAgent,
            opencode_agent: openCodeAgent,
            mode,
            auto_skill_recommendations: autoSkillRecommendations.map(compactSkillRecommendation),
            ...skillContext,
        });
    }
    const delegatedPrompt = skillContext.prompt_prefix ? `${skillContext.prompt_prefix}\n\n${args.prompt}` : args.prompt;
    const promptRef = await writeArtifact(store, run.run_id, {
        name: `${agentCallId}.prompt`,
        extension: ".md",
        content: delegatedPrompt,
    });
    const callBase = {
        agent_call_id: agentCallId,
        idempotency_key: args.idempotency_key,
        timestamp_start: start,
        run_id: run.run_id,
        parent_session_id: context.sessionID,
        caller_agent: actor,
        target_agent: requestedTargetAgent,
        task_id: args.task_id,
        mode,
        prompt_summary: args.prompt_summary ?? args.prompt.slice(0, 200),
        full_prompt_ref: promptRef,
        model_profile: modelRoute.model_profile,
        requested_model: modelRoute.requested_model,
        evidence_refs: [],
    };
    await appendTeamConversationEntry(store, run.run_id, {
        type: "agent_call_requested",
        from: actor,
        to: requestedTargetAgent,
        agent_call_id: agentCallId,
        prompt_ref: promptRef,
        prompt_summary: callBase.prompt_summary,
        status: "running",
        metadata: {
            mode,
            task_id: args.task_id,
            opencode_agent: openCodeAgent,
            model_route: compactModelRoute(modelRoute),
            allowed_tools: teamMember?.tool_policy?.allowed_tools ?? [],
            denied_tools: teamMember?.tool_policy?.denied_tools ?? [],
            read_paths: teamMember?.read_paths ?? [],
            write_paths: teamMember?.write_paths ?? [],
            mcp_policy: teamMember?.mcp_policy,
            skill_policy: teamMember?.skill_policy,
            session_tools: sessionTools,
            skills: skillContext.loaded,
            auto_skill_recommendations: autoSkillRecommendations.map(compactSkillRecommendation),
        },
    });
    if (skillContext.loaded.length > 0) {
        await appendEvent(store, run.run_id, {
            type: "delegation_skill_context_loaded",
            actor,
            session_id: context.sessionID,
            summary: `${requestedTargetAgent}: loaded ${skillContext.loaded.map((skill) => skill.name).join(", ")}`,
            related_agent_call_id: agentCallId,
            related_task_id: args.task_id,
            metadata: { skills: skillContext.loaded },
        });
    }
    const pendingAttempts = assignAttemptIdentity(agentCallId, plannedModelAttempts(modelRoute));
    await appendAgentCall(store, run.run_id, {
        ...callBase,
        current_attempt_id: currentAttemptId(pendingAttempts),
        status: "running",
        result_summary: "OpenCode child session launch requested.",
        model_attempts: pendingAttempts,
    });
    await appendEvent(store, run.run_id, {
        type: "agent_delegated",
        actor,
        summary: `${requestedTargetAgent}: ${args.prompt_summary ?? args.prompt.slice(0, 100)}`,
        related_agent_call_id: agentCallId,
        related_task_id: args.task_id,
        metadata: {
            model_route: compactModelRoute(modelRoute),
            requested_target_agent: requestedTargetAgent,
            opencode_agent: openCodeAgent,
            skills: skillContext.loaded,
            auto_skill_recommendations: autoSkillRecommendations.map(compactSkillRecommendation),
        },
    });
    try {
        const child = await runtime.launchOpenCodeDelegation({
            parentSessionId: context.sessionID,
            targetAgent: requestedTargetAgent,
            openCodeAgent,
            prompt: delegatedPrompt,
            promptSummary: args.prompt_summary ?? args.prompt.slice(0, 200),
            mode,
            modelRoute,
            sessionTools,
        });
        const outputRef = child.output
            ? await writeArtifact(store, run.run_id, {
                name: `${agentCallId}.response`,
                extension: ".md",
                content: child.output,
            })
            : undefined;
        const budget = await recordRunBudgetUsage(store, run.run_id, {
            child_sessions: 1,
            model_calls: countCompletedModelAttempts(child.modelAttempts),
            model: child.resolvedModel,
            token_usage: child.tokenUsage,
        });
        if (mode === "background") {
            const backgroundId = createId("bg");
            const helper = actor !== LAB_REPRESENTATIVE_AGENT
                ? await recordHelperLaunch(store, run.run_id, {
                    owner_thread_id: actor,
                    target_agent: requestedTargetAgent,
                    prompt_ref: promptRef,
                    prompt_summary: callBase.prompt_summary,
                    child_session_id: child.sessionId,
                    background_id: backgroundId,
                    agent_call_id: agentCallId,
                    status: "running",
                    allowed_tools: teamMember?.tool_policy?.allowed_tools ?? [],
                    denied_tools: teamMember?.tool_policy?.denied_tools ?? [],
                    allowed_skills: teamMember?.skill_policy?.allowed_skills ?? [],
                    denied_skills: teamMember?.skill_policy?.denied_skills ?? [],
                })
                : undefined;
            await runtime.registerBackgroundDelegation({
                runId: run.run_id,
                backgroundId,
                startedAt: start,
                sessionId: child.sessionId,
                parentSessionId: context.sessionID,
                agentCallId,
                targetAgent: requestedTargetAgent,
                taskId: args.task_id,
                title: args.prompt_summary ?? args.prompt.slice(0, 160),
                ownerThreadId: helper?.owner_thread_id,
                helperId: helper?.helper_id,
            });
            const completedAttempts = assignAttemptIdentity(agentCallId, child.modelAttempts);
            await appendAgentCall(store, run.run_id, {
                ...callBase,
                current_attempt_id: currentAttemptId(completedAttempts),
                timestamp_end: nowIso(),
                child_session_id: child.sessionId,
                status: "queued",
                result_summary: `OpenCode background session launched: ${child.sessionId}`,
                resolved_model: child.resolvedModel,
                model_attempts: completedAttempts,
                evidence_refs: outputRef ? [outputRef] : [],
            });
            await recordDelegationMemberLaunch(store, run.run_id, requestedTargetAgent, {
                status: "active",
                launch_status: "queued",
                session_id: child.sessionId,
                background_id: backgroundId,
                agent_call_id: agentCallId,
                prompt_ref: promptRef,
                resolved_agent: openCodeAgent,
                opencode_agent: openCodeAgent,
            });
            await appendTeamConversationEntry(store, run.run_id, {
                type: "agent_call_queued",
                from: actor,
                to: requestedTargetAgent,
                agent_call_id: agentCallId,
                child_session_id: child.sessionId,
                background_id: backgroundId,
                prompt_ref: promptRef,
                prompt_summary: callBase.prompt_summary,
                status: "queued",
                metadata: {
                    mode,
                    opencode_agent: openCodeAgent,
                    resolved_model: child.resolvedModel,
                    model_attempts: completedAttempts,
                    output_ref: outputRef,
                    owner_thread_id: helper?.owner_thread_id,
                    helper_id: helper?.helper_id,
                },
            });
            if (idempotencyKey) {
                await completeIdempotencyKey(store, run.run_id, idempotencyKey, {
                    result_ref: agentCallId,
                    metadata: { child_session_id: child.sessionId, background_id: backgroundId },
                });
            }
            return jsonToolOutput("SEED delegation launched", {
                run_id: run.run_id,
                agent_call_id: agentCallId,
                child_session_id: child.sessionId,
                background_id: backgroundId,
                helper_id: helper?.helper_id,
                target_agent: requestedTargetAgent,
                opencode_agent: openCodeAgent,
                mode,
                prompt_ref: promptRef,
                skills: skillContext.loaded,
                auto_skill_recommendations: autoSkillRecommendations.map(compactSkillRecommendation),
                budget,
            });
        }
        const completedAttempts = assignAttemptIdentity(agentCallId, child.modelAttempts);
        await appendAgentCall(store, run.run_id, {
            ...callBase,
            current_attempt_id: currentAttemptId(completedAttempts),
            timestamp_end: nowIso(),
            child_session_id: child.sessionId,
            status: "completed",
            result_summary: child.output ? child.output.slice(0, 1000) : `OpenCode child session completed: ${child.sessionId}`,
            resolved_model: child.resolvedModel,
            model_attempts: completedAttempts,
            evidence_refs: outputRef ? [outputRef] : [],
            token_usage: child.tokenUsage,
        });
        await recordDelegationMemberLaunch(store, run.run_id, requestedTargetAgent, {
            status: "completed",
            launch_status: "queued",
            session_id: child.sessionId,
            agent_call_id: agentCallId,
            prompt_ref: promptRef,
            resolved_agent: openCodeAgent,
            opencode_agent: openCodeAgent,
        });
        await appendTeamConversationEntry(store, run.run_id, {
            type: "agent_call_completed",
            from: requestedTargetAgent,
            to: actor,
            agent_call_id: agentCallId,
            child_session_id: child.sessionId,
            prompt_ref: promptRef,
            prompt_summary: callBase.prompt_summary,
            status: "completed",
            metadata: {
                mode,
                opencode_agent: openCodeAgent,
                resolved_model: child.resolvedModel,
                model_attempts: completedAttempts,
                output_ref: outputRef,
                output_summary: child.output?.slice(0, 1000),
            },
        });
        if (idempotencyKey) {
            await completeIdempotencyKey(store, run.run_id, idempotencyKey, {
                result_ref: agentCallId,
                metadata: { child_session_id: child.sessionId },
            });
        }
        return jsonToolOutput("SEED delegation completed", {
            run_id: run.run_id,
            agent_call_id: agentCallId,
            child_session_id: child.sessionId,
            target_agent: requestedTargetAgent,
            opencode_agent: openCodeAgent,
            mode,
            resolved_model: child.resolvedModel,
            model_attempts: completedAttempts,
            skills: skillContext.loaded,
            auto_skill_recommendations: autoSkillRecommendations.map(compactSkillRecommendation),
            prompt_ref: promptRef,
            output_ref: outputRef,
            output_summary: child.output?.slice(0, 1000),
            budget,
        });
    }
    catch (error) {
        const message = error instanceof Error ? error.message : String(error);
        const modelAttempts = modelAttemptsFromError(error);
        const failedAttempts = assignAttemptIdentity(agentCallId, modelAttempts.length ? modelAttempts : plannedModelAttempts(modelRoute));
        if (failedAttempts.some((attempt) => attempt.status === "failed" || attempt.status === "succeeded")) {
            await recordRunBudgetUsage(store, run.run_id, {
                model_calls: countCompletedModelAttempts(failedAttempts),
                model: failedAttempts.find((attempt) => attempt.current)?.model,
            });
        }
        await appendAgentCall(store, run.run_id, {
            ...callBase,
            current_attempt_id: currentAttemptId(failedAttempts),
            timestamp_end: nowIso(),
            status: "failed",
            result_summary: "OpenCode delegation failed.",
            model_attempts: failedAttempts,
            evidence_refs: [],
            error: message,
        });
        await recordDelegationMemberLaunch(store, run.run_id, requestedTargetAgent, {
            status: "failed",
            launch_status: "failed",
            agent_call_id: agentCallId,
            prompt_ref: promptRef,
            resolved_agent: openCodeAgent,
            opencode_agent: openCodeAgent,
            launch_error: message,
        });
        await appendTeamConversationEntry(store, run.run_id, {
            type: "agent_call_failed",
            from: requestedTargetAgent,
            to: actor,
            agent_call_id: agentCallId,
            prompt_ref: promptRef,
            prompt_summary: callBase.prompt_summary,
            status: "failed",
            metadata: {
                mode,
                opencode_agent: openCodeAgent,
                model_attempts: failedAttempts,
                error: message,
            },
        });
        if (idempotencyKey) {
            await completeIdempotencyKey(store, run.run_id, idempotencyKey, {
                status: "failed",
                result_ref: agentCallId,
                metadata: { error: message },
            });
        }
        await appendEvent(store, run.run_id, {
            type: "agent_delegation_failed",
            actor,
            summary: `${requestedTargetAgent}: ${message.slice(0, 180)}`,
            related_agent_call_id: agentCallId,
            related_task_id: args.task_id,
        });
        throw error;
    }
}
function normalizeDelegationTarget(target) {
    const normalized = sanitizeText(target).trim();
    return normalized.length > 0 ? normalized : LAB_REPRESENTATIVE_AGENT;
}
async function ensureDelegationMember(store, runId, input) {
    if (!store.config.team_mode.enabled)
        return undefined;
    if (input.targetAgent === LAB_REPRESENTATIVE_AGENT)
        return undefined;
    const runtime = await loadTeamRuntime(store, runId);
    if (!runtime)
        return undefined;
    const existing = runtime.members.find((member) => member.name === input.targetAgent);
    if (existing)
        return existing;
    const timestamp = nowIso();
    const member = {
        name: input.targetAgent,
        role: "member",
        status: "launching",
        joined_at: timestamp,
        last_seen_at: timestamp,
        role_label: input.targetAgent,
        capability_profile: "execution",
        resolved_agent: LAB_REPRESENTATIVE_AGENT,
        opencode_agent: LAB_REPRESENTATIVE_AGENT,
        parent_session_id: input.parentSessionId,
        coverage: ["executor"],
        mission_prompt: `${input.targetAgent}: complete the delegated SEED work order and report evidence or blockers.`,
        model_route: { fallback_profiles: [] },
        spawn_policy: store.config.virtual_member_defaults.default_spawn_policy,
        launch_policy: { mode: "background", wait_for_dependencies: false },
        delivery_policy: { report_to: input.actor, expected_artifact_paths: [] },
        evidence_contract: { required_refs: [], required_artifacts: [], oracle_scope: [] },
        read_paths: [],
        write_paths: [],
        evidence_paths: [],
        artifact_paths: [],
        expected_outputs: [],
        dependencies: [],
        artifact_inputs: [],
        evidence_inputs: [],
        verifier_obligations: [],
        oracle_scope: [],
        tool_policy: { allowed_tools: [], denied_tools: [] },
        mcp_policy: { allowed_mcps: [], denied_mcps: [] },
        skill_policy: { allowed_skills: [], denied_skills: [], allow_user_skills: false },
        pending_message_ids: [],
        launch_status: "pending",
    };
    try {
        await addTeamMemberToRuntime(store, runId, member);
        await appendTeamConversationEntry(store, runId, {
            type: "member_registered_from_delegation",
            from: input.actor,
            to: input.targetAgent,
            status: "registered",
            metadata: {
                role_id: input.targetAgent,
                parent_session_id: input.parentSessionId,
                reason: "seed_delegate target was not yet present in team/runtime.json",
            },
        });
        return member;
    }
    catch (error) {
        const latest = await loadTeamRuntime(store, runId);
        return latest?.members.find((candidate) => candidate.name === input.targetAgent);
    }
}
async function recordDelegationMemberLaunch(store, runId, targetAgent, patch) {
    if (targetAgent === LAB_REPRESENTATIVE_AGENT)
        return;
    const runtime = await loadTeamRuntime(store, runId);
    if (!runtime?.members.some((member) => member.name === targetAgent))
        return;
    await recordTeamMemberLaunch(store, runId, targetAgent, patch).catch(() => undefined);
}
export function sessionToolsForTeamMember(member) {
    const tools = {
        question: false,
        task: member.spawn_policy?.allowed === true && member.spawn_policy.requires_lab_representative_approval === false,
        seed_delegate: false,
        seed_delegate_background: false,
        seed_delegate_followup: false,
    };
    for (const safe of [
        "seed_team_inbox",
        "seed_team_ack",
        "seed_team_send",
        "seed_team_broadcast",
        "seed_team_status",
        "seed_team_roster",
        "seed_team_conversation",
        "seed_team_meeting_create",
        "seed_team_meeting_post",
        "seed_team_meeting_status",
        "seed_team_meeting_close",
        "seed_team_member_request",
        "seed_team_task_list",
        "seed_context_bundle_list",
        "seed_context_bundle_read",
        "seed_context_metrics",
        "seed_orchestrator_next",
        "seed_orchestrator_record_decision",
        "seed_orchestrator_tick",
        "seed_session_info",
    ]) {
        tools[safe] = true;
    }
    for (const allowed of member.tool_policy?.allowed_tools ?? []) {
        for (const permission of permissionsForToolName(allowed))
            tools[permission] = true;
    }
    for (const denied of member.tool_policy?.denied_tools ?? []) {
        for (const permission of permissionsForToolName(denied))
            tools[permission] = false;
    }
    const canSpawn = member.spawn_policy?.allowed === true &&
        (member.spawn_policy.max_depth ?? 0) > 0 &&
        member.spawn_policy.requires_lab_representative_approval === false;
    if (canSpawn) {
        for (const toolName of member.tool_policy?.allowed_tools ?? []) {
            if (toolName === "seed_delegate" || toolName === "seed_delegate_background" || toolName === "seed_delegate_followup") {
                tools[toolName] = true;
            }
        }
    }
    return tools;
}
function permissionsForToolName(toolName) {
    const normalized = toolName.trim().toLowerCase();
    switch (normalized) {
        case "apply_patch":
        case "edit":
        case "write":
        case "multi_edit":
        case "notebook_edit":
            return [normalized, "edit"];
        case "read":
        case "grep":
        case "glob":
        case "bash":
        case "websearch":
        case "webfetch":
        case "task":
            return [normalized];
        default:
            return [normalized];
    }
}
async function buildDelegationSkillContext(store, config, runId, names, context, agentCallId) {
    const requested = uniqueStrings(names.map((name) => sanitizeText(name).trim()).filter(Boolean));
    if (requested.length === 0)
        return { status: "ready", loaded: [] };
    if (config.skills.enabled === false) {
        return {
            status: "blocked",
            reason: "Skill loading is disabled.",
            requested_skills: requested,
            next_action: "Enable skills.enabled or remove skills from the delegation request.",
        };
    }
    const roots = skillRoots(store.directory, config);
    const inventory = createMcpInventory(config, store.directory);
    const loadedSkills = [];
    const missingSkills = [];
    const blockedDiagnostics = [];
    for (const name of requested) {
        const skill = await loadSeedSkill(name, roots, inventory);
        if (!skill) {
            missingSkills.push(name);
            continue;
        }
        const unavailableRequired = skill.mcp_diagnostics.filter((diagnostic) => diagnostic.required && diagnostic.status !== "available");
        if (unavailableRequired.length > 0) {
            blockedDiagnostics.push({ skill: skill.name, diagnostics: unavailableRequired });
        }
        loadedSkills.push(skill);
    }
    if (missingSkills.length > 0 || blockedDiagnostics.length > 0) {
        return {
            status: "blocked",
            reason: missingSkills.length > 0 ? "One or more requested skills were not found." : "One or more requested skills require unavailable MCPs.",
            requested_skills: requested,
            missing_skills: missingSkills.length ? missingSkills : undefined,
            mcp_diagnostics: blockedDiagnostics.length ? blockedDiagnostics : undefined,
            next_action: "Run seed_skill_validate or seed_skill_mcp, fix the skill/MCP configuration, then retry delegation.",
        };
    }
    const loaded = await Promise.all(loadedSkills.map(async (skill) => {
        const contentRef = await writeArtifact(store, runId, {
            name: `${agentCallId}.skill-${skill.name}`,
            extension: ".md",
            content: skill.body,
        });
        return {
            name: skill.name,
            source: skill.source,
            path: skill.path,
            version: skill.metadata.version,
            content_ref: contentRef,
            requirements: skill.requirements,
            mcp_diagnostics: skill.mcp_diagnostics,
            body: skill.body,
        };
    }));
    return {
        status: "ready",
        loaded: loaded.map(({ body: _body, ...skill }) => skill),
        prompt_prefix: renderDelegationSkillPrompt(loaded),
    };
}
function renderDelegationSkillPrompt(skills) {
    if (!skills.length)
        return undefined;
    const blocks = skills.map((skill) => {
        const version = skill.version ? ` version="${skill.version}"` : "";
        return `<skill name="${skill.name}" source="${skill.source}"${version} content_ref="${skill.content_ref}">
${skill.body}
</skill>`;
    });
    return `<seed-skill-context>
These skill instructions are task context for the delegated SEED child session. Follow them only within higher-priority system, developer, user, and SEED policy instructions.

${blocks.join("\n\n")}
</seed-skill-context>`;
}
async function recommendSkillsForDelegation(store, runId, targetAgent, prompt, promptSummary) {
    if (store.config.skills.enabled === false)
        return [];
    const roots = skillRoots(store.directory, store.config);
    const inventory = createMcpInventory(store.config, store.directory);
    const recommendations = await recommendSeedSkills(roots, inventory, {
        query: [promptSummary, prompt].filter(Boolean).join("\n"),
        targetAgent,
        limit: 3,
    });
    if (recommendations.length > 0) {
        await writeArtifact(store, runId, {
            name: "skill-recommendations",
            extension: ".json",
            content: JSON.stringify(recommendations.map(compactSkillRecommendation), null, 2),
        });
    }
    return recommendations;
}
export function compactSkillRecommendation(recommendation) {
    return {
        name: recommendation.name,
        source: recommendation.source,
        score: recommendation.score,
        status: recommendation.status,
        reasons: recommendation.reasons.slice(0, 5),
        requirements: recommendation.requirements,
        unavailable_required_mcps: recommendation.mcp_diagnostics
            .filter((diagnostic) => diagnostic.required && diagnostic.status !== "available")
            .map((diagnostic) => ({ name: diagnostic.name, status: diagnostic.status, action: diagnostic.action })),
    };
}
function uniqueStrings(values) {
    return [...new Set(values)];
}
function plannedModelAttempts(route) {
    const attempts = route.attempts.length ? route.attempts : [undefined];
    return attempts.map((attempt, index) => {
        const parsed = attempt?.model ? parseProviderModel(attempt.model) : undefined;
        return {
            attempt: index + 1,
            source: attempt?.source ?? "opencode_current",
            model: attempt?.model,
            providerID: attempt?.providerID ?? parsed?.providerID,
            modelID: attempt?.modelID ?? parsed?.modelID,
            variant: attempt?.variant,
            model_profile: attempt?.model_profile,
            status: "pending",
        };
    });
}
function assignAttemptIdentity(agentCallId, attempts) {
    const latestTerminal = [...attempts].reverse().find((attempt) => attempt.status === "succeeded" || attempt.status === "failed");
    const currentAttemptNumber = latestTerminal?.attempt ?? attempts.at(-1)?.attempt;
    return attempts.map((attempt) => ({
        ...attempt,
        attempt_id: attempt.attempt_id ?? `${agentCallId}-attempt-${attempt.attempt}`,
        current: attempt.attempt === currentAttemptNumber,
        stale: currentAttemptNumber !== undefined ? attempt.attempt < currentAttemptNumber : false,
    }));
}
function currentAttemptId(attempts) {
    return attempts.find((attempt) => attempt.current)?.attempt_id ?? attempts.at(-1)?.attempt_id;
}
function countCompletedModelAttempts(attempts) {
    return attempts.filter((attempt) => attempt.status === "succeeded" || attempt.status === "failed").length || 1;
}
function modelAttemptsFromError(error) {
    if (!error || typeof error !== "object")
        return [];
    const attempts = error.modelAttempts;
    return Array.isArray(attempts) ? attempts : [];
}
function parseProviderModel(model) {
    const [providerID, ...rest] = model.split("/");
    const modelID = rest.join("/");
    return providerID && modelID ? { providerID, modelID } : undefined;
}
//# sourceMappingURL=delegation.js.map