const ACTIVE_SERVER_STATUSES = new Set([
    "queued",
    "running",
    "waitingforapproval",
    "waitingforinput",
]);
function normalizeStatus(value) {
    return (value || "").replace(/\s+/g, "").toLowerCase();
}
function isWaitingForCapacity(localSnapshot, serverDiagnostics) {
    if (normalizeStatus(localSnapshot.lastStatusReason) === "machinecapacity") {
        return true;
    }
    if (normalizeStatus(serverDiagnostics?.transport?.lastStatusState) ===
        "waitingforcapacity") {
        return true;
    }
    return (normalizeStatus(serverDiagnostics?.execution?.status) === "running" &&
        (serverDiagnostics?.persistentLogs || []).some((log) => normalizeStatus(log.stage) === "waiting-for-capacity"));
}
function toTimestamp(value) {
    if (!value)
        return null;
    const parsed = Date.parse(value);
    return Number.isFinite(parsed) ? parsed : null;
}
function getMostRecentTimestamp(values) {
    let latest = null;
    for (const value of values) {
        const parsed = toTimestamp(value);
        if (parsed == null)
            continue;
        if (latest == null || parsed > latest) {
            latest = parsed;
        }
    }
    return latest;
}
export function isServerExecutionActive(diagnostics) {
    return ACTIVE_SERVER_STATUSES.has(normalizeStatus(diagnostics?.execution?.status ?? null));
}
export function interpretAgentRunDiagnostics(params) {
    const { socketDiagnostics, localSnapshot, serverDiagnostics, now = new Date(), stalledAfterMs = 30_000, } = params;
    const serverActive = isServerExecutionActive(serverDiagnostics);
    const serverFailed = normalizeStatus(serverDiagnostics?.execution?.status) === "error" ||
        serverDiagnostics?.transport?.lastLifecycleEventType === "agent:run:error";
    const socketOpen = socketDiagnostics.readyStateLabel === "open";
    const sessionSubscribed = serverDiagnostics?.currentSession?.isSubscribed ?? localSnapshot.isSubscribed;
    const sessionConnected = serverDiagnostics?.currentSession?.isConnected ?? socketOpen;
    const serverLastSeq = serverDiagnostics?.currentSession?.lastDelivery?.lastSeq ??
        serverDiagnostics?.transport?.lastSeq ??
        null;
    const serverLastDeliveryAt = getMostRecentTimestamp([
        serverDiagnostics?.currentSession?.lastDelivery?.lastSuccessAt,
        serverDiagnostics?.transport?.lastBroadcastAt,
        serverDiagnostics?.transport?.lastProducedAt,
    ]);
    const latestProgressAt = getMostRecentTimestamp([
        localSnapshot.lastEventAt,
        serverDiagnostics?.transport?.lastBroadcastAt,
        serverDiagnostics?.transport?.lastProducedAt,
    ]);
    const clientLagging = serverActive &&
        socketOpen &&
        sessionConnected &&
        sessionSubscribed &&
        typeof serverLastSeq === "number" &&
        serverLastSeq > localSnapshot.lastSeq &&
        serverLastDeliveryAt != null &&
        now.getTime() - serverLastDeliveryAt > 8_000;
    const stalled = serverActive &&
        socketOpen &&
        latestProgressAt != null &&
        now.getTime() - latestProgressAt > stalledAfterMs;
    const waitingForCapacity = isWaitingForCapacity(localSnapshot, serverDiagnostics);
    if (serverFailed) {
        return {
            code: "server-failed",
            title: "Server failed",
            detail: serverDiagnostics?.execution?.error ||
                serverDiagnostics?.transport?.lastFailure ||
                "The backend reported an agent error.",
        };
    }
    if (serverActive && !socketOpen) {
        return {
            code: "client-disconnected",
            title: "Client disconnected",
            detail: "The backend still reports the run as active, but this editor WebSocket is not open.",
        };
    }
    if (serverActive && sessionConnected && !sessionSubscribed) {
        return {
            code: "subscription-lost",
            title: "Subscription lost",
            detail: "This tab is connected, but the current session is no longer subscribed to the agent stream.",
        };
    }
    if (waitingForCapacity) {
        return {
            code: "waiting-for-capacity",
            title: "Waiting for capacity",
            detail: localSnapshot.lastStatusMessage ||
                "This agent is queued and will start automatically when a machine slot becomes available.",
        };
    }
    if (clientLagging) {
        return {
            code: "client-lagging",
            title: "Client stream lagging",
            detail: "The backend has delivered newer stream events than this terminal has applied. The terminal will reconnect and resubscribe to recover.",
        };
    }
    if (stalled) {
        return {
            code: "stream-stalled",
            title: "Stream stalled",
            detail: "The run still looks active, but no non-heartbeat status or delta progress has arrived recently.",
        };
    }
    if (serverActive && socketOpen && sessionSubscribed) {
        return {
            code: "healthy",
            title: "Stream healthy",
            detail: "The socket is open, this session is subscribed, and the backend still reports the run as active.",
        };
    }
    if (normalizeStatus(serverDiagnostics?.execution?.status) === "completed" ||
        normalizeStatus(serverDiagnostics?.execution?.status) === "cancelled") {
        return {
            code: "run-finished",
            title: "Run finished",
            detail: "The backend no longer reports an active execution for this run.",
        };
    }
    if (localSnapshot.isExecuting || localSnapshot.isSubmitting) {
        return {
            code: "waiting",
            title: "Waiting for activity",
            detail: "The client still believes the run is active, but the backend has not reported a definitive state yet.",
        };
    }
    return {
        code: "run-finished",
        title: "Run idle",
        detail: "No active execution or recent stream activity was detected.",
    };
}
export function formatSeqRanges(seqs) {
    const sorted = [...new Set(seqs)].sort((a, b) => a - b);
    const first = sorted[0];
    if (first === undefined)
        return "";
    const ranges = [];
    let start = first;
    let end = first;
    for (let i = 1; i < sorted.length; i++) {
        const value = sorted[i];
        if (value === undefined)
            continue;
        if (value === end + 1) {
            end = value;
            continue;
        }
        ranges.push(start === end ? `${start}` : `${start}-${end}`);
        start = value;
        end = value;
    }
    ranges.push(start === end ? `${start}` : `${start}-${end}`);
    return ranges.join(", ");
}
export function formatAgentDiagnosticsEvent(event) {
    const direction = "direction" in event && event.direction ? `${event.direction} ` : "";
    const eventLabel = "type" in event ? `${direction}${event.type}` : event.messageType;
    const parts = [event.timestamp, eventLabel].filter(Boolean);
    const detail = "detail" in event ? event.detail : undefined;
    if (detail) {
        parts.push(String(detail));
    }
    if (event.seq != null) {
        parts.push(`seq ${event.seq}`);
    }
    return parts.join(" | ");
}
//# sourceMappingURL=agentDiagnostics.js.map