/**
 * Envelope the runtime and its worker exchange. Tool-payload validation is
 * delegated to `ToolRegistry`; this file only checks the envelope shape.
 */
import { isAgentCommand, isAgentEvent } from './agent-api.js';
import { isShortcutXLModelStreamEvent } from './model-stream.js';
export const WorkerMessageKind = {
    HostToolRequest: 'hostToolRequest',
    HostToolResult: 'hostToolResult',
    ModelStreamCancel: 'modelStreamCancel',
    ModelStreamEvent: 'modelStreamEvent',
    ModelStreamRequest: 'modelStreamRequest',
    AgentCommandAck: 'runtimeCommandAck',
    AgentCommand: 'runtimeCommand',
    AgentEvent: 'runtimeEvent'
};
/** Envelope-shape guard; tool-payload validation goes through the registry. */
export function isWorkerMessage(value, registry) {
    if (!value || typeof value !== 'object')
        return false;
    const candidate = value;
    if (typeof candidate.kind !== 'string' ||
        !Object.values(WorkerMessageKind).includes(candidate.kind)) {
        return false;
    }
    switch (candidate.kind) {
        case WorkerMessageKind.AgentCommandAck: {
            const message = candidate;
            return (typeof message.commandId === 'string' &&
                typeof message.ok === 'boolean' &&
                (message.error == null || typeof message.error === 'string'));
        }
        case WorkerMessageKind.AgentCommand:
            return (typeof candidate.commandId === 'string' &&
                isAgentCommand(candidate.command) &&
                (candidate.fatalOnError == null ||
                    typeof candidate.fatalOnError === 'boolean'));
        case WorkerMessageKind.HostToolRequest:
            return registry.isHostToolRequest(candidate.request);
        case WorkerMessageKind.HostToolResult:
            return registry.isHostToolResult(candidate.result);
        case WorkerMessageKind.ModelStreamRequest:
            return isShortcutXLAiModelStreamRequest(candidate.aiRequest);
        case WorkerMessageKind.ModelStreamCancel:
            return typeof candidate.requestId === 'string';
        case WorkerMessageKind.ModelStreamEvent:
            return (typeof candidate.requestId === 'string' &&
                isShortcutXLModelStreamEvent(candidate.event));
        case WorkerMessageKind.AgentEvent:
            return isAgentEvent(candidate.event, registry);
        default:
            return false;
    }
}
function isRecord(value) {
    return value !== null && typeof value === 'object' && !Array.isArray(value);
}
function isShortcutXLAiModelStreamRequest(value) {
    if (!isRecord(value))
        return false;
    if (typeof value.requestId !== 'string')
        return false;
    const model = value.model;
    const context = value.context;
    if (!isRecord(model) || typeof model.id !== 'string')
        return false;
    if (typeof model.api !== 'string' || typeof model.provider !== 'string')
        return false;
    if (!isRecord(context) || !Array.isArray(context.messages))
        return false;
    if (context.systemPrompt !== undefined && typeof context.systemPrompt !== 'string')
        return false;
    if (context.tools !== undefined && !Array.isArray(context.tools))
        return false;
    return value.options === undefined || isRecord(value.options);
}
export function isShortcutXLAiModelInvokeRequest(value) {
    if (!isRecord(value))
        return false;
    if (typeof value.requestId !== 'string')
        return false;
    const model = value.model;
    const context = value.context;
    if (!isRecord(model) || typeof model.id !== 'string')
        return false;
    if (typeof model.api !== 'string' || typeof model.provider !== 'string')
        return false;
    if (!isRecord(context) || !Array.isArray(context.messages))
        return false;
    if (context.systemPrompt !== undefined && typeof context.systemPrompt !== 'string')
        return false;
    if (context.tools !== undefined && !Array.isArray(context.tools))
        return false;
    return value.options === undefined || isRecord(value.options);
}
//# sourceMappingURL=wire.js.map