export async function extractMessagesFromSessionUpdateStream(stream) {
    const updates = [];
    for await (const entry of stream) {
        const update = toSessionUpdate(entry);
        if (update.sessionUpdate === "user_message_chunk" ||
            update.sessionUpdate === "agent_message_chunk" ||
            update.sessionUpdate === "agent_thought_chunk") {
            updates.push(update);
        }
    }
    return updates;
}
export async function extractUsageFromSessionUpdateStream(stream) {
    const updates = [];
    for await (const entry of stream) {
        const update = toSessionUpdate(entry);
        if (update.sessionUpdate === "usage_update") {
            updates.push(update);
        }
    }
    return updates;
}
export async function extractToolCallSummariesFromSessionUpdateStream(stream) {
    const summaries = new Map();
    const startedToolCallIds = new Set();
    for await (const entry of stream) {
        const update = toSessionUpdate(entry);
        if (update.sessionUpdate === "tool_call") {
            if (startedToolCallIds.has(update.toolCallId)) {
                throw new Error(`Duplicate tool call identifier "${update.toolCallId}".`);
            }
            startedToolCallIds.add(update.toolCallId);
            const summary = {
                toolCallId: update.toolCallId,
                title: update.title,
            };
            if (update.kind !== undefined) {
                summary.kind = update.kind;
            }
            if (update.status !== undefined) {
                summary.status = update.status;
            }
            if (update.rawInput !== undefined) {
                summary.rawInput = update.rawInput;
            }
            if (update.rawOutput !== undefined) {
                summary.rawOutput = update.rawOutput;
            }
            summaries.set(update.toolCallId, summary);
            continue;
        }
        if (update.sessionUpdate === "tool_call_update") {
            const existing = summaries.get(update.toolCallId);
            const summary = existing ?? {
                toolCallId: update.toolCallId,
                title: toTitle(update.title, update.toolCallId),
            };
            if (update.title !== null && update.title !== undefined && update.title.length > 0) {
                summary.title = update.title;
            }
            if (update.kind !== null && update.kind !== undefined) {
                summary.kind = update.kind;
            }
            if (update.status !== null && update.status !== undefined) {
                summary.status = update.status;
            }
            if (update.rawInput !== undefined) {
                summary.rawInput = update.rawInput;
            }
            if (update.rawOutput !== undefined) {
                summary.rawOutput = update.rawOutput;
            }
            summaries.set(update.toolCallId, summary);
        }
    }
    return Array.from(summaries.values());
}
export function mapLegacyEventToSessionUpdates(event) {
    switch (event.event) {
        case "session_start":
            return mapSessionStart(event);
        case "agent_message":
            return mapAgentMessage(event);
        case "reasoning":
            return mapReasoning(event);
        case "tool_start":
            return mapToolStart(event);
        case "tool_complete":
            return mapToolComplete(event);
        case "usage":
            return mapUsage(event);
        default:
            return [];
    }
}
function toSessionUpdate(entry) {
    if (typeof entry.sessionUpdate === "string") {
        return entry;
    }
    if (isSessionUpdateNotification(entry)) {
        return entry.params.update;
    }
    return entry;
}
function isSessionUpdateNotification(entry) {
    return (typeof entry.jsonrpc === "string" &&
        entry.method === "session/update" &&
        typeof entry.params?.update?.sessionUpdate === "string");
}
function toTitle(value, fallback) {
    if (typeof value === "string" && value.length > 0) {
        return value;
    }
    return fallback;
}
function mapSessionStart(event) {
    const threadId = readString(event.threadId);
    if (!threadId) {
        return [];
    }
    return [{ sessionUpdate: "session_info_update", _meta: { threadId } }];
}
function mapAgentMessage(event) {
    const text = readString(event.text);
    if (!text) {
        return [];
    }
    return [{ sessionUpdate: "agent_message_chunk", content: { type: "text", text } }];
}
function mapReasoning(event) {
    const text = readString(event.text);
    if (!text) {
        return [];
    }
    return [{ sessionUpdate: "agent_thought_chunk", content: { type: "text", text } }];
}
function mapToolStart(event) {
    const toolCallId = readString(event.id) ?? readString(event.toolCallId);
    if (!toolCallId) {
        return [];
    }
    const kind = toToolKind(event.kind);
    const toolCall = {
        sessionUpdate: "tool_call",
        toolCallId,
        title: readString(event.title) ?? toolCallId,
        status: "pending",
    };
    const toolCallUpdate = {
        sessionUpdate: "tool_call_update",
        toolCallId,
        status: "in_progress",
    };
    if (kind) {
        toolCall.kind = kind;
        toolCallUpdate.kind = kind;
    }
    if (hasOwnProperty(event, "input")) {
        toolCall.rawInput = event.input;
    }
    else if (hasOwnProperty(event, "rawInput")) {
        toolCall.rawInput = event.rawInput;
    }
    return [toolCall, toolCallUpdate];
}
function mapToolComplete(event) {
    const toolCallId = readString(event.id) ?? readString(event.toolCallId);
    if (!toolCallId) {
        return [];
    }
    const status = toToolCallStatus(event.status);
    if (event.status !== undefined && status === undefined) {
        return [];
    }
    const toolCallUpdate = {
        sessionUpdate: "tool_call_update",
        toolCallId,
        status: status ?? "completed",
    };
    const kind = toToolKind(event.kind);
    if (kind) {
        toolCallUpdate.kind = kind;
    }
    if (hasOwnProperty(event, "output")) {
        toolCallUpdate.rawOutput = event.output;
    }
    else if (hasOwnProperty(event, "path")) {
        toolCallUpdate.rawOutput = event.path;
    }
    else if (hasOwnProperty(event, "rawOutput")) {
        toolCallUpdate.rawOutput = event.rawOutput;
    }
    return [toolCallUpdate];
}
function mapUsage(event) {
    const inputTokens = readTokenCount(event.inputTokens);
    const outputTokens = readTokenCount(event.outputTokens);
    const cachedTokens = readTokenCount(event.cachedTokens);
    const costUsd = readFiniteNumber(event.costUsd);
    if ((event.inputTokens !== undefined && inputTokens === undefined) ||
        (event.outputTokens !== undefined && outputTokens === undefined) ||
        (event.cachedTokens !== undefined && cachedTokens === undefined) ||
        (event.costUsd !== undefined && costUsd === undefined)) {
        return [];
    }
    const usage = {
        sessionUpdate: "usage_update",
        used: (inputTokens ?? 0) + (outputTokens ?? 0),
        size: (inputTokens ?? 0) + (outputTokens ?? 0) + (cachedTokens ?? 0),
    };
    if (costUsd !== undefined) {
        usage.cost = {
            amount: costUsd,
            currency: "USD",
        };
    }
    return [usage];
}
function toToolKind(value) {
    if (value === "exec" || value === "execute") {
        return "execute";
    }
    if (value === "read") {
        return "read";
    }
    if (value === "write" || value === "edit" || value === "delete" || value === "move") {
        return "write";
    }
    if (value === "other" ||
        value === "search" ||
        value === "think" ||
        value === "fetch" ||
        value === "switch_mode") {
        return "other";
    }
    return undefined;
}
function toToolCallStatus(value) {
    if (value === "pending" ||
        value === "in_progress" ||
        value === "completed" ||
        value === "failed" ||
        value === "cancelled") {
        return value;
    }
    return undefined;
}
function readTokenCount(value) {
    return typeof value === "number" && Number.isInteger(value) && value >= 0
        ? value
        : undefined;
}
function readFiniteNumber(value) {
    return typeof value === "number" && Number.isFinite(value) ? value : undefined;
}
function readString(value) {
    return typeof value === "string" && value.length > 0 ? value : undefined;
}
function hasOwnProperty(value, name) {
    return Object.prototype.hasOwnProperty.call(value, name);
}
