import { parseStreamErrorPayload, ShortcutXLAgentAssistantContentKind, ShortcutXLModelStreamEventKind, ShortcutXLModelStreamStopReason } from '../contracts/model-stream.js';
import { ShortcutXLAgentProviderId } from './model-registry.js';
import { isRetryableStreamError, ShortcutXLHttpStreamError } from './stream-errors.js';
const ShortcutRuntimeApi = 'shortcut-llm';
// Decode the proxy's usage shape. LangChain-style keys are primary; OpenAI-style
// fallbacks keep the parser tolerant if a future provider emits them.
function buildUsage(rawUsage) {
    const details = rawUsage.input_token_details ?? {};
    const input = rawUsage.input_tokens ??
        rawUsage.prompt_tokens ??
        0;
    const output = rawUsage.output_tokens ??
        rawUsage.completion_tokens ??
        0;
    const cacheRead = details.cache_read ??
        rawUsage.cache_read_tokens ??
        0;
    const cacheWrite = details.cache_creation ??
        rawUsage.cache_creation_tokens ??
        0;
    return {
        input,
        output,
        cacheRead,
        cacheWrite,
        totalTokens: input + output,
        cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 }
    };
}
export function createInitialAssistantMessage(model) {
    return {
        role: 'assistant',
        content: [],
        api: ShortcutRuntimeApi,
        provider: ShortcutXLAgentProviderId.Shortcut,
        model,
        usage: buildUsage({}),
        stopReason: 'stop',
        timestamp: Date.now()
    };
}
export function createAssistantMessageSnapshot(message) {
    return {
        api: message.api,
        content: message.content.map((content) => {
            switch (content.type) {
                case 'text':
                    return {
                        type: ShortcutXLAgentAssistantContentKind.Text,
                        text: content.text
                    };
                case 'thinking':
                    return {
                        type: ShortcutXLAgentAssistantContentKind.Thinking,
                        thinking: content.thinking,
                        redacted: content.redacted ?? false,
                        thinkingSignature: content.thinkingSignature ?? ''
                    };
                case 'toolCall':
                    return {
                        type: ShortcutXLAgentAssistantContentKind.ToolCall,
                        id: content.id,
                        name: content.name,
                        arguments: content.arguments
                    };
            }
        }),
        ...(message.errorDetails ? { errorDetails: message.errorDetails } : {}),
        errorMessage: message.errorMessage,
        model: message.model,
        provider: message.provider,
        role: 'assistant',
        stopReason: message.stopReason,
        timestamp: message.timestamp,
        usage: message.usage
    };
}
export function processStreamEvent(event, state, onEvent, canRetryInlineError) {
    const { partial, toolCallArguments, thinkingText } = state;
    if (event.event === 'error') {
        const details = parseStreamErrorPayload(event.payload);
        const streamError = new ShortcutXLHttpStreamError(event.payload.message, details);
        if (canRetryInlineError() && isRetryableStreamError(streamError)) {
            throw streamError;
        }
        // Terminal error. Emit Start first so consumers always see
        // Start -> ... -> Error ordering even when the very first SSE frame errors.
        state.emitStartIfNeeded();
        partial.stopReason = ShortcutXLModelStreamStopReason.Error;
        partial.errorMessage = event.payload.message;
        if (details)
            partial.errorDetails = details;
        state.markTerminal();
        onEvent({
            kind: ShortcutXLModelStreamEventKind.Error,
            error: createAssistantMessageSnapshot(partial),
            partial: createAssistantMessageSnapshot(partial),
            reason: ShortcutXLModelStreamStopReason.Error
        });
        return;
    }
    state.emitStartIfNeeded();
    switch (event.event) {
        case 'text_start':
            ensureContentSlot(partial.content, event.payload.content_index, partial);
            partial.content[event.payload.content_index] = {
                type: 'text',
                text: ''
            };
            onEvent({
                kind: ShortcutXLModelStreamEventKind.TextStart,
                contentIndex: event.payload.content_index,
                partial: createAssistantMessageSnapshot(partial)
            });
            return;
        case 'text_delta': {
            ensureContentSlot(partial.content, event.payload.content_index, partial);
            const existing = partial.content[event.payload.content_index];
            const nextText = (existing?.text ?? '') + event.payload.delta;
            partial.content[event.payload.content_index] = {
                type: 'text',
                text: nextText
            };
            onEvent({
                kind: ShortcutXLModelStreamEventKind.TextDelta,
                contentIndex: event.payload.content_index,
                delta: event.payload.delta,
                partial: createAssistantMessageSnapshot(partial)
            });
            return;
        }
        case 'thinking_start':
            ensureContentSlot(partial.content, event.payload.content_index, partial);
            thinkingText.set(event.payload.content_index, '');
            partial.content[event.payload.content_index] = {
                type: 'thinking',
                thinking: '',
                redacted: false,
                thinkingSignature: ''
            };
            onEvent({
                kind: ShortcutXLModelStreamEventKind.ThinkingStart,
                contentIndex: event.payload.content_index,
                partial: createAssistantMessageSnapshot(partial)
            });
            return;
        case 'thinking_delta': {
            const nextThinking = (thinkingText.get(event.payload.content_index) ?? '') + event.payload.delta;
            thinkingText.set(event.payload.content_index, nextThinking);
            partial.content[event.payload.content_index] = {
                type: 'thinking',
                thinking: nextThinking,
                redacted: false,
                thinkingSignature: ''
            };
            onEvent({
                kind: ShortcutXLModelStreamEventKind.ThinkingDelta,
                contentIndex: event.payload.content_index,
                delta: event.payload.delta,
                partial: createAssistantMessageSnapshot(partial)
            });
            return;
        }
        case 'thinking_end': {
            const existing = partial.content[event.payload.content_index];
            partial.content[event.payload.content_index] = {
                ...existing,
                type: 'thinking',
                thinkingSignature: event.payload.signature,
                redacted: false
            };
            onEvent({
                kind: ShortcutXLModelStreamEventKind.ThinkingEnd,
                content: existing?.thinking ?? '',
                contentIndex: event.payload.content_index,
                partial: createAssistantMessageSnapshot(partial)
            });
            return;
        }
        case 'thinking_redacted': {
            const existing = partial.content[event.payload.content_index];
            partial.content[event.payload.content_index] = {
                ...existing,
                type: 'thinking',
                redacted: true,
                thinkingSignature: event.payload.signature
            };
            onEvent({
                kind: ShortcutXLModelStreamEventKind.ThinkingRedacted,
                contentIndex: event.payload.content_index,
                partial: createAssistantMessageSnapshot(partial)
            });
            return;
        }
        case 'toolcall_start':
            partial.content[event.payload.content_index] = {
                type: 'toolCall',
                id: event.payload.id,
                name: event.payload.name,
                arguments: {}
            };
            toolCallArguments.set(event.payload.content_index, '');
            onEvent({
                kind: ShortcutXLModelStreamEventKind.ToolCallStart,
                contentIndex: event.payload.content_index,
                partial: createAssistantMessageSnapshot(partial)
            });
            return;
        case 'toolcall_delta': {
            const nextArguments = (toolCallArguments.get(event.payload.content_index) ?? '') + event.payload.delta;
            toolCallArguments.set(event.payload.content_index, nextArguments);
            onEvent({
                kind: ShortcutXLModelStreamEventKind.ToolCallDelta,
                contentIndex: event.payload.content_index,
                delta: event.payload.delta,
                partial: createAssistantMessageSnapshot(partial)
            });
            return;
        }
        case 'toolcall_end': {
            let parsedArguments = {};
            try {
                parsedArguments = JSON.parse(event.payload.arguments);
            }
            catch {
                parsedArguments = {};
            }
            partial.content[event.payload.content_index] = {
                type: 'toolCall',
                id: event.payload.id,
                name: event.payload.name,
                arguments: parsedArguments
            };
            onEvent({
                kind: ShortcutXLModelStreamEventKind.ToolCallEnd,
                contentIndex: event.payload.content_index,
                partial: createAssistantMessageSnapshot(partial),
                toolCall: {
                    type: ShortcutXLAgentAssistantContentKind.ToolCall,
                    id: event.payload.id,
                    name: event.payload.name,
                    arguments: parsedArguments
                }
            });
            return;
        }
        case 'done':
            partial.stopReason =
                event.payload.stop_reason === 'tool_use'
                    ? ShortcutXLModelStreamStopReason.ToolUse
                    : event.payload.stop_reason === 'max_tokens'
                        ? ShortcutXLModelStreamStopReason.Length
                        : ShortcutXLModelStreamStopReason.Stop;
            partial.usage = buildUsage(event.payload.usage);
            state.markTerminal();
            onEvent({
                kind: ShortcutXLModelStreamEventKind.Done,
                message: createAssistantMessageSnapshot(partial),
                partial: createAssistantMessageSnapshot(partial),
                reason: partial.stopReason
            });
            return;
    }
}
function ensureContentSlot(content, index, fallback) {
    while (content.length <= index) {
        content.push({ type: 'text', text: '' });
    }
    fallback.content = content;
}
//# sourceMappingURL=stream-message-state.js.map