import path from "node:path";
import { activityJournalStatus } from "../activity-journal/index.js";
import { listAgentThreadHelpers, listAgentThreads } from "../agent-thread/index.js";
import { listBackgroundTasks } from "../background-state/index.js";
import { listContextBundles, readContextMetrics } from "../context-ledger/index.js";
import { peekLabMeetingDeadline } from "../lab-meeting/index.js";
import { readTraceSummary } from "../observability/index.js";
import { evaluateRunBudget, formatRunBudgetStatus, readRunBudget } from "../run-budget/index.js";
import { getRun, listTasks, runDir } from "../run-state/index.js";
import { listSubplans } from "../subplan/index.js";
import { listTeamInbox, listTeamMeetings, listTeamTasks, loadTeamRuntime } from "../team-mode/index.js";
import { listWorkspaceConflicts } from "../workspace-state/index.js";
export async function buildSeedStatusBoard(store, runId) {
    const requestedRun = await getRun(store, runId);
    const run = requestedRun;
    if (!run)
        return "No active SEED run found.";
    const tasks = await listTasks(store, run.run_id);
    const backgrounds = await listBackgroundTasks(store, run.run_id);
    const trace = await readTraceSummary(store, run.run_id);
    const teamRuntime = await loadTeamRuntime(store, run.run_id);
    const teamMembers = teamRuntime?.members ?? [];
    const teamTasks = teamRuntime ? await listTeamTasks(store, run.run_id) : [];
    const workspaceConflicts = await listWorkspaceConflicts(store, run.run_id);
    const labMeeting = await peekLabMeetingDeadline(store, run.run_id);
    const budgetState = await readRunBudget(store, run.run_id);
    const budgetEvaluation = budgetState ? await evaluateRunBudget(store, budgetState) : undefined;
    const contextBundles = await listContextBundles(store, run.run_id);
    const contextMetrics = await readContextMetrics(store, run.run_id, { limit: 20 });
    const subplans = await listSubplans(store, run.run_id);
    const threads = await listAgentThreads(store, run.run_id);
    const threadById = new Map(threads.map((thread) => [thread.thread_id, thread]));
    const helperCounts = Object.fromEntries(await Promise.all(threads.map(async (thread) => [
        thread.thread_id,
        (await listAgentThreadHelpers(store, run.run_id, thread.thread_id)).length,
    ])));
    const openMeetings = teamRuntime ? await listTeamMeetings(store, run.run_id, { status: "open" }) : [];
    const promptRefs = uniqueStrings([
        ...teamMembers.map((member) => member.prompt_ref).filter(isString),
        ...threads.map((thread) => thread.prompt_ref).filter(isString),
        ...trace.agentCalls.map((call) => call.full_prompt_ref).filter(isString),
    ]).slice(-6);
    const conversationRefs = uniqueStrings([
        ...teamMembers.filter((member) => member.name !== "lab-representative").map((member) => `team/inbox/${member.name}/`),
        ...openMeetings.map((meeting) => `team/meetings/${meeting.meeting_id}.json`),
    ]).slice(-8);
    const unreadByMember = Object.fromEntries(await Promise.all(teamMembers.map(async (member) => [
        member.name,
        (await listTeamInbox(store, run.run_id, member.name, { includeAcknowledged: false })).length,
    ])));
    const memberNames = new Set(teamMembers.map((member) => String(member.name)));
    const workerRows = [
        ...teamMembers.map((member) => {
            const roleId = String(member.name);
            const thread = threadById.get(roleId);
            return {
                role_id: roleId,
                role: thread?.role_label ?? member.role_label ?? member.role,
                opencode_agent: String(member.opencode_agent ?? member.resolved_agent ?? "lab-representative"),
                status: thread?.status ?? member.status,
                session_id: thread?.opencode_session_id ?? member.session_id,
                background_id: thread?.background_id ?? member.background_id,
                prompt_ref: thread?.prompt_ref ?? member.prompt_ref,
                tool_manifest_ref: thread?.tool_manifest_ref ?? member.tool_manifest_ref,
                helper_count: helperCounts[roleId] ?? member.helper_counts?.running ?? 0,
                latest_checkpoint: member.launch_error ?? thread?.capability_profile,
            };
        }),
        ...threads
            .filter((thread) => !memberNames.has(thread.thread_id))
            .map((thread) => ({
            role_id: thread.thread_id,
            role: thread.role_label ?? thread.role,
            opencode_agent: thread.agent_name,
            status: thread.status,
            session_id: thread.opencode_session_id,
            background_id: thread.background_id,
            prompt_ref: thread.prompt_ref,
            tool_manifest_ref: thread.tool_manifest_ref,
            helper_count: helperCounts[thread.thread_id] ?? 0,
            latest_checkpoint: thread.capability_profile,
        })),
    ];
    return formatSeedStatus({
        run_id: run.run_id,
        status: run.status,
        run_mode: run.run_mode,
        goal: run.professor_goal,
        active_agent: run.active_agent,
        progress_path: path.join(runDir(store, run.run_id), "progress.md"),
        activity_journal: activityJournalStatus(store, run.run_id),
        task_counts: countBy(tasks.map((task) => task.status)),
        team: {
            member_count: teamMembers.length,
            unread_by_member: unreadByMember,
            task_counts: countBy(teamTasks.map((task) => task.status)),
            workers: workerRows,
        },
        subplans: {
            counts: countBy(subplans.map((subplan) => subplan.status)),
            active: subplans
                .filter((subplan) => subplan.status !== "accepted" && subplan.status !== "cancelled")
                .slice(0, 6)
                .map((subplan) => ({
                id: subplan.subplan_id,
                status: subplan.status,
                title: subplan.title,
                owner: subplan.owner_member,
                verifier: subplan.verifier_member,
            })),
        },
        background_tasks: backgrounds.slice(-6).map((task) => ({
            id: task.background_id,
            agent: task.target_agent ?? task.kind,
            status: task.stale_at ? `${task.status} stale` : task.status,
            checkpoints: task.checkpoint_count,
            latest: task.stale_reason ?? task.last_message,
        })),
        budget: budgetState && budgetEvaluation ? formatRunBudgetStatus(budgetState, budgetEvaluation) : "- status: not initialized",
        context: {
            bundle_counts: countBy(contextBundles.map((bundle) => bundle.category)),
            latest_refs: contextBundles.slice(-6).map((bundle) => `context:${bundle.bundle_id} ${bundle.category}/${bundle.scope} ${bundle.title}`),
            metrics_count: contextMetrics.length,
            latest_metric: contextMetrics.at(-1)?.summary,
        },
        recent_events: trace.events.slice(-5).map((event) => `${event.type}: ${event.summary}`),
        refs: {
            latest_prompt_refs: promptRefs,
            latest_conversation_refs: conversationRefs,
        },
        lab_meeting: labMeeting.state
            ? {
                status: labMeeting.state.status,
                next_deadline_at: labMeeting.state.next_deadline_at,
                meeting_path: labMeeting.state.current_meeting_ref,
                waiting_background_ids: labMeeting.state.waiting_background_ids ?? [],
            }
            : undefined,
        reassurance: {
            current_phase: statusPhase(run.status, teamMembers.length, workspaceConflicts.filter((conflict) => conflict.status === "open").length),
            active_roles: teamMembers
                .filter((member) => ["queued", "launching", "running", "active", "waiting_on_mailbox", "blocked"].includes(member.status))
                .map((member) => `${member.name}:${member.status}`)
                .slice(0, 8),
            latest_safe_observation: trace.events.at(-1)?.summary ?? "No recent trace event yet.",
            blocker: statusBlocker({
                taskBlockers: tasks.filter((task) => task.status === "blocked").length,
                teamTaskBlockers: teamTasks.filter((task) => task.status === "blocked").length,
                failedBackgrounds: backgrounds.filter((task) => task.status === "failed").length,
                staleBackgrounds: backgrounds.filter((task) => task.status === "running" && task.stale_at).length,
                openWorkspaceConflicts: workspaceConflicts.filter((conflict) => conflict.status === "open").length,
            }),
            next_action: statusNextAction(run.status, backgrounds.some((task) => task.status === "running"), backgrounds.some((task) => task.status === "running" && task.stale_at)),
        },
    });
}
function countBy(values) {
    const output = {};
    for (const value of values)
        output[value] = (output[value] ?? 0) + 1;
    return output;
}
function uniqueStrings(values) {
    return [...new Set(values)];
}
function isString(value) {
    return typeof value === "string" && value.length > 0;
}
function formatSeedStatus(input) {
    const taskCounts = Object.entries(input.task_counts).map(([status, count]) => `${status}:${count}`).join(", ") || "none";
    const teamTaskCounts = Object.entries(input.team.task_counts).map(([status, count]) => `${status}:${count}`).join(", ") || "none";
    const unreadCounts = Object.entries(input.team.unread_by_member).map(([member, count]) => `${member}:${count}`).join(", ") || "none";
    const workerLines = input.team.workers.length
        ? [
            "| agent-thread | role | status | session/background | helpers | prompt/tool refs | latest checkpoint |",
            "| --- | --- | --- | --- | ---: | --- | --- |",
            ...input.team.workers.map((worker) => [
                `| ${worker.role_id}`,
                worker.role ?? "-",
                worker.status,
                [worker.session_id ? `session:${worker.session_id}` : "", worker.background_id ? `background:${worker.background_id}` : ""].filter(Boolean).join("<br>") || "-",
                String(worker.helper_count),
                [worker.prompt_ref ? `prompt:${worker.prompt_ref}` : "", worker.tool_manifest_ref ? `tools:${worker.tool_manifest_ref}` : ""].filter(Boolean).join("<br>") || "-",
                truncateTableCell(worker.latest_checkpoint ?? "-"),
            ].join(" | ") + " |"),
        ].join("\n")
        : "| agent-thread | role | status | session/background | helpers | prompt/tool refs | latest checkpoint |\n| --- | --- | --- | --- | ---: | --- | --- |\n| none | - | - | - | 0 | - | - |";
    const subplanCounts = Object.entries(input.subplans.counts).map(([status, count]) => `${status}:${count}`).join(", ") || "none";
    const activeSubplans = input.subplans.active.length
        ? input.subplans.active.map((subplan) => `- ${subplan.id} ${subplan.status}${subplan.owner ? ` owner:${subplan.owner}` : ""}${subplan.verifier ? ` verifier:${subplan.verifier}` : ""}: ${subplan.title}`).join("\n")
        : "- none";
    const backgrounds = input.background_tasks.length
        ? input.background_tasks.map((task) => `- ${task.id} ${task.agent} ${task.status} checkpoints:${task.checkpoints}${task.latest ? ` latest: ${task.latest.slice(0, 140)}` : ""}`).join("\n")
        : "- none";
    const events = input.recent_events.length ? input.recent_events.map((event) => `- ${event}`).join("\n") : "- none";
    const contextCounts = Object.entries(input.context.bundle_counts).map(([category, count]) => `${category}:${count}`).join(", ") || "none";
    const labMeeting = input.lab_meeting
        ? `Lab Meeting:
- status: ${input.lab_meeting.status}
- next deadline: ${input.lab_meeting.next_deadline_at}
- waiting backgrounds: ${input.lab_meeting.waiting_background_ids.length ? input.lab_meeting.waiting_background_ids.join(", ") : "none"}
- summary: ${input.lab_meeting.meeting_path ?? "(not written yet)"}`
        : "Lab Meeting: disabled";
    return `SEED status
Run: ${input.run_id}
Status: ${input.status}
Run mode: ${input.run_mode}
Goal: ${input.goal}
Active agent: ${input.active_agent}
Tasks: ${taskCounts}
Team:
- members: ${input.team.member_count}
- unread: ${unreadCounts}
- team tasks: ${teamTaskCounts}
Workers:
${workerLines}
Sub-plans:
- counts: ${subplanCounts}
${activeSubplans}
Background:
${backgrounds}
Budget:
${input.budget}
Context ledger:
- bundles: ${contextCounts}
- metrics sampled: ${input.context.metrics_count}
- latest metric: ${input.context.latest_metric ?? "none"}
- recent refs: ${input.context.latest_refs.join(", ") || "none"}
${labMeeting}
Recent trace:
${events}
Refs:
- prompts: ${input.refs.latest_prompt_refs.join(", ") || "none"}
- conversations: ${input.refs.latest_conversation_refs.join(", ") || "none"}
Reassurance:
- current phase: ${input.reassurance.current_phase}
- active roles: ${input.reassurance.active_roles.length ? input.reassurance.active_roles.join(", ") : input.active_agent}
- latest safe observation: ${input.reassurance.latest_safe_observation}
- blocker: ${input.reassurance.blocker}
- next action: ${input.reassurance.next_action}
Progress: ${input.progress_path}
Activity journal:
- latest briefing: ${input.activity_journal.latest_path}
- index: ${input.activity_journal.index_path}
- latest: ${input.activity_journal.latest_path}
- current window: ${input.activity_journal.current_window_path}

Read-only note: /seed-status is handled by the OpenCode/SEED TUI framework, not sent to Lab-Representative. It does not wake Lab-Representative, checkpoint backgrounds, write progress/report files, transition subplans, or mutate team state.`;
}
function statusPhase(status, teamMemberCount, openWorkspaceConflicts) {
    if (status === "awaiting_feedback")
        return "awaiting-feedback lab meeting";
    if (status !== "running")
        return status;
    if (openWorkspaceConflicts > 0)
        return "conflict resolution";
    if (teamMemberCount > 1)
        return "team orchestration";
    return "running";
}
function statusBlocker(input) {
    const blockers = [
        input.taskBlockers ? `${input.taskBlockers} blocked task(s)` : "",
        input.teamTaskBlockers ? `${input.teamTaskBlockers} blocked team task(s)` : "",
        input.failedBackgrounds ? `${input.failedBackgrounds} failed background task(s)` : "",
        input.staleBackgrounds ? `${input.staleBackgrounds} stale background task(s)` : "",
        input.openWorkspaceConflicts ? `${input.openWorkspaceConflicts} open workspace conflict(s)` : "",
    ].filter(Boolean);
    return blockers.join(", ") || "no blocker";
}
function truncateTableCell(value) {
    return value.replace(/\s+/g, " ").replace(/\|/g, "\\|").slice(0, 120);
}
function statusNextAction(status, hasRunningBackground, hasStaleBackground = false) {
    if (status === "completed")
        return "Review final report and cited evidence.";
    if (status === "stopped")
        return "Start a new /seed run if more work is needed.";
    if (status === "awaiting_feedback")
        return "Send normal professor feedback in the Lab-Representative chat to resume.";
    if (status === "blocked")
        return "Resolve the blocker or record professor guidance.";
    if (hasStaleBackground)
        return "Review stale background workers, then checkpoint, follow up, cancel, or relaunch.";
    if (hasRunningBackground)
        return "Monitor active background work and checkpoint if it runs long.";
    return "Continue the Lab-Representative plan and keep the latest briefing current.";
}
//# sourceMappingURL=index.js.map