{"version":3,"sources":["../../src/cli/console/transcript-reducer.ts","../../src/cli/console/calls-model.ts"],"names":["open"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Transcript reducer — the ONE event → conversation state machine.\n *\n * `pinecall run` has three observers of the same agent events: the terminal\n * live view (src/cli/live-view.ts), the console server's CallsModel\n * (src/cli/console/calls-model.ts) and the web console in the browser. They\n * must never disagree about what was said, so none of them owns the logic:\n * they all feed the store below and render what comes out.\n *\n *   store.feed(agentId, \"user.speaking\", [{ text }, call])\n *        │\n *        ├── updates the CallSnapshot (the state anybody can read)\n *        └── emits effects: \"a caller line was finalised\", \"the draft moved\",\n *            \"a tool ran\", \"the session ended\" — one per thing a renderer\n *            would draw, in the order it should draw them.\n *\n * The semantics are exactly the ones the terminal view shipped with:\n *\n *   - `user.speaking` is interim: it REPLACES the caller draft; `user.message`\n *     fixes it as a line.\n *   - on voice, `bot.speaking` may carry the whole reply up front but nothing\n *     is shown until `bot.word` plays it — the line is what has been HEARD.\n *   - chat and WhatsApp have no audio and no words, so there `bot.speaking` IS\n *     the line: chunks are coalesced as they stream and fixed after a short\n *     settle (or on the next event).\n *   - a session that never announced itself (`pinecall chat`, the MCP chat\n *     tool, any llm.chat client) gets an implicit context on its first event.\n *   - `bot.interrupted` closes the line with a cut marker.\n *\n * Dependency-free and side-effect-free at import time on purpose: the browser\n * console imports this very file through a Vite alias, so it must not reach\n * for node:*, for the SDK's Agent type, or for anything at module scope.\n * Timers are injectable for the same reason (and so tests can drive them).\n *\n * Importable as `@pinecall/sdk/console`, or by relative path from the repo.\n */\n\n// ── The state anybody can read ───────────────────────────────────────────\n\nexport type TranscriptChannel = \"phone\" | \"webrtc\" | \"chat\" | \"whatsapp\" | \"unknown\";\n\nexport type TranscriptState = \"ringing\" | \"listening\" | \"thinking\" | \"pause\" | \"speaking\" | \"ended\";\n\n/** One finalised thing in the conversation. */\nexport interface TranscriptLine {\n    who: \"caller\" | \"agent\" | \"tool\";\n    /** What was said — for a tool line, a short rendering of the call. */\n    text: string;\n    at: number;\n    final: boolean;\n    /** The agent was cut off mid-utterance (bot.interrupted). */\n    cut?: boolean;\n    tool?: { name: string; args?: unknown; result?: unknown };\n}\n\n/** A call/session as the console shows it. Plain JSON — it goes over HTTP as-is. */\nexport interface CallSnapshot {\n    id: string;\n    agent: string;\n    channel: TranscriptChannel;\n    direction?: string;\n    peer?: string;\n    startedAt: number;\n    endedAt?: number;\n    durationS?: number;\n    reason?: string;\n    state: TranscriptState;\n    lines: TranscriptLine[];\n    /** What is in flight right now: the caller's interim words, the agent's growing line. */\n    draft: { caller?: string; agent?: string };\n}\n\n/** The slice of a Call the reducer reads (matches the SDK's Call and the SSE payloads). */\nexport interface TranscriptCall {\n    id: string;\n    from?: string;\n    to?: string;\n    direction?: string;\n    transport?: string;\n    duration?: number;\n}\n\n// ── What a renderer is told ──────────────────────────────────────────────\n\nexport type TranscriptEffect =\n    | { kind: \"session.started\"; agent: string; call: CallSnapshot; implicit: boolean }\n    | { kind: \"session.ended\"; agent: string; call: CallSnapshot; reason: string; durationS: number }\n    | { kind: \"ringing\"; agent: string; from?: string; to?: string }\n    | { kind: \"caller.line\"; agent: string; call: CallSnapshot; text: string }\n    | { kind: \"agent.line\"; agent: string; call: CallSnapshot; text: string; cut: boolean }\n    | { kind: \"tool.call\"; agent: string; call?: CallSnapshot; name: string; args: unknown }\n    | { kind: \"tool.result\"; agent: string; call?: CallSnapshot; name?: string; result: unknown }\n    /** The draft or the turn state moved — redraw the live line / the open bubble. */\n    | { kind: \"draft\"; agent: string; call: CallSnapshot }\n    | { kind: \"wa.message\"; agent: string; who: string; text: string }\n    | { kind: \"wa.response\"; agent: string; text: string; source?: string };\n\n/** Every event the store subscribes to — one list, so no observer can drift. */\nexport const TRANSCRIPT_EVENTS = [\n    \"call.started\", \"call.ended\", \"call.ringing\",\n    \"chat.started\", \"whatsapp.started\",\n    \"speech.started\", \"user.speaking\", \"user.message\",\n    \"eager.turn\", \"turn.end\", \"turn.pause\", \"turn.resumed\", \"turn.continued\",\n    \"bot.speaking\", \"bot.word\", \"bot.finished\", \"bot.interrupted\",\n    \"llm.toolCall\",\n    \"whatsapp.message\", \"whatsapp.response\",\n] as const;\n\nexport type TranscriptEventName = (typeof TRANSCRIPT_EVENTS)[number];\n\n// ── Options and surface ──────────────────────────────────────────────────\n\nexport interface TranscriptTimers {\n    set(fn: () => void, ms: number): unknown;\n    clear(handle: unknown): void;\n}\n\nexport interface TranscriptStoreOptions {\n    /** Milliseconds clock — injectable for tests. Default Date.now. */\n    clock?: () => number;\n    /**\n     * How long a text reply (chat, or a session whose channel is unknown) waits\n     * for more chunks — or for `bot.word`s that would make it a voice line —\n     * before it is fixed as the agent line. Default 300 ms.\n     */\n    settleMs?: number;\n    /** How many ended sessions to keep. Default 50. */\n    keepEnded?: number;\n    /** setTimeout/clearTimeout, injectable so this module imports nothing. */\n    timers?: TranscriptTimers;\n}\n\n/** The slice of Agent the store subscribes to — structural, so no SDK import. */\nexport interface TranscriptEmitter {\n    id: string;\n    on(event: string, handler: (...args: any[]) => void): unknown;\n    off(event: string, handler: (...args: any[]) => void): unknown;\n}\n\nexport interface TranscriptStore {\n    /** Subscribe to an agent's events. Idempotent per id. Returns the matching detach. */\n    attach(agent: TranscriptEmitter): () => void;\n    /** Feed one agent event, with the handler's raw arguments. */\n    feed(agentId: string, name: string, args: unknown[]): void;\n    /**\n     * A tool returned. Tool results are not an event — the SDK auto-executes\n     * tools — so the runner's execute wrapper hands them in here.\n     */\n    toolResult(agentId: string, call: TranscriptCall | undefined, result: unknown): void;\n    /** Drop everything an agent owns (pending timers included). */\n    detach(agentId: string): void;\n    /** Subscribe to effects. Returns the unsubscribe. */\n    on(listener: (effect: TranscriptEffect) => void): () => void;\n    /** Sessions in flight, by id — insertion ordered. */\n    readonly live: ReadonlyMap<string, CallSnapshot>;\n    /** Live + the last `keepEnded` ended sessions, newest first. */\n    snapshots(): CallSnapshot[];\n    get(id: string): CallSnapshot | undefined;\n    /** Release every pending timer (process exit). */\n    dispose(): void;\n}\n\n// ── Internals kept off the snapshot (so it stays JSON the UI can eat) ────\n\ninterface Internal {\n    /** The bot line being built. null = no utterance in flight. */\n    bot: string | null;\n    /** Full text announced by bot.speaking (voice fallback when no words arrive). */\n    botAnnounced: string;\n    /** bot.word count of the utterance in flight — decides text vs voice when the channel is unknown. */\n    words: number;\n    /** Pending settle timer for a text reply (chat / unknown channel). */\n    settle: unknown;\n    /** Opened on the first event of a session that never sent call.started. */\n    implicit: boolean;\n    /** Everything the agent said this turn — a re-sent or cumulative bot.speaking must not print it twice. */\n    lastBot: string;\n    /** `event:messageId` pairs already applied — a re-sent wire/SSE frame must never produce a second bubble. */\n    applied: Set<string>;\n    /** `text -> ts` for messageId-less `user.message` (chat) — dedupes a re-sent frame within 2s. */\n    recentUserText: Map<string, number>;\n}\n\n/**\n * True (and records it) when (event, messageId) was already applied for this\n * call — belt-and-braces against a duplicated wire/SSE frame. A messageId-less\n * `user.message` (chat has none) falls back to callId+text within 2s.\n */\nfunction alreadyApplied(i: Internal, event: string, messageId: string, text: string, now: number): boolean {\n    if (messageId) {\n        const key = `${event}:${messageId}`;\n        if (i.applied.has(key)) return true;\n        i.applied.add(key);\n        return false;\n    }\n    if (event !== \"user.message\") return false;\n    const last = i.recentUserText.get(text);\n    if (last !== undefined && now - last < 2000) return true;\n    i.recentUserText.set(text, now);\n    return false;\n}\n\nconst DEFAULT_TIMERS: TranscriptTimers = {\n    set: (fn, ms) => setTimeout(fn, ms),\n    clear: (h) => clearTimeout(h as ReturnType<typeof setTimeout>),\n};\n\nexport function createTranscriptStore(opts: TranscriptStoreOptions = {}): TranscriptStore {\n    const clock = opts.clock ?? (() => Date.now());\n    const settleMs = opts.settleMs ?? 300;\n    const keepEnded = opts.keepEnded ?? 50;\n    const timers = opts.timers ?? DEFAULT_TIMERS;\n\n    const live = new Map<string, CallSnapshot>();\n    const internals = new Map<string, Internal>();\n    const ended: CallSnapshot[] = []; // newest first\n    const listeners = new Set<(effect: TranscriptEffect) => void>();\n\n    const emit = (effect: TranscriptEffect) => {\n        for (const l of listeners) l(effect);\n    };\n\n    const inner = (cs: CallSnapshot): Internal => internals.get(cs.id)!;\n\n    // ── Session lifecycle ────────────────────────────────────────────\n\n    function open(agentId: string, call: TranscriptCall, implicit: boolean): CallSnapshot {\n        const known = live.get(call.id);\n        if (known) return known;\n        const channel = toChannel(call.transport);\n        const cs: CallSnapshot = {\n            id: call.id,\n            agent: agentId,\n            channel,\n            direction: call.direction,\n            peer: implicit\n                ? call.from || undefined\n                : (call.direction === \"outbound\" ? call.to : call.from) || undefined,\n            startedAt: clock(),\n            state: \"listening\",\n            lines: [],\n            draft: {},\n        };\n        live.set(cs.id, cs);\n        internals.set(cs.id, {\n            bot: null, botAnnounced: \"\", words: 0, settle: null, implicit, lastBot: \"\",\n            applied: new Set(), recentUserText: new Map(),\n        });\n        emit({ kind: \"session.started\", agent: agentId, call: cs, implicit });\n        emit({ kind: \"draft\", agent: agentId, call: cs });\n        return cs;\n    }\n\n    /**\n     * The context an event belongs to — opened implicitly when the session never\n     * sent call.started / chat.started. Without a call object at all the\n     * context is per agent (one implicit session per agent at a time).\n     */\n    function contextFor(agentId: string, call: TranscriptCall | undefined): CallSnapshot {\n        const id = call?.id || `${agentId}:implicit`;\n        const known = live.get(id);\n        if (known) return known;\n        return open(agentId, {\n            id,\n            from: call?.from,\n            to: call?.to,\n            direction: call?.direction,\n            transport: call?.transport ?? \"unknown\",\n        }, true);\n    }\n\n    /** The known context of an event, or the agent's implicit session when the event carries no call. */\n    function lookup(agentId: string, call: TranscriptCall | undefined): CallSnapshot | undefined {\n        return call ? live.get(call.id) : live.get(`${agentId}:implicit`);\n    }\n\n    function close(agentId: string, call: TranscriptCall, reason: string): void {\n        const cs = live.get(call.id) ?? live.get(`${agentId}:implicit`);\n        if (!cs) return;\n        finishBot(cs);\n        cs.draft.caller = undefined;\n        cs.draft.agent = undefined;\n        const secs = call.duration && call.duration > 0 ? call.duration : (clock() - cs.startedAt) / 1000;\n        cs.endedAt = clock();\n        cs.durationS = secs;\n        cs.reason = reason;\n        cs.state = \"ended\";\n        live.delete(cs.id);\n        clearSettle(cs);\n        internals.delete(cs.id);\n        ended.unshift(cs);\n        while (ended.length > keepEnded) ended.pop();\n        emit({ kind: \"session.ended\", agent: agentId, call: cs, reason, durationS: secs });\n    }\n\n    // ── Lines and drafts ─────────────────────────────────────────────\n\n    function callerLine(cs: CallSnapshot, text: string): void {\n        cs.lines.push({ who: \"caller\", text, at: clock(), final: true });\n        emit({ kind: \"caller.line\", agent: cs.agent, call: cs, text });\n    }\n\n    function agentLine(cs: CallSnapshot, text: string, cut: boolean): void {\n        cs.lines.push({ who: \"agent\", text, at: clock(), final: true, ...(cut ? { cut: true } : {}) });\n        const i = inner(cs);\n        i.lastBot = i.lastBot ? `${i.lastBot}\\n${text}` : text;\n        emit({ kind: \"agent.line\", agent: cs.agent, call: cs, text, cut });\n    }\n\n    function refresh(cs: CallSnapshot): void {\n        const i = inner(cs);\n        cs.draft.agent = i.bot === null ? undefined : i.bot;\n        emit({ kind: \"draft\", agent: cs.agent, call: cs });\n    }\n\n    function setState(cs: CallSnapshot, state: TranscriptState): void {\n        cs.state = state;\n        refresh(cs);\n    }\n\n    /** Close the bot line in flight, if any. */\n    function finishBot(cs: CallSnapshot, cut = false): void {\n        clearSettle(cs);\n        const i = internals.get(cs.id);\n        if (!i || i.bot === null) return;\n        const text = i.bot || i.botAnnounced;\n        if (text) agentLine(cs, text, cut);\n        i.bot = null;\n        i.botAnnounced = \"\";\n        i.words = 0;\n        cs.draft.agent = undefined;\n    }\n\n    /** Text reply in flight: fix it once no more chunks (and no words) arrive for `settleMs`. */\n    function armSettle(cs: CallSnapshot): void {\n        clearSettle(cs);\n        const i = inner(cs);\n        i.settle = timers.set(() => {\n            const cur = internals.get(cs.id);\n            if (!cur) return;\n            cur.settle = null;\n            if (cur.bot === null || cur.words > 0) return;\n            finishBot(cs);\n            setState(cs, \"listening\");\n        }, settleMs);\n    }\n\n    function clearSettle(cs: CallSnapshot): void {\n        const i = internals.get(cs.id);\n        if (!i) return;\n        if (i.settle) timers.clear(i.settle);\n        i.settle = null;\n    }\n\n    const isTextual = (cs: CallSnapshot) =>\n        cs.channel === \"chat\" || cs.channel === \"whatsapp\" || cs.channel === \"unknown\";\n\n    // ── Feed ─────────────────────────────────────────────────────────\n\n    function feed(agentId: string, name: string, args: unknown[]): void {\n        const first = args[0] as any;\n        const second = args[1] as TranscriptCall | undefined;\n\n        switch (name) {\n            case \"call.started\":\n            case \"chat.started\":\n            case \"whatsapp.started\":\n                open(agentId, first as TranscriptCall, false);\n                return;\n\n            case \"call.ended\":\n                close(agentId, first as TranscriptCall, (args[1] as string) ?? \"\");\n                return;\n\n            case \"call.ringing\":\n                emit({ kind: \"ringing\", agent: agentId, from: first?.from, to: first?.to });\n                return;\n\n            case \"speech.started\": {\n                const cs = second ? live.get(second.id) : undefined;\n                if (cs && cs.state !== \"speaking\") setState(cs, \"listening\");\n                return;\n            }\n\n            case \"user.speaking\": {\n                const cs = second ? live.get(second.id) : undefined;\n                if (!cs) return;\n                cs.draft.caller = typeof first?.text === \"string\" ? first.text || undefined : undefined;\n                if (cs.state !== \"listening\") cs.state = \"listening\";\n                refresh(cs);\n                return;\n            }\n\n            case \"user.message\": {\n                const cs = contextFor(agentId, second);\n                const text = typeof first?.text === \"string\" ? first.text : \"\";\n                const messageId = typeof first?.messageId === \"string\" ? first.messageId : \"\";\n                if (alreadyApplied(inner(cs), \"user.message\", messageId, text, clock())) return;\n                // A text reply still open (chat / unknown channel): the user replied, so it is done.\n                if (isTextual(cs)) finishBot(cs);\n                cs.draft.caller = undefined;\n                inner(cs).lastBot = \"\";\n                if (text) callerLine(cs, text);\n                // Chat has no turn detector — the model starts right away.\n                if (isTextual(cs)) setState(cs, \"thinking\");\n                else refresh(cs);\n                return;\n            }\n\n            case \"eager.turn\":\n            case \"turn.end\": {\n                const cs = second ? live.get(second.id) : undefined;\n                if (cs) setState(cs, \"thinking\");\n                return;\n            }\n\n            case \"turn.pause\": {\n                const cs = second ? live.get(second.id) : undefined;\n                if (cs) setState(cs, \"pause\");\n                return;\n            }\n\n            case \"turn.resumed\":\n            case \"turn.continued\": {\n                const cs = second ? live.get(second.id) : undefined;\n                if (cs) setState(cs, \"listening\");\n                return;\n            }\n\n            case \"bot.speaking\": {\n                const cs = contextFor(agentId, second);\n                const i = inner(cs);\n                let text = typeof first?.text === \"string\" ? first.text : \"\";\n                if (isTextual(cs)) {\n                    // Chunks stream in; bot.speaking IS the line — fixed once they settle,\n                    // unless bot.words arrive and prove this is voice after all.\n                    if (i.words > 0) finishBot(cs); // a new utterance after a spoken one\n                    if (i.bot === null && i.lastBot) {\n                        // The server re-sent the reply already fixed (or the cumulative text\n                        // containing it): print nothing, or only what is new.\n                        if (i.lastBot.includes(text)) return;\n                        if (text.startsWith(i.lastBot)) text = text.slice(i.lastBot.length).replace(/^\\s+/, \"\");\n                        if (!text) return;\n                    }\n                    i.bot = mergeChunk(i.bot ?? \"\", text);\n                    i.words = 0;\n                    armSettle(cs);\n                } else {\n                    // A new utterance: close the previous one (no bot.finished arrived), start empty.\n                    if (i.bot !== null && cs.state === \"speaking\") finishBot(cs);\n                    i.bot = \"\";\n                    i.botAnnounced = text;\n                }\n                setState(cs, \"speaking\");\n                return;\n            }\n\n            case \"bot.word\": {\n                const cs = second ? live.get(second.id) : undefined;\n                if (!cs) return;\n                const i = inner(cs);\n                const word = typeof first?.word === \"string\" ? first.word : \"\";\n                if (i.bot === null) i.bot = \"\";\n                if (i.words === 0 && cs.channel === \"unknown\" && i.bot) {\n                    // Words are playing: the text announced up front is not the line, what is heard is.\n                    i.botAnnounced = i.bot;\n                    i.bot = \"\";\n                }\n                clearSettle(cs);\n                i.bot = appendWord(i.bot, word);\n                i.words += 1;\n                cs.state = \"speaking\";\n                refresh(cs);\n                return;\n            }\n\n            case \"bot.finished\": {\n                const cs = second ? live.get(second.id) : undefined;\n                if (!cs) return;\n                const messageId = typeof first?.messageId === \"string\" ? first.messageId : \"\";\n                if (messageId && alreadyApplied(inner(cs), \"bot.finished\", messageId, \"\", clock())) return;\n                finishBot(cs);\n                setState(cs, \"listening\");\n                return;\n            }\n\n            case \"bot.interrupted\": {\n                const cs = second ? live.get(second.id) : undefined;\n                if (!cs) return;\n                finishBot(cs, true);\n                setState(cs, \"listening\");\n                return;\n            }\n\n            case \"llm.toolCall\": {\n                const cs = lookup(agentId, second);\n                const items: Array<{ name?: string; arguments?: unknown }> =\n                    Array.isArray(first?.toolCalls) ? first.toolCalls : [];\n                for (const item of items) {\n                    const toolName = item.name || \"unknown\";\n                    const toolArgs = parseArgs(item.arguments);\n                    if (cs) {\n                        cs.lines.push({\n                            who: \"tool\", text: toolName, at: clock(), final: false,\n                            tool: { name: toolName, args: toolArgs },\n                        });\n                    }\n                    emit({ kind: \"tool.call\", agent: agentId, call: cs, name: toolName, args: toolArgs });\n                }\n                if (cs) setState(cs, \"thinking\");\n                return;\n            }\n\n            case \"whatsapp.message\": {\n                const who = String(first?.name || first?.from || \"whatsapp\");\n                const text = typeof first?.text === \"string\" ? first.text : \"\";\n                if (!text) return;\n                // WhatsApp events carry no call: the session (if it announced\n                // itself) collects the line, but the renderers draw the wa.*\n                // effect — never both.\n                waSession(agentId)?.lines.push({ who: \"caller\", text, at: clock(), final: true });\n                emit({ kind: \"wa.message\", agent: agentId, who, text });\n                return;\n            }\n\n            case \"whatsapp.response\": {\n                const text = typeof first?.text === \"string\" ? first.text : \"\";\n                if (!text) return;\n                waSession(agentId)?.lines.push({ who: \"agent\", text, at: clock(), final: true });\n                emit({ kind: \"wa.response\", agent: agentId, text, source: first?.source });\n                return;\n            }\n\n            default:\n                return;\n        }\n    }\n\n    /** The agent's open WhatsApp session, if it announced itself — WA events carry no call. */\n    function waSession(agentId: string): CallSnapshot | undefined {\n        for (const cs of live.values()) {\n            if (cs.agent === agentId && cs.channel === \"whatsapp\") return cs;\n        }\n        return undefined;\n    }\n\n    function toolResult(agentId: string, call: TranscriptCall | undefined, result: unknown): void {\n        const cs = lookup(agentId, call);\n        let name: string | undefined;\n        if (cs) {\n            // Attach to the newest tool line still waiting for its result.\n            for (let i = cs.lines.length - 1; i >= 0; i--) {\n                const line = cs.lines[i]!;\n                if (line.who === \"tool\" && !line.final) {\n                    line.final = true;\n                    line.tool = { ...line.tool!, result };\n                    name = line.tool.name;\n                    break;\n                }\n            }\n        }\n        emit({ kind: \"tool.result\", agent: agentId, call: cs, ...(name ? { name } : {}), result });\n    }\n\n    const subs = new Map<string, Array<[string, (...a: any[]) => void]>>();\n\n    function attach(agent: TranscriptEmitter): () => void {\n        if (subs.has(agent.id)) return () => detachAgent(agent);\n        const mine: Array<[string, (...a: any[]) => void]> = [];\n        for (const name of TRANSCRIPT_EVENTS) {\n            const handler = (...args: any[]) => feed(agent.id, name, args);\n            mine.push([name, handler]);\n            agent.on(name, handler);\n        }\n        subs.set(agent.id, mine);\n        return () => detachAgent(agent);\n    }\n\n    function detachAgent(agent: TranscriptEmitter): void {\n        const mine = subs.get(agent.id);\n        if (mine) {\n            for (const [name, handler] of mine) agent.off(name, handler);\n            subs.delete(agent.id);\n        }\n        detach(agent.id);\n    }\n\n    function detach(agentId: string): void {\n        for (const cs of [...live.values()]) {\n            if (cs.agent !== agentId) continue;\n            clearSettle(cs);\n        }\n    }\n\n    function dispose(): void {\n        for (const cs of live.values()) clearSettle(cs);\n        listeners.clear();\n    }\n\n    function snapshots(): CallSnapshot[] {\n        const open = [...live.values()].sort((a, b) => b.startedAt - a.startedAt);\n        return [...open, ...ended];\n    }\n\n    return {\n        attach,\n        feed,\n        toolResult,\n        detach,\n        on(listener) {\n            listeners.add(listener);\n            return () => listeners.delete(listener);\n        },\n        live,\n        snapshots,\n        get: (id) => live.get(id) ?? ended.find((c) => c.id === id),\n        dispose,\n    };\n}\n\n// ── Pure helpers (shared with the renderers) ─────────────────────────────\n\n/** Map the SDK's transport to the console's channel vocabulary. */\nexport function toChannel(transport: string | undefined): TranscriptChannel {\n    switch (transport) {\n        case \"phone\":\n        case \"webrtc\":\n        case \"chat\":\n        case \"whatsapp\":\n            return transport;\n        default:\n            return \"unknown\";\n    }\n}\n\n/** Merge a streamed chunk: servers send deltas (append) or the growing text so far (replace). */\nexport function mergeChunk(cur: string, text: string): string {\n    if (!cur) return text;\n    if (text.startsWith(cur)) return text;\n    return cur + text;\n}\n\n/** Append a spoken word with single-space joining. */\nexport function appendWord(line: string, word: string): string {\n    const w = word.trim();\n    if (!w) return line;\n    return line ? `${line} ${w}` : w;\n}\n\n/** Tool arguments arrive as a JSON string on the wire; older shapes may already be objects. */\nexport function parseArgs(args: unknown): unknown {\n    if (typeof args !== \"string\") return args ?? {};\n    if (!args.trim()) return {};\n    try {\n        return JSON.parse(args);\n    } catch {\n        return args;\n    }\n}\n","/**\n * CallsModel — the console's read model over the shared transcript store.\n *\n * The third observer of a `pinecall run` process (after the terminal live view\n * and anything the developer wires with `pc.stream()`): it holds no logic of\n * its own, it reads the SAME `TranscriptStore` the terminal renders from, so\n * `GET /api/calls` and the terminal can never disagree about what was said.\n *\n * What it adds on top of the store is only what HTTP needs: a newest-first\n * list capped at the live calls plus the last N ended ones, lookup by id, and\n * hanging a live call up through the agent that owns it.\n */\n\nimport type { CallSnapshot, TranscriptStore } from \"./transcript-reducer.js\";\n\n/** The slice of Agent the model needs — structural, so tests pass fakes. */\nexport interface CallsModelAgent {\n    id: string;\n    call(callId: string): { hangup(): void } | undefined;\n}\n\nexport interface CallsModelOptions {\n    store: TranscriptStore;\n    agents: ReadonlyMap<string, CallsModelAgent>;\n    /** Cap on the returned list (live + ended). Default 50. */\n    limit?: number;\n}\n\nexport interface CallsModel {\n    /** Live + recently ended sessions, newest first. */\n    list(): CallSnapshot[];\n    get(id: string): CallSnapshot | undefined;\n    /** End a live call. False when the id is unknown or already ended. */\n    hangup(id: string): boolean;\n}\n\nexport function createCallsModel(opts: CallsModelOptions): CallsModel {\n    const limit = opts.limit ?? 50;\n\n    return {\n        list() {\n            return opts.store.snapshots().slice(0, limit);\n        },\n        get(id) {\n            return opts.store.get(id);\n        },\n        hangup(id) {\n            const snapshot = opts.store.live.get(id);\n            if (!snapshot) return false;\n            const call = opts.agents.get(snapshot.agent)?.call(id);\n            if (!call) return false;\n            call.hangup();\n            return true;\n        },\n    };\n}\n"]}