{"version":3,"sources":["../src/index.ts","../src/kernel/event-bus.ts","../src/kernel/errors.ts","../src/kernel/logger.ts","../src/kernel/backoff.ts","../src/transport/websocket.ts","../src/transport/reconnect.ts","../src/protocol/id-resolver.ts","../src/protocol/shortcuts.ts","../src/dispatch/dispatcher.ts","../src/dispatch/proxy.ts","../src/dispatch/handlers/connection.ts","../src/dispatch/handlers/error.ts","../src/dispatch/handlers/channel.ts","../src/kernel/id.ts","../src/kernel/requester.ts","../src/domain/call-requests.ts","../src/domain/reply-stream.ts","../src/domain/call-history.ts","../src/sse/call-stream.ts","../src/domain/call.ts","../src/domain/ringing-call.ts","../src/protocol/codec.ts","../src/dispatch/handlers/lifecycle.ts","../src/dispatch/handlers/speech.ts","../src/dispatch/handlers/turn.ts","../src/dispatch/handlers/bot.ts","../src/dispatch/handlers/tool.ts","../src/dispatch/handlers/skill.ts","../src/dispatch/handlers/session.ts","../src/dispatch/handlers/chat.ts","../src/domain/wa-session.ts","../src/dispatch/handlers/whatsapp.ts","../src/dispatch/handlers/history.ts","../src/dispatch/handlers/system.ts","../src/dispatch/handlers/fallback.ts","../src/dispatch/handlers/preparing.ts","../src/dispatch/handlers/memory.ts","../src/dispatch/handlers/line.ts","../src/api/memory.ts","../src/skill.ts","../src/domain/agent.ts","../src/domain/line.ts","../src/log/types.ts","../src/log/view.ts","../src/api/http.ts","../src/api/tokens.ts","../src/observe.ts","../src/sse/format.ts","../src/sse/event-data.ts","../src/sse/stream.ts","../src/sse/parse.ts","../src/api/voices.ts","../src/api/audio-stt.ts","../src/api/audio.ts","../src/client.ts","../src/tool.ts","../src/history.ts","../src/api/phones.ts","../src/api/balance.ts","../src/api/models.ts","../src/api/knowledge.ts"],"sourcesContent":["/**\n * @pinecall/sdk — Core SDK for Pinecall Voice.\n *\n * Minimal, zero-opinion client for building voice AI integrations.\n *\n * @example\n * ```ts\n * import { Pinecall } from \"@pinecall/sdk\";\n *\n * const pc = new Pinecall({ apiKey: \"pk_...\" });\n *\n * const agent = pc.agent(\"my-agent\", {\n *   voice: \"elevenlabs:abc\",\n *   language: \"es\",\n *   phoneNumber: \"+19035551234\",\n * });\n *\n * agent.on(\"call.started\", (call) => {\n *   call.say(\"Hello! How can I help you?\");\n * });\n *\n * agent.on(\"turn.end\", (turn, call) => {\n *   call.reply(\"I heard: \" + turn.text);\n * });\n * ```\n */\n\n// Core classes\nexport { Pinecall, PinecallError, AgentConflictError, ServerAtCapacityError } from \"./client.js\";\nexport type { PinecallOptions, PinecallEvents } from \"./client.js\";\nexport type { StreamOptions } from \"./sse/stream.js\";\n\n// Tool definition\nexport { tool } from \"./tool.js\";\nexport type { Tool, ToolConfig } from \"./tool.js\";\n\n// Skill definition — bundles of prompt + tools + knowledge base (progressive disclosure)\nexport { skill } from \"./skill.js\";\nexport type { Skill, SkillConfig, SkillActivation } from \"./skill.js\";\n\n// History persistence\nexport { JsonFileHistory } from \"./history.js\";\nexport type { HistoryStore, ConversationRecord } from \"./history.js\";\nexport type { MemoryConfig } from \"./config/agent.js\";\nexport type { MemoryOp, MemoryOpsEvent, AgentMemory, MemoryHit, MemoryContact, MemoryFact } from \"./domain/agent.js\";\n\n// WhatsApp session\nexport { WhatsAppSession } from \"./domain/wa-session.js\";\n\nexport { Agent } from \"./domain/agent.js\";\nexport type {\n    AgentEvents,\n} from \"./domain/agent.js\";\n\nexport type {\n    AgentConfig,\n    PhoneNumberConfig,\n    ChannelConfig,\n    WhatsAppChannelConfig,\n    VoiceShortcut,\n    STTShortcut,\n    InterruptionShortcut,\n} from \"./config/agent.js\";\n\nexport { Call } from \"./domain/call.js\";\nexport type { CallEvents, CallInit, SayResult, LineTranscriptEntry, ReplyOptions, ForwardOptions, CallLogOptions, CallLogRejectedEvent, SSEResponse, StreamSSEOptions } from \"./domain/call.js\";\n\n// Phone lines — a number you program, with no model behind it.\nexport { PhoneLine, LineCall, DEFAULT_EXTENSION_WINDOW_MS } from \"./domain/line.js\";\nexport type {\n    LineOptions,\n    PhoneLineEvents,\n    ExtensionTable,\n    ListenOptions,\n    ListenResult,\n    SayOptions,\n    RouteOptions,\n    RouteResult,\n    RouteFailureReason,\n} from \"./domain/line.js\";\n\nexport { RingingCall } from \"./domain/ringing-call.js\";\n\n// Re-export Turn from domain\nexport type { Turn } from \"./domain/turn.js\";\n\nexport { ReplyStream } from \"./domain/reply-stream.js\";\nexport type { ReplyStreamOptions } from \"./domain/reply-stream.js\";\n\n// Config types\nexport type {\n    SessionConfig,\n    STTConfig,\n    DeepgramSTTConfig,\n    FluxSTTConfig,\n    GladiaSTTConfig,\n    TranscribeSTTConfig,\n    SonioxSTTConfig,\n    TTSConfig,\n    ElevenLabsTTSConfig,\n    CartesiaTTSConfig,\n    PollyTTSConfig,\n    InterruptionConfig,\n    SpeakerFilterConfig,\n    AnalysisConfig,\n} from \"./config/session.js\";\n\n// Event types\nexport type {\n    ServerEvent,\n    CallStartedEvent,\n    CallEndedEvent,\n    SpeechStartedEvent,\n    SpeechEndedEvent,\n    UserSpeakingEvent,\n    UserMessageEvent,\n    EagerTurnEvent,\n    TurnPauseEvent,\n    TurnEndEvent,\n    TurnResumedEvent,\n    TurnContinuedEvent,\n    BotSpeakingEvent,\n    BotWordEvent,\n    BotFinishedEvent,\n    BotInterruptedEvent,\n    BargeInEvent,\n    MessageConfirmedEvent,\n    ReplyRejectedEvent,\n    AudioMetricsEvent,\n    RegisteredEvent,\n    ErrorEvent,\n    PongEvent,\n    CallHeldEvent,\n    CallUnheldEvent,\n    CallMutedEvent,\n    CallUnmutedEvent,\n    SessionTimeoutEvent,\n    ToolCallEvent,\n    ToolCallItem,\n    CallRingingEvent,\n    CallRejectedEvent,\n} from \"./protocol/events.js\";\n\n// Command types\nexport type {\n    ClientCommand,\n    RegisterCommand,\n    BotReplyCommand,\n    BotReplyStreamCommand,\n    BotCancelCommand,\n    BotClearCommand,\n    CallHangupCommand,\n    CallDialCommand,\n    CallForwardCommand,\n    CallDtmfCommand,\n    UpdateConfigCommand,\n    UpdateSessionConfigCommand,\n    AddPhoneCommand,\n    RemovePhoneCommand,\n    PingCommand,\n    CallHoldCommand,\n    CallUnholdCommand,\n    CallMuteCommand,\n    CallUnmuteCommand,\n    ConnectCommand,\n    AgentCreateCommand,\n    AgentResumeCommand,\n    AgentConfigureCommand,\n    ChannelAddCommand,\n    ChannelConfigureCommand,\n    ChannelRemoveCommand,\n    SessionConfigureCommand,\n} from \"./protocol/commands.js\";\n\n// Utilities\nexport { generateId } from \"./kernel/id.js\";\nexport { Reconnector } from \"./transport/reconnect.js\";\nexport type { ReconnectOptions } from \"./transport/reconnect.js\";\n\n// REST API helpers\nexport { fetchVoices } from \"./api/voices.js\";\nexport type { Voice, VoiceLanguage, FetchVoicesOptions } from \"./api/voices.js\";\n\nexport { speech, fetchAudioVoices, transcribe, transcribeStream, AudioApiError } from \"./api/audio.js\";\nexport type {\n    SpeechOptions,\n    SpeechResult,\n    SpeechWord,\n    SpeechDone,\n    SpeechFormat,\n    SpeechApiOptions,\n    FetchAudioVoicesOptions,\n    TranscriptionModel,\n    TranscribeInput,\n    TranscribeOptions,\n    TranscribeApiOptions,\n    TranscriptWord,\n    TranscriptSegment,\n    Transcription,\n    StreamModel,\n    TranscribeStreamOptions,\n    StreamFinal,\n    StreamReady,\n    StreamDone,\n    TranscribeStreamEvents,\n    TranscribeStreamItem,\n    TranscribeStream,\n} from \"./api/audio.js\";\nexport type { AudioNamespace } from \"./client.js\";\n\nexport { fetchPhones } from \"./api/phones.js\";\nexport type { Phone as PhoneInfo, FetchPhonesOptions } from \"./api/phones.js\";\n\nexport { createToken } from \"./api/tokens.js\";\nexport type {\n    WebRTCToken,\n    TokenResponse,\n    FetchWebRTCTokenOptions,\n    CreateTokenOptions,\n    TokenScope,\n    TokenScopeOptions,\n} from \"./api/tokens.js\";\n\n// Call Log observation — SSE reader of the log (also `pc.observe`)\nexport { observe, sseDecoder, observeBackoffDelay } from \"./observe.js\";\nexport type {\n    ObserveOptions,\n    Observation,\n    ObserveFinishInfo,\n    ObserveError,\n    ObserveFetch,\n    ObserveResponseLike,\n    IdleReconnect,\n    SseEvent,\n} from \"./observe.js\";\n\nexport { fetchTwilioBalance } from \"./api/balance.js\";\nexport type {\n    TwilioBalance,\n    FetchTwilioBalanceOptions,\n} from \"./api/balance.js\";\n\nexport { fetchModelAccess, hasModelAccess, fetchModelCatalog } from \"./api/models.js\";\nexport type {\n    ModelAccess,\n    ModelAccessReason,\n    FetchModelAccessOptions,\n    ListModelAccessOptions,\n} from \"./api/models.js\";\n\nexport {\n    listKnowledgeBases,\n    createKnowledgeBase,\n    getKnowledgeBase,\n    deleteKnowledgeBase,\n    reindexKnowledge,\n    pushDoc,\n    pushDocs,\n    getDoc,\n    deleteDoc,\n    queryKnowledge,\n    KnowledgeApiError,\n    DEFAULT_PLAYGROUND_URL,\n} from \"./api/knowledge.js\";\nexport type {\n    KnowledgeBase,\n    KnowledgeDoc,\n    KnowledgeDocWithText,\n    KnowledgeDocInput,\n    KnowledgeHit,\n    KnowledgeApiOptions,\n    PushResult,\n} from \"./api/knowledge.js\";\n","/**\n * TypedEventBus — zero-dependency typed event emitter.\n *\n * Improvements over the previous TypedEmitter:\n *   1. Handler errors routed to onError callback (not console.error).\n *   2. once-handlers removed BEFORE invocation (prevents re-entry bugs).\n *   3. emit is protected (subclass-only).\n *   4. listenerCount() added.\n */\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type EventMap = { [key: string]: (...args: any[]) => void };\n\nexport interface EventBusOptions {\n    /** Called when a handler throws. If unset, error surfaces via queueMicrotask. */\n    onError?: (err: unknown, event: string, args: unknown[]) => void;\n}\n\nexport class TypedEventBus<E extends EventMap> {\n    #handlers = new Map<keyof E, Set<E[keyof E]>>();\n    #onceSet = new WeakSet<Function>();\n    #onError: ((err: unknown, event: string, args: unknown[]) => void) | undefined;\n\n    constructor(opts?: EventBusOptions) {\n        this.#onError = opts?.onError;\n    }\n\n    on<K extends keyof E>(event: K, handler: E[K]): this {\n        let set = this.#handlers.get(event);\n        if (!set) {\n            set = new Set();\n            this.#handlers.set(event, set);\n        }\n        set.add(handler);\n        return this;\n    }\n\n    off<K extends keyof E>(event: K, handler: E[K]): this {\n        this.#handlers.get(event)?.delete(handler);\n        return this;\n    }\n\n    once<K extends keyof E>(event: K, handler: E[K]): this {\n        const wrapped = ((...args: Parameters<E[K]>) => {\n            // Remove BEFORE invocation — prevents re-entry from re-emitting\n            this.off(event, wrapped as E[K]);\n            (handler as (...a: unknown[]) => void)(...args);\n        }) as E[K];\n        this.#onceSet.add(wrapped);\n        return this.on(event, wrapped);\n    }\n\n    protected emit<K extends keyof E>(event: K, ...args: Parameters<E[K]>): void {\n        const set = this.#handlers.get(event);\n        if (!set) return;\n        for (const handler of set) {\n            try {\n                (handler as (...a: unknown[]) => void)(...args);\n            } catch (err) {\n                if (this.#onError) {\n                    this.#onError(err, String(event), args as unknown[]);\n                } else {\n                    // Surface via unhandled rejection — never swallow silently\n                    queueMicrotask(() => { throw err; });\n                }\n            }\n        }\n    }\n\n    /**\n     * Like `emit`, but KEEPS what each handler returned.\n     *\n     * Exists for `call.preparing`: the server holds the turn open while the app\n     * refreshes its per-turn variables, so the SDK has to know when the app is\n     * actually done — which for an async handler means awaiting the promise it\n     * returned. Plain `emit` throws that value away, and the SDK could only\n     * guess, which is exactly how the barrier used to be lost.\n     */\n    protected emitCollect<K extends keyof E>(event: K, ...args: Parameters<E[K]>): unknown[] {\n        const set = this.#handlers.get(event);\n        if (!set) return [];\n        const results: unknown[] = [];\n        for (const handler of set) {\n            try {\n                results.push((handler as (...a: unknown[]) => unknown)(...args));\n            } catch (err) {\n                if (this.#onError) {\n                    this.#onError(err, String(event), args as unknown[]);\n                } else {\n                    queueMicrotask(() => { throw err; });\n                }\n            }\n        }\n        return results;\n    }\n\n    listenerCount<K extends keyof E>(event: K): number {\n        return this.#handlers.get(event)?.size ?? 0;\n    }\n\n    removeAllListeners(event?: keyof E): void {\n        if (event) {\n            this.#handlers.delete(event);\n        } else {\n            this.#handlers.clear();\n        }\n    }\n}\n","/**\n * Base error type.\n *\n * Lives in kernel/ rather than client.ts so the domain layer (Call, Agent) can\n * throw it without importing the client — client.ts already imports the domain,\n * and the cycle would bite at module-evaluation time.\n *\n * `client.ts` re-exports it, so `import { PinecallError } from \"@pinecall/sdk\"`\n * keeps working exactly as before.\n */\nexport class PinecallError extends Error {\n    constructor(message: string, public code?: string) {\n        super(message);\n        this.name = \"PinecallError\";\n    }\n}\n\n/**\n * Terminal registration conflict — the agent id is held by another LIVE\n * process and retrying cannot change that.\n *\n * Emitted on the client's `error` event (so it is catchable programmatically,\n * not just a log line) when either:\n *   - the server answered `AGENT_CONFLICT_FATAL` (its liveness probe confirmed\n *     the holder alive), or\n *   - the retry budget (2× the server's stale-registration window) ran out.\n *\n * Lives here, not in client.ts, so a dispatch handler can construct one\n * without importing the orchestrator that dispatches it. `client.ts` and\n * `index.ts` re-export it, so both existing import paths keep working.\n */\nexport class AgentConflictError extends PinecallError {\n    constructor(\n        message: string,\n        /** The agent id that could not be registered. */\n        public readonly agentId: string,\n        /** How the terminal state was reached. */\n        public readonly reason: \"server_fatal\" | \"retry_budget_exhausted\",\n    ) {\n        super(message, \"AGENT_CONFLICT_FATAL\");\n        this.name = \"AgentConflictError\";\n    }\n}\n\n/**\n * The server ran out of client slots — it refused to register this agent.\n *\n * A distinct type because it is a distinct fact with a distinct remedy. The\n * server used to report the refusal as a nondescript REGISTRATION_ERROR, and\n * the token-mint endpoints — which only see that the agent never appeared —\n * answered `Agent 'x' is not online`. Nothing about the agent is wrong: the\n * SERVER is full. Surface the server's own words verbatim.\n */\nexport class ServerAtCapacityError extends PinecallError {\n    constructor(\n        message: string,\n        /** The agent id that could not be registered. */\n        public readonly agentId: string,\n        /** Client slots in use, as reported by the server (if provided). */\n        public readonly used?: number,\n        /** The server's max_clients ceiling (if provided). */\n        public readonly limit?: number,\n    ) {\n        super(message, \"SERVER_AT_CAPACITY\");\n        this.name = \"ServerAtCapacityError\";\n    }\n}\n","/**\n * Logger — structured logging interface.\n *\n * Pinecall accepts an optional logger in its options; defaults to noopLogger.\n * fileLogger writes to PINECALL_LOG (port of old Pinecall._log).\n */\n\nexport interface Logger {\n    debug(msg: string, meta?: Record<string, unknown>): void;\n    info(msg: string, meta?: Record<string, unknown>): void;\n    warn(msg: string, meta?: Record<string, unknown>): void;\n    error(msg: string, meta?: Record<string, unknown>): void;\n}\n\nconst noop = () => {};\n\nexport const noopLogger: Logger = {\n    debug: noop,\n    info: noop,\n    warn: noop,\n    error: noop,\n};\n\n/**\n * File logger — appends JSON lines to a file.\n * Used when PINECALL_LOG env var is set.\n */\nexport function fileLogger(path: string): Logger {\n    // Lazy import to stay browser-safe\n    let appendFileSync: typeof import(\"node:fs\").appendFileSync | null = null;\n    try {\n        // eslint-disable-next-line @typescript-eslint/no-require-imports\n        appendFileSync = require(\"node:fs\").appendFileSync;\n    } catch {\n        // Browser context — fall back to noop\n        return noopLogger;\n    }\n\n    const write = (level: string, msg: string, meta?: Record<string, unknown>) => {\n        const ts = new Date().toISOString();\n        const line = meta\n            ? `${ts} [${level}] ${msg} ${JSON.stringify(meta)}\\n`\n            : `${ts} [${level}] ${msg}\\n`;\n        try { appendFileSync!(path, line); } catch { /* ignore */ }\n    };\n\n    return {\n        debug: (msg, meta) => write(\"DEBUG\", msg, meta),\n        info: (msg, meta) => write(\"INFO\", msg, meta),\n        warn: (msg, meta) => write(\"WARN\", msg, meta),\n        error: (msg, meta) => write(\"ERROR\", msg, meta),\n    };\n}\n","/**\n * Registration-retry backoff — pure delay math for AGENT_CONFLICT retries.\n *\n * Two regimes, chosen by what the server told us:\n *   - holder ALIVE (a real second process owns the name): server-guided\n *     `retryAfterS` (escalating server-side) or local exponential growth,\n *     capped at 10 minutes — never a constant-cadence storm for hours.\n *   - holder unknown/dead (old server, or a stale registration about to be\n *     freed): legacy 5s → 60s exponential, so recovery stays fast.\n * Jitter (±15%) keeps N processes fighting for one name from syncing up.\n */\n\nexport const RETRY_CAP_HELD_MS = 600_000; // name actively held elsewhere\nexport const RETRY_CAP_STALE_MS = 60_000; // stale/unknown — server frees it soon\n\n/**\n * The server's stale-registration window (`LIVENESS_WINDOW_SECS` in\n * sdk-server `session/manager.py`): a registration whose socket has gone\n * silent for this long fails the liveness probe and is displaced.\n */\nexport const SERVER_LIVENESS_WINDOW_MS = 45_000;\n\n/**\n * TOTAL time a plain (non-fatal) AGENT_CONFLICT may be retried — 2× the\n * server's liveness window, i.e. long enough for a stale registration to be\n * reaped twice over. Past it, the name is held by something the server keeps\n * calling alive, and retrying forever is a storm, not persistence.\n * NOT a per-attempt cap: it bounds the whole episode.\n */\nexport const CONFLICT_RETRY_BUDGET_MS = 2 * SERVER_LIVENESS_WINDOW_MS;\n\n/** Mutable per-agent conflict-retry state (owned by the client). */\nexport interface ConflictRetryState {\n    attempt: number;\n    holderAlive: boolean;\n    /** Epoch ms the current conflict episode began — the budget clock. */\n    startedAt: number;\n}\n\n/**\n * Decide the next move for a conflicted registration: retry after a delay, or\n * stop for good. Pure — the client only owns the timer.\n *\n * - `holderAlive: false` (the server says the holder died) starts a FRESH\n *   episode: fast retries again, budget clock restarted.\n * - the delay never overshoots what is left of the budget, so the last\n *   attempt lands exactly at CONFLICT_RETRY_BUDGET_MS.\n * - once the budget is spent, the answer is terminal.\n */\nexport function planConflictRetry(\n    state: ConflictRetryState,\n    hint: { retryAfterS?: number; holderAlive?: boolean } | undefined,\n    now: number,\n    random: () => number = Math.random,\n): { action: \"retry\"; delayMs: number } | { action: \"terminal\" } {\n    if (hint?.holderAlive === true) state.holderAlive = true;\n    if (hint?.holderAlive === false) {\n        state.holderAlive = false;\n        state.attempt = 0;\n        state.startedAt = now;\n    }\n\n    const remaining = CONFLICT_RETRY_BUDGET_MS - (now - state.startedAt);\n    if (remaining <= 0) return { action: \"terminal\" };\n\n    const delayMs = Math.min(\n        computeRegisterRetryDelay(state.attempt, state.holderAlive, hint?.retryAfterS, random),\n        remaining,\n    );\n    state.attempt++;\n    return { action: \"retry\", delayMs };\n}\n\nexport function computeRegisterRetryDelay(\n    attempt: number,\n    holderAlive: boolean,\n    retryAfterS?: number,\n    random: () => number = Math.random,\n): number {\n    const cap = holderAlive ? RETRY_CAP_HELD_MS : RETRY_CAP_STALE_MS;\n    const base = retryAfterS != null\n        ? Math.min(retryAfterS * 1_000, cap)\n        : Math.min(5_000 * 2 ** attempt, cap);\n    return Math.round(base * (0.85 + random() * 0.3));\n}\n","/**\n * WebSocketTransport — production Transport adapter.\n *\n * Wraps Node's `ws` (or browser `WebSocket` if `globalThis.WebSocket` exists).\n * Owns: connect timeout, stale-socket guard.\n */\n\nimport type { Transport } from \"./transport.js\";\n\n// Node.js < 22 lacks global WebSocket. Polyfill from 'ws' package.\nlet WS: typeof WebSocket | undefined = globalThis.WebSocket;\n\nasync function getWS(): Promise<typeof WebSocket> {\n    if (WS) return WS;\n    try {\n        const ws = await import(\"ws\");\n        WS = ws.default as unknown as typeof WebSocket;\n        return WS;\n    } catch {\n        throw new Error(\n            \"WebSocket is not available. Install the 'ws' package for Node.js: npm i ws\",\n        );\n    }\n}\n\nexport interface WebSocketTransportOptions {\n    url: string;\n    /** Connect timeout in ms. Default: 10000. */\n    connectTimeout?: number;\n}\n\nexport class WebSocketTransport implements Transport {\n    readonly #url: string;\n    readonly #connectTimeout: number;\n\n    #ws: WebSocket | null = null;\n    #messageHandler: ((data: Record<string, unknown>) => void) | null = null;\n    #closeHandler: ((reason: string) => void) | null = null;\n    #errorHandler: ((err: Error) => void) | null = null;\n\n    constructor(opts: WebSocketTransportOptions) {\n        this.#url = opts.url;\n        this.#connectTimeout = opts.connectTimeout ?? 10000;\n    }\n\n    get isOpen(): boolean {\n        return this.#ws?.readyState === 1; /* WebSocket.OPEN */\n    }\n\n    async open(): Promise<void> {\n        const WSConstructor = await getWS();\n        return new Promise<void>((resolve, reject) => {\n            try {\n                this.#ws = new WSConstructor(this.#url) as WebSocket;\n            } catch (err) {\n                reject(new Error(`Failed to create WebSocket: ${err}`));\n                return;\n            }\n\n            const timeout = setTimeout(() => {\n                reject(new Error(`Connection timeout: could not reach ${this.#url}`));\n                try { this.#ws?.close(); } catch { /* ignore */ }\n            }, this.#connectTimeout);\n\n            this.#ws.onopen = () => {\n                clearTimeout(timeout);\n                resolve();\n            };\n\n            // Capture reference for stale-socket guard\n            const thisSocket = this.#ws;\n\n            this.#ws.onmessage = (evt: MessageEvent) => {\n                try {\n                    const data = JSON.parse(\n                        typeof evt.data === \"string\" ? evt.data : \"\",\n                    ) as Record<string, unknown>;\n                    this.#messageHandler?.(data);\n                } catch {\n                    // Ignore non-JSON messages\n                }\n            };\n\n            this.#ws.onclose = (evt: CloseEvent) => {\n                clearTimeout(timeout);\n                // Stale-socket guard: ignore onclose from a replaced socket\n                if (thisSocket !== this.#ws) return;\n                this.#closeHandler?.(evt.reason || \"connection_lost\");\n            };\n\n            this.#ws.onerror = () => {\n                // onclose will fire after this — no action needed here\n            };\n        });\n    }\n\n    async close(code = 1000, reason = \"client_disconnect\"): Promise<void> {\n        if (this.#ws) {\n            try { this.#ws.close(code, reason); } catch { /* ignore */ }\n            this.#ws = null;\n        }\n    }\n\n    send(data: Record<string, unknown>): void {\n        if (this.#ws && this.#ws.readyState === 1 /* WebSocket.OPEN */) {\n            this.#ws.send(JSON.stringify(data));\n        }\n    }\n\n    onMessage(handler: (data: Record<string, unknown>) => void): void {\n        this.#messageHandler = handler;\n    }\n\n    onClose(handler: (reason: string) => void): void {\n        this.#closeHandler = handler;\n    }\n\n    onError(handler: (err: Error) => void): void {\n        this.#errorHandler = handler;\n    }\n}\n","/**\n * Reconnector — exponential backoff reconnection logic.\n *\n * Port of src.bkp/utils/reconnect.ts with maxAttempts addition.\n * When maxAttempts is exceeded, wait() rejects.\n */\n\nexport interface ReconnectOptions {\n    /** Initial delay in ms (default: 1000) */\n    initialDelay?: number;\n    /** Maximum delay in ms (default: 30000) */\n    maxDelay?: number;\n    /** Multiplier per attempt (default: 2) */\n    factor?: number;\n    /** Add random jitter 0-25% (default: true) */\n    jitter?: boolean;\n    /** Maximum attempts before giving up (default: Infinity) */\n    maxAttempts?: number;\n}\n\nconst DEFAULTS: Required<ReconnectOptions> = {\n    initialDelay: 1000,\n    maxDelay: 30000,\n    factor: 2,\n    jitter: true,\n    maxAttempts: Infinity,\n};\n\nexport class Reconnector {\n    #opts: Required<ReconnectOptions>;\n    #attempt = 0;\n    #timer: ReturnType<typeof setTimeout> | null = null;\n\n    constructor(opts?: ReconnectOptions) {\n        this.#opts = { ...DEFAULTS, ...opts };\n    }\n\n    get attempt(): number {\n        return this.#attempt;\n    }\n\n    /** Calculate delay for the next attempt. */\n    nextDelay(): number {\n        const base = Math.min(\n            this.#opts.initialDelay * Math.pow(this.#opts.factor, this.#attempt),\n            this.#opts.maxDelay,\n        );\n        const jitter = this.#opts.jitter ? base * Math.random() * 0.25 : 0;\n        this.#attempt++;\n        return Math.round(base + jitter);\n    }\n\n    /** Wait for the next backoff delay. Rejects if maxAttempts exceeded. */\n    async wait(): Promise<number> {\n        if (this.#attempt >= this.#opts.maxAttempts) {\n            throw new Error(`Reconnect failed after ${this.#opts.maxAttempts} attempts`);\n        }\n        const delay = this.nextDelay();\n        await new Promise<void>((resolve) => {\n            this.#timer = setTimeout(resolve, delay);\n        });\n        return delay;\n    }\n\n    /** Reset attempt counter (call on successful connection). */\n    reset(): void {\n        this.#attempt = 0;\n        if (this.#timer) {\n            clearTimeout(this.#timer);\n            this.#timer = null;\n        }\n    }\n\n    /** Cancel any pending wait. */\n    cancel(): void {\n        if (this.#timer) {\n            clearTimeout(this.#timer);\n            this.#timer = null;\n        }\n    }\n}\n","/**\n * Agent ID resolver — maps server-provided agent_id to a local agent slug.\n *\n * The server sends agent_id in two shapes:\n *   1. Plain slug:         \"florencia\"\n *   2. Compound key:       \"org_id:florencia\"\n *\n * Since agent IDs are now fully user-controlled (no magic prefixing),\n * resolution is straightforward.\n */\n\nexport interface AgentIdResolver {\n    resolve(rawId: string, localAgents: ReadonlySet<string>): string | null;\n}\n\n/**\n * Slugify a value the SAME way the server does (lowercase, underscores/spaces\n * → hyphens, strip non-alphanumeric, collapse/trim hyphens). Used to match a\n * server-provided slug back to a user-supplied agent id like \"futbolAgent\" or\n * \"My Agent\", which the server stores as \"futbolagent\" / \"my-agent\".\n */\nfunction slugify(value: string): string {\n    return value\n        .trim()\n        .toLowerCase()\n        .replace(/[_\\s]+/g, \"-\")     // underscores + whitespace → hyphen\n        .replace(/[^a-z0-9-]/g, \"\")  // drop everything else\n        .replace(/-+/g, \"-\")          // collapse repeats\n        .replace(/^-+|-+$/g, \"\");     // trim leading/trailing\n}\n\nexport class StandardAgentIdResolver implements AgentIdResolver {\n    resolve(rawId: string, localAgents: ReadonlySet<string>): string | null {\n        // 1. Direct match\n        if (localAgents.has(rawId)) return rawId;\n\n        // 2. Strip compound key prefix (org_id:slug)\n        let candidate = rawId;\n        if (rawId.includes(\":\")) {\n            candidate = rawId.split(\":\").pop()!;\n            if (localAgents.has(candidate)) return candidate;\n        }\n\n        // 3. Slug match — the server lowercases + hyphenates agent ids, so a\n        //    local \"futbolAgent\" / \"My Agent\" must be compared by its slug.\n        //    (toLowerCase() alone misses spaces/underscores; matching against\n        //    the local set's slugs is what makes camelCase ids work.)\n        const target = slugify(candidate);\n        for (const local of localAgents) {\n            if (local === candidate || slugify(local) === target) return local;\n        }\n\n        return null;\n    }\n}\n","/**\n * Protocol utilities — serialization helpers for the Pinecall WebSocket protocol.\n *\n * Pure functions: buildShortcutPayload, normalizePreparing, expandSTT.\n * Ported from src.bkp/utils/protocol.ts unchanged.\n *\n * This is the SECOND wire boundary of the SDK (codec.ts is the other): the one\n * place that knows the server's snake_case names for the agent config. It is\n * table-driven on purpose — one ordered list of fields, read once — so that\n * \"which SDK key becomes which wire key\" is data you can read in ten seconds\n * instead of a hundred lines of branching, and so the key ORDER on the wire is\n * a property of the table rather than of statement order.\n */\n\nimport type { ShortcutInput, WireAgentConfig, WirePreparing } from \"./wire-config.js\";\n\nexport type { ShortcutInput, WireAgentConfig, WirePreparing } from \"./wire-config.js\";\n\n// ─── The table ───────────────────────────────────────────────────────────\n\n/** One field: reads the SDK config, writes at most one wire key. */\ntype FieldEncoder = (opts: ShortcutInput, out: WireAgentConfig) => void;\n\n/**\n * Declare a wire field: its key, and how to read it off the SDK config.\n *\n * `read` returning `undefined` means \"the user did not set it\" — the key is\n * then OMITTED, never sent as null: `agent.configure` is a patch, and a null\n * would ask the server to erase a setting the user never mentioned.\n *\n * First writer wins, which is how two spellings (`sessionLimits` and an\n * already snake_cased `session_limits`) can target the same wire key.\n */\nfunction field<K extends keyof WireAgentConfig>(\n    key: K,\n    read: (opts: ShortcutInput) => WireAgentConfig[K] | undefined,\n): FieldEncoder {\n    return (opts, out) => {\n        if (out[key] !== undefined) return;\n        const value = read(opts);\n        if (value !== undefined) out[key] = value;\n    };\n}\n\n/**\n * SDK key → wire key, in the order the server has always received them.\n *\n * The order is not cosmetic: it is the byte order of every registration frame\n * ever sent, and tests lock it.\n */\nconst WIRE_FIELDS: readonly FieldEncoder[] = [\n    field(\"voice\", (o) => o.voice),\n    field(\"language\", (o) => o.language),\n    field(\"flash\", (o) => o.flash),\n    field(\"stt\", (o) => (o.stt === undefined ? undefined : expandSTT(o.stt))),\n    field(\"interruption\", (o) => o.interruption),\n    field(\"llm\", (o) => o.llm),\n    field(\"prompt\", (o) => o.prompt),\n    // Default prompt {{vars}} seeded server-side at registration, so they resolve\n    // on the FIRST turn (chat especially) without the per-call setPromptVars round-trip.\n    field(\"vars\", (o) => o.promptVars),\n    // THE greeting travels on the wire: the SERVER owns delivery on every\n    // channel (voice speaks it via _send_greeting; chat emits it as the first\n    // bot message when `greetingInChat` is set). client.ts strips function\n    // greetings before this runs — they cannot serialize and keep the legacy\n    // client-side call.say. An object greeting sends its text; per-call\n    // addToHistory is not a wire concept (the server always records it).\n    field(\"greeting\", (o) => {\n        // Three shapes reach the wire: a string; `{ text, addToHistory? }`\n        // (its text — the server always records a greeting); and a\n        // per-language map `{ en: \"…\", es: \"…\" }`, which travels whole so the\n        // server can pick by the SESSION's language.\n        const g = o.greeting;\n        if (g === null || g === undefined || typeof g !== \"object\") return g;\n        return typeof g.text === \"string\" ? g.text : g;\n    }),\n    field(\"greetingInChat\", (o) => o.greetingInChat),\n    // Long-term memory declaration — the server owns extraction and storage.\n    field(\"memory\", (o) => o.memory),\n    // IANA timezone → server resolves built-in {{date}}/{{time}}/{{day}}/{{date_block}}\n    // in this zone (all transports), so an agent \"in Madrid\" reports the right hour.\n    field(\"timezone\", (o) => o.timezone),\n    // Pre-turn barrier opt-in. camelCase timeoutMs → snake_case on the wire,\n    // like every other config key; a server that predates it ignores the field\n    // and keeps its legacy 150ms wait.\n    field(\"preparing\", (o) => normalizePreparing(o.preparing)),\n    field(\"raw_prompt\", (o) => o.rawPrompt),\n    // Tools and skills know their own wire shape. The fallback keeps a plain\n    // already-wire-shaped object working — JS callers and tests pass those.\n    field(\"tools\", (o) => o.tools?.map((t) => (t._toWire ? t._toWire() : t))),\n    field(\"skills\", (o) => o.skills?.map((s) => (s._toWire ? s._toWire() : s))),\n    field(\"session_limits\", (o) => o.sessionLimits),\n    field(\"session_limits\", (o) => o.session_limits),\n    field(\"config\", (o) => o.config),\n    field(\"knowledge_base\", (o) => o.knowledgeBase),\n    field(\"mode\", (o) => o.mode),\n    field(\"media\", (o) => o.media),\n];\n\n// ─── The encoder ─────────────────────────────────────────────────────────\n\n/**\n * Convert SDK shortcut fields to protocol payload.\n *\n * Transforms camelCase SDK config into the snake_case wire format:\n *   { promptVars: { name: \"Ana\" }, rawPrompt: true }\n *   → { vars: { name: \"Ana\" }, raw_prompt: true }\n */\nexport function buildShortcutPayload(opts?: ShortcutInput): WireAgentConfig {\n    if (!opts) return {};\n    const payload: WireAgentConfig = {};\n    for (const encode of WIRE_FIELDS) encode(opts, payload);\n    return payload;\n}\n\n// ─── Transforms ──────────────────────────────────────────────────────────\n\n/** Normalize the `preparing` shortcut to its wire shape. */\nexport function normalizePreparing(\n    value: boolean | { enabled?: boolean; timeoutMs?: number } | undefined,\n): boolean | WirePreparing | undefined {\n    if (typeof value !== \"object\" || value === null) return value;\n    const out: WirePreparing = {};\n    if (value.enabled !== undefined) out.enabled = value.enabled;\n    if (value.timeoutMs !== undefined) out.timeout_ms = value.timeoutMs;\n    return out;\n}\n\n/**\n * Expand STT string shortcut → object.\n *\n *   \"deepgram\"            → \"deepgram\"              (simple provider name)\n *   \"deepgram:nova-3\"     → { provider, model }\n *   \"deepgram:nova-3:es\"  → { provider, model, language }\n */\nexport function expandSTT(stt: string | Record<string, unknown>): string | Record<string, unknown> {\n    if (typeof stt !== \"string\") return stt;\n    const parts = stt.split(\":\");\n    if (parts.length === 1) return stt;\n    const obj: Record<string, string> = { provider: parts[0] };\n    if (parts[1]) obj.model = parts[1];\n    if (parts[2]) obj.language = parts[2];\n    return obj;\n}\n","/**\n * Dispatcher — ordered handler registry, first-match wins.\n *\n * Built once at Pinecall construction time with all handlers.\n * For each incoming WireEvent, the dispatcher iterates handlers\n * and stops at the first one that returns true.\n */\n\nimport type { EventHandler, DispatchContext } from \"./handler.js\";\nimport type { WireEvent } from \"../protocol/wire.js\";\n\nexport class Dispatcher {\n    readonly #handlers: EventHandler[];\n    readonly #eventMap: Map<string, EventHandler[]>;\n\n    constructor(handlers: EventHandler[]) {\n        this.#handlers = handlers;\n        // Pre-build a lookup map: event name → handlers that care about it\n        this.#eventMap = new Map();\n        for (const handler of handlers) {\n            for (const event of handler.events) {\n                let list = this.#eventMap.get(event);\n                if (!list) {\n                    list = [];\n                    this.#eventMap.set(event, list);\n                }\n                list.push(handler);\n            }\n        }\n    }\n\n    dispatch(wire: WireEvent, ctx: DispatchContext): boolean {\n        const eventName = wire.event;\n        const handlers = this.#eventMap.get(eventName);\n\n        if (handlers) {\n            for (const handler of handlers) {\n                if (handler.handle(wire, ctx)) return true;\n            }\n        }\n\n        // Fall back to wildcard handlers (those listening to \"*\")\n        const wildcards = this.#eventMap.get(\"*\");\n        if (wildcards) {\n            for (const handler of wildcards) {\n                if (handler.handle(wire, ctx)) return true;\n            }\n        }\n\n        return false;\n    }\n}\n","/**\n * Event proxy — forward call/agent events up the chain.\n *\n * Call → Agent: event args + call appended\n * Agent → Pinecall: passthrough\n *\n * Port of src.bkp/utils/proxy.ts.\n */\n\nimport type { TypedEventBus, EventMap } from \"../kernel/event-bus.js\";\n\n/** Events that are proxied from Call → Agent (and Agent → Pinecall). */\nexport const CALL_PROXY_EVENTS = [\n    \"speech.started\",\n    \"speech.ended\",\n    \"user.speaking\",\n    \"user.message\",\n    \"eager.turn\",\n    \"turn.pause\",\n    \"turn.end\",\n    \"turn.resumed\",\n    \"turn.continued\",\n    \"bot.speaking\",\n    \"bot.word\",\n    \"bot.finished\",\n    \"bot.interrupted\",\n    \"message.confirmed\",\n    \"reply.rejected\",\n    \"audio.metrics\",\n    \"call.held\",\n    \"call.unheld\",\n    \"call.muted\",\n    \"call.unmuted\",\n    \"call.dtmf_received\",\n    \"llm.toolCall\",\n    \"skill.loaded\",\n    \"skill.unloaded\",\n    \"session.timeout\",\n] as const;\n\n/**\n * Forward events from a Call emitter to an Agent/Pinecall emitter.\n *\n * Call emits: `(event, ...callArgs)`\n * Agent emits: `(event, ...callArgs, call)`\n */\nexport function forwardCallEvents(\n    source: TypedEventBus<any>,\n    target: TypedEventBus<any>,\n    context: unknown,\n): void {\n    for (const event of CALL_PROXY_EVENTS) {\n        source.on(event, (...args: unknown[]) => {\n            (target as any).emit(event, ...args, context);\n        });\n    }\n}\n\n/**\n * Forward events from an Agent emitter to a Pinecall emitter.\n *\n * Agent emits: `(event, ...agentArgs)`\n * Pinecall emits: `(event, ...agentArgs)` — passthrough, same signature.\n */\nexport function forwardAgentEvents(\n    source: TypedEventBus<any>,\n    target: TypedEventBus<any>,\n): void {\n    for (const event of CALL_PROXY_EVENTS) {\n        source.on(event, (...args: unknown[]) => {\n            (target as any).emit(event, ...args);\n        });\n    }\n    // Also forward call lifecycle events\n    source.on(\"call.started\", (...args: unknown[]) => {\n        (target as any).emit(\"call.started\", ...args);\n    });\n    source.on(\"call.ended\", (...args: unknown[]) => {\n        (target as any).emit(\"call.ended\", ...args);\n    });\n}\n","/**\n * Connection handler — server-side agent lifecycle events.\n *\n * Handles: connected, authenticated, pong, agent.displaced,\n *          agent.created, agent.configured, agent.resumed\n *\n * Business logic ported from client.ts:\n *   - §7.5 reconnect re-registration: on agent.created/resumed → _flushPending\n *   - agent.displaced: emit on agent + client\n */\n\nimport type { EventHandler, DispatchContext } from \"../handler.js\";\nimport type { WireEvent } from \"../../protocol/wire.js\";\n\nexport class ConnectionHandler implements EventHandler {\n    readonly events = [\n        \"connected\",\n        \"authenticated\",\n        \"pong\",\n        \"agent.displaced\",\n        \"agent.created\",\n        \"agent.configured\",\n        \"agent.resumed\",\n    ] as const;\n\n    handle(wire: WireEvent, ctx: DispatchContext): boolean {\n        switch (wire.event) {\n            case \"connected\":\n                // Server confirmed auth — finalize connection\n                ctx.onConnected();\n                return true;\n\n            case \"authenticated\":\n                // Additional auth confirmation — no further action needed\n                return true;\n\n            case \"pong\":\n                return true;\n\n            case \"agent.displaced\": {\n                const agentId = wire.agent_id;\n                if (!agentId) return false;\n                const agent = ctx.agent(agentId);\n                if (agent) {\n                    agent._emitWire(\"channel.removed\" as any, wire.reason ?? \"displaced\");\n                    ctx.logger.warn(`Agent ${agent.id} displaced: ${wire.reason}`);\n                }\n                return true;\n            }\n\n            case \"agent.created\":\n            case \"agent.resumed\": {\n                const agentId = wire.agent_id;\n                if (!agentId) return false;\n                const agent = ctx.agent(agentId);\n                if (agent) {\n                    // Registration confirmed — cancel any pending conflict retry\n                    ctx.registration.clear(agent.id);\n                    // Re-register channels and flush pending messages\n                    agent._flushPending();\n                    // The agent exists server-side ONLY from here on — settle\n                    // `agent.ready` so a token mint can be ordered after it.\n                    agent._markRegistered();\n                    agent._emitWire(\"ready\");\n                    ctx.logger.info(`Agent ${agent.id} ${wire.event === \"agent.created\" ? \"created\" : \"resumed\"}`);\n                }\n                return true;\n            }\n\n            case \"agent.configured\": {\n                // Server acknowledged agent.configure — no-op\n                return true;\n            }\n\n            default:\n                return false;\n        }\n    }\n}\n","/**\n * Error handler — server error events.\n *\n * Business logic ported from client.ts:\n *   - PHONE_IN_USE: warn + remove channel from agent\n *   - AGENT_IN_USE: warn (agent removed by server)\n *   - CALL_LOG_REJECTED: emit `log.rejected` on the call, then on client\n *   - All other errors: emit on client\n */\n\nimport type { EventHandler, DispatchContext } from \"../handler.js\";\nimport type { WireEvent } from \"../../protocol/wire.js\";\nimport { ServerAtCapacityError } from \"../../kernel/errors.js\";\nimport type { CallLogRejectedEvent } from \"../../domain/call-events.js\";\n\nexport class ErrorHandler implements EventHandler {\n    readonly events = [\"error\"] as const;\n\n    handle(wire: WireEvent, ctx: DispatchContext): boolean {\n        const errorMsg = (wire.error ?? wire.message ?? \"Unknown error\") as string;\n        const code = wire.code as string | undefined;\n\n        // PHONE_IN_USE — a phone number is already claimed by another agent\n        if (code === \"PHONE_IN_USE\" || errorMsg.includes(\"PHONE_IN_USE\")) {\n            const phone = wire.phone as string | undefined;\n            const agentId = wire.agent_id as string | undefined;\n            console.warn(\n                `[pinecall] Phone ${phone || \"?\"} is already in use by another agent. ` +\n                `Removing from ${agentId || \"this agent\"}.`,\n            );\n            // Remove the channel from the local agent if we can identify it\n            if (agentId) {\n                const agent = ctx.agent(agentId);\n                if (agent && phone) {\n                    agent._getChannels().delete(phone);\n                }\n            }\n            return true;\n        }\n\n        // SERVER_AT_CAPACITY — the server's max_clients ceiling refused this\n        // registration. NOT a conflict, NOT a bad config, and above all NOT an\n        // offline agent: retrying the same call cannot help until a slot frees.\n        // It reached us as a generic REGISTRATION_ERROR before, and the only\n        // symptom a consumer saw afterwards was the token mint answering\n        // \"Agent 'x' is not online\" — which is why this gets its own type and\n        // its own words, verbatim from the server.\n        if (code === \"SERVER_AT_CAPACITY\" || errorMsg.startsWith(\"SERVER_AT_CAPACITY:\")) {\n            const agentId = (wire.agent_id as string | undefined) ?? \"\";\n            const used = wire.used as number | undefined;\n            const limit = wire.limit as number | undefined;\n            const err = new ServerAtCapacityError(errorMsg, agentId, used, limit);\n            console.error(\n                `\\n  \\x1b[91m✗\\x1b[0m Server at capacity — agent \"${agentId || \"?\"}\" was NOT registered` +\n                (used != null && limit != null ? ` (${used}/${limit} client slots used)` : \"\") + `.\\n` +\n                `    The agent is not offline: the server refused it a slot.\\n` +\n                `    Free slots (\\x1b[96mpinecall agents\\x1b[0m shows the holders) or raise the server cap.\\n`,\n            );\n            if (agentId) ctx.agent(agentId)?._failRegistration(err);\n            ctx.emitClientEvent(\"error\", err);\n            return true;\n        }\n\n        // AGENT_IN_USE / AGENT_CONFLICT — the agent slug is already registered\n        // by another connection. This is often TRANSIENT: after a network blip\n        // or process restart, the server may still hold our own dead socket as\n        // \"alive\" for a short window. Giving up permanently here turned a\n        // 1-minute blip into an hours-long outage — so we retry with backoff\n        // until the server frees the stale registration (or forever, if a real\n        // second instance owns the slug — then `pinecall kick` resolves it).\n        // AGENT_CONFLICT_FATAL is the exception: the server's liveness probe\n        // just CONFIRMED the holder alive. That is a terminal state — retrying\n        // it is a storm, so we stop immediately and say what to do instead.\n        if (\n            code === \"AGENT_IN_USE\" || code === \"AGENT_CONFLICT\" ||\n            code === \"AGENT_CONFLICT_FATAL\" || errorMsg.includes(\"AGENT_IN_USE\")\n        ) {\n            const agentId = wire.agent_id as string | undefined;\n\n            if (code === \"AGENT_CONFLICT_FATAL\") {\n                console.error(\n                    `\\n  \\x1b[91m✗\\x1b[0m Agent \"${agentId || \"?\"}\" is held by a LIVE process — not retrying.\\n` +\n                    `    Run \\x1b[96mpinecall kick ${agentId || \"<agent>\"}\\x1b[0m to disconnect the current holder,\\n` +\n                    `    or register this agent under a different id.\\n`,\n                );\n                // The coordinator emits the typed AgentConflictError itself;\n                // without an agent id there is nothing to fail, so the plain\n                // error is all we can surface.\n                if (agentId) {\n                    ctx.registration.fail(agentId);\n                } else {\n                    ctx.emitClientEvent(\"error\", new Error(errorMsg));\n                }\n                return true;\n            }\n\n            // Structured guidance from a new server (old servers omit both).\n            const retryAfterS = wire.retry_after_s as number | undefined;\n            const holderAlive = wire.holder_alive as boolean | undefined;\n            const hint = retryAfterS != null || holderAlive != null\n                ? { retryAfterS, holderAlive }\n                : undefined;\n\n            // No agent id means no episode to track — banner it once and move on.\n            const first = agentId ? ctx.registration.scheduleRetry(agentId, hint) : true;\n            // Log the human-facing banner ONCE per conflict episode — a name\n            // actively held elsewhere used to spam this every attempt for hours.\n            if (first) {\n                console.error(\n                    `\\n  \\x1b[91m✗\\x1b[0m Agent \"${agentId || \"?\"}\" is already connected` +\n                    (holderAlive ? \" (held by a LIVE process)\" : \"\") + `.\\n` +\n                    `    Retrying registration automatically with backoff` +\n                    (holderAlive ? \" (up to 10 min between attempts)\" : \" (stale registrations clear in ~1 min)\") + `.\\n` +\n                    `    If another live instance owns it, run \\x1b[96mpinecall kick ${agentId || \"<agent>\"}\\x1b[0m.\\n`,\n                );\n            }\n            ctx.emitClientEvent(\"error\", new Error(errorMsg));\n            return true;\n        }\n\n        // CALL_LOG_REJECTED — a `call.log()` the server did not append (bad\n        // name, value too large, sealed call, over the durable cap, …). The\n        // frame carries `call_id`, so it also reaches the call itself as\n        // `log.rejected`; the client `error` below still fires, like every\n        // other call-verb refusal.\n        if (code === \"CALL_LOG_REJECTED\") {\n            const callId = wire.call_id as string | undefined;\n            if (callId) {\n                const event: CallLogRejectedEvent = {\n                    callId,\n                    reason: (wire.reason as string | undefined) ?? errorMsg.replace(/^call\\.log:\\s*/, \"\"),\n                    error: errorMsg,\n                };\n                let agent = wire.agent_id ? ctx.agent(wire.agent_id as string) : null;\n                if (!agent) {\n                    for (const a of ctx.allAgents()) {\n                        if (a._getCall(callId)) { agent = a; break; }\n                    }\n                }\n                agent?._getCall(callId)?._emitWire(\"log.rejected\", event);\n            }\n            ctx.emitClientEvent(\"error\", new Error(errorMsg));\n            return true;\n        }\n\n        // REGISTRATION_ERROR — the server refused this agent for a reason that\n        // no retry can fix (bad config). The client cap used to land here too;\n        // it has its own code now, above. Fail anyone awaiting\n        // `agent.ready` right away instead of letting them wait out a deadline.\n        if (code === \"REGISTRATION_ERROR\") {\n            const agentId = wire.agent_id as string | undefined;\n            if (agentId) ctx.agent(agentId)?._failRegistration(new Error(errorMsg));\n        }\n\n        // Generic error — emit on client\n        ctx.emitClientEvent(\"error\", new Error(errorMsg));\n        return true;\n    }\n}\n","/**\n * Channel handler — channel lifecycle events.\n *\n * Handles: channel.added, channel.configured, channel.removed\n * Simple emit-on-agent passthrough.\n */\n\nimport type { EventHandler, DispatchContext } from \"../handler.js\";\nimport type { WireEvent } from \"../../protocol/wire.js\";\n\nexport class ChannelHandler implements EventHandler {\n    readonly events = [\"channel.added\", \"channel.configured\", \"channel.removed\"] as const;\n\n    handle(wire: WireEvent, ctx: DispatchContext): boolean {\n        const agentId = wire.agent_id;\n        if (!agentId) return false;\n\n        const agent = ctx.agent(agentId);\n        if (!agent) return false;\n\n        switch (wire.event) {\n            case \"channel.added\":\n                agent._emitWire(\"channel.added\", wire.type as string, wire.ref as string);\n                return true;\n\n            case \"channel.configured\":\n                agent._emitWire(\"channel.configured\", wire.ref as string);\n                return true;\n\n            case \"channel.removed\":\n                agent._emitWire(\"channel.removed\", wire.ref as string);\n                return true;\n\n            default:\n                return false;\n        }\n    }\n}\n","/**\n * ID generation — Stripe-style prefixed IDs.\n *\n *   generateId()        → \"msg_a1b2c3d4e5f6\"\n *   generateId(\"greet\") → \"greet_a1b2c3d4e5f6\"\n *\n * Uses crypto.getRandomValues() for proper randomness (browser-safe).\n */\n\nconst CHARS = \"abcdefghijklmnopqrstuvwxyz0123456789\";\n\nfunction randomSuffix(len = 12): string {\n    const bytes = crypto.getRandomValues(new Uint8Array(len));\n    let result = \"\";\n    for (let i = 0; i < len; i++) {\n        result += CHARS[bytes[i] % CHARS.length];\n    }\n    return result;\n}\n\nexport function generateId(prefix = \"msg\"): string {\n    return `${prefix}_${randomSuffix()}`;\n}\n\n// ─── Branded types ───────────────────────────────────────────────────────\n\n/** Nominal typing via brand tag. Compile-time only — zero runtime cost. */\nexport type Brand<T, B> = T & { readonly __brand: B };\n\nexport type CallId = Brand<string, \"CallId\">;\nexport type AgentId = Brand<string, \"AgentId\">;\nexport type MessageId = Brand<string, \"MessageId\">;\nexport type WireId = Brand<string, \"WireId\">;\n\nexport const CallId = (s: string): CallId => s as CallId;\nexport const AgentId = (s: string): AgentId => s as AgentId;\nexport const MessageId = (s: string): MessageId => s as MessageId;\nexport const WireId = (s: string): WireId => s as WireId;\n","/**\n * Requester — the request/response machine used by every scope that asks the\n * server a question over the same socket it sends fire-and-forget events on.\n *\n * Call and WhatsAppSession both need it, and both used to carry their own\n * copy. The machine is small but every line of it is load-bearing, so one copy\n * is one place to fix it.\n */\n\nimport { PinecallError } from \"./errors.js\";\n\n/**\n * How long a history/prompt request waits for its server ack before rejecting.\n * Generous on purpose — this is a failure detector, not a latency budget. The\n * turn's own budget is the `preparing` one, enforced server-side.\n */\nexport const REQUEST_TIMEOUT_MS = 10_000;\n\n/**\n * Request ids only need to be unique, never meaningful, so one module-level\n * counter serves every scope in the process.\n */\nlet requestSeq = 0;\n\nexport interface RequesterOptions {\n    /** Puts a frame on the wire. */\n    send: (data: Record<string, unknown>) => void;\n    /** The id that goes into the frame's `call_id` field. */\n    scopeId: string;\n    /** What the error messages call this scope — \"call abc\", \"WhatsApp session wa-x\". */\n    scopeLabel: string;\n    timeoutMs?: number;\n}\n\nexport class Requester {\n    readonly #send: (data: Record<string, unknown>) => void;\n    readonly #scopeId: string;\n    readonly #scopeLabel: string;\n    readonly #timeoutMs: number;\n\n    /** Pending response resolvers for request/response events. */\n    readonly #pending = new Map<string, (data: any) => void>();\n\n    constructor(opts: RequesterOptions) {\n        this.#send = opts.send;\n        this.#scopeId = opts.scopeId;\n        this.#scopeLabel = opts.scopeLabel;\n        this.#timeoutMs = opts.timeoutMs ?? REQUEST_TIMEOUT_MS;\n    }\n\n    /**\n     * Send a request and wait for its response event.\n     *\n     * Correlated by `request_id`, which the server echoes. Two reasons:\n     * concurrent requests used to overwrite each other in the pending map (they\n     * all key on \"history.updated\"), and a late reply could resolve the wrong\n     * caller. Servers that don't echo it fall back to event-name keying, which\n     * is what shipped before.\n     *\n     * The timeout is the point: without one, an ack that never routes leaves\n     * `await call.setPromptVars()` pending FOREVER, which is how the whole\n     * mechanism managed to fail without anyone noticing.\n     */\n    request(sendEvent: string, responseEvent: string, data: Record<string, unknown> = {}): Promise<any> {\n        const requestId = `rq_${(++requestSeq).toString(36)}_${Math.random().toString(36).slice(2, 8)}`;\n        const promise = new Promise<any>((resolve, reject) => {\n            const timer = setTimeout(() => {\n                this.#pending.delete(responseEvent);\n                this.#pending.delete(requestId);\n                reject(new PinecallError(\n                    `Timed out after ${this.#timeoutMs}ms waiting for \"${responseEvent}\" ` +\n                    `in reply to \"${sendEvent}\" on ${this.#scopeLabel}.`,\n                    \"REQUEST_TIMEOUT\",\n                ));\n            }, this.#timeoutMs);\n            const settle = (payload: any) => { clearTimeout(timer); resolve(payload); };\n            // Registered under BOTH keys: request_id for a server that echoes it,\n            // event name for one that doesn't.\n            this.#pending.set(responseEvent, settle);\n            this.#pending.set(requestId, settle);\n            this.#send({ event: sendEvent, call_id: this.#scopeId, request_id: requestId, ...data });\n        });\n        return promise.then((res) => {\n            // The server acks even when it could not find a handler for the\n            // call, and says so — better a rejection the app can see than the\n            // silence that used to leave the promise pending for good.\n            if (res?.error) {\n                throw new PinecallError(\n                    `\"${sendEvent}\" was rejected by the server on ${this.#scopeLabel}: ${res.error}`,\n                    \"REQUEST_REJECTED\",\n                );\n            }\n            return res;\n        });\n    }\n\n    /** Resolve a pending request from a wire reply. Returns true if one matched. */\n    applyResponse(eventType: string, data: Record<string, unknown>): boolean {\n        // request_id first — exact correlation when the server echoes it.\n        const requestId = data.request_id as string | undefined;\n        const resolver = (requestId ? this.#pending.get(requestId) : undefined)\n            ?? this.#pending.get(eventType);\n        if (resolver) {\n            if (requestId) this.#pending.delete(requestId);\n            this.#pending.delete(eventType);\n            resolver(data);\n            return true;\n        }\n        return false;\n    }\n\n    /**\n     * Mark a returned promise as handled so a fire-and-forget caller — the\n     * overwhelmingly common shape, `call.setPromptVars(v)` with no `await` —\n     * cannot bring the process down with an unhandled rejection when a request\n     * fails. A caller that DOES await still receives the error.\n     */\n    static handled<T>(p: Promise<T>): Promise<T> {\n        p.catch(() => {});\n        return p;\n    }\n}\n","/**\n * CallRequests — the call's server-side LLM history/prompt API.\n *\n * Every method here is one round-trip: a `history.*` frame out, a\n * `history.updated` / `history.data` ack back, matched by the kernel Requester.\n * Split out of `call.ts` so the class stays a handle plus turn state; the\n * public methods on Call delegate here one-to-one, so the wire frames are the\n * same frames they always were.\n */\n\nimport { Requester } from \"../kernel/requester.js\";\n\nexport class CallRequests {\n    #requester: Requester;\n\n    constructor(callId: string, send: (data: Record<string, unknown>) => void) {\n        this.#requester = new Requester({\n            send,\n            scopeId: callId,\n            scopeLabel: `call ${callId}`,\n        });\n    }\n\n    getHistory(): Promise<Array<{ role: string; content: string }>> {\n        return Requester.handled(\n            this.#requester.request(\"history.get\", \"history.data\").then((res) => res.messages ?? []),\n        );\n    }\n\n    addHistory(messages: Array<{ role: string; content: string }>): Promise<number> {\n        return Requester.handled(\n            this.#requester.request(\"history.add\", \"history.updated\", { messages })\n                .then((res) => res.count ?? 0),\n        );\n    }\n\n    setHistory(messages: Array<{ role: string; content: string }>): Promise<number> {\n        return Requester.handled(\n            this.#requester.request(\"history.set\", \"history.updated\", { messages })\n                .then((res) => res.count ?? 0),\n        );\n    }\n\n    clearHistory(): Promise<number> {\n        return Requester.handled(\n            this.#requester.request(\"history.clear\", \"history.updated\").then((res) => res.count ?? 0),\n        );\n    }\n\n    setVars(vars: Record<string, string>): Promise<number> {\n        return Requester.handled(\n            this.#requester.request(\"history.set_vars\", \"history.updated\", { vars })\n                .then((res) => res.count ?? 0),\n        );\n    }\n\n    addContext(text: string): Promise<number> {\n        return Requester.handled(\n            this.#requester.request(\"history.add_context\", \"history.updated\", { text })\n                .then((res) => res.count ?? 0),\n        );\n    }\n\n    setInstructions(text: string): Promise<number> {\n        return Requester.handled(\n            this.#requester.request(\"history.set_instructions\", \"history.updated\", { prompt: text })\n                .then((res) => res.count ?? 0),\n        );\n    }\n\n    /** Resolve a pending request from its server ack. */\n    applyResponse(eventType: string, data: Record<string, unknown>): boolean {\n        return this.#requester.applyResponse(eventType, data);\n    }\n}\n","/**\n * ReplyStream — writable stream for bot.reply.stream protocol.\n *\n * Auto-aborts on turn.continued. Pairs naturally with LLM streaming:\n *\n *   const stream = call.replyStream(turn);\n *   for await (const token of llm.stream(prompt)) {\n *     if (stream.aborted) break;\n *     stream.write(token);\n *   }\n *   stream.end();\n */\n\nimport { generateId } from \"../kernel/id.js\";\n\n/** Outbox interface — decouples ReplyStream from raw WebSocket send. */\nexport interface Outbox {\n    send(data: Record<string, unknown>): void;\n}\n\nexport interface ReplyStreamOptions {\n    callId: string;\n    messageId?: string;\n    inReplyTo: string;\n    send: (data: Record<string, unknown>) => void;\n    /** Called when the stream ends or is aborted — for cleanup. */\n    onComplete?: () => void;\n}\n\nexport class ReplyStream {\n    readonly messageId: string;\n    readonly callId: string;\n\n    #aborted = false;\n    #ended = false;\n    #started = false;\n    #send: (data: Record<string, unknown>) => void;\n    #inReplyTo: string;\n\n    // AbortController for external cancellation\n    #ac = new AbortController();\n\n    #onComplete?: () => void;\n\n    constructor(opts: ReplyStreamOptions) {\n        this.messageId = opts.messageId ?? generateId(\"msg\");\n        this.callId = opts.callId;\n        this.#inReplyTo = opts.inReplyTo;\n        this.#send = opts.send;\n        this.#onComplete = opts.onComplete;\n    }\n\n    /** True if the stream was aborted (e.g. turn.continued). */\n    get aborted(): boolean {\n        return this.#aborted;\n    }\n\n    /** True if end() was called. */\n    get ended(): boolean {\n        return this.#ended;\n    }\n\n    /** AbortSignal that fires on abort — use with fetch, LLM clients, etc. */\n    get signal(): AbortSignal {\n        return this.#ac.signal;\n    }\n\n    /**\n     * Write a token/chunk to the stream.\n     * Automatically sends `start` on the first write.\n     */\n    write(token: string): void {\n        if (this.#aborted || this.#ended) return;\n\n        if (!this.#started) {\n            this.#started = true;\n            this.#send({\n                event: \"bot.reply.stream\",\n                call_id: this.callId,\n                message_id: this.messageId,\n                action: \"start\",\n                in_reply_to: this.#inReplyTo,\n            });\n        }\n\n        this.#send({\n            event: \"bot.reply.stream\",\n            call_id: this.callId,\n            message_id: this.messageId,\n            action: \"chunk\",\n            token,\n        });\n    }\n\n    /** End the stream normally — flushes remaining buffer on server. */\n    end(): void {\n        if (this.#aborted || this.#ended) return;\n        this.#ended = true;\n        this.#fireComplete();\n\n        // If we never wrote anything, send start+end so server knows\n        if (!this.#started) {\n            this.#started = true;\n            this.#send({\n                event: \"bot.reply.stream\",\n                call_id: this.callId,\n                message_id: this.messageId,\n                action: \"start\",\n                in_reply_to: this.#inReplyTo,\n            });\n        }\n\n        this.#send({\n            event: \"bot.reply.stream\",\n            call_id: this.callId,\n            message_id: this.messageId,\n            action: \"end\",\n        });\n    }\n\n    /** Abort the stream immediately (e.g. on turn.continued). */\n    abort(): void {\n        if (this.#aborted) return;\n        this.#aborted = true;\n        this.#ended = true;\n\n        // Tell the server this stream is done so it cleans up\n        // (_is_streaming, TTS flush, etc.)\n        if (this.#started) {\n            this.#send({\n                event: \"bot.reply.stream\",\n                call_id: this.callId,\n                message_id: this.messageId,\n                action: \"end\",\n            });\n        }\n\n        this.#fireComplete();\n        this.#ac.abort();\n    }\n\n    #fireComplete(): void {\n        if (this.#onComplete) {\n            const cb = this.#onComplete;\n            this.#onComplete = undefined;\n            cb();\n        }\n    }\n}\n","/**\n * CallHistoryRecorder — incremental persistence of a call's conversation.\n *\n * A call writes its record many times: once when it starts (status \"active\"),\n * once per confirmed message, and a final time when it ends. The middle ones\n * are debounced — a burst of tool/bot/user events would otherwise hammer the\n * store with near-identical records — and the final one is FLUSHED, so the\n * ended record is never left behind a pending timer.\n *\n * Kept out of `call.ts` so a Call stays a handle on a session; the record is\n * built from the call's public fields only.\n */\n\nimport type { Call } from \"./call.js\";\nimport type { ConversationRecord, HistoryStore } from \"../history.js\";\n\nexport class CallHistoryRecorder {\n    /** Debounce interval for incremental history saves (ms). */\n    static HISTORY_DEBOUNCE_MS = 200;\n\n    #call: Call;\n    #agentId: string;\n    #store: HistoryStore;\n    #timer: ReturnType<typeof setTimeout> | undefined;\n\n    constructor(call: Call, agentId: string, store: HistoryStore) {\n        this.#call = call;\n        this.#agentId = agentId;\n        this.#store = store;\n    }\n\n    /**\n     * Schedule a debounced save (coalesces rapid events).\n     */\n    saveDebounced(): void {\n        if (this.#timer) clearTimeout(this.#timer);\n        this.#timer = setTimeout(() => {\n            this.#timer = undefined;\n            this.saveNow();\n        }, CallHistoryRecorder.HISTORY_DEBOUNCE_MS);\n    }\n\n    /**\n     * Immediate save. Builds a ConversationRecord from the call's current state.\n     */\n    saveNow(): void {\n        const call = this.#call;\n\n        const contactId = (\n            call.metadata?.userId\n                ? String(call.metadata.userId)\n                : call.from\n        );\n\n        const record: ConversationRecord = {\n            callId: call.id,\n            agentId: this.#agentId,\n            channel: call.transport as ConversationRecord[\"channel\"],\n            direction: call.direction,\n            from: contactId,\n            to: call.to,\n            startedAt: call.startedAt,\n            endedAt: call.endedAt,\n            duration: call.duration,\n            reason: call.reason,\n            status: call.status,\n            transcript: call.transcript,\n            messages: call.messages,\n            metadata: call.metadata,\n        };\n\n        // Fire-and-forget — never block event dispatch\n        this.#store.save(record).catch(() => {\n            // Silently ignore save errors during call\n        });\n    }\n\n    /**\n     * Cancel any pending debounced save and write the current state now.\n     * Used on call.ended, where the last record must be the final one.\n     */\n    flush(): void {\n        if (this.#timer) clearTimeout(this.#timer);\n        this.#timer = undefined;\n        this.saveNow();\n    }\n}\n","/**\n * Call SSE streaming — a live transcript of ONE call, pushed to an HTTP response.\n *\n * This lives outside `domain/call.ts` on purpose: a Call is a handle on a\n * session, not an HTTP concern. `Call.streamSSE()` stays as a one-line delegate\n * so the public API is unchanged.\n */\n\nimport type { Call } from \"../domain/call.js\";\n\n// ── SSE types (minimal duck-typing for Express/Connect/raw http) ─────\n\n/** Minimal writable response for streamSSE. */\nexport interface SSEResponse {\n    writeHead?: (status: number, headers: Record<string, string>) => void;\n    write: (chunk: string) => boolean;\n    end: () => void;\n    on: (event: string, handler: () => void) => void;\n}\n\nexport interface StreamSSEOptions {\n    /** Greeting text to send as the first bot message (for outbound calls). */\n    greeting?: string;\n}\n\n// ─── SSE streaming ──────────────────────────────────────────────────\n\n/**\n * Stream a call's events as Server-Sent Events to an HTTP response.\n *\n * Handles SSE headers, word-by-word buffering, event scoping,\n * keepalive pings, and automatic cleanup. Designed for \"Call Me\"\n * endpoints where the browser needs a live transcript.\n *\n * @param call The call to stream\n * @param res  Node.js HTTP response (Express, Connect, raw http.ServerResponse)\n * @param opts Optional config\n */\nexport function streamCallSSE(call: Call, res: SSEResponse, opts?: StreamSSEOptions): void {\n    const greeting = opts?.greeting ?? call.greeting;\n\n    // ── SSE headers ──\n    if (typeof res.writeHead === \"function\") {\n        res.writeHead(200, {\n            \"Content-Type\": \"text/event-stream\",\n            \"Cache-Control\": \"no-cache\",\n            \"Connection\": \"keep-alive\",\n            \"X-Accel-Buffering\": \"no\",\n        });\n    }\n    if (typeof (res as any).flushHeaders === \"function\") {\n        (res as any).flushHeaders();\n    }\n\n    const send = (event: string, data: Record<string, unknown>) => {\n        try {\n            res.write(`event: ${event}\\ndata: ${JSON.stringify(data)}\\n\\n`);\n            if (typeof (res as any).flush === \"function\") (res as any).flush();\n        } catch { /* client gone */ }\n    };\n\n    // ── Keepalive ping ──\n    const ping = setInterval(() => {\n        try {\n            res.write(\":ping\\n\\n\");\n            if (typeof (res as any).flush === \"function\") (res as any).flush();\n        } catch { clearInterval(ping); }\n    }, 25_000);\n\n    // ── Initial events ──\n    send(\"call.started\", { callId: call.id });\n\n    if (greeting) {\n        send(\"bot.confirmed\", { text: greeting, messageId: \"greeting\" });\n    }\n\n    // ── Event listeners ──\n    call.on(\"bot.word\", () => {\n        send(\"bot.word\", { text: call.currentBotText, messageId: call._currentBotMessageId ?? \"\" });\n    });\n\n    call.on(\"message.confirmed\", (event) => {\n        if (event.text) {\n            send(\"bot.confirmed\", { text: event.text, messageId: event.messageId });\n        }\n    });\n\n    call.on(\"user.speaking\", (event) => {\n        send(\"user.speaking\", { text: event.text, messageId: event.messageId });\n    });\n\n    call.on(\"user.message\", (event) => {\n        send(\"user.message\", { text: event.text, messageId: event.messageId });\n    });\n\n    call.on(\"llm.toolCall\", (event) => {\n        const tools = event.toolCalls ?? [];\n        for (const tc of tools) {\n            send(\"tool.call\", { name: tc.name, args: tc.arguments });\n        }\n    });\n\n    call.on(\"ended\", (reason) => {\n        send(\"call.ended\", { reason, duration: Math.round(call.duration || 0) });\n        clearInterval(ping);\n        res.end();\n    });\n\n    // ── Client disconnect ──\n    res.on(\"close\", () => {\n        clearInterval(ping);\n        // Call listeners auto-cleanup on _applyEnd\n    });\n}\n","/**\n * Call — per-session handle for interacting with a voice call.\n *\n * Created automatically when `call.started` is received.\n * Provides high-level methods: say(), reply(), replyStream(), hold(), mute(), cancel(), hangup().\n *\n * Tracks `lastMessageId` from user.message events for automatic `in_reply_to`.\n *\n * The old _handleEvent() 140-line switch is gone. Dispatch handlers now call\n * typed _apply* methods directly. Each method is small, typed, and explicit.\n */\n\nimport { TypedEventBus } from \"../kernel/event-bus.js\";\nimport { generateId } from \"../kernel/id.js\";\nimport { Requester, REQUEST_TIMEOUT_MS } from \"../kernel/requester.js\";\nimport { CallRequests } from \"./call-requests.js\";\nimport { ReplyStream } from \"./reply-stream.js\";\nimport type { Turn } from \"./turn.js\";\nimport type { CallEvents, CallLogOptions } from \"./call-events.js\";\nimport type { ReplyOptions, ForwardOptions } from \"./call-events.js\";\nimport type {\n    UserMessageEvent,\n    TurnContinuedEvent,\n    BotSpeakingEvent,\n    BotWordEvent,\n    BotFinishedEvent,\n    BotInterruptedEvent,\n    LineTranscriptEntry,\n} from \"../protocol/events.js\";\nimport { CallHistoryRecorder } from \"./call-history.js\";\nimport { streamCallSSE } from \"../sse/call-stream.js\";\nimport type { SSEResponse, StreamSSEOptions } from \"../sse/call-stream.js\";\nimport type { SessionConfig } from \"../config/session.js\";\nimport type { HistoryStore } from \"../history.js\";\n\n// These types used to live in this file; index.ts (and every app) imports them\n// from here, so they keep travelling through it.\nexport type { SSEResponse, StreamSSEOptions };\nexport type { CallEvents, PreparingTimeoutEvent, SkillEvent, CallLogRejectedEvent, CallLogOptions, ReplyOptions, ForwardOptions } from \"./call-events.js\";\nexport type { LineTranscriptEntry } from \"../protocol/events.js\";\n\n/**\n * What a `call.started` carries into a `Call`.\n *\n * Named because `Agent._createCall()` hands it on: a `PhoneLine` builds a\n * `LineCall` from exactly this, so the shape had to stop being an inline\n * literal on one constructor.\n */\nexport interface CallInit {\n    call_id: string;\n    from: string;\n    to: string;\n    direction: \"inbound\" | \"outbound\";\n    transport?: \"webrtc\" | \"phone\" | \"chat\" | \"whatsapp\" | \"unknown\";\n    metadata?: Record<string, unknown>;\n    language?: string;\n    /** The extension dialled after the number, when a line resolved one. */\n    extension?: string | null;\n    /** Who is driving this session — a line, or an agent. */\n    owner?: \"line\" | \"agent\";\n    /** The line that handed this call over, `line:<number>`. */\n    routed_from?: string;\n    /** What the line heard and said before the hand-over. */\n    line_transcript?: Array<{ who: \"caller\" | \"line\"; text: string; at?: number }>;\n}\n\n/** What an awaited `say()` reports: whether the caller talked over it. */\nexport interface SayResult {\n    interrupted: boolean;\n}\n\n// ─── Call class ──────────────────────────────────────────────────────────\n\n/**\n * How long a history/prompt request waits for its server ack before rejecting.\n * Lives in the kernel now (the requester owns the timer); re-exported here\n * because that is where it has always been imported from.\n */\nexport { REQUEST_TIMEOUT_MS };\n\nexport class Call extends TypedEventBus<CallEvents> {\n    readonly id: string;\n    readonly from: string;\n    readonly to: string;\n    readonly direction: \"inbound\" | \"outbound\";\n    readonly transport: \"webrtc\" | \"phone\" | \"chat\" | \"whatsapp\" | \"unknown\";\n    readonly metadata: Record<string, unknown>;\n    /**\n     * The SESSION's language, as the server resolved it: the browser's pick on\n     * webrtc (`config.language` in the offer, e.g. a language toggle in the\n     * page), the dialled number's channel config on phone, the agent's default\n     * otherwise. BCP-47 base (\"en\", \"es\"). Empty when the server predates it.\n     * Read this — not `metadata` — to localise a session's prompt: it is the\n     * same fact the server used to pick STT/TTS language and the greeting.\n     *\n     * It FOLLOWS a mid-call switch: when a browser changes the session's\n     * language (`VoiceSession.configure({ language })`), the server moves STT\n     * and TTS and tells the SDK, which updates this before the next\n     * `call.preparing`. So a prompt localised in that hook stays in step with\n     * what the caller is hearing — read it per turn, do not cache it.\n     */\n    get language(): string {\n        return this.#language;\n    }\n    #language: string;\n\n    /** @internal The server reported a new session language (mid-call switch). */\n    _setLanguage(lang: string): void {\n        this.#language = lang;\n    }\n\n    /**\n     * The extension the caller dialled after the number (\"33\"), or null.\n     *\n     * Set by a phone line (`pc.line()`), and carried through `routeTo` so the\n     * agent knows which door the call came through. Always null on a call that\n     * no line answered.\n     */\n    readonly extension: string | null;\n\n    /**\n     * The line that handed this call over — `line:<number>` — or null when the\n     * call came straight to the agent.\n     */\n    readonly routedFrom: string | null;\n\n    /**\n     * What the line heard and said before it routed the call here. Empty on a\n     * call no line answered.\n     */\n    readonly lineTranscript: readonly LineTranscriptEntry[];\n\n    /** Auto-tracked from the latest user.message. Used as default `in_reply_to`. */\n    lastMessageId: string | null = null;\n\n    /** Conversation transcript (user + assistant messages only). Derived from `messages`. */\n    get transcript(): Array<{ role: string; content: string }> {\n        return this.messages\n            .filter(m => (m.role === \"user\" || m.role === \"assistant\") && m.content)\n            .map(m => ({ role: m.role as string, content: m.content as string }));\n    }\n    /** Full LLM message history. Built incrementally from events; server copy merged on call.ended. */\n    messages: Array<Record<string, unknown>> = [];\n    /** Conversation status. `\"active\"` during call, `\"ended\"` after call.ended. */\n    status: \"active\" | \"ended\" = \"active\";\n    /** Call duration in seconds. Populated on call.ended. */\n    duration: number = 0;\n    /** Epoch seconds when call started. Populated on call.ended. */\n    startedAt: number = 0;\n    /** Epoch seconds when call ended. Populated on call.ended. */\n    endedAt: number = 0;\n    /** End reason (e.g. \"hangup\", \"timeout\"). Populated on call.ended. */\n    reason: string = \"\";\n\n    /**\n     * Live preview of what the bot is currently saying.\n     * Accumulated word-by-word from `bot.word` events.\n     * Resets when a new bot message starts, clears when finished/interrupted.\n     */\n    get currentBotText(): string {\n        return this.#botWords.join(\" \");\n    }\n\n    /** @internal Word accumulator for current bot message. */\n    #botWords: string[] = [];\n    /** @internal Message ID being tracked for word accumulation. */\n    #botWordMessageId: string | null = null;\n\n    /** @internal The message id the word buffer belongs to — read by the SSE stream. */\n    get _currentBotMessageId(): string | null {\n        return this.#botWordMessageId;\n    }\n\n    /** Outbound greeting (set by dial). Used by streamSSE to send the first transcript entry. */\n    greeting: string | null = null;\n\n    /** Active ReplyStreams — aborted automatically on turn.continued. */\n    #activeStreams = new Set<ReplyStream>();\n\n    /** @internal Base prompt template (for variable interpolation). */\n    _promptTemplate = \"\";\n\n    /** @internal Prompts directory (set by agent). */\n    _promptsDir = \"prompts\";\n\n    /** Send function provided by Pinecall client. */\n    #send: (data: Record<string, unknown>) => void;\n\n    // Latest turn data (built from eager.turn + user.message + turn.end)\n    #lastTurnId = 0;\n    #lastTurnText = \"\";\n    #lastTurnConfidence = 0;\n    #lastTurnLanguage: string | undefined;\n\n    /** @internal Server-side history/prompt round-trips — see call-requests.ts. */\n    #requests: CallRequests;\n\n    /** Skills currently active on this call (tracked from server skill events). */\n    #activeSkills = new Set<string>();\n\n    /** @internal Incremental history persistence — see domain/call-history.ts. */\n    #history: CallHistoryRecorder | undefined;\n\n    /**\n     * Debounce interval for incremental history saves (ms).\n     * The recorder owns it now; kept here because that is where it has always\n     * been read from (and set from, in tests).\n     */\n    static get HISTORY_DEBOUNCE_MS(): number {\n        return CallHistoryRecorder.HISTORY_DEBOUNCE_MS;\n    }\n    static set HISTORY_DEBOUNCE_MS(ms: number) {\n        CallHistoryRecorder.HISTORY_DEBOUNCE_MS = ms;\n    }\n\n    constructor(\n        data: CallInit,\n        send: (data: Record<string, unknown>) => void,\n    ) {\n        super();\n        this.id = data.call_id;\n        this.from = data.from;\n        this.to = data.to;\n        this.direction = data.direction;\n        this.transport = data.transport ?? \"unknown\";\n        this.metadata = data.metadata ?? {};\n        this.#language = data.language ?? \"\";\n        this.extension = data.extension ?? null;\n        this.routedFrom = data.routed_from ?? null;\n        this.lineTranscript = (data.line_transcript ?? []).map((e) => ({\n            who: e.who,\n            text: e.text,\n            at: e.at ?? Date.now(),\n            role: e.who === \"caller\" ? \"user\" as const : \"assistant\" as const,\n            content: e.text,\n        }));\n        this.#send = send;\n        this.#requests = new CallRequests(this.id, send);\n    }\n\n    // ── High-level reply methods ─────────────────────────────────────────\n\n    /**\n     * Send a greeting or standalone message (no in_reply_to required).\n     *\n     * Pass `{ addToHistory: true }` to inject this text into the server-side\n     * LLM conversation history as an assistant message, so the model knows\n     * what was said and won't repeat it.\n     */\n    say(text: string, opts?: { addToHistory?: boolean }): Promise<SayResult> {\n        const messageId = generateId(\"msg\");\n        this.#send({\n            event: \"bot.reply\",\n            call_id: this.id,\n            message_id: messageId,\n            text,\n            in_reply_to: \"\",\n            ...(opts?.addToHistory ? { add_to_history: true } : {}),\n        });\n        return this._awaitPlayback(messageId);\n    }\n\n    /**\n     * @internal Resolve when the audio for `messageId` stopped coming out of\n     * the speaker — finished, interrupted, or the call ended under it.\n     *\n     * NEVER rejects. `say()` has always been fire-and-forget and stays that\n     * way: an un-awaited call cannot produce an unhandled rejection, because\n     * there is nothing to reject.\n     */\n    protected _awaitPlayback(messageId: string): Promise<SayResult> {\n        if (this.status === \"ended\") return Promise.resolve({ interrupted: true });\n        return new Promise<SayResult>((resolve) => {\n            const settle = (interrupted: boolean) => {\n                this.off(\"bot.finished\", onFinished);\n                this.off(\"bot.interrupted\", onInterrupted);\n                this.off(\"ended\", onEnded);\n                resolve({ interrupted });\n            };\n            // A server that omits message_id is answering about the only reply\n            // in flight — ours.\n            const onFinished = (e: BotFinishedEvent) => {\n                if (!e?.messageId || e.messageId === messageId) settle(false);\n            };\n            const onInterrupted = (e: BotInterruptedEvent) => {\n                if (!e?.messageId || e.messageId === messageId) settle(true);\n            };\n            const onEnded = () => settle(true);\n            this.on(\"bot.finished\", onFinished);\n            this.on(\"bot.interrupted\", onInterrupted);\n            this.on(\"ended\", onEnded);\n        });\n    }\n\n    /**\n     * @internal One raw frame out on this call's socket.\n     *\n     * The private `#send` cannot cross a subclass boundary, and `LineCall`\n     * has verbs of its own to send (`call.route`, `set_context`).\n     */\n    protected _sendRaw(data: Record<string, unknown>): void {\n        this.#send(data);\n    }\n\n    /** Reply to the latest user message (auto-tracks in_reply_to). */\n    reply(text: string, options?: ReplyOptions): void {\n        const id = options?.messageId ?? generateId(\"msg\");\n        const inReplyTo = options?.inReplyTo ?? this.lastMessageId ?? \"\";\n        this.#send({\n            event: \"bot.reply\",\n            call_id: this.id,\n            message_id: id,\n            text,\n            in_reply_to: inReplyTo,\n        });\n    }\n\n    /** Create a streaming reply. Write tokens, then end. */\n    replyStream(turn?: Turn, messageId?: string): ReplyStream {\n        const inReplyTo = turn?.messageId ?? this.lastMessageId ?? \"\";\n        const stream = new ReplyStream({\n            callId: this.id,\n            messageId: messageId ?? generateId(\"msg\"),\n            inReplyTo,\n            send: (data) => this.#send(data),\n            onComplete: () => this.#activeStreams.delete(stream),\n        });\n        this.#activeStreams.add(stream);\n        return stream;\n    }\n\n    /** Respond to a server-side LLM tool call. */\n    toolResult(\n        msgId: string,\n        results: Array<{ toolCallId: string; result: unknown; ephemeral?: boolean; noFollowup?: boolean }>,\n    ): void {\n        this.#send({\n            event: \"llm.tool_result\",\n            call_id: this.id,\n            msg_id: msgId,\n            results: results.map(r => ({\n                tool_call_id: r.toolCallId,\n                result: r.result,\n                // Ephemeral results are dropped from history by the server after\n                // they're used for the current reply. Omitted when false.\n                ...(r.ephemeral ? { ephemeral: true } : {}),\n                // noFollowup: the server skips the follow-up assistant turn after\n                // this tool (UI-only tools). Omitted when false.\n                ...(r.noFollowup ? { no_followup: true } : {}),\n            })),\n        });\n    }\n\n    // ── Control ──────────────────────────────────────────────────────────\n\n    /** Cancel a specific message or the current one. */\n    cancel(messageId?: string): void {\n        this.#send({\n            event: \"bot.cancel\",\n            call_id: this.id,\n            ...(messageId ? { message_id: messageId } : {}),\n        });\n    }\n\n    /** Clear all queued audio. */\n    clear(): void {\n        this.#send({ event: \"bot.clear\", call_id: this.id });\n    }\n\n    /** Hang up the call. */\n    hangup(): void {\n        this.#send({ event: \"call.hangup\", call_id: this.id });\n    }\n\n    /** Forward the call to another number. */\n    forward(to: string, options?: ForwardOptions): void {\n        this.#send({\n            event: \"call.forward\",\n            call_id: this.id,\n            to,\n            message: options?.message ?? \"\",\n            announce: options?.announce ?? false,\n        });\n    }\n\n    /** Send DTMF tones. */\n    sendDTMF(digits: string): void {\n        this.#send({ event: \"call.dtmf\", call_id: this.id, digits });\n    }\n\n    /** Update config for this call (mid-call). */\n    update(opts: Record<string, unknown>): void {\n        this.#send({\n            event: \"session.configure\",\n            session_id: this.id,\n            ...opts,\n        });\n    }\n\n    /** @deprecated Use `call.update()` instead. */\n    configure(opts: Record<string, unknown>): void {\n        this.update(opts);\n    }\n\n    /** @deprecated Use `call.update()` instead. */\n    updateConfig(config: Partial<SessionConfig>): void {\n        this.update({ config });\n    }\n\n    // ── Skills ──────────────────────────────────────────────────────────────\n\n    /** Skills currently active on this call (server-authoritative). */\n    get activeSkills(): string[] {\n        return [...this.#activeSkills];\n    }\n\n    /**\n     * Activate a declared skill on this call now — exposing its tools and\n     * instructions to the LLM and adding its knowledge base to RAG. Programmatic\n     * counterpart to the model-driven `loadSkill` meta-tool. Takes effect on the\n     * next LLM turn. Emits `skill.loaded` once the server confirms.\n     */\n    loadSkill(name: string): void {\n        this.#send({ event: \"skill.load\", call_id: this.id, skill: name });\n    }\n\n    /** Deactivate a skill on this call (inverse of `loadSkill`). */\n    unloadSkill(name: string): void {\n        this.#send({ event: \"skill.unload\", call_id: this.id, skill: name });\n    }\n\n    /** @internal Update tracked active-skill state from a server skill event. */\n    _setSkillActive(name: string, active: boolean): void {\n        if (active) this.#activeSkills.add(name);\n        else this.#activeSkills.delete(name);\n    }\n\n    // ── Custom log entries ─────────────────────────────────────────────\n\n    /**\n     * Append a custom entry to this call's log: `type: \"custom\"`,\n     * `data: { name, value, id?, turn }`. Durable by default — visible to every\n     * observer of the call (dashboards, `useCall`, `GET /v1/calls/{id}/events`,\n     * SSE) and replayed on resume; `ephemeral: true` fans it out live only.\n     * Reachable from a tool through its `call` parameter.\n     *\n     * Fire-and-forget: the server validates (`name` matches\n     * `^[a-z0-9][a-z0-9._-]{0,63}$`, `value` ≤ 16 KiB as JSON, `id` ≤ 128\n     * chars, ≤ 1000 durable entries per call, call still open) and a refusal\n     * arrives as the call's `log.rejected` event (and the client `error`).\n     */\n    log(name: string, value: unknown, opts?: CallLogOptions): void {\n        this.#send({\n            event: \"call.log\",\n            call_id: this.id,\n            name,\n            value,\n            ...(opts?.id !== undefined ? { id: opts.id } : {}),\n            ...(opts?.ephemeral ? { ephemeral: true } : {}),\n        });\n    }\n\n    // ── Hold / Mute ────────────────────────────────────────────────────\n\n    hold(): void { this.#send({ event: \"call.hold\", call_id: this.id }); }\n    unhold(): void { this.#send({ event: \"call.unhold\", call_id: this.id }); }\n    mute(): void { this.#send({ event: \"call.mute\", call_id: this.id }); }\n    unmute(): void { this.#send({ event: \"call.unmute\", call_id: this.id }); }\n\n    // ── History management (server-side LLM) ─────────────────────────────\n    // One frame out, one ack back — the machinery lives in call-requests.ts.\n\n    getHistory(): Promise<Array<{ role: string; content: string }>> { return this.#requests.getHistory(); }\n    addHistory(messages: Array<{ role: string; content: string }>): Promise<number> { return this.#requests.addHistory(messages); }\n    setHistory(messages: Array<{ role: string; content: string }>): Promise<number> { return this.#requests.setHistory(messages); }\n    clearHistory(): Promise<number> { return this.#requests.clearHistory(); }\n    addContext(text: string): Promise<number> { return this.#requests.addContext(text); }\n\n    setPrompt(prompt: string): Promise<number> {\n        this._promptTemplate = prompt;\n        return this.#requests.setInstructions(prompt);\n    }\n\n    setPromptFile(filePath: string): Promise<number> {\n        return Requester.handled((async () => {\n            // Lazy import — browser-safe, fixes the require(\"path\")/require(\"fs\") bundler issue\n            const { readFileSync } = await import(\"node:fs\");\n            const { resolve } = await import(\"node:path\");\n            const resolved = resolve(this._promptsDir, filePath);\n            this._promptTemplate = readFileSync(resolved, \"utf-8\").trim();\n            return this.#requests.setInstructions(this._promptTemplate);\n        })());\n    }\n\n    /**\n     * Push `{{var}}` values for the CURRENT turn. Highest precedence: they beat\n     * the agent-level `promptVars` and stay until you overwrite them.\n     *\n     * Inside a `call.preparing` handler this is the per-turn contract — return\n     * the promise (or `await` it) and the server holds the generation until it\n     * lands. Resolves with the message count, or rejects if the server never\n     * acknowledges it.\n     */\n    setPromptVars(vars: Record<string, string>): Promise<number> { return this.#requests.setVars(vars); }\n\n    // ── Dispatch-only API (friend methods) ───────────────────────────────\n    // Called by dispatch handlers. Prefixed with _ and marked @internal.\n    // Not part of the public contract.\n\n    /** @internal Reset word buffer and start tracking a new bot message. */\n    _applyBotSpeaking(event: BotSpeakingEvent): void {\n        this.#botWords = [];\n        this.#botWordMessageId = event.messageId;\n        this.emit(\"bot.speaking\", event);\n    }\n\n    /** @internal Append a word to the live preview buffer. */\n    _applyBotWord(event: BotWordEvent): void {\n        if (event.messageId === this.#botWordMessageId) {\n            this.#botWords.push(event.word);\n        }\n        this.emit(\"bot.word\", event);\n    }\n\n    /** @internal Clear the word buffer (bot finished or interrupted). */\n    _clearBotWords(): void {\n        this.#botWords = [];\n        this.#botWordMessageId = null;\n    }\n\n    /** @internal Resolve a pending history request/response promise. */\n    _applyHistoryResponse(eventType: string, data: Record<string, unknown>): boolean {\n        return this.#requests.applyResponse(eventType, data);\n    }\n\n    /**\n     * @internal Run the `call.preparing` handlers and hand back whatever they\n     * returned, so the caller can await async ones before releasing the turn.\n     */\n    _emitPreparing(): unknown[] {\n        return this.emitCollect(\"call.preparing\", this);\n    }\n\n    /** @internal True when the app is listening for the pre-turn hook. */\n    _hasPreparingListener(): boolean {\n        return this.listenerCount(\"call.preparing\") > 0;\n    }\n\n    /** @internal Apply user.message — tracks lastMessageId and turn state. */\n    _applyUserMessage(event: UserMessageEvent): void {\n        this.lastMessageId = event.messageId;\n        // Read raw wire fields for turn tracking (event is already camelized)\n        this.#lastTurnId = event.turnId;\n        this.#lastTurnText = event.text;\n        this.#lastTurnConfidence = event.confidence;\n        this.#lastTurnLanguage = event.language;\n        this.emit(\"user.message\", event);\n    }\n\n    /** @internal Apply eager.turn — pre-tracks turn state. */\n    _applyEagerTurn(turn: Turn): void {\n        this.lastMessageId = turn.messageId;\n        this.#lastTurnId = turn.id;\n        this.#lastTurnText = turn.text;\n        this.#lastTurnConfidence = 0;\n        this.#lastTurnLanguage = undefined;\n        this.emit(\"eager.turn\", turn);\n    }\n\n    /** @internal Apply turn.end — emits Turn with merged state. */\n    _applyTurnEnd(wireEvent: Record<string, unknown>): void {\n        const turn: Turn = {\n            id: wireEvent.turn_id as number,\n            messageId: (wireEvent.message_id as string) || this.lastMessageId || \"\",\n            text: (wireEvent.text as string) || this.#lastTurnText,\n            confidence: this.#lastTurnConfidence,\n            language: this.#lastTurnLanguage,\n            probability: wireEvent.probability as number,\n            latencyMs: wireEvent.latency_ms as number,\n        };\n        if (wireEvent.text) this.#lastTurnText = wireEvent.text as string;\n        if (wireEvent.message_id) this.lastMessageId = wireEvent.message_id as string;\n        this.emit(\"turn.end\", turn);\n    }\n\n    /** @internal Apply turn.continued — aborts all active streams. */\n    _applyTurnContinued(event: TurnContinuedEvent): void {\n        for (const stream of this.#activeStreams) {\n            stream.abort();\n        }\n        this.#activeStreams.clear();\n        this.emit(\"turn.continued\", event);\n    }\n\n    /** @internal Emit a typed event. Used by dispatch handlers. */\n    _emitWire<K extends keyof CallEvents>(event: K, ...args: Parameters<CallEvents[K]>): void {\n        this.emit(event, ...args);\n    }\n\n    /** @internal Mark call as ended. Populates messages from server data. */\n    _applyEnd(reason: string, data?: Record<string, unknown>): void {\n        this.reason = reason;\n        this.status = \"ended\";\n\n        if (data) {\n            // Prefer server's definitive messages if available\n            if (Array.isArray(data.messages) && (data.messages as any[]).length > 0) {\n                this.messages = data.messages as any;\n            }\n            if (typeof data.duration_seconds === \"number\") this.duration = data.duration_seconds as number;\n            if (typeof data.started_at === \"number\") this.startedAt = data.started_at as number;\n            if (typeof data.ended_at === \"number\") this.endedAt = data.ended_at as number;\n        }\n\n        // Cancel any pending debounced save and force a final save\n        this.#history?.flush();\n\n        // Abort all streams\n        for (const stream of this.#activeStreams) {\n            stream.abort();\n        }\n        this.#activeStreams.clear();\n        this.emit(\"ended\", reason);\n        // Defer listener cleanup so \"ended\" handlers can still interact\n        queueMicrotask(() => this.removeAllListeners());\n    }\n\n    // ─── Incremental history ─────────────────────────────────────────────\n\n    /**\n     * @internal Initialize history tracking. Called by lifecycle handler on call.started.\n     */\n    _initHistory(agentId: string, historyStore: HistoryStore): void {\n        this.#history = new CallHistoryRecorder(this, agentId, historyStore);\n        this.startedAt = Date.now() / 1000;\n        // Initial save — creates the record with status: \"active\"\n        this.#history.saveNow();\n    }\n\n    /**\n     * @internal Append a message and trigger a debounced history save.\n     * Called by speech/bot/tool handlers on confirmed events.\n     */\n    _pushMessage(msg: Record<string, unknown>): void {\n        this.messages.push(msg);\n        this.#history?.saveDebounced();\n    }\n\n    // ─── SSE streaming ──────────────────────────────────────────────────\n\n    /**\n     * Stream this call's events as Server-Sent Events to an HTTP response —\n     * headers, word buffering, keepalive pings and cleanup. See sse/call-stream.ts.\n     */\n    streamSSE(res: SSEResponse, opts?: StreamSSEOptions): void {\n        streamCallSSE(this, res, opts);\n    }\n}\n","/**\n * RingingCall — lightweight handle for an inbound call pending accept/reject.\n *\n * Created when the server sends `call.ringing` (opt-in via `ringing: true`\n * on the phone channel). Unlike `Call`, this object only has `accept()` and\n * `reject()` — no `say()`, `reply()`, `hangup()`, etc.\n *\n * If neither method is called within the server timeout (5s), the call is\n * auto-accepted and `call.started` fires as usual.\n */\n\nexport class RingingCall {\n    readonly callId: string;\n    readonly from: string;\n    readonly to: string;\n    readonly direction: \"inbound\" = \"inbound\";\n\n    #send: (data: Record<string, unknown>) => void;\n    #agentId: string;\n    #settled = false;\n\n    constructor(\n        data: { callId: string; from: string; to: string; agentId: string },\n        send: (data: Record<string, unknown>) => void,\n    ) {\n        this.callId = data.callId;\n        this.from = data.from;\n        this.to = data.to;\n        this.#agentId = data.agentId;\n        this.#send = send;\n    }\n\n    /** Whether accept() or reject() has been called. */\n    get settled(): boolean {\n        return this.#settled;\n    }\n\n    /** Accept the call — proceeds to call.started. */\n    accept(): void {\n        if (this.#settled) return;\n        this.#settled = true;\n        this.#send({\n            event: \"call.accept\",\n            agent_id: this.#agentId,\n            call_id: this.callId,\n        });\n    }\n\n    /**\n     * Reject the call — caller hears a rejection tone, call.started never fires.\n     *\n     * @param reason - `\"busy\"` (busy tone) or `\"rejected\"` (generic rejection).\n     *                 Default: `\"busy\"`.\n     */\n    reject(reason: \"busy\" | \"rejected\" = \"busy\"): void {\n        if (this.#settled) return;\n        this.#settled = true;\n        this.#send({\n            event: \"call.reject\",\n            agent_id: this.#agentId,\n            call_id: this.callId,\n            reason,\n        });\n    }\n}\n","/**\n * Wire → SDK transform utilities.\n *\n * The boundary between snake_case wire protocol and camelCase SDK types.\n * This is the ONLY place that touches wire key names.\n */\n\n/** Convert a single snake_case key to camelCase. */\nexport function snakeToCamel(s: string): string {\n    return s.replace(/_([a-z])/g, (_, c) => c.toUpperCase());\n}\n\n/** Convert a single camelCase key to snake_case. */\nexport function camelToSnake(s: string): string {\n    return s.replace(/[A-Z]/g, (c) => `_${c.toLowerCase()}`);\n}\n\n/**\n * Camelize the top-level keys of a wire event into a typed domain event.\n * Does NOT recurse — nested objects (e.g. provider configs) are pass-through.\n */\nexport function decodeEvent<T>(wire: Record<string, unknown>): T {\n    const out: Record<string, unknown> = {};\n    for (const [k, v] of Object.entries(wire)) {\n        out[snakeToCamel(k)] = v;\n    }\n    return out as T;\n}\n\n/**\n * Snakeize the top-level keys of an outgoing command.\n * Used only at the transport boundary.\n */\nexport function encodeCommand(cmd: Record<string, unknown>): Record<string, unknown> {\n    const out: Record<string, unknown> = {};\n    for (const [k, v] of Object.entries(cmd)) {\n        out[camelToSnake(k)] = v;\n    }\n    return out;\n}\n","/**\n * Lifecycle handler — call creation and teardown.\n *\n * Handles: call.started, call.ended, call.dialing, call.error, call.forwarded\n *\n * Business logic ported from agent.ts:\n *   - §7.8 Call creation from call.started wire event\n *   - call.dialing → temp Call for outbound that hasn't connected yet\n *   - call.error → PinecallError emit on agent\n *   - call.ended → _applyEnd + cleanup\n */\n\nimport type { EventHandler, DispatchContext } from \"../handler.js\";\nimport type { WireEvent } from \"../../protocol/wire.js\";\nimport { Call } from \"../../domain/call.js\";\nimport type { CallInit } from \"../../domain/call.js\";\nimport { RingingCall } from \"../../domain/ringing-call.js\";\nimport { decodeEvent } from \"../../protocol/codec.js\";\nimport { forwardCallEvents } from \"../proxy.js\";\nimport type { CallStartedEvent, CallEndedEvent } from \"../../protocol/events.js\";\n\n\nexport class LifecycleHandler implements EventHandler {\n    readonly events = [\"call.started\", \"call.ended\", \"call.updated\", \"call.dialing\", \"call.error\", \"call.forwarded\", \"call.dtmf_sent\", \"call.ringing\", \"call.rejected\"] as const;\n\n    handle(wire: WireEvent, ctx: DispatchContext): boolean {\n        const agentId = wire.agent_id;\n        if (!agentId) return false;\n\n        const agent = ctx.agent(agentId);\n        if (!agent) return false;\n\n        switch (wire.event) {\n            // The session changed under the call — today only its language,\n            // when a browser switches it mid-call. Silent by design: there is\n            // no event for an app to handle, the Call object simply tells the\n            // truth from the next turn on.\n            case \"call.updated\": {\n                const callId = wire.call_id;\n                const call = callId ? agent._getCall(callId) : undefined;\n                if (call && typeof wire.language === \"string\" && wire.language) {\n                    call._setLanguage(wire.language);\n                }\n                return true;\n            }\n            case \"call.started\": {\n                const callId = wire.call_id;\n                if (!callId) return false;\n\n                // Detect transport from call_id prefix or metadata\n                let transport: \"webrtc\" | \"phone\" | \"unknown\" = \"unknown\";\n                if (typeof wire.transport === \"string\") {\n                    transport = wire.transport as any;\n                } else if (callId.startsWith(\"wrt_\")) {\n                    transport = \"webrtc\";\n                }\n\n                // Built through the agent so a phone line hands out a LineCall\n                // (see Agent._createCall) without forking this handler.\n                const call = agent._createCall(\n                    {\n                        call_id: callId,\n                        from: (wire.from ?? \"\") as string,\n                        to: (wire.to ?? \"\") as string,\n                        direction: (wire.direction ?? \"inbound\") as \"inbound\" | \"outbound\",\n                        transport,\n                        metadata: wire.metadata as Record<string, unknown> | undefined,\n                        language: typeof wire.language === \"string\" ? wire.language : undefined,\n                        // Set by a phone line: which extension the caller\n                        // dialled, who owns the session, and — on a routed\n                        // call — the line it came from and what it heard.\n                        extension: typeof wire.extension === \"string\" ? wire.extension : null,\n                        owner: wire.owner === \"line\" || wire.owner === \"agent\" ? wire.owner : undefined,\n                        routed_from: typeof wire.routed_from === \"string\" ? wire.routed_from : undefined,\n                        line_transcript: Array.isArray(wire.line_transcript)\n                            ? (wire.line_transcript as CallInit[\"line_transcript\"])\n                            : undefined,\n                    },\n                    (data) => agent.send(data),\n                );\n\n                // Set prompt info from agent\n                call._promptsDir = (agent as any)._promptsDir ?? \"prompts\";\n\n                agent._setCall(callId, call);\n\n                // Initialize incremental history if configured\n                const historyStore = agent.getConfig().history;\n                if (historyStore?.save) {\n                    call._initHistory(agent.id, historyStore);\n                }\n\n                // Auto-restore prior conversations for returning contacts\n                if (historyStore?.findByContact && call.from) {\n                    historyStore.findByContact(call.from, 5).then((prior) => {\n                        if (!prior || prior.length === 0) return;\n                        const messages = prior\n                            .reverse()\n                            .flatMap((c) => c.messages)\n                            .filter((m) => m.role === \"user\" || m.role === \"assistant\")\n                            .slice(-20);\n                        if (messages.length > 0) {\n                            call.setHistory(messages as any).catch(() => {});\n                        }\n                    }).catch(() => {});\n                }\n\n                // Set up event forwarding: Call → Agent → Pinecall\n                forwardCallEvents(call, agent, call);\n\n                // Emit on agent\n                agent._emitWire(\"call.started\", call);\n\n                ctx.logger.info(`Call started: ${callId} (${wire.direction})`, {\n                    agent: agent.id,\n                    from: wire.from as string,\n                    to: wire.to as string,\n                });\n\n                return true;\n            }\n\n            case \"call.ended\": {\n                const callId = wire.call_id;\n                if (!callId) return false;\n\n                let call = agent._getCall(callId);\n\n                // For outbound calls that were rejected before connecting\n                // (busy, no-answer, failed), call.started never fired so\n                // there's no Call object. Create a temporary one so dial()\n                // can properly reject with the reason.\n                if (!call) {\n                    const reason = (wire.reason ?? \"unknown\") as string;\n                    const direction = (wire.direction ?? \"outbound\") as \"inbound\" | \"outbound\";\n\n                    if (direction === \"outbound\" || reason === \"busy\" || reason === \"no-answer\" || reason === \"failed\" || reason === \"canceled\") {\n                        call = new Call(\n                            {\n                                call_id: callId,\n                                from: (wire.from ?? \"\") as string,\n                                to: (wire.to ?? \"\") as string,\n                                direction,\n                                transport: \"phone\",\n                                metadata: wire.metadata as Record<string, unknown> | undefined,\n                                language: typeof wire.language === \"string\" ? wire.language : undefined,\n                            },\n                            (data) => agent.send(data),\n                        );\n                        call._applyEnd(reason, wire);\n                        agent._emitWire(\"call.ended\", call, reason);\n\n                        ctx.logger.info(`Call ended (never connected): ${callId} (${reason})`, {\n                            agent: agent.id,\n                        });\n\n                        return true;\n                    }\n\n                    return true; // Inbound already cleaned up\n                }\n\n                const reason = (wire.reason ?? \"unknown\") as string;\n                call._applyEnd(reason, wire);\n\n                agent._emitWire(\"call.ended\", call, reason);\n                agent._deleteCall(callId);\n\n                ctx.logger.info(`Call ended: ${callId} (${reason})`, {\n                    agent: agent.id,\n                    duration: wire.duration_seconds,\n                });\n\n                return true;\n            }\n\n            case \"call.dialing\": {\n                // Outbound call is being placed but hasn't connected yet\n                // Create a temporary call object so events can be attached\n                const callId = wire.call_id;\n                if (!callId || agent._hasCall(callId)) return true;\n\n                const call = new Call(\n                    {\n                        call_id: callId,\n                        from: (wire.from ?? \"\") as string,\n                        to: (wire.to ?? \"\") as string,\n                        direction: \"outbound\",\n                        transport: \"phone\",\n                    },\n                    (data) => agent.send(data),\n                );\n\n                agent._setCall(callId, call);\n                forwardCallEvents(call, agent, call);\n\n                return true;\n            }\n\n            case \"call.error\": {\n                const errorMsg = (wire.error ?? \"Unknown call error\") as string;\n                ctx.logger.error(`Call error: ${errorMsg}`, {\n                    agent: agent.id,\n                    callId: wire.call_id,\n                });\n                agent._emitWire(\"call.ended\" as any, null as any, errorMsg);\n                return true;\n            }\n\n            case \"call.forwarded\": {\n                const callId = wire.call_id;\n                if (!callId) return false;\n                const call = agent._getCall(callId);\n                if (call) {\n                    call._emitWire(\"call.forwarded\" as any, decodeEvent(wire));\n                }\n                return true;\n            }\n\n            case \"call.dtmf_sent\": {\n                const callId = wire.call_id;\n                if (!callId) return false;\n                const call = agent._getCall(callId);\n                if (call) {\n                    call._emitWire(\"call.dtmf_sent\" as any, decodeEvent(wire));\n                }\n                return true;\n            }\n\n            case \"call.ringing\": {\n                const ringingCall = new RingingCall(\n                    {\n                        callId: (wire.call_id ?? \"\") as string,\n                        from: (wire.from ?? \"\") as string,\n                        to: (wire.to ?? \"\") as string,\n                        agentId: agent.id,\n                    },\n                    (data) => agent.send(data),\n                );\n\n                agent._emitWire(\"call.ringing\", ringingCall);\n\n                ctx.logger.info(`Call ringing: ${wire.call_id} from ${wire.from}`, {\n                    agent: agent.id,\n                });\n\n                return true;\n            }\n\n            case \"call.rejected\": {\n                ctx.logger.info(`Call rejected: ${wire.call_id} (${wire.reason})`, {\n                    agent: agent.id,\n                });\n                return true;\n            }\n\n            default:\n                return false;\n        }\n    }\n}\n","/**\n * Speech handler — STT transcript events.\n *\n * Handles: speech.started, speech.ended, user.speaking, user.message\n * All events camelize + emit on call (+ agent via proxy).\n */\n\nimport type { EventHandler, DispatchContext } from \"../handler.js\";\nimport type { WireEvent } from \"../../protocol/wire.js\";\nimport { decodeEvent } from \"../../protocol/codec.js\";\nimport type {\n    SpeechStartedEvent,\n    SpeechEndedEvent,\n    UserSpeakingEvent,\n    UserMessageEvent,\n} from \"../../protocol/events.js\";\n\nexport class SpeechHandler implements EventHandler {\n    readonly events = [\"speech.started\", \"speech.ended\", \"user.speaking\", \"user.message\"] as const;\n\n    handle(wire: WireEvent, ctx: DispatchContext): boolean {\n        const agent = wire.agent_id ? ctx.agent(wire.agent_id) : null;\n        if (!agent) return false;\n\n        const callId = wire.call_id;\n        if (!callId) return false;\n\n        const call = agent._getCall(callId);\n        if (!call) return false;\n\n        switch (wire.event) {\n            case \"speech.started\":\n                call._emitWire(\"speech.started\", decodeEvent<SpeechStartedEvent>(wire));\n                return true;\n\n            case \"speech.ended\":\n                call._emitWire(\"speech.ended\", decodeEvent<SpeechEndedEvent>(wire));\n                return true;\n\n            case \"user.speaking\":\n                call._emitWire(\"user.speaking\", decodeEvent<UserSpeakingEvent>(wire));\n                return true;\n\n            case \"user.message\": {\n                const event = decodeEvent<UserMessageEvent>(wire);\n                call._applyUserMessage(event);\n                call._pushMessage({ role: \"user\", content: event.text });\n                return true;\n            }\n\n            default:\n                return false;\n        }\n    }\n}\n","/**\n * Turn handler — turn lifecycle events.\n *\n * Handles: eager.turn, turn.pause, turn.end, turn.resumed, turn.continued\n *\n * Business logic:\n *   - eager.turn: builds Turn object, calls _applyEagerTurn\n *   - turn.end: calls _applyTurnEnd (merges with last user.message state)\n *   - turn.continued: calls _applyTurnContinued (aborts active streams)\n */\n\nimport type { EventHandler, DispatchContext } from \"../handler.js\";\nimport type { WireEvent } from \"../../protocol/wire.js\";\nimport { decodeEvent } from \"../../protocol/codec.js\";\nimport type { Turn } from \"../../domain/turn.js\";\nimport type { TurnPauseEvent, TurnResumedEvent, TurnContinuedEvent } from \"../../protocol/events.js\";\n\nexport class TurnHandler implements EventHandler {\n    readonly events = [\"eager.turn\", \"turn.pause\", \"turn.end\", \"turn.resumed\", \"turn.continued\"] as const;\n\n    handle(wire: WireEvent, ctx: DispatchContext): boolean {\n        const agent = wire.agent_id ? ctx.agent(wire.agent_id) : null;\n        if (!agent) return false;\n\n        const callId = wire.call_id;\n        if (!callId) return false;\n\n        const call = agent._getCall(callId);\n        if (!call) return false;\n\n        switch (wire.event) {\n            case \"eager.turn\": {\n                const turn: Turn = {\n                    id: wire.turn_id as number,\n                    messageId: (wire.message_id ?? \"\") as string,\n                    text: (wire.text ?? \"\") as string,\n                    confidence: 0,\n                    probability: (wire.probability ?? 0) as number,\n                    latencyMs: (wire.latency_ms ?? 0) as number,\n                };\n                call._applyEagerTurn(turn);\n                return true;\n            }\n\n            case \"turn.pause\":\n                call._emitWire(\"turn.pause\", decodeEvent<TurnPauseEvent>(wire));\n                return true;\n\n            case \"turn.end\":\n                // Delegate to Call — it merges with tracked user.message state\n                call._applyTurnEnd(wire);\n                return true;\n\n            case \"turn.resumed\":\n                call._emitWire(\"turn.resumed\", decodeEvent<TurnResumedEvent>(wire));\n                return true;\n\n            case \"turn.continued\":\n                call._applyTurnContinued(decodeEvent<TurnContinuedEvent>(wire));\n                return true;\n\n            default:\n                return false;\n        }\n    }\n}\n","/**\n * Bot handler — TTS playback events.\n *\n * Handles: bot.speaking, bot.word, bot.finished, bot.interrupted,\n *          message.confirmed, reply.rejected\n *\n * All events camelize + emit on call.\n */\n\nimport type { EventHandler, DispatchContext } from \"../handler.js\";\nimport type { WireEvent } from \"../../protocol/wire.js\";\nimport { decodeEvent } from \"../../protocol/codec.js\";\nimport type {\n    BotSpeakingEvent,\n    BotWordEvent,\n    BotFinishedEvent,\n    BotInterruptedEvent,\n    MessageConfirmedEvent,\n    ReplyRejectedEvent,\n} from \"../../protocol/events.js\";\n\nexport class BotHandler implements EventHandler {\n    readonly events = [\n        \"bot.speaking\", \"bot.word\", \"bot.finished\", \"bot.interrupted\",\n        \"message.confirmed\", \"reply.rejected\", \"barge_in\",\n    ] as const;\n\n    handle(wire: WireEvent, ctx: DispatchContext): boolean {\n        const agent = wire.agent_id ? ctx.agent(wire.agent_id) : null;\n        if (!agent) return false;\n\n        const callId = wire.call_id;\n        if (!callId) return false;\n\n        const call = agent._getCall(callId);\n        if (!call) return false;\n\n        switch (wire.event) {\n            case \"bot.speaking\":\n                call._applyBotSpeaking(decodeEvent<BotSpeakingEvent>(wire));\n                return true;\n\n            case \"bot.word\":\n                call._applyBotWord(decodeEvent<BotWordEvent>(wire));\n                return true;\n\n            case \"bot.finished\":\n                call._emitWire(\"bot.finished\", decodeEvent<BotFinishedEvent>(wire));\n                call._clearBotWords();\n                return true;\n\n            case \"bot.interrupted\":\n                call._emitWire(\"bot.interrupted\", decodeEvent<BotInterruptedEvent>(wire));\n                call._clearBotWords();\n                return true;\n\n            case \"message.confirmed\": {\n                const event = decodeEvent<MessageConfirmedEvent>(wire);\n                call._emitWire(\"message.confirmed\", event);\n                if (event.text) {\n                    call._pushMessage({ role: \"assistant\", content: event.text });\n                }\n                return true;\n            }\n\n            case \"reply.rejected\":\n                call._emitWire(\"reply.rejected\", decodeEvent<ReplyRejectedEvent>(wire));\n                return true;\n\n            case \"barge_in\":\n                // barge_in is fire-and-forget, no Call-level event\n                return true;\n\n            default:\n                return false;\n        }\n    }\n}\n","/**\n * Tool handler — server-side LLM tool call events.\n *\n * Handles: llm.tool_call (non-chat only — chat tool calls handled by chat.ts)\n *\n * Business logic:\n *   - §7.6 Filter re-emissions (server may re-send; only emit once per msgId)\n *   - Camelize tool_calls → toolCalls\n *   - Auto-execute Tool objects registered on the agent\n *   - Emit on call + agent (via proxy)\n */\n\nimport type { EventHandler, DispatchContext } from \"../handler.js\";\nimport type { WireEvent } from \"../../protocol/wire.js\";\nimport type { ToolCallEvent, ToolCallItem } from \"../../protocol/events.js\";\nimport type { Agent } from \"../../domain/agent.js\";\nimport { noopLogger, type Logger } from \"../../kernel/logger.js\";\n\nexport class ToolHandler implements EventHandler {\n    readonly events = [\"llm.tool_call\"] as const;\n\n    /** Track emitted msg_ids to prevent duplicate emissions. */\n    #emittedMsgIds = new Set<string>();\n\n    handle(wire: WireEvent, ctx: DispatchContext): boolean {\n        // Chat tool calls are handled by the ChatHandler\n        if (wire.call_id && (wire.call_id as string).startsWith(\"chat-\")) {\n            return false; // Let ChatHandler handle it\n        }\n\n        const callId = wire.call_id as string;\n        if (!callId) return false;\n\n        // Resolve agent — try wire.agent_id first, then search all agents for the call\n        let agent: Agent | null = wire.agent_id\n            ? ctx.agent(wire.agent_id)\n            : null;\n\n        if (!agent) {\n            // Server didn't include agent_id (WhatsApp, legacy voice) —\n            // search all agents for one that owns this call or has tools\n            agent = this.#findAgentByCall(callId, ctx);\n        }\n        if (!agent) return false;\n\n        const call = agent._getCall(callId);\n\n        const msgId = (wire.msg_id ?? wire.message_id ?? \"\") as string;\n\n        // Deduplicate — server may re-send tool calls\n        if (msgId && this.#emittedMsgIds.has(msgId)) {\n            return true;\n        }\n        if (msgId) this.#emittedMsgIds.add(msgId);\n\n        // Transform wire tool_calls → SDK toolCalls\n        const rawToolCalls = (wire.tool_calls ?? []) as Array<Record<string, unknown>>;\n        const toolCalls: ToolCallItem[] = rawToolCalls.map(tc => ({\n            id: (tc.id ?? \"\") as string,\n            name: (tc.name ?? (tc.function as any)?.name ?? \"\") as string,\n            arguments: (tc.arguments ?? (tc.function as any)?.arguments ?? \"{}\") as string,\n        }));\n\n        const event: ToolCallEvent = {\n            event: \"llm.toolCall\",\n            callId,\n            toolCalls,\n            msgId,\n        };\n\n        // Emit event on call (so agent proxy picks it up too)\n        if (call) {\n            call._emitWire(\"llm.toolCall\", event);\n            // Push tool_calls to incremental history — unless every called tool\n            // is ephemeral, in which case the whole round is left out of history.\n            const toolList = agent._getTools();\n            const tMap = new Map(toolList.map(t => [t.name, t]));\n            const allEphemeral = toolCalls.length > 0 &&\n                toolCalls.every(tc => tMap.get(tc.name)?.ephemeral ?? false);\n            if (!allEphemeral) {\n                call._pushMessage({\n                    role: \"assistant\",\n                    tool_calls: toolCalls.map(tc => ({\n                        id: tc.id,\n                        type: \"function\",\n                        function: { name: tc.name, arguments: tc.arguments },\n                    })),\n                });\n            }\n        } else {\n            // No Call object (WhatsApp sessions) — emit directly on agent\n            agent._emitWire(\"llm.toolCall\", event, null as any);\n        }\n\n        // Auto-execute registered Tool objects\n        const tools = agent._getTools();\n        if (tools.length > 0) {\n            if (call) {\n                void autoExecuteTools(tools, event, call, ctx.logger);\n            } else {\n                // WhatsApp: build a lightweight proxy with toolResult\n                void autoExecuteTools(tools, event, {\n                    toolResult: (mId: string, results: Array<{ toolCallId: string; result: unknown; ephemeral?: boolean }>) => {\n                        ctx.send({\n                            event: \"llm.tool_result\",\n                            call_id: callId,\n                            msg_id: mId,\n                            results: results.map(r => ({\n                                tool_call_id: r.toolCallId,\n                                result: r.result,\n                                ...(r.ephemeral ? { ephemeral: true } : {}),\n                            })),\n                        });\n                    },\n                } as any, ctx.logger);\n            }\n        }\n\n        return true;\n    }\n\n    /** Find the agent that owns the given call, or the first agent with tools. */\n    #findAgentByCall(callId: string, ctx: DispatchContext): Agent | null {\n        const agents = ctx.allAgents();\n\n        // First pass: find agent that owns the call\n        for (const a of agents) {\n            if (a._getCall(callId)) return a;\n        }\n\n        // Second pass: find agent with tools (for WhatsApp where no Call object exists)\n        for (const a of agents) {\n            if (a._getTools().length > 0) return a;\n        }\n\n        return null;\n    }\n\n}\n\n/**\n * Auto-execute registered Tool objects for a tool-call event and send the\n * results back via `call.toolResult`. Shared by the voice/WhatsApp ToolHandler\n * and the ChatHandler (chat tool calls auto-execute the same way).\n *\n * `log` is where the per-call trace goes. This is LIBRARY code running inside\n * every consumer's process, so it must never write to console on its own — the\n * caller passes ctx.logger and decides whether debug lines are visible.\n */\nexport async function autoExecuteTools(\n    tools: Array<{ name: string; schema: { parse: (input: unknown) => any }; execute: (args: any, call: any) => unknown | Promise<unknown>; ephemeral?: boolean; noFollowup?: boolean }>,\n    event: ToolCallEvent,\n    call: { toolResult: (msgId: string, results: Array<{ toolCallId: string; result: unknown; ephemeral?: boolean; noFollowup?: boolean }>) => void },\n    log: Logger = noopLogger,\n): Promise<void> {\n    const toolMap = new Map(tools.map(t => [t.name, t]));\n    const names = event.toolCalls.map(tc => tc.name);\n    log.debug(`tool_call [${names.join(\", \")}] msgId=${event.msgId.slice(0, 12)}`);\n\n    const results = await Promise.all(\n        event.toolCalls.map(async (tc) => {\n            const t = toolMap.get(tc.name);\n            if (!t) {\n                log.debug(`  ${tc.name} → unknown tool`);\n                return { toolCallId: tc.id, result: { error: `Unknown tool: ${tc.name}` }, ephemeral: false, noFollowup: false };\n            }\n\n            const ephemeral = t.ephemeral ?? false;\n            const noFollowup = t.noFollowup ?? false;\n            try {\n                const args = t.schema.parse(JSON.parse(tc.arguments));\n                log.debug(`  ${tc.name}(${JSON.stringify(args).slice(0, 120)})`);\n                const result = await t.execute(args, call as any);\n                const preview = JSON.stringify(result).slice(0, 200);\n                log.debug(`  ${tc.name} → ${preview}${ephemeral ? \" (ephemeral)\" : \"\"}${noFollowup ? \" (noFollowup)\" : \"\"}`);\n                return { toolCallId: tc.id, result, ephemeral, noFollowup };\n            } catch (err: any) {\n                log.debug(`  ${tc.name} → error: ${err.message ?? err}`);\n                return { toolCallId: tc.id, result: { error: err.message ?? String(err) }, ephemeral, noFollowup };\n            }\n        }),\n    );\n\n    call.toolResult(event.msgId, results);\n\n    // Push tool results to incremental history — skip ephemeral ones, they are\n    // never persisted (the server drops them from the LLM context too).\n    if (\"_pushMessage\" in call) {\n        for (const r of results) {\n            if (r.ephemeral) continue;\n            (call as any)._pushMessage({\n                role: \"tool\",\n                tool_call_id: r.toolCallId,\n                content: typeof r.result === \"string\" ? r.result : JSON.stringify(r.result),\n            });\n        }\n    }\n}\n\n","/**\n * Skill handler — server-side skill activation events.\n *\n * Handles: skill.loaded, skill.unloaded\n *\n * The server resolves loadSkill/unloadSkill natively and notifies the SDK so it\n * can track which skills are active on a call and surface the change as events\n * on the call + agent (via proxy).\n */\n\nimport type { EventHandler, DispatchContext } from \"../handler.js\";\nimport type { WireEvent } from \"../../protocol/wire.js\";\nimport type { Agent } from \"../../domain/agent.js\";\nimport type { SkillEvent } from \"../../domain/call.js\";\n\nexport class SkillHandler implements EventHandler {\n    readonly events = [\"skill.loaded\", \"skill.unloaded\"] as const;\n\n    handle(wire: WireEvent, ctx: DispatchContext): boolean {\n        const callId = (wire.call_id ?? \"\") as string;\n\n        // Resolve the owning agent — by agent_id, else by the call it belongs to.\n        let agent: Agent | null = wire.agent_id ? ctx.agent(wire.agent_id) : null;\n        if (!agent && callId) {\n            for (const a of ctx.allAgents()) {\n                if (a._getCall(callId)) { agent = a; break; }\n            }\n        }\n        if (!agent) return false;\n\n        const event: SkillEvent = {\n            skill: (wire.skill ?? \"\") as string,\n            by: ((wire.by as string) === \"manual\" ? \"manual\" : \"model\"),\n        };\n        const loaded = wire.event === \"skill.loaded\";\n\n        const call = callId ? agent._getCall(callId) : null;\n        if (call) {\n            call._setSkillActive(event.skill, loaded);\n            // Emits on the call and, via the proxy, on the agent (with the call).\n            call._emitWire(wire.event as \"skill.loaded\" | \"skill.unloaded\", event);\n        } else {\n            agent._emitWire(wire.event as \"skill.loaded\" | \"skill.unloaded\", event, null as any);\n        }\n        return true;\n    }\n}\n","/**\n * Session handler — session lifecycle, config, and human-in-the-loop events.\n *\n * Handles: session.idle_warning, session.timeout, session.configured,\n *          session.paused, session.resumed,\n *          session_config_updated, config_updated, phone_added, phone_removed\n */\n\nimport type { EventHandler, DispatchContext } from \"../handler.js\";\nimport type { WireEvent } from \"../../protocol/wire.js\";\nimport { decodeEvent } from \"../../protocol/codec.js\";\nimport type { SessionTimeoutEvent } from \"../../protocol/events.js\";\n\nexport class SessionHandler implements EventHandler {\n    readonly events = [\n        \"session.idle_warning\",\n        \"session.timeout\",\n        \"session.configured\",\n        \"session.paused\",\n        \"session.resumed\",\n        \"session.sent\",\n        \"session_config_updated\",\n        \"config_updated\",\n        \"phone_added\",\n        \"phone_removed\",\n    ] as const;\n\n    handle(wire: WireEvent, ctx: DispatchContext): boolean {\n        const agent = wire.agent_id ? ctx.agent(wire.agent_id) : null;\n\n        switch (wire.event) {\n            case \"session.idle_warning\": {\n                if (!agent) return false;\n                const callId = wire.call_id as string;\n                if (!callId) return false;\n                const call = agent._getCall(callId);\n                if (call) {\n                    call._emitWire(\"session.idleWarning\" as any, decodeEvent(wire));\n                    agent._emitWire(\"session.idleWarning\", decodeEvent(wire), call);\n                }\n                return true;\n            }\n\n            case \"session.timeout\": {\n                if (!agent) return false;\n                const callId = wire.call_id as string;\n                if (!callId) return false;\n                const call = agent._getCall(callId);\n                if (call) {\n                    call._emitWire(\"session.timeout\", decodeEvent<SessionTimeoutEvent>(wire));\n                }\n                return true;\n            }\n\n            case \"session.configured\":\n            case \"session.sent\":\n            case \"session_config_updated\":\n            case \"config_updated\":\n            case \"phone_added\":\n            case \"phone_removed\":\n                // Acknowledgments — no action needed\n                return true;\n\n            case \"session.paused\": {\n                if (!agent) return false;\n                agent._emitWire(\"session.paused\", {\n                    sessionId: (wire.session_id as string) || undefined,\n                    contact: (wire.contact as string) || undefined,\n                });\n                return true;\n            }\n\n            case \"session.resumed\": {\n                if (!agent) return false;\n                agent._emitWire(\"session.resumed\", {\n                    sessionId: (wire.session_id as string) || undefined,\n                    contact: (wire.contact as string) || undefined,\n                });\n                return true;\n            }\n\n            default:\n                return false;\n        }\n    }\n}\n","/**\n * Chat handler — server-side LLM chat events.\n *\n * Handles: llm.chat.started, llm.chat.chunk, llm.chat.ended,\n *          llm.chat.error, llm.tool_call (with chat- prefix)\n *\n * Business logic:\n *   - Creates a Call with transport=\"chat\" on llm.chat.started\n *   - Emits call.started (same as voice/WA) so the developer's universal\n *     call.started handler runs setPromptVars, addContext, etc.\n *   - Fallback lazy Call creation on llm.chat.chunk if chat.started was missed\n */\n\nimport type { EventHandler, DispatchContext } from \"../handler.js\";\nimport type { WireEvent } from \"../../protocol/wire.js\";\nimport { Call } from \"../../domain/call.js\";\nimport { decodeEvent } from \"../../protocol/codec.js\";\nimport { forwardCallEvents } from \"../proxy.js\";\nimport { autoExecuteTools } from \"./tool.js\";\nimport type { ToolCallItem } from \"../../protocol/events.js\";\n\n\n\nexport class ChatHandler implements EventHandler {\n    readonly events = [\n        \"llm.chat.started\",\n        \"llm.chat.chunk\",\n        \"llm.chat.ended\",\n        \"llm.chat.error\",\n        \"llm.tool_call\",\n        \"chat.message\",\n        \"chat.response\",\n    ] as const;\n\n    handle(wire: WireEvent, ctx: DispatchContext): boolean {\n        // Only handle chat-prefixed call_ids for llm.tool_call\n        if (wire.event === \"llm.tool_call\") {\n            const callId = wire.call_id as string;\n            if (!callId || !callId.startsWith(\"chat-\")) return false;\n        }\n\n        const agent = wire.agent_id ? ctx.agent(wire.agent_id) : null;\n        if (!agent) return false;\n\n        const callId = wire.call_id as string;\n        if (!callId) return false;\n\n        switch (wire.event) {\n            case \"llm.chat.started\": {\n                const call = new Call(\n                    {\n                        call_id: callId,\n                        from: \"chat\",\n                        to: agent.id,\n                        direction: \"inbound\",\n                        transport: \"chat\" as any,\n                        // Sealed session metadata (companyId, userId, …) from the chat token.\n                        metadata: wire.metadata as Record<string, unknown> | undefined,\n                        language: typeof wire.language === \"string\" ? wire.language : undefined,\n                    },\n                    (data) => agent.send(data),\n                );\n\n                agent._setCall(callId, call);\n\n                // Initialize incremental history (parity with voice in\n                // lifecycle.ts). The save on llm.chat.ended carries the full\n                // transcript; this initial save just creates the active record.\n                const historyStore = agent.getConfig().history;\n                if (historyStore?.save) {\n                    call._initHistory(agent.id, historyStore);\n                }\n\n                // Auto-restore prior conversations. Chat keys on\n                // call.metadata.userId (call.from is always \"chat\"), unlike\n                // voice/WA which key on call.from.\n                const contactId = call.metadata?.userId ? String(call.metadata.userId) : \"\";\n                if (historyStore?.findByContact && contactId) {\n                    historyStore.findByContact(contactId, 5).then((prior) => {\n                        if (!prior || prior.length === 0) return;\n                        const messages = prior\n                            .reverse()\n                            .flatMap((c) => c.messages)\n                            .filter((m) => m.role === \"user\" || m.role === \"assistant\")\n                            .slice(-20);\n                        if (messages.length > 0) {\n                            call.setHistory(messages as any).catch(() => {});\n                        }\n                    }).catch(() => {});\n                }\n\n                forwardCallEvents(call, agent, call);\n\n                // Emit chat.started — the entry point for chat sessions\n                agent._emitWire(\"chat.started\" as any, call);\n\n                return true;\n            }\n\n            case \"llm.chat.chunk\": {\n                // Lazy Call creation if chat.started was missed\n                let call = agent._getCall(callId);\n                if (!call) {\n                    call = new Call(\n                        {\n                            call_id: callId,\n                            from: \"chat\",\n                            to: agent.id,\n                            direction: \"inbound\",\n                            transport: \"chat\" as any,\n                            metadata: wire.metadata as Record<string, unknown> | undefined,\n                            language: typeof wire.language === \"string\" ? wire.language : undefined,\n                        },\n                        (data) => agent.send(data),\n                    );\n                    agent._setCall(callId, call);\n                    forwardCallEvents(call, agent, call);\n                    agent._emitWire(\"chat.started\" as any, call);\n                }\n\n                // Emit as bot.speaking for consistency\n                call._emitWire(\"bot.speaking\", {\n                    event: \"bot.speaking\",\n                    callId,\n                    messageId: (wire.message_id ?? \"\") as string,\n                    text: (wire.token ?? wire.text ?? \"\") as string,\n                });\n\n                return true;\n            }\n\n            case \"llm.chat.ended\": {\n                const call = agent._getCall(callId);\n                if (call) {\n                    call._applyEnd(\"chat_completed\", wire);\n                    agent._emitWire(\"call.ended\", call, \"chat_completed\");\n                    agent._deleteCall(callId);\n                }\n                return true;\n            }\n\n            case \"llm.chat.error\": {\n                const call = agent._getCall(callId);\n                if (call) {\n                    call._applyEnd(\"chat_error\", wire);\n                    agent._emitWire(\"call.ended\", call, \"chat_error\");\n                    agent._deleteCall(callId);\n                }\n                return true;\n            }\n\n            case \"chat.message\": {\n                const call = agent._getCall(callId);\n                if (call) {\n                    const text = (wire.text ?? \"\") as string;\n                    call._pushMessage({ role: \"user\", content: text });\n                    // A chat message carries no STT metadata — there is no\n                    // recogniser and no turn timer — so the numeric fields the\n                    // voice path fills are neutral here rather than absent:\n                    // the event's TYPE is the contract every listener reads,\n                    // and a handler that logs `confidence` should not crash on\n                    // a channel that has none.\n                    call._emitWire(\"user.message\", {\n                        event: \"user.message\",\n                        callId,\n                        messageId: (wire.message_id ?? \"\") as string,\n                        text,\n                        confidence: 1,\n                        turnId: 0,\n                    });\n                }\n                return true;\n            }\n\n            case \"chat.response\": {\n                const call = agent._getCall(callId);\n                if (call) {\n                    const text = (wire.text ?? \"\") as string;\n                    call._pushMessage({ role: \"assistant\", content: text });\n                    call._emitWire(\"bot.speaking\", { event: \"bot.speaking\", callId, messageId: \"\", text });\n                }\n                return true;\n            }\n\n            case \"llm.tool_call\": {\n                let call = agent._getCall(callId);\n                if (!call) {\n                    // Lazy creation for tool calls that arrive before chat.started\n                    call = new Call(\n                        {\n                            call_id: callId,\n                            from: \"chat\",\n                            to: agent.id,\n                            direction: \"inbound\",\n                            transport: \"chat\" as any,\n                            metadata: wire.metadata as Record<string, unknown> | undefined,\n                            language: typeof wire.language === \"string\" ? wire.language : undefined,\n                        },\n                        (data) => agent.send(data),\n                    );\n                    agent._setCall(callId, call);\n                    forwardCallEvents(call, agent, call);\n                    agent._emitWire(\"call.started\", call);\n                }\n\n                const rawToolCalls = (wire.tool_calls ?? []) as Array<Record<string, unknown>>;\n                const toolCalls: ToolCallItem[] = rawToolCalls.map(tc => ({\n                    id: (tc.id ?? \"\") as string,\n                    name: (tc.name ?? (tc.function as any)?.name ?? \"\") as string,\n                    arguments: (tc.arguments ?? (tc.function as any)?.arguments ?? \"{}\") as string,\n                }));\n\n                const toolEvent = {\n                    event: \"llm.toolCall\" as const,\n                    callId,\n                    toolCalls,\n                    msgId: (wire.msg_id ?? \"\") as string,\n                };\n                call._emitWire(\"llm.toolCall\", toolEvent);\n\n                // Auto-execute registered tools (chat does NOT go through ToolHandler).\n                // Without this, chat tool calls never get a result → server times out.\n                const tools = agent._getTools();\n                if (tools.length > 0) void autoExecuteTools(tools, toolEvent, call, ctx.logger);\n\n                return true;\n            }\n\n            default:\n                return false;\n        }\n    }\n}\n","/**\n * WhatsAppSession — a session handle passed to `whatsapp.sessionStarted`.\n *\n * Provides history injection methods (setHistory, addHistory, addContext, etc.)\n * that work identically to the Call equivalents, allowing WhatsApp conversations\n * to restore prior context on reconnection.\n *\n * @example\n * ```ts\n * agent.on(\"whatsapp.sessionStarted\", async (session) => {\n *     const prior = await history.findByContact(session.contactPhone, 1);\n *     if (prior.length > 0) {\n *         await session.setHistory(prior[0].messages);\n *     }\n * });\n * ```\n */\n\nimport { Requester } from \"../kernel/requester.js\";\n\nexport interface WhatsAppSessionEvent {\n    sessionId: string;\n    agentId: string;\n    contactPhone: string;\n    contactName: string;\n}\n\ntype SendFn = (payload: Record<string, unknown>) => void;\n\nexport class WhatsAppSession {\n    /** Session ID (e.g. `\"wa-70bebcaf5817\"`). */\n    readonly id: string;\n    /** Contact phone number. */\n    readonly contactPhone: string;\n    /** Contact display name. */\n    readonly contactName: string;\n    /** Agent ID this session belongs to. */\n    readonly agentId: string;\n\n    /** @internal The request/response machine — see kernel/requester.ts. */\n    readonly #requester: Requester;\n\n    /** @internal Created by the WhatsApp dispatch handler. */\n    constructor(event: WhatsAppSessionEvent, send: SendFn) {\n        this.id = event.sessionId;\n        this.contactPhone = event.contactPhone;\n        this.contactName = event.contactName;\n        this.agentId = event.agentId;\n        this.#requester = new Requester({\n            send,\n            scopeId: this.id,\n            scopeLabel: `WhatsApp session ${this.id}`,\n        });\n    }\n\n    // ── History manipulation ─────────────────────────────────────────────\n\n    /** Get the current LLM conversation history from the server. */\n    getHistory(): Promise<Array<Record<string, unknown>>> {\n        return Requester.handled(\n            this.#requester.request(\"history.get\", \"history.data\")\n                .then((res) => (res.messages ?? []) as Array<Record<string, unknown>>),\n        );\n    }\n\n    /** Inject messages into the server-side LLM history. */\n    addHistory(messages: Array<{ role: string; content: string }>): Promise<void> {\n        return Requester.handled(\n            this.#requester.request(\"history.add\", \"history.updated\", { messages }).then(() => {}),\n        );\n    }\n\n    /** Replace the entire server-side LLM history. */\n    setHistory(messages: Array<{ role: string; content: string }>): Promise<void> {\n        return Requester.handled(\n            this.#requester.request(\"history.set\", \"history.updated\", { messages }).then(() => {}),\n        );\n    }\n\n    /** Clear all messages from the server-side LLM history. */\n    clearHistory(): Promise<void> {\n        return Requester.handled(\n            this.#requester.request(\"history.clear\", \"history.updated\").then(() => {}),\n        );\n    }\n\n    // ── Prompt manipulation ──────────────────────────────────────────────\n\n    /** Replace the system prompt for this session. */\n    setPrompt(text: string): Promise<void> {\n        return Requester.handled(\n            this.#requester.request(\"history.set_instructions\", \"history.updated\", { prompt: text })\n                .then(() => {}),\n        );\n    }\n\n    /** Set `{{variable}}` values in the prompt template. */\n    setPromptVars(vars: Record<string, string>): Promise<void> {\n        return Requester.handled(\n            this.#requester.request(\"history.set_vars\", \"history.updated\", { vars }).then(() => {}),\n        );\n    }\n\n    /** Append context after the system prompt. */\n    addContext(text: string): Promise<void> {\n        return Requester.handled(\n            this.#requester.request(\"history.add_context\", \"history.updated\", { text }).then(() => {}),\n        );\n    }\n\n    // ── Internal ─────────────────────────────────────────────────────────\n\n    /** @internal Resolve a pending history request/response promise. */\n    _applyHistoryResponse(\n        eventType: string,\n        data: Record<string, unknown>,\n    ): boolean {\n        return this.#requester.applyResponse(eventType, data);\n    }\n}\n","/**\n * WhatsApp handler — WhatsApp-specific events.\n *\n * Handles: whatsapp.message, whatsapp.response, whatsapp.status,\n *          whatsapp.session_started, whatsapp.session_ended\n *\n * On session_started, creates a WhatsAppSession object with history methods\n * and emits it as the event argument (like Call for voice calls).\n * Messages are saved incrementally via HistoryStore.\n * whatsapp.session_ended triggers the final save with status: \"ended\".\n */\n\nimport type { EventHandler, DispatchContext } from \"../handler.js\";\nimport type { WireEvent } from \"../../protocol/wire.js\";\nimport type { ConversationRecord, HistoryStore } from \"../../history.js\";\nimport { WhatsAppSession } from \"../../domain/wa-session.js\";\nimport { Call } from \"../../domain/call.js\";\nimport { decodeEvent } from \"../../protocol/codec.js\";\nimport { forwardCallEvents } from \"../proxy.js\";\n\n/** In-memory session tracker for incremental WhatsApp saves. */\ninterface WaSession {\n    sessionId: string;\n    agentId: string;\n    contactPhone: string;\n    contactName: string;\n    startedAt: number;\n    messages: Array<Record<string, unknown>>;\n    saveTimer?: ReturnType<typeof setTimeout>;\n    /** The WhatsAppSession instance exposed to userland. */\n    handle?: WhatsAppSession;\n}\n\nconst DEBOUNCE_MS = 200;\n\nexport class WhatsAppHandler implements EventHandler {\n    readonly events = [\n        \"whatsapp.message\",\n        \"whatsapp.response\",\n        \"whatsapp.status\",\n        \"whatsapp.session_started\",\n        \"whatsapp.session_ended\",\n    ] as const;\n\n    /** Active sessions keyed by sessionId. */\n    #sessions = new Map<string, WaSession>();\n\n    /** @internal Get a WhatsAppSession handle by ID. Used by HistoryHandler. */\n    getSession(sessionId: string): WhatsAppSession | undefined {\n        return this.#sessions.get(sessionId)?.handle;\n    }\n\n    handle(wire: WireEvent, ctx: DispatchContext): boolean {\n        let agent = wire.agent_id ? ctx.agent(wire.agent_id) : null;\n\n        // Server may omit agent_id for WhatsApp events — find the agent\n        if (!agent) {\n            const agents = ctx.allAgents();\n            for (const a of agents) {\n                const channels = a._getChannels();\n                for (const [, ch] of channels) {\n                    if (ch.type === \"whatsapp\") { agent = a; break; }\n                }\n                if (agent) break;\n            }\n        }\n        if (!agent) return false;\n\n        const historyStore = agent.getConfig().history;\n        const sessionId = (wire.session_id ?? \"\") as string;\n\n        switch (wire.event) {\n            case \"whatsapp.session_started\": {\n                ctx.logger.debug(`[wa] session_started session=${sessionId} agent=${agent.id} phone=${wire.contact_phone}`);\n                // Create the WaSession tracker\n                const waSession: WaSession = {\n                    sessionId,\n                    agentId: agent.id,\n                    contactPhone: (wire.contact_phone ?? \"\") as string,\n                    contactName: (wire.contact_name ?? \"\") as string,\n                    startedAt: Date.now() / 1000,\n                    messages: [],\n                };\n\n                // Create the public WhatsAppSession handle with history methods\n                const sendFn = (data: Record<string, unknown>) => agent!._send(data);\n                waSession.handle = new WhatsAppSession(\n                    {\n                        sessionId,\n                        agentId: agent.id,\n                        contactPhone: waSession.contactPhone,\n                        contactName: waSession.contactName,\n                    },\n                    sendFn,\n                );\n\n                this.#sessions.set(sessionId, waSession);\n\n                // Initial save (active status)\n                if (historyStore?.save) {\n                    this.#saveNow(waSession, historyStore, \"active\");\n                }\n\n                // Auto-restore prior conversation history (fire & forget)\n                if (historyStore?.findByContact) {\n                    const handle = waSession.handle!;\n                    const phone = waSession.contactPhone;\n                    historyStore.findByContact(phone, 5).then((prior) => {\n                        if (!prior || prior.length === 0) return;\n                        const messages = prior\n                            .reverse()\n                            .flatMap((c) => c.messages)\n                            .filter((m) => m.role === \"user\" || m.role === \"assistant\")\n                            .slice(-20);\n                        if (messages.length > 0) {\n                            handle.setHistory(messages as any).catch(() => {});\n                        }\n                    }).catch(() => {});\n                }\n\n                // Create a Call object for universal call.started handling.\n                // This lets developers write ONE call.started handler for all\n                // transports (voice, chat, whatsapp) with setPromptVars, addContext, etc.\n                const call = new Call(\n                    {\n                        call_id: sessionId,\n                        from: waSession.contactPhone,\n                        to: agent.id,\n                        direction: \"inbound\",\n                        transport: \"whatsapp\",\n                    },\n                    sendFn,\n                );\n                agent._setCall(sessionId, call);\n                forwardCallEvents(call, agent, call);\n\n                ctx.logger.debug(`[wa] session ready session=${sessionId} agent=${agent.id}`);\n\n                // Emit whatsapp.started — the single entry point for WA sessions\n                agent._emitWire(\"whatsapp.started\" as any, call, waSession.handle as any);\n                return true;\n            }\n\n            case \"whatsapp.message\": {\n                ctx.logger.debug(`[wa] message session=${sessionId} text=\"${(wire.text ?? \"\").toString().slice(0, 50)}\"`);\n                const session = this.#sessions.get(sessionId);\n                if (session && historyStore?.save) {\n                    const text = (wire.text ?? \"\") as string;\n                    if (text) {\n                        session.messages.push({ role: \"user\", content: text });\n                        this.#saveDebounced(session, historyStore);\n                    }\n                }\n                break;\n            }\n\n            case \"whatsapp.response\": {\n                const session = this.#sessions.get(sessionId);\n                if (session && historyStore?.save) {\n                    const text = (wire.text ?? \"\") as string;\n                    const source = (wire.source ?? undefined) as string | undefined;\n                    if (text) {\n                        const msg: Record<string, unknown> = { role: \"assistant\", content: text };\n                        if (source) msg.source = source; // \"human\" for operator messages\n                        session.messages.push(msg);\n                        this.#saveDebounced(session, historyStore);\n                    }\n                }\n                break;\n            }\n\n            case \"whatsapp.session_ended\": {\n                const session = this.#sessions.get(sessionId);\n                if (historyStore?.save) {\n                    // Use server's definitive data if we have it\n                    const serverTranscript = wire.transcript as Array<{ role: string; content: string }> | undefined;\n                    const serverMessages = wire.messages as Array<Record<string, unknown>> | undefined;\n\n                    // Build final record\n                    const messages = (serverMessages && serverMessages.length > 0)\n                        ? serverMessages\n                        : session?.messages ?? [];\n\n                    const record: ConversationRecord = {\n                        callId: sessionId,\n                        agentId: agent.id,\n                        channel: \"whatsapp\",\n                        direction: \"inbound\",\n                        from: (wire.contact_phone ?? session?.contactPhone ?? \"\") as string,\n                        to: agent.id,\n                        startedAt: session?.startedAt ?? (wire.started_at ?? 0) as number,\n                        endedAt: (wire.ended_at ?? Date.now() / 1000) as number,\n                        duration: (wire.duration ?? 0) as number,\n                        reason: (wire.reason ?? \"unknown\") as string,\n                        status: \"ended\",\n                        transcript: serverTranscript ?? messages\n                            .filter(m => (m.role === \"user\" || m.role === \"assistant\") && m.content)\n                            .map(m => ({ role: m.role as string, content: m.content as string })),\n                        messages,\n                        metadata: {\n                            contactName: wire.contact_name ?? session?.contactName,\n                            messageCount: wire.message_count ?? messages.length,\n                        },\n                    };\n\n                    historyStore.save(record).catch((err) => {\n                        ctx.logger.error(`WhatsApp history save failed: ${err}`, {\n                            agent: agent!.id, sessionId,\n                        });\n                    });\n                }\n\n                // Clean up\n                if (session?.saveTimer) clearTimeout(session.saveTimer);\n                this.#sessions.delete(sessionId);\n                break;\n            }\n        }\n\n        // Normalize wire event name → SDK camelCase\n        const sdkEvent = wire.event === \"whatsapp.session_ended\"\n            ? \"whatsapp.sessionEnded\"\n            : wire.event;\n        agent._emitWire(sdkEvent as any, decodeEvent(wire));\n        return true;\n    }\n\n    // ── Save helpers ─────────────────────────────────────────────────────\n\n    #saveDebounced(session: WaSession, store: HistoryStore): void {\n        if (session.saveTimer) clearTimeout(session.saveTimer);\n        session.saveTimer = setTimeout(() => {\n            this.#saveNow(session, store, \"active\");\n        }, DEBOUNCE_MS);\n    }\n\n    #saveNow(session: WaSession, store: HistoryStore, status: \"active\" | \"ended\"): void {\n        const record: ConversationRecord = {\n            callId: session.sessionId,\n            agentId: session.agentId,\n            channel: \"whatsapp\",\n            direction: \"inbound\",\n            from: session.contactPhone,\n            to: session.agentId,\n            startedAt: session.startedAt,\n            endedAt: 0,\n            duration: 0,\n            reason: \"\",\n            status,\n            transcript: session.messages\n                .filter(m => (m.role === \"user\" || m.role === \"assistant\") && m.content)\n                .map(m => ({ role: m.role as string, content: m.content as string })),\n            messages: session.messages,\n            metadata: {\n                contactName: session.contactName,\n                messageCount: session.messages.length,\n            },\n        };\n\n        store.save(record).catch(() => { /* silently ignore */ });\n    }\n}\n","/**\n * History handler — server-side conversation history events.\n *\n * Handles: history.data, history.updated\n *\n * Business logic:\n *   - §7.4 Request/response correlation via Call._applyHistoryResponse\n *   - Also routes to WhatsAppSession for wa- prefixed call_ids\n *\n * Routing note — this is why `await call.setPromptVars()` used to hang forever:\n * the server sends these acks WITHOUT an `agent_id`, and the lookup keyed on\n * one, so every ack was dropped before it reached the pending promise. Not just\n * setPromptVars: getHistory, setHistory, clearHistory, setPrompt and addContext\n * all awaited an event that could never arrive. `call_id` identifies the call\n * unambiguously across every agent on this socket, so resolve by that whenever\n * `agent_id` is absent — which also makes a current SDK work against a server\n * that hasn't been upgraded yet.\n */\n\nimport type { EventHandler, DispatchContext } from \"../handler.js\";\nimport type { WireEvent } from \"../../protocol/wire.js\";\n\nexport class HistoryHandler implements EventHandler {\n    readonly events = [\"history.data\", \"history.updated\"] as const;\n\n    handle(wire: WireEvent, ctx: DispatchContext): boolean {\n        const callId = wire.call_id as string;\n        if (!callId) return false;\n\n        // Preferred: the agent the server named. Fallback: whichever agent on\n        // this client owns the call.\n        const named = wire.agent_id ? ctx.agent(wire.agent_id) : null;\n        const candidates = named ? [named] : ctx.allAgents();\n\n        for (const agent of candidates) {\n            const call = agent._getCall(callId);\n            if (call && call._applyHistoryResponse(wire.event, wire)) return true;\n        }\n\n        // WhatsApp sessions (call_id starts with \"wa-\")\n        if (callId.startsWith(\"wa-\")) {\n            const waSession = ctx.whatsappSession(callId);\n            if (waSession) {\n                return waSession._applyHistoryResponse(wire.event, wire);\n            }\n        }\n\n        return false;\n    }\n}\n","/**\n * System handler — heartbeat and connection maintenance.\n *\n * Handles: ping (server-initiated)\n * Responds with pong.\n */\n\nimport type { EventHandler, DispatchContext } from \"../handler.js\";\nimport type { WireEvent } from \"../../protocol/wire.js\";\n\nexport class SystemHandler implements EventHandler {\n    readonly events = [\"ping\"] as const;\n\n    handle(wire: WireEvent, ctx: DispatchContext): boolean {\n        if (wire.event === \"ping\") {\n            ctx.send({ event: \"pong\" });\n            return true;\n        }\n        return false;\n    }\n}\n","/**\n * Fallback handler — catches unmatched events.\n *\n * Handles: any event with a call_id that wasn't matched by a specific handler.\n * Includes hold/mute events and WebRTC auto-create logic.\n *\n * Business logic:\n *   - §7.8 Auto-create Call for WebRTC (wrt_ prefix)\n *   - Hold/mute events emit on existing call\n *   - llm.* events route to agent\n */\n\nimport type { EventHandler, DispatchContext } from \"../handler.js\";\nimport type { WireEvent } from \"../../protocol/wire.js\";\nimport { Call } from \"../../domain/call.js\";\nimport { decodeEvent } from \"../../protocol/codec.js\";\nimport { forwardCallEvents } from \"../proxy.js\";\n\nexport class FallbackHandler implements EventHandler {\n    // Wildcard — matches anything not handled above\n    readonly events = [\"*\", \"call.held\", \"call.unheld\", \"call.muted\", \"call.unmuted\"] as const;\n\n    handle(wire: WireEvent, ctx: DispatchContext): boolean {\n        // Hold/mute events\n        if (wire.event === \"call.held\" || wire.event === \"call.unheld\" ||\n            wire.event === \"call.muted\" || wire.event === \"call.unmuted\") {\n            return this.#handleHoldMute(wire, ctx);\n        }\n\n        // For unmatched events with an agent_id and call_id, try to route\n        const agent = wire.agent_id ? ctx.agent(wire.agent_id) : null;\n        if (!agent) return false;\n\n        const callId = wire.call_id as string;\n        if (!callId) {\n            // Agent-level event with no call — emit as raw on agent\n            if (wire.event.startsWith(\"llm.\")) {\n                agent._emitWire(wire.event as any, decodeEvent(wire));\n                return true;\n            }\n            return false;\n        }\n\n        let call = agent._getCall(callId);\n\n        // Auto-create for WebRTC calls (wrt_ prefix) that arrive before call.started\n        if (!call && callId.startsWith(\"wrt_\")) {\n            call = new Call(\n                {\n                    call_id: callId,\n                    from: \"webrtc\",\n                    to: agent.id,\n                    direction: \"inbound\",\n                    transport: \"webrtc\",\n                },\n                (data) => agent.send(data),\n            );\n            agent._setCall(callId, call);\n            forwardCallEvents(call, agent, call);\n            agent._emitWire(\"call.started\", call);\n        }\n\n        if (call) {\n            // Route unmatched events to the call\n            call._emitWire(wire.event as any, decodeEvent(wire));\n            return true;\n        }\n\n        return false;\n    }\n\n    #handleHoldMute(wire: WireEvent, ctx: DispatchContext): boolean {\n        const agent = wire.agent_id ? ctx.agent(wire.agent_id) : null;\n        if (!agent) return false;\n\n        const callId = wire.call_id as string;\n        if (!callId) return false;\n\n        const call = agent._getCall(callId);\n        if (!call) return false;\n\n        switch (wire.event) {\n            case \"call.held\":\n                call._emitWire(\"call.held\");\n                return true;\n            case \"call.unheld\":\n                call._emitWire(\"call.unheld\");\n                return true;\n            case \"call.muted\":\n                call._emitWire(\"call.muted\");\n                return true;\n            case \"call.unmuted\":\n                call._emitWire(\"call.unmuted\", (wire.muted_transcript ?? null) as string | null);\n                return true;\n            default:\n                return false;\n        }\n    }\n}\n","/**\n * Pre-LLM handler — the app's half of the pre-turn barrier.\n *\n * Handles: llm.before, llm.preparing_timeout\n *\n * `llm.before` means \"I am about to generate, and I am holding the turn open\n * for you\". The developer's `call.preparing` handler runs, and the moment it\n * settles we answer `llm.ready` so the server stops waiting. That answer is the\n * whole point: without it the server can only burn its entire budget on every\n * turn, so the budget has to stay small, so an app on the far side of a WAN can\n * never win the race. With it, a fast handler costs one round trip and a slow\n * one costs exactly what it costs — up to the budget the agent asked for.\n *\n * `llm.preparing_timeout` is the server admitting it gave up. It used to be a\n * bare `pass` with no log and no event, which is why apps shipped for months\n * rendering prompts with stale values and never found out.\n */\n\nimport type { EventHandler, DispatchContext } from \"../handler.js\";\nimport type { WireEvent } from \"../../protocol/wire.js\";\nimport type { Call, PreparingTimeoutEvent } from \"../../domain/call.js\";\n\nexport class PreparingHandler implements EventHandler {\n    readonly events = [\"llm.before\", \"llm.preparing_timeout\"] as const;\n\n    handle(wire: WireEvent, ctx: DispatchContext): boolean {\n        const agent = wire.agent_id ? ctx.agent(wire.agent_id) : null;\n        if (!agent) return false;\n\n        const callId = wire.call_id as string;\n        if (!callId) return false;\n\n        const call = agent._getCall(callId);\n        if (!call) return false;\n\n        if (wire.event === \"llm.preparing_timeout\") {\n            const event: PreparingTimeoutEvent = {\n                callId,\n                turn: Number(wire.turn ?? 0),\n                waitedMs: Number(wire.waited_ms ?? 0),\n                budgetMs: Number(wire.budget_ms ?? 0),\n            };\n            ctx.logger.warn(\n                `call.preparing did not answer in time on ${callId} ` +\n                `(turn ${event.turn}, waited ${event.waitedMs}ms of ${event.budgetMs}ms). ` +\n                `The server generated with the previous prompt variables.`,\n            );\n            call._emitWire(\"call.preparingTimeout\" as any, event);\n            agent._emitWire(\"call.preparingTimeout\" as any, event, call);\n            return true;\n        }\n\n        const turn = wire.turn as number | undefined;\n        void this.#runPreparing(call, agent, callId, turn, ctx);\n        return true;\n    }\n\n    /**\n     * Run the developer's handlers, then release the turn.\n     *\n     * Handlers that return a promise (any `async` one) are awaited — so an\n     * `await call.setPromptVars(...)` inside them is on THIS generation. A\n     * handler that throws or hangs must not wedge the turn: the server's budget\n     * is the backstop, and we release regardless.\n     */\n    async #runPreparing(\n        call: Call,\n        agent: { id: string; _emitPreparing?(call: Call): unknown[]; _emitWire(e: any, ...a: any[]): void },\n        callId: string,\n        turn: number | undefined,\n        ctx: DispatchContext,\n    ): Promise<void> {\n        const results = [\n            ...call._emitPreparing(),\n            ...(agent._emitPreparing?.(call) ?? []),\n        ];\n        const pending = results.filter(\n            (r): r is Promise<unknown> => !!r && typeof (r as Promise<unknown>).then === \"function\",\n        );\n        if (pending.length > 0) {\n            try {\n                await Promise.allSettled(pending);\n            } catch {\n                /* allSettled never rejects; belt and braces */\n            }\n        }\n        // Tell the server we're done. A server that predates llm.ready simply\n        // ignores the frame and falls back to its timeout, exactly as today.\n        try {\n            ctx.send({\n                event: \"llm.ready\",\n                call_id: callId,\n                agent_id: agent.id,\n                ...(turn !== undefined ? { turn } : {}),\n            });\n        } catch {\n            /* socket gone — the server's budget covers it */\n        }\n    }\n}\n","/**\n * Memory handler — `memory.ops` from the server (see AgentConfig.memory).\n *\n * The server learned or revised something about the session's contact. Emitted\n * on the agent (the normal place to persist it) and on the call (for code that\n * follows one conversation). The payload is passed through untouched: it is\n * the same JSON the call log and the DataChannel carry.\n */\nimport type { EventHandler, DispatchContext } from \"../handler.js\";\nimport type { WireEvent } from \"../../protocol/wire.js\";\n\nexport class MemoryHandler implements EventHandler {\n    readonly events = [\"memory.ops\"] as const;\n\n    handle(wire: WireEvent, ctx: DispatchContext): boolean {\n        const agent = wire.agent_id ? ctx.agent(wire.agent_id) : null;\n        if (!agent) return false;\n        const callId = (wire.call_id ?? wire.session_id) as string | undefined;\n        const call = callId ? agent._getCall(callId) : undefined;\n        const { event: _e, agent_id: _a, ...payload } = wire as Record<string, unknown>;\n        if (call) call._emitWire(\"memory.ops\" as any, payload);\n        agent._emitWire(\"memory.ops\", payload as any, call);\n        return true;\n    }\n}\n","/**\n * Line handler — the four events only a phone line receives.\n *\n * Handles: line.created, line.error, line.destroyed, call.routed,\n *          call.route_failed\n *\n * Everything ELSE a line gets (call.started, bot.*, turn.*, dtmf) is a\n * standard event carrying `agent_id: \"line:<number>\"`, and the existing\n * handlers route it unchanged — that is the whole point of registering a line\n * under an agent id. Only the registration ack and the owner swap are new.\n */\n\nimport type { EventHandler, DispatchContext } from \"../handler.js\";\nimport type { WireEvent } from \"../../protocol/wire.js\";\nimport type { PhoneLine, LineCall, RouteFailureReason } from \"../../domain/line.js\";\n\nexport class LineHandler implements EventHandler {\n    readonly events = [\"line.created\", \"line.error\", \"line.destroyed\", \"call.routed\", \"call.route_failed\"] as const;\n\n    handle(wire: WireEvent, ctx: DispatchContext): boolean {\n        switch (wire.event) {\n            case \"line.created\": {\n                const line = this.#line(wire, ctx);\n                if (!line) return false;\n                line._markCreated();\n                ctx.logger.info(`Line ${line.number} created`);\n                return true;\n            }\n\n            case \"line.error\": {\n                const line = this.#line(wire, ctx);\n                if (!line) return false;\n                const code = (wire.code ?? \"LINE_CONFIG_ERROR\") as string;\n                const message = (wire.error ?? `Line ${line.number} was refused (${code})`) as string;\n                line._markError(code, message);\n                ctx.logger.error(`Line ${line.number} refused: ${code} — ${message}`);\n                return true;\n            }\n\n            case \"line.destroyed\": {\n                const line = this.#line(wire, ctx);\n                if (!line) return false;\n                ctx.logger.info(`Line ${line.number} destroyed`);\n                return true;\n            }\n\n            case \"call.routed\": {\n                const call = this.#call(wire, ctx);\n                if (!call) return false;\n                call._applyRouted((wire.agent ?? \"\") as string);\n                ctx.logger.info(`Call ${call.id} routed to ${wire.agent}`);\n                return true;\n            }\n\n            case \"call.route_failed\": {\n                const call = this.#call(wire, ctx);\n                if (!call) return false;\n                const reason = (wire.reason ?? \"swap_failed\") as RouteFailureReason;\n                call._applyRouteFailed((wire.agent ?? \"\") as string, reason);\n                ctx.logger.warn(`Call ${call.id} not routed to ${wire.agent}: ${reason}`);\n                return true;\n            }\n\n            default:\n                return false;\n        }\n    }\n\n    /** By `number` (what the line events carry) or by `agent_id` (what everything else carries). */\n    #line(wire: WireEvent, ctx: DispatchContext): PhoneLine | null {\n        const number = typeof wire.number === \"string\" ? wire.number : null;\n        const agentId = typeof wire.agent_id === \"string\" ? wire.agent_id : null;\n        for (const line of ctx.lines()) {\n            if (line.number === number || line.id === agentId) return line;\n        }\n        return null;\n    }\n\n    /**\n     * The routed call. `agent_id` names the line, but a server that omits it on\n     * an answer is not worth losing a hand-over over — the call id is unique.\n     */\n    #call(wire: WireEvent, ctx: DispatchContext): LineCall | null {\n        const callId = typeof wire.call_id === \"string\" ? wire.call_id : null;\n        if (!callId) return null;\n        for (const line of ctx.lines()) {\n            const call = line._getCall(callId);\n            if (call) return call;\n        }\n        return null;\n    }\n}\n","/**\n * Memory REST client — what an agent remembers about its contacts.\n *\n * Talks to `/api/memory` on the voice server with the org's API key. The\n * agent does not need to be online: memory is a store, not a session, which\n * is what lets a back office ask \"which callers asked not to be phoned\" long\n * after the calls ended.\n */\n\nexport interface MemoryFact {\n    id: string;\n    kind: string;\n    text: string;\n    confidence: number;\n    valid_from: string;\n    valid_to?: string | null;\n    supersedes?: string;\n    evidence?: string;\n    source?: { call?: string; turn?: number; transport?: string };\n}\n\nexport interface MemoryHit {\n    contact: string;\n    kind: string;\n    text: string;\n    score: number | null;\n}\n\nexport interface MemoryContact {\n    contact: string;\n    revision: number;\n    facts: MemoryFact[];\n    /** The regenerated memory.md — the same text the prompt sees as {{MEMORY}}. */\n    memoryMd: string;\n}\n\nexport interface MemoryApiOptions {\n    apiKey: string;\n    apiUrl: string;\n    agent: string;\n}\n\nasync function call<T>(opts: MemoryApiOptions, method: string, path: string): Promise<T> {\n    const res = await fetch(`${opts.apiUrl}/api/memory${path}`, {\n        method,\n        headers: { Authorization: `Bearer ${opts.apiKey}` },\n    });\n    const data = (await res.json().catch(() => ({}))) as Record<string, unknown>;\n    if (!res.ok || data.success === false) {\n        throw new Error(`memory ${method} ${path}: ${res.status} ${(data.error as string) ?? res.statusText}`);\n    }\n    return data as T;\n}\n\nexport async function memorySearch(\n    opts: MemoryApiOptions,\n    query: string,\n    o: { contact?: string | null; k?: number } = {},\n): Promise<MemoryHit[]> {\n    const qs = new URLSearchParams({ agent: opts.agent, q: query, k: String(o.k ?? 6) });\n    if (o.contact) qs.set(\"contact\", o.contact);\n    const data = await call<{ hits: MemoryHit[] }>(opts, \"GET\", `/search?${qs}`);\n    return data.hits ?? [];\n}\n\nexport async function memoryGet(opts: MemoryApiOptions, contact: string): Promise<MemoryContact> {\n    const data = await call<{ contact: string; revision: number; facts: MemoryFact[]; memory_md: string }>(\n        opts, \"GET\", `/${encodeURIComponent(opts.agent)}/${encodeURIComponent(contact)}`,\n    );\n    return { contact: data.contact, revision: data.revision, facts: data.facts ?? [], memoryMd: data.memory_md ?? \"\" };\n}\n\nexport async function memoryForget(opts: MemoryApiOptions, contact: string): Promise<boolean> {\n    const data = await call<{ forgotten: boolean }>(\n        opts, \"DELETE\", `/${encodeURIComponent(opts.agent)}/${encodeURIComponent(contact)}`,\n    );\n    return Boolean(data.forgotten);\n}\n","/**\n * skill() — bundle prompt + tools + knowledge base into a unit the LLM can\n * load and unload on demand (progressive disclosure).\n *\n * A Skill is a named capability. When it is *active* the server:\n *   - injects its `instructions` as a dedicated section of the system prompt,\n *   - exposes its `tools` to the LLM (merged into the live tool list),\n *   - includes its `knowledgeBase` in RAG retrieval.\n * When inactive, none of that is visible to the model — keeping the prompt and\n * tool list small. Activation is driven by the model (auto-generated\n * `loadSkill` / `unloadSkill` meta-tools), by your code (`call.loadSkill(...)`),\n * or pinned with `activation: \"always\"`.\n *\n * Usage:\n * ```ts\n * import { skill, tool } from \"@pinecall/sdk\";\n * import { z } from \"zod\";\n *\n * const booking = skill({\n *   name: \"booking\",\n *   description: \"Reserve, reschedule or cancel calendar appointments.\",\n *   instructions: \"Confirm date, time and name before booking.\",\n *   tools: [getAvailableSlots, bookAppointment],\n *   knowledgeBase: \"kb_booking_policies\",\n * });\n *\n * pc.agent(\"front-desk\", { tools: [endCall], skills: [booking] });\n * ```\n */\n\nimport type { Tool } from \"./tool.js\";\n\n/** How a skill becomes active. */\nexport type SkillActivation = \"model\" | \"manual\" | \"always\";\n\n// ─── Public types ────────────────────────────────────────────────────────\n\nexport interface SkillConfig {\n    /** Unique id — used by `loadSkill(\"name\")`. */\n    name: string;\n    /** Shown to the LLM (in the `loadSkill` meta-tool) so it knows when to load it. */\n    description: string;\n    /** Prompt fragment injected as a system-prompt section while the skill is active. */\n    instructions?: string;\n    /** Tools that become visible to the LLM while the skill is active. */\n    tools?: Tool[];\n    /** Knowledge base (id) added to RAG retrieval while the skill is active. */\n    knowledgeBase?: string;\n    /** Per-skill RAG top-k. Falls back to the agent's value when omitted. */\n    ragTopK?: number;\n    /**\n     * Activation mode:\n     *   - \"model\"  (default) — the LLM loads it via the `loadSkill` meta-tool.\n     *   - \"manual\"           — only your code loads it (`call.loadSkill`).\n     *   - \"always\"           — active from the start of every call.\n     */\n    activation?: SkillActivation;\n}\n\nexport interface Skill {\n    readonly name: string;\n    readonly description: string;\n    readonly instructions?: string;\n    readonly tools: Tool[];\n    readonly knowledgeBase?: string;\n    readonly ragTopK?: number;\n    readonly activation: SkillActivation;\n    /** @internal Convert to wire format for the server. */\n    _toWire(): Record<string, unknown>;\n}\n\n// ─── Factory ─────────────────────────────────────────────────────────────\n\nexport function skill(config: SkillConfig): Skill {\n    const tools = config.tools ?? [];\n    const activation = config.activation ?? \"model\";\n\n    return {\n        name: config.name,\n        description: config.description,\n        instructions: config.instructions,\n        tools,\n        knowledgeBase: config.knowledgeBase,\n        ragTopK: config.ragTopK,\n        activation,\n        _toWire() {\n            return {\n                name: config.name,\n                description: config.description,\n                ...(config.instructions ? { instructions: config.instructions } : {}),\n                tools: tools.map((t) => (t._toWire ? t._toWire() : t)),\n                ...(config.knowledgeBase ? { knowledge_base: config.knowledgeBase } : {}),\n                ...(config.ragTopK != null ? { rag_top_k: config.ragTopK } : {}),\n                activation,\n            };\n        },\n    };\n}\n","/**\n * Agent — a logical voice agent within a Pinecall connection.\n *\n * Created via `pc.agent(\"my-agent\", config?)`.\n * Each agent owns channels (phone, webrtc) and receives events\n * independently from other agents on the same connection.\n *\n * The old _handleEvent() 200-line switch is gone. Dispatch handlers now\n * call typed _apply* methods and _emitWire directly.\n */\n\nimport { TypedEventBus } from \"../kernel/event-bus.js\";\nimport { Call } from \"./call.js\";\nimport type { CallInit } from \"./call.js\";\nimport { RingingCall } from \"./ringing-call.js\";\nimport { buildShortcutPayload } from \"../protocol/shortcuts.js\";\nimport type { Turn } from \"./turn.js\";\nimport type { AgentConfig, ChannelConfig, WhatsAppChannelConfig } from \"../config/agent.js\";\nimport type { Tool } from \"../tool.js\";\nimport { memorySearch, memoryGet, memoryForget, type MemoryHit, type MemoryContact, type MemoryFact } from \"../api/memory.js\";\nimport type { Skill, SkillConfig } from \"../skill.js\";\nimport { skill as makeSkill } from \"../skill.js\";\nimport type { TokenResponse, TokenScopeOptions } from \"../api/tokens.js\";\nimport type {\n    CallStartedEvent,\n    SpeechStartedEvent,\n    SpeechEndedEvent,\n    UserSpeakingEvent,\n    UserMessageEvent,\n    EagerTurnEvent,\n    TurnPauseEvent,\n    TurnEndEvent,\n    TurnResumedEvent,\n    TurnContinuedEvent,\n    BotSpeakingEvent,\n    BotWordEvent,\n    BotFinishedEvent,\n    BotInterruptedEvent,\n    MessageConfirmedEvent,\n    ReplyRejectedEvent,\n    AudioMetricsEvent,\n    SessionTimeoutEvent,\n    ToolCallEvent,\n} from \"../protocol/events.js\";\n\n// ─── Agent events ────────────────────────────────────────────────────────\n\n/** One applied memory op, as emitted on `memory.ops`. */\nexport type MemoryOp =\n    | { op: \"add\"; id: string; kind: string; text: string; confidence: number; valid_from: string; evidence?: string }\n    | { op: \"update\"; id: string; supersedes: string; kind: string; text: string; confidence: number; valid_from: string; evidence?: string }\n    | { op: \"delete\"; id: string; kind?: string; text?: string; reason?: string };\n\n/** The `memory.ops` payload — the same JSON the call log and the DataChannel carry. */\nexport interface MemoryOpsEvent {\n    contact: string;\n    call_id: string;\n    turn: number;\n    /** True on the end-of-call consolidation pass. */\n    final: boolean;\n    ops: MemoryOp[];\n    memory: { revision: number; path: string };\n    model: string;\n    latency_ms: number;\n}\n\n/** `agent.memory` — read what the server remembers. */\nexport interface AgentMemory {\n    /** Semantic + lexical search. With `contact`, only that contact; without, across every contact of the agent. */\n    search(query: string, opts?: { contact?: string | null; k?: number }): Promise<MemoryHit[]>;\n    /** Every fact held about a contact, plus the regenerated memory.md. */\n    get(contact: string): Promise<MemoryContact>;\n    /** The right to be forgotten: facts, view and index entries, gone. */\n    forget(contact: string): Promise<boolean>;\n}\nexport type { MemoryHit, MemoryContact, MemoryFact };\n\nexport interface AgentEvents {\n    [key: string]: (...args: any[]) => void;\n\n    // Lifecycle\n    ready: () => void;\n    \"call.started\": (call: Call) => void;\n    /**\n     * Memory learned or revised something about the contact of a session —\n     * see `AgentConfig.memory`. `ops` is what was APPLIED (final ids, validity),\n     * not what was asked; `final` marks the end-of-call pass.\n     */\n    \"memory.ops\": (ops: MemoryOpsEvent, call: Call | undefined) => void;\n    \"call.ended\": (call: Call, reason: string) => void;\n    \"call.ringing\": (call: RingingCall) => void;\n\n    // Speech events\n    \"speech.started\": (event: SpeechStartedEvent, call: Call) => void;\n    \"speech.ended\": (event: SpeechEndedEvent, call: Call) => void;\n    \"user.speaking\": (event: UserSpeakingEvent, call: Call) => void;\n    \"user.message\": (event: UserMessageEvent, call: Call) => void;\n\n    // Turn events\n    \"eager.turn\": (turn: Turn, call: Call) => void;\n    \"turn.pause\": (event: TurnPauseEvent, call: Call) => void;\n    \"turn.end\": (turn: Turn, call: Call) => void;\n    \"turn.resumed\": (event: TurnResumedEvent, call: Call) => void;\n    \"turn.continued\": (event: TurnContinuedEvent, call: Call) => void;\n\n    // Bot events\n    \"bot.speaking\": (event: BotSpeakingEvent, call: Call) => void;\n    \"bot.word\": (event: BotWordEvent, call: Call) => void;\n    \"bot.finished\": (event: BotFinishedEvent, call: Call) => void;\n    \"bot.interrupted\": (event: BotInterruptedEvent, call: Call) => void;\n\n    // Confirmations\n    \"message.confirmed\": (event: MessageConfirmedEvent, call: Call) => void;\n    \"reply.rejected\": (event: ReplyRejectedEvent, call: Call) => void;\n\n    // Analysis\n    \"audio.metrics\": (event: AudioMetricsEvent, call: Call) => void;\n\n    // Session limits\n    \"session.idleWarning\": (event: any, call: Call) => void;\n    \"session.timeout\": (event: SessionTimeoutEvent, call: Call) => void;\n\n    // Keypad — phone only; a browser has no keypad to press.\n    \"call.dtmf_received\": (event: import(\"../protocol/events.js\").CallDtmfReceivedEvent, call: Call) => void;\n\n    // LLM / Tool calls\n    \"llm.toolCall\": (event: ToolCallEvent, call: Call) => void;\n\n    // Skills\n    \"skill.loaded\": (event: import(\"./call.js\").SkillEvent, call: Call) => void;\n    \"skill.unloaded\": (event: import(\"./call.js\").SkillEvent, call: Call) => void;\n\n    // Channel events\n    \"channel.added\": (type: string, ref: string) => void;\n    \"channel.configured\": (ref: string) => void;\n    \"channel.removed\": (ref: string) => void;\n\n    // WhatsApp events\n    \"whatsapp.message\": (event: Record<string, unknown>) => void;\n    \"whatsapp.response\": (event: Record<string, unknown>) => void;\n    \"whatsapp.status\": (event: Record<string, unknown>) => void;\n    \"whatsapp.sessionStarted\": (session: import(\"./wa-session.js\").WhatsAppSession) => void;\n    \"whatsapp.sessionEnded\": (event: Record<string, unknown>) => void;\n\n    // Human-in-the-loop\n    \"session.paused\": (event: { sessionId?: string; contact?: string }) => void;\n    \"session.resumed\": (event: { sessionId?: string; contact?: string }) => void;\n\n    // Pre-turn hook — see CallEvents[\"call.preparing\"]. Returning a promise\n    // holds the turn until it settles.\n    \"call.preparing\": (call: Call) => void | Promise<unknown>;\n    \"call.preparingTimeout\": (\n        event: import(\"./call.js\").PreparingTimeoutEvent,\n        call: Call,\n    ) => void;\n}\n\n// ─── Agent class ─────────────────────────────────────────────────────────\n\nexport class Agent extends TypedEventBus<AgentEvents> {\n    readonly id: string;\n    /** Human-readable display name. Defaults to id. */\n    name: string;\n    #config: AgentConfig;\n    #tools: Tool[] = [];\n    /** Declared skills (latent on the server until activated). */\n    #skills: Skill[] = [];\n    #calls = new Map<string, Call>();\n    #sendRaw: (data: Record<string, unknown>) => void;\n    #serverReady = false;\n    #pendingQueue: Record<string, unknown>[] = [];\n    /** Tracks registered channels for re-registration on reconnect. */\n    #channels = new Map<string, { type: string; ref?: string; config?: ChannelConfig }>();\n    /** Tracked dev callers for re-registration on reconnect. */\n    #devCallers: string[] = [];\n    /** @internal Reference to parent Pinecall client (for createToken). */\n    #client: {\n        createToken: (channel: \"webrtc\" | \"chat\" | \"stream\", agentId: string, metadata?: Record<string, unknown>, opts?: TokenScopeOptions) => Promise<TokenResponse>;\n        memoryApi?: { apiKey: string; apiUrl: string };\n    } | null = null;\n    /** True once the SERVER acknowledged this agent (`agent.created`/`agent.resumed`). */\n    #registered = false;\n    #readyPromise!: Promise<void>;\n    #readyResolve!: () => void;\n    #readyReject!: (err: Error) => void;\n\n    /** @internal — created by Pinecall.agent() */\n    constructor(\n        id: string,\n        config: AgentConfig,\n        send: (data: Record<string, unknown>) => void,\n    ) {\n        super();\n        this.id = id;\n        this.name = id;\n        this.#config = config;\n        this.#tools = config.tools ?? [];\n        this.#skills = config.skills ?? [];\n        this.#sendRaw = send;\n        this.#armReady();\n    }\n\n    #armReady(): void {\n        this.#readyPromise = new Promise<void>((resolve, reject) => {\n            this.#readyResolve = resolve;\n            this.#readyReject = reject;\n        });\n        // Awaiting `ready` is optional, so a rejection must never surface as an\n        // unhandledRejection crash in a process that never looked at it.\n        this.#readyPromise.catch(() => {});\n    }\n\n    /**\n     * Send a raw protocol message. Buffers if the agent isn't server-ready yet.\n     *\n     * Prefer high-level methods like `call.toolResult()`, `call.say()`,\n     * `call.reply()`, `agent.setDevCallers()` etc. Use `send()` only\n     * as an escape hatch for protocol-level access.\n     */\n    send(data: Record<string, unknown>): void {\n        if (this.#serverReady) {\n            this.#sendRaw(data);\n        } else {\n            this.#pendingQueue.push(data);\n        }\n    }\n\n    /** @internal Alias for backwards compat — use send() instead. */\n    _send(data: Record<string, unknown>): void {\n        this.send(data);\n    }\n\n    // ── Public getters ───────────────────────────────────────────────────\n\n    /** All active calls for this agent. */\n    get calls(): ReadonlyMap<string, Call> {\n        return this.#calls;\n    }\n\n    /** Get a specific call by ID. */\n    call(callId: string): Call | undefined {\n        return this.#calls.get(callId);\n    }\n\n    /** Get the current agent config. */\n    getConfig(): AgentConfig {\n        return this.#config;\n    }\n\n    /**\n     * True once the SERVER has acknowledged this agent's registration.\n     *\n     * `pc.agent()` returns synchronously — it only *queues* `agent.create` on\n     * the socket. Until the server answers `agent.created`, the agent does not\n     * exist server-side, so token mints and inbound routing 404 on it.\n     */\n    get registered(): boolean {\n        return this.#registered;\n    }\n\n    /**\n     * Resolves when the SERVER has acknowledged this agent's registration\n     * (`agent.created` / `agent.resumed`) — NOT when `pc.agent()` returned.\n     *\n     * Await this before doing anything that requires the agent to exist\n     * server-side (minting a chat/WebRTC token, dialing out). Rejects with\n     * {@link AgentConflictError} if the registration is terminally refused.\n     * Goes back to pending if the socket drops, and resolves again once the\n     * reconnect re-registers the agent.\n     *\n     * @example\n     * const agent = pc.agent(\"recepcion\", { prompt });\n     * await agent.ready;                       // server now knows it\n     * const { token } = await agent.createToken(\"chat\");\n     */\n    get ready(): Promise<void> {\n        return this.#readyPromise;\n    }\n\n    // ── Channel management ───────────────────────────────────────────────\n\n    /**\n     * Register a phone number or SIP URI. Idempotent — calling again with the\n     * same number updates its config.\n     *\n     * @example\n     * agent.addPhoneNumber(\"+13186330963\");\n     * agent.addPhoneNumber(\"+34612345678\", { ringing: true, voice: \"elevenlabs/lucia\" });\n     * agent.addPhoneNumber(\"sip:bot@trunk.twilio.com\");\n     */\n    addPhoneNumber(number: string, config?: ChannelConfig): void {\n        this._addChannel(\"phone\", number, config);\n    }\n\n    /**\n     * Register a WhatsApp channel. Idempotent — calling again with the\n     * same phoneNumberId updates its config.\n     *\n     * @example\n     * agent.addWhatsapp({ phoneNumberId: \"123\", accessToken: \"EAA...\" });\n     */\n    addWhatsapp(config: WhatsAppChannelConfig): void {\n        this._addChannel(\"whatsapp\", config);\n    }\n\n    /**\n     * Register the browser voice channel, so this agent can take WebRTC calls.\n     *\n     * Phone and WhatsApp had public methods and these two did not — the only\n     * way in was `_addChannel`, which is internal. Anything outside this\n     * package (a plugin, another @pinecall/* module) could not open a browser\n     * channel without reaching past the public API.\n     *\n     * @example\n     * agent.addWebrtc();\n     */\n    addWebrtc(config?: ChannelConfig): void {\n        this._addChannel(\"webrtc\", undefined, config);\n    }\n\n    /**\n     * Register the text chat channel. Same reasoning as `addWebrtc()`.\n     *\n     * @example\n     * agent.addChat();\n     */\n    addChat(config?: ChannelConfig): void {\n        this._addChannel(\"chat\", undefined, config);\n    }\n\n    /**\n     * Remove a phone number or SIP URI.\n     *\n     * @example agent.removePhone(\"+13186330963\");\n     */\n    removePhone(number: string): void {\n        this.#channels.delete(number);\n        this._send({ event: \"channel.remove\", agent_id: this.id, type: \"phone\", ref: number });\n    }\n\n    /**\n     * Remove a WhatsApp channel by phoneNumberId.\n     *\n     * @example agent.removeWhatsapp(\"123\");\n     */\n    removeWhatsapp(phoneNumberId: string): void {\n        this.#channels.delete(phoneNumberId);\n        this._send({ event: \"channel.remove\", agent_id: this.id, type: \"whatsapp\", ref: phoneNumberId });\n    }\n\n    /** @internal — used by client.ts and config processing. */\n    _addChannel(type: \"phone\" | \"webrtc\" | \"chat\" | \"whatsapp\", ref?: string | WhatsAppChannelConfig, config?: ChannelConfig): void {\n        // Validate phone numbers early (SIP URIs pass through)\n        if (type === \"phone\" && typeof ref === \"string\" && ref && !ref.startsWith(\"sip:\")) {\n            const cleaned = ref.replace(/[\\s\\-()]/g, \"\");\n            const normalized = cleaned.startsWith(\"+\") ? cleaned : \"+\" + cleaned;\n            const digits = normalized.slice(1);\n            if (!/^\\d+$/.test(digits) || digits.length < 7 || digits.length > 15) {\n                throw new Error(`Invalid phone number \"${ref}\": must be E.164 format (+, 7-15 digits)`);\n            }\n        }\n\n        // Track for re-registration on reconnect\n        const key = (typeof ref === \"string\" ? ref : undefined) ?? type;\n        this.#channels.set(key, { type, ref: typeof ref === \"string\" ? ref : undefined, config: typeof ref === \"object\" ? ref : config });\n\n        // WhatsApp: ref is a WhatsAppChannelConfig object\n        if (type === \"whatsapp\" && typeof ref === \"object\" && ref !== null) {\n            const waConfig = ref as WhatsAppChannelConfig;\n            const msg = {\n                event: \"channel.add\",\n                agent_id: this.id,\n                type: \"whatsapp\",\n                ref: waConfig.phoneNumberId,\n                accessToken: waConfig.accessToken,\n                ...(waConfig.verifyToken ? { verifyToken: waConfig.verifyToken } : {}),\n                ...(waConfig.appSecret ? { appSecret: waConfig.appSecret } : {}),\n                ...(waConfig.phone ? { phone: waConfig.phone } : {}),\n                ...buildShortcutPayload(waConfig),\n            };\n            this._send(msg);\n            return;\n        }\n\n        const msg = {\n            event: \"channel.add\",\n            agent_id: this.id,\n            type,\n            ...(typeof ref === \"string\" && ref ? { ref } : {}),\n            ...buildShortcutPayload(config),\n            ...(config?.ringing ? { ringing: true } : {}),\n        };\n        this._send(msg);\n    }\n\n    configureChannel(ref: string, config: ChannelConfig): void {\n        this._send({\n            event: \"channel.configure\",\n            agent_id: this.id,\n            ref,\n            ...buildShortcutPayload(config),\n        });\n    }\n\n    removeChannel(ref: string): void {\n        this.#channels.delete(ref);\n        this._send({\n            event: \"channel.remove\",\n            agent_id: this.id,\n            ref,\n        });\n    }\n\n    // ── Agent configuration ──────────────────────────────────────────────\n\n    update(opts: AgentConfig): void {\n        this.#config = { ...this.#config, ...opts };\n        // Keep the executable universe in sync so auto-dispatch can run any\n        // tool the LLM may now call (otherwise _getTools() goes stale and the\n        // SDK replies \"Unknown tool\" to freshly hot-reloaded tools).\n        if (opts.tools !== undefined) this.#tools = opts.tools;\n        if (opts.skills !== undefined) this.#skills = opts.skills;\n        this._send({\n            event: \"agent.configure\",\n            agent_id: this.id,\n            ...buildShortcutPayload(opts),\n        });\n    }\n\n    /**\n     * Attach (or hot-reload) a single skill at runtime. The skill is sent to the\n     * server and kept latent until activated (by the model, by `call.loadSkill`,\n     * or immediately if `activation: \"always\"`).\n     */\n    skill(config: SkillConfig): Skill {\n        const s = makeSkill(config);\n        // Replace an existing skill with the same name, else append.\n        const idx = this.#skills.findIndex((x) => x.name === s.name);\n        if (idx >= 0) this.#skills[idx] = s;\n        else this.#skills.push(s);\n        this.#config = { ...this.#config, skills: this.#skills };\n        this._send({\n            event: \"agent.configure\",\n            agent_id: this.id,\n            skills: this.#skills.map((x) => x._toWire()),\n        });\n        return s;\n    }\n\n    /** @deprecated Use `agent.update()` instead. */\n    configure(opts: AgentConfig): void {\n        this.update(opts);\n    }\n\n    configureSession(sessionId: string, opts: ChannelConfig): void {\n        this._send({\n            event: \"session.configure\",\n            agent_id: this.id,\n            session_id: sessionId,\n            ...buildShortcutPayload(opts),\n        });\n    }\n\n    // ── Development ──────────────────────────────────────────────────────\n\n    routeCallers(callers: string[]): void {\n        this.#devCallers = callers;\n        this.send({ event: \"dev.config\", callers });\n    }\n\n    // ── Token generation ─────────────────────────────────────────────────\n\n    /**\n     * Mint a short-lived browser token for this agent (webrtc / chat / stream).\n     *\n     * `metadata` (optional) is sealed into the signed token — trusted server-side\n     * (the browser cannot forge it) and surfaced as `call.metadata` for tools.\n     * Use for per-session identity (tenantId, userId, role).\n     */\n    async createToken(\n        channel: \"webrtc\" | \"chat\" | \"stream\",\n        metadata?: Record<string, unknown>,\n        opts?: TokenScopeOptions,\n    ): Promise<TokenResponse> {\n        if (!this.#client) {\n            throw new Error(\n                \"Cannot create token: agent is not connected to a Pinecall client. \" +\n                \"Use pc.createToken(channel, agentId) instead.\",\n            );\n        }\n        return this.#client.createToken(channel, this.id, metadata, opts);\n    }\n\n    /** @internal Set the parent Pinecall client reference. */\n    _setClient(client: {\n        createToken: (channel: \"webrtc\" | \"chat\" | \"stream\", agentId: string, metadata?: Record<string, unknown>, opts?: TokenScopeOptions) => Promise<TokenResponse>;\n        memoryApi?: { apiKey: string; apiUrl: string };\n    }): void {\n        this.#client = client;\n    }\n\n    // ── Memory ────────────────────────────────────────────────────────────\n\n    /**\n     * What this agent remembers about its contacts. Reads go to the server's\n     * store over REST with the org's key — the agent need not be online.\n     * See `AgentConfig.memory` for how facts get there.\n     */\n    get memory(): AgentMemory {\n        const api = () => {\n            const m = this.#client?.memoryApi;\n            if (!m?.apiKey) throw new Error(\"agent.memory needs an API key (PINECALL_API_KEY / new Pinecall({ apiKey }))\");\n            return { ...m, agent: this.id };\n        };\n        return {\n            search: (query, opts) => memorySearch(api(), query, opts),\n            get: (contact) => memoryGet(api(), contact),\n            forget: (contact) => memoryForget(api(), contact),\n        };\n    }\n\n    // ── Dial ──────────────────────────────────────────────────────────────\n\n    dial(options: {\n        to: string;\n        /** Caller ID. If omitted, uses the agent's only phone channel. */\n        from?: string;\n        greeting?: string;\n        metadata?: Record<string, unknown>;\n        config?: Record<string, unknown>;\n        /**\n         * When true, the server also detects the OTHER party's end-of-turn and\n         * emits `turn.end` to this (initiating) side — so an automated caller\n         * (e.g. a test/judge agent talking to another agent) knows when to\n         * speak. Default false (a normal caller is a human and doesn't need it).\n         */\n        detectTurnEnd?: boolean;\n    }): Promise<Call> {\n        // Auto-resolve `from` if not provided\n        let from = options.from;\n        if (!from) {\n            const phoneChannels: string[] = [];\n            for (const [key, ch] of this.#channels) {\n                if (ch.type === \"phone\" && ch.ref) phoneChannels.push(ch.ref);\n            }\n            if (phoneChannels.length === 0) {\n                return Promise.reject(new Error(\n                    \"No phone numbers registered. Add one with `phoneNumber: \\\"+1...\\\"` or pass `from` explicitly.\",\n                ));\n            }\n            if (phoneChannels.length > 1) {\n                return Promise.reject(new Error(\n                    `Multiple phone channels registered (${phoneChannels.join(\", \")}). Pass \\`from\\` to specify which one to use.`,\n                ));\n            }\n            from = phoneChannels[0];\n        }\n\n        return new Promise<Call>((resolve, reject) => {\n            let settled = false;\n            const cleanup = () => {\n                this.off(\"call.started\", onStarted);\n                this.off(\"call.ended\", onEnded);\n                this.off(\"error\" as any, onError);\n            };\n            const onStarted = (call: Call) => {\n                if (call.to === options.to || call.direction === \"outbound\") {\n                    if (settled) return;\n                    settled = true;\n                    cleanup();\n                    if (options.greeting) call.greeting = options.greeting;\n                    resolve(call);\n                }\n            };\n            const onEnded = (call: Call | null, reason: string) => {\n                // Outbound call ended before connecting (busy, no-answer, failed, canceled)\n                if (settled) return;\n                settled = true;\n                cleanup();\n                reject(new Error(reason || \"call_rejected\"));\n            };\n            const onError = (err: Error) => {\n                if (settled) return;\n                settled = true;\n                cleanup();\n                reject(err);\n            };\n            this.on(\"call.started\", onStarted);\n            this.on(\"call.ended\", onEnded);\n            this.on(\"error\" as any, onError);\n\n            this._send({\n                event: \"call.dial\",\n                agent_id: this.id,\n                to: options.to,\n                from,\n                ...(options.greeting ? { greeting: options.greeting } : {}),\n                ...(options.metadata ? { metadata: options.metadata } : {}),\n                ...(options.config ? { config: options.config } : {}),\n                ...(options.detectTurnEnd ? { detect_turn_end: true } : {}),\n            });\n\n            setTimeout(() => {\n                if (settled) return;\n                settled = true;\n                cleanup();\n                reject(new Error(\"Dial timeout\"));\n            }, 30000);\n        });\n    }\n\n    // ── Bridge (agent-to-agent voice) ─────────────────────────────────────\n\n    /**\n     * Place a VOICE call to ANOTHER Pinecall agent (no phone, no WebRTC).\n     *\n     * The server cross-wires the two agents' audio: this agent's TTS becomes the\n     * target's incoming audio and vice-versa, so both run their real\n     * STT/turn-detection/TTS pipelines. This agent is driven manually — speak\n     * with `call.say()` and read the target via `user.message` / `turn.end`.\n     * Typically the calling agent has no server-side LLM (it's puppeted by your\n     * code), e.g. the `pinecall test` voice judge.\n     *\n     * @param target - The target agent's slug (must be online in the same org).\n     */\n    bridge(target: string, options: {\n        greeting?: string;\n        /** Detect the target's end-of-turn and emit `turn.end` to this side. Default true. */\n        detectTurnEnd?: boolean;\n        /** Per-call config override for THIS (calling) agent — voice, STT, language. */\n        config?: Record<string, unknown>;\n        /** Enable live listening / recording on the bridged call. */\n        media?: { live?: boolean; recording?: boolean };\n        metadata?: Record<string, unknown>;\n    } = {}): Promise<Call> {\n        return new Promise<Call>((resolve, reject) => {\n            let settled = false;\n            const cleanup = () => {\n                this.off(\"call.started\", onStarted);\n                this.off(\"call.ended\", onEnded);\n                this.off(\"error\" as any, onError);\n            };\n            const onStarted = (call: Call) => {\n                if (settled) return;\n                settled = true;\n                cleanup();\n                if (options.greeting) call.greeting = options.greeting;\n                resolve(call);\n            };\n            const onEnded = (_call: Call | null, reason: string) => {\n                if (settled) return;\n                settled = true;\n                cleanup();\n                reject(new Error(reason || \"bridge_rejected\"));\n            };\n            const onError = (err: Error) => {\n                if (settled) return;\n                settled = true;\n                cleanup();\n                reject(err);\n            };\n            this.on(\"call.started\", onStarted);\n            this.on(\"call.ended\", onEnded);\n            this.on(\"error\" as any, onError);\n\n            this._send({\n                event: \"call.bridge\",\n                agent_id: this.id,\n                target,\n                ...(options.greeting ? { greeting: options.greeting } : {}),\n                ...(options.config ? { config: options.config } : {}),\n                ...(options.media ? { media: options.media } : {}),\n                ...(options.metadata ? { metadata: options.metadata } : {}),\n                detect_turn_end: options.detectTurnEnd !== false,\n            });\n\n            setTimeout(() => {\n                if (settled) return;\n                settled = true;\n                cleanup();\n                reject(new Error(\"Bridge timeout\"));\n            }, 30000);\n        });\n    }\n\n    // ── Human-in-the-loop ─────────────────────────────────────────────────\n\n    /**\n     * Pause the AI agent. While paused, incoming messages are forwarded to\n     * the SDK but the LLM does not generate responses — a human takes over.\n     *\n     * @param target - Session ID, `{ contact: \"+34...\" }`, or omit for global pause.\n     */\n    pause(target?: string | { contact: string }): void {\n        const msg: Record<string, unknown> = {\n            event: \"session.pause\",\n            agent_id: this.id,\n        };\n        if (typeof target === \"string\") {\n            msg.session_id = target;\n        } else if (target && \"contact\" in target) {\n            msg.contact = target.contact;\n        }\n        this.send(msg);\n    }\n\n    /**\n     * Resume the AI agent after a pause.\n     *\n     * @param target - Session ID, `{ contact: \"+34...\" }`, or omit for global resume.\n     */\n    resume(target?: string | { contact: string }): void {\n        const msg: Record<string, unknown> = {\n            event: \"session.resume\",\n            agent_id: this.id,\n        };\n        if (typeof target === \"string\") {\n            msg.session_id = target;\n        } else if (target && \"contact\" in target) {\n            msg.contact = target.contact;\n        }\n        this.send(msg);\n    }\n\n    /**\n     * Send a message as the human operator (not AI-generated).\n     * Works while the session is paused — the message is sent through the\n     * channel (WhatsApp, etc.) and added to LLM history for context.\n     *\n     * Pass `contact` (the customer's phone) alongside `sessionId` so the server\n     * can still deliver via WhatsApp when the referenced session has already\n     * expired (2h idle / 24h window GC) — it falls back to a direct channel\n     * send for that contact instead of a silent no-op.\n     */\n    sendMessage(opts: { sessionId?: string; contact?: string; text: string }): void {\n        this.send({\n            event: \"session.send\",\n            agent_id: this.id,\n            ...(opts.sessionId ? { session_id: opts.sessionId } : {}),\n            ...(opts.contact ? { contact: opts.contact } : {}),\n            text: opts.text,\n        });\n    }\n\n    // ── Dispatch-only API (friend methods) ───────────────────────────────\n\n    /** @internal End all calls (on disconnect). */\n    _endAllCalls(reason: string): void {\n        for (const call of this.#calls.values()) {\n            call._applyEnd(reason);\n        }\n        this.#calls.clear();\n        this.#serverReady = false;\n    }\n\n    /** @internal Emit a typed event — used by dispatch handlers. */\n    _emitWire<K extends keyof AgentEvents>(event: K, ...args: Parameters<AgentEvents[K]>): void {\n        this.emit(event, ...args);\n    }\n\n    /**\n     * @internal Run agent-level `call.preparing` handlers and hand back what\n     * they returned, so async ones can be awaited before the turn is released.\n     */\n    _emitPreparing(call: Call): unknown[] {\n        return this.emitCollect(\"call.preparing\", call);\n    }\n\n    /** @internal True when the app is listening for the pre-turn hook. */\n    _hasPreparingListener(): boolean {\n        return this.listenerCount(\"call.preparing\") > 0;\n    }\n\n    /**\n     * @internal Build the `Call` for an inbound session.\n     *\n     * A seam, not a factory pattern for its own sake: a `PhoneLine` registers\n     * under `line:<number>` so that every dispatch handler routes to it\n     * unchanged, and this is the one place it has to differ — the object the\n     * handler hands out is a `LineCall`, with `say`/`listen`/`ask`/`routeTo`.\n     */\n    _createCall(data: CallInit, send: (data: Record<string, unknown>) => void): Call {\n        return new Call(data, send);\n    }\n\n    /** @internal Get a call by ID. */\n    _getCall(callId: string): Call | undefined {\n        return this.#calls.get(callId);\n    }\n\n    /** @internal Set a call in the registry. */\n    _setCall(callId: string, call: Call): void {\n        this.#calls.set(callId, call);\n    }\n\n    /** @internal Remove a call from the registry. */\n    _deleteCall(callId: string): boolean {\n        return this.#calls.delete(callId);\n    }\n\n    /** @internal Check if a call exists. */\n    _hasCall(callId: string): boolean {\n        return this.#calls.has(callId);\n    }\n\n    /** @internal Get channels map (for PHONE_IN_USE handling). */\n    _getChannels(): Map<string, { type: string; ref?: string; config?: ChannelConfig }> {\n        return this.#channels;\n    }\n\n    /**\n     * @internal Get executable Tool objects for auto-dispatch.\n     *\n     * Returns the full executable universe — global tools plus every declared\n     * skill's tools — regardless of which skills are currently active on the\n     * server. Visibility to the LLM is decided server-side; execution must\n     * always succeed, so we never want a \"Unknown tool\" for a latent skill.\n     */\n    _getTools(): Tool[] {\n        if (this.#skills.length === 0) return this.#tools;\n        const byName = new Map<string, Tool>();\n        for (const t of this.#tools) byName.set(t.name, t);\n        for (const s of this.#skills) for (const t of s.tools) byName.set(t.name, t);\n        return [...byName.values()];\n    }\n\n    /** @internal Get declared skills. */\n    _getSkills(): Skill[] {\n        return this.#skills;\n    }\n\n    /** @internal Mark agent as server-ready and flush buffered messages. */\n    _flushPending(): void {\n        this.#serverReady = true;\n\n        // Re-register all tracked channels (critical for reconnection)\n        for (const [key, ch] of this.#channels) {\n            // WhatsApp channels need special handling\n            if (ch.type === \"whatsapp\" && ch.config) {\n                const waConfig = ch.config as any;\n                const msg = {\n                    event: \"channel.add\",\n                    agent_id: this.id,\n                    type: \"whatsapp\",\n                    ref: waConfig.phoneNumberId,\n                    accessToken: waConfig.accessToken,\n                    ...(waConfig.verifyToken ? { verifyToken: waConfig.verifyToken } : {}),\n                    ...(waConfig.appSecret ? { appSecret: waConfig.appSecret } : {}),\n                    ...buildShortcutPayload(waConfig),\n                };\n                this.#sendRaw(msg);\n            } else {\n                const msg = {\n                    event: \"channel.add\",\n                    agent_id: this.id,\n                    type: ch.type,\n                    ...(ch.ref ? { ref: ch.ref } : {}),\n                    ...buildShortcutPayload(ch.config),\n                    ...(ch.config?.ringing ? { ringing: true } : {}),\n                };\n                this.#sendRaw(msg);\n            }\n        }\n\n        // Re-send dev callers if configured\n        if (this.#devCallers.length > 0) {\n            this.#sendRaw({ event: \"dev.config\", callers: this.#devCallers });\n        }\n\n        // Flush any other pending messages (skip channel.add and dev.config — already handled above)\n        for (const msg of this.#pendingQueue) {\n            if (msg.event === \"channel.add\" || msg.event === \"dev.config\") continue;\n            this.#sendRaw(msg);\n        }\n        this.#pendingQueue = [];\n    }\n\n    /**\n     * @internal The server acknowledged this agent (`agent.created`/`agent.resumed`).\n     * Settles `ready` — this is the ONLY moment the agent exists server-side.\n     */\n    _markRegistered(): void {\n        this.#registered = true;\n        this.#readyResolve();\n    }\n\n    /**\n     * @internal The socket dropped — the server no longer holds this\n     * registration, so `ready` goes back to pending until the reconnect\n     * re-registers us. Without this, a mint during a reconnect would race\n     * against `agent.create` all over again.\n     */\n    _markUnregistered(): void {\n        if (!this.#registered) return;\n        this.#registered = false;\n        this.#armReady();\n    }\n\n    /**\n     * @internal The registration was terminally refused (see AgentConflictError).\n     * Rejects `ready` so an awaiting caller fails loudly instead of hanging.\n     */\n    _failRegistration(err: Error): void {\n        this.#readyReject(err);\n    }\n}\n\n// ── Re-export ────────────────────────────────────────────────────────────\n\nexport { buildShortcutPayload } from \"../protocol/shortcuts.js\";\n","/**\n * PhoneLine — a phone number you program, with no model behind it.\n *\n * `pc.line(\"+12186633772\")` claims a number as a session OWNER that is not an\n * agent: it has its own STT and TTS, it takes the call first, and every\n * decision it makes is plain code — `if`, `switch`, `await`. The first model\n * call happens only if the code hands the live call to an agent\n * (`call.routeTo`), or never at all.\n *\n * The line registers under the id `line:<number>` in the client's registry, so\n * every existing dispatch handler routes its events without knowing lines\n * exist. The one seam is `Agent._createCall`, which a line overrides to hand\n * out a {@link LineCall} instead of a plain `Call`.\n *\n * Contract: docs/notes/phone-line-plan.md §11 (frozen).\n */\n\nimport { TypedEventBus } from \"../kernel/event-bus.js\";\nimport { PinecallError } from \"../kernel/errors.js\";\nimport { Agent } from \"./agent.js\";\nimport { Call } from \"./call.js\";\nimport type { CallInit, SayResult, LineTranscriptEntry } from \"./call.js\";\nimport { buildShortcutPayload } from \"../protocol/shortcuts.js\";\nimport type { Turn } from \"./turn.js\";\nimport type { CallDtmfReceivedEvent } from \"../protocol/events.js\";\nimport type { VoiceShortcut, STTShortcut } from \"../config/agent.js\";\n\n// ─── Options ─────────────────────────────────────────────────────────────\n\n/**\n * The line's own pipeline — the same shortcut shapes an agent accepts, minus\n * everything that implies a model.\n *\n * `llm`, `prompt`, `tools` and `greeting` are REFUSED, synchronously, in\n * `pc.line()`: a line has no model, and its first words are code (the first\n * `call.say()` takes the greeting lock exactly like an agent's greeting does).\n */\nexport interface LineOptions {\n    /** The line's STT. Multilingual by default is the point — nobody knows the caller's language yet. */\n    stt?: STTShortcut;\n    /** The line's voice. */\n    voice?: VoiceShortcut;\n    /** BCP-47 language for STT/TTS. */\n    language?: string;\n    /** End-of-turn detection, passed through to the server untouched. */\n    turnDetection?: string | Record<string, unknown>;\n    /**\n     * Opt-in, and OFF by default: a post-dial extension window. For that many\n     * ms after connect the line stays SILENT and collects the digits a phone\n     * sends on its own when the caller dialled `+1218…,33` (the comma is a\n     * ~2 s pause, then `3 3` as keypad tones); `call.started` then carries\n     * them as `call.extension`. It costs every caller that much dead air, so\n     * it is for a line that knowingly wants extension dialling — a\n     * switchboard — never for a front desk, where the caller expects to hear\n     * a voice the instant the call connects.\n     */\n    extension?: { window: number };\n}\n\n/**\n * Default post-dial extension window, in ms: NONE. A caller who dials a number\n * expects to hear something the instant it connects, not to guess that a digit\n * is wanted. The window exists only for a line that knowingly trades silence\n * for `+1…,10`-style extension dialling, and it must be asked for.\n */\nexport const DEFAULT_EXTENSION_WINDOW_MS = 0;\n\n/** Config keys that mean \"a model\" — a line has none of them. */\nconst REFUSED_KEYS = [\"llm\", \"prompt\", \"tools\", \"greeting\"] as const;\n\n/**\n * A routing table: extension → an agent slug, or code.\n *\n * `\"*\"` is the no-extension / unmatched case. Checked BEFORE `line.on(\"call\")`;\n * a call with no matching key and no `\"*\"` falls through to the `call`\n * listeners.\n */\nexport type ExtensionTable = Record<string, string | ((call: LineCall) => void | Promise<void>)>;\n\n// ─── LineCall ────────────────────────────────────────────────────────────\n\n/** What `listen()` was waiting for, and what it got. */\nexport type ListenResult =\n    | { by: \"keypad\"; digit: string; digits: string }\n    | { by: \"speech\"; text: string; confidence: number }\n    | { by: \"timeout\" };\n\nexport interface ListenOptions {\n    /** Resolve once this many keys have been pressed. `1` resolves on the first press. */\n    digits?: number;\n    /** Resolve when this key is pressed, whatever the buffer holds (\"#\"). */\n    terminator?: string;\n    /** Also race the caller's SPEECH — the session's own end-of-turn, not a second STT. Opt-in. */\n    speech?: boolean;\n    /** How long to wait before giving up, in ms. */\n    timeout: number;\n    /** Switch the session's language before listening. */\n    language?: string;\n}\n\nexport interface SayOptions {\n    /** Speak this one line in another voice. */\n    voice?: VoiceShortcut;\n    /** Speak this one line in another language. */\n    language?: string;\n    /** Inject the text into the server-side history (inherited from `Call.say`). */\n    addToHistory?: boolean;\n}\n\nexport interface RouteOptions {\n    language?: string;\n    voice?: VoiceShortcut;\n    stt?: STTShortcut;\n    /** Override the agent's own greeting for this hand-over. */\n    greeting?: string;\n    promptVars?: Record<string, string>;\n    /** Keyed context the agent inherits — the same wire as `call.context()`. */\n    context?: Record<string, unknown>;\n    /** Prime the agent with what the line heard. Default true. */\n    history?: boolean;\n}\n\n/** Why the owner swap did not happen. The line is still the owner. */\nexport type RouteFailureReason = \"offline\" | \"unknown\" | \"no_phone_config\" | \"capacity\" | \"swap_failed\";\n\nexport type RouteResult = { ok: true } | { ok: false; reason: RouteFailureReason };\n\n/** A listen in flight: the promise, and the timer that has not started yet. */\ninterface ListenSession {\n    promise: Promise<ListenResult>;\n    /** Arm the timeout. `ask()` arms it only after the line stopped speaking. */\n    start(): void;\n}\n\n/**\n * The `Call` a line's handler receives — a real `Call` (`instanceof Call` is\n * true, and every event and control it has still works) plus the verbs that\n * make a menu possible: an awaitable `say`, a `listen` that races keypad\n * against speech, `ask` as the two together, and `routeTo` as the hand-over.\n *\n * None of them talks to a model.\n */\nexport class LineCall extends Call {\n    /** What the caller said and what the line said back, in order. */\n    #entries: LineTranscriptEntry[] = [];\n    /** Set once the server acked a `call.route` — every verb goes inert after it. */\n    #routed = false;\n    #pendingRoute: ((result: RouteResult) => void) | null = null;\n\n    constructor(data: CallInit, send: (data: Record<string, unknown>) => void) {\n        super(data, send);\n        // The line's transcript is fed from both sides: the caller's confirmed\n        // turns, and every `say()` this object sent.\n        this.on(\"user.message\", (event) => this.#record(\"caller\", event.text));\n    }\n\n    /**\n     * What the line heard and said — `[{ who, text, at }]`.\n     *\n     * Overrides `Call.transcript` (which derives `{role, content}` from the LLM\n     * message list — a line has no LLM). The entries carry `role`/`content`\n     * too, so anything written against a plain Call transcript still reads it.\n     */\n    override get transcript(): LineTranscriptEntry[] {\n        return [...this.#entries];\n    }\n\n    /** True once the call has been handed to an agent. */\n    get routed(): boolean {\n        return this.#routed;\n    }\n\n    // ── say ──────────────────────────────────────────────────────────────\n\n    /**\n     * Speak, and resolve when the audio FINISHED PLAYING —\n     * `{ interrupted: false }` — or when the caller talked over it,\n     * `{ interrupted: true }`. Never rejects; a call that ends mid-sentence\n     * resolves as interrupted.\n     *\n     * `voice`/`language` reconfigure the session for the rest of the call\n     * (`session.configure`), sent before the reply so the line is heard in the\n     * new voice from this sentence on.\n     */\n    override say(text: string, opts?: SayOptions): Promise<SayResult> {\n        if (opts?.voice || opts?.language) {\n            this.update({\n                ...(opts.voice ? { voice: opts.voice } : {}),\n                ...(opts.language ? { language: opts.language } : {}),\n            });\n        }\n        this.#record(\"line\", text);\n        return super.say(text, opts?.addToHistory ? { addToHistory: true } : undefined);\n    }\n\n    // ── listen / ask ─────────────────────────────────────────────────────\n\n    /**\n     * Wait for the FIRST of: the keypad, the caller's speech, or the timeout.\n     *\n     * Both inputs come off the one `CallSession` the agent will keep using\n     * after `routeTo` — same VAD, same STT, same turn detector. There is no\n     * `<Gather>`, no second recognizer, no HTTP round trip.\n     *\n     * `speech` is opt-in: a menu that only takes digits should not wait on VAD.\n     * Every listener is removed the moment it resolves.\n     */\n    listen(opts: ListenOptions): Promise<ListenResult> {\n        return this.#openListen(opts, true).promise;\n    }\n\n    /**\n     * `say` then `listen` — a question.\n     *\n     * The keypad is collected from BEFORE the first syllable: barge-in on a\n     * menu is the normal case, and a caller who knows the menu presses over it.\n     * A press that satisfies the listen **cuts the menu and resolves at once**\n     * — the rest of the sentence is dead air to somebody who already answered.\n     * Otherwise the timeout starts counting the moment the line stops speaking.\n     */\n    async ask(text: string, opts: ListenOptions): Promise<ListenResult> {\n        const session = this.#openListen(opts, false);\n        let spoken = false;\n        const speech = this.say(text).then(() => {\n            spoken = true;\n            session.start();\n        });\n        const result = await session.promise;\n        // Answered while the line was still talking: stop the audio now.\n        // `bot.cancel` makes the server drop what is playing; the pending\n        // `say()` promise settles on the resulting interruption and is\n        // otherwise inert.\n        if (!spoken && result.by !== \"timeout\") this.cancel();\n        void speech.catch(() => {});\n        return result;\n    }\n\n    #openListen(opts: ListenOptions, autoStart: boolean): ListenSession {\n        const wanted = opts.digits ?? 0;\n        const terminator = opts.terminator;\n        let buffer = \"\";\n        let timer: ReturnType<typeof setTimeout> | null = null;\n        let settled = false;\n        let resolveWith!: (result: ListenResult) => void;\n        const promise = new Promise<ListenResult>((resolve) => { resolveWith = resolve; });\n\n        const settle = (result: ListenResult) => {\n            if (settled) return;\n            settled = true;\n            if (timer) { clearTimeout(timer); timer = null; }\n            this.off(\"call.dtmf_received\", onDtmf);\n            this.off(\"turn.end\", onTurn);\n            this.off(\"ended\", onEnded);\n            resolveWith(result);\n        };\n\n        const onDtmf = (event: CallDtmfReceivedEvent) => {\n            const digit = event?.digit ?? \"\";\n            if (!digit) return;\n            if (terminator && digit === terminator) {\n                settle({ by: \"keypad\", digit, digits: buffer });\n                return;\n            }\n            buffer += digit;\n            if (wanted > 0 && buffer.length >= wanted) {\n                settle({ by: \"keypad\", digit, digits: buffer });\n            }\n        };\n        const onTurn = (turn: Turn) => {\n            settle({ by: \"speech\", text: turn.text, confidence: turn.confidence });\n        };\n        // A call that ends under a listen resolves like a timeout: the flow\n        // above gets one answer and one code path, never a dangling promise.\n        const onEnded = () => settle({ by: \"timeout\" });\n\n        this.on(\"call.dtmf_received\", onDtmf);\n        if (opts.speech) this.on(\"turn.end\", onTurn);\n        this.on(\"ended\", onEnded);\n\n        if (opts.language) this.update({ language: opts.language });\n\n        const start = () => {\n            if (settled || timer) return;\n            timer = setTimeout(() => settle({ by: \"timeout\" }), opts.timeout);\n            (timer as { unref?: () => void })?.unref?.();\n        };\n        if (autoStart) start();\n\n        return { promise, start };\n    }\n\n    // ── routeTo ──────────────────────────────────────────────────────────\n\n    /**\n     * Hand the LIVE call to an agent — no re-dial, no drop. The server swaps\n     * the session's owner and config in place; the agent sees a normal\n     * `call.started` with `routed_from`, `extension` and `line_transcript`.\n     *\n     * Resolves `{ ok: true }` once the swap landed, or `{ ok: false, reason }`\n     * with the session untouched — an offline agent is the LINE's decision to\n     * make (say so, forward, hang up, try another), not a 404.\n     */\n    routeTo(agent: string, opts: RouteOptions = {}): Promise<RouteResult> {\n        if (this.#routed) return Promise.resolve({ ok: true });\n        this._sendRaw({\n            event: \"call.route\",\n            call_id: this.id,\n            agent,\n            ...(opts.language ? { language: opts.language } : {}),\n            ...(opts.voice ? { voice: opts.voice } : {}),\n            ...(opts.stt ? { stt: opts.stt } : {}),\n            ...(opts.greeting ? { greeting: opts.greeting } : {}),\n            ...(opts.promptVars ? { prompt_vars: opts.promptVars } : {}),\n            ...(opts.context ? { context: opts.context } : {}),\n            history: opts.history !== false,\n        });\n        return new Promise<RouteResult>((resolve) => {\n            // A call that dies between `call.route` and its answer is a failed\n            // swap, not a hung promise.\n            const onEnded = () => {\n                this.#pendingRoute = null;\n                resolve({ ok: false, reason: \"swap_failed\" });\n            };\n            this.on(\"ended\", onEnded);\n            this.#pendingRoute = (result) => {\n                this.off(\"ended\", onEnded);\n                resolve(result);\n            };\n        });\n    }\n\n    // ── The rest of the verbs ────────────────────────────────────────────\n\n    /** Hang up, with a reason the call log keeps. */\n    override hangup(reason?: string): void {\n        this._sendRaw({\n            event: \"call.hangup\",\n            call_id: this.id,\n            ...(reason ? { reason } : {}),\n        });\n    }\n\n    /**\n     * Set keyed context on the session. It SURVIVES `routeTo`, so the agent\n     * inherits what the line learned before it ever saw the call.\n     */\n    context(key: string, value: unknown): void {\n        this._sendRaw({ event: \"set_context\", call_id: this.id, key, value });\n    }\n\n    // ── Dispatch-only API (friend methods) ───────────────────────────────\n\n    /** @internal The server acked `call.route` — the agent owns the session now. */\n    _applyRouted(agent: string): void {\n        this.#routed = true;\n        // The Call object goes inert: the server's `call.ended (routed)` is\n        // what actually ends it, and until then nothing this object sends\n        // belongs to anybody.\n        this.status = \"ended\";\n        this.reason = \"routed\";\n        const resolve = this.#pendingRoute;\n        this.#pendingRoute = null;\n        resolve?.({ ok: true });\n        this._emitWire(\"call.routed\", { event: \"call.routed\", callId: this.id, agent });\n    }\n\n    /** @internal The swap did not happen. The line is still the owner. */\n    _applyRouteFailed(agent: string, reason: RouteFailureReason): void {\n        const resolve = this.#pendingRoute;\n        this.#pendingRoute = null;\n        resolve?.({ ok: false, reason });\n        this._emitWire(\"call.route_failed\", { event: \"call.route_failed\", callId: this.id, agent, reason });\n    }\n\n    #record(who: \"caller\" | \"line\", text: string): void {\n        if (!text) return;\n        this.#entries.push({\n            who,\n            text,\n            at: Date.now(),\n            role: who === \"caller\" ? \"user\" : \"assistant\",\n            content: text,\n        });\n    }\n}\n\n// ─── The registry entry ──────────────────────────────────────────────────\n\n/**\n * The line's face in the client's agent registry.\n *\n * Not public and not an agent anyone can configure: it exists so that\n * `agent_id: \"line:<number>\"` resolves, and so `call.started` builds a\n * {@link LineCall}. Everything else — the events, the calls map, the pending\n * queue, the reconnect discipline — is `Agent`'s, unchanged.\n */\nclass LineAgent extends Agent {\n    override _createCall(data: CallInit, send: (data: Record<string, unknown>) => void): Call {\n        return new LineCall(data, send);\n    }\n}\n\n// ─── PhoneLine ───────────────────────────────────────────────────────────\n\nexport interface PhoneLineEvents {\n    [key: string]: (...args: any[]) => void;\n    /** The server registered the line; the number is ours. */\n    ready: () => void;\n    /** The registration was refused. `error.code` is the server's `LINE_*` code. */\n    error: (error: PinecallError) => void;\n    /** An inbound call, connected and HELD for this handler. Fires after the extension window. */\n    call: (call: LineCall) => void | Promise<void>;\n    /** Ended at any stage, including mid-menu. `reason` is `\"routed\"` after a hand-over. */\n    \"call.ended\": (call: LineCall, reason: string) => void;\n}\n\nexport class PhoneLine extends TypedEventBus<PhoneLineEvents> {\n    /** The number this line owns, E.164 or `sip:`. */\n    readonly number: string;\n    /** How the server addresses this line: `line:<number>`. */\n    readonly id: string;\n\n    readonly #agent: LineAgent;\n    readonly #opts: LineOptions;\n    readonly #sendRaw: (data: Record<string, unknown>) => void;\n    #extensions: ExtensionTable | null = null;\n    /** call_id → already told the app it ended. One emission, whichever path got there first. */\n    readonly #ended = new Set<string>();\n\n    /** @internal — created by Pinecall.line() */\n    constructor(number: string, opts: LineOptions, send: (data: Record<string, unknown>) => void) {\n        super();\n        this.number = number;\n        this.id = `line:${number}`;\n        this.#opts = opts;\n        this.#sendRaw = send;\n        this.#agent = new LineAgent(this.id, {}, send);\n\n        this.#agent.on(\"call.started\", (call) => { void this.#onCall(call as LineCall); });\n        this.#agent.on(\"call.ended\", (call, reason) => this.#onCallEnded(call as LineCall, reason));\n    }\n\n    // ── Public getters ───────────────────────────────────────────────────\n\n    /** True once the SERVER acknowledged the line (`line.created`). */\n    get registered(): boolean {\n        return this.#agent.registered;\n    }\n\n    /** Resolves on `line.created`. Goes back to pending across a reconnect, like an agent's. */\n    get ready(): Promise<void> {\n        return this.#agent.ready;\n    }\n\n    /** Calls this line is currently holding. */\n    get calls(): ReadonlyMap<string, LineCall> {\n        return this.#agent.calls as ReadonlyMap<string, LineCall>;\n    }\n\n    // ── Routing table ────────────────────────────────────────────────────\n\n    /**\n     * Declare where each extension goes: an agent slug, or code.\n     *\n     * Runs BEFORE the `call` listeners, and a match consumes the call. `\"*\"`\n     * catches the no-extension and unmatched cases; with neither a match nor a\n     * `\"*\"`, the call falls through to `line.on(\"call\")`.\n     */\n    extensions(map: ExtensionTable): this {\n        this.#extensions = map;\n        return this;\n    }\n\n    /** Release the number. The server answers `line.destroyed`. */\n    destroy(): void {\n        this.#agent.send({ event: \"line.destroy\", number: this.number });\n    }\n\n    // ── Client-only API (friend methods) ─────────────────────────────────\n\n    /** @internal The registry entry dispatch routes `line:<number>` events to. */\n    get _agent(): Agent {\n        return this.#agent;\n    }\n\n    /**\n     * @internal Claim the number. Sent on connect and re-sent on every\n     * reconnect, exactly like an agent's `agent.create` — a line that comes\n     * back has to take its number back or the number is stranded.\n     */\n    _register(): void {\n        // Straight down the socket, NOT through the agent's queue: this frame\n        // is what makes the line server-ready, so it cannot wait on it.\n        this.#sendRaw({ event: \"line.create\", number: this.number, config: this.#wireConfig() });\n    }\n\n    /** @internal `line.created` — the line exists server-side from here on. */\n    _markCreated(): void {\n        this.#agent._flushPending();\n        this.#agent._markRegistered();\n        this.emit(\"ready\");\n    }\n\n    /** @internal `line.error` — refused, with the server's code. */\n    _markError(code: string, message: string): void {\n        this.emit(\"error\", new PinecallError(message, code));\n    }\n\n    /** @internal The socket dropped — `ready` goes back to pending. */\n    _markUnregistered(): void {\n        this.#agent._markUnregistered();\n    }\n\n    /** @internal End every call this line is holding (disconnect). */\n    _endAllCalls(reason: string): void {\n        this.#agent._endAllCalls(reason);\n    }\n\n    /** @internal Find a call this line is holding, by id. */\n    _getCall(callId: string): LineCall | undefined {\n        return this.#agent._getCall(callId) as LineCall | undefined;\n    }\n\n    // ── Internals ────────────────────────────────────────────────────────\n\n    /**\n     * The line's pipeline on the wire — the same shortcut resolution an agent's\n     * config gets, plus the two keys only a line has.\n     */\n    #wireConfig(): Record<string, unknown> {\n        const { turnDetection, extension } = this.#opts;\n        return {\n            ...buildShortcutPayload({\n                stt: this.#opts.stt,\n                voice: this.#opts.voice,\n                language: this.#opts.language,\n            }),\n            ...(turnDetection !== undefined ? { turn_detection: turnDetection } : {}),\n            extension_window_ms: extension?.window ?? DEFAULT_EXTENSION_WINDOW_MS,\n        };\n    }\n\n    /**\n     * Extensions first, `call` listeners second.\n     *\n     * A declared extension consumes the call: an app that wants both writes the\n     * fall-through itself, in the function it registered.\n     */\n    async #onCall(call: LineCall): Promise<void> {\n        const table = this.#extensions;\n        const entry = table ? this.#match(table, call.extension) : undefined;\n        if (entry === undefined) {\n            this.emit(\"call\", call);\n            return;\n        }\n        try {\n            if (typeof entry === \"string\") await call.routeTo(entry);\n            else await entry(call);\n        } catch (err) {\n            this.emit(\"error\", err instanceof PinecallError\n                ? err\n                : new PinecallError(`Extension handler failed: ${String(err)}`, \"LINE_EXTENSION_ERROR\"));\n        }\n    }\n\n    #match(table: ExtensionTable, extension: string | null): ExtensionTable[string] | undefined {\n        if (extension !== null && Object.prototype.hasOwnProperty.call(table, extension)) {\n            return table[extension];\n        }\n        return Object.prototype.hasOwnProperty.call(table, \"*\") ? table[\"*\"] : undefined;\n    }\n\n    /** One `call.ended` per call, whichever path got there first. */\n    #onCallEnded(call: LineCall, reason: string): void {\n        if (this.#ended.has(call.id)) return;\n        this.#ended.add(call.id);\n        this.emit(\"call.ended\", call, reason);\n    }\n}\n\n// ─── Construction ────────────────────────────────────────────────────────\n\n/**\n * Validate the options and normalise the number. Called by `pc.line()` so a\n * config that implies a model fails on the line that wrote it, not three\n * seconds later on a socket.\n */\nexport function prepareLine(number: string, opts: LineOptions): string {\n    for (const key of REFUSED_KEYS) {\n        if ((opts as Record<string, unknown>)[key] !== undefined) {\n            throw new PinecallError(\n                `pc.line() does not take \\`${key}\\`: a line has no model — its first words are code. ` +\n                `Say them with \\`call.say()\\`, or hand the call to an agent with \\`call.routeTo(\"<slug>\")\\`.`,\n                \"LINE_CONFIG_ERROR\",\n            );\n        }\n    }\n    return normalizeNumber(number);\n}\n\n/** E.164 or a SIP URI — the same shapes `addPhoneNumber` accepts. */\nfunction normalizeNumber(number: string): string {\n    if (number.startsWith(\"sip:\")) return number;\n    const cleaned = number.replace(/[\\s\\-()]/g, \"\");\n    const normalized = cleaned.startsWith(\"+\") ? cleaned : \"+\" + cleaned;\n    const digits = normalized.slice(1);\n    if (!/^\\d+$/.test(digits) || digits.length < 7 || digits.length > 15) {\n        throw new Error(`Invalid phone number \"${number}\": must be E.164 format (+, 7-15 digits)`);\n    }\n    return normalized;\n}\n","/**\n * The Call Log — envelope + closed vocabulary (CALL_LOG_SPEC.md §1, §2).\n *\n * ─────────────────────────────────────────────────────────────────────────\n * WIRE SHAPE. This module speaks the WIRE, verbatim.\n *\n * Envelope keys are exactly the seven of spec §1 (`seq`, `ts`, `call`,\n * `agent`, `type`, `ephemeral`, `data`) and every key INSIDE `data` is\n * snake_case, exactly as the server appends it. There is deliberately NO\n * codec in the path: the server emits an envelope, the browser applies that\n * same envelope, and `GET /v1/calls/{id}/events` returns the same bytes\n * during the call and after it (spec §10.4). A camelCase translation layer\n * would make \"identical\" a claim about a transform rather than about bytes.\n *\n * `src/protocol/events.ts` (camelCase, legacy SDK surface) is a DIFFERENT,\n * frozen vocabulary and stays untouched — see spec §8.\n * ─────────────────────────────────────────────────────────────────────────\n *\n * ZERO DEPENDENCIES. Nothing under `src/log/**` imports anything outside\n * itself. The `@pinecall/sdk` root entrypoint pulls in `ws` and node\n * builtins; the `./log` subpath must be usable from a browser bundle, so\n * the isolation is enforced by a test (`tests/log-browser-safe.test.ts`).\n *\n * FORWARD COMPATIBILITY. Unknown `type`s MUST be ignored (§1). The unions\n * below are closed for what a consumer may *rely* on, not for what may\n * arrive: `AnyLogEntry` therefore admits an unknown-type arm, and the\n * reducer's switch is exhaustive over the known arms.\n */\n\nimport type { LogGapSnapshot } from \"./view.js\";\n\n// ── §1 The envelope ──────────────────────────────────────────────────────\n\n/** Every fact a session produces becomes exactly one of these. */\nexport interface LogEntry<T extends LogEventType = LogEventType, D = LogData<T>> {\n    /**\n     * Monotonic per call, assigned only at the append point. The cursor AND\n     * the dedupe key. May have holes after compaction — never assume\n     * contiguity; \"caught up\" is signalled by `log.caught_up`, never inferred.\n     */\n    seq: number;\n    /** Server wall clock, float seconds. */\n    ts: number;\n    /** Call id. `null` on the agent's lifecycle-only log (§2, \"The agent log\"). */\n    call: string | null;\n    /** Agent id. */\n    agent: string;\n    /** One vocabulary (§2). No per-channel dialects. */\n    type: T;\n    /** `true` → delivered live, never persisted (§4). */\n    ephemeral: boolean;\n    /** Type-specific payload (§2). Additive-only per type. */\n    data: D;\n}\n\n// ── §2 The vocabulary — data payloads ────────────────────────────────────\n\nexport type CallDirection = \"inbound\" | \"outbound\";\n\n/** `call.ringing` — outbound: exists before pickup. */\nexport interface CallRingingData {\n    direction: CallDirection;\n    from: string;\n    to: string;\n}\n\n/** `call.started` — `metadata` is the sealed token metadata. */\nexport interface CallStartedData {\n    direction: CallDirection;\n    from: string;\n    to: string;\n    channel: string;\n    metadata?: Record<string, unknown>;\n}\n\n/** `call.ended` */\nexport interface CallEndedData {\n    reason: string;\n    duration: number;\n}\n\n/** One latency distribution inside `call.summary`. */\nexport interface MetricDistribution {\n    p50: number;\n    p90: number;\n    p95: number;\n    max: number;\n    n: number;\n}\n\nexport interface CallSummaryMetrics {\n    e2e: MetricDistribution;\n    asr: MetricDistribution;\n    llm_ttft: MetricDistribution;\n    tts_ttfb: MetricDistribution;\n}\n\n/** `call.summary` — ALWAYS the last entry. History needs no second API. */\nexport interface CallSummaryData {\n    metrics: CallSummaryMetrics;\n    cost?: number;\n    reason: string;\n    /** Recordings are referenced, never embedded (§8). */\n    recording_url?: string;\n}\n\n/** `user.speaking` — ephemeral. */\nexport interface UserSpeakingData {\n    active: boolean;\n}\n\n/** `user.message` — partials ephemeral, finals persisted. */\nexport interface UserMessageData {\n    id: string;\n    text: string;\n    final: boolean;\n    language?: string;\n}\n\n/** One word of TTS alignment, carried INSIDE `bot.speaking`. */\nexport interface WordTiming {\n    w: string;\n    t0: number;\n    t1: number;\n}\n\n/** `bot.speaking` — word alignment inside the event when TTS provides it. */\nexport interface BotSpeakingData {\n    id: string;\n    text: string;\n    words?: WordTiming[];\n}\n\n/** `bot.word` — ephemeral; live typing effect only. */\nexport interface BotWordData {\n    id: string;\n    w: string;\n}\n\n/** `bot.finished` */\nexport interface BotFinishedData {\n    id: string;\n}\n\n/** `bot.interrupted` */\nexport interface BotInterruptedData {\n    id: string;\n    at_word?: number;\n}\n\n/**\n * `bot.corrected` — the transcript self-heals. An EVENT, not a mutation:\n * consumers replace the text of the entry named by `supersedes`.\n */\nexport interface BotCorrectedData {\n    supersedes: number;\n    id: string;\n    text: string;\n}\n\nexport type TurnRole = \"user\" | \"bot\";\n\n/** `turn.start` */\nexport interface TurnStartData {\n    turn: number;\n    role: TurnRole;\n}\n\n/** Per-turn latency is first-class. */\nexport interface TurnLatency {\n    vad: number;\n    asr: number;\n    eou: number;\n    llm_ttft: number;\n    tts_ttfb: number;\n    e2e: number;\n}\n\n/** `turn.end` */\nexport interface TurnEndData {\n    turn: number;\n    latency: TurnLatency;\n}\n\n/** `tool.call` — reaches EVERY audience, correlated with `tool.result` by `id`. */\nexport interface ToolCallData {\n    id: string;\n    name: string;\n    /** Providers send either a parsed object or a JSON string. Both are legal. */\n    args: Record<string, unknown> | string;\n}\n\n/** `tool.result` */\nexport interface ToolResultData {\n    id: string;\n    name: string;\n    result: unknown;\n    ms: number;\n    error?: string;\n}\n\n/** `docs.sources` — RAG citations. */\nexport interface DocsSourcesData {\n    sources: unknown[];\n}\n\n/** `skill.loaded` / `skill.unloaded` */\nexport interface SkillData {\n    skill: string;\n    by: string;\n}\n\n/** `audio.metrics` — ephemeral; rolled up into `call.summary`. */\nexport interface AudioMetricsData {\n    mos?: number;\n    jitter?: number;\n    loss?: number;\n    [k: string]: unknown;\n}\n\n/** `handoff.requested` / `handoff.active` / `handoff.released` */\nexport interface HandoffData {\n    by: string;\n}\n\n/** `supervisor.said` / `supervisor.whispered` — audit trail of the §7 verbs. */\nexport interface SupervisorData {\n    text: string;\n    by: string;\n}\n\n/**\n * `log.gap` (§3, anti-Slack rule) — a gap is DECLARED, never silently\n * papered over. `snapshot` is consolidated call state so the consumer can\n * render immediately and continue from `resume_from`.\n */\nexport interface LogGapData {\n    from: number;\n    resume_from: number;\n    /** Consolidated state — see `LogGapSnapshot` in view.ts for the exact keys. */\n    snapshot?: LogGapSnapshot;\n}\n\n/** `log.caught_up` (§5) — backlog drained, live entries follow. */\nexport interface LogCaughtUpData {\n    seq: number;\n}\n\n/**\n * `custom` — the one open extension point: `call.log(name, value)`. The\n * reducer never interprets `value`; it projects the latest value per\n * `(name, id)` into `state.custom` (upsert — the wire itself stays\n * append-only). Ephemeral ones are fanned out live and never stored.\n */\nexport interface CustomData {\n    name: string;\n    value: unknown;\n    /** Upsert key in the projection; absent → the entry's seq. */\n    id?: string;\n    /** Server-stamped turn id, when the session has turns. */\n    turn?: number;\n}\n\n// ── The closed type union ────────────────────────────────────────────────\n\n/**\n * The complete vocabulary. A fact that does not fit one of these is a\n * finding to report, not a new type to mint.\n */\nexport interface LogDataMap {\n    \"call.ringing\": CallRingingData;\n    \"call.started\": CallStartedData;\n    \"call.ended\": CallEndedData;\n    \"call.summary\": CallSummaryData;\n    \"user.speaking\": UserSpeakingData;\n    \"user.message\": UserMessageData;\n    \"bot.speaking\": BotSpeakingData;\n    \"bot.word\": BotWordData;\n    \"bot.finished\": BotFinishedData;\n    \"bot.interrupted\": BotInterruptedData;\n    \"bot.corrected\": BotCorrectedData;\n    \"turn.start\": TurnStartData;\n    \"turn.end\": TurnEndData;\n    \"tool.call\": ToolCallData;\n    \"tool.result\": ToolResultData;\n    \"docs.sources\": DocsSourcesData;\n    \"skill.loaded\": SkillData;\n    \"skill.unloaded\": SkillData;\n    \"audio.metrics\": AudioMetricsData;\n    \"handoff.requested\": HandoffData;\n    \"handoff.active\": HandoffData;\n    \"handoff.released\": HandoffData;\n    \"supervisor.said\": SupervisorData;\n    \"supervisor.whispered\": SupervisorData;\n    \"log.gap\": LogGapData;\n    \"log.caught_up\": LogCaughtUpData;\n    \"custom\": CustomData;\n}\n\n/** Every legal `type` value. Closed — see §2. */\nexport type LogEventType = keyof LogDataMap;\n\n/** The payload that belongs to a given `type`. */\nexport type LogData<T extends LogEventType> = LogDataMap[T];\n\n/** The discriminated union of all known entries — what the reducer switches on. */\nexport type KnownLogEntry = {\n    [T in LogEventType]: LogEntry<T, LogDataMap[T]>;\n}[LogEventType];\n\n/**\n * An entry as it arrives off the wire: either a known one, or one whose\n * `type` this SDK version has never heard of. §1 requires the latter be\n * ignored rather than rejected, so it is part of the input type.\n */\nexport type UnknownLogEntry = Omit<LogEntry<LogEventType, unknown>, \"type\"> & {\n    type: string;\n};\n\nexport type AnyLogEntry = KnownLogEntry | UnknownLogEntry;\n\n/** The set of `type` values this build understands. */\nexport const LOG_EVENT_TYPES: readonly LogEventType[] = [\n    \"call.ringing\",\n    \"call.started\",\n    \"call.ended\",\n    \"call.summary\",\n    \"user.speaking\",\n    \"user.message\",\n    \"bot.speaking\",\n    \"bot.word\",\n    \"bot.finished\",\n    \"bot.interrupted\",\n    \"bot.corrected\",\n    \"turn.start\",\n    \"turn.end\",\n    \"tool.call\",\n    \"tool.result\",\n    \"docs.sources\",\n    \"skill.loaded\",\n    \"skill.unloaded\",\n    \"audio.metrics\",\n    \"handoff.requested\",\n    \"handoff.active\",\n    \"handoff.released\",\n    \"supervisor.said\",\n    \"supervisor.whispered\",\n    \"log.gap\",\n    \"log.caught_up\",\n    \"custom\",\n] as const;\n\nconst KNOWN = new Set<string>(LOG_EVENT_TYPES);\n\n/** Narrow an off-the-wire entry to the known vocabulary. */\nexport function isKnownLogEntry(entry: AnyLogEntry): entry is KnownLogEntry {\n    return KNOWN.has(entry.type);\n}\n\n/**\n * Structural check for the §1 envelope. Anything that fails this is not a\n * log entry and must not be fed to a view.\n */\nexport function isLogEntry(value: unknown): value is AnyLogEntry {\n    if (typeof value !== \"object\" || value === null) return false;\n    const v = value as Record<string, unknown>;\n    return (\n        typeof v.seq === \"number\" &&\n        typeof v.ts === \"number\" &&\n        typeof v.type === \"string\" &&\n        typeof v.agent === \"string\" &&\n        (typeof v.call === \"string\" || v.call === null)\n    );\n}\n","/**\n * CallLogView — THE reducer (CALL_LOG_SPEC.md §6).\n *\n * \"Client SDKs maintain ONE reducer (log → {phase, messages, toolCalls,\n * turns, metrics}) fed by any pipe, deduped by seq.\"\n *\n * This is the whole point of the module: WS attach, WebRTC DataChannel, GET\n * polling and replay are four pipes carrying one envelope, and they must\n * land on one piece of state-building code. A second reducer would be a\n * second vocabulary in disguise.\n *\n * ── Semantics ────────────────────────────────────────────────────────────\n * Ported from the proven `VoiceSession.handleDataChannelMessage` switch\n * (@pinecall/web, src/core/VoiceSession.ts:303-502) — word reassembly,\n * `mergeUserTurn` interim merging, tool-argument parsing — with four\n * deliberate corrections:\n *\n *   1. NO transport coupling and no `trackedTools` filter. The view exposes\n *      every tool call; a UI that wants a subset filters at render time.\n *      Filtering during reduction makes the state depend on widget config.\n *   2. NO `disconnect()` back-edge. VoiceSession called `this.disconnect()`\n *      from inside the switch (:418) — a reducer reaching into a socket.\n *      Here, terminal facts produce an *intent* on the state; the owner of\n *      the transport decides what to do about it.\n *   3. Duration is derived from entry `ts`, never from wall clock, so a\n *      replay of a finished call reproduces the same state as watching it\n *      live (§10.5).\n *   4. `phase` gains \"ended\", and `bot.corrected` REPLACES the text of the\n *      entry it supersedes (§2) rather than appending a second bubble.\n *\n * ── Idempotence and order independence ───────────────────────────────────\n * `apply()` is idempotent by `seq` and independent of arrival order. It is\n * not a naive running fold: entries are retained in a seq-keyed map and the\n * state is the fold over them in seq order. Applying an entry newer than\n * everything seen (the live case) folds incrementally in O(1); an\n * out-of-order or backfilled entry rebuilds, which is what correctness\n * costs and what makes in-order === shuffled === resumed.\n *\n * ── Immutability ─────────────────────────────────────────────────────────\n * State is produced by structural sharing, never by mutation: an apply\n * yields a new state object, new arrays, and new objects for exactly the\n * entries it changed. Reference equality on a message therefore MEANS \"this\n * line did not change\" — the contract a memoized transcript line depends on.\n */\n\nimport type {\n    AnyLogEntry,\n    CallSummaryData,\n    KnownLogEntry,\n    TurnLatency,\n    TurnRole,\n    WordTiming,\n} from \"./types.js\";\nimport { isKnownLogEntry, isLogEntry } from \"./types.js\";\n\n// ── State ────────────────────────────────────────────────────────────────\n\nexport type CallPhase =\n    | \"idle\"\n    | \"ringing\"\n    | \"listening\"\n    | \"thinking\"\n    | \"speaking\"\n    | \"ended\";\n\nexport type MessageRole = \"user\" | \"bot\" | \"system\";\n\n/** One transcript bubble. `seq` is the entry that created it — `bot.corrected.supersedes` points here. */\nexport interface CallMessage {\n    /** The seq of the entry that created this message. Stable identity. */\n    seq: number;\n    role: MessageRole;\n    text: string;\n    /** Provider message id (`user.message.id`, `bot.speaking.id`, …). */\n    id?: string;\n    /** True while a non-final `user.message` is the latest word on this turn. */\n    interim?: boolean;\n    /** True between `bot.speaking` and `bot.finished`/`bot.interrupted`. */\n    speaking?: boolean;\n    interrupted?: boolean;\n    /** Set on the system bubble that mirrors a `tool.call`. */\n    toolCallId?: string;\n    /** Word alignment when TTS provided it (`bot.speaking.words`). */\n    words?: WordTiming[];\n    /** True once a `bot.corrected` entry replaced this text. */\n    corrected?: boolean;\n}\n\nexport interface CallToolCall {\n    id: string;\n    name: string;\n    args: Record<string, unknown>;\n    /** seq of the `tool.call` entry. */\n    seq: number;\n    /** Present once the correlated `tool.result` arrives. */\n    result?: unknown;\n    ms?: number;\n    error?: string;\n    done: boolean;\n}\n\nexport interface CallTurn {\n    turn: number;\n    role?: TurnRole;\n    latency?: TurnLatency;\n    startedAt?: number;\n    endedAt?: number;\n}\n\nexport interface CallMetrics {\n    /** Rolled-up distributions, present once `call.summary` lands. */\n    summary?: CallSummaryData[\"metrics\"];\n    cost?: number;\n    recordingUrl?: string;\n    /** Mean end-to-end latency over the `turn.end` entries seen so far. */\n    e2eMean?: number;\n    turnCount: number;\n}\n\n/**\n * Something the log says should happen to the transport, surfaced instead of\n * done. Correction #2 above: the reducer never touches a socket.\n */\nexport interface CallIntent {\n    kind: \"disconnect\";\n    reason: string;\n    seq: number;\n}\n\n/**\n * One row of `state.custom`: the latest value per `(name, id)`, in first-seen\n * order. The wire stays append-only — every `call.log()` is its own entry\n * with its own seq — the upsert is a projection of this reducer only.\n */\nexport interface CallCustomEntry<V = unknown> {\n    name: string;\n    /** `data.id ?? String(seq)` — the upsert key together with `name`. */\n    id: string;\n    value: V;\n    /** seq of the entry that LAST set this value. */\n    seq: number;\n    ts: number;\n    /** Server-stamped turn id, when the session has turns. */\n    turn?: number;\n}\n\nexport interface CallLogState {\n    phase: CallPhase;\n    messages: CallMessage[];\n    toolCalls: CallToolCall[];\n    turns: CallTurn[];\n    metrics: CallMetrics;\n    /** False once `call.ended` is applied. */\n    live: boolean;\n    /** Highest seq applied. The cursor to resume from (`after=`). */\n    lastSeq: number;\n    /** Call id, from the first entry that carried one. */\n    call: string | null;\n    agent: string | null;\n    /** Seconds, derived from entry `ts` — never from wall clock. */\n    duration: number;\n    /** True after `log.caught_up`; never inferred from contiguity (§1). */\n    caughtUp: boolean;\n    /** Declared gaps (§3). Never silently papered over. */\n    gaps: { from: number; resumeFrom: number }[];\n    userSpeaking: boolean;\n    botSpeaking: boolean;\n    /** Reason from `call.ended`, if any. */\n    endedReason?: string;\n    /** Human takeover state (`handoff.*`). */\n    handoff: \"none\" | \"requested\" | \"active\";\n    /** Skills currently loaded (`skill.loaded` / `skill.unloaded`). */\n    skills: string[];\n    /** Latest RAG citations (`docs.sources`). */\n    sources: unknown[];\n    /** Things the log asked the transport to do (§ correction #2). */\n    intents: CallIntent[];\n    /** Durable `custom` entries, upserted by (name, id). Ephemeral ones never land here. */\n    custom: CallCustomEntry[];\n}\n\nfunction emptyState(): CallLogState {\n    return {\n        phase: \"idle\",\n        messages: [],\n        toolCalls: [],\n        turns: [],\n        metrics: { turnCount: 0 },\n        live: true,\n        lastSeq: 0,\n        call: null,\n        agent: null,\n        duration: 0,\n        caughtUp: false,\n        gaps: [],\n        userSpeaking: false,\n        botSpeaking: false,\n        handoff: \"none\",\n        skills: [],\n        sources: [],\n        intents: [],\n        custom: [],\n    };\n}\n\n/**\n * What a `log.gap` carries in `data.snapshot` — the consolidated state of\n * everything the server could still see when it declared the gap, so a\n * client lands with a populated view instead of an empty one (§3, ag-ui\n * \"For Pinecall\" 5 and 9). This is the wire contract between\n * `calls_api._snapshot()` and `CallLogView`: the server emits exactly these\n * keys, the reducer hydrates exactly these fields.\n *\n * Rows reuse the reducer's own row types, so hydration is a keyed merge\n * rather than a second fold: `messages` by `seq` (bot bubbles by `id`),\n * `tool_calls` by `id`, `turns` by `turn`, `custom` by `(name, id)`.\n * Scalars are values — the snapshot's word wins. Every key is optional: a\n * missing key leaves the local state untouched, and an unknown key is\n * ignored (§1 forward compatibility).\n *\n * Not carried, by design: `metrics.summary`/`cost` (only `call.summary` sets\n * them, and it is never skipped — a sealed cursor answers 204), `intents`\n * (transport asks, not call facts) and the `log.*` control state.\n */\nexport interface LogGapSnapshot {\n    phase?: CallPhase;\n    live?: boolean;\n    /** ts of `call.started` — the duration anchor. */\n    started_at?: number | null;\n    ended_reason?: string;\n    user_speaking?: boolean;\n    bot_speaking?: boolean;\n    handoff?: CallLogState[\"handoff\"];\n    skills?: string[];\n    sources?: unknown[];\n    messages?: CallMessage[];\n    tool_calls?: CallToolCall[];\n    turns?: CallTurn[];\n    custom?: CallCustomEntry[];\n}\n\n/**\n * Project a state into the snapshot a `log.gap` would carry for it — the\n * inverse of hydration. The golden test feeds `snapshotOf(prefix)` into a\n * gap and asserts the result equals the full replay; a server that wants\n * to mint gaps against a TS reducer can use it directly.\n */\nexport function snapshotOf(state: Readonly<CallLogState>, startedAt: number | null = null): LogGapSnapshot {\n    return {\n        phase: state.phase,\n        live: state.live,\n        started_at: startedAt,\n        ...(state.endedReason !== undefined ? { ended_reason: state.endedReason } : {}),\n        user_speaking: state.userSpeaking,\n        bot_speaking: state.botSpeaking,\n        handoff: state.handoff,\n        skills: [...state.skills],\n        sources: [...state.sources],\n        messages: state.messages.map((m) => ({ ...m })),\n        tool_calls: state.toolCalls.map((t) => ({ ...t })),\n        turns: state.turns.map((t) => ({ ...t })),\n        custom: state.custom.map((c) => ({ ...c })),\n    };\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────────\n\n/**\n * Merge a user transcript into the CURRENT turn's user bubble — the last\n * user message with no bot reply after it — instead of appending a new one.\n * STT emits several interim AND several final transcripts per turn (Deepgram\n * Flux fires multiple finals), so appending per event duplicates the bubble.\n * A new turn starts only after a bot reply. Ported verbatim in spirit from\n * VoiceSession.ts:38-50.\n */\nfunction mergeUserTurn(\n    messages: CallMessage[],\n    seq: number,\n    id: string,\n    text: string,\n    interim: boolean,\n): void {\n    let lastUser = -1;\n    for (let i = messages.length - 1; i >= 0; i--) {\n        if (messages[i]!.role === \"user\") { lastUser = i; break; }\n    }\n    let botAfter = false;\n    for (let i = lastUser + 1; i < messages.length; i++) {\n        if (messages[i]!.role === \"bot\") { botAfter = true; break; }\n    }\n    if (lastUser >= 0 && !botAfter) {\n        const m = cow(messages, lastUser);\n        m.text = text;\n        m.interim = interim;\n        m.id = id;\n        return;\n    }\n    messages.push({ seq, role: \"user\", text, id, interim });\n}\n\n/**\n * Copy-on-write: replace `list[i]` with a shallow copy and return it, so the\n * caller mutates the copy and never an object a consumer already holds.\n *\n * Structural sharing of the touched path, not a deep clone — untouched\n * siblings keep their references. This matters because the hottest render\n * path in the whole system is word-by-word typing (`bot.word`), where the\n * obvious consumer optimization is a memoized transcript line keyed on the\n * message object. Mutating in place under a stable reference makes that line\n * freeze mid-sentence while the text underneath keeps changing; a fresh\n * ARRAY reference does not help, because the memo never looks at the array.\n * VoiceSession got this right by replacing the tail object per word, so the\n * reducer that supersedes it must not regress there.\n */\nfunction cow<T extends object>(list: T[], i: number): T {\n    const copy = { ...list[i]! };\n    list[i] = copy;\n    return copy;\n}\n\n/** Tool args arrive parsed or as a JSON string, depending on the provider. */\nfunction parseArgs(args: Record<string, unknown> | string): Record<string, unknown> {\n    if (typeof args !== \"string\") return args ?? {};\n    try {\n        const parsed: unknown = JSON.parse(args);\n        return typeof parsed === \"object\" && parsed !== null\n            ? (parsed as Record<string, unknown>)\n            : {};\n    } catch {\n        return {};\n    }\n}\n\n/** A `tool.result` may carry a JSON string; surface the parsed value. */\nfunction parseResult(result: unknown): unknown {\n    if (typeof result !== \"string\") return result;\n    try {\n        return JSON.parse(result);\n    } catch {\n        return result;\n    }\n}\n\nconst PHASES: ReadonlySet<string> = new Set([\"idle\", \"ringing\", \"listening\", \"thinking\", \"speaking\", \"ended\"]);\nconst HANDOFFS: ReadonlySet<string> = new Set([\"none\", \"requested\", \"active\"]);\n\nfunction isRecord(v: unknown): v is Record<string, unknown> {\n    return typeof v === \"object\" && v !== null && !Array.isArray(v);\n}\n\n/** Rows of a snapshot array that are at least objects; anything else is ignored (§1). */\nfunction rows<T>(v: unknown, ok: (r: Record<string, unknown>) => boolean): T[] {\n    if (!Array.isArray(v)) return [];\n    return v.filter((r): r is Record<string, unknown> => isRecord(r) && ok(r)) as unknown as T[];\n}\n\n// ── The reducer ──────────────────────────────────────────────────────────\n\n/** Mutable scratch carried across the fold — never part of the public state. */\ninterface FoldContext {\n    /** Live word buffers keyed by bot message id (`bot.word` reassembly). */\n    botWords: Map<string, string[]>;\n    /** bot message id → index in `messages`. */\n    botIndex: Map<string, number>;\n    /** tool call id → index in `toolCalls`. */\n    toolIndex: Map<string, number>;\n    /** turn number → index in `turns`. */\n    turnIndex: Map<number, number>;\n    /** message seq → index in `messages` (for `bot.corrected.supersedes`). */\n    bySeq: Map<number, number>;\n    /** `name + \"/\" + id` → index in `custom` (the (name, id) upsert). */\n    customIndex: Map<string, number>;\n    /** ts of the first entry / of `call.started`. */\n    startTs: number | null;\n    lastTs: number | null;\n    e2eSum: number;\n    e2eN: number;\n}\n\nfunction emptyContext(): FoldContext {\n    return {\n        botWords: new Map(),\n        botIndex: new Map(),\n        toolIndex: new Map(),\n        turnIndex: new Map(),\n        bySeq: new Map(),\n        customIndex: new Map(),\n        startTs: null,\n        lastTs: null,\n        e2eSum: 0,\n        e2eN: 0,\n    };\n}\n\n/**\n * A single log view. Feed it entries from any pipe, in any order, as many\n * times as you like; read `state`.\n */\nexport class CallLogView {\n    #entries = new Map<number, KnownLogEntry>();\n    #state: CallLogState = emptyState();\n    #ctx: FoldContext = emptyContext();\n    #maxSeq = -1;\n    /**\n     * Every `log.gap` applied, in arrival order. Markers are never stored in\n     * `#entries` (§5), but a gap HYDRATES — so an out-of-order rebuild must\n     * re-step each gap at its place in the seq order or the hydrated stretch\n     * would evaporate.\n     */\n    #gaps: KnownLogEntry[] = [];\n    #listeners = new Set<(state: CallLogState) => void>();\n\n    /**\n     * How many entries to retain for out-of-order rebuilds. The retained\n     * window bounds memory on a long call; entries older than the window are\n     * still reflected in the state, they just cannot be re-folded. Default\n     * 10_000 (the hot buffer is 1000, so this is generous by 10x).\n     */\n    constructor(private readonly retain = 10_000) {}\n\n    /**\n     * Read-only snapshot, safe to retain and to compare by reference.\n     *\n     * Every state-affecting apply produces a new state object, new\n     * `messages`/`toolCalls`/`turns`/`custom` arrays, and new objects for exactly the\n     * entries that changed — untouched siblings keep their identity. So\n     * `prev.messages[3] === next.messages[3]` is a truthful \"this line did\n     * not change\", which is what makes a memoized transcript line correct\n     * rather than merely fast.\n     */\n    get state(): Readonly<CallLogState> {\n        return this.#state;\n    }\n\n    /** The cursor to resume from: `?after=<lastSeq>`. */\n    get lastSeq(): number {\n        return this.#state.lastSeq;\n    }\n\n    /** Subscribe to state changes. Returns an unsubscribe function. */\n    subscribe(fn: (state: CallLogState) => void): () => void {\n        this.#listeners.add(fn);\n        return () => { this.#listeners.delete(fn); };\n    }\n\n    /** The entries this view retains, in seq order — the resume payload. */\n    entries(): KnownLogEntry[] {\n        return [...this.#entries.keys()].sort((a, b) => a - b).map((s) => this.#entries.get(s)!);\n    }\n\n    /** True if this exact seq has already been applied. */\n    has(seq: number): boolean {\n        return this.#entries.has(seq);\n    }\n\n    /**\n     * Apply one entry. Idempotent by `seq`, order-independent.\n     * Returns true if the view changed.\n     */\n    apply(entry: AnyLogEntry): boolean {\n        if (!isLogEntry(entry)) return false;\n        // §1: unknown types MUST be ignored, not rejected.\n        if (!isKnownLogEntry(entry)) return false;\n\n        // §5: control markers are FULL envelopes whose seq REPEATS the last\n        // seq delivered — the dedupe below would swallow them, and storing\n        // them would poison entries(), which is the resume payload. Dispatch\n        // immediately; never store, never advance the cursor.\n        if (entry.type === \"log.caught_up\" || entry.type === \"log.gap\") {\n            if (entry.type === \"log.gap\") this.#gaps.push(entry);\n            this.#state = {\n                ...this.#state,\n                messages: [...this.#state.messages],\n                toolCalls: [...this.#state.toolCalls],\n                turns: [...this.#state.turns],\n                custom: [...this.#state.custom],\n            };\n            this.#step(this.#state, this.#ctx, entry);\n            this.#finish(this.#state, this.#ctx);\n            for (const fn of this.#listeners) fn(this.#state);\n            return true;\n        }\n\n        // §1: consumers MUST dedupe by seq — transports overlap.\n        if (this.#entries.has(entry.seq)) return false;\n\n        this.#entries.set(entry.seq, entry);\n\n        if (entry.seq > this.#maxSeq) {\n            // Live path: strictly newer than anything seen — fold forward.\n            this.#maxSeq = entry.seq;\n            // New top-level and array references so snapshot consumers\n            // (useSyncExternalStore and friends) see a change.\n            this.#state = {\n                ...this.#state,\n                messages: [...this.#state.messages],\n                toolCalls: [...this.#state.toolCalls],\n                turns: [...this.#state.turns],\n                custom: [...this.#state.custom],\n            };\n            this.#step(this.#state, this.#ctx, entry);\n            this.#finish(this.#state, this.#ctx);\n            this.#trim();\n        } else {\n            // Backfill / out-of-order: the fold must run in seq order.\n            this.#trim();\n            this.#rebuild();\n        }\n\n        for (const fn of this.#listeners) fn(this.#state);\n        return true;\n    }\n\n    /** Apply many. Returns how many changed the view. */\n    applyAll(entries: readonly AnyLogEntry[]): number {\n        let n = 0;\n        for (const e of entries) if (this.apply(e)) n++;\n        return n;\n    }\n\n    /** Drop everything and start over. */\n    reset(): void {\n        this.#entries.clear();\n        this.#state = emptyState();\n        this.#ctx = emptyContext();\n        this.#maxSeq = -1;\n        this.#gaps = [];\n        for (const fn of this.#listeners) fn(this.#state);\n    }\n\n    // ── Internals ──\n\n    #trim(): void {\n        if (this.#entries.size <= this.retain) return;\n        const keys = [...this.#entries.keys()].sort((a, b) => a - b);\n        const drop = keys.length - this.retain;\n        for (let i = 0; i < drop; i++) this.#entries.delete(keys[i]!);\n    }\n\n    #rebuild(): void {\n        const state = emptyState();\n        const ctx = emptyContext();\n        // Gaps are re-stepped in seq order, interleaved with the entries: a\n        // gap's seq sits right before the first entry it resumes at, so\n        // everything at or below it folds first, then the snapshot lands,\n        // then the rest — the order the transport delivered.\n        const gaps = [...this.#gaps].sort((a, b) => a.seq - b.seq);\n        let g = 0;\n        for (const entry of this.entries()) {\n            while (g < gaps.length && gaps[g]!.seq < entry.seq) this.#step(state, ctx, gaps[g++]!);\n            this.#step(state, ctx, entry);\n        }\n        while (g < gaps.length) this.#step(state, ctx, gaps[g++]!);\n        this.#finish(state, ctx);\n        // Caught-up is a TRANSPORT signal, not a log fact: the marker is never\n        // stored, so a rebuild cannot re-derive it. Carry the transport's\n        // last word across.\n        state.caughtUp = this.#state.caughtUp;\n        this.#state = state;\n        this.#ctx = ctx;\n    }\n\n    #finish(state: CallLogState, ctx: FoldContext): void {\n        // Correction #3: duration comes from entry ts, never wall clock.\n        state.duration =\n            ctx.startTs !== null && ctx.lastTs !== null\n                ? Math.max(0, ctx.lastTs - ctx.startTs)\n                : 0;\n        state.metrics = {\n            ...state.metrics,\n            turnCount: state.turns.length,\n            ...(ctx.e2eN > 0 ? { e2eMean: ctx.e2eSum / ctx.e2eN } : {}),\n        };\n    }\n\n    /**\n     * Fold one entry into `state`. Exhaustive over the closed vocabulary —\n     * the `never` in the default arm is the compile-time guarantee that a\n     * new §2 type cannot be added without teaching the reducer about it.\n     */\n    #step(state: CallLogState, ctx: FoldContext, entry: KnownLogEntry): void {\n        state.lastSeq = Math.max(state.lastSeq, entry.seq);\n        if (entry.call && !state.call) state.call = entry.call;\n        if (entry.agent && !state.agent) state.agent = entry.agent;\n        // Control markers are minted by the transport at wall-clock time —\n        // they say nothing about when the call happened, so they never move\n        // the duration anchors (correction #3).\n        if (entry.type !== \"log.caught_up\" && entry.type !== \"log.gap\") {\n            if (ctx.startTs === null) ctx.startTs = entry.ts;\n            ctx.lastTs = ctx.lastTs === null ? entry.ts : Math.max(ctx.lastTs, entry.ts);\n        }\n\n        const messages = state.messages;\n\n        switch (entry.type) {\n            // ── Lifecycle ──\n            case \"call.ringing\":\n                state.phase = \"ringing\";\n                break;\n\n            case \"call.started\":\n                ctx.startTs = entry.ts;\n                state.phase = \"listening\";\n                state.live = true;\n                break;\n\n            case \"call.ended\":\n                state.phase = \"ended\";\n                state.live = false;\n                state.userSpeaking = false;\n                state.botSpeaking = false;\n                state.endedReason = entry.data.reason;\n                // Correction #2: surface the intent, never call disconnect().\n                state.intents = [\n                    ...state.intents,\n                    { kind: \"disconnect\", reason: entry.data.reason, seq: entry.seq },\n                ];\n                break;\n\n            case \"call.summary\":\n                state.metrics = {\n                    ...state.metrics,\n                    summary: entry.data.metrics,\n                    ...(entry.data.cost !== undefined ? { cost: entry.data.cost } : {}),\n                    ...(entry.data.recording_url\n                        ? { recordingUrl: entry.data.recording_url }\n                        : {}),\n                };\n                state.live = false;\n                if (state.phase !== \"ended\") state.phase = \"ended\";\n                break;\n\n            // ── Speech & transcript ──\n            case \"user.speaking\":\n                state.userSpeaking = entry.data.active;\n                if (entry.data.active && state.phase !== \"ended\") state.phase = \"listening\";\n                break;\n\n            case \"user.message\": {\n                if (entry.data.text) {\n                    mergeUserTurn(\n                        messages,\n                        entry.seq,\n                        entry.data.id,\n                        entry.data.text,\n                        !entry.data.final,\n                    );\n                    this.#reindex(ctx, messages);\n                }\n                if (entry.data.final) {\n                    state.userSpeaking = false;\n                    if (state.phase !== \"ended\") state.phase = \"thinking\";\n                }\n                break;\n            }\n\n            case \"bot.speaking\": {\n                const id = entry.data.id;\n                ctx.botWords.set(id, []);\n                const idx = ctx.botIndex.get(id);\n                const words = entry.data.words;\n                if (idx === undefined) {\n                    messages.push({\n                        seq: entry.seq,\n                        role: \"bot\",\n                        text: entry.data.text ?? \"\",\n                        id,\n                        speaking: true,\n                        ...(words ? { words } : {}),\n                    });\n                    this.#reindex(ctx, messages);\n                } else {\n                    const m = cow(messages, idx);\n                    if (entry.data.text) m.text = entry.data.text;\n                    if (words) m.words = words;\n                    m.speaking = true;\n                }\n                state.botSpeaking = true;\n                if (state.phase !== \"ended\") state.phase = \"speaking\";\n                break;\n            }\n\n            case \"bot.word\": {\n                // Ephemeral typing effect. §2's bot.word carries no index, so\n                // reassembly is append-in-seq-order — deterministic because the\n                // fold always runs in seq order.\n                const id = entry.data.id;\n                let buf = ctx.botWords.get(id);\n                if (!buf) { buf = []; ctx.botWords.set(id, buf); }\n                buf.push(entry.data.w);\n                const text = buf.join(\" \");\n                const idx = ctx.botIndex.get(id);\n                if (idx === undefined) {\n                    messages.push({ seq: entry.seq, role: \"bot\", text, id, speaking: true });\n                    this.#reindex(ctx, messages);\n                } else {\n                    // Never clobber an authoritative bot.speaking.text with a\n                    // partial word buffer.\n                    const m = cow(messages, idx);\n                    if (!m.corrected && buf.length > 0 && m.text.length <= text.length) {\n                        m.text = text;\n                    }\n                    m.speaking = true;\n                }\n                state.botSpeaking = true;\n                if (state.phase !== \"ended\") state.phase = \"speaking\";\n                break;\n            }\n\n            case \"bot.finished\": {\n                const idx = ctx.botIndex.get(entry.data.id);\n                if (idx !== undefined) {\n                    // The LLM went straight to a tool call: drop the phantom\n                    // bubble rather than copying it only to remove it.\n                    if (!messages[idx]!.text) {\n                        messages.splice(idx, 1);\n                        this.#reindex(ctx, messages);\n                    } else {\n                        cow(messages, idx).speaking = false;\n                    }\n                }\n                state.botSpeaking = false;\n                if (state.phase !== \"ended\") state.phase = \"listening\";\n                break;\n            }\n\n            case \"bot.interrupted\": {\n                const idx = ctx.botIndex.get(entry.data.id);\n                if (idx !== undefined) {\n                    const m = cow(messages, idx);\n                    m.speaking = false;\n                    m.interrupted = true;\n                }\n                state.botSpeaking = false;\n                if (state.phase !== \"ended\") state.phase = \"listening\";\n                break;\n            }\n\n            case \"bot.corrected\": {\n                // Correction #4 / §2: replace the text of the superseded entry.\n                // An event, not a mutation — replay reaches the same place.\n                const idx = ctx.bySeq.get(entry.data.supersedes);\n                if (idx !== undefined) {\n                    const m = cow(messages, idx);\n                    m.text = entry.data.text;\n                    m.corrected = true;\n                } else {\n                    messages.push({\n                        seq: entry.seq,\n                        role: \"bot\",\n                        text: entry.data.text,\n                        id: entry.data.id,\n                        corrected: true,\n                    });\n                    this.#reindex(ctx, messages);\n                }\n                break;\n            }\n\n            // ── Turns & latency ──\n            case \"turn.start\": {\n                const i = ctx.turnIndex.get(entry.data.turn);\n                if (i === undefined) {\n                    ctx.turnIndex.set(entry.data.turn, state.turns.length);\n                    state.turns.push({\n                        turn: entry.data.turn,\n                        role: entry.data.role,\n                        startedAt: entry.ts,\n                    });\n                } else {\n                    state.turns[i] = {\n                        ...state.turns[i]!,\n                        role: entry.data.role,\n                        startedAt: entry.ts,\n                    };\n                }\n                break;\n            }\n\n            case \"turn.end\": {\n                const i = ctx.turnIndex.get(entry.data.turn);\n                // A hydrated turn may already carry an e2e (the gap snapshot\n                // folds the entries it is served with): retire it before the\n                // entry's own counts, so re-application never double-counts.\n                const prev = i !== undefined ? state.turns[i]!.latency?.e2e : undefined;\n                if (typeof prev === \"number\") { ctx.e2eSum -= prev; ctx.e2eN -= 1; }\n                if (i === undefined) {\n                    ctx.turnIndex.set(entry.data.turn, state.turns.length);\n                    state.turns.push({\n                        turn: entry.data.turn,\n                        latency: entry.data.latency,\n                        endedAt: entry.ts,\n                    });\n                } else {\n                    state.turns[i] = {\n                        ...state.turns[i]!,\n                        latency: entry.data.latency,\n                        endedAt: entry.ts,\n                    };\n                }\n                if (typeof entry.data.latency?.e2e === \"number\") {\n                    ctx.e2eSum += entry.data.latency.e2e;\n                    ctx.e2eN += 1;\n                }\n                break;\n            }\n\n            // ── Tools, knowledge, skills ──\n            case \"tool.call\": {\n                // Correction #1: no trackedTools filter — expose everything.\n                const id = entry.data.id;\n                if (ctx.toolIndex.get(id) === undefined) {\n                    ctx.toolIndex.set(id, state.toolCalls.length);\n                    state.toolCalls.push({\n                        id,\n                        name: entry.data.name,\n                        args: parseArgs(entry.data.args),\n                        seq: entry.seq,\n                        done: false,\n                    });\n                    messages.push({\n                        seq: entry.seq,\n                        role: \"system\",\n                        text: `Using ${entry.data.name}…`,\n                        toolCallId: id,\n                    });\n                    this.#reindex(ctx, messages);\n                }\n                break;\n            }\n\n            case \"tool.result\": {\n                const i = ctx.toolIndex.get(entry.data.id);\n                if (i !== undefined) {\n                    state.toolCalls[i] = {\n                        ...state.toolCalls[i]!,\n                        result: parseResult(entry.data.result),\n                        ms: entry.data.ms,\n                        ...(entry.data.error ? { error: entry.data.error } : {}),\n                        done: true,\n                    };\n                } else {\n                    // Result without its call (backlog started mid-pair).\n                    ctx.toolIndex.set(entry.data.id, state.toolCalls.length);\n                    state.toolCalls.push({\n                        id: entry.data.id,\n                        name: entry.data.name,\n                        args: {},\n                        seq: entry.seq,\n                        result: parseResult(entry.data.result),\n                        ms: entry.data.ms,\n                        ...(entry.data.error ? { error: entry.data.error } : {}),\n                        done: true,\n                    });\n                }\n                for (let i = 0; i < messages.length; i++) {\n                    if (messages[i]!.toolCallId === entry.data.id) {\n                        cow(messages, i).text = entry.data.error\n                            ? `${entry.data.name} failed`\n                            : `${entry.data.name}`;\n                    }\n                }\n                break;\n            }\n\n            case \"docs.sources\":\n                state.sources = entry.data.sources ?? [];\n                break;\n\n            case \"skill.loaded\":\n                if (!state.skills.includes(entry.data.skill)) {\n                    state.skills = [...state.skills, entry.data.skill];\n                }\n                break;\n\n            case \"skill.unloaded\":\n                state.skills = state.skills.filter((s) => s !== entry.data.skill);\n                break;\n\n            // ── Metrics & control ──\n            case \"audio.metrics\":\n                // Ephemeral; rolled up into call.summary server-side (§4).\n                break;\n\n            case \"handoff.requested\":\n                state.handoff = \"requested\";\n                break;\n            case \"handoff.active\":\n                state.handoff = \"active\";\n                break;\n            case \"handoff.released\":\n                state.handoff = \"none\";\n                break;\n\n            case \"supervisor.said\":\n            case \"supervisor.whispered\":\n                // A gap snapshot may already carry this line (its fold covers\n                // the entries it is served with) — keyed by seq, once.\n                if (!ctx.bySeq.has(entry.seq)) {\n                    messages.push({\n                        seq: entry.seq,\n                        role: \"system\",\n                        text: entry.data.text,\n                    });\n                    this.#reindex(ctx, messages);\n                }\n                break;\n\n            // ── Log control ──\n            case \"log.caught_up\":\n                state.caughtUp = true;\n                break;\n\n            case \"log.gap\":\n                // §3: declare the gap, land the snapshot, move the cursor.\n                // `after=` is exclusive (seq > after), so the cursor that\n                // resumes AT resume_from is resume_from - 1 — the seq the\n                // server stamps on the marker itself.\n                state.gaps = [\n                    ...state.gaps,\n                    { from: entry.data.from, resumeFrom: entry.data.resume_from },\n                ];\n                state.caughtUp = false;\n                state.lastSeq = Math.max(state.lastSeq, entry.data.resume_from - 1);\n                if (isRecord(entry.data.snapshot)) {\n                    this.#hydrate(state, ctx, entry.data.snapshot as LogGapSnapshot);\n                }\n                break;\n\n            // ── Custom entries (`call.log()`) ──\n            case \"custom\": {\n                // Ephemeral: fanned out to listeners, never projected — the\n                // store never has it, so live state must not have it either\n                // (replay === live). Durable: upsert by (name, id) — the row\n                // is REPLACED wholesale (value, seq, ts, turn), never merged,\n                // so the final state never depends on which entries were\n                // skipped. Absent id → the entry's own seq, i.e. append.\n                if (entry.ephemeral) break;\n                const id = entry.data.id ?? String(entry.seq);\n                const key = `${entry.data.name}/${id}`;\n                const row: CallCustomEntry = {\n                    name: entry.data.name,\n                    id,\n                    value: entry.data.value,\n                    seq: entry.seq,\n                    ts: entry.ts,\n                    ...(entry.data.turn !== undefined ? { turn: entry.data.turn } : {}),\n                };\n                const i = ctx.customIndex.get(key);\n                if (i === undefined) {\n                    ctx.customIndex.set(key, state.custom.length);\n                    state.custom.push(row);\n                } else {\n                    state.custom[i] = row;\n                }\n                break;\n            }\n\n            default: {\n                // Exhaustiveness: adding a §2 type without a case fails to compile.\n                const _never: never = entry;\n                void _never;\n            }\n        }\n    }\n\n    /**\n     * Merge a `log.gap` snapshot into `state` (ag-ui \"For Pinecall\" 9:\n     * MESSAGES_SNAPSHOT's rule — merge by id, never wipe).\n     *\n     *   - `messages`: keyed by `seq` (bot bubbles by `id`). A snapshot row\n     *     REPLACES its local counterpart and a new one is inserted; local-only\n     *     rows survive. Result is re-sorted by seq — the order the fold would\n     *     have produced.\n     *   - `tool_calls`: keyed by `id`, same rule, sorted by seq.\n     *   - `turns`: keyed by `turn`, field-merged (`{...local, ...row}`) so a\n     *     `turn.end` already folded locally is not lost to a snapshot that\n     *     only saw the `turn.start`. Latency sums are recomputed from the\n     *     merged turns.\n     *   - `custom`: keyed by `(name, id)`; the row with the HIGHER seq wins —\n     *     the one rule the upsert already has. First-seen order kept, new\n     *     keys appended.\n     *   - scalars (`phase`, `live`, `started_at`, `ended_reason`,\n     *     `user_speaking`, `bot_speaking`, `handoff`, `skills`, `sources`):\n     *     values — present wins, absent leaves local alone.\n     *\n     * Re-applying the entries the snapshot was folded from is a no-op for\n     * what it carried: every case in `#step` is keyed the same way.\n     */\n    #hydrate(state: CallLogState, ctx: FoldContext, snap: LogGapSnapshot): void {\n        if (typeof snap.phase === \"string\" && PHASES.has(snap.phase)) state.phase = snap.phase;\n        if (typeof snap.live === \"boolean\") state.live = snap.live;\n        if (typeof snap.started_at === \"number\") ctx.startTs = snap.started_at;\n        if (typeof snap.ended_reason === \"string\") state.endedReason = snap.ended_reason;\n        if (typeof snap.user_speaking === \"boolean\") state.userSpeaking = snap.user_speaking;\n        if (typeof snap.bot_speaking === \"boolean\") state.botSpeaking = snap.bot_speaking;\n        if (typeof snap.handoff === \"string\" && HANDOFFS.has(snap.handoff)) state.handoff = snap.handoff;\n        if (Array.isArray(snap.skills)) state.skills = snap.skills.filter((x) => typeof x === \"string\");\n        if (Array.isArray(snap.sources)) state.sources = [...snap.sources];\n\n        const msgRows = rows<CallMessage>(snap.messages, (r) => typeof r.seq === \"number\" && typeof r.role === \"string\");\n        if (msgRows.length) {\n            const messages = state.messages;\n            for (const r of msgRows) {\n                const row: CallMessage = { ...r, text: typeof r.text === \"string\" ? r.text : \"\" };\n                const idx = row.role === \"bot\" && row.id !== undefined\n                    ? ctx.botIndex.get(row.id) ?? ctx.bySeq.get(row.seq)\n                    : ctx.bySeq.get(row.seq);\n                if (idx === undefined) messages.push(row);\n                else messages[idx] = row;\n                this.#reindex(ctx, messages);\n            }\n            messages.sort((a, b) => a.seq - b.seq);\n            this.#reindex(ctx, messages);\n        }\n\n        const toolRows = rows<CallToolCall>(snap.tool_calls, (r) => typeof r.id === \"string\" && typeof r.seq === \"number\");\n        if (toolRows.length) {\n            for (const r of toolRows) {\n                const row: CallToolCall = {\n                    ...r,\n                    name: typeof r.name === \"string\" ? r.name : \"\",\n                    args: isRecord(r.args) ? r.args : {},\n                    done: r.done === true,\n                };\n                const i = ctx.toolIndex.get(row.id);\n                if (i === undefined) state.toolCalls.push(row);\n                else state.toolCalls[i] = row;\n                ctx.toolIndex.set(row.id, state.toolCalls.length - 1);\n            }\n            state.toolCalls.sort((a, b) => a.seq - b.seq);\n            ctx.toolIndex.clear();\n            state.toolCalls.forEach((t, i) => ctx.toolIndex.set(t.id, i));\n        }\n\n        const turnRows = rows<CallTurn>(snap.turns, (r) => typeof r.turn === \"number\");\n        if (turnRows.length) {\n            for (const r of turnRows) {\n                const i = ctx.turnIndex.get(r.turn);\n                if (i === undefined) state.turns.push({ ...r });\n                else state.turns[i] = { ...state.turns[i]!, ...r };\n                ctx.turnIndex.set(r.turn, i ?? state.turns.length - 1);\n            }\n            state.turns.sort((a, b) => a.turn - b.turn);\n            ctx.turnIndex.clear();\n            ctx.e2eSum = 0;\n            ctx.e2eN = 0;\n            state.turns.forEach((t, i) => {\n                ctx.turnIndex.set(t.turn, i);\n                if (typeof t.latency?.e2e === \"number\") { ctx.e2eSum += t.latency.e2e; ctx.e2eN += 1; }\n            });\n        }\n\n        const customRows = rows<CallCustomEntry>(snap.custom, (r) => typeof r.name === \"string\" && typeof r.seq === \"number\");\n        for (const r of customRows) {\n            const id = r.id !== undefined && r.id !== null ? String(r.id) : String(r.seq);\n            const row: CallCustomEntry = { ...r, id };\n            const key = `${row.name}/${id}`;\n            const i = ctx.customIndex.get(key);\n            if (i === undefined) {\n                ctx.customIndex.set(key, state.custom.length);\n                state.custom.push(row);\n            } else if (row.seq >= state.custom[i]!.seq) {\n                state.custom[i] = row;\n            }\n        }\n    }\n\n    /** Rebuild the id→index maps after a splice/push. Cheap: messages are small. */\n    #reindex(ctx: FoldContext, messages: CallMessage[]): void {\n        ctx.botIndex.clear();\n        ctx.bySeq.clear();\n        for (let i = 0; i < messages.length; i++) {\n            const m = messages[i]!;\n            ctx.bySeq.set(m.seq, i);\n            if (m.role === \"bot\" && m.id !== undefined) ctx.botIndex.set(m.id, i);\n        }\n    }\n}\n\n/** Build a view from a batch of entries. */\nexport function createCallLogView(entries?: readonly AnyLogEntry[]): CallLogView {\n    const view = new CallLogView();\n    if (entries) view.applyAll(entries);\n    return view;\n}\n","/**\n * HTTP — shared fetch wrapper for REST API calls.\n *\n * Centralizes error mapping and Authorization header injection.\n */\n\nexport const DEFAULT_API_URL = \"https://voice.pinecall.io\";\n\nexport interface HttpOptions {\n    apiUrl?: string;\n    apiKey?: string;\n}\n\nexport interface ApiFetchOptions extends HttpOptions {\n    query?: Record<string, string>;\n    /** HTTP method. Defaults to GET (POST when a `body` is given). */\n    method?: string;\n    /** JSON body — serialised and sent as `application/json`. */\n    body?: unknown;\n    /** Aborts the request (and, for streaming endpoints, the work behind it). */\n    signal?: AbortSignal;\n    /** Extra request headers. Authorization is injected from `apiKey`. */\n    headers?: Record<string, string>;\n}\n\nexport async function apiFetch(\n    path: string,\n    opts: ApiFetchOptions = {},\n): Promise<Response> {\n    const base = opts.apiUrl ?? DEFAULT_API_URL;\n    const url = new URL(path, base);\n    if (opts.query) {\n        for (const [k, v] of Object.entries(opts.query)) {\n            url.searchParams.set(k, v);\n        }\n    }\n\n    const headers: Record<string, string> = { ...(opts.headers ?? {}) };\n    if (opts.apiKey) headers[\"Authorization\"] = `Bearer ${opts.apiKey}`;\n\n    const hasBody = opts.body !== undefined;\n    if (hasBody) headers[\"Content-Type\"] = \"application/json\";\n\n    const res = await fetch(url.toString(), {\n        method: opts.method ?? (hasBody ? \"POST\" : \"GET\"),\n        headers,\n        ...(hasBody ? { body: JSON.stringify(opts.body) } : {}),\n        ...(opts.signal ? { signal: opts.signal } : {}),\n    });\n    return res;\n}\n","/**\n * Token API — create tokens for browser connections.\n */\n\nimport { DEFAULT_API_URL } from \"./http.js\";\n\nexport interface WebRTCToken {\n    token: string;\n    server?: string;\n}\n\nexport interface TokenResponse {\n    token: string;\n    server: string;\n    expiresIn: number;\n}\n\nexport interface FetchWebRTCTokenOptions {\n    agentId: string;\n    apiUrl?: string;\n    apiKey?: string;\n}\n\n/**\n * Token scope (CALL_LOG_SPEC.md §5).\n *\n *  · `observe`     read-only: the call log, nothing else. Agent-scoped (all\n *                  its calls) or call-scoped (one, via `callId`).\n *  · `participate` media + log — what today's webrtc/chat tokens already are.\n *  · `supervise`   observe + the control verbs of §7.\n *\n * Optional and additive: omitting it mints exactly the token this SDK has\n * always minted (§8 — `createToken(\"webrtc\"|\"chat\")` keeps working).\n */\nexport type TokenScope = \"observe\" | \"participate\" | \"supervise\";\n\n/** Extra, optional token attributes. Absent ⇒ today's behavior, byte-identical. */\nexport interface TokenScopeOptions {\n    /** §5 scope. Absent ⇒ the server's channel default. */\n    scope?: TokenScope;\n    /** Narrow an `observe`/`supervise` token to a single call. */\n    callId?: string;\n}\n\nexport interface CreateTokenOptions extends TokenScopeOptions {\n    channel: \"webrtc\" | \"chat\" | \"stream\";\n    /**\n     * One agent slug — or a non-empty list: the AGENT SET this token may see\n     * (CALL_LOG_SPEC.md §5, \"VISIBILITY — the agent set\"). Minted per logged\n     * session by YOUR backend, sealed in the token: the browser cannot widen\n     * it. Stream tokens only; media channels take one agent.\n     */\n    agentId: string | readonly string[];\n    apiKey: string;\n    apiUrl?: string;\n    /**\n     * Sealed session metadata baked into the signed token. Trusted server-side\n     * (the browser cannot forge or alter it) — surfaces as `call.metadata` for\n     * tools and event handlers. Use for per-session identity (tenantId, userId,\n     * role). Only honored when minting with an API key (this method). Max ~2KB.\n     */\n    metadata?: Record<string, unknown>;\n}\n\nexport async function fetchWebRTCToken(opts: FetchWebRTCTokenOptions): Promise<WebRTCToken> {\n    const apiUrl = opts.apiUrl ?? DEFAULT_API_URL;\n    const headers: Record<string, string> = {};\n    if (opts.apiKey) headers[\"Authorization\"] = `Bearer ${opts.apiKey}`;\n\n    let res: Response;\n    try {\n        res = await fetch(\n            `${apiUrl}/webrtc/token?agent_id=${encodeURIComponent(opts.agentId)}`,\n            { headers },\n        );\n    } catch (err) {\n        throw new Error(`Network error fetching WebRTC token: ${err}`);\n    }\n\n    if (!res.ok) {\n        const data = await res.json().catch(() => ({ detail: res.statusText }));\n        throw new Error(`Failed to fetch WebRTC token: ${(data as any).detail || `HTTP ${res.status}`}`);\n    }\n\n    const data = await res.json() as Record<string, unknown>;\n    if (typeof data.token !== \"string\") {\n        throw new Error(\"WebRTC token response missing 'token' field\");\n    }\n\n    return {\n        token: data.token,\n        server: (data.server as string) || undefined,\n    };\n}\n\nexport async function createToken(opts: CreateTokenOptions): Promise<TokenResponse> {\n    const apiUrl = opts.apiUrl ?? DEFAULT_API_URL;\n    const endpoints: Record<string, string> = {\n        webrtc: \"/webrtc/token\",\n        chat: \"/chat/token\",\n        stream: \"/stream/token\",\n    };\n    const endpoint = endpoints[opts.channel] || \"/webrtc/token\";\n    // An agent SET serializes comma-separated — the server authorizes each\n    // slug through the same gate a single mint uses, then seals the set.\n    const agentParam = Array.isArray(opts.agentId)\n        ? opts.agentId.join(\",\")\n        : (opts.agentId as string);\n    let url = `${apiUrl}${endpoint}?agent_id=${encodeURIComponent(agentParam)}`;\n    if (opts.metadata && Object.keys(opts.metadata).length > 0) {\n        url += `&metadata=${encodeURIComponent(JSON.stringify(opts.metadata))}`;\n    }\n    // Additive (spec §5/§8): a call without scope/callId produces the exact\n    // same URL as before this parameter existed — pinned by a URL snapshot\n    // test in tests/token-url.test.ts.\n    if (opts.scope) {\n        url += `&scope=${encodeURIComponent(opts.scope)}`;\n    }\n    if (opts.callId) {\n        url += `&call_id=${encodeURIComponent(opts.callId)}`;\n    }\n\n    let res: Response;\n    try {\n        res = await fetch(url, {\n            headers: { Authorization: `Bearer ${opts.apiKey}` },\n        });\n    } catch (err) {\n        throw new Error(`Network error creating ${opts.channel} token: ${err}`);\n    }\n\n    if (!res.ok) {\n        const data = await res.json().catch(() => ({ detail: res.statusText }));\n        throw new Error(\n            `Failed to create ${opts.channel} token: ${(data as any).detail || `HTTP ${res.status}`}`,\n        );\n    }\n\n    const data = await res.json() as Record<string, unknown>;\n    if (typeof data.token !== \"string\") {\n        throw new Error(`Token response missing 'token' field`);\n    }\n\n    return {\n        token: data.token as string,\n        server: (data.server as string) || apiUrl,\n        expiresIn: (data.expires_in as number) || 60,\n    };\n}\n","/**\n * `observe()` — the Node reader of the Call Log.\n *\n * ONE verb to read a call (or an agent's lifecycle log) from a server\n * process: it opens `GET /v1/calls/{id}/events` (or\n * `/v1/agents/{slug}/calls`) with `Accept: text/event-stream`, feeds every\n * envelope into the SAME `CallLogView` reducer the browser uses, and hands\n * the caller three ways to consume it — `for await`, `on(\"entry\")` /\n * `on(\"custom\")`, and the reduced `state` snapshot.\n *\n * ── TWINS, NOT YET SHARED ────────────────────────────────────────────────\n *\n * The SSE decoder, the idle watchdog, the backoff-with-jitter, the\n * `withListeners()` seam and the finish reasons in this file are a\n * DELIBERATE, SEMANTICALLY IDENTICAL port of\n * `@pinecall/web`'s `src/log/transport.ts` (branch `call-log-v2`, commit\n * `30cf4af`). Same constants, same clamps, same field parsing, same\n * `min(1000·2^n, 15000) + rand(0, 1000)` reconnect, same\n * `\"summary\" | \"closed\" | \"error\"` trichotomy, same \"resume always carries\n * `after=<view.lastSeq>`, never `Last-Event-ID`\" rule. Read one, you have\n * read the other.\n *\n * They are twins rather than one shared module because the two packages sit\n * on opposite sides of a publish boundary: `@pinecall/sdk` cannot depend on\n * `@pinecall/web` (the web package depends on the SDK's contract, and a\n * cycle between two published packages is not a thing), and the reducer's\n * own answer to that — vendoring `src/log/{types,view}.ts` byte-for-byte\n * into webrtc, checked by `pnpm run log:sync-check` — buys its determinism\n * by being pure: no `fetch`, no timers, no environment. A transport is the\n * opposite: this one has no `document` to defer reconnects on (Node has no\n * `visibilitychange`) and no `WebSocket` half, while the browser twin has\n * both and needs them. Sharing them today would mean shipping a\n * lowest-common-denominator transport to both. When the divergence stops\n * paying for itself, the merge target is a third `@pinecall/log-wire`\n * package that both depend on — not a copy in either direction.\n *\n * The parts that MUST NOT drift are pinned by tests in both repos against\n * the same `fixtures/call-log-golden.json`: a replayed finished call reduces\n * to the same state here as it does in the browser.\n *\n * ── WHY NOT `EventSource` ────────────────────────────────────────────────\n *\n * Same four reasons as the browser: it cannot send an `Authorization`\n * header, it hides `:` comment lines from JS (the idle watchdog's\n * heartbeat), it owns its own reconnect (no abort, no backoff, no jitter),\n * and it fires `onerror` on every reconnect. `fetch` + `ReadableStream` +\n * the ~60-line decoder below is the portable answer, and on Node 18+ both\n * are global.\n *\n * @example\n * ```ts\n * const obs = pc.observe({ agent: \"lucia\" });\n * for await (const entry of obs) {\n *   if (entry.type === \"call.started\") console.log(\"call\", entry.call);\n * }\n * ```\n */\n\nimport { LOG_EVENT_TYPES, type AnyLogEntry, type LogEntry } from \"./log/types.js\";\nimport { CallLogView, type CallLogState } from \"./log/view.js\";\nimport { createToken } from \"./api/tokens.js\";\nimport { DEFAULT_API_URL } from \"./api/http.js\";\n\n// ── Structural seams (a test injects both) ───────────────────────────────\n\n/** What `FetchLike` must resolve to. `body` is what the stream reads from. */\nexport interface ObserveResponseLike {\n    ok: boolean;\n    status: number;\n    text(): Promise<string>;\n    body?: ReadableStream<Uint8Array> | null;\n}\n\n/** Minimal structural `fetch` — the injection seam for tests. */\nexport type ObserveFetch = (\n    url: string,\n    init?: { headers?: Record<string, string>; signal?: AbortSignal },\n) => Promise<ObserveResponseLike>;\n\n/**\n * Idle watchdog. `\"auto\"` is dormant until two heartbeats were seen, then\n * the window is `clamp(3 × observed cadence, 6 s, 30 s)`; a number is a\n * fixed window in ms armed from the first frame; `0` turns it off.\n *\n * Identical to the browser twin's `IdleReconnect`.\n */\nexport type IdleReconnect = \"auto\" | number | 0;\n\n/** Why an observation ended. `\"summary\"` is the one clean end. */\nexport interface ObserveFinishInfo {\n    reason: \"summary\" | \"closed\" | \"error\";\n    error?: Error;\n    lastSeq: number;\n}\n\nexport interface ObserveOptions {\n    /** Call-scoped: one call's log. Exactly one of `call` / `agent`. */\n    call?: string;\n    /** Agent-scoped: the agent's lifecycle log. Exactly one of `call` / `agent`. */\n    agent?: string;\n    /** Start cursor. Default `0` — from the beginning of the log. */\n    after?: number;\n    /** Server-side filter: only these entry types, plus the always-pass set. */\n    types?: readonly string[];\n    /** Server-side filter: skip ephemeral entries in the live tail. */\n    durable?: boolean;\n    /**\n     * An `observe` / `supervise` token. Omitted ⇒ one is minted with the\n     * client's API key (`createToken({ channel: \"stream\", scope: \"observe\" })`).\n     *\n     * Minting needs an AGENT: a stream token's visibility is an agent set.\n     * So `observe({ call })` WITHOUT a token also requires `agent` — the SDK\n     * does not resolve a call id to its agent behind your back, because the\n     * only endpoint that would answer needs the very token being minted.\n     * Pass `{ call, agent }`, or pass a `token` you already hold.\n     */\n    token?: string;\n    /** Defaults to `https://voice.pinecall.io` (or the client's `apiUrl`). */\n    server?: string;\n    /** Aborting it is exactly `close()`. */\n    signal?: AbortSignal;\n    /** Half-open detection. Default `\"auto\"`. */\n    idleReconnect?: IdleReconnect;\n    /** `false` disables auto-reconnect (an intentional close never reconnects). */\n    reconnect?: boolean;\n    /**\n     * Bound on the async-iterator's buffer, in entries. Default 1024.\n     * See {@link Observation.dropped} for what an overflow costs.\n     */\n    queueLimit?: number;\n    /** Transport-level failures. State is never faked into the view. */\n    onError?: (error: Error) => void;\n    /** Injection seam. Defaults to the global `fetch`. */\n    fetchImpl?: ObserveFetch;\n    /** Used to mint a token when `token` is absent. */\n    apiKey?: string;\n    /** REST base for the mint. Defaults to `server`. */\n    apiUrl?: string;\n}\n\nexport interface Observation extends AsyncIterable<AnyLogEntry> {\n    /** The SAME `CallLogView` reducer state the browser renders from. */\n    readonly state: Readonly<CallLogState>;\n    /** The resume cursor: highest seq the view has accepted. */\n    readonly lastSeq: number;\n    /**\n     * Entries the async iterator never saw because the consumer was slower\n     * than the wire and the queue hit `queueLimit`. The OLDEST queued entries\n     * are dropped, never the newest — a slow tail should show recent truth.\n     *\n     * `state` is NOT affected: every entry is reduced into the view before it\n     * is ever queued, so the reduced state is complete even when the iterator\n     * skipped rows. `on(\"entry\")` is likewise never dropped — it fires\n     * synchronously. The queue is the only lossy surface, and only under\n     * genuine backpressure.\n     */\n    readonly dropped: number;\n    /** True while entries can still arrive. */\n    readonly active: boolean;\n\n    on(\n        event: \"entry\",\n        fn: (entry: AnyLogEntry, state: Readonly<CallLogState>) => void,\n    ): () => void;\n    on(\n        event: \"custom\",\n        fn: (name: string, value: unknown, entry: LogEntry<\"custom\">) => void,\n    ): () => void;\n    on(event: \"finish\", fn: (info: ObserveFinishInfo) => void): () => void;\n\n    /** Resolves once, when this observation ends for good. Never rejects. */\n    readonly done: Promise<{ reason: \"summary\" | \"closed\" | \"error\"; lastSeq: number }>;\n    /** Stop for good. Idempotent; never reconnects afterwards. */\n    close(): void;\n}\n\n// ── Constants — identical to the browser twin ────────────────────────────\n\nconst MAX_BACKOFF_MS = 15_000;\nconst JITTER_MS = 1000;\nconst IDLE_MIN_MS = 6_000;\nconst IDLE_MAX_MS = 30_000;\nconst DEFAULT_QUEUE_LIMIT = 1024;\n\n/** `min(1000·2^n, 15000) + rand(0, 1000)` ms — the twin's exact curve. */\nexport function observeBackoffDelay(attempt: number): number {\n    return Math.min(1000 * 2 ** attempt, MAX_BACKOFF_MS) + Math.floor(Math.random() * JITTER_MS);\n}\n\nconst KNOWN_TYPES: ReadonlySet<string> = new Set<string>(LOG_EVENT_TYPES as readonly string[]);\n\n/** Types the reducer knows and keeps, vs. ones it can never store. */\nfunction isStorable(entry: AnyLogEntry): boolean {\n    return KNOWN_TYPES.has((entry as { type?: string }).type ?? \"\");\n}\n\nfunction httpBase(server?: string): string {\n    return (server ?? DEFAULT_API_URL).replace(/^ws/, \"http\").replace(/\\/+$/, \"\");\n}\n\n/** The GET cursor path for a target: the call's events, or the agent's log. */\nfunction eventsPath(opts: { call?: string; agent?: string }): string {\n    if (opts.call) return `/v1/calls/${encodeURIComponent(opts.call)}/events`;\n    if (opts.agent) return `/v1/agents/${encodeURIComponent(opts.agent)}/calls`;\n    throw new Error(\"observe: exactly one of { call, agent } is required\");\n}\n\n/** `&types=a,b&durable=1` — the server-side filters, same spelling as the browser. */\nfunction filterQuery(opts: { types?: readonly string[]; durable?: boolean }): string {\n    let q = \"\";\n    if (opts.types && opts.types.length > 0) {\n        q += `&types=${encodeURIComponent(opts.types.join(\",\"))}`;\n    }\n    if (opts.durable) q += \"&durable=1\";\n    return q;\n}\n\nfunction asError(err: unknown): Error {\n    return err instanceof Error ? err : new Error(String(err));\n}\n\n/** A transport error that carries the HTTP status it came from. */\nexport interface ObserveError extends Error {\n    status?: number;\n}\n\nfunction httpError(status: number, detail = \"\"): ObserveError {\n    const e: ObserveError = new Error(`observe: ${status}${detail ? ` ${detail}` : \"\"}`);\n    e.status = status;\n    return e;\n}\n\n/** Statuses no reconnect fixes: the token, or the target, is the problem. */\nfunction isTerminalStatus(status: number): boolean {\n    return status === 401 || status === 403 || status === 404;\n}\n\n/**\n * Has the log said this call is over? Only ever asked of a CALL-scoped\n * stream: an agent log is lifecycle-only and never ends.\n */\nfunction isTerminal(view: CallLogView, target: { call?: string }): boolean {\n    if (!target.call) return false;\n    const s = view.state;\n    return !s.live || s.intents.some((i) => i.kind === \"disconnect\");\n}\n\n// ── The SSE decoder ──────────────────────────────────────────────────────\n\nexport interface SseEvent {\n    /** Sticky across events, as the spec says — an event with no `id:` inherits. */\n    id: string | undefined;\n    event: string;\n    data: string;\n}\n\n/**\n * Bytes → lines → events. Honours `\\n`, `\\r\\n` and a lone `\\r`; `id:` is\n * sticky across events; `retry:` is parsed and ignored (we schedule our own\n * reconnects); comment lines (`: ping`) are DROPPED here but reported to\n * `onComment` first, so the idle watchdog one stage earlier sees them.\n *\n * A line-for-line twin of `@pinecall/web`'s `sseDecoder`.\n */\nexport function sseDecoder(handlers: {\n    onEvent: (ev: SseEvent) => void;\n    onComment?: (text: string) => void;\n    onLine?: () => void;\n}) {\n    const textDecoder = new TextDecoder();\n    let buf = \"\";\n    let event = \"\";\n    let data: string[] = [];\n    let lastId: string | undefined;\n\n    function line(l: string): void {\n        handlers.onLine?.();\n        if (l === \"\") {\n            if (event === \"\" && data.length === 0) return; // nothing to dispatch\n            handlers.onEvent({ id: lastId, event, data: data.join(\"\\n\") });\n            event = \"\";\n            data = [];\n            return;\n        }\n        if (l[0] === \":\") {\n            handlers.onComment?.(l.slice(1).replace(/^ /, \"\"));\n            return;\n        }\n        const i = l.indexOf(\":\");\n        const field = i === -1 ? l : l.slice(0, i);\n        let value = i === -1 ? \"\" : l.slice(i + 1);\n        if (value[0] === \" \") value = value.slice(1);\n        if (field === \"event\") event = value;\n        else if (field === \"data\") data.push(value);\n        else if (field === \"id\") {\n            if (!value.includes(\"\\0\")) lastId = value;\n        }\n        // `retry:` and unknown fields: ignored.\n    }\n\n    return {\n        push(chunk: Uint8Array): void {\n            buf += textDecoder.decode(chunk, { stream: true });\n            let start = 0;\n            for (let i = 0; i < buf.length; i++) {\n                const c = buf[i];\n                if (c === \"\\n\") {\n                    line(buf.slice(start, i));\n                    start = i + 1;\n                } else if (c === \"\\r\") {\n                    // A `\\r` at the very end may be half of a `\\r\\n` split\n                    // across chunks: hold it until the next byte says which.\n                    if (i === buf.length - 1) break;\n                    line(buf.slice(start, i));\n                    if (buf[i + 1] === \"\\n\") i++;\n                    start = i + 1;\n                }\n            }\n            buf = buf.slice(start);\n        },\n        /** Body ended: flush a trailing event that lacked its blank line. */\n        end(): void {\n            buf += textDecoder.decode();\n            if (buf.length > 0) {\n                const rest = buf.endsWith(\"\\r\") ? buf.slice(0, -1) : buf;\n                buf = \"\";\n                line(rest);\n            }\n            if (event !== \"\" || data.length > 0) line(\"\");\n        },\n        get lastId(): string | undefined {\n            return lastId;\n        },\n    };\n}\n\n// ── The idle watchdog ────────────────────────────────────────────────────\n\n/**\n * Half-open detection. Any line re-arms the timer (`touch`); `: ping`\n * comments also teach `\"auto\"` the server's cadence (`heartbeat`). When the\n * timer fires the pipe is presumed dead and `onTrip` aborts it, so the\n * reconnect path reopens with the cursor — the answer to \"pod hard-killed,\n * no FIN\".\n *\n * A twin of the browser's `idleWatchdog`, constants included.\n */\nfunction idleWatchdog(mode: IdleReconnect | undefined, onTrip: () => void) {\n    const setting: IdleReconnect = mode ?? \"auto\";\n    let window_: number = typeof setting === \"number\" ? setting : 0;\n    let lastBeat: number | null = null;\n    let beats = 0;\n    let timer: ReturnType<typeof setTimeout> | null = null;\n    let stopped = false;\n\n    function clear(): void {\n        if (timer !== null) {\n            clearTimeout(timer);\n            timer = null;\n        }\n    }\n\n    function arm(): void {\n        clear();\n        if (stopped || window_ <= 0) return;\n        timer = setTimeout(() => {\n            timer = null;\n            onTrip();\n        }, window_);\n        // A dangling watchdog must never hold the Node event loop open: an\n        // observation is a tail, not a reason for the process to live.\n        (timer as unknown as { unref?: () => void }).unref?.();\n    }\n\n    return {\n        touch(): void {\n            arm();\n        },\n        heartbeat(): void {\n            if (setting === \"auto\") {\n                const now = Date.now();\n                beats++;\n                if (lastBeat !== null && beats >= 2) {\n                    const cadence = now - lastBeat;\n                    window_ = Math.min(IDLE_MAX_MS, Math.max(IDLE_MIN_MS, 3 * cadence));\n                }\n                lastBeat = now;\n            }\n            arm();\n        },\n        /** A new pipe: forget the last pipe's timer, keep the learned cadence. */\n        reset(): void {\n            clear();\n            lastBeat = null;\n            beats = 0;\n            if (setting === \"auto\") window_ = 0;\n        },\n        stop(): void {\n            stopped = true;\n            clear();\n        },\n        get window(): number {\n            return window_;\n        },\n    };\n}\n\n// ── withListeners() — the onEntry / onCustom seam ────────────────────────\n\ninterface Sink {\n    apply(entry: AnyLogEntry): boolean;\n    applyAll(entries: readonly AnyLogEntry[]): number;\n}\n\n/**\n * Decorate a view so every applied entry fires `onEntry` (and `onCustom` for\n * `type: \"custom\"`) — in seq order, before any other notification, never\n * throttled. Fires when the view accepted the entry, or when it could never\n * store it (an unknown type); never for a seq duplicate, so a resume overlap\n * does not re-fire.\n *\n * A twin of the browser's `withListeners`.\n */\nfunction withListeners(\n    view: CallLogView,\n    listeners: {\n        onEntry: (entry: AnyLogEntry, state: Readonly<CallLogState>) => void;\n    },\n): Sink {\n    /** Highest seq the decorator saw — the dedupe for entries the view cannot. */\n    let seen = 0;\n\n    function apply(entry: AnyLogEntry): boolean {\n        const changed = view.apply(entry);\n        const seq = (entry as { seq?: unknown }).seq;\n        if (changed) {\n            listeners.onEntry(entry, view.state);\n        } else if (entry && typeof entry === \"object\" && typeof seq === \"number\"\n            && seq > seen && !isStorable(entry)) {\n            listeners.onEntry(entry, view.state);\n        }\n        if (typeof seq === \"number\") seen = Math.max(seen, seq);\n        return changed;\n    }\n\n    return {\n        apply,\n        applyAll(entries) {\n            let n = 0;\n            for (const e of entries) if (apply(e)) n++;\n            return n;\n        },\n    };\n}\n\n/**\n * Feed one wire frame into the sink. A frame is a single envelope or a\n * batch; unknown shapes are ignored (forward compatibility), never thrown.\n */\nfunction applyFrame(sink: Sink, raw: string): void {\n    let payload: unknown;\n    try {\n        payload = JSON.parse(raw);\n    } catch {\n        return;\n    }\n    if (Array.isArray(payload)) {\n        sink.applyAll(payload as AnyLogEntry[]);\n        return;\n    }\n    if (payload && typeof payload === \"object\") {\n        const obj = payload as { entries?: unknown };\n        if (Array.isArray(obj.entries)) {\n            sink.applyAll(obj.entries as AnyLogEntry[]);\n            return;\n        }\n        sink.apply(payload as AnyLogEntry);\n    }\n}\n\n// ── observe() ────────────────────────────────────────────────────────────\n\ntype EntryListener = (entry: AnyLogEntry, state: Readonly<CallLogState>) => void;\ntype CustomListener = (name: string, value: unknown, entry: LogEntry<\"custom\">) => void;\ntype FinishListener = (info: ObserveFinishInfo) => void;\n\n/**\n * Open an SSE observation of one call, or of an agent's lifecycle log.\n *\n * Exactly one of `call` / `agent`. Without a `token` one is minted from\n * `apiKey` — which needs an agent, so `{ call }` alone must carry a token\n * (see {@link ObserveOptions.token}).\n *\n * Terminal facts: a `204` (sealed cursor, nothing left) and a body that ends\n * after `call.summary` both finish with `\"summary\"`; `401/403/404` finish\n * with `\"error\"` and never retry; anything else reconnects on\n * `min(1000·2^n, 15000) + rand(0, 1000)` carrying `after=<lastSeq>`.\n */\nexport function observe(opts: ObserveOptions): Observation {\n    if (!opts.call === !opts.agent) {\n        throw new Error(\"observe: exactly one of { call, agent } is required\");\n    }\n    if (!opts.token && !opts.apiKey) {\n        throw new Error(\n            \"observe: a `token` is required (or an API key on the client to mint one)\",\n        );\n    }\n    if (!opts.token && !opts.agent) {\n        throw new Error(\n            \"observe: minting a stream token needs an agent — pass { call, agent } or a `token`\",\n        );\n    }\n\n    const doFetch: ObserveFetch =\n        opts.fetchImpl ?? ((url, init) => fetch(url, init) as unknown as Promise<ObserveResponseLike>);\n    const base = httpBase(opts.server);\n    const path = eventsPath(opts);\n    const queueLimit = Math.max(1, opts.queueLimit ?? DEFAULT_QUEUE_LIMIT);\n\n    const view = new CallLogView();\n\n    const entryListeners = new Set<EntryListener>();\n    const customListeners = new Set<CustomListener>();\n    const finishListeners = new Set<FinishListener>();\n\n    /** The bounded hand-off to `for await`. Oldest-out on overflow. */\n    const queue: AnyLogEntry[] = [];\n    let dropped = 0;\n    /** Parked `next()` calls, waiting for an entry or the end. */\n    const waiters: Array<(v: IteratorResult<AnyLogEntry>) => void> = [];\n\n    let finished = false;\n    let finishInfo: ObserveFinishInfo | null = null;\n    let resolveDone!: (v: { reason: \"summary\" | \"closed\" | \"error\"; lastSeq: number }) => void;\n    const done = new Promise<{ reason: \"summary\" | \"closed\" | \"error\"; lastSeq: number }>((r) => {\n        resolveDone = r;\n    });\n\n    const sink = withListeners(view, {\n        onEntry: (entry, state) => {\n            for (const fn of entryListeners) fn(entry, state);\n            if (entry.type === \"custom\") {\n                const d = (entry as { data?: { name?: unknown; value?: unknown } }).data;\n                if (d && typeof d.name === \"string\") {\n                    for (const fn of customListeners) {\n                        fn(d.name, d.value, entry as LogEntry<\"custom\">);\n                    }\n                }\n            }\n            const waiter = waiters.shift();\n            if (waiter) {\n                waiter({ value: entry, done: false });\n                return;\n            }\n            if (queue.length >= queueLimit) {\n                queue.shift();\n                dropped++;\n            }\n            queue.push(entry);\n        },\n    });\n\n    // ── transport state ──\n    let controller: AbortController | null = null;\n    let timer: ReturnType<typeof setTimeout> | null = null;\n    let attempts = 0;\n    let opened = 0;\n    /** Set when the watchdog aborted the request: the read error is a drop, not a failure. */\n    let idleTripped = false;\n\n    const watchdog = idleWatchdog(opts.idleReconnect, () => {\n        if (!controller || finished) return;\n        idleTripped = true;\n        controller.abort();\n    });\n\n    function clearTimer(): void {\n        if (timer !== null) {\n            clearTimeout(timer);\n            timer = null;\n        }\n    }\n\n    function finish(reason: ObserveFinishInfo[\"reason\"], error?: Error): void {\n        if (finished) return;\n        finished = true;\n        clearTimer();\n        watchdog.stop();\n        if (opts.signal) opts.signal.removeEventListener(\"abort\", onAbort);\n        const c = controller;\n        controller = null;\n        c?.abort();\n        const info: ObserveFinishInfo = {\n            reason,\n            ...(error ? { error } : {}),\n            lastSeq: view.lastSeq,\n        };\n        finishInfo = info;\n        for (const fn of finishListeners) fn(info);\n        resolveDone({ reason, lastSeq: info.lastSeq });\n        // Wake every parked consumer; whatever is already queued is still\n        // drained first by `next()`.\n        while (waiters.length > 0) {\n            waiters.shift()!({ value: undefined, done: true });\n        }\n    }\n\n    function onAbort(): void {\n        finish(\"closed\");\n    }\n    if (opts.signal) {\n        if (opts.signal.aborted) {\n            // Nothing to open: report the close on the next tick so the caller\n            // can still attach `on(\"finish\")` to the handle it is about to get.\n            queueMicrotask(() => finish(\"closed\"));\n        } else {\n            opts.signal.addEventListener(\"abort\", onAbort, { once: true });\n        }\n    }\n\n    function scheduleReconnect(): void {\n        if (finished || timer !== null) return;\n        if (opts.reconnect === false) {\n            finish(\"error\", new Error(\"observe: stream lost and reconnect is off\"));\n            return;\n        }\n        const delay = observeBackoffDelay(attempts);\n        attempts++;\n        timer = setTimeout(() => {\n            timer = null;\n            void open();\n        }, delay);\n        (timer as unknown as { unref?: () => void }).unref?.();\n    }\n\n    /** Minted once and reused across reconnects. */\n    let tokenPromise: Promise<string> | null = opts.token ? Promise.resolve(opts.token) : null;\n\n    function resolveToken(): Promise<string> {\n        if (!tokenPromise) {\n            tokenPromise = createToken({\n                channel: \"stream\",\n                agentId: opts.agent as string,\n                apiKey: opts.apiKey as string,\n                apiUrl: opts.apiUrl ?? base,\n                scope: \"observe\",\n                ...(opts.call ? { callId: opts.call } : {}),\n            }).then((r) => r.token);\n            // A failed mint must not be cached as a rejected promise forever:\n            // the next reconnect deserves a fresh attempt.\n            tokenPromise.catch(() => {\n                tokenPromise = null;\n            });\n        }\n        return tokenPromise;\n    }\n\n    async function open(): Promise<void> {\n        if (finished || controller) return;\n\n        let token: string;\n        try {\n            token = await resolveToken();\n        } catch (err) {\n            if (finished) return;\n            opts.onError?.(asError(err));\n            scheduleReconnect();\n            return;\n        }\n        if (finished || controller) return;\n\n        // Resume ALWAYS carries `after=<view.lastSeq>` — the view dedupes by\n        // seq, so an overlapping replay is safe by construction. `Last-Event-ID`\n        // is for the zero-JS `new EventSource(url)` path, not for this one.\n        const after = opened === 0 ? (opts.after ?? view.lastSeq) : view.lastSeq;\n        const url =\n            `${base}${path}?token=${encodeURIComponent(token)}` +\n            `&after=${after}` +\n            filterQuery(opts);\n\n        const c = new AbortController();\n        controller = c;\n        idleTripped = false;\n        watchdog.reset();\n\n        let res: ObserveResponseLike;\n        try {\n            res = await doFetch(url, {\n                headers: { Accept: \"text/event-stream\", Authorization: `Bearer ${token}` },\n                signal: c.signal,\n            });\n        } catch (err) {\n            if (controller !== c) return; // closed meanwhile\n            controller = null;\n            if (finished) return;\n            opts.onError?.(asError(err));\n            scheduleReconnect();\n            return;\n        }\n        if (controller !== c) return;\n\n        if (res.status === 204) {\n            // Sealed, and the cursor is already at the end: nothing left, ever.\n            controller = null;\n            finish(\"summary\");\n            return;\n        }\n        if (!res.ok) {\n            controller = null;\n            let detail = \"\";\n            try {\n                detail = await res.text();\n            } catch {\n                /* no body to quote */\n            }\n            const err = httpError(res.status, detail);\n            opts.onError?.(err);\n            if (isTerminalStatus(res.status)) {\n                finish(\"error\", err);\n                return;\n            }\n            scheduleReconnect();\n            return;\n        }\n        const body = res.body;\n        if (!body) {\n            controller = null;\n            opts.onError?.(new Error(\"observe: response has no readable body\"));\n            scheduleReconnect();\n            return;\n        }\n\n        opened++;\n        attempts = 0;\n        watchdog.touch();\n\n        const decoder = sseDecoder({\n            onLine: () => watchdog.touch(),\n            onComment: () => watchdog.heartbeat(),\n            onEvent: (ev) => {\n                if (ev.data === \"\") return;\n                applyFrame(sink, ev.data);\n            },\n        });\n\n        const reader = body.getReader();\n        let readError: Error | null = null;\n        try {\n            for (;;) {\n                const { done: streamDone, value } = await reader.read();\n                if (controller !== c || finished) return; // closed mid-read\n                if (streamDone) break;\n                if (value) decoder.push(value);\n            }\n            decoder.end();\n        } catch (err) {\n            if (controller !== c || finished) return;\n            readError = asError(err);\n        } finally {\n            try {\n                reader.releaseLock();\n            } catch {\n                /* already released */\n            }\n        }\n        if (controller !== c || finished) return;\n        controller = null;\n\n        // Unlike a WS attach, the stream does NOT stop on the reducer's\n        // disconnect intent (`call.ended`): the server ends the body right\n        // after `call.summary`, and cutting at `call.ended` would lose the\n        // summary that follows it. The body end — or a 204 — is the terminator.\n        if (isTerminal(view, opts)) {\n            finish(\"summary\");\n            return;\n        }\n        if (readError && !idleTripped) opts.onError?.(readError);\n        // Body ended without the call ending (agent log, slow consumer, proxy\n        // timeout, idle trip): the cursor is in the view — reopen from it.\n        scheduleReconnect();\n    }\n\n    if (!(opts.signal?.aborted)) void open();\n\n    function next(): Promise<IteratorResult<AnyLogEntry>> {\n        const queued = queue.shift();\n        if (queued !== undefined) return Promise.resolve({ value: queued, done: false });\n        if (finished) return Promise.resolve({ value: undefined, done: true });\n        return new Promise((resolve) => waiters.push(resolve));\n    }\n\n    const observation: Observation = {\n        get state() {\n            return view.state;\n        },\n        get lastSeq() {\n            return view.lastSeq;\n        },\n        get dropped() {\n            return dropped;\n        },\n        get active() {\n            return !finished;\n        },\n        on(event: \"entry\" | \"custom\" | \"finish\", fn: (...args: never[]) => void): () => void {\n            if (event === \"entry\") {\n                const l = fn as unknown as EntryListener;\n                entryListeners.add(l);\n                return () => entryListeners.delete(l);\n            }\n            if (event === \"custom\") {\n                const l = fn as unknown as CustomListener;\n                customListeners.add(l);\n                return () => customListeners.delete(l);\n            }\n            const l = fn as unknown as FinishListener;\n            // A listener attached after the end still hears it — the one fact\n            // it exists for must not depend on winning a race with the wire.\n            if (finishInfo) {\n                const info = finishInfo;\n                queueMicrotask(() => l(info));\n                return () => {};\n            }\n            finishListeners.add(l);\n            return () => finishListeners.delete(l);\n        },\n        done,\n        close() {\n            finish(\"closed\");\n        },\n        [Symbol.asyncIterator](): AsyncIterator<AnyLogEntry> {\n            return {\n                next,\n                return(): Promise<IteratorResult<AnyLogEntry>> {\n                    // `break` out of a `for await` closes the observation.\n                    finish(\"closed\");\n                    return Promise.resolve({ value: undefined, done: true });\n                },\n            };\n        },\n    };\n\n    return observation;\n}\n","/**\n * SSE format utilities — shared helpers for SSE streams.\n *\n * Derives STREAM_EVENTS from CALL_PROXY_EVENTS to avoid duplication.\n */\n\nimport { CALL_PROXY_EVENTS } from \"../dispatch/proxy.js\";\n\n/** SSE-streamable events — call lifecycle + proxy + WhatsApp + session. */\nexport const STREAM_EVENTS = [\n    \"call.started\", \"call.ended\",\n    ...CALL_PROXY_EVENTS.filter(e =>\n        e !== \"call.held\" && e !== \"call.unheld\" &&\n        e !== \"call.muted\" && e !== \"call.unmuted\" &&\n        e !== \"llm.toolCall\" && e !== \"session.timeout\"\n    ),\n    // WhatsApp\n    \"whatsapp.sessionStarted\", \"whatsapp.sessionEnded\",\n    \"whatsapp.message\", \"whatsapp.response\", \"whatsapp.status\",\n    // Human-in-the-loop\n    \"session.paused\", \"session.resumed\",\n] as const;\n\n/** Format a single SSE message. */\nexport function formatSSE(event: string, data: Record<string, unknown>): string {\n    return `event: ${event}\\ndata: ${JSON.stringify(data)}\\n\\n`;\n}\n\n/** SSE headers for HTTP responses. */\nexport const SSE_HEADERS: Record<string, string> = {\n    \"Content-Type\": \"text/event-stream\",\n    \"Cache-Control\": \"no-cache\",\n    \"Connection\": \"keep-alive\",\n    \"X-Accel-Buffering\": \"no\", // nginx\n};\n","/**\n * Event data — the shape an agent event takes on the wire.\n *\n * Agent events are emitted with whatever arguments the emitter had at hand:\n * a Call, a plain data object, or both. Every stream transport (SSE and\n * WebSocket) has to flatten that argument list into ONE JSON object before it\n * can send it, and they must flatten it the SAME way — a browser listening on\n * `/events` and one listening on `/ws/events` are looking at the same call.\n *\n * That is why this lives here instead of once per transport: it IS the shared\n * shape, not a helper either transport happens to need.\n */\n\nimport type { Call } from \"../domain/call.js\";\n\n/**\n * Flatten an event's emitted arguments into a single JSON-safe object.\n *\n * A Call argument is recognised structurally (id + from + to + transport) and\n * reduced to its identifying fields — the whole object is not serialisable.\n * Anything else is copied field by field, skipping functions and `_`-prefixed\n * internals so nothing private leaks to a listener.\n */\nexport function buildEventData(event: string, args: unknown[]): Record<string, unknown> {\n    const data: Record<string, unknown> = {};\n\n    for (const arg of args) {\n        if (!arg || typeof arg !== \"object\") continue;\n\n        // Call object — extract key fields\n        if (\"id\" in arg && \"from\" in arg && \"to\" in arg && \"transport\" in arg) {\n            const call = arg as Call;\n            data.callId = call.id;\n            data.from = call.from;\n            data.to = call.to;\n            data.direction = call.direction;\n            data.transport = call.transport;\n            if (call.duration) data.duration = call.duration;\n            if (call.reason) data.reason = call.reason;\n            continue;\n        }\n\n        // Event data — copy safe fields\n        for (const [k, v] of Object.entries(arg as Record<string, unknown>)) {\n            if (typeof v === \"function\" || k.startsWith(\"_\")) continue;\n            data[k] = v;\n        }\n    }\n\n    return data;\n}\n","/**\n * SSE stream — creates SSE responses from agent events.\n *\n * Port of src.bkp/sse.ts — identical behavior.\n */\n\nimport type { Agent } from \"../domain/agent.js\";\nimport type { ServerResponse } from \"node:http\";\nimport { formatSSE, SSE_HEADERS, STREAM_EVENTS } from \"./format.js\";\nimport { buildEventData } from \"./event-data.js\";\n\nexport interface StreamOptions {\n    agents?: string[];\n}\n\n// ─── Dedup ───────────────────────────────────────────────────────────────\n\n/**\n * A call's events can reach an agent listener more than once for the same\n * logical message — a re-sent wire frame from the server, or a call proxied\n * twice under a race. Each SSE connection guards against writing the same\n * (event, callId, messageId) frame twice: the FIRST copy wins, every later\n * one is dropped before it reaches `res.write()`. Events with no messageId\n * (call.started, audio.metrics, …) are never deduped — only a message has an\n * id to be idempotent on.\n */\nfunction createDedupeGuard(): (event: string, data: Record<string, unknown>) => boolean {\n    const seen = new Set<string>();\n    return (event, data) => {\n        const messageId = typeof data.messageId === \"string\" ? data.messageId : \"\";\n        if (!messageId) return false;\n        const key = `${event}|${data.callId ?? \"\"}|${messageId}`;\n        if (seen.has(key)) return true;\n        seen.add(key);\n        return false;\n    };\n}\n\n// ─── Multi-agent stream ──────────────────────────────────────────────────\n\nexport function createMultiAgentStream(\n    agents: Map<string, Agent>,\n    filter?: StreamOptions,\n): Response;\nexport function createMultiAgentStream(\n    agents: Map<string, Agent>,\n    res: ServerResponse,\n    filter?: StreamOptions,\n): void;\nexport function createMultiAgentStream(\n    agents: Map<string, Agent>,\n    resOrFilter?: ServerResponse | StreamOptions,\n    filter?: StreamOptions,\n): Response | void {\n    let res: ServerResponse | undefined;\n    let opts: StreamOptions | undefined;\n\n    if (resOrFilter && typeof (resOrFilter as any).writeHead === \"function\") {\n        res = resOrFilter as ServerResponse;\n        opts = filter;\n    } else {\n        opts = resOrFilter as StreamOptions;\n    }\n\n    const targetAgents = getFilteredAgents(agents, opts);\n    const allHandlers: Array<{ agent: Agent; event: string; handler: (...args: any[]) => void }> = [];\n\n    const cleanup = () => {\n        for (const { agent, event, handler } of allHandlers) {\n            agent.off(event, handler);\n        }\n        allHandlers.length = 0;\n    };\n\n    const agentIds = targetAgents.map(a => a.id);\n\n    // ── Node.js ServerResponse mode ──\n    if (res) {\n        res.writeHead(200, SSE_HEADERS);\n        res.flushHeaders();\n        res.write(formatSSE(\"connected\", { agents: agentIds }));\n\n        const dedupe = createDedupeGuard();\n        for (const agent of targetAgents) {\n            for (const evt of STREAM_EVENTS) {\n                const handler = (...args: any[]) => {\n                    const data = buildEventData(evt, args);\n                    if (dedupe(evt, data)) return;\n                    const payload = { ...data, agent: agent.id };\n                    try { res!.write(formatSSE(evt, payload)); }\n                    catch { cleanup(); }\n                };\n                allHandlers.push({ agent, event: evt, handler });\n                agent.on(evt, handler);\n            }\n        }\n\n        const ping = setInterval(() => {\n            try { res!.write(\":ping\\n\\n\"); } catch { clearInterval(ping); cleanup(); }\n        }, 30_000);\n\n        res.on(\"close\", () => { clearInterval(ping); cleanup(); });\n        return;\n    }\n\n    // ── Web API Response mode ──\n    const encoder = new TextEncoder();\n    const stream = new ReadableStream({\n        start(controller) {\n            controller.enqueue(encoder.encode(\n                formatSSE(\"connected\", { agents: agentIds }),\n            ));\n\n            const dedupe = createDedupeGuard();\n            for (const agent of targetAgents) {\n                for (const evt of STREAM_EVENTS) {\n                    const handler = (...args: any[]) => {\n                        const data = buildEventData(evt, args);\n                        if (dedupe(evt, data)) return;\n                        const payload = { ...data, agent: agent.id };\n                        try { controller.enqueue(encoder.encode(formatSSE(evt, payload))); }\n                        catch { cleanup(); }\n                    };\n                    allHandlers.push({ agent, event: evt, handler });\n                    agent.on(evt, handler);\n                }\n            }\n\n            const ping = setInterval(() => {\n                try { controller.enqueue(encoder.encode(\":ping\\n\\n\")); }\n                catch { clearInterval(ping); cleanup(); }\n            }, 30_000);\n            (controller as any)._pingTimer = ping;\n        },\n        cancel() {\n            const ping = (this as any)?._pingTimer;\n            if (ping) clearInterval(ping);\n            cleanup();\n        },\n    });\n\n    return new Response(stream, { headers: SSE_HEADERS });\n}\n\n// ─── Helpers ─────────────────────────────────────────────────────────────\n\nfunction getFilteredAgents(agents: Map<string, Agent>, opts?: StreamOptions): Agent[] {\n    const all = [...agents.values()];\n    if (!opts?.agents?.length) return all;\n    return all.filter(a => opts.agents!.includes(a.id));\n}\n\n","/**\n * SSE parser — the CLIENT half of Server-Sent Events.\n *\n * `format.ts` writes the wire; this reads it. Incremental by design: feed it\n * whatever the network hands over — a frame may arrive split across chunks,\n * or several frames may land in one — and it dispatches one callback per\n * complete event, as soon as its terminating blank line is in.\n *\n * Handles `data:` (multi-line data joined with \"\\n\", per the spec), `event:`,\n * `id:`, comments (`:ping`) and CRLF/CR line endings. Everything else is\n * ignored.\n */\n\nexport interface SSEEvent {\n    event?: string;\n    id?: string;\n    data: string;\n}\n\nexport interface SSEParser {\n    /** Feed raw bytes or text as they arrive. */\n    feed(chunk: Uint8Array | string): void;\n    /** Flush a trailing event that had no blank line after it. */\n    end(): void;\n}\n\nexport function createSSEParser(onEvent: (evt: SSEEvent) => void): SSEParser {\n    const decoder = new TextDecoder();\n    let buffer = \"\";\n    let data: string[] = [];\n    let event: string | undefined;\n    let id: string | undefined;\n\n    const dispatch = () => {\n        if (data.length === 0 && event === undefined && id === undefined) return;\n        if (data.length > 0) onEvent({ event, id, data: data.join(\"\\n\") });\n        data = [];\n        event = undefined;\n        id = undefined;\n    };\n\n    const line = (raw: string) => {\n        if (raw === \"\") { dispatch(); return; }\n        if (raw.startsWith(\":\")) return; // comment / keepalive\n        const colon = raw.indexOf(\":\");\n        const field = colon === -1 ? raw : raw.slice(0, colon);\n        let value = colon === -1 ? \"\" : raw.slice(colon + 1);\n        if (value.startsWith(\" \")) value = value.slice(1);\n        switch (field) {\n            case \"data\": data.push(value); break;\n            case \"event\": event = value; break;\n            case \"id\": id = value; break;\n            default: break; // retry / unknown fields — not our concern\n        }\n    };\n\n    const drain = (final: boolean) => {\n        // Normalise line endings, then split on what we are sure is complete.\n        buffer = buffer.replace(/\\r\\n?/g, \"\\n\");\n        let nl: number;\n        while ((nl = buffer.indexOf(\"\\n\")) !== -1) {\n            line(buffer.slice(0, nl));\n            buffer = buffer.slice(nl + 1);\n        }\n        if (final && buffer.length > 0) { line(buffer); buffer = \"\"; }\n    };\n\n    return {\n        feed(chunk) {\n            buffer += typeof chunk === \"string\" ? chunk : decoder.decode(chunk, { stream: true });\n            drain(false);\n        },\n        end() {\n            buffer += decoder.decode();\n            drain(true);\n            dispatch();\n        },\n    };\n}\n","/**\n * Voice API — fetch available TTS voices.\n */\n\nimport { DEFAULT_API_URL } from \"./http.js\";\n\nexport interface Voice {\n    id: string;\n    name: string;\n    /** Friendly alias for use in `voice` config, e.g. \"sarah\" → `\"elevenlabs/sarah\"` */\n    alias?: string;\n    provider: string;\n    gender?: string;\n    style?: string;\n    languages: VoiceLanguage[];\n    description?: string;\n    previewUrl?: string;\n}\n\nexport interface VoiceLanguage {\n    code: string;\n    name: string;\n    flag?: string;\n    nativeName?: string;\n    region?: string;\n}\n\nexport interface FetchVoicesOptions {\n    provider?: string;\n    language?: string;\n    apiUrl?: string;\n}\n\nexport async function fetchVoices(opts: FetchVoicesOptions = {}): Promise<Voice[]> {\n    const provider = opts.provider ?? \"elevenlabs\";\n    const apiUrl = opts.apiUrl ?? DEFAULT_API_URL;\n    let url = `${apiUrl}/api/sdk/voices?provider=${encodeURIComponent(provider)}`;\n    if (opts.language) url += `&language=${encodeURIComponent(opts.language)}`;\n\n    let res: Response;\n    try {\n        res = await fetch(url);\n    } catch (err) {\n        throw new Error(`Network error fetching voices: ${err}`);\n    }\n\n    if (!res.ok) {\n        throw new Error(`Failed to fetch voices: HTTP ${res.status}`);\n    }\n\n    const data = await res.json();\n    if (!data.success || !Array.isArray(data.voices)) return [];\n\n    let voices: Voice[] = data.voices.map(mapVoice(provider));\n\n    if (opts.language) {\n        const lang = opts.language.toLowerCase();\n        voices = voices.filter((v) =>\n            v.languages.some((l) => l.code.toLowerCase().startsWith(lang)),\n        );\n    }\n\n    return voices;\n}\n\n/**\n * Map a raw server voice to the SDK shape. `provider` is the fallback; a\n * voice that names its own provider (as `/v1/audio/voices` rows do) wins.\n */\nexport function mapVoice(provider: string): (raw: Record<string, unknown>) => Voice {\n    return (v) => ({\n        id: (v.id ?? v.voice_id ?? \"\") as string,\n        name: (v.name ?? \"Unknown\") as string,\n        alias: v.alias as string | undefined,\n        provider: (typeof v.provider === \"string\" && v.provider) || provider,\n        gender: v.gender as string | undefined,\n        style: v.style as string | undefined,\n        languages: Array.isArray(v.languages) ? v.languages.map(mapLanguage) : [],\n        description: v.description as string | undefined,\n        previewUrl: v.preview_url as string | undefined,\n    });\n}\n\nfunction mapLanguage(raw: unknown): VoiceLanguage {\n    if (typeof raw === \"string\") return { code: raw, name: raw };\n    const l = raw as Record<string, unknown>;\n    return {\n        code: (l.code ?? \"\") as string,\n        name: (l.name ?? \"\") as string,\n        flag: l.flag as string | undefined,\n        nativeName: l.nativeName as string | undefined,\n        region: l.region as string | undefined,\n    };\n}\n","/**\n * Audio API — standalone speech-to-text, no agent and no call.\n *\n * Two endpoints, the batch one and the live one:\n *   - `POST {apiUrl}/v1/audio/transcriptions` — one audio file in (multipart,\n *     OpenAI shape), one transcript out: `json` (text + language + duration),\n *     `verbose_json` (adds words and segments, with speaker labels when\n *     `diarize` is on) or `text` (plain body). `transcribe()`.\n *   - `WS {wsUrl}/v1/audio/transcriptions/stream` — raw PCM frames in,\n *     `partial` / `final` frames out as the speech is recognised, one `done`\n *     frame with the billing at the end. `transcribeStream()`.\n *\n * Auth is the `Authorization: Bearer` header on both — the socket too (Node's\n * `ws` sends headers; the `?api_key=` fallback the server accepts is never used\n * here, a key in a URL ends up in logs). Runs on Node ≥ 18 and in Electron\n * main; `ws` and `node:fs/promises` are imported lazily so a browser bundle\n * that only uses `transcribe()` with bytes never pays for them.\n */\n\nimport { TypedEventBus, type EventMap } from \"../kernel/event-bus.js\";\nimport { DEFAULT_API_URL } from \"./http.js\";\nimport { AudioApiError, AsyncQueue, readError } from \"./audio.js\";\n\n// ── Types — batch ────────────────────────────────────────────────────────\n\nexport type TranscriptionModel =\n    | \"elevenlabs/scribe_v1\"\n    | \"deepgram/nova-3\"\n    | \"deepgram/nova-2\"\n    | \"soniox/stt-async-preview\"\n    | (string & {});\n\nexport interface TranscribeOptions {\n    /** `\"provider/model\"` or `\"provider\"`; omitted → `elevenlabs/scribe_v1`. */\n    model?: TranscriptionModel;\n    /** ISO-639-1 language code; omitted → auto-detect. */\n    language?: string;\n    /** Label speakers (`words[].speaker`, `segments[].speaker`). Default false. */\n    diarize?: boolean;\n    /** `\"json\"` (default) | `\"verbose_json\"` (words + segments) | `\"text\"`. */\n    format?: \"json\" | \"verbose_json\" | \"text\";\n    /** Name sent with the file part — the server infers the container from it. */\n    filename?: string;\n    /** MIME type of the file part; inferred from `filename` / the path when omitted. */\n    contentType?: string;\n    /** Abort the request from outside. */\n    signal?: AbortSignal;\n}\n\nexport interface TranscriptWord {\n    word: string;\n    /** Seconds from the start of the audio. */\n    start: number;\n    end: number;\n    /** Speaker label (`\"0\"`, `\"1\"`, …) when diarization is on. */\n    speaker?: string;\n}\n\nexport interface TranscriptSegment {\n    id: number;\n    start: number;\n    end: number;\n    text: string;\n    speaker?: string;\n}\n\nexport interface Transcription {\n    requestId: string;\n    text: string;\n    /** Detected or requested language; `\"\"` when the wire had none (`format: \"text\"`). */\n    language: string;\n    /** Audio duration in seconds; 0 when the wire had none (`format: \"text\"`). */\n    duration: number;\n    /** Only with `format: \"verbose_json\"`. */\n    model?: string;\n    words?: TranscriptWord[];\n    segments?: TranscriptSegment[];\n}\n\n/** Bytes, a `Blob`/`File`, or — Node only — a path to read. */\nexport type TranscribeInput = Uint8Array | ArrayBuffer | Blob | string;\n\n// ── Types — streaming ────────────────────────────────────────────────────\n\nexport type StreamModel =\n    | \"deepgram/nova-3\"\n    | \"elevenlabs/scribe_v2_realtime\"\n    | \"soniox/stt-rt-v5\"\n    | (string & {});\n\nexport interface TranscribeStreamOptions {\n    /** Omitted → `deepgram/nova-3`. */\n    model?: StreamModel;\n    /** ISO-639-1 language code; omitted → auto-detect. */\n    language?: string;\n    /** Sample rate of the PCM you write. Default 16000. */\n    sampleRate?: 8000 | 16000 | 24000 | 48000;\n    /** `\"linear16\"` (default, s16le mono) | `\"mulaw\"`. */\n    encoding?: \"linear16\" | \"mulaw\";\n    /** Speaker labels on `final` segments (soniox / deepgram). */\n    diarize?: boolean;\n}\n\nexport interface StreamFinal {\n    text: string;\n    start?: number;\n    end?: number;\n    language?: string;\n    speaker?: string;\n    words?: TranscriptWord[];\n}\n\nexport interface StreamReady {\n    requestId: string;\n    model: string;\n    sampleRate: number;\n}\n\nexport interface StreamDone {\n    audioSeconds: number;\n    billedMinutes: number;\n}\n\nexport interface TranscribeStreamEvents {\n    /** The server accepted the socket and is listening for audio. */\n    ready: (info: StreamReady) => void;\n    /** Interim hypothesis for the current utterance — replaced by the next one. */\n    partial: (text: string) => void;\n    /** A committed segment. */\n    final: (seg: StreamFinal) => void;\n    /** The server finished after `end()` — billing for the session. */\n    done: (info: StreamDone) => void;\n    /** A refusal (auth, args, upstream) or a socket failure. The stream is over. */\n    error: (err: AudioApiError) => void;\n    /** The socket closed, with its close code. Always last. */\n    close: (code: number) => void;\n}\n\nexport type TranscribeStreamItem =\n    | { type: \"partial\"; text: string }\n    | { type: \"final\"; segment: StreamFinal };\n\nexport interface TranscribeStream {\n    /** Set by the `ready` frame; `\"\"` before. */\n    readonly requestId: string;\n    /** Resolves on `ready`; rejects if the server refuses before that. */\n    readonly ready: Promise<void>;\n    /** Queue audio bytes. Buffered until `ready`, then sent in order as binary frames. */\n    write(chunk: Uint8Array | ArrayBuffer): void;\n    /** Ask the server to commit what it has heard so far (a `final` follows). */\n    finalize(): void;\n    /** No more audio: the server flushes, sends `done` and closes. Resolves on `done`. */\n    end(): Promise<StreamDone>;\n    /** Drop the socket now (close 1000) without waiting for `done`. */\n    close(): void;\n    on<K extends keyof TranscribeStreamEvents>(ev: K, fn: TranscribeStreamEvents[K]): this;\n    off<K extends keyof TranscribeStreamEvents>(ev: K, fn: TranscribeStreamEvents[K]): this;\n    once<K extends keyof TranscribeStreamEvents>(ev: K, fn: TranscribeStreamEvents[K]): this;\n    /** `partial` and `final` frames in order; ends on `done`, throws on `error`. */\n    [Symbol.asyncIterator](): AsyncIterator<TranscribeStreamItem>;\n}\n\nexport interface TranscribeApiOptions {\n    apiKey: string;\n    /** Voice server base, e.g. https://voice.pinecall.io (the default). */\n    apiUrl?: string;\n}\n\n// ── Wire frames ──────────────────────────────────────────────────────────\n\ninterface WireWord { word: string; start: number; end: number; speaker?: string | number }\ninterface WireSegment { id: number; start: number; end: number; text: string; speaker?: string | number }\n\ninterface WireTranscription {\n    text?: string;\n    language?: string;\n    duration?: number;\n    model?: string;\n    words?: WireWord[];\n    segments?: WireSegment[];\n}\n\ntype StreamFrame =\n    | { type: \"ready\"; request_id?: string; model?: string; sample_rate?: number; encoding?: string; diarize?: boolean }\n    | { type: \"partial\"; text?: string }\n    | { type: \"final\"; text?: string; start?: number; end?: number; language?: string; speaker?: string | number; words?: WireWord[] }\n    | { type: \"done\"; request_id?: string; audio_seconds?: number; billed_minutes?: number }\n    | { type: \"error\"; code?: string; error?: string };\n\n// ── Helpers ──────────────────────────────────────────────────────────────\n\nconst MIME_BY_EXT: Record<string, string> = {\n    wav: \"audio/wav\",\n    wave: \"audio/wav\",\n    mp3: \"audio/mpeg\",\n    mpga: \"audio/mpeg\",\n    m4a: \"audio/mp4\",\n    mp4: \"audio/mp4\",\n    aac: \"audio/aac\",\n    webm: \"audio/webm\",\n    ogg: \"audio/ogg\",\n    oga: \"audio/ogg\",\n    opus: \"audio/ogg\",\n    flac: \"audio/flac\",\n    pcm: \"audio/pcm\",\n    raw: \"audio/pcm\",\n    mulaw: \"audio/basic\",\n    ulaw: \"audio/basic\",\n};\n\nconst EXT_BY_MIME: Record<string, string> = {\n    \"audio/wav\": \"wav\",\n    \"audio/x-wav\": \"wav\",\n    \"audio/wave\": \"wav\",\n    \"audio/mpeg\": \"mp3\",\n    \"audio/mp3\": \"mp3\",\n    \"audio/mp4\": \"m4a\",\n    \"audio/x-m4a\": \"m4a\",\n    \"audio/aac\": \"aac\",\n    \"audio/webm\": \"webm\",\n    \"audio/ogg\": \"ogg\",\n    \"audio/opus\": \"ogg\",\n    \"audio/flac\": \"flac\",\n    \"audio/x-flac\": \"flac\",\n    \"audio/pcm\": \"pcm\",\n    \"audio/l16\": \"pcm\",\n    \"audio/basic\": \"ulaw\",\n};\n\nfunction extOf(name: string): string {\n    const base = name.split(/[\\\\/]/).pop() ?? name;\n    const dot = base.lastIndexOf(\".\");\n    return dot > 0 ? base.slice(dot + 1).toLowerCase() : \"\";\n}\n\nfunction basename(path: string): string {\n    return path.split(/[\\\\/]/).pop() || path;\n}\n\nfunction speakerLabel(s: string | number | undefined): string | undefined {\n    if (s === undefined || s === null) return undefined;\n    return typeof s === \"string\" ? s : String(s);\n}\n\nfunction mapWord(w: WireWord): TranscriptWord {\n    const out: TranscriptWord = { word: w.word, start: w.start, end: w.end };\n    const sp = speakerLabel(w.speaker);\n    if (sp !== undefined) out.speaker = sp;\n    return out;\n}\n\nfunction mapSegment(s: WireSegment): TranscriptSegment {\n    const out: TranscriptSegment = { id: s.id, start: s.start, end: s.end, text: s.text };\n    const sp = speakerLabel(s.speaker);\n    if (sp !== undefined) out.speaker = sp;\n    return out;\n}\n\nfunction abortError(): Error {\n    const err = new Error(\"The transcription request was aborted\");\n    err.name = \"AbortError\";\n    return err;\n}\n\n/** Resolve `input` to a Blob plus the filename/content type to send it under. */\nasync function toFilePart(\n    input: TranscribeInput,\n    opts: TranscribeOptions,\n): Promise<{ blob: Blob; filename: string }> {\n    let bytes: Uint8Array | ArrayBuffer | Blob;\n    let filename = opts.filename;\n    let contentType = opts.contentType;\n\n    if (typeof input === \"string\") {\n        // Variable specifier: browser bundlers leave it alone (same trick as toFile).\n        const fsSpecifier = \"node:fs/promises\";\n        const fs = (await import(/* @vite-ignore */ fsSpecifier)) as typeof import(\"node:fs/promises\");\n        const buf = await fs.readFile(input);\n        bytes = new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);\n        filename ??= basename(input);\n    } else {\n        bytes = input;\n        if (!filename && typeof Blob !== \"undefined\" && input instanceof Blob) {\n            const name = (input as { name?: unknown }).name;\n            if (typeof name === \"string\" && name) filename = name;\n            if (!contentType && input.type) contentType = input.type;\n        }\n    }\n\n    // Fill the gaps from each other; `audio.wav` is the last resort.\n    if (!contentType && filename) contentType = MIME_BY_EXT[extOf(filename)];\n    if (!filename) filename = `audio.${(contentType && EXT_BY_MIME[contentType.split(\";\")[0].trim().toLowerCase()]) || \"wav\"}`;\n    if (!contentType) contentType = MIME_BY_EXT[extOf(filename)] ?? \"audio/wav\";\n\n    const blob = bytes instanceof Blob && bytes.type === contentType\n        ? bytes\n        : new Blob([bytes as BlobPart], { type: contentType });\n    return { blob, filename };\n}\n\nfunction mapTranscription(requestId: string, w: WireTranscription): Transcription {\n    const out: Transcription = {\n        requestId,\n        text: typeof w.text === \"string\" ? w.text : \"\",\n        language: typeof w.language === \"string\" ? w.language : \"\",\n        duration: typeof w.duration === \"number\" ? w.duration : 0,\n    };\n    if (typeof w.model === \"string\") out.model = w.model;\n    if (Array.isArray(w.words)) out.words = w.words.map(mapWord);\n    if (Array.isArray(w.segments)) out.segments = w.segments.map(mapSegment);\n    return out;\n}\n\n// ── transcribe() ─────────────────────────────────────────────────────────\n\n/**\n * `POST /v1/audio/transcriptions` — transcribe one file.\n *\n * `input` is the audio: bytes, a `Blob`/`File`, or (Node only) a path, read\n * lazily through `node:fs/promises`. The content type comes from\n * `contentType`, else the filename / path extension, else `audio/wav`.\n */\nexport async function transcribe(\n    input: TranscribeInput,\n    opts: TranscribeOptions & TranscribeApiOptions,\n): Promise<Transcription> {\n    if (!opts.apiKey) {\n        throw new AudioApiError(\"transcribe() needs an apiKey\", 0, \"MISSING_KEY\");\n    }\n    if (opts.signal?.aborted) throw abortError();\n\n    const { blob, filename } = await toFilePart(input, opts);\n    if (opts.signal?.aborted) throw abortError();\n\n    const form = new FormData();\n    form.append(\"file\", blob, filename);\n    if (opts.model !== undefined) form.append(\"model\", opts.model);\n    if (opts.language !== undefined) form.append(\"language\", opts.language);\n    if (opts.diarize !== undefined) form.append(\"diarize\", opts.diarize ? \"true\" : \"false\");\n    if (opts.format !== undefined) form.append(\"response_format\", opts.format);\n\n    const url = new URL(\"/v1/audio/transcriptions\", opts.apiUrl ?? DEFAULT_API_URL);\n    let res: Response;\n    try {\n        res = await fetch(url.toString(), {\n            method: \"POST\",\n            headers: {\n                Authorization: `Bearer ${opts.apiKey}`,\n                Accept: opts.format === \"text\" ? \"text/plain\" : \"application/json\",\n            },\n            body: form,\n            ...(opts.signal ? { signal: opts.signal } : {}),\n        });\n    } catch (err) {\n        if ((err as Error)?.name === \"AbortError\") throw err;\n        throw new AudioApiError(\n            `Cannot reach the voice server: ${(err as Error)?.message ?? err}`,\n            0,\n            \"NETWORK_ERROR\",\n        );\n    }\n\n    if (!res.ok) throw await readError(res, \"audio/transcriptions\");\n\n    const requestId = res.headers.get(\"x-pinecall-request-id\") ?? \"\";\n    const contentType = (res.headers.get(\"content-type\") ?? \"\").toLowerCase();\n\n    if (opts.format === \"text\" || contentType.startsWith(\"text/plain\")) {\n        const text = await res.text();\n        return { requestId, text, language: \"\", duration: 0 };\n    }\n\n    const raw = await res.text();\n    let body: WireTranscription;\n    try {\n        body = JSON.parse(raw) as WireTranscription;\n    } catch {\n        throw new AudioApiError(\n            `audio/transcriptions: the server answered with something that is not JSON: ${raw.slice(0, 200)}`,\n            res.status,\n            \"BAD_RESPONSE\",\n        );\n    }\n    return mapTranscription(requestId, body);\n}\n\n// ── transcribeStream() ───────────────────────────────────────────────────\n\nconst STREAM_PATH = \"/v1/audio/transcriptions/stream\";\n\n/** Shape of the `ws` default export we need — kept local so `ws` stays a lazy import. */\ninterface NodeWebSocketLike {\n    readyState: number;\n    send(data: Uint8Array | string, cb?: (err?: Error) => void): void;\n    close(code?: number, reason?: string): void;\n    terminate?(): void;\n    on(event: \"open\", fn: () => void): unknown;\n    on(event: \"message\", fn: (data: unknown, isBinary: boolean) => void): unknown;\n    on(event: \"close\", fn: (code: number, reason: unknown) => void): unknown;\n    on(event: \"error\", fn: (err: Error) => void): unknown;\n    on(event: \"unexpected-response\", fn: (req: unknown, res: { statusCode?: number; statusMessage?: string }) => void): unknown;\n}\n\ntype NodeWebSocketCtor = new (url: string, opts: { headers: Record<string, string> }) => NodeWebSocketLike;\n\nasync function loadWS(): Promise<NodeWebSocketCtor> {\n    try {\n        const mod = await import(\"ws\");\n        return mod.default as unknown as NodeWebSocketCtor;\n    } catch {\n        throw new AudioApiError(\n            \"transcribeStream() needs the 'ws' package on Node: npm i ws\",\n            0,\n            \"NETWORK_ERROR\",\n        );\n    }\n}\n\nfunction streamUrl(apiUrl: string | undefined, opts: TranscribeStreamOptions): string {\n    const url = new URL(STREAM_PATH, apiUrl ?? DEFAULT_API_URL);\n    url.protocol = url.protocol === \"https:\" ? \"wss:\" : url.protocol === \"http:\" ? \"ws:\" : url.protocol;\n    if (opts.model !== undefined) url.searchParams.set(\"model\", opts.model);\n    if (opts.language !== undefined) url.searchParams.set(\"language\", opts.language);\n    if (opts.sampleRate !== undefined) url.searchParams.set(\"sample_rate\", String(opts.sampleRate));\n    if (opts.encoding !== undefined) url.searchParams.set(\"encoding\", opts.encoding);\n    if (opts.diarize !== undefined) url.searchParams.set(\"diarize\", opts.diarize ? \"true\" : \"false\");\n    return url.toString();\n}\n\nfunction toBytes(chunk: Uint8Array | ArrayBuffer): Uint8Array {\n    return chunk instanceof Uint8Array ? chunk : new Uint8Array(chunk);\n}\n\nfunction frameToText(data: unknown): string | null {\n    if (typeof data === \"string\") return data;\n    if (data instanceof Uint8Array) return new TextDecoder().decode(data);\n    if (data instanceof ArrayBuffer) return new TextDecoder().decode(new Uint8Array(data));\n    if (Array.isArray(data)) return data.map((d) => frameToText(d) ?? \"\").join(\"\");\n    return null;\n}\n\n// The bus wants an index signature; the public event map stays exact.\ntype StreamEventMap = TranscribeStreamEvents & EventMap;\n\nclass TranscribeStreamImpl extends TypedEventBus<StreamEventMap> implements TranscribeStream {\n    #ws: NodeWebSocketLike | null = null;\n    #requestId = \"\";\n    #isReady = false;\n    #finished = false;       // done, error or close seen — nothing more goes out\n    #closedByUser = false;\n    #pending: Array<Uint8Array | string> = [];\n    #doneInfo: StreamDone | undefined;\n    #error: AudioApiError | undefined;\n\n    readonly ready: Promise<void>;\n    #resolveReady!: () => void;\n    #rejectReady!: (e: unknown) => void;\n\n    #endPromise: Promise<StreamDone> | undefined;\n    #resolveEnd: ((d: StreamDone) => void) | undefined;\n    #rejectEnd: ((e: unknown) => void) | undefined;\n\n    readonly #items = new AsyncQueue<TranscribeStreamItem>();\n\n    constructor(url: string, apiKey: string) {\n        super();\n        this.ready = new Promise<void>((resolve, reject) => {\n            this.#resolveReady = resolve;\n            this.#rejectReady = reject;\n        });\n        // A caller who never awaits `ready` must not crash the process on a refusal.\n        this.ready.catch(() => {});\n        void this.#open(url, apiKey);\n    }\n\n    get requestId(): string {\n        return this.#requestId;\n    }\n\n    // ── socket ───────────────────────────────────────────────────────────\n\n    async #open(url: string, apiKey: string): Promise<void> {\n        let WS: NodeWebSocketCtor;\n        try {\n            WS = await loadWS();\n        } catch (err) {\n            this.#fail(err as AudioApiError);\n            return;\n        }\n        if (this.#closedByUser) {\n            this.#settleClose(1000);\n            return;\n        }\n        let ws: NodeWebSocketLike;\n        try {\n            ws = new WS(url, { headers: { Authorization: `Bearer ${apiKey}` } });\n        } catch (err) {\n            this.#fail(new AudioApiError(\n                `Cannot open the transcription socket: ${(err as Error)?.message ?? err}`,\n                0,\n                \"NETWORK_ERROR\",\n            ));\n            return;\n        }\n        this.#ws = ws;\n        ws.on(\"open\", () => {\n            if (this.#closedByUser) ws.close(1000);\n        });\n        ws.on(\"message\", (data, isBinary) => {\n            if (isBinary) return; // the server never sends binary; ignore\n            const text = frameToText(data);\n            if (text === null) return;\n            this.#onFrame(text);\n        });\n        ws.on(\"unexpected-response\", (_req, res) => {\n            // The handshake was refused (401/402/…) before any frame could reach us.\n            const status = res?.statusCode ?? 0;\n            const code = status === 401 ? \"INVALID_KEY\"\n                : status === 402 ? \"SUBSCRIPTION_REQUIRED\"\n                : status === 429 ? \"RATE_LIMITED\"\n                : `HTTP_${status}`;\n            this.#fail(new AudioApiError(\n                `audio/transcriptions/stream: HTTP ${status}${res?.statusMessage ? ` ${res.statusMessage}` : \"\"}`,\n                status,\n                code,\n            ));\n            ws.terminate?.();\n        });\n        ws.on(\"error\", (err) => {\n            this.#fail(new AudioApiError(\n                `Transcription socket failed: ${err?.message ?? err}`,\n                0,\n                \"NETWORK_ERROR\",\n            ));\n        });\n        ws.on(\"close\", (code) => {\n            // A dirty close (1006/1011/…) with no error frame before it is a\n            // failure; a clean 1000 without `done` is just an early hangup.\n            if (!this.#finished && !this.#closedByUser && code !== 1000) {\n                this.#fail(new AudioApiError(\n                    `The transcription socket closed with code ${code}`,\n                    0,\n                    \"NETWORK_ERROR\",\n                ), /* emitClose */ false);\n            }\n            this.#settleClose(code);\n        });\n    }\n\n    #onFrame(text: string): void {\n        if (this.#finished) return;\n        let frame: StreamFrame;\n        try {\n            frame = JSON.parse(text) as StreamFrame;\n        } catch {\n            return; // not ours — ignore\n        }\n        switch (frame.type) {\n            case \"ready\": {\n                if (frame.request_id) this.#requestId = frame.request_id;\n                this.#isReady = true;\n                this.#flush();\n                this.#resolveReady();\n                this.emit(\"ready\", {\n                    requestId: this.#requestId,\n                    model: frame.model ?? \"\",\n                    sampleRate: typeof frame.sample_rate === \"number\" ? frame.sample_rate : 16000,\n                });\n                break;\n            }\n            case \"partial\": {\n                const t = frame.text ?? \"\";\n                this.#items.push({ type: \"partial\", text: t });\n                this.emit(\"partial\", t);\n                break;\n            }\n            case \"final\": {\n                const seg: StreamFinal = { text: frame.text ?? \"\" };\n                if (typeof frame.start === \"number\") seg.start = frame.start;\n                if (typeof frame.end === \"number\") seg.end = frame.end;\n                if (typeof frame.language === \"string\") seg.language = frame.language;\n                const sp = speakerLabel(frame.speaker);\n                if (sp !== undefined) seg.speaker = sp;\n                if (Array.isArray(frame.words)) seg.words = frame.words.map(mapWord);\n                this.#items.push({ type: \"final\", segment: seg });\n                this.emit(\"final\", seg);\n                break;\n            }\n            case \"done\": {\n                if (frame.request_id && !this.#requestId) this.#requestId = frame.request_id;\n                this.#finished = true;\n                this.#doneInfo = {\n                    audioSeconds: typeof frame.audio_seconds === \"number\" ? frame.audio_seconds : 0,\n                    billedMinutes: typeof frame.billed_minutes === \"number\" ? frame.billed_minutes : 0,\n                };\n                this.#items.close();\n                this.#resolveEnd?.(this.#doneInfo);\n                this.emit(\"done\", this.#doneInfo);\n                break;\n            }\n            case \"error\": {\n                this.#fail(new AudioApiError(\n                    frame.error ?? \"audio/transcriptions/stream: the server refused\",\n                    200,\n                    frame.code ?? \"UPSTREAM_ERROR\",\n                ));\n                break;\n            }\n            default:\n                break;\n        }\n    }\n\n    /** One failure path: remember it, reject the waiters, emit once. */\n    #fail(err: AudioApiError, emitClose = true): void {\n        if (this.#finished) return;\n        this.#finished = true;\n        this.#error = err;\n        this.#pending = [];\n        this.#rejectReady(err);\n        this.#rejectEnd?.(err);\n        this.#items.fail(err);\n        this.emit(\"error\", err);\n        // A socket that never opened emits no `close` of its own.\n        if (emitClose && !this.#ws) this.#settleClose(0);\n    }\n\n    /** The last word: the iterator ends, whoever still waits on ready/end is told, `close` fires once. */\n    #closeEmitted = false;\n    #settleClose(code: number): void {\n        if (this.#closeEmitted) return;\n        this.#closeEmitted = true;\n        if (!this.#finished) {\n            // Closed before `done` and without an error — by us or by the server.\n            this.#finished = true;\n            this.#pending = [];\n            this.#items.close();\n            const err = new AudioApiError(\n                this.#closedByUser\n                    ? \"The transcription stream was closed before done\"\n                    : \"The server closed the transcription stream before done\",\n                0,\n                \"CLOSED\",\n            );\n            this.#rejectReady(err);\n            this.#rejectEnd?.(err);\n        }\n        this.emit(\"close\", code);\n    }\n\n    #flush(): void {\n        const ws = this.#ws;\n        if (!ws || !this.#isReady) return;\n        for (const item of this.#pending.splice(0)) ws.send(item);\n    }\n\n    #send(item: Uint8Array | string): void {\n        if (this.#finished) return;\n        this.#pending.push(item);\n        this.#flush();\n    }\n\n    // ── public ───────────────────────────────────────────────────────────\n\n    write(chunk: Uint8Array | ArrayBuffer): void {\n        this.#send(toBytes(chunk));\n    }\n\n    finalize(): void {\n        this.#send(JSON.stringify({ type: \"finalize\" }));\n    }\n\n    end(): Promise<StreamDone> {\n        if (this.#endPromise) return this.#endPromise;\n        this.#endPromise = new Promise<StreamDone>((resolve, reject) => {\n            this.#resolveEnd = resolve;\n            this.#rejectEnd = reject;\n        });\n        this.#endPromise.catch(() => {});\n        if (this.#doneInfo) {\n            this.#resolveEnd!(this.#doneInfo);\n        } else if (this.#error) {\n            this.#rejectEnd!(this.#error);\n        } else if (this.#finished) {\n            this.#rejectEnd!(new AudioApiError(\"The transcription stream is already closed\", 0, \"CLOSED\"));\n        } else {\n            this.#send(JSON.stringify({ type: \"stop\" }));\n        }\n        return this.#endPromise;\n    }\n\n    close(): void {\n        if (this.#closedByUser) return;\n        this.#closedByUser = true;\n        this.#pending = [];\n        const ws = this.#ws;\n        // CONNECTING (0): closing now would abort the handshake with an error;\n        // the `open` handler closes it cleanly instead. Not created yet: #open()\n        // settles it. Otherwise close 1000 and let the close handler emit.\n        if (ws && ws.readyState !== 0) {\n            try { ws.close(1000); } catch { /* already closing */ }\n        }\n    }\n\n    [Symbol.asyncIterator](): AsyncIterator<TranscribeStreamItem> {\n        return this.#items[Symbol.asyncIterator]();\n    }\n}\n\n/**\n * `WS /v1/audio/transcriptions/stream` — live transcription of PCM you write.\n *\n * Opens the socket immediately; `write()` before `ready` is buffered and sent\n * in order once the server is listening. `end()` tells the server there is no\n * more audio and resolves with the billing on `done`; `close()` hangs up now.\n * Node only (needs `ws` for header auth).\n */\nexport function transcribeStream(opts: TranscribeStreamOptions & TranscribeApiOptions): TranscribeStream {\n    if (!opts.apiKey) {\n        throw new AudioApiError(\"transcribeStream() needs an apiKey\", 0, \"MISSING_KEY\");\n    }\n    return new TranscribeStreamImpl(streamUrl(opts.apiUrl, opts), opts.apiKey);\n}\n","/**\n * Audio API — standalone text-to-speech, no agent and no call.\n *\n * `POST {apiUrl}/v1/audio/speech` synthesises one utterance and streams the\n * bytes back as they are produced. This client resolves as soon as the\n * response headers arrive, so a desktop app can start playback on the first\n * chunk; the body is never buffered unless the caller asks for it\n * (`arrayBuffer()` / `toFile()`).\n *\n * Two wire modes, one result shape:\n *   - `timestamps: false` (default) → a chunked binary body (`audio/pcm`,\n *     `audio/wav` or `audio/mpeg`) that flows straight into `result.audio`.\n *   - `timestamps: true` → `text/event-stream`; audio frames (base64) are\n *     decoded into `result.audio`, word frames reach `result.words`, the done\n *     frame resolves `result.done`, and an error frame rejects everything.\n *\n * Runs on Node ≥ 18 and in Electron main; `toFile` is the only Node-specific\n * bit and loads `node:fs` lazily so browser bundles are untouched.\n */\n\nimport { PinecallError } from \"../kernel/errors.js\";\nimport { createSSEParser } from \"../sse/parse.js\";\nimport { apiFetch } from \"./http.js\";\nimport { mapVoice, type Voice } from \"./voices.js\";\n\n// ── Types ────────────────────────────────────────────────────────────────\n\nexport type SpeechFormat = \"pcm\" | \"wav\" | \"mp3\";\n\nexport interface SpeechOptions {\n    /** Text to speak — 1..5000 characters. */\n    input: string;\n    /** `\"provider/alias\"` (e.g. `\"elevenlabs/sarah\"`) or a raw provider voice id. */\n    voice: string;\n    /** `\"provider/model\"`, `\"provider/auto\"`, or omitted (auto by language). */\n    model?: string;\n    /** ISO-639-1 language code, e.g. `\"es\"`. */\n    language?: string;\n    /** `\"pcm\"` (default) | `\"wav\"` | `\"mp3\"`. pcm/wav are s16le mono. */\n    format?: SpeechFormat;\n    /** 16000 (default) | 24000 — pcm/wav sample rate. */\n    sampleRate?: 16000 | 24000;\n    speed?: number;\n    /** Request word timestamps (switches the wire to SSE). */\n    timestamps?: boolean;\n    /** Abort the request — and the synthesis behind it — from outside. */\n    signal?: AbortSignal;\n}\n\nexport interface SpeechWord {\n    word: string;\n    /** Seconds from the start of the audio. */\n    start: number;\n    end: number;\n}\n\nexport interface SpeechDone {\n    /** Characters billed for this request. */\n    characters: number;\n    /** Audio duration in milliseconds. */\n    audioMs: number;\n}\n\nexport interface SpeechResult {\n    requestId: string;\n    format: SpeechFormat;\n    sampleRate: number;\n    channels: 1;\n    bitDepth: 16;\n    /** Raw audio bytes as they arrive (base64-decoded in SSE mode). Never buffered. */\n    audio: ReadableStream<Uint8Array>;\n    /** Word timestamps — empty when `timestamps` is off or the provider has none. */\n    words: AsyncIterable<SpeechWord>;\n    /** Resolves when synthesis finishes; rejects on a mid-stream error or cancel. */\n    done: Promise<SpeechDone>;\n    /** Abort the request; the server cancels synthesis. */\n    cancel(): void;\n    /** Drain `audio` into one buffer. */\n    arrayBuffer(): Promise<ArrayBuffer>;\n    /** Drain `audio` into a file. Node only — `node:fs` is imported lazily. */\n    toFile(path: string): Promise<void>;\n}\n\nexport interface SpeechApiOptions {\n    apiKey: string;\n    /** Voice server base, e.g. https://voice.pinecall.io (the default). */\n    apiUrl?: string;\n}\n\nexport interface FetchAudioVoicesOptions {\n    provider?: string;\n    language?: string;\n    apiKey?: string;\n    apiUrl?: string;\n}\n\n// ── Errors ───────────────────────────────────────────────────────────────\n\n/**\n * A refusal from the audio endpoint — before streaming (HTTP status + the\n * server's `code`: BAD_VOICE, INSUFFICIENT_CREDITS, RATE_LIMITED, …) or\n * mid-stream (status 200, the `code` of the error frame). `status` is 0 when\n * the server could not be reached at all.\n */\nexport class AudioApiError extends PinecallError {\n    declare code: string;\n    constructor(message: string, public status: number, code: string) {\n        super(message, code);\n        this.name = \"AudioApiError\";\n    }\n}\n\n// ── Wire frames (SSE mode) ───────────────────────────────────────────────\n\ntype SpeechFrame =\n    | { type: \"start\"; request_id?: string; format?: string; sample_rate?: number }\n    | { type: \"audio\"; data: string }\n    | { type: \"word\"; word: string; start: number; end: number }\n    | { type: \"done\"; characters?: number; audio_ms?: number }\n    | { type: \"error\"; code?: string; error?: string };\n\n// ── Helpers ──────────────────────────────────────────────────────────────\n\n/** Minimal async queue: push from the network side, iterate from the consumer side. */\nexport class AsyncQueue<T> implements AsyncIterable<T> {\n    #items: T[] = [];\n    #waiters: Array<{ resolve: (r: IteratorResult<T>) => void; reject: (e: unknown) => void }> = [];\n    #closed = false;\n    #error: unknown = undefined;\n\n    push(item: T): void {\n        if (this.#closed) return;\n        const w = this.#waiters.shift();\n        if (w) w.resolve({ value: item, done: false });\n        else this.#items.push(item);\n    }\n\n    close(): void {\n        if (this.#closed) return;\n        this.#closed = true;\n        for (const w of this.#waiters.splice(0)) w.resolve({ value: undefined as T, done: true });\n    }\n\n    fail(err: unknown): void {\n        if (this.#closed) return;\n        this.#closed = true;\n        this.#error = err;\n        for (const w of this.#waiters.splice(0)) w.reject(err);\n    }\n\n    [Symbol.asyncIterator](): AsyncIterator<T> {\n        return {\n            next: () => {\n                if (this.#items.length > 0) {\n                    return Promise.resolve({ value: this.#items.shift() as T, done: false });\n                }\n                if (this.#closed) {\n                    return this.#error !== undefined\n                        ? Promise.reject(this.#error)\n                        : Promise.resolve({ value: undefined as T, done: true });\n                }\n                return new Promise((resolve, reject) => this.#waiters.push({ resolve, reject }));\n            },\n            return: () => {\n                this.#closed = true;\n                this.#items = [];\n                return Promise.resolve({ value: undefined as T, done: true });\n            },\n        };\n    }\n}\n\nfunction decodeBase64(b64: string): Uint8Array {\n    if (typeof Buffer !== \"undefined\") {\n        const buf = Buffer.from(b64, \"base64\");\n        return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);\n    }\n    const bin = atob(b64);\n    const out = new Uint8Array(bin.length);\n    for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);\n    return out;\n}\n\nfunction headerInt(res: Response, name: string): number | undefined {\n    const raw = res.headers.get(name);\n    if (raw === null || raw === \"\") return undefined;\n    const n = Number(raw);\n    return Number.isFinite(n) ? n : undefined;\n}\n\nfunction formatFromContentType(ct: string | null, requested: SpeechFormat): SpeechFormat {\n    const t = (ct ?? \"\").toLowerCase();\n    if (t.includes(\"audio/wav\") || t.includes(\"audio/x-wav\") || t.includes(\"audio/wave\")) return \"wav\";\n    if (t.includes(\"audio/mpeg\") || t.includes(\"audio/mp3\")) return \"mp3\";\n    if (t.includes(\"audio/pcm\") || t.includes(\"audio/l16\")) return \"pcm\";\n    return requested;\n}\n\n/** Byte count → milliseconds for s16le audio; unknown (mp3) → 0. */\nfunction bytesToMs(bytes: number, format: SpeechFormat, sampleRate: number, channels: number, bitDepth: number): number {\n    if (format === \"mp3\") return 0;\n    const payload = format === \"wav\" ? Math.max(0, bytes - 44) : bytes;\n    const bytesPerSec = sampleRate * channels * (bitDepth / 8);\n    return bytesPerSec > 0 ? Math.round((payload / bytesPerSec) * 1000) : 0;\n}\n\nfunction abortError(): Error {\n    const err = new Error(\"The speech request was aborted\");\n    err.name = \"AbortError\";\n    return err;\n}\n\nexport async function readError(res: Response, endpoint = \"audio/speech\"): Promise<AudioApiError> {\n    let message = `${endpoint}: HTTP ${res.status}${res.statusText ? ` ${res.statusText}` : \"\"}`;\n    let code = `HTTP_${res.status}`;\n    const text = await res.text().catch(() => \"\");\n    if (text) {\n        try {\n            const body = JSON.parse(text) as { error?: string; code?: string; message?: string };\n            if (typeof body.code === \"string\" && body.code) code = body.code;\n            const msg = body.error ?? body.message;\n            if (typeof msg === \"string\" && msg) message = msg;\n        } catch {\n            message = `${message}: ${text.slice(0, 200)}`;\n        }\n    }\n    return new AudioApiError(message, res.status, code);\n}\n\n// ── speech() ─────────────────────────────────────────────────────────────\n\nexport async function speech(opts: SpeechOptions & SpeechApiOptions): Promise<SpeechResult> {\n    if (!opts.apiKey) {\n        throw new AudioApiError(\"speech() needs an apiKey\", 0, \"MISSING_KEY\");\n    }\n\n    // One controller for cancel() and the caller's own signal.\n    const ac = new AbortController();\n    if (opts.signal) {\n        if (opts.signal.aborted) ac.abort(opts.signal.reason);\n        else opts.signal.addEventListener(\"abort\", () => ac.abort(opts.signal?.reason), { once: true });\n    }\n\n    const requested: SpeechFormat = opts.format ?? \"pcm\";\n    const body: Record<string, unknown> = { input: opts.input, voice: opts.voice };\n    if (opts.model !== undefined) body.model = opts.model;\n    if (opts.language !== undefined) body.language = opts.language;\n    if (opts.format !== undefined) body.response_format = opts.format;\n    if (opts.sampleRate !== undefined) body.sample_rate = opts.sampleRate;\n    if (opts.speed !== undefined) body.speed = opts.speed;\n    if (opts.timestamps !== undefined) body.timestamps = opts.timestamps;\n\n    let res: Response;\n    try {\n        res = await apiFetch(\"/v1/audio/speech\", {\n            apiKey: opts.apiKey,\n            apiUrl: opts.apiUrl,\n            body,\n            signal: ac.signal,\n            headers: { Accept: opts.timestamps ? \"text/event-stream\" : \"audio/*\" },\n        });\n    } catch (err) {\n        if ((err as Error)?.name === \"AbortError\") throw err;\n        throw new AudioApiError(\n            `Cannot reach the voice server: ${(err as Error)?.message ?? err}`,\n            0,\n            \"NETWORK_ERROR\",\n        );\n    }\n\n    if (!res.ok) throw await readError(res);\n    if (!res.body) {\n        throw new AudioApiError(\"audio/speech: the response has no body to stream\", 0, \"NO_BODY\");\n    }\n\n    const contentType = res.headers.get(\"content-type\");\n    const isSSE = (contentType ?? \"\").toLowerCase().includes(\"text/event-stream\");\n\n    const meta = {\n        requestId: res.headers.get(\"x-pinecall-request-id\") ?? \"\",\n        format: formatFromContentType(contentType, requested),\n        sampleRate: headerInt(res, \"x-sample-rate\") ?? opts.sampleRate ?? 16000,\n        channels: 1 as const,\n        bitDepth: 16 as const,\n    };\n    const headerChars = headerInt(res, \"x-pinecall-characters\");\n    const headerAudioMs = headerInt(res, \"x-pinecall-audio-ms\");\n\n    let resolveDone!: (d: SpeechDone) => void;\n    let rejectDone!: (e: unknown) => void;\n    const done = new Promise<SpeechDone>((resolve, reject) => {\n        resolveDone = resolve;\n        rejectDone = reject;\n    });\n    // A consumer who never awaits `done` must not crash the process on cancel.\n    done.catch(() => {});\n\n    const words = new AsyncQueue<SpeechWord>();\n    const reader = res.body.getReader();\n    let audio: ReadableStream<Uint8Array>;\n\n    if (!isSSE) {\n        // ── Binary mode: pull-through, so backpressure reaches the socket ──\n        words.close();\n        let bytes = 0;\n        audio = new ReadableStream<Uint8Array>({\n            async pull(controller) {\n                let r: ReadableStreamReadResult<Uint8Array>;\n                try {\n                    r = await reader.read();\n                } catch (err) {\n                    const e = ac.signal.aborted ? abortError() : err;\n                    rejectDone(e);\n                    controller.error(e);\n                    return;\n                }\n                if (r.done) {\n                    controller.close();\n                    resolveDone({\n                        characters: headerChars ?? opts.input.length,\n                        audioMs: headerAudioMs ?? bytesToMs(bytes, meta.format, meta.sampleRate, meta.channels, meta.bitDepth),\n                    });\n                    return;\n                }\n                bytes += r.value.byteLength;\n                controller.enqueue(r.value);\n            },\n            cancel() {\n                ac.abort();\n                rejectDone(abortError());\n            },\n        });\n    } else {\n        // ── SSE mode: pump eagerly — words must flow even if audio is unread ──\n        let audioCtrl!: ReadableStreamDefaultController<Uint8Array>;\n        audio = new ReadableStream<Uint8Array>({\n            start(controller) { audioCtrl = controller; },\n            cancel() { ac.abort(); },\n        });\n        let audioClosed = false;\n        let bytes = 0;\n        let finished = false;\n        let doneFrame: SpeechDone | undefined;\n\n        const closeAudio = () => {\n            if (audioClosed) return;\n            audioClosed = true;\n            try { audioCtrl.close(); } catch { /* already closed */ }\n        };\n        const failAll = (err: unknown) => {\n            if (finished) return;\n            finished = true;\n            rejectDone(err);\n            words.fail(err);\n            if (!audioClosed) {\n                audioClosed = true;\n                try { audioCtrl.error(err); } catch { /* already closed */ }\n            }\n        };\n        const finishAll = () => {\n            if (finished) return;\n            finished = true;\n            closeAudio();\n            words.close();\n            resolveDone(doneFrame ?? {\n                characters: headerChars ?? opts.input.length,\n                audioMs: headerAudioMs ?? bytesToMs(bytes, meta.format, meta.sampleRate, meta.channels, meta.bitDepth),\n            });\n        };\n\n        const parser = createSSEParser(({ data }) => {\n            if (finished) return;\n            if (data.trim() === \"[DONE]\") { finishAll(); return; }\n            let frame: SpeechFrame;\n            try {\n                frame = JSON.parse(data) as SpeechFrame;\n            } catch {\n                return; // not ours — ignore\n            }\n            switch (frame.type) {\n                case \"start\":\n                    if (frame.request_id) meta.requestId = frame.request_id;\n                    if (frame.format === \"pcm\" || frame.format === \"wav\" || frame.format === \"mp3\") meta.format = frame.format;\n                    if (typeof frame.sample_rate === \"number\") meta.sampleRate = frame.sample_rate;\n                    break;\n                case \"audio\": {\n                    if (audioClosed) break;\n                    const chunk = decodeBase64(frame.data ?? \"\");\n                    bytes += chunk.byteLength;\n                    audioCtrl.enqueue(chunk);\n                    break;\n                }\n                case \"word\":\n                    words.push({ word: frame.word, start: frame.start, end: frame.end });\n                    break;\n                case \"done\":\n                    doneFrame = {\n                        characters: frame.characters ?? headerChars ?? opts.input.length,\n                        audioMs: frame.audio_ms ?? bytesToMs(bytes, meta.format, meta.sampleRate, meta.channels, meta.bitDepth),\n                    };\n                    resolveDone(doneFrame);\n                    break;\n                case \"error\":\n                    failAll(new AudioApiError(\n                        frame.error ?? \"audio/speech: synthesis failed\",\n                        200,\n                        frame.code ?? \"UPSTREAM_ERROR\",\n                    ));\n                    break;\n                default:\n                    break;\n            }\n        });\n\n        void (async () => {\n            try {\n                for (;;) {\n                    const r = await reader.read();\n                    if (r.done) break;\n                    parser.feed(r.value);\n                }\n                parser.end();\n                // Stream ended without [DONE]: treat a seen done frame as the end,\n                // otherwise close what we have.\n                finishAll();\n            } catch (err) {\n                failAll(ac.signal.aborted ? abortError() : err);\n            }\n        })();\n    }\n\n    const result: SpeechResult = {\n        get requestId() { return meta.requestId; },\n        get format() { return meta.format; },\n        get sampleRate() { return meta.sampleRate; },\n        channels: 1,\n        bitDepth: 16,\n        audio,\n        words,\n        done,\n        cancel() {\n            ac.abort();\n        },\n        async arrayBuffer() {\n            const chunks: Uint8Array[] = [];\n            let total = 0;\n            const r = audio.getReader();\n            for (;;) {\n                const { done: d, value } = await r.read();\n                if (d) break;\n                chunks.push(value);\n                total += value.byteLength;\n            }\n            const out = new Uint8Array(total);\n            let off = 0;\n            for (const c of chunks) { out.set(c, off); off += c.byteLength; }\n            return out.buffer;\n        },\n        async toFile(path: string) {\n            // Variable specifier: browser bundlers leave it alone.\n            const fsSpecifier = \"node:fs/promises\";\n            const fs = (await import(/* @vite-ignore */ fsSpecifier)) as typeof import(\"node:fs/promises\");\n            const handle = await fs.open(path, \"w\");\n            const r = audio.getReader();\n            try {\n                for (;;) {\n                    const { done: d, value } = await r.read();\n                    if (d) break;\n                    await handle.write(value);\n                }\n            } finally {\n                await handle.close();\n            }\n        },\n    };\n    return result;\n}\n\n// ── voices ───────────────────────────────────────────────────────────────\n\n/** `GET /v1/audio/voices` — the voices `speech()` accepts, optionally filtered. */\nexport async function fetchAudioVoices(opts: FetchAudioVoicesOptions = {}): Promise<Voice[]> {\n    const query: Record<string, string> = {};\n    if (opts.provider) query.provider = opts.provider;\n    if (opts.language) query.language = opts.language;\n\n    let res: Response;\n    try {\n        res = await apiFetch(\"/v1/audio/voices\", { apiKey: opts.apiKey, apiUrl: opts.apiUrl, query });\n    } catch (err) {\n        throw new AudioApiError(\n            `Cannot reach the voice server: ${(err as Error)?.message ?? err}`,\n            0,\n            \"NETWORK_ERROR\",\n        );\n    }\n    if (!res.ok) throw await readError(res);\n\n    const data = (await res.json().catch(() => ({}))) as { success?: boolean; voices?: unknown[] };\n    if (!data.success || !Array.isArray(data.voices)) return [];\n    return (data.voices as Record<string, unknown>[]).map(mapVoice(opts.provider ?? \"elevenlabs\"));\n}\n\n// ── speech-to-text ───────────────────────────────────────────────────────\n// Lives in audio-stt.ts; re-exported here so `import { transcribe } from\n// \"@pinecall/sdk\"` and `./api/audio.js` both work.\n\nexport { transcribe, transcribeStream } from \"./audio-stt.js\";\nexport type {\n    TranscriptionModel,\n    TranscribeInput,\n    TranscribeOptions,\n    TranscribeApiOptions,\n    TranscriptWord,\n    TranscriptSegment,\n    Transcription,\n    StreamModel,\n    TranscribeStreamOptions,\n    StreamFinal,\n    StreamReady,\n    StreamDone,\n    TranscribeStreamEvents,\n    TranscribeStreamItem,\n    TranscribeStream,\n} from \"./audio-stt.js\";\n","/**\n * Pinecall — main client class. The orchestrator.\n *\n * Composes Transport, Dispatcher, Reconnector, Logger, IdResolver.\n * Owns the agent registry and WebSocket lifecycle.\n *\n * Public API is identical to src.bkp/client.ts.\n */\n\nimport { TypedEventBus } from \"./kernel/event-bus.js\";\nimport { PinecallError, AgentConflictError } from \"./kernel/errors.js\";\nimport { noopLogger, fileLogger } from \"./kernel/logger.js\";\nimport { planConflictRetry, CONFLICT_RETRY_BUDGET_MS } from \"./kernel/backoff.js\";\nimport type { Logger } from \"./kernel/logger.js\";\nimport { WebSocketTransport } from \"./transport/websocket.js\";\nimport { Reconnector } from \"./transport/reconnect.js\";\nimport type { Transport } from \"./transport/transport.js\";\nimport { StandardAgentIdResolver } from \"./protocol/id-resolver.js\";\nimport { buildShortcutPayload } from \"./protocol/shortcuts.js\";\nimport { Dispatcher } from \"./dispatch/dispatcher.js\";\nimport { forwardAgentEvents } from \"./dispatch/proxy.js\";\nimport type { WireEvent } from \"./protocol/wire.js\";\nimport type { DispatchContext } from \"./dispatch/handler.js\";\nimport type { RegistrationCoordinator } from \"./dispatch/registration.js\";\n\n\n// Handlers\nimport { ConnectionHandler } from \"./dispatch/handlers/connection.js\";\nimport { ErrorHandler } from \"./dispatch/handlers/error.js\";\nimport { ChannelHandler } from \"./dispatch/handlers/channel.js\";\nimport { LifecycleHandler } from \"./dispatch/handlers/lifecycle.js\";\nimport { SpeechHandler } from \"./dispatch/handlers/speech.js\";\nimport { TurnHandler } from \"./dispatch/handlers/turn.js\";\nimport { BotHandler } from \"./dispatch/handlers/bot.js\";\nimport { ToolHandler } from \"./dispatch/handlers/tool.js\";\nimport { SkillHandler } from \"./dispatch/handlers/skill.js\";\nimport { SessionHandler } from \"./dispatch/handlers/session.js\";\nimport { ChatHandler } from \"./dispatch/handlers/chat.js\";\nimport { WhatsAppHandler } from \"./dispatch/handlers/whatsapp.js\";\nimport { HistoryHandler } from \"./dispatch/handlers/history.js\";\nimport { SystemHandler } from \"./dispatch/handlers/system.js\";\nimport { FallbackHandler } from \"./dispatch/handlers/fallback.js\";\nimport { PreparingHandler } from \"./dispatch/handlers/preparing.js\";\nimport { MemoryHandler } from \"./dispatch/handlers/memory.js\";\nimport { LineHandler } from \"./dispatch/handlers/line.js\";\n\n// Domain\nimport { Agent } from \"./domain/agent.js\";\nimport { PhoneLine, prepareLine } from \"./domain/line.js\";\nimport type { LineOptions } from \"./domain/line.js\";\nimport type { AgentConfig, ChannelConfig } from \"./config/agent.js\";\nimport type { TokenResponse } from \"./api/tokens.js\";\nimport type { Turn } from \"./domain/turn.js\";\nimport type { Call } from \"./domain/call.js\";\n\n// Call Log observation\nimport { observe as observeLog } from \"./observe.js\";\nimport type { ObserveOptions, Observation } from \"./observe.js\";\n\n// SSE\nimport { createMultiAgentStream } from \"./sse/stream.js\";\nimport type { StreamOptions } from \"./sse/stream.js\";\nimport type { ServerResponse } from \"node:http\";\n\n// REST API\nimport { createToken as createTokenApi } from \"./api/tokens.js\";\nimport type { TokenScopeOptions } from \"./api/tokens.js\";\nimport { speech as speechApi, fetchAudioVoices, transcribe as transcribeApi, transcribeStream as transcribeStreamApi } from \"./api/audio.js\";\nimport type {\n    SpeechOptions,\n    SpeechResult,\n    FetchAudioVoicesOptions,\n    TranscribeInput,\n    TranscribeOptions,\n    Transcription,\n    TranscribeStreamOptions,\n    TranscribeStream,\n} from \"./api/audio.js\";\nimport type { Voice } from \"./api/voices.js\";\n\n/**\n * `pc.audio` — standalone speech, bound to this client's key and URL. No\n * agent, no call: `speech()` streams one utterance, `voices()` lists what it\n * accepts, `transcribe()` turns a file into text, `transcribeStream()` turns\n * live PCM into partial/final segments. See `src/api/audio.ts` and\n * `src/api/audio-stt.ts` for the wire contracts.\n */\nexport interface AudioNamespace {\n    /** Synthesise `input` with `voice`; resolves on headers, audio streams. */\n    speech(opts: SpeechOptions): Promise<SpeechResult>;\n    /** Voices `speech()` accepts, optionally filtered by provider/language. */\n    voices(opts?: Omit<FetchAudioVoicesOptions, \"apiKey\" | \"apiUrl\">): Promise<Voice[]>;\n    /** Transcribe one file (bytes, Blob, or a Node path). */\n    transcribe(input: TranscribeInput, opts?: TranscribeOptions): Promise<Transcription>;\n    /** Open a live transcription socket; write PCM, read partial/final. Node only. */\n    transcribeStream(opts?: TranscribeStreamOptions): TranscribeStream;\n}\n\n// ─── Types ───────────────────────────────────────────────────────────────\n\nexport interface PinecallOptions {\n    /** API key. Falls back to PINECALL_API_KEY env var if not provided. */\n    apiKey?: string;\n    /** Server URL. Default: wss://voice.pinecall.io */\n    apiUrl?: string;\n    /** Auto-reconnect on disconnect. Default: true. */\n    autoReconnect?: boolean;\n    /** Prompts directory for setPromptFile. Default: \"prompts\". */\n    promptsDir?: string;\n}\n\nexport interface PinecallEvents {\n    [key: string]: (...args: any[]) => void;\n    connected: () => void;\n    disconnected: (reason: string) => void;\n    reconnecting: (attempt: number, delay: number) => void;\n    error: (err: Error) => void;\n    \"call.started\": (call: Call) => void;\n    \"call.ended\": (call: Call, reason: string) => void;\n\n    // Proxied events (from Agent → Pinecall)\n    \"speech.started\": (...args: any[]) => void;\n    \"speech.ended\": (...args: any[]) => void;\n    \"user.speaking\": (...args: any[]) => void;\n    \"user.message\": (...args: any[]) => void;\n    \"eager.turn\": (turn: Turn, call: Call) => void;\n    \"turn.pause\": (...args: any[]) => void;\n    \"turn.end\": (turn: Turn, call: Call) => void;\n    \"turn.resumed\": (...args: any[]) => void;\n    \"turn.continued\": (...args: any[]) => void;\n    \"bot.speaking\": (...args: any[]) => void;\n    \"bot.word\": (...args: any[]) => void;\n    \"bot.finished\": (...args: any[]) => void;\n    \"bot.interrupted\": (...args: any[]) => void;\n    \"message.confirmed\": (...args: any[]) => void;\n    \"reply.rejected\": (...args: any[]) => void;\n    \"audio.metrics\": (...args: any[]) => void;\n    \"llm.toolCall\": (...args: any[]) => void;\n    \"session.timeout\": (...args: any[]) => void;\n}\n\n// The error types live in kernel/errors.ts so a dispatch handler can build one\n// without importing this module (a handler importing its own orchestrator is a\n// cycle waiting to happen). Re-exported here so both\n// `import { AgentConflictError } from \"@pinecall/sdk\"` and\n// `from \"./client.js\"` keep working exactly as before.\nexport { PinecallError, AgentConflictError, ServerAtCapacityError } from \"./kernel/errors.js\";\n\n/**\n * How long `createToken` waits for a locally-owned agent's `agent.created`\n * before failing with AGENT_NOT_REGISTERED. Mirrors the connect() timeout.\n */\nconst REGISTRATION_WAIT_MS = 10_000;\n\n// ─── Pinecall ────────────────────────────────────────────────────────────\n\nexport class Pinecall extends TypedEventBus<PinecallEvents> {\n    readonly #apiKey: string;\n    readonly #apiUrl: string;\n    readonly #wsUrl: string;\n    readonly #autoReconnect: boolean;\n    readonly #promptsDir: string;\n\n    /** Standalone TTS/STT — `pc.audio.speech()` / `voices()` / `transcribe()` / `transcribeStream()`. */\n    readonly audio: AudioNamespace = {\n        speech: (opts) => speechApi({ ...opts, apiKey: this.#apiKey, apiUrl: this.#apiUrl }),\n        voices: (opts = {}) => fetchAudioVoices({ ...opts, apiKey: this.#apiKey, apiUrl: this.#apiUrl }),\n        transcribe: (input, opts = {}) => transcribeApi(input, { ...opts, apiKey: this.#apiKey, apiUrl: this.#apiUrl }),\n        transcribeStream: (opts = {}) => transcribeStreamApi({ ...opts, apiKey: this.#apiKey, apiUrl: this.#apiUrl }),\n    };\n\n    readonly #agents = new Map<string, Agent>();\n    /** Phone lines, by number. Kept apart from #agents: a line is not an agent. */\n    readonly #lines = new Map<string, PhoneLine>();\n    readonly #reconnector: Reconnector;\n    readonly #resolver: StandardAgentIdResolver;\n    readonly #dispatcher: Dispatcher;\n    readonly #logger: Logger;\n    readonly #waHandler: WhatsAppHandler;\n    /**\n     * The registration state machine, handed to dispatch as a capability.\n     *\n     * Built once — the three methods below are the whole contract dispatch has\n     * with this class, and stating it as an object (instead of a bag of\n     * optional `_` methods on the context) is what lets handlers stop guessing\n     * whether a hook is wired.\n     */\n    readonly #registration: RegistrationCoordinator = {\n        scheduleRetry: (id, hint) => this.#scheduleRegisterRetry(id, hint),\n        fail: (id) => this.#failRegistration(id, \"server_fatal\"),\n        clear: (id) => this.#clearRegisterRetry(id),\n    };\n    #runnerHook: ((agent: Agent) => void) | null = null;\n\n    #transport: Transport | null = null;\n    #pingInterval: ReturnType<typeof setInterval> | null = null;\n    /** Registration-conflict retry state: agentId → attempt count + pending timer. */\n    readonly #registerRetries = new Map<string, { attempt: number; timer: ReturnType<typeof setTimeout> | null; holderAlive: boolean; startedAt: number }>();\n    #intentionalClose = false;\n    #connected = false;\n    #connectResolve: (() => void) | null = null;\n    #connectReject: ((err: Error) => void) | null = null;\n    #connectPromise: Promise<void> | null = null;\n\n    constructor(opts: PinecallOptions = {}) {\n        super();\n        this.#apiKey = opts.apiKey ?? this.#getEnv(\"PINECALL_API_KEY\") ?? \"\";\n\n        // Normalize URLs\n        const rawUrl = opts.apiUrl ?? \"wss://voice.pinecall.io\";\n        this.#apiUrl = rawUrl.replace(/^ws/, \"http\");\n        this.#wsUrl = rawUrl.replace(/^http/, \"ws\");\n\n        this.#autoReconnect = opts.autoReconnect !== false;\n        this.#promptsDir = opts.promptsDir ?? \"prompts\";\n\n        this.#reconnector = new Reconnector();\n        this.#resolver = new StandardAgentIdResolver();\n\n        const logPath = this.#getEnv(\"PINECALL_LOG\");\n        this.#logger = logPath ? fileLogger(logPath) : noopLogger;\n\n        // Build dispatcher with all handlers in priority order\n        this.#waHandler = new WhatsAppHandler();\n        this.#dispatcher = new Dispatcher([\n            new SystemHandler(),\n            new ConnectionHandler(),\n            new ErrorHandler(),\n            new ChannelHandler(),\n            new ChatHandler(),\n            new LifecycleHandler(),\n            new LineHandler(),\n            new SpeechHandler(),\n            new TurnHandler(),\n            new BotHandler(),\n            new ToolHandler(),\n            new SkillHandler(),\n            new PreparingHandler(),\n            new MemoryHandler(),\n            new SessionHandler(),\n            this.#waHandler,\n            new HistoryHandler(),\n            new FallbackHandler(),\n        ]);\n\n        // Auto-attach runner display for `pinecall run`\n        if (this.#getEnv(\"PINECALL_CLI_RUN\") === \"1\") {\n            import(\"./runner.js\").then((mod) => {\n                // The host is what the runner's web console needs — the agents\n                // it observes, where to mint tokens, and how to stream. The API\n                // key is NOT part of it: it never leaves this object.\n                this.#runnerHook = mod.attachRunner({\n                    agents: this.#agents,\n                    apiUrl: this.#apiUrl,\n                    createToken: (channel, agentId, metadata) => this.createToken(channel, agentId, metadata),\n                    stream: (res, opts) => this.stream(res, opts),\n                    close: () => this.disconnect(),\n                });\n                // Attach to any agents already created before import resolved\n                for (const agent of this.#agents.values()) {\n                    this.#runnerHook!(agent);\n                }\n            }).catch(() => {});\n        }\n\n        // Auto-connect on instantiation — connect() is idempotent,\n        // so existing `await pc.connect()` calls become a harmless no-op.\n        if (this.#apiKey) {\n            this.connect();\n        }\n    }\n\n    // ── Public getters ───────────────────────────────────────────────────\n\n    get connected(): boolean {\n        return this.#connected;\n    }\n\n    /** Promise that resolves when the connection is established. */\n    get ready(): Promise<void> {\n        return this.#connectPromise ?? Promise.resolve();\n    }\n\n    get agents(): ReadonlyMap<string, Agent> {\n        return this.#agents;\n    }\n\n    getAgent(id: string): Agent | undefined {\n        return this.#agents.get(id);\n    }\n\n    /** Phone lines registered on this client, by number. */\n    get lines(): ReadonlyMap<string, PhoneLine> {\n        return this.#lines;\n    }\n\n    // ── Connect / Disconnect ─────────────────────────────────────────────\n\n    async connect(): Promise<void> {\n        // Idempotent: if already connecting/connected, return the existing promise\n        if (this.#connectPromise && !this.#intentionalClose) {\n            return this.#connectPromise;\n        }\n\n        this.#connectPromise = this.#doConnect();\n        return this.#connectPromise;\n    }\n\n    async #doConnect(): Promise<void> {\n        this.#intentionalClose = false;\n\n        // Server endpoint is always /client\n        const wsUrl = this.#wsUrl.replace(/\\/+$/, \"\") + \"/client\";\n        const transport = new WebSocketTransport({ url: wsUrl });\n\n        transport.onMessage((data) => this.#onMessage(data));\n        transport.onClose((reason) => this.#onClose(reason));\n\n        await transport.open();\n        this.#transport = transport;\n\n        // Wait for the server's \"connected\" event before resolving.\n        await new Promise<void>((resolve, reject) => {\n            this.#connectResolve = resolve;\n            this.#connectReject = reject;\n\n            // Send auth\n            this.#send({ event: \"connect\", api_key: this.#apiKey });\n\n            // Timeout if server doesn't respond\n            setTimeout(() => {\n                if (!this.#connected) {\n                    this.#connectResolve = null;\n                    this.#connectReject = null;\n                    reject(new PinecallError(\"Connection timeout: no 'connected' event from server\", \"CONNECTION_TIMEOUT\"));\n                }\n            }, 10000);\n        });\n    }\n\n    async disconnect(): Promise<void> {\n        this.#intentionalClose = true;\n        this.#reconnector.cancel();\n        this.#connectPromise = null;\n\n        if (this.#pingInterval) {\n            clearInterval(this.#pingInterval);\n            this.#pingInterval = null;\n        }\n\n        this.#clearAllRegisterRetries();\n\n        // End all calls across all agents and lines\n        for (const agent of this.#agents.values()) {\n            agent._endAllCalls(\"client_disconnect\");\n        }\n        for (const line of this.#lines.values()) {\n            line._endAllCalls(\"client_disconnect\");\n        }\n\n        if (this.#transport) {\n            await this.#transport.close();\n            this.#transport = null;\n        }\n\n        this.#connected = false;\n    }\n\n    // ── Agent management ─────────────────────────────────────────────────\n\n    agent(id: string, config: AgentConfig = {}): Agent {\n        if (this.#agents.has(id)) {\n            return this.#agents.get(id)!;\n        }\n\n        // Extract channel fields before passing to Agent. `greeting` STAYS in\n        // the config when it is a string/object: it goes on the wire and the\n        // SERVER delivers it on every channel — one text, one owner. Only a\n        // FUNCTION greeting is extracted: it cannot serialize, so it keeps the\n        // legacy client-side call.say on voice events.\n        const { phoneNumber, phoneNumbers, whatsapp, ...agentConfig } = config;\n        const greeting = typeof config.greeting === \"function\" ? config.greeting : undefined;\n        if (greeting) delete (agentConfig as any).greeting;\n\n        const agent = new Agent(\n            id,\n            agentConfig,\n            (data) => this.#send(data),\n        );\n\n        agent._setClient({\n            createToken: (channel, agentId, metadata, opts) => this.createToken(channel, agentId, metadata, opts),\n            memoryApi: { apiKey: this.#apiKey, apiUrl: this.#apiUrl },\n        });\n\n        this.#agents.set(id, agent);\n\n        // Set up event forwarding: Agent → Pinecall\n        forwardAgentEvents(agent, this);\n\n        // Register phone number(s) — singular takes precedence over deprecated array\n        if (phoneNumber) {\n            if (typeof phoneNumber === \"string\") {\n                agent._addChannel(\"phone\", phoneNumber);\n            } else {\n                const { number, ...phoneConfig } = phoneNumber;\n                agent._addChannel(\"phone\", number, phoneConfig);\n            }\n        } else if (phoneNumbers) {\n            for (const p of phoneNumbers) {\n                if (typeof p === \"string\") {\n                    agent._addChannel(\"phone\", p);\n                } else {\n                    const { number, ...phoneConfig } = p;\n                    agent._addChannel(\"phone\", number, phoneConfig);\n                }\n            }\n        }\n\n        // Register WhatsApp channels\n        if (whatsapp) {\n            for (const wa of whatsapp) {\n                agent._addChannel(\"whatsapp\", wa);\n            }\n        }\n\n        // Function greetings only — string/object ones rode the wire above and\n        // the server delivers them itself (voice speaks, chat emits when\n        // greetingInChat is set). A per-call computed greeting cannot\n        // serialize, so it keeps the legacy client-side say on voice events.\n        if (greeting) {\n            agent.on(\"call.started\", async (call) => {\n                const text = await greeting(call);\n                call.say(text, { addToHistory: true });\n            });\n        }\n\n        // If already connected, register immediately\n        if (this.#connected) {\n            this.#registerAgent(agent);\n        }\n\n        // Runner display hook (pinecall run)\n        if (this.#runnerHook) {\n            this.#runnerHook(agent);\n        }\n\n        return agent;\n    }\n\n    /**\n     * Claim a phone number as a programmable LINE — its own STT and TTS, no\n     * model. It answers first, resolves the dialled extension, speaks and\n     * listens in code, and hands the LIVE call to an agent when the code says\n     * so (`call.routeTo`). The destination agent does not have to be online for\n     * the number to answer.\n     *\n     * Idempotent per number, like `pc.agent()`. `llm`/`prompt`/`tools`/\n     * `greeting` are refused here and now: a line has no model.\n     *\n     * @example\n     * const line = pc.line(\"+12186633772\", { stt: \"soniox\", voice: \"elevenlabs/sarah\" });\n     * line.extensions({ \"10\": \"pres-restaurantes\", \"11\": \"pres-hoteles\" });\n     * line.on(\"call\", async (call) => {\n     *   const a = await call.ask(\"Press one for sales.\", { digits: 1, timeout: 5000 });\n     *   if (a.by === \"keypad\" && a.digit === \"1\") await call.routeTo(\"ventas\");\n     * });\n     */\n    line(number: string, opts: LineOptions = {}): PhoneLine {\n        const normalized = prepareLine(number, opts);\n        const existing = this.#lines.get(normalized);\n        if (existing) return existing;\n\n        const line = new PhoneLine(normalized, opts, (data) => this.#send(data));\n        this.#lines.set(normalized, line);\n\n        // If already connected, claim the number immediately\n        if (this.#connected) {\n            line._register();\n        }\n\n        return line;\n    }\n\n    removeAgent(id: string): boolean {\n        const agent = this.#agents.get(id);\n        if (agent) {\n            agent._endAllCalls(\"agent_removed\");\n            agent.removeAllListeners();\n        }\n        return this.#agents.delete(id);\n    }\n\n    // ── Token generation ─────────────────────────────────────────────────\n\n    /**\n     * Mint a short-lived browser token for an agent.\n     *\n     * `opts` (optional, spec §5) narrows the token: `{ scope: \"observe\",\n     * callId }` mints a read-only Call Log token for a single call. Omitting\n     * it mints exactly the token this method has always minted.\n     *\n     * Ordered AFTER the agent's server-side registration: `pc.agent()` returns\n     * synchronously and only queues `agent.create` on the socket, so a mint\n     * issued in the next statement used to overtake it on the wire and come\n     * back `404 Agent '<id>' is not online` — a valid, healthy registration\n     * refused purely because the HTTP request beat the WebSocket frame. For an\n     * agent this client owns we wait for `agent.created` first. Agents owned by\n     * another process are minted straight through (nothing local to wait on).\n     */\n    async createToken(\n        channel: \"webrtc\" | \"chat\" | \"stream\",\n        agentId: string | readonly string[],\n        metadata?: Record<string, unknown>,\n        opts?: TokenScopeOptions,\n    ): Promise<TokenResponse> {\n        // An agent set (§5) awaits each locally-owned registration, so a mint\n        // issued right after pc.agent(...) cannot race any member's create.\n        const ids = Array.isArray(agentId) ? agentId : [agentId as string];\n        for (const id of ids) await this.#awaitRegistration(id);\n        return createTokenApi({\n            channel,\n            agentId,\n            apiKey: this.#apiKey,\n            apiUrl: this.#apiUrl,\n            metadata,\n            ...(opts?.scope ? { scope: opts.scope } : {}),\n            ...(opts?.callId ? { callId: opts.callId } : {}),\n        });\n    }\n\n    // ── Call Log observation ─────────────────────────────────────────────\n\n    /**\n     * Read the Call Log over SSE — the ONE way to observe a call from Node.\n     *\n     * Opens `GET /v1/calls/{id}/events` (or `/v1/agents/{slug}/calls`) with\n     * `Accept: text/event-stream`, feeds every envelope into the same\n     * `CallLogView` reducer the browser uses, and exposes it three ways: the\n     * reduced `state`, `on(\"entry\" | \"custom\" | \"finish\")`, and `for await`.\n     * No WebSocket is opened — observation is read-only by construction.\n     *\n     * The token defaults to one minted with this client's API key\n     * (`createToken({ channel: \"stream\", scope: \"observe\" })`), which needs an\n     * agent: `observe({ call })` without a token must also pass `agent`.\n     *\n     * @example\n     * ```ts\n     * const obs = pc.observe({ agent: \"lucia\", types: [\"custom\", \"call.ended\"] });\n     * obs.on(\"custom\", (name, value) => console.log(name, value));\n     * for await (const entry of obs) console.log(entry.seq, entry.type);\n     * ```\n     */\n    observe(opts: ObserveOptions): Observation {\n        return observeLog({\n            ...opts,\n            apiKey: opts.apiKey ?? this.#apiKey,\n            server: opts.server ?? this.#apiUrl,\n            apiUrl: opts.apiUrl ?? this.#apiUrl,\n        });\n    }\n\n    // ── SSE Streaming ────────────────────────────────────────────────────\n\n    stream(opts?: StreamOptions): Response;\n    stream(res: ServerResponse, opts?: StreamOptions): void;\n    stream(resOrOpts?: ServerResponse | StreamOptions, opts?: StreamOptions): Response | void {\n        if (resOrOpts && typeof (resOrOpts as any).writeHead === \"function\") {\n            return createMultiAgentStream(this.#agents, resOrOpts as ServerResponse, opts);\n        }\n        return createMultiAgentStream(this.#agents, resOrOpts as StreamOptions);\n    }\n\n    // ── Raw send (escape hatch) ──────────────────────────────────────────\n\n    send(data: Record<string, unknown>): void {\n        this.#send(data);\n    }\n\n    // ── Private methods ──────────────────────────────────────────────────\n\n    /**\n     * Wait until the server has acknowledged a locally-owned agent.\n     *\n     * NOT a grace period: the wait ends the moment `agent.created` arrives (sub-\n     * millisecond on a live socket). The deadline exists only so a caller inside\n     * a request handler cannot hang forever while the socket is down — and it\n     * fails with the real reason instead of minting a token that would 404.\n     */\n    async #awaitRegistration(agentId: string): Promise<void> {\n        const agent = this.#agents.get(agentId);\n        if (!agent || agent.registered) return;\n\n        let timer: ReturnType<typeof setTimeout> | undefined;\n        const deadline = new Promise<never>((_, reject) => {\n            timer = setTimeout(() => reject(new PinecallError(\n                `Agent \"${agentId}\" was not registered by the server within ` +\n                `${Math.round(REGISTRATION_WAIT_MS / 1000)}s — it cannot be used yet ` +\n                `(is the client connected?).`,\n                \"AGENT_NOT_REGISTERED\",\n            )), REGISTRATION_WAIT_MS);\n            (timer as any)?.unref?.();\n        });\n        try {\n            await Promise.race([agent.ready, deadline]);\n        } finally {\n            if (timer) clearTimeout(timer);\n        }\n    }\n\n    #send(data: Record<string, unknown>): void {\n        if (this.#transport?.isOpen) {\n            this.#transport.send(data);\n            this.#logger.debug(\"→\", data);\n        }\n    }\n\n    #registerAgent(agent: Agent): void {\n        const config = agent.getConfig();\n\n        this.#send({\n            event: \"agent.create\",\n            agent_id: agent.id,\n            ...buildShortcutPayload(config),\n            ...(config.allowedOrigins ? { allowed_origins: config.allowedOrigins } : {}),\n        });\n    }\n\n    /**\n     * Retry a registration rejected with AGENT_CONFLICT / AGENT_IN_USE.\n     *\n     * The rejection is often transient: after a network blip or a process\n     * restart, the server may briefly hold our own dead socket as \"alive\".\n     * A new server also tells us WHICH case we're in:\n     *   - `retry_after_s` (escalating server-side) is honored directly;\n     *   - `holder_alive: true` = a real second process owns the name — cap\n     *     grows to 10 min so we never storm the server for hours;\n     *   - `holder_alive: false` = the holder died — reset to fast retries.\n     * Against an old server (no hint) the legacy 5s→60s backoff applies,\n     * now with jitter. Cleared on agent.created/agent.resumed and on socket\n     * close (a full reconnect re-registers every agent anyway).\n     *\n     * Retries are BOUNDED: the whole episode gets CONFLICT_RETRY_BUDGET_MS\n     * (2× the server's stale-registration window) — enough for any stale\n     * registration to be reaped, and no more. Past it the conflict is\n     * terminal (see #failRegistration) instead of a forever-storm. A new\n     * server short-circuits this with AGENT_CONFLICT_FATAL; an old server\n     * never sends it, and the budget alone still ends the storm.\n     *\n     * Returns true when this is the FIRST conflict of the episode (the\n     * caller logs the human-facing banner exactly once).\n     */\n    #scheduleRegisterRetry(agentId: string, hint?: { retryAfterS?: number; holderAlive?: boolean }): boolean {\n        let state = this.#registerRetries.get(agentId);\n        const first = !state;\n        if (!state) {\n            state = { attempt: 0, timer: null, holderAlive: false, startedAt: Date.now() };\n            this.#registerRetries.set(agentId, state);\n        }\n        if (state.timer) {\n            // A retry is already scheduled; still absorb a \"holder died\" hint.\n            if (hint?.holderAlive === false) state.holderAlive = false;\n            return first;\n        }\n\n        const plan = planConflictRetry(state, hint, Date.now());\n        if (plan.action === \"terminal\") {\n            this.#failRegistration(agentId, \"retry_budget_exhausted\");\n            return first;\n        }\n        const delay = plan.delayMs;\n\n        const timer = setTimeout(() => {\n            state!.timer = null;\n            const agent = this.#agents.get(agentId);\n            if (this.#connected && agent) {\n                this.#logger.info(`Retrying registration for \"${agentId}\" (attempt ${state!.attempt})`);\n                this.#registerAgent(agent);\n            }\n        }, delay);\n        // Don't hold the process open just for a retry timer (Node.js)\n        (timer as any)?.unref?.();\n        state.timer = timer;\n\n        const line = `Registration conflict for \"${agentId}\" — retrying in ${Math.round(delay / 1000)}s` +\n            (state.holderAlive ? \" (name actively held elsewhere)\" : \"\");\n        // First rejection gets a visible warn; the rest stay quiet (info) —\n        // a held name used to spam an error banner every attempt for hours.\n        if (first) this.#logger.warn(line);\n        else this.#logger.info(line);\n        return first;\n    }\n\n    /**\n     * Give up on a registration — the TERMINAL state for a conflict.\n     *\n     * Reached either because the server said the holder is provably alive\n     * (`AGENT_CONFLICT_FATAL`) or because the retry budget ran out. Drops the\n     * retry state (no further attempts) and surfaces a typed\n     * {@link AgentConflictError} on the client's `error` event so a developer\n     * can catch it — a log line alone is not an API.\n     */\n    #failRegistration(agentId: string, reason: \"server_fatal\" | \"retry_budget_exhausted\"): void {\n        const state = this.#registerRetries.get(agentId);\n        if (state?.timer) clearTimeout(state.timer);\n        this.#registerRetries.delete(agentId);\n\n        const why = reason === \"server_fatal\"\n            ? \"the server confirmed another LIVE process holds it\"\n            : `no registration after ${Math.round(CONFLICT_RETRY_BUDGET_MS / 1000)}s of retries — another LIVE process holds it`;\n        const message =\n            `Agent \"${agentId}\" could not be registered: ${why}. ` +\n            `Either run \\`pinecall kick ${agentId}\\` to disconnect the current holder, ` +\n            `or register this agent under a different id.`;\n        this.#logger.error(message);\n        const err = new AgentConflictError(message, agentId, reason);\n        // Fail anyone awaiting `agent.ready` (e.g. a token mint) instead of\n        // leaving them pending on a registration that will never land.\n        this.#agents.get(agentId)?._failRegistration(err);\n        this.emit(\"error\", err);\n    }\n\n    #clearRegisterRetry(agentId: string): void {\n        const state = this.#registerRetries.get(agentId);\n        if (state?.timer) clearTimeout(state.timer);\n        if (state && state.attempt > 0) {\n            this.#logger.info(`Registration for \"${agentId}\" succeeded after ${state.attempt} retr${state.attempt === 1 ? \"y\" : \"ies\"}`);\n        }\n        this.#registerRetries.delete(agentId);\n    }\n\n    #clearAllRegisterRetries(): void {\n        for (const state of this.#registerRetries.values()) {\n            if (state.timer) clearTimeout(state.timer);\n        }\n        this.#registerRetries.clear();\n    }\n\n    #getEnv(key: string): string | undefined {\n        try {\n            return (globalThis as any).process?.env?.[key];\n        } catch {\n            return undefined;\n        }\n    }\n\n    #onMessage(data: Record<string, unknown>): void {\n        const wire = data as WireEvent;\n        this.#logger.debug(\"←\", data);\n\n        // Build dispatch context\n        const ctx: DispatchContext = {\n            agent: (wireId: string) => {\n                // Lines share this namespace on purpose: registered under\n                // `line:<number>`, every existing handler routes to one\n                // without knowing lines exist.\n                const localKeys = new Set(this.#agents.keys());\n                for (const line of this.#lines.values()) localKeys.add(line.id);\n                const resolved = this.#resolver.resolve(wireId, localKeys);\n                if (!resolved) return null;\n                if (resolved.startsWith(\"line:\")) {\n                    return this.#lines.get(resolved.slice(\"line:\".length))?._agent ?? null;\n                }\n                return this.#agents.get(resolved) ?? null;\n            },\n            call: (agent, callId) => agent._getCall(callId),\n            logger: this.#logger,\n            send: (d) => this.#send(d),\n            onConnected: () => {\n                this.#connected = true;\n                this.#reconnector.reset();\n\n                // Register all pre-created agents\n                for (const agent of this.#agents.values()) {\n                    this.#registerAgent(agent);\n                }\n\n                // And re-claim every line's number. A line that comes back\n                // from a reconnect without re-sending `line.create` strands\n                // its number exactly like an unregistered agent would.\n                for (const line of this.#lines.values()) {\n                    line._register();\n                }\n\n                // Start ping interval\n                if (!this.#pingInterval) {\n                    this.#pingInterval = setInterval(() => {\n                        this.#send({ event: \"ping\" });\n                    }, 30_000);\n                }\n\n                // Resolve the connect() promise\n                if (this.#connectResolve) {\n                    this.#connectResolve();\n                    this.#connectResolve = null;\n                    this.#connectReject = null;\n                }\n\n                this.emit(\"connected\");\n                this.#logger.info(\"Connected to Pinecall\");\n            },\n            registration: this.#registration,\n            // Routed through the friend methods below so each capability has\n            // exactly one implementation on this class.\n            emitClientEvent: (event, ...args) => this._emitWire(event, ...args),\n            allAgents: () => this._allAgents(),\n            whatsappSession: (id) => this._getWhatsAppHandler().getSession(id),\n            lines: () => [...this.#lines.values()],\n        };\n\n        this.#dispatcher.dispatch(wire, ctx);\n    }\n\n    #onClose(reason: string): void {\n        this.#connected = false;\n\n        if (this.#pingInterval) {\n            clearInterval(this.#pingInterval);\n            this.#pingInterval = null;\n        }\n\n        // Reconnect re-registers every agent — drop per-agent retry timers\n        this.#clearAllRegisterRetries();\n\n        // End all active calls. The server drops every registration on this\n        // socket too, so `ready` goes back to pending until the reconnect\n        // re-registers each agent — otherwise a mint during a reconnect would\n        // race `agent.create` exactly like a cold start does.\n        for (const agent of this.#agents.values()) {\n            agent._endAllCalls(reason);\n            agent._markUnregistered();\n        }\n        for (const line of this.#lines.values()) {\n            line._endAllCalls(reason);\n            line._markUnregistered();\n        }\n\n        this.emit(\"disconnected\", reason);\n        this.#logger.info(`Disconnected: ${reason}`);\n\n        // Auto-reconnect unless intentional close or displacement\n        const displaced = reason.includes(\"Displaced\") || reason.includes(\"displaced\");\n        if (!this.#intentionalClose && this.#autoReconnect && !displaced) {\n            this.#reconnect();\n        }\n    }\n\n    async #reconnect(): Promise<void> {\n        // Clear the old promise so connect() creates a fresh connection\n        this.#connectPromise = null;\n        try {\n            const delay = await this.#reconnector.wait();\n            this.emit(\"reconnecting\", this.#reconnector.attempt, delay);\n            this.#logger.info(`Reconnecting (attempt ${this.#reconnector.attempt}, delay ${delay}ms)`);\n            await this.connect();\n        } catch (err) {\n            this.#logger.error(`Reconnection failed: ${err}`);\n            // Schedule another attempt\n            if (!this.#intentionalClose) {\n                this.#reconnect();\n            }\n        }\n    }\n\n    // ── Friend methods (the client half of the DispatchContext) ──────────\n\n    /** @internal Emit a typed event (the context's `emitClientEvent`). */\n    _emitWire(event: string, ...args: unknown[]): void {\n        (this as any).emit(event, ...args);\n    }\n\n    /** @internal Get an agent by ID. */\n    _getAgent(id: string): Agent | undefined {\n        return this.#agents.get(id);\n    }\n\n    /** @internal Get all registered agents (the context's `allAgents`). Used when agent_id is missing. */\n    _allAgents(): Agent[] {\n        return [...this.#agents.values()];\n    }\n\n    /** @internal Get the WhatsApp handler (backs the context's `whatsappSession`). */\n    _getWhatsAppHandler(): WhatsAppHandler {\n        return this.#waHandler;\n    }\n}\n","/**\n * tool() — declarative tool definitions with Zod schema + auto-execution.\n *\n * Usage:\n * ```ts\n * import { tool } from \"@pinecall/sdk\";\n * import { z } from \"zod\";\n *\n * const openDoor = tool({\n *   name: \"openDoor\",\n *   description: \"Opens the door if the code is valid\",\n *   schema: z.object({ code: z.string().describe(\"5-digit code\") }),\n *   execute: async ({ code }, call) => ({ success: VALID_CODES.has(code) }),\n * });\n * ```\n *\n * The returned Tool object is passed to `tools: [openDoor]` in agent config.\n * The SDK auto-executes matching tools on `llm.tool_call` events.\n */\n\nimport type { Call } from \"./domain/call.js\";\n\n// ─── Public types ────────────────────────────────────────────────────────\n\nexport interface ToolConfig<T = any> {\n    name: string;\n    description: string;\n    /** Zod schema (or any object with .parse() and ._def). */\n    schema: ZodLike<T>;\n    /** Execute function — receives parsed args + call. */\n    execute: (args: T, call: Call) => unknown | Promise<unknown>;\n    /**\n     * Ephemeral tools — the result is used to generate the current reply but is\n     * NOT persisted to conversation history (neither the LLM context for later\n     * turns nor the saved transcript). Defaults to `false` (results are saved).\n     * Use for sensitive lookups or large/noisy payloads you don't want to keep.\n     */\n    ephemeral?: boolean;\n    /**\n     * Fire-and-forget / UI-only tools — after this tool's result the server does\n     * NOT generate a follow-up assistant turn. Use for tools whose result only\n     * drives the UI (suggested-question chips, a toast, a state mutation) and\n     * should NOT produce another spoken/written reply. The result still reaches\n     * the client via `llm.tool_result`. Defaults to `false`.\n     *\n     * Only takes effect when EVERY tool called in that round is `noFollowup`; a\n     * mixed round (a normal tool + a noFollowup tool) still replies, because the\n     * normal tool's result needs one.\n     */\n    noFollowup?: boolean;\n}\n\nexport interface Tool<T = any> {\n    readonly name: string;\n    readonly description: string;\n    readonly schema: ZodLike<T>;\n    readonly execute: (args: T, call: Call) => unknown | Promise<unknown>;\n    /** Result is not persisted to history when true. */\n    readonly ephemeral: boolean;\n    /** No follow-up assistant turn is generated after this tool when true. */\n    readonly noFollowup: boolean;\n    /** @internal JSON Schema for wire protocol. */\n    readonly _jsonSchema: Record<string, unknown>;\n    /** @internal Convert to OpenAI function-calling wire format. */\n    _toWire(): Record<string, unknown>;\n}\n\n/** Duck-typed Zod schema — anything with parse() and _def. */\ninterface ZodLike<T = any> {\n    parse: (input: unknown) => T;\n    _def: Record<string, any>;\n    [key: string]: any;\n}\n\n// ─── Factory ─────────────────────────────────────────────────────────────\n\nexport function tool<T>(config: ToolConfig<T>): Tool<T> {\n    const jsonSchema = zodToJsonSchema(config.schema);\n\n    return {\n        name: config.name,\n        description: config.description,\n        schema: config.schema,\n        execute: config.execute,\n        ephemeral: config.ephemeral ?? false,\n        noFollowup: config.noFollowup ?? false,\n        _jsonSchema: jsonSchema,\n        _toWire() {\n            return {\n                type: \"function\",\n                function: {\n                    name: config.name,\n                    description: config.description,\n                    parameters: jsonSchema,\n                },\n            };\n        },\n    };\n}\n\n// ─── Zod → JSON Schema micro-converter ──────────────────────────────────\n//\n// Handles the Zod types actually used in voice agent tools:\n//   ZodObject, ZodString, ZodNumber, ZodBoolean, ZodEnum, ZodArray,\n//   ZodOptional, ZodNullable, ZodDefault, ZodLiteral, ZodEffects,\n//   plus .describe() on any type.\n\nfunction zodToJsonSchema(schema: ZodLike): Record<string, unknown> {\n    return convertNode(schema);\n}\n\nfunction convertNode(node: ZodLike): Record<string, unknown> {\n    const def = node._def;\n    // Zod 4 renamed the discriminant: `_def.typeName` (\"ZodString\") became\n    // `_def.type` (\"string\"). A v4 schema fed to the v3 switch matched NOTHING,\n    // fell through to the default, and every tool went to the LLM as\n    // `parameters: {}` — the model then \"correctly\" called it with no args and\n    // the SDK-side Zod validation rejected what the model was never told about.\n    // Silent, because tests asserted on `.schema` (the Zod object), never on\n    // the generated wire schema. Both formats are handled from here on.\n    if (typeof def.type === \"string\" && def.typeName === undefined) {\n        return convertNodeV4(node);\n    }\n    const typeName: string = def.typeName ?? \"\";\n    let result: Record<string, unknown> = {};\n\n    switch (typeName) {\n        case \"ZodObject\": {\n            result.type = \"object\";\n            const shape = def.shape?.() ?? def.shape ?? {};\n            const properties: Record<string, unknown> = {};\n            const required: string[] = [];\n\n            for (const [key, value] of Object.entries(shape)) {\n                properties[key] = convertNode(value as ZodLike);\n                if (!isOptional(value as ZodLike)) {\n                    required.push(key);\n                }\n            }\n\n            result.properties = properties;\n            if (required.length > 0) result.required = required;\n            break;\n        }\n\n        case \"ZodString\":\n            result.type = \"string\";\n            break;\n\n        case \"ZodNumber\":\n            result.type = \"number\";\n            break;\n\n        case \"ZodBoolean\":\n            result.type = \"boolean\";\n            break;\n\n        case \"ZodEnum\":\n            result.type = \"string\";\n            result.enum = def.values;\n            break;\n\n        case \"ZodArray\":\n            result.type = \"array\";\n            if (def.type) {\n                result.items = convertNode(def.type);\n            }\n            break;\n\n        case \"ZodOptional\":\n            result = convertNode(def.innerType);\n            break;\n\n        case \"ZodNullable\":\n            result = convertNode(def.innerType);\n            break;\n\n        case \"ZodDefault\":\n            result = convertNode(def.innerType);\n            if (def.defaultValue !== undefined) {\n                result.default = typeof def.defaultValue === \"function\"\n                    ? def.defaultValue()\n                    : def.defaultValue;\n            }\n            break;\n\n        case \"ZodLiteral\":\n            result.const = def.value;\n            break;\n\n        case \"ZodEffects\":\n            // .refine() / .transform() — convert the inner schema\n            result = convertNode(def.schema);\n            break;\n\n        default:\n            // Unknown Zod type — pass through as empty object\n            break;\n    }\n\n    // .describe() — Zod stores it on _def.description\n    if (def.description) {\n        result.description = def.description;\n    }\n\n    return result;\n}\n\n/**\n * Zod 4 branch. Same JSON Schema output as the v3 switch, from v4's internals:\n * `_def.type` is lowercase (\"object\"), object shape is a plain object (not a\n * thunk), enums live in `_def.entries`, array element in `_def.element`, and\n * `.transform()/.refine()` compose through \"pipe\" (`_def.in`). `.describe()`\n * no longer writes `_def.description` — it registers metadata that surfaces on\n * the schema's own `.description` getter, which v3 also has, so the caller\n * reads `node.description` first for both.\n */\nfunction convertNodeV4(node: ZodLike): Record<string, unknown> {\n    const def = node._def;\n    let result: Record<string, unknown> = {};\n\n    switch (def.type) {\n        case \"object\": {\n            result.type = \"object\";\n            const shape = typeof def.shape === \"function\" ? def.shape() : (def.shape ?? {});\n            const properties: Record<string, unknown> = {};\n            const required: string[] = [];\n\n            for (const [key, value] of Object.entries(shape)) {\n                properties[key] = convertNode(value as ZodLike);\n                if (!isOptional(value as ZodLike)) {\n                    required.push(key);\n                }\n            }\n\n            result.properties = properties;\n            if (required.length > 0) result.required = required;\n            break;\n        }\n\n        case \"string\":\n            result.type = \"string\";\n            break;\n\n        case \"number\":\n        case \"int\":\n            result.type = \"number\";\n            break;\n\n        case \"boolean\":\n            result.type = \"boolean\";\n            break;\n\n        case \"enum\":\n            result.type = \"string\";\n            result.enum = def.entries ? Object.values(def.entries) : def.values;\n            break;\n\n        case \"array\":\n            result.type = \"array\";\n            if (def.element) {\n                result.items = convertNode(def.element);\n            }\n            break;\n\n        case \"optional\":\n        case \"nullable\":\n            result = convertNode(def.innerType);\n            break;\n\n        case \"default\":\n            result = convertNode(def.innerType);\n            if (def.defaultValue !== undefined) {\n                result.default = typeof def.defaultValue === \"function\"\n                    ? def.defaultValue()\n                    : def.defaultValue;\n            }\n            break;\n\n        case \"literal\": {\n            // v4 literals hold an ARRAY of values (z.literal([\"a\", \"b\"]) is legal).\n            const values: unknown[] = def.values ?? [];\n            if (values.length === 1) result.const = values[0];\n            else if (values.length > 1) result.enum = values;\n            break;\n        }\n\n        case \"pipe\":\n            // .transform() / piped refinements — the LLM's contract is the INPUT\n            result = convertNode(def.in);\n            break;\n\n        default:\n            // Unknown Zod type — pass through as empty object\n            break;\n    }\n\n    const description = node.description ?? def.description;\n    if (description) {\n        result.description = description;\n    }\n\n    return result;\n}\n\nfunction isOptional(node: ZodLike): boolean {\n    const def = node._def ?? {};\n    // Zod 4 (lowercase `type` discriminant)\n    if (typeof def.type === \"string\" && def.typeName === undefined) {\n        if (def.type === \"optional\") return true;\n        if (def.type === \"default\") return true;\n        if (def.type === \"pipe\") return isOptional(def.in);\n        return false;\n    }\n    const typeName: string = def.typeName ?? \"\";\n    if (typeName === \"ZodOptional\") return true;\n    if (typeName === \"ZodDefault\") return true;\n    // Unwrap effects\n    if (typeName === \"ZodEffects\") return isOptional(node._def.schema);\n    return false;\n}\n","/**\n * History — pluggable conversation persistence.\n *\n * When `history` is set on an agent config, conversations are saved\n * incrementally: each confirmed user message, bot response, and tool call\n * triggers an upsert. The final save on `call.ended` adds metadata.\n *\n * If the store implements `findByContact()`, prior conversations are\n * automatically restored for returning contacts — no extra code needed.\n *\n * Built-in: `JsonFileHistory` — appends to a JSON file on disk.\n * Custom: implement `HistoryStore` (only `save()` is required).\n *\n * @example\n * ```ts\n * import { Pinecall, JsonFileHistory } from \"@pinecall/sdk\";\n *\n * const agent = pc.agent(\"my-agent\", {\n *     history: new JsonFileHistory(\"./data/calls.json\"),\n *     // auto-saves AND auto-restores — zero boilerplate\n * });\n * ```\n */\n\n// ─── Types ───────────────────────────────────────────────────────────────\n\n/** A conversation record — saved incrementally during a call and finalized on end. */\nexport interface ConversationRecord {\n    callId: string;\n    agentId: string;\n    channel: \"phone\" | \"webrtc\" | \"chat\" | \"whatsapp\" | \"unknown\";\n    direction: \"inbound\" | \"outbound\";\n    from: string;\n    to: string;\n    startedAt: number;\n    endedAt: number;\n    duration: number;\n    reason: string;\n    /** `\"active\"` while the call is in progress, `\"ended\"` after call.ended. */\n    status: \"active\" | \"ended\";\n    transcript: Array<{ role: string; content: string }>;\n    /** Full LLM messages including tool calls. Built incrementally from events. */\n    messages: Array<Record<string, unknown>>;\n    metadata: Record<string, unknown>;\n}\n\n// ─── Interface ───────────────────────────────────────────────────────────\n\n/**\n * Pluggable storage interface for conversation history.\n *\n * Only `save()` is required. Implement `findByContact`, `list`, `get`,\n * `delete` for richer features (returning callers, admin dashboards, etc.).\n *\n * @example Custom MongoDB store\n * ```ts\n * class MongoHistory implements HistoryStore {\n *     async save(record: ConversationRecord) {\n *         await db.conversations.updateOne(\n *             { callId: record.callId },\n *             { $set: record },\n *             { upsert: true },\n *         );\n *     }\n *\n *     async findByContact(contactId: string, limit = 5) {\n *         return db.conversations\n *             .find({ from: contactId })\n *             .sort({ endedAt: -1 })\n *             .limit(limit)\n *             .toArray();\n *     }\n * }\n * ```\n */\nexport interface HistoryStore {\n    /** Save/upsert a conversation. Called on every confirmed message and on call.ended. */\n    save(record: ConversationRecord): Promise<void>;\n\n    /**\n     * Find conversations by contact identifier (phone number, userId, etc.).\n     * Searches the `from` field. Override for custom matching logic.\n     */\n    findByContact?(contactId: string, limit?: number): Promise<ConversationRecord[]>;\n\n    /** List conversations for an agent, newest first. */\n    list?(agentId: string, limit?: number): Promise<ConversationRecord[]>;\n\n    /** Get a single conversation by call ID. */\n    get?(callId: string): Promise<ConversationRecord | null>;\n\n    /** Delete a single conversation. Returns true if found and deleted. */\n    delete?(callId: string): Promise<boolean>;\n}\n\n// ─── JsonFileHistory ─────────────────────────────────────────────────────\n\n/**\n * Built-in history store — appends conversations to a JSON file.\n *\n * Good for prototyping and small projects. For production at scale,\n * implement `HistoryStore` with MongoDB, Postgres, or your own API.\n *\n * @example\n * ```ts\n * import { JsonFileHistory } from \"@pinecall/sdk\";\n * const history = new JsonFileHistory(\"./data/calls.json\");\n * ```\n */\nexport class JsonFileHistory implements HistoryStore {\n    readonly path: string;\n\n    constructor(path: string) {\n        this.path = path;\n    }\n\n    async save(record: ConversationRecord): Promise<void> {\n        const fs = await import(\"node:fs/promises\");\n        const { dirname } = await import(\"node:path\");\n\n        // Ensure directory exists\n        try {\n            await fs.mkdir(dirname(this.path), { recursive: true });\n        } catch { /* already exists */ }\n\n        const data = await this.#readAll();\n\n        // Upsert by callId\n        const idx = data.findIndex((r) => r.callId === record.callId);\n        if (idx >= 0) {\n            data[idx] = record;\n        } else {\n            data.push(record);\n        }\n\n        await fs.writeFile(this.path, JSON.stringify(data, null, 2));\n    }\n\n    async findByContact(\n        contactId: string,\n        limit = 10,\n    ): Promise<ConversationRecord[]> {\n        const data = await this.#readAll();\n        return data\n            .filter((r) => r.from === contactId)\n            .sort((a, b) => b.endedAt - a.endedAt)\n            .slice(0, limit);\n    }\n\n    async list(agentId: string, limit = 50): Promise<ConversationRecord[]> {\n        const data = await this.#readAll();\n        return data\n            .filter((r) => r.agentId === agentId)\n            .sort((a, b) => b.endedAt - a.endedAt)\n            .slice(0, limit);\n    }\n\n    async get(callId: string): Promise<ConversationRecord | null> {\n        const data = await this.#readAll();\n        return data.find((r) => r.callId === callId) ?? null;\n    }\n\n    async delete(callId: string): Promise<boolean> {\n        const fs = await import(\"node:fs/promises\");\n        const data = await this.#readAll();\n        const filtered = data.filter((r) => r.callId !== callId);\n        if (filtered.length === data.length) return false;\n        await fs.writeFile(this.path, JSON.stringify(filtered, null, 2));\n        return true;\n    }\n\n    // ── Internal ─────────────────────────────────────────────────────────\n\n    async #readAll(): Promise<ConversationRecord[]> {\n        const fs = await import(\"node:fs/promises\");\n        try {\n            const raw = await fs.readFile(this.path, \"utf-8\");\n            const parsed = JSON.parse(raw);\n            return Array.isArray(parsed) ? parsed : [];\n        } catch {\n            return [];\n        }\n    }\n}\n","/**\n * Phone API — fetch account phone numbers.\n */\n\nimport { DEFAULT_API_URL } from \"./http.js\";\n\nexport interface Phone {\n    number: string;\n    name: string;\n    sid: string;\n    isSdk?: boolean;\n}\n\nexport interface FetchPhonesOptions {\n    apiKey: string;\n    apiUrl?: string;\n}\n\nexport async function fetchPhones(opts: FetchPhonesOptions): Promise<Phone[]> {\n    const apiUrl = opts.apiUrl ?? DEFAULT_API_URL;\n    const url = `${apiUrl}/api/sdk/phone-numbers`;\n\n    let res: Response;\n    try {\n        res = await fetch(url, {\n            headers: { Authorization: `Bearer ${opts.apiKey}` },\n        });\n    } catch (err) {\n        throw new Error(`Network error fetching phone numbers: ${err}`);\n    }\n\n    if (!res.ok) {\n        throw new Error(`Failed to fetch phone numbers: HTTP ${res.status}`);\n    }\n\n    const data = await res.json();\n    if (!data.success) return [];\n\n    const raw: Record<string, unknown>[] = data.phones ?? data.phoneNumbers ?? [];\n    return raw.map(mapPhone);\n}\n\nfunction mapPhone(raw: Record<string, unknown>): Phone {\n    return {\n        number: (raw.number ?? \"\") as string,\n        name: (raw.name ?? raw.number ?? \"\") as string,\n        sid: (raw.sid ?? \"\") as string,\n        isSdk: (raw.isSdk ?? false) as boolean,\n    };\n}\n","/**\n * Balance API — Twilio and account balance.\n */\n\nimport { DEFAULT_API_URL } from \"./http.js\";\n\nexport interface FetchTwilioBalanceOptions {\n    apiKey?: string;\n    apiUrl?: string;\n}\n\nexport interface TwilioBalance {\n    balance: string;\n    currency: string;\n}\n\nexport async function fetchTwilioBalance(opts: FetchTwilioBalanceOptions = {}): Promise<TwilioBalance | null> {\n    const apiUrl = opts.apiUrl ?? DEFAULT_API_URL;\n    const url = `${apiUrl}/api/sdk/twilio-balance`;\n\n    const headers: Record<string, string> = {};\n    if (opts.apiKey) headers[\"Authorization\"] = `Bearer ${opts.apiKey}`;\n\n    let res: Response;\n    try {\n        res = await fetch(url, { headers });\n    } catch {\n        return null;\n    }\n\n    if (!res.ok) return null;\n\n    const data = await res.json();\n    if (!data.success) return null;\n\n    return {\n        balance: data.balance,\n        currency: data.currency,\n    };\n}\n","/**\n * Model access API — check whether the authenticated org can use a given\n * STT/TTS/LLM model (plan + managed/BYOK gates), before configuring an agent.\n *\n * Hits the Playground org API (authenticated with your API key), not the voice\n * server. Default base: https://playground.pinecall.io (override with\n * PINECALL_PLAYGROUND_URL or the `playgroundUrl` option).\n */\n\nconst DEFAULT_PLAYGROUND_URL = \"https://playground.pinecall.io\";\n\nexport type ModelAccessReason = \"ok\" | \"unknown_model\" | \"plan_restricted\" | \"byok_key_required\";\n\nexport interface ModelAccess {\n    service: string;\n    provider?: string;\n    model: string;\n    /** model is priced/known */\n    exists: boolean;\n    /** Pinecall serves it with its own key (no token needed) */\n    managed: boolean;\n    /** the model's provider is allowed on the org's plan */\n    planAllowed: boolean;\n    /** the org has saved its own key for this provider */\n    hasKey: boolean;\n    /** BYOK provider with no saved key → user must add one */\n    requiresKey: boolean;\n    /** final verdict: planAllowed && (managed || hasKey) */\n    allowed: boolean;\n    reason: ModelAccessReason;\n}\n\nexport interface FetchModelAccessOptions {\n    service: \"stt\" | \"tts\" | \"llm\";\n    model: string;\n    apiKey?: string;\n    playgroundUrl?: string;\n}\n\nexport interface ListModelAccessOptions {\n    apiKey?: string;\n    playgroundUrl?: string;\n}\n\nfunction resolveAuth(opts: { apiKey?: string; playgroundUrl?: string }) {\n    const env = (typeof process !== \"undefined\" ? process.env : {}) as Record<string, string | undefined>;\n    const apiKey = opts.apiKey ?? env.PINECALL_API_KEY;\n    const base = opts.playgroundUrl ?? env.PINECALL_PLAYGROUND_URL ?? DEFAULT_PLAYGROUND_URL;\n    if (!apiKey) throw new Error(\"fetchModelAccess: apiKey required (pass apiKey or set PINECALL_API_KEY)\");\n    return { apiKey, base };\n}\n\n/** Access decision for one (service, model). */\nexport async function fetchModelAccess(opts: FetchModelAccessOptions): Promise<ModelAccess> {\n    const { apiKey, base } = resolveAuth(opts);\n    const url = `${base}/api/models/access?service=${encodeURIComponent(opts.service)}&model=${encodeURIComponent(opts.model)}`;\n    const res = await fetch(url, { headers: { Authorization: `Bearer ${apiKey}` } });\n    if (!res.ok) throw new Error(`Failed to check model access: HTTP ${res.status}`);\n    return (await res.json()) as ModelAccess;\n}\n\n/** Convenience: true if the org can use the model. */\nexport async function hasModelAccess(opts: FetchModelAccessOptions): Promise<boolean> {\n    return (await fetchModelAccess(opts)).allowed;\n}\n\n/** Access for every priced model the org could use. */\nexport async function fetchModelCatalog(opts: ListModelAccessOptions = {}): Promise<ModelAccess[]> {\n    const { apiKey, base } = resolveAuth(opts);\n    const res = await fetch(`${base}/api/models/access`, { headers: { Authorization: `Bearer ${apiKey}` } });\n    if (!res.ok) throw new Error(`Failed to list model access: HTTP ${res.status}`);\n    const data = await res.json();\n    return Array.isArray(data.models) ? (data.models as ModelAccess[]) : [];\n}\n","/**\n * Knowledge base (RAG) REST client — the documents an agent can look things up in.\n *\n * Knowledge bases live on the PLAYGROUND API (the management plane), not on\n * the voice server: creating a KB, pushing docs and rebuilding the index are\n * account operations, and they happen whether or not any agent is online.\n * That is why this module takes its own `playgroundUrl` instead of the\n * `apiUrl` the rest of the SDK talks to.\n *\n * Knowledge bases are a paid feature. The server answers HTTP 402 for orgs on\n * a plan without them, and that arrives here as a typed\n * `KnowledgeApiError` with `code === \"UPGRADE_REQUIRED\"` — catchable, so a\n * consumer can offer the upgrade instead of parsing a message.\n */\n\nimport { PinecallError } from \"../kernel/errors.js\";\n\nexport const DEFAULT_PLAYGROUND_URL = \"https://playground.pinecall.io\";\n\n// ── Types ────────────────────────────────────────────────────────────────\n\nexport interface KnowledgeBase {\n    id: string;\n    name: string;\n    description?: string;\n    docCount: number;\n    status: string;\n}\n\nexport interface KnowledgeDoc {\n    id: string;\n    path: string;\n    title: string;\n    bytes: number;\n}\n\n/** A document as returned by `getDoc` — the listing fields plus the text. */\nexport interface KnowledgeDocWithText extends KnowledgeDoc {\n    text: string;\n}\n\nexport interface KnowledgeHit {\n    score: number;\n    text: string;\n    heading?: string;\n    doc_title?: string;\n    doc_path?: string;\n}\n\nexport interface KnowledgeApiOptions {\n    apiKey: string;\n    /**\n     * Management API base. Defaults to `PINECALL_PLAYGROUND_URL` and then to\n     * https://playground.pinecall.io. Trailing slashes are stripped, so\n     * \"http://localhost:3000/\" and \"http://localhost:3000\" are the same host.\n     */\n    playgroundUrl?: string;\n}\n\n/** A document to upsert. `path` is the identity: pushing the same path updates. */\nexport interface KnowledgeDocInput {\n    path: string;\n    title?: string;\n    text: string;\n}\n\n/** One entry of a `pushDocs` batch — a failure never aborts the rest. */\nexport interface PushResult {\n    path: string;\n    ok: boolean;\n    doc?: KnowledgeDoc;\n    error?: Error;\n}\n\n// ── Errors ───────────────────────────────────────────────────────────────\n\nexport class KnowledgeApiError extends PinecallError {\n    constructor(message: string, public status: number, code?: string) {\n        super(message, code);\n        this.name = \"KnowledgeApiError\";\n    }\n}\n\n// ── Transport ────────────────────────────────────────────────────────────\n\nfunction baseUrl(opts: KnowledgeApiOptions): string {\n    const raw =\n        opts.playgroundUrl ??\n        (typeof process !== \"undefined\" ? process.env?.PINECALL_PLAYGROUND_URL : undefined) ??\n        DEFAULT_PLAYGROUND_URL;\n    return raw.replace(/\\/+$/, \"\");\n}\n\nasync function call<T>(\n    opts: KnowledgeApiOptions,\n    method: string,\n    path: string,\n    body?: unknown,\n): Promise<T> {\n    const url = `${baseUrl(opts)}/api/knowledge${path}`;\n    let res: Response;\n    try {\n        res = await fetch(url, {\n            method,\n            headers: {\n                \"Content-Type\": \"application/json\",\n                Authorization: `Bearer ${opts.apiKey}`,\n            },\n            ...(body === undefined ? {} : { body: JSON.stringify(body) }),\n        });\n    } catch (err) {\n        throw new KnowledgeApiError(\n            `Cannot reach the Playground at ${baseUrl(opts)}: ${(err as Error)?.message ?? err}`,\n            0,\n            \"NETWORK_ERROR\",\n        );\n    }\n\n    if (res.status === 402) {\n        throw new KnowledgeApiError(\n            \"Knowledge bases are a paid feature — upgrade to Starter or higher.\",\n            402,\n            \"UPGRADE_REQUIRED\",\n        );\n    }\n\n    if (!res.ok) {\n        const text = await res.text().catch(() => \"\");\n        throw new KnowledgeApiError(\n            `knowledge ${method} ${path}: ${res.status} ${text || res.statusText}`,\n            res.status,\n        );\n    }\n\n    return (await res.json().catch(() => ({}))) as T;\n}\n\n// ── Knowledge bases ──────────────────────────────────────────────────────\n\nexport async function listKnowledgeBases(opts: KnowledgeApiOptions): Promise<KnowledgeBase[]> {\n    const data = await call<{ knowledgeBases?: KnowledgeBase[] }>(opts, \"GET\", \"\");\n    return data.knowledgeBases ?? [];\n}\n\nexport async function createKnowledgeBase(\n    opts: KnowledgeApiOptions,\n    name: string,\n    description?: string,\n): Promise<KnowledgeBase> {\n    const data = await call<{ knowledgeBase: KnowledgeBase }>(opts, \"POST\", \"\", { name, description });\n    return data.knowledgeBase;\n}\n\nexport async function getKnowledgeBase(\n    opts: KnowledgeApiOptions,\n    kbId: string,\n): Promise<{ knowledgeBase: KnowledgeBase; docs: KnowledgeDoc[] }> {\n    const data = await call<{ knowledgeBase: KnowledgeBase; docs?: KnowledgeDoc[] }>(\n        opts, \"GET\", `/${encodeURIComponent(kbId)}`,\n    );\n    return { knowledgeBase: data.knowledgeBase, docs: data.docs ?? [] };\n}\n\nexport async function deleteKnowledgeBase(opts: KnowledgeApiOptions, kbId: string): Promise<void> {\n    await call<unknown>(opts, \"DELETE\", `/${encodeURIComponent(kbId)}`);\n}\n\nexport async function reindexKnowledge(opts: KnowledgeApiOptions, kbId: string): Promise<void> {\n    await call<unknown>(opts, \"POST\", `/${encodeURIComponent(kbId)}/reindex`);\n}\n\n// ── Documents ────────────────────────────────────────────────────────────\n\n/**\n * Upsert one document. The server keys on `path`, so pushing the same path\n * twice updates the document instead of duplicating it — which is what lets a\n * consumer re-push a whole folder on every build.\n */\nexport async function pushDoc(\n    opts: KnowledgeApiOptions,\n    kbId: string,\n    doc: KnowledgeDocInput,\n): Promise<KnowledgeDoc> {\n    const data = await call<{ doc: KnowledgeDoc }>(\n        opts, \"POST\", `/${encodeURIComponent(kbId)}/docs`,\n        { path: doc.path, title: doc.title, text: doc.text },\n    );\n    return data.doc;\n}\n\n/**\n * Push a batch. One bad document does not lose the other forty: every entry\n * comes back with its own ok/error, in the order given.\n */\nexport async function pushDocs(\n    opts: KnowledgeApiOptions,\n    kbId: string,\n    docs: KnowledgeDocInput[],\n): Promise<PushResult[]> {\n    const results: PushResult[] = [];\n    for (const doc of docs) {\n        try {\n            results.push({ path: doc.path, ok: true, doc: await pushDoc(opts, kbId, doc) });\n        } catch (err) {\n            results.push({ path: doc.path, ok: false, error: err as Error });\n        }\n    }\n    return results;\n}\n\nexport async function getDoc(\n    opts: KnowledgeApiOptions,\n    kbId: string,\n    docId: string,\n): Promise<KnowledgeDocWithText> {\n    const data = await call<{ doc: KnowledgeDocWithText }>(\n        opts, \"GET\", `/${encodeURIComponent(kbId)}/docs/${encodeURIComponent(docId)}`,\n    );\n    return data.doc;\n}\n\nexport async function deleteDoc(\n    opts: KnowledgeApiOptions,\n    kbId: string,\n    docId: string,\n): Promise<void> {\n    await call<unknown>(opts, \"DELETE\", `/${encodeURIComponent(kbId)}/docs/${encodeURIComponent(docId)}`);\n}\n\n// ── Query ────────────────────────────────────────────────────────────────\n\n/** Retrieval only — the top `k` chunks, no LLM in the loop. */\nexport async function queryKnowledge(\n    opts: KnowledgeApiOptions,\n    kbId: string,\n    query: string,\n    o: { k?: number } = {},\n): Promise<KnowledgeHit[]> {\n    const data = await call<{ hits?: KnowledgeHit[] }>(\n        opts, \"POST\", `/${encodeURIComponent(kbId)}/query`,\n        { query, k: o.k ?? 6 },\n    );\n    return data.hits ?? [];\n}\n"],"mappings":"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","names":["DEFAULT_PLAYGROUND_URL","_handlers","_send","_timer","call","call","_send","_send","_agentId","call","reason","call","call","call","call","call","call","callId","call","_requester","call","call","call","call","call","call","msg","call","_call","speech","_opts","_sendRaw","_ended","call","_entries","i","data","field","readError","l","call","field","_ws","_pending","WS","_items","_error","abortError","send_fn","opts","call","DEFAULT_PLAYGROUND_URL","call"]}