{"version":3,"file":"realtime.mjs","names":[],"sources":["../../../../../../../../packages/ai-live/src/realtime/realtime.ts"],"sourcesContent":["import { generateRunId } from \"@warlock.js/ai\";\nimport type {\n  RealtimeOptions,\n  RealtimeReport,\n  RealtimeSession,\n} from \"../contracts/realtime.contract\";\n\n/**\n * Open a live duplex voice session — the stateful primitive of\n * `@warlock.js/ai-live`. Connects through the provided\n * {@link RealtimeOptions.transport} (an OpenAI Realtime WebSocket\n * adapter, a mock in tests), then hands back a {@link RealtimeSession}\n * you drive: push audio/text in, consume the event stream out, and\n * `close()` to end it and receive a `type: \"realtime\"` report for the\n * cost/observability surfaces.\n *\n * Unlike the one-shot `ai.*` verbs, this returns a long-lived session —\n * its closest sibling is `ai.orchestrator`. Keeping the transport\n * pluggable is what lets the session surface ship without hard-wiring a\n * WebSocket dependency.\n *\n * @example\n * const session = await ai.realtime({ transport, model: \"gpt-realtime\", voice: \"alloy\" });\n * session.sendAudio(micChunk, \"audio/pcm\");\n * for await (const event of session.events()) {\n *   if (event.type === \"audio\") speaker.write(event.base64);\n * }\n * const report = await session.close();\n */\nexport async function realtime(options: RealtimeOptions): Promise<RealtimeSession> {\n  const runId = generateRunId(\"realtime\");\n  const startedAt = new Date().toISOString();\n  const startPerf = performance.now();\n\n  const connection = await options.transport.connect({\n    model: options.model,\n    voice: options.voice,\n    instructions: options.instructions,\n  });\n\n  let report: RealtimeReport | undefined;\n\n  return {\n    sendAudio: (base64, mediaType) => connection.sendAudio(base64, mediaType),\n    sendText: (text) => connection.sendText(text),\n    events: () => connection.events(),\n    async close(): Promise<RealtimeReport> {\n      // Idempotent — closing twice returns the first report, never\n      // re-tears-down the connection.\n      if (report) {\n        return report;\n      }\n\n      await connection.close();\n\n      report = {\n        runId,\n        rootRunId: runId,\n        type: \"realtime\",\n        name: options.name ?? \"realtime\",\n        status: \"completed\",\n        startedAt,\n        endedAt: new Date().toISOString(),\n        duration: performance.now() - startPerf,\n        ...(options.sessionId ? { sessionId: options.sessionId } : {}),\n      };\n\n      return report;\n    },\n  };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AA6BA,eAAsB,SAAS,SAAoD;CACjF,MAAM,QAAQ,cAAc,UAAU;CACtC,MAAM,6BAAY,IAAI,KAAK,EAAC,CAAC,YAAY;CACzC,MAAM,YAAY,YAAY,IAAI;CAElC,MAAM,aAAa,MAAM,QAAQ,UAAU,QAAQ;EACjD,OAAO,QAAQ;EACf,OAAO,QAAQ;EACf,cAAc,QAAQ;CACxB,CAAC;CAED,IAAI;CAEJ,OAAO;EACL,YAAY,QAAQ,cAAc,WAAW,UAAU,QAAQ,SAAS;EACxE,WAAW,SAAS,WAAW,SAAS,IAAI;EAC5C,cAAc,WAAW,OAAO;EAChC,MAAM,QAAiC;GAGrC,IAAI,QACF,OAAO;GAGT,MAAM,WAAW,MAAM;GAEvB,SAAS;IACP;IACA,WAAW;IACX,MAAM;IACN,MAAM,QAAQ,QAAQ;IACtB,QAAQ;IACR;IACA,0BAAS,IAAI,KAAK,EAAC,CAAC,YAAY;IAChC,UAAU,YAAY,IAAI,IAAI;IAC9B,GAAI,QAAQ,YAAY,EAAE,WAAW,QAAQ,UAAU,IAAI,CAAC;GAC9D;GAEA,OAAO;EACT;CACF;AACF"}