@warlock.js/ai-live 5.30.0 → 5.32.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,18 @@ All notable changes to `@warlock.js/ai-live` are documented in this file.
4
4
 
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). `@warlock.js/*` packages are released in lockstep — every package shares the same version number, so a version below may list only the changes that affected this package.
6
6
 
7
+ ## 5.32.0 - 2026-10-18
8
+
9
+ ### Changed
10
+
11
+ - Pin the package development compiler to TypeScript 7.0.2 and use explicit Node types and source roots with supported module resolution.
12
+
13
+ ## 5.31.0 - 2026-10-18
14
+
15
+ ### Changed
16
+
17
+ - Lockstep release; package APIs are unchanged.
18
+
7
19
  ## 5.30.0 - 2026-10-16
8
20
 
9
21
  ### Changed
@@ -81,6 +93,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
81
93
  ### Changed
82
94
 
83
95
  - Lockstep release maintenance and dependency refresh.
96
+
84
97
  ## 5.20.0 - 2026-09-24
85
98
 
86
99
  ### Changed
package/README.md CHANGED
@@ -15,6 +15,7 @@ import "@warlock.js/ai-live"; // side-effect: lights up ai.realtime + ai.video
15
15
  ## What it gives you
16
16
 
17
17
  ### `ai.realtime(options)` — duplex realtime voice sessions
18
+
18
19
  A **stateful, bidirectional voice session** (OpenAI Realtime-class): stream
19
20
  microphone audio in, stream synthesized audio + transcripts + tool-calls out,
20
21
  with barge-in. Unlike every other `ai.*` verb (one-shot request → result), this
@@ -25,7 +26,7 @@ endpoint), push audio, and consume an async event stream until you `close()` it
25
26
 
26
27
  ```ts
27
28
  const session = await ai.realtime({
28
- transport: openAiRealtime({ apiKey }), // provider transport (own adapter)
29
+ transport: openAiRealtime({ apiKey }), // provider transport (own adapter)
29
30
  model: "gpt-realtime",
30
31
  voice: "alloy",
31
32
  instructions: "You are a friendly phone receptionist.",
@@ -40,6 +41,7 @@ const report = await session.close();
40
41
  ```
41
42
 
42
43
  ### `ai.video(params)` — text-to-video generation
44
+
43
45
  Prompt → video (Sora / Veo / Kling-class). Generation is **async** (submit →
44
46
  poll), but the adapter hides the polling, so the verb returns the same uniform
45
47
  never-throws `{ data, error, usage, report }` envelope as `ai.image`, with
@@ -60,8 +62,8 @@ if (!error) download(data.video); // { type: "url" | "base64", ... }
60
62
  - **Heavy / optional deps.** Realtime needs a WebSocket transport (`ws` is an
61
63
  optional peer); video pulls long-poll + large-payload handling. Most apps
62
64
  using text/image/speech shouldn't carry that weight.
63
- - **Different shape.** `ai.realtime` is a *session*, not a request; `ai.video`
64
- is a *long job*. Isolating them keeps the core verbs simple and synchronous.
65
+ - **Different shape.** `ai.realtime` is a _session_, not a request; `ai.video`
66
+ is a _long job_. Isolating them keeps the core verbs simple and synchronous.
65
67
  - **Same contracts.** Both still produce a `BaseReport` (`type: "realtime"` /
66
68
  `"video"`) and route through the shared `observe` seam, so panoptic and the
67
69
  cost tree pick them up for free.
package/cjs/index.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["AIError","ProviderError","REPORT_SCHEMA_VERSION"],"sources":["../../../../../../../packages/ai-live/src/realtime/realtime.ts","../../../../../../../packages/ai-live/src/video/video.ts","../../../../../../../packages/ai-live/src/mock/index.ts","../../../../../../../packages/ai-live/src/index.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","import {\n AIError,\n computeCost,\n generateRunId,\n ProviderError,\n REPORT_SCHEMA_VERSION,\n resolveObservers,\n stampReportLineage,\n type BaseReport,\n type ExecuteResult,\n type FlowObserveOption,\n type ModelPricing,\n type Usage,\n} from \"@warlock.js/ai\";\nimport type {\n GeneratedVideo,\n VideoModelContract,\n VideoModelPricing,\n} from \"../contracts/video.contract\";\n\n/** Parameters for {@link video}. `model` comes from an adapter's `video({ name })`. */\nexport type VideoParams = {\n model: VideoModelContract;\n prompt: string;\n durationSeconds?: number;\n aspectRatio?: string;\n resolution?: string;\n negativePrompt?: string;\n signal?: AbortSignal;\n observe?: FlowObserveOption;\n sessionId?: string;\n name?: string;\n options?: Record<string, unknown>;\n};\n\n/** Success payload of a {@link video} run. */\nexport type VideoData = { video: GeneratedVideo };\n\n/** The report node a {@link video} run produces (`type: \"video\"`). */\nexport type VideoReport = BaseReport & {\n type: \"video\";\n model: { name: string; provider: string };\n /** Final clip duration in seconds, when reported. */\n durationSeconds?: number;\n};\n\n/** Result envelope of {@link video} — the uniform `{ data, error, usage, report }`. */\nexport type VideoResult = ExecuteResult<VideoData> & { type: \"video\"; report: VideoReport };\n\n/**\n * Generate a video from a text prompt — the moving-image verb of the\n * output-modality track. The adapter hides the provider's submit→poll\n * job, so this returns the framework's uniform never-throws envelope:\n *\n * - **Never throws.** Provider failures surface as a typed `AIError`.\n * - **Cost-truth.** `usage.cost` is filled per-second (Sora / Veo) or\n * per-token, folding into the same `Usage.cost` rollup as everything else.\n * - **Observable.** The completed {@link VideoReport} routes to any\n * registered `Observer` via the shared `observe` seam.\n *\n * @example\n * const { data, error } = await ai.video({\n * model: sora.video({ name: \"sora-2\", pricing: { perSecond: 0.1 } }),\n * prompt: \"a timelapse of a city skyline at dusk, cinematic\",\n * durationSeconds: 8,\n * });\n * if (!error) download(data.video);\n */\nexport async function video(params: VideoParams): Promise<VideoResult> {\n const { model, prompt } = params;\n\n const runId = generateRunId(\"video\");\n const startedAt = new Date().toISOString();\n const startPerf = performance.now();\n\n const usage: Usage = { input: 0, output: 0, total: 0 };\n let data: VideoData | undefined;\n let error: AIError | undefined;\n let status: VideoReport[\"status\"] = \"completed\";\n let durationSeconds: number | undefined;\n\n try {\n const response = await model.generate(prompt, {\n durationSeconds: params.durationSeconds,\n aspectRatio: params.aspectRatio,\n resolution: params.resolution,\n negativePrompt: params.negativePrompt,\n signal: params.signal,\n ...params.options,\n });\n\n Object.assign(usage, response.usage);\n durationSeconds = response.durationSeconds;\n\n if (usage.cost === undefined) {\n const cost = computeVideoCost(usage, durationSeconds, model.pricing);\n if (cost !== undefined) {\n usage.cost = cost;\n }\n }\n\n data = { video: response.video };\n } catch (thrown) {\n error =\n thrown instanceof AIError ? thrown : new ProviderError(toMessage(thrown), { cause: thrown });\n status = params.signal?.aborted ? \"cancelled\" : \"failed\";\n }\n\n const report: VideoReport = {\n runId,\n rootRunId: runId,\n name: params.name ?? \"video\",\n type: \"video\",\n status,\n error,\n startedAt,\n endedAt: new Date().toISOString(),\n duration: performance.now() - startPerf,\n usage,\n children: [],\n model: { name: model.name, provider: model.provider },\n ...(durationSeconds !== undefined ? { durationSeconds } : {}),\n reportSchemaVersion: REPORT_SCHEMA_VERSION,\n };\n\n stampReportLineage(report, { rootRunId: runId, sessionId: params.sessionId });\n\n for (const observer of resolveObservers(params.observe)) {\n try {\n await observer.collect(report);\n } catch {\n // Isolate observer failures — never break the run.\n }\n }\n\n return { type: \"video\", data, error, usage, report };\n}\n\n/**\n * Price a video run: `perSecond × durationSeconds` (per-second metering,\n * attributed to `cost.output`) wins when configured, otherwise the\n * standard token math. Returns `undefined` when no usable pricing is\n * present.\n */\nfunction computeVideoCost(\n usage: Usage,\n durationSeconds: number | undefined,\n pricing: VideoModelPricing | undefined,\n): ModelPricing | undefined {\n if (!pricing) {\n return undefined;\n }\n\n if (pricing.perSecond !== undefined) {\n if (durationSeconds === undefined) {\n return undefined;\n }\n return { input: 0, output: durationSeconds * pricing.perSecond };\n }\n\n if (pricing.input !== undefined && pricing.output !== undefined) {\n return computeCost(usage, { input: pricing.input, output: pricing.output });\n }\n\n return undefined;\n}\n\n/** Best-effort message for a non-`AIError` thrown value. */\nfunction toMessage(thrown: unknown): string {\n return thrown instanceof Error ? thrown.message : String(thrown);\n}\n","import type { Usage } from \"@warlock.js/ai\";\nimport type {\n RealtimeConnectConfig,\n RealtimeConnection,\n RealtimeEvent,\n RealtimeTransport,\n} from \"../contracts/realtime.contract\";\nimport type {\n GeneratedVideo,\n VideoGenerationResponse,\n VideoModelContract,\n VideoModelPricing,\n VideoOptions,\n} from \"../contracts/video.contract\";\n\n/** One scripted response for a {@link MockVideoModel}. */\nexport type MockVideoResponse = {\n video?: GeneratedVideo;\n usage?: Usage;\n durationSeconds?: number;\n error?: Error;\n};\n\n/** Deterministic {@link VideoModelContract} double for tests — no HTTP, no polling. */\nexport class MockVideoModel implements VideoModelContract {\n public readonly provider = \"mock\";\n public readonly calls: { prompt: string; options: VideoOptions | undefined }[] = [];\n\n private callIndex = 0;\n\n public constructor(\n public readonly name: string,\n private readonly responses: MockVideoResponse[],\n public readonly pricing?: VideoModelPricing,\n ) {}\n\n public async generate(\n prompt: string,\n options?: VideoOptions,\n ): Promise<VideoGenerationResponse> {\n this.calls.push({ prompt, options });\n\n const response = this.responses[Math.min(this.callIndex, this.responses.length - 1)] ?? {};\n this.callIndex += 1;\n\n if (response.error) {\n throw response.error;\n }\n\n return {\n video: response.video ?? { type: \"url\", url: \"https://mock/video.mp4\", mediaType: \"video/mp4\" },\n usage: response.usage ?? { input: 0, output: 0, total: 0 },\n durationSeconds: response.durationSeconds ?? options?.durationSeconds ?? 5,\n };\n }\n}\n\n/** A recording {@link RealtimeConnection} the mock transport hands back. */\nexport class MockRealtimeConnection implements RealtimeConnection {\n public readonly sentAudio: { base64: string; mediaType: string }[] = [];\n public readonly sentText: string[] = [];\n public closed = false;\n\n public constructor(private readonly scripted: RealtimeEvent[]) {}\n\n public sendAudio(base64: string, mediaType: string): void {\n this.sentAudio.push({ base64, mediaType });\n }\n\n public sendText(text: string): void {\n this.sentText.push(text);\n }\n\n public async *events(): AsyncIterable<RealtimeEvent> {\n for (const event of this.scripted) {\n yield event;\n }\n }\n\n public async close(): Promise<void> {\n this.closed = true;\n }\n}\n\n/** Deterministic {@link RealtimeTransport} double — scripts the event stream, records sends. */\nexport class MockRealtimeTransport implements RealtimeTransport {\n public readonly connectConfigs: RealtimeConnectConfig[] = [];\n public lastConnection?: MockRealtimeConnection;\n\n public constructor(private readonly scriptedEvents: RealtimeEvent[] = []) {}\n\n public async connect(config: RealtimeConnectConfig): Promise<RealtimeConnection> {\n this.connectConfigs.push(config);\n this.lastConnection = new MockRealtimeConnection(this.scriptedEvents);\n return this.lastConnection;\n }\n}\n","import { ai } from \"@warlock.js/ai\";\nimport { realtime } from \"./realtime/realtime\";\nimport { video } from \"./video/video\";\n\n/**\n * Augment the shared `Ai` facade with this package's two heavy\n * modalities. Importing `@warlock.js/ai-live` mounts `ai.video` +\n * `ai.realtime` as a side effect, mirroring how `@warlock.js/ai-tools`\n * mounts `ai.mcp` / `ai.tools` and `@warlock.js/ai-workspace` mounts\n * `ai.workspace`.\n */\ndeclare module \"@warlock.js/ai\" {\n interface Ai {\n /**\n * Text-to-video generation (Sora / Veo / Kling-class). Async under\n * the hood (submit→poll), surfaced as the uniform never-throws\n * `{ data, error, usage, report }` envelope. Ships in `@warlock.js/ai-live`.\n */\n video: typeof video;\n /**\n * Live duplex voice sessions (OpenAI Realtime-class). A stateful\n * session over a pluggable transport — push audio/text in, consume\n * events out, `close()` for a report. Ships in `@warlock.js/ai-live`.\n */\n realtime: typeof realtime;\n }\n}\n\nai.video = video;\nai.realtime = realtime;\n\nexport { realtime, video };\nexport type { VideoData, VideoParams, VideoReport, VideoResult } from \"./video/video\";\nexport * from \"./contracts/video.contract\";\nexport * from \"./contracts/realtime.contract\";\nexport * from \"./mock\";\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":["generateRunId","generateRunId","AIError","ProviderError","REPORT_SCHEMA_VERSION","resolveObservers","computeCost"],"sources":["../../../../../../../packages/ai-live/src/realtime/realtime.ts","../../../../../../../packages/ai-live/src/video/video.ts","../../../../../../../packages/ai-live/src/mock/index.ts","../../../../../../../packages/ai-live/src/index.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","import {\n AIError,\n computeCost,\n generateRunId,\n ProviderError,\n REPORT_SCHEMA_VERSION,\n resolveObservers,\n stampReportLineage,\n type BaseReport,\n type ExecuteResult,\n type FlowObserveOption,\n type ModelPricing,\n type Usage,\n} from \"@warlock.js/ai\";\nimport type {\n GeneratedVideo,\n VideoModelContract,\n VideoModelPricing,\n} from \"../contracts/video.contract\";\n\n/** Parameters for {@link video}. `model` comes from an adapter's `video({ name })`. */\nexport type VideoParams = {\n model: VideoModelContract;\n prompt: string;\n durationSeconds?: number;\n aspectRatio?: string;\n resolution?: string;\n negativePrompt?: string;\n signal?: AbortSignal;\n observe?: FlowObserveOption;\n sessionId?: string;\n name?: string;\n options?: Record<string, unknown>;\n};\n\n/** Success payload of a {@link video} run. */\nexport type VideoData = { video: GeneratedVideo };\n\n/** The report node a {@link video} run produces (`type: \"video\"`). */\nexport type VideoReport = BaseReport & {\n type: \"video\";\n model: { name: string; provider: string };\n /** Final clip duration in seconds, when reported. */\n durationSeconds?: number;\n};\n\n/** Result envelope of {@link video} — the uniform `{ data, error, usage, report }`. */\nexport type VideoResult = ExecuteResult<VideoData> & { type: \"video\"; report: VideoReport };\n\n/**\n * Generate a video from a text prompt — the moving-image verb of the\n * output-modality track. The adapter hides the provider's submit→poll\n * job, so this returns the framework's uniform never-throws envelope:\n *\n * - **Never throws.** Provider failures surface as a typed `AIError`.\n * - **Cost-truth.** `usage.cost` is filled per-second (Sora / Veo) or\n * per-token, folding into the same `Usage.cost` rollup as everything else.\n * - **Observable.** The completed {@link VideoReport} routes to any\n * registered `Observer` via the shared `observe` seam.\n *\n * @example\n * const { data, error } = await ai.video({\n * model: sora.video({ name: \"sora-2\", pricing: { perSecond: 0.1 } }),\n * prompt: \"a timelapse of a city skyline at dusk, cinematic\",\n * durationSeconds: 8,\n * });\n * if (!error) download(data.video);\n */\nexport async function video(params: VideoParams): Promise<VideoResult> {\n const { model, prompt } = params;\n\n const runId = generateRunId(\"video\");\n const startedAt = new Date().toISOString();\n const startPerf = performance.now();\n\n const usage: Usage = { input: 0, output: 0, total: 0 };\n let data: VideoData | undefined;\n let error: AIError | undefined;\n let status: VideoReport[\"status\"] = \"completed\";\n let durationSeconds: number | undefined;\n\n try {\n const response = await model.generate(prompt, {\n durationSeconds: params.durationSeconds,\n aspectRatio: params.aspectRatio,\n resolution: params.resolution,\n negativePrompt: params.negativePrompt,\n signal: params.signal,\n ...params.options,\n });\n\n Object.assign(usage, response.usage);\n durationSeconds = response.durationSeconds;\n\n if (usage.cost === undefined) {\n const cost = computeVideoCost(usage, durationSeconds, model.pricing);\n if (cost !== undefined) {\n usage.cost = cost;\n }\n }\n\n data = { video: response.video };\n } catch (thrown) {\n error =\n thrown instanceof AIError ? thrown : new ProviderError(toMessage(thrown), { cause: thrown });\n status = params.signal?.aborted ? \"cancelled\" : \"failed\";\n }\n\n const report: VideoReport = {\n runId,\n rootRunId: runId,\n name: params.name ?? \"video\",\n type: \"video\",\n status,\n error,\n startedAt,\n endedAt: new Date().toISOString(),\n duration: performance.now() - startPerf,\n usage,\n children: [],\n model: { name: model.name, provider: model.provider },\n ...(durationSeconds !== undefined ? { durationSeconds } : {}),\n reportSchemaVersion: REPORT_SCHEMA_VERSION,\n };\n\n stampReportLineage(report, { rootRunId: runId, sessionId: params.sessionId });\n\n for (const observer of resolveObservers(params.observe)) {\n try {\n await observer.collect(report);\n } catch {\n // Isolate observer failures — never break the run.\n }\n }\n\n return { type: \"video\", data, error, usage, report };\n}\n\n/**\n * Price a video run: `perSecond × durationSeconds` (per-second metering,\n * attributed to `cost.output`) wins when configured, otherwise the\n * standard token math. Returns `undefined` when no usable pricing is\n * present.\n */\nfunction computeVideoCost(\n usage: Usage,\n durationSeconds: number | undefined,\n pricing: VideoModelPricing | undefined,\n): ModelPricing | undefined {\n if (!pricing) {\n return undefined;\n }\n\n if (pricing.perSecond !== undefined) {\n if (durationSeconds === undefined) {\n return undefined;\n }\n return { input: 0, output: durationSeconds * pricing.perSecond };\n }\n\n if (pricing.input !== undefined && pricing.output !== undefined) {\n return computeCost(usage, { input: pricing.input, output: pricing.output });\n }\n\n return undefined;\n}\n\n/** Best-effort message for a non-`AIError` thrown value. */\nfunction toMessage(thrown: unknown): string {\n return thrown instanceof Error ? thrown.message : String(thrown);\n}\n","import type { Usage } from \"@warlock.js/ai\";\nimport type {\n RealtimeConnectConfig,\n RealtimeConnection,\n RealtimeEvent,\n RealtimeTransport,\n} from \"../contracts/realtime.contract\";\nimport type {\n GeneratedVideo,\n VideoGenerationResponse,\n VideoModelContract,\n VideoModelPricing,\n VideoOptions,\n} from \"../contracts/video.contract\";\n\n/** One scripted response for a {@link MockVideoModel}. */\nexport type MockVideoResponse = {\n video?: GeneratedVideo;\n usage?: Usage;\n durationSeconds?: number;\n error?: Error;\n};\n\n/** Deterministic {@link VideoModelContract} double for tests — no HTTP, no polling. */\nexport class MockVideoModel implements VideoModelContract {\n public readonly provider = \"mock\";\n public readonly calls: { prompt: string; options: VideoOptions | undefined }[] = [];\n\n private callIndex = 0;\n\n public constructor(\n public readonly name: string,\n private readonly responses: MockVideoResponse[],\n public readonly pricing?: VideoModelPricing,\n ) {}\n\n public async generate(prompt: string, options?: VideoOptions): Promise<VideoGenerationResponse> {\n this.calls.push({ prompt, options });\n\n const response = this.responses[Math.min(this.callIndex, this.responses.length - 1)] ?? {};\n this.callIndex += 1;\n\n if (response.error) {\n throw response.error;\n }\n\n return {\n video: response.video ?? {\n type: \"url\",\n url: \"https://mock/video.mp4\",\n mediaType: \"video/mp4\",\n },\n usage: response.usage ?? { input: 0, output: 0, total: 0 },\n durationSeconds: response.durationSeconds ?? options?.durationSeconds ?? 5,\n };\n }\n}\n\n/** A recording {@link RealtimeConnection} the mock transport hands back. */\nexport class MockRealtimeConnection implements RealtimeConnection {\n public readonly sentAudio: { base64: string; mediaType: string }[] = [];\n public readonly sentText: string[] = [];\n public closed = false;\n\n public constructor(private readonly scripted: RealtimeEvent[]) {}\n\n public sendAudio(base64: string, mediaType: string): void {\n this.sentAudio.push({ base64, mediaType });\n }\n\n public sendText(text: string): void {\n this.sentText.push(text);\n }\n\n public async *events(): AsyncIterable<RealtimeEvent> {\n for (const event of this.scripted) {\n yield event;\n }\n }\n\n public async close(): Promise<void> {\n this.closed = true;\n }\n}\n\n/** Deterministic {@link RealtimeTransport} double — scripts the event stream, records sends. */\nexport class MockRealtimeTransport implements RealtimeTransport {\n public readonly connectConfigs: RealtimeConnectConfig[] = [];\n public lastConnection?: MockRealtimeConnection;\n\n public constructor(private readonly scriptedEvents: RealtimeEvent[] = []) {}\n\n public async connect(config: RealtimeConnectConfig): Promise<RealtimeConnection> {\n this.connectConfigs.push(config);\n this.lastConnection = new MockRealtimeConnection(this.scriptedEvents);\n return this.lastConnection;\n }\n}\n","import { ai } from \"@warlock.js/ai\";\nimport { realtime } from \"./realtime/realtime\";\nimport { video } from \"./video/video\";\n\n/**\n * Augment the shared `Ai` facade with this package's two heavy\n * modalities. Importing `@warlock.js/ai-live` mounts `ai.video` +\n * `ai.realtime` as a side effect, mirroring how `@warlock.js/ai-tools`\n * mounts `ai.mcp` / `ai.tools` and `@warlock.js/ai-workspace` mounts\n * `ai.workspace`.\n */\ndeclare module \"@warlock.js/ai\" {\n interface Ai {\n /**\n * Text-to-video generation (Sora / Veo / Kling-class). Async under\n * the hood (submit→poll), surfaced as the uniform never-throws\n * `{ data, error, usage, report }` envelope. Ships in `@warlock.js/ai-live`.\n */\n video: typeof video;\n /**\n * Live duplex voice sessions (OpenAI Realtime-class). A stateful\n * session over a pluggable transport — push audio/text in, consume\n * events out, `close()` for a report. Ships in `@warlock.js/ai-live`.\n */\n realtime: typeof realtime;\n }\n}\n\nai.video = video;\nai.realtime = realtime;\n\nexport { realtime, video };\nexport type { VideoData, VideoParams, VideoReport, VideoResult } from \"./video/video\";\nexport * from \"./contracts/video.contract\";\nexport * from \"./contracts/realtime.contract\";\nexport * from \"./mock\";\n"],"mappings":"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"}
@@ -1,5 +1,4 @@
1
1
  import { AIError } from "@warlock.js/ai";
2
-
3
2
  //#region ../../packages/ai-live/src/contracts/realtime.contract.d.ts
4
3
  /**
5
4
  * One event streamed out of a realtime voice session. A closed union so
@@ -11,7 +10,7 @@ import { AIError } from "@warlock.js/ai";
11
10
  * - `error` — a typed, non-fatal provider/transport error.
12
11
  * - `done` — the session ended (server-side).
13
12
  */
14
- type RealtimeEvent = {
13
+ export type RealtimeEvent = {
15
14
  type: "audio";
16
15
  base64: string;
17
16
  mediaType: string;
@@ -32,9 +31,12 @@ type RealtimeEvent = {
32
31
  type: "done";
33
32
  };
34
33
  /** Config a {@link RealtimeTransport} needs to open a connection. */
35
- type RealtimeConnectConfig = {
36
- /** Realtime model id (e.g. `"gpt-realtime"`). */model: string; /** Default voice. */
37
- voice?: string; /** System instructions for the session. */
34
+ export type RealtimeConnectConfig = {
35
+ /** Realtime model id (e.g. `"gpt-realtime"`). */
36
+ model: string;
37
+ /** Default voice. */
38
+ voice?: string;
39
+ /** System instructions for the session. */
38
40
  instructions?: string;
39
41
  };
40
42
  /**
@@ -44,7 +46,7 @@ type RealtimeConnectConfig = {
44
46
  * mock transport drives the tests. Keeping this pluggable is what lets
45
47
  * `ai-live` ship the session surface without hard-wiring `ws`.
46
48
  */
47
- interface RealtimeConnection {
49
+ export interface RealtimeConnection {
48
50
  /** Push a chunk of microphone audio (base64) upstream. */
49
51
  sendAudio(base64: string, mediaType: string): void;
50
52
  /** Push a text message upstream (the model can reply with audio). */
@@ -55,16 +57,22 @@ interface RealtimeConnection {
55
57
  close(): Promise<void>;
56
58
  }
57
59
  /** Opens a {@link RealtimeConnection}. Implemented per provider. */
58
- interface RealtimeTransport {
60
+ export interface RealtimeTransport {
59
61
  connect(config: RealtimeConnectConfig): Promise<RealtimeConnection>;
60
62
  }
61
63
  /** Options for {@link ai.realtime}. */
62
- type RealtimeOptions = {
63
- /** The provider transport (e.g. an OpenAI Realtime WebSocket adapter). */transport: RealtimeTransport; /** Realtime model id. */
64
- model: string; /** Default voice. */
65
- voice?: string; /** System instructions for the session. */
66
- instructions?: string; /** Groups this session into a wider request for cost/trace queries. */
67
- sessionId?: string; /** Report node name (defaults to `"realtime"`). */
64
+ export type RealtimeOptions = {
65
+ /** The provider transport (e.g. an OpenAI Realtime WebSocket adapter). */
66
+ transport: RealtimeTransport;
67
+ /** Realtime model id. */
68
+ model: string;
69
+ /** Default voice. */
70
+ voice?: string;
71
+ /** System instructions for the session. */
72
+ instructions?: string;
73
+ /** Groups this session into a wider request for cost/trace queries. */
74
+ sessionId?: string;
75
+ /** Report node name (defaults to `"realtime"`). */
68
76
  name?: string;
69
77
  };
70
78
  /**
@@ -73,7 +81,7 @@ type RealtimeOptions = {
73
81
  * `close()` to end the session and get a report for cost + observability.
74
82
  * Its closest sibling is `ai.orchestrator` (a session, not a one-shot).
75
83
  */
76
- interface RealtimeSession {
84
+ export interface RealtimeSession {
77
85
  /** Push microphone audio (base64) into the session. */
78
86
  sendAudio(base64: string, mediaType: string): void;
79
87
  /** Push a text turn into the session. */
@@ -88,7 +96,7 @@ interface RealtimeSession {
88
96
  * `type: "realtime"` node for the trace/cost surfaces. (Realtime usage
89
97
  * accounting is provider-dependent and refined as transports land.)
90
98
  */
91
- type RealtimeReport = {
99
+ export type RealtimeReport = {
92
100
  runId: string;
93
101
  rootRunId: string;
94
102
  type: "realtime";
@@ -100,5 +108,4 @@ type RealtimeReport = {
100
108
  sessionId?: string;
101
109
  };
102
110
  //#endregion
103
- export { RealtimeConnectConfig, RealtimeConnection, RealtimeEvent, RealtimeOptions, RealtimeReport, RealtimeSession, RealtimeTransport };
104
111
  //# sourceMappingURL=realtime.contract.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"realtime.contract.d.mts","names":[],"sources":["../../../../../../../../packages/ai-live/src/contracts/realtime.contract.ts"],"mappings":";;;;;AAYA;;;;;;;;KAAY,aAAA;EACN,IAAA;EAAe,MAAA;EAAgB,SAAA;AAAA;EAC/B,IAAA;EAAoB,IAAA;EAA4B,IAAA;EAAc,KAAA;AAAA;EAC9D,IAAA;EAAmB,EAAA;EAAY,IAAA;EAAc,KAAA;AAAA;EAC7C,IAAA;EAAe,KAAA,EAAO,OAAO;AAAA;EAC7B,IAAA;AAAA;;KAGM,qBAAA;EAgBK,iDAdf,KAAA;EAEA,KAAA,WAkBU;EAhBV,YAAA;AAAA;;;;;;;;UAUe,kBAAA;EAMS;EAJxB,SAAA,CAAU,MAAA,UAAgB,SAAA;EAMjB;EAJT,QAAA,CAAS,IAAA;EAIO;EAFhB,MAAA,IAAU,aAAA,CAAc,aAAA;EAMQ;EAJhC,KAAA,IAAS,OAAA;AAAA;;UAIM,iBAAA;EACf,OAAA,CAAQ,MAAA,EAAQ,qBAAA,GAAwB,OAAA,CAAQ,kBAAA;AAAA;;KAItC,eAAA;EAJF,0EAMR,SAAA,EAAW,iBAAiB,EANoB;EAQhD,KAAA,UARkE;EAUlE,KAAA,WANyB;EAQzB,YAAA,WAN4B;EAQ5B,SAAA,WARW;EAUX,IAAA;AAAA;;;;;AAAI;AASN;UAAiB,eAAA;;EAEf,SAAA,CAAU,MAAA,UAAgB,SAAA;EAIhB;EAFV,QAAA,CAAS,IAAA;EAIA;EAFT,MAAA,IAAU,aAAA,CAAc,aAAA;EAER;EAAhB,KAAA,IAAS,OAAA,CAAQ,cAAA;AAAA;;;;;;KAQP,cAAA;EACV,KAAA;EACA,SAAA;EACA,IAAA;EACA,IAAA;EACA,MAAA;EACA,SAAA;EACA,OAAA;EACA,QAAA;EACA,SAAA;AAAA"}
1
+ {"version":3,"file":"realtime.contract.d.mts","names":[],"sources":["../../../../../../../../packages/ai-live/src/contracts/realtime.contract.ts"],"mappings":";;;;;;;;;;;;YAYY;EACN;EAAe;EAAgB;;EAC/B;EAAoB;EAA4B;EAAc;;EAC9D;EAAmB;EAAY;EAAc;;EAC7C;EAAe,OAAO;;EACtB;;;YAGM;;EAEV;;EAEA;;EAEA;;;;;;;;;iBAUe;;EAEf,UAAU,gBAAgB;;EAE1B,SAAS;;EAET,UAAU,cAAc;;EAExB,SAAS;;;iBAIM;EACf,QAAQ,QAAQ,wBAAwB,QAAQ;;;YAItC;;EAEV,WAAW;;EAEX;;EAEA;;EAEA;;EAEA;;EAEA;;;;;;;;iBASe;;EAEf,UAAU,gBAAgB;;EAE1B,SAAS;;EAET,UAAU,cAAc;;EAExB,SAAS,QAAQ;;;;;;;YAQP;EACV;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA"}
@@ -1,5 +1,4 @@
1
1
  import { Usage } from "@warlock.js/ai";
2
-
3
2
  //#region ../../packages/ai-live/src/contracts/video.contract.d.ts
4
3
  /**
5
4
  * USD pricing for a text-to-video model. Video providers meter per
@@ -10,9 +9,12 @@ import { Usage } from "@warlock.js/ai";
10
9
  * @example
11
10
  * const pricing: VideoModelPricing = { perSecond: 0.1 };
12
11
  */
13
- type VideoModelPricing = {
14
- /** USD per second of generated video — per-second-metered models. */perSecond?: number; /** USD per 1M input tokens — token-metered models. */
15
- input?: number; /** USD per 1M output tokens — token-metered models. */
12
+ export type VideoModelPricing = {
13
+ /** USD per second of generated video — per-second-metered models. */
14
+ perSecond?: number;
15
+ /** USD per 1M input tokens — token-metered models. */
16
+ input?: number;
17
+ /** USD per 1M output tokens — token-metered models. */
16
18
  output?: number;
17
19
  };
18
20
  /**
@@ -20,7 +22,7 @@ type VideoModelPricing = {
20
22
  * `GeneratedImage`). Providers return either a hosted URL (typically the
21
23
  * common case for video, which is large) or inlined base64 bytes.
22
24
  */
23
- type GeneratedVideo = {
25
+ export type GeneratedVideo = {
24
26
  type: "url";
25
27
  url: string;
26
28
  mediaType?: string;
@@ -30,12 +32,18 @@ type GeneratedVideo = {
30
32
  mediaType: string;
31
33
  };
32
34
  /** Options for a single {@link VideoModelContract.generate} request. */
33
- type VideoOptions = {
34
- /** Requested clip length in seconds. */durationSeconds?: number; /** Aspect ratio (e.g. `"16:9"`, `"9:16"`). */
35
- aspectRatio?: string; /** Resolution hint (e.g. `"720p"`, `"1080p"`). */
36
- resolution?: string; /** Concepts to steer away from. */
37
- negativePrompt?: string; /** Cancellation handle. */
38
- signal?: AbortSignal; /** Provider-specific escape hatch — forwarded verbatim. */
35
+ export type VideoOptions = {
36
+ /** Requested clip length in seconds. */
37
+ durationSeconds?: number;
38
+ /** Aspect ratio (e.g. `"16:9"`, `"9:16"`). */
39
+ aspectRatio?: string;
40
+ /** Resolution hint (e.g. `"720p"`, `"1080p"`). */
41
+ resolution?: string;
42
+ /** Concepts to steer away from. */
43
+ negativePrompt?: string;
44
+ /** Cancellation handle. */
45
+ signal?: AbortSignal;
46
+ /** Provider-specific escape hatch — forwarded verbatim. */
39
47
  [key: string]: unknown;
40
48
  };
41
49
  /**
@@ -44,9 +52,11 @@ type VideoOptions = {
44
52
  * ready (or throws a typed `AIError`). The never-throws envelope is
45
53
  * added by `ai.video()`.
46
54
  */
47
- type VideoGenerationResponse = {
48
- video: GeneratedVideo; /** Token usage when the provider reports it; otherwise all-zero. */
49
- usage: Usage; /** Final clip duration in seconds — drives per-second cost. */
55
+ export type VideoGenerationResponse = {
56
+ video: GeneratedVideo;
57
+ /** Token usage when the provider reports it; otherwise all-zero. */
58
+ usage: Usage;
59
+ /** Final clip duration in seconds — drives per-second cost. */
50
60
  durationSeconds?: number;
51
61
  };
52
62
  /**
@@ -55,18 +65,17 @@ type VideoGenerationResponse = {
55
65
  * factory and consumed by `ai.video()`. `generate()` encapsulates the
56
66
  * provider's async job (submit → poll → fetch result).
57
67
  */
58
- interface VideoModelContract {
68
+ export interface VideoModelContract {
59
69
  readonly name: string;
60
70
  readonly provider: string;
61
71
  readonly pricing?: VideoModelPricing;
62
72
  generate(prompt: string, options?: VideoOptions): Promise<VideoGenerationResponse>;
63
73
  }
64
74
  /** Configuration passed to an adapter's `video()` factory. */
65
- type VideoModelConfig = {
75
+ export type VideoModelConfig = {
66
76
  name: string;
67
77
  pricing?: VideoModelPricing;
68
78
  [key: string]: unknown;
69
79
  };
70
80
  //#endregion
71
- export { GeneratedVideo, VideoGenerationResponse, VideoModelConfig, VideoModelContract, VideoModelPricing, VideoOptions };
72
81
  //# sourceMappingURL=video.contract.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"video.contract.d.mts","names":[],"sources":["../../../../../../../../packages/ai-live/src/contracts/video.contract.ts"],"mappings":";;;;;AAWA;;;;;;;KAAY,iBAAA;EAMJ,qEAJN,SAAA,WAYwB;EAVxB,KAAA,WAUwB;EARxB,MAAA;AAAA;;;;;;KAQU,cAAA;EACN,IAAA;EAAa,GAAA;EAAa,SAAA;AAAA;EAC1B,IAAA;EAAgB,MAAA;EAAgB,SAAA;AAAA;;KAG1B,YAAA;EAYT,wCAVD,eAAA,WAUY;EARZ,WAAA,WAiBiC;EAfjC,UAAA,WAkBY;EAhBZ,cAAA,WAcO;EAZP,MAAA,GAAS,WAAW,EAcb;EAAA,CAZN,GAAA;AAAA;AAcc;AASjB;;;;;AATiB,KALL,uBAAA;EACV,KAAA,EAAO,cAAA,EAiBkD;EAfzD,KAAA,EAAO,KAAK,EAYH;EAVT,eAAA;AAAA;;;;;;;UASe,kBAAA;EAAA,SACN,IAAA;EAAA,SACA,QAAA;EAAA,SACA,OAAA,GAAU,iBAAA;EACnB,QAAA,CAAS,MAAA,UAAgB,OAAA,GAAU,YAAA,GAAe,OAAA,CAAQ,uBAAA;AAAA;;KAIhD,gBAAA;EACV,IAAA;EACA,OAAA,GAAU,iBAAiB;EAAA,CAC1B,GAAA;AAAA"}
1
+ {"version":3,"file":"video.contract.d.mts","names":[],"sources":["../../../../../../../../packages/ai-live/src/contracts/video.contract.ts"],"mappings":";;;;;;;;;;;YAWY;;EAEV;;EAEA;;EAEA;;;;;;;YAQU;EACN;EAAa;EAAa;;EAC1B;EAAgB;EAAgB;;;YAG1B;;EAEV;;EAEA;;EAEA;;EAEA;;EAEA,SAAS;;GAER;;;;;;;;YASS;EACV,OAAO;;EAEP,OAAO;;EAEP;;;;;;;;iBASe;WACN;WACA;WACA,UAAU;EACnB,SAAS,gBAAgB,UAAU,eAAe,QAAQ;;;YAIhD;EACV;EACA,UAAU;GACT"}
package/esm/index.d.mts CHANGED
@@ -3,7 +3,6 @@ import { realtime } from "./realtime/realtime.mjs";
3
3
  import { GeneratedVideo, VideoGenerationResponse, VideoModelConfig, VideoModelContract, VideoModelPricing, VideoOptions } from "./contracts/video.contract.mjs";
4
4
  import { VideoData, VideoParams, VideoReport, VideoResult, video } from "./video/video.mjs";
5
5
  import { MockRealtimeConnection, MockRealtimeTransport, MockVideoModel, MockVideoResponse } from "./mock/index.mjs";
6
-
7
6
  //#region ../../packages/ai-live/src/index.d.ts
8
7
  /**
9
8
  * Augment the shared `Ai` facade with this package's two heavy
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../../../../../../../packages/ai-live/src/index.ts"],"mappings":";;;;;;;;;;;;AAEsC;;;YAU1B,EAAA;IAAA;;;;;IAMR,KAAA,SAAc,KAAA;IAMW;AAAA;;;;IAAzB,QAAA,SAAiB,QAAQ;EAAA;AAAA"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../../../../../../packages/ai-live/src/index.ts"],"mappings":";;;;;;;;;;;;;;YAYY;;;;;;IAMR,cAAc;;;;;;IAMd,iBAAiB"}
@@ -1,17 +1,16 @@
1
1
  import { RealtimeConnectConfig, RealtimeConnection, RealtimeEvent, RealtimeTransport } from "../contracts/realtime.contract.mjs";
2
2
  import { GeneratedVideo, VideoGenerationResponse, VideoModelContract, VideoModelPricing, VideoOptions } from "../contracts/video.contract.mjs";
3
3
  import { Usage } from "@warlock.js/ai";
4
-
5
4
  //#region ../../packages/ai-live/src/mock/index.d.ts
6
5
  /** One scripted response for a {@link MockVideoModel}. */
7
- type MockVideoResponse = {
6
+ export type MockVideoResponse = {
8
7
  video?: GeneratedVideo;
9
8
  usage?: Usage;
10
9
  durationSeconds?: number;
11
10
  error?: Error;
12
11
  };
13
12
  /** Deterministic {@link VideoModelContract} double for tests — no HTTP, no polling. */
14
- declare class MockVideoModel implements VideoModelContract {
13
+ export declare class MockVideoModel implements VideoModelContract {
15
14
  readonly name: string;
16
15
  private readonly responses;
17
16
  readonly pricing?: VideoModelPricing | undefined;
@@ -25,7 +24,7 @@ declare class MockVideoModel implements VideoModelContract {
25
24
  generate(prompt: string, options?: VideoOptions): Promise<VideoGenerationResponse>;
26
25
  }
27
26
  /** A recording {@link RealtimeConnection} the mock transport hands back. */
28
- declare class MockRealtimeConnection implements RealtimeConnection {
27
+ export declare class MockRealtimeConnection implements RealtimeConnection {
29
28
  private readonly scripted;
30
29
  readonly sentAudio: {
31
30
  base64: string;
@@ -40,7 +39,7 @@ declare class MockRealtimeConnection implements RealtimeConnection {
40
39
  close(): Promise<void>;
41
40
  }
42
41
  /** Deterministic {@link RealtimeTransport} double — scripts the event stream, records sends. */
43
- declare class MockRealtimeTransport implements RealtimeTransport {
42
+ export declare class MockRealtimeTransport implements RealtimeTransport {
44
43
  private readonly scriptedEvents;
45
44
  readonly connectConfigs: RealtimeConnectConfig[];
46
45
  lastConnection?: MockRealtimeConnection;
@@ -48,5 +47,4 @@ declare class MockRealtimeTransport implements RealtimeTransport {
48
47
  connect(config: RealtimeConnectConfig): Promise<RealtimeConnection>;
49
48
  }
50
49
  //#endregion
51
- export { MockRealtimeConnection, MockRealtimeTransport, MockVideoModel, MockVideoResponse };
52
50
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../../../../../../../../packages/ai-live/src/mock/index.ts"],"mappings":";;;;;;KAgBY,iBAAA;EACV,KAAA,GAAQ,cAAA;EACR,KAAA,GAAQ,KAAA;EACR,eAAA;EACA,KAAA,GAAQ,KAAA;AAAA;;cAIG,cAAA,YAA0B,kBAAA;EAAA,SAOnB,IAAA;EAAA,iBACC,SAAA;EAAA,SACD,OAAA,GAAU,iBAAA;EAAA,SARZ,QAAA;EAAA,SACA,KAAA;IAAS,MAAA;IAAgB,OAAA,EAAS,YAAA;EAAA;EAAA,QAE1C,SAAA;cAGU,IAAA,UACC,SAAA,EAAW,iBAAA,IACZ,OAAA,GAAU,iBAAA;EAGf,QAAA,CACX,MAAA,UACA,OAAA,GAAU,YAAA,GACT,OAAA,CAAQ,uBAAA;AAAA;;cAmBA,sBAAA,YAAkC,kBAAA;EAAA,iBAKT,QAAA;EAAA,SAJpB,SAAA;IAAa,MAAA;IAAgB,SAAA;EAAA;EAAA,SAC7B,QAAA;EACT,MAAA;cAE6B,QAAA,EAAU,aAAA;EAEvC,SAAA,CAAU,MAAA,UAAgB,SAAA;EAI1B,QAAA,CAAS,IAAA;EAIF,MAAA,IAAU,aAAA,CAAc,aAAA;EAMzB,KAAA,IAAS,OAAA;AAAA;;cAMX,qBAAA,YAAiC,iBAAA;EAAA,iBAIR,cAAA;EAAA,SAHpB,cAAA,EAAgB,qBAAA;EACzB,cAAA,GAAiB,sBAAA;cAEY,cAAA,GAAgB,aAAA;EAEvC,OAAA,CAAQ,MAAA,EAAQ,qBAAA,GAAwB,OAAA,CAAQ,kBAAA;AAAA"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../../../../../../../packages/ai-live/src/mock/index.ts"],"mappings":";;;;;YAgBY;EACV,QAAQ;EACR,QAAQ;EACR;EACA,QAAQ;;;qBAIG,0BAA0B;WAOnB;mBACC;WACD,UAAU;WARZ;WACA;IAAS;IAAgB,SAAS;;UAE1C;EAER,YACkB,cACC,WAAW,qBACZ,UAAU;EAGf,SAAS,gBAAgB,UAAU,eAAe,QAAQ;;;qBAuB5D,kCAAkC;mBAKT;WAJpB;IAAa;IAAgB;;WAC7B;EACT;EAEP,YAAoC,UAAU;EAEvC,UAAU,gBAAgB;EAI1B,SAAS;EAIF,UAAU,cAAc;EAMzB,SAAS;;;qBAMX,iCAAiC;mBAIR;WAHpB,gBAAgB;EACzB,iBAAiB;EAExB,YAAoC,iBAAgB;EAEvC,QAAQ,QAAQ,wBAAwB,QAAQ"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../../../../../../../packages/ai-live/src/mock/index.ts"],"sourcesContent":["import type { Usage } from \"@warlock.js/ai\";\nimport type {\n RealtimeConnectConfig,\n RealtimeConnection,\n RealtimeEvent,\n RealtimeTransport,\n} from \"../contracts/realtime.contract\";\nimport type {\n GeneratedVideo,\n VideoGenerationResponse,\n VideoModelContract,\n VideoModelPricing,\n VideoOptions,\n} from \"../contracts/video.contract\";\n\n/** One scripted response for a {@link MockVideoModel}. */\nexport type MockVideoResponse = {\n video?: GeneratedVideo;\n usage?: Usage;\n durationSeconds?: number;\n error?: Error;\n};\n\n/** Deterministic {@link VideoModelContract} double for tests — no HTTP, no polling. */\nexport class MockVideoModel implements VideoModelContract {\n public readonly provider = \"mock\";\n public readonly calls: { prompt: string; options: VideoOptions | undefined }[] = [];\n\n private callIndex = 0;\n\n public constructor(\n public readonly name: string,\n private readonly responses: MockVideoResponse[],\n public readonly pricing?: VideoModelPricing,\n ) {}\n\n public async generate(\n prompt: string,\n options?: VideoOptions,\n ): Promise<VideoGenerationResponse> {\n this.calls.push({ prompt, options });\n\n const response = this.responses[Math.min(this.callIndex, this.responses.length - 1)] ?? {};\n this.callIndex += 1;\n\n if (response.error) {\n throw response.error;\n }\n\n return {\n video: response.video ?? { type: \"url\", url: \"https://mock/video.mp4\", mediaType: \"video/mp4\" },\n usage: response.usage ?? { input: 0, output: 0, total: 0 },\n durationSeconds: response.durationSeconds ?? options?.durationSeconds ?? 5,\n };\n }\n}\n\n/** A recording {@link RealtimeConnection} the mock transport hands back. */\nexport class MockRealtimeConnection implements RealtimeConnection {\n public readonly sentAudio: { base64: string; mediaType: string }[] = [];\n public readonly sentText: string[] = [];\n public closed = false;\n\n public constructor(private readonly scripted: RealtimeEvent[]) {}\n\n public sendAudio(base64: string, mediaType: string): void {\n this.sentAudio.push({ base64, mediaType });\n }\n\n public sendText(text: string): void {\n this.sentText.push(text);\n }\n\n public async *events(): AsyncIterable<RealtimeEvent> {\n for (const event of this.scripted) {\n yield event;\n }\n }\n\n public async close(): Promise<void> {\n this.closed = true;\n }\n}\n\n/** Deterministic {@link RealtimeTransport} double — scripts the event stream, records sends. */\nexport class MockRealtimeTransport implements RealtimeTransport {\n public readonly connectConfigs: RealtimeConnectConfig[] = [];\n public lastConnection?: MockRealtimeConnection;\n\n public constructor(private readonly scriptedEvents: RealtimeEvent[] = []) {}\n\n public async connect(config: RealtimeConnectConfig): Promise<RealtimeConnection> {\n this.connectConfigs.push(config);\n this.lastConnection = new MockRealtimeConnection(this.scriptedEvents);\n return this.lastConnection;\n }\n}\n"],"mappings":";;AAwBA,IAAa,iBAAb,MAA0D;CAMxD,AAAO,YACL,AAAgB,MAChB,AAAiB,WACjB,AAAgB,SAChB;EAHgB;EACC;EACD;kBARS;eACsD,CAAC;mBAE9D;CAMjB;CAEH,MAAa,SACX,QACA,SACkC;EAClC,KAAK,MAAM,KAAK;GAAE;GAAQ;EAAQ,CAAC;EAEnC,MAAM,WAAW,KAAK,UAAU,KAAK,IAAI,KAAK,WAAW,KAAK,UAAU,SAAS,CAAC,MAAM,CAAC;EACzF,KAAK,aAAa;EAElB,IAAI,SAAS,OACX,MAAM,SAAS;EAGjB,OAAO;GACL,OAAO,SAAS,SAAS;IAAE,MAAM;IAAO,KAAK;IAA0B,WAAW;GAAY;GAC9F,OAAO,SAAS,SAAS;IAAE,OAAO;IAAG,QAAQ;IAAG,OAAO;GAAE;GACzD,iBAAiB,SAAS,mBAAmB,SAAS,mBAAmB;EAC3E;CACF;AACF;;AAGA,IAAa,yBAAb,MAAkE;CAKhE,AAAO,YAAY,AAAiB,UAA2B;EAA3B;mBAJiC,CAAC;kBACjC,CAAC;gBACtB;CAEgD;CAEhE,AAAO,UAAU,QAAgB,WAAyB;EACxD,KAAK,UAAU,KAAK;GAAE;GAAQ;EAAU,CAAC;CAC3C;CAEA,AAAO,SAAS,MAAoB;EAClC,KAAK,SAAS,KAAK,IAAI;CACzB;CAEA,OAAc,SAAuC;EACnD,KAAK,MAAM,SAAS,KAAK,UACvB,MAAM;CAEV;CAEA,MAAa,QAAuB;EAClC,KAAK,SAAS;CAChB;AACF;;AAGA,IAAa,wBAAb,MAAgE;CAI9D,AAAO,YAAY,AAAiB,iBAAkC,CAAC,GAAG;EAAtC;wBAHsB,CAAC;CAGgB;CAE3E,MAAa,QAAQ,QAA4D;EAC/E,KAAK,eAAe,KAAK,MAAM;EAC/B,KAAK,iBAAiB,IAAI,uBAAuB,KAAK,cAAc;EACpE,OAAO,KAAK;CACd;AACF"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../../../../../../../packages/ai-live/src/mock/index.ts"],"sourcesContent":["import type { Usage } from \"@warlock.js/ai\";\nimport type {\n RealtimeConnectConfig,\n RealtimeConnection,\n RealtimeEvent,\n RealtimeTransport,\n} from \"../contracts/realtime.contract\";\nimport type {\n GeneratedVideo,\n VideoGenerationResponse,\n VideoModelContract,\n VideoModelPricing,\n VideoOptions,\n} from \"../contracts/video.contract\";\n\n/** One scripted response for a {@link MockVideoModel}. */\nexport type MockVideoResponse = {\n video?: GeneratedVideo;\n usage?: Usage;\n durationSeconds?: number;\n error?: Error;\n};\n\n/** Deterministic {@link VideoModelContract} double for tests — no HTTP, no polling. */\nexport class MockVideoModel implements VideoModelContract {\n public readonly provider = \"mock\";\n public readonly calls: { prompt: string; options: VideoOptions | undefined }[] = [];\n\n private callIndex = 0;\n\n public constructor(\n public readonly name: string,\n private readonly responses: MockVideoResponse[],\n public readonly pricing?: VideoModelPricing,\n ) {}\n\n public async generate(prompt: string, options?: VideoOptions): Promise<VideoGenerationResponse> {\n this.calls.push({ prompt, options });\n\n const response = this.responses[Math.min(this.callIndex, this.responses.length - 1)] ?? {};\n this.callIndex += 1;\n\n if (response.error) {\n throw response.error;\n }\n\n return {\n video: response.video ?? {\n type: \"url\",\n url: \"https://mock/video.mp4\",\n mediaType: \"video/mp4\",\n },\n usage: response.usage ?? { input: 0, output: 0, total: 0 },\n durationSeconds: response.durationSeconds ?? options?.durationSeconds ?? 5,\n };\n }\n}\n\n/** A recording {@link RealtimeConnection} the mock transport hands back. */\nexport class MockRealtimeConnection implements RealtimeConnection {\n public readonly sentAudio: { base64: string; mediaType: string }[] = [];\n public readonly sentText: string[] = [];\n public closed = false;\n\n public constructor(private readonly scripted: RealtimeEvent[]) {}\n\n public sendAudio(base64: string, mediaType: string): void {\n this.sentAudio.push({ base64, mediaType });\n }\n\n public sendText(text: string): void {\n this.sentText.push(text);\n }\n\n public async *events(): AsyncIterable<RealtimeEvent> {\n for (const event of this.scripted) {\n yield event;\n }\n }\n\n public async close(): Promise<void> {\n this.closed = true;\n }\n}\n\n/** Deterministic {@link RealtimeTransport} double — scripts the event stream, records sends. */\nexport class MockRealtimeTransport implements RealtimeTransport {\n public readonly connectConfigs: RealtimeConnectConfig[] = [];\n public lastConnection?: MockRealtimeConnection;\n\n public constructor(private readonly scriptedEvents: RealtimeEvent[] = []) {}\n\n public async connect(config: RealtimeConnectConfig): Promise<RealtimeConnection> {\n this.connectConfigs.push(config);\n this.lastConnection = new MockRealtimeConnection(this.scriptedEvents);\n return this.lastConnection;\n }\n}\n"],"mappings":";;AAwBA,IAAa,iBAAb,MAA0D;CAMxD,AAAO,YACL,AAAgB,MAChB,AAAiB,WACjB,AAAgB,SAChB;EAHgB;EACC;EACD;kBARS;eACsD,CAAC;mBAE9D;CAMjB;CAEH,MAAa,SAAS,QAAgB,SAA0D;EAC9F,KAAK,MAAM,KAAK;GAAE;GAAQ;EAAQ,CAAC;EAEnC,MAAM,WAAW,KAAK,UAAU,KAAK,IAAI,KAAK,WAAW,KAAK,UAAU,SAAS,CAAC,MAAM,CAAC;EACzF,KAAK,aAAa;EAElB,IAAI,SAAS,OACX,MAAM,SAAS;EAGjB,OAAO;GACL,OAAO,SAAS,SAAS;IACvB,MAAM;IACN,KAAK;IACL,WAAW;GACb;GACA,OAAO,SAAS,SAAS;IAAE,OAAO;IAAG,QAAQ;IAAG,OAAO;GAAE;GACzD,iBAAiB,SAAS,mBAAmB,SAAS,mBAAmB;EAC3E;CACF;AACF;;AAGA,IAAa,yBAAb,MAAkE;CAKhE,AAAO,YAAY,AAAiB,UAA2B;EAA3B;mBAJiC,CAAC;kBACjC,CAAC;gBACtB;CAEgD;CAEhE,AAAO,UAAU,QAAgB,WAAyB;EACxD,KAAK,UAAU,KAAK;GAAE;GAAQ;EAAU,CAAC;CAC3C;CAEA,AAAO,SAAS,MAAoB;EAClC,KAAK,SAAS,KAAK,IAAI;CACzB;CAEA,OAAc,SAAuC;EACnD,KAAK,MAAM,SAAS,KAAK,UACvB,MAAM;CAEV;CAEA,MAAa,QAAuB;EAClC,KAAK,SAAS;CAChB;AACF;;AAGA,IAAa,wBAAb,MAAgE;CAI9D,AAAO,YAAY,AAAiB,iBAAkC,CAAC,GAAG;EAAtC;wBAHsB,CAAC;CAGgB;CAE3E,MAAa,QAAQ,QAA4D;EAC/E,KAAK,eAAe,KAAK,MAAM;EAC/B,KAAK,iBAAiB,IAAI,uBAAuB,KAAK,cAAc;EACpE,OAAO,KAAK;CACd;AACF"}
@@ -1,5 +1,4 @@
1
1
  import { RealtimeOptions, RealtimeSession } from "../contracts/realtime.contract.mjs";
2
-
3
2
  //#region ../../packages/ai-live/src/realtime/realtime.d.ts
4
3
  /**
5
4
  * Open a live duplex voice session — the stateful primitive of
@@ -23,7 +22,6 @@ import { RealtimeOptions, RealtimeSession } from "../contracts/realtime.contract
23
22
  * }
24
23
  * const report = await session.close();
25
24
  */
26
- declare function realtime(options: RealtimeOptions): Promise<RealtimeSession>;
25
+ export declare function realtime(options: RealtimeOptions): Promise<RealtimeSession>;
27
26
  //#endregion
28
- export { realtime };
29
27
  //# sourceMappingURL=realtime.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"realtime.d.mts","names":[],"sources":["../../../../../../../../packages/ai-live/src/realtime/realtime.ts"],"mappings":";;;;;AA6BA;;;;;;;;;;;;;AAAiF;;;;;;;iBAA3D,QAAA,CAAS,OAAA,EAAS,eAAA,GAAkB,OAAA,CAAQ,eAAA"}
1
+ {"version":3,"file":"realtime.d.mts","names":[],"sources":["../../../../../../../../packages/ai-live/src/realtime/realtime.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;wBA6BsB,SAAS,SAAS,kBAAkB,QAAQ"}
@@ -1,9 +1,8 @@
1
1
  import { GeneratedVideo, VideoModelContract } from "../contracts/video.contract.mjs";
2
2
  import { BaseReport, ExecuteResult, FlowObserveOption } from "@warlock.js/ai";
3
-
4
3
  //#region ../../packages/ai-live/src/video/video.d.ts
5
4
  /** Parameters for {@link video}. `model` comes from an adapter's `video({ name })`. */
6
- type VideoParams = {
5
+ export type VideoParams = {
7
6
  model: VideoModelContract;
8
7
  prompt: string;
9
8
  durationSeconds?: number;
@@ -17,20 +16,21 @@ type VideoParams = {
17
16
  options?: Record<string, unknown>;
18
17
  };
19
18
  /** Success payload of a {@link video} run. */
20
- type VideoData = {
19
+ export type VideoData = {
21
20
  video: GeneratedVideo;
22
21
  };
23
22
  /** The report node a {@link video} run produces (`type: "video"`). */
24
- type VideoReport = BaseReport & {
23
+ export type VideoReport = BaseReport & {
25
24
  type: "video";
26
25
  model: {
27
26
  name: string;
28
27
  provider: string;
29
- }; /** Final clip duration in seconds, when reported. */
28
+ };
29
+ /** Final clip duration in seconds, when reported. */
30
30
  durationSeconds?: number;
31
31
  };
32
32
  /** Result envelope of {@link video} — the uniform `{ data, error, usage, report }`. */
33
- type VideoResult = ExecuteResult<VideoData> & {
33
+ export type VideoResult = ExecuteResult<VideoData> & {
34
34
  type: "video";
35
35
  report: VideoReport;
36
36
  };
@@ -53,7 +53,6 @@ type VideoResult = ExecuteResult<VideoData> & {
53
53
  * });
54
54
  * if (!error) download(data.video);
55
55
  */
56
- declare function video(params: VideoParams): Promise<VideoResult>;
56
+ export declare function video(params: VideoParams): Promise<VideoResult>;
57
57
  //#endregion
58
- export { VideoData, VideoParams, VideoReport, VideoResult, video };
59
58
  //# sourceMappingURL=video.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"video.d.mts","names":[],"sources":["../../../../../../../../packages/ai-live/src/video/video.ts"],"mappings":";;;;;KAqBY,WAAA;EACV,KAAA,EAAO,kBAAA;EACP,MAAA;EACA,eAAA;EACA,WAAA;EACA,UAAA;EACA,cAAA;EACA,MAAA,GAAS,WAAA;EACT,OAAA,GAAU,iBAAA;EACV,SAAA;EACA,IAAA;EACA,OAAA,GAAU,MAAA;AAAA;;KAIA,SAAA;EAAc,KAAA,EAAO,cAAc;AAAA;;KAGnC,WAAA,GAAc,UAAU;EAClC,IAAA;EACA,KAAA;IAAS,IAAA;IAAc,QAAA;EAAA,GATb;EAWV,eAAA;AAAA;AAPF;AAAA,KAWY,WAAA,GAAc,aAAA,CAAc,SAAA;EAAe,IAAA;EAAe,MAAA,EAAQ,WAAA;AAAA;AAR9E;;;;;;;;;;;AAIiB;AAIjB;;;;;;;AARA,iBA6BsB,KAAA,CAAM,MAAA,EAAQ,WAAA,GAAc,OAAA,CAAQ,WAAA"}
1
+ {"version":3,"file":"video.d.mts","names":[],"sources":["../../../../../../../../packages/ai-live/src/video/video.ts"],"mappings":";;;;YAqBY;EACV,OAAO;EACP;EACA;EACA;EACA;EACA;EACA,SAAS;EACT,UAAU;EACV;EACA;EACA,UAAU;;;YAIA;EAAc,OAAO;;;YAGrB,cAAc;EACxB;EACA;IAAS;IAAc;;;EAEvB;;;YAIU,cAAc,cAAc;EAAe;EAAe,QAAQ;;;;;;;;;;;;;;;;;;;;;wBAqBxD,MAAM,QAAQ,cAAc,QAAQ"}
package/llms-full.txt CHANGED
@@ -39,9 +39,9 @@ const { data, error, usage, report } = await ai.video({
39
39
  });
40
40
 
41
41
  if (error) {
42
- console.warn(error.code); // typed AIError — NEVER thrown
42
+ console.warn(error.code); // typed AIError — NEVER thrown
43
43
  } else {
44
- const clip = data.video; // GeneratedVideo (discriminated)
44
+ const clip = data.video; // GeneratedVideo (discriminated)
45
45
  if (clip.type === "url") download(clip.url);
46
46
  else save(Buffer.from(clip.base64, "base64"), clip.mediaType);
47
47
  }
@@ -59,17 +59,17 @@ type GeneratedVideo =
59
59
 
60
60
  // VideoParams (provider-neutral) — the model is the only required field beyond prompt:
61
61
  await ai.video({
62
- model, // VideoModelContract from an adapter's video({ name })
62
+ model, // VideoModelContract from an adapter's video({ name })
63
63
  prompt: "...",
64
- durationSeconds: 8, // requested clip length
64
+ durationSeconds: 8, // requested clip length
65
65
  aspectRatio: "9:16",
66
- resolution: "1080p", // hint
66
+ resolution: "1080p", // hint
67
67
  negativePrompt: "blurry, watermark",
68
- signal, // AbortSignal → status "cancelled"
69
- observe: collector, // route the report to an Observer (panoptic), like agents
68
+ signal, // AbortSignal → status "cancelled"
69
+ observe: collector, // route the report to an Observer (panoptic), like agents
70
70
  sessionId: "campaign-42",
71
- name: "hero-clip", // report node name (defaults to "video")
72
- options: { seed: 7 }, // provider-specific escape hatch, forwarded verbatim
71
+ name: "hero-clip", // report node name (defaults to "video")
72
+ options: { seed: 7 }, // provider-specific escape hatch, forwarded verbatim
73
73
  });
74
74
  ```
75
75
 
@@ -97,13 +97,23 @@ const session = await ai.realtime({
97
97
  session.sendAudio(micChunkBase64, "audio/pcm"); // push mic audio upstream
98
98
  session.sendText("Please hold for one moment."); // or a text turn
99
99
 
100
- for await (const event of session.events()) { // duplex output
100
+ for await (const event of session.events()) {
101
+ // duplex output
101
102
  switch (event.type) {
102
- case "audio": speaker.write(event.base64); break;
103
- case "transcript": if (event.final) log(event.role, event.text); break;
104
- case "tool-call": await handleTool(event.name, event.input); break;
105
- case "error": console.warn(event.error.code); break;
106
- case "done": break;
103
+ case "audio":
104
+ speaker.write(event.base64);
105
+ break;
106
+ case "transcript":
107
+ if (event.final) log(event.role, event.text);
108
+ break;
109
+ case "tool-call":
110
+ await handleTool(event.name, event.input);
111
+ break;
112
+ case "error":
113
+ console.warn(event.error.code);
114
+ break;
115
+ case "done":
116
+ break;
107
117
  }
108
118
  }
109
119
 
@@ -124,13 +134,19 @@ type RealtimeEvent =
124
134
  | { type: "audio"; base64: string; mediaType: string }
125
135
  | { type: "transcript"; role: "user" | "assistant"; text: string; final: boolean }
126
136
  | { type: "tool-call"; id: string; name: string; input: unknown }
127
- | { type: "error"; error: AIError } // typed, non-fatal
128
- | { type: "done" }; // server ended the session
137
+ | { type: "error"; error: AIError } // typed, non-fatal
138
+ | { type: "done" }; // server ended the session
129
139
 
130
140
  type RealtimeReport = {
131
- runId: string; rootRunId: string; type: "realtime";
132
- name: string; status: "completed" | "failed" | "cancelled";
133
- startedAt: string; endedAt: string; duration: number; sessionId?: string;
141
+ runId: string;
142
+ rootRunId: string;
143
+ type: "realtime";
144
+ name: string;
145
+ status: "completed" | "failed" | "cancelled";
146
+ startedAt: string;
147
+ endedAt: string;
148
+ duration: number;
149
+ sessionId?: string;
134
150
  };
135
151
  ```
136
152
 
@@ -187,7 +203,9 @@ const transport = new MockRealtimeTransport([
187
203
  ]);
188
204
  const session = await ai.realtime({ transport, model: "mock-realtime" });
189
205
  session.sendText("hello");
190
- for await (const e of session.events()) { /* ... */ }
206
+ for await (const e of session.events()) {
207
+ /* ... */
208
+ }
191
209
  const report = await session.close();
192
210
  // transport.lastConnection.sentText → ["hello"]
193
211
  // transport.connectConfigs[0] → { model: "mock-realtime", ... }
package/package.json CHANGED
@@ -15,17 +15,17 @@
15
15
  ],
16
16
  "license": "MIT",
17
17
  "dependencies": {
18
- "@warlock.js/logger": "5.30.0"
18
+ "@warlock.js/logger": "5.32.0"
19
19
  },
20
20
  "peerDependencies": {
21
- "@warlock.js/ai": "5.30.0"
21
+ "@warlock.js/ai": "5.32.0"
22
22
  },
23
23
  "peerDependenciesMeta": {
24
24
  "ws": {
25
25
  "optional": true
26
26
  }
27
27
  },
28
- "version": "5.30.0",
28
+ "version": "5.32.0",
29
29
  "main": "./cjs/index.cjs",
30
30
  "module": "./esm/index.mjs",
31
31
  "types": "./esm/index.d.mts",
@@ -31,9 +31,9 @@ const { data, error, usage, report } = await ai.video({
31
31
  });
32
32
 
33
33
  if (error) {
34
- console.warn(error.code); // typed AIError — NEVER thrown
34
+ console.warn(error.code); // typed AIError — NEVER thrown
35
35
  } else {
36
- const clip = data.video; // GeneratedVideo (discriminated)
36
+ const clip = data.video; // GeneratedVideo (discriminated)
37
37
  if (clip.type === "url") download(clip.url);
38
38
  else save(Buffer.from(clip.base64, "base64"), clip.mediaType);
39
39
  }
@@ -51,17 +51,17 @@ type GeneratedVideo =
51
51
 
52
52
  // VideoParams (provider-neutral) — the model is the only required field beyond prompt:
53
53
  await ai.video({
54
- model, // VideoModelContract from an adapter's video({ name })
54
+ model, // VideoModelContract from an adapter's video({ name })
55
55
  prompt: "...",
56
- durationSeconds: 8, // requested clip length
56
+ durationSeconds: 8, // requested clip length
57
57
  aspectRatio: "9:16",
58
- resolution: "1080p", // hint
58
+ resolution: "1080p", // hint
59
59
  negativePrompt: "blurry, watermark",
60
- signal, // AbortSignal → status "cancelled"
61
- observe: collector, // route the report to an Observer (panoptic), like agents
60
+ signal, // AbortSignal → status "cancelled"
61
+ observe: collector, // route the report to an Observer (panoptic), like agents
62
62
  sessionId: "campaign-42",
63
- name: "hero-clip", // report node name (defaults to "video")
64
- options: { seed: 7 }, // provider-specific escape hatch, forwarded verbatim
63
+ name: "hero-clip", // report node name (defaults to "video")
64
+ options: { seed: 7 }, // provider-specific escape hatch, forwarded verbatim
65
65
  });
66
66
  ```
67
67
 
@@ -89,13 +89,23 @@ const session = await ai.realtime({
89
89
  session.sendAudio(micChunkBase64, "audio/pcm"); // push mic audio upstream
90
90
  session.sendText("Please hold for one moment."); // or a text turn
91
91
 
92
- for await (const event of session.events()) { // duplex output
92
+ for await (const event of session.events()) {
93
+ // duplex output
93
94
  switch (event.type) {
94
- case "audio": speaker.write(event.base64); break;
95
- case "transcript": if (event.final) log(event.role, event.text); break;
96
- case "tool-call": await handleTool(event.name, event.input); break;
97
- case "error": console.warn(event.error.code); break;
98
- case "done": break;
95
+ case "audio":
96
+ speaker.write(event.base64);
97
+ break;
98
+ case "transcript":
99
+ if (event.final) log(event.role, event.text);
100
+ break;
101
+ case "tool-call":
102
+ await handleTool(event.name, event.input);
103
+ break;
104
+ case "error":
105
+ console.warn(event.error.code);
106
+ break;
107
+ case "done":
108
+ break;
99
109
  }
100
110
  }
101
111
 
@@ -116,13 +126,19 @@ type RealtimeEvent =
116
126
  | { type: "audio"; base64: string; mediaType: string }
117
127
  | { type: "transcript"; role: "user" | "assistant"; text: string; final: boolean }
118
128
  | { type: "tool-call"; id: string; name: string; input: unknown }
119
- | { type: "error"; error: AIError } // typed, non-fatal
120
- | { type: "done" }; // server ended the session
129
+ | { type: "error"; error: AIError } // typed, non-fatal
130
+ | { type: "done" }; // server ended the session
121
131
 
122
132
  type RealtimeReport = {
123
- runId: string; rootRunId: string; type: "realtime";
124
- name: string; status: "completed" | "failed" | "cancelled";
125
- startedAt: string; endedAt: string; duration: number; sessionId?: string;
133
+ runId: string;
134
+ rootRunId: string;
135
+ type: "realtime";
136
+ name: string;
137
+ status: "completed" | "failed" | "cancelled";
138
+ startedAt: string;
139
+ endedAt: string;
140
+ duration: number;
141
+ sessionId?: string;
126
142
  };
127
143
  ```
128
144
 
@@ -179,7 +195,9 @@ const transport = new MockRealtimeTransport([
179
195
  ]);
180
196
  const session = await ai.realtime({ transport, model: "mock-realtime" });
181
197
  session.sendText("hello");
182
- for await (const e of session.events()) { /* ... */ }
198
+ for await (const e of session.events()) {
199
+ /* ... */
200
+ }
183
201
  const report = await session.close();
184
202
  // transport.lastConnection.sentText → ["hello"]
185
203
  // transport.connectConfigs[0] → { model: "mock-realtime", ... }