@agimon-ai/po-voice 0.0.0-alpha.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.
Files changed (84) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE +13 -0
  3. package/README.md +249 -0
  4. package/dist/apiContracts.cjs +809 -0
  5. package/dist/apiContracts.cjs.map +1 -0
  6. package/dist/apiContracts.d.mts +53 -0
  7. package/dist/apiContracts.d.mts.map +1 -0
  8. package/dist/apiContracts.mjs +805 -0
  9. package/dist/apiContracts.mjs.map +1 -0
  10. package/dist/assets/browserCaptureWorklet-Droj0fW0.js +13 -0
  11. package/dist/assets/silero_vad_v6.2.1-SjbCxFXk.onnx +0 -0
  12. package/dist/clientCaptureActivity-DN4xQtmw.d.mts +234 -0
  13. package/dist/clientCaptureActivity-DN4xQtmw.d.mts.map +1 -0
  14. package/dist/clientMedia-CfTfc9_4.mjs +49 -0
  15. package/dist/clientMedia-CfTfc9_4.mjs.map +1 -0
  16. package/dist/clientMedia-DuA4aYhD.cjs +156 -0
  17. package/dist/clientMedia-DuA4aYhD.cjs.map +1 -0
  18. package/dist/clientMedia.cjs +134 -0
  19. package/dist/clientMedia.cjs.map +1 -0
  20. package/dist/clientMedia.d.mts +2 -0
  21. package/dist/clientMedia.mjs +114 -0
  22. package/dist/clientMedia.mjs.map +1 -0
  23. package/dist/extensions/server.cjs +8975 -0
  24. package/dist/extensions/server.cjs.map +1 -0
  25. package/dist/extensions/server.d.mts +5 -0
  26. package/dist/extensions/server.d.mts.map +1 -0
  27. package/dist/extensions/server.mjs +8968 -0
  28. package/dist/extensions/server.mjs.map +1 -0
  29. package/dist/extensions/web.mjs +4530 -0
  30. package/dist/extensions/web.mjs.map +1 -0
  31. package/dist/index-C95HCjmT.d.mts +212 -0
  32. package/dist/index-C95HCjmT.d.mts.map +1 -0
  33. package/dist/index.cjs +637 -0
  34. package/dist/index.cjs.map +1 -0
  35. package/dist/index.d.mts +603 -0
  36. package/dist/index.d.mts.map +1 -0
  37. package/dist/index.mjs +557 -0
  38. package/dist/index.mjs.map +1 -0
  39. package/dist/narrationBargeIn-C_Po8fgw.mjs +62 -0
  40. package/dist/narrationBargeIn-C_Po8fgw.mjs.map +1 -0
  41. package/dist/narrationBargeIn-Dje82XOm.cjs +73 -0
  42. package/dist/narrationBargeIn-Dje82XOm.cjs.map +1 -0
  43. package/dist/sileroVadWorker-D894njUe.mjs +110 -0
  44. package/dist/sileroVadWorker-D894njUe.mjs.map +1 -0
  45. package/dist/vad-DDe4RIdW.mjs +315 -0
  46. package/dist/vad-DDe4RIdW.mjs.map +1 -0
  47. package/dist/vad-n2RlruzB.cjs +332 -0
  48. package/dist/vad-n2RlruzB.cjs.map +1 -0
  49. package/dist/voiceReloadHandoff.cjs +9 -0
  50. package/dist/voiceReloadHandoff.d.mts +1 -0
  51. package/dist/voiceReloadHandoff.mjs +2 -0
  52. package/dist/voiceTools-CRQHK_Uc.cjs +616 -0
  53. package/dist/voiceTools-CRQHK_Uc.cjs.map +1 -0
  54. package/dist/voiceTools-aCCREMjS.mjs +611 -0
  55. package/dist/voiceTools-aCCREMjS.mjs.map +1 -0
  56. package/dist/voiceTools.cjs +12 -0
  57. package/dist/voiceTools.d.mts +7 -0
  58. package/dist/voiceTools.d.mts.map +1 -0
  59. package/dist/voiceTools.mjs +3 -0
  60. package/dist/voiceWorker.cjs +1929 -0
  61. package/dist/voiceWorker.cjs.map +1 -0
  62. package/dist/voiceWorker.d.mts +200 -0
  63. package/dist/voiceWorker.d.mts.map +1 -0
  64. package/dist/voiceWorker.mjs +1925 -0
  65. package/dist/voiceWorker.mjs.map +1 -0
  66. package/dist/voiceWorkerProtocol-0H3czPjt.cjs +2385 -0
  67. package/dist/voiceWorkerProtocol-0H3czPjt.cjs.map +1 -0
  68. package/dist/voiceWorkerProtocol-B_4B2_fR.mjs +2085 -0
  69. package/dist/voiceWorkerProtocol-B_4B2_fR.mjs.map +1 -0
  70. package/dist/voiceWorkerSessionController-DaYemiL3.cjs +1800 -0
  71. package/dist/voiceWorkerSessionController-DaYemiL3.cjs.map +1 -0
  72. package/dist/voiceWorkerSessionController-GB3SJ6YE.mjs +1734 -0
  73. package/dist/voiceWorkerSessionController-GB3SJ6YE.mjs.map +1 -0
  74. package/licenses/Codex-Apache-2.0.txt +201 -0
  75. package/llms.txt +9 -0
  76. package/package.json +153 -0
  77. package/src/extensions/workspaces/sessions/(frontend)/lifecycle/_lib/models/README.md +11 -0
  78. package/src/extensions/workspaces/sessions/(frontend)/lifecycle/_lib/models/SILERO-LICENSE +21 -0
  79. package/src/prompts/po-use-voice/SKILL.md +35 -0
  80. package/src/types/clientCaptureActivity.ts +155 -0
  81. package/src/types/clientMedia.ts +226 -0
  82. package/src/types/manualTranscription.ts +53 -0
  83. package/src/types/realtime.ts +107 -0
  84. package/src/types/voiceOwnership.ts +315 -0
@@ -0,0 +1,805 @@
1
+ import { defineApiContract, jsonApiResponses } from "@agimon-ai/po-core/apiContracts";
2
+ import { Type } from "typebox";
3
+ import { defineDoomPluginMethod } from "@agimon-ai/po-core/pluginProtocol";
4
+ //#region src/schemas/voiceControl.ts
5
+ const voiceControlMethod = defineDoomPluginMethod({
6
+ service: "voice",
7
+ method: "control",
8
+ scope: "session",
9
+ direction: "client-to-server",
10
+ input: Type.Object({
11
+ action: Type.Union([
12
+ "status",
13
+ "manual",
14
+ "activate",
15
+ "deactivate",
16
+ "mute",
17
+ "unmute",
18
+ "interrupt",
19
+ "transfer"
20
+ ].map((value) => Type.Literal(value))),
21
+ target: Type.Optional(Type.Integer({ minimum: 1 })),
22
+ revision: Type.Optional(Type.String({
23
+ minLength: 1,
24
+ maxLength: 128
25
+ }))
26
+ }, { additionalProperties: false }),
27
+ output: Type.Object({
28
+ state: Type.String(),
29
+ mode: Type.String(),
30
+ manual: Type.String(),
31
+ muted: Type.Boolean(),
32
+ error: Type.Optional(Type.String())
33
+ }, { additionalProperties: false })
34
+ });
35
+ //#endregion
36
+ //#region src/schemas/apiContracts.ts
37
+ const S = Type.String();
38
+ const N = Type.Number();
39
+ const B = Type.Boolean();
40
+ const O = Type.Optional;
41
+ const values = (items) => Type.Union(items.map((item) => Type.Literal(item)));
42
+ const Client = {
43
+ clientId: S,
44
+ connectionId: S
45
+ };
46
+ const Configuration = Type.Object({
47
+ mode: values(["manual", "autonomous"]),
48
+ activityControl: values(["host", "client"]),
49
+ endpointSilenceMs: O(Type.Integer({ minimum: 250 }))
50
+ });
51
+ const Playback = {
52
+ playbackId: S,
53
+ outcome: values([
54
+ "completed",
55
+ "stopped",
56
+ "aborted",
57
+ "failed"
58
+ ]),
59
+ error: O(S)
60
+ };
61
+ const Sequence = { sequence: N };
62
+ const Control = values([
63
+ "mute",
64
+ "unmute",
65
+ "interrupt"
66
+ ]);
67
+ const Browser = Type.Object({
68
+ connection: values([
69
+ "connecting",
70
+ "connected",
71
+ "closed",
72
+ "failed"
73
+ ]),
74
+ listening: B,
75
+ speaking: B,
76
+ muted: B,
77
+ error: O(S)
78
+ });
79
+ const VoiceMediaEventSchema = Type.Union([
80
+ Type.Object({
81
+ ...Sequence,
82
+ type: Type.Literal("capture-start"),
83
+ captureId: S,
84
+ sampleRate: Type.Literal(16e3),
85
+ channels: Type.Literal(1),
86
+ bitsPerSample: Type.Literal(16),
87
+ configuration: Configuration
88
+ }),
89
+ Type.Object({
90
+ ...Sequence,
91
+ type: values(["capture-stop", "capture-abort"]),
92
+ captureId: S
93
+ }),
94
+ Type.Object({
95
+ ...Sequence,
96
+ type: Type.Literal("playback-start"),
97
+ playbackId: S,
98
+ text: S,
99
+ delivery: O(values(["client", "streamed"])),
100
+ voice: O(S),
101
+ rate: O(N)
102
+ }),
103
+ Type.Object({
104
+ ...Sequence,
105
+ type: values(["playback-stop", "playback-abort"]),
106
+ playbackId: S
107
+ }),
108
+ Type.Object({
109
+ ...Sequence,
110
+ type: values(["realtime-start", "realtime-stop"]),
111
+ activationId: S
112
+ }),
113
+ Type.Object({
114
+ ...Sequence,
115
+ type: Type.Literal("realtime-control"),
116
+ activationId: S,
117
+ action: Control
118
+ }),
119
+ Type.Object({
120
+ ...Sequence,
121
+ type: Type.Literal("realtime-send"),
122
+ activationId: S,
123
+ messages: Type.Array(S)
124
+ })
125
+ ]);
126
+ const RealtimeEvent = Type.Union([
127
+ Type.Object({ type: Type.Literal("ready") }),
128
+ Type.Object({
129
+ type: Type.Literal("transcript"),
130
+ role: values(["user", "assistant"]),
131
+ text: S,
132
+ complete: B
133
+ }),
134
+ Type.Object({
135
+ type: Type.Literal("request"),
136
+ requestId: S,
137
+ text: S
138
+ }),
139
+ Type.Object({
140
+ type: Type.Literal("error"),
141
+ code: S
142
+ })
143
+ ]);
144
+ const RealtimeSnapshot = Type.Object({
145
+ activationId: S,
146
+ state: values([
147
+ "connecting",
148
+ "active",
149
+ "closed",
150
+ "failed"
151
+ ]),
152
+ cursor: N,
153
+ events: Type.Array(Type.Object({
154
+ sequence: N,
155
+ event: RealtimeEvent
156
+ })),
157
+ browser: O(Browser)
158
+ });
159
+ const Wake = Type.Object({
160
+ eventEpoch: S,
161
+ sequence: N
162
+ });
163
+ const GlobalLiveStatus = Type.Object({
164
+ version: Type.Literal(1),
165
+ state: values([
166
+ "disabled",
167
+ "starting",
168
+ "active",
169
+ "draining",
170
+ "shuttingDown"
171
+ ]),
172
+ activeSessionId: Type.Union([S, Type.Null()]),
173
+ muted: B,
174
+ error: O(S),
175
+ media: Type.Object({
176
+ client: B,
177
+ realtime: B
178
+ })
179
+ });
180
+ const Version = { version: Type.Literal(3) };
181
+ const Targets = Type.Array(Type.Object({
182
+ handle: S,
183
+ label: S,
184
+ order: N
185
+ }), { maxItems: 32 });
186
+ const OwnershipAction = values([
187
+ "catalog",
188
+ "prepare",
189
+ "activate",
190
+ "deactivate",
191
+ "readiness",
192
+ "fence"
193
+ ]);
194
+ const Acknowledgement = Type.Object({
195
+ ...Version,
196
+ commandId: S,
197
+ action: OwnershipAction,
198
+ ok: B,
199
+ active: B,
200
+ error: O(S)
201
+ });
202
+ const Command = Type.Object({
203
+ ...Version,
204
+ commandId: S,
205
+ action: OwnershipAction,
206
+ targets: O(Targets),
207
+ catalogRevision: O(S),
208
+ handoffId: O(S),
209
+ controllerId: O(S),
210
+ leaseId: O(S),
211
+ revision: O(N)
212
+ });
213
+ const Snapshot = Type.Object({
214
+ registration: O(Type.Object({
215
+ ...Version,
216
+ leaseId: S,
217
+ revision: N,
218
+ label: S,
219
+ eligible: B,
220
+ active: B
221
+ })),
222
+ targets: Targets,
223
+ catalogRevision: O(S),
224
+ activation: O(Type.Object({
225
+ ...Version,
226
+ requestId: S
227
+ })),
228
+ handoff: O(Type.Object({
229
+ ...Version,
230
+ requestId: S,
231
+ handle: S,
232
+ catalogRevision: S
233
+ })),
234
+ acknowledgement: O(Acknowledgement)
235
+ });
236
+ const Errors = Object.fromEntries([
237
+ 400,
238
+ 404,
239
+ 409,
240
+ 410,
241
+ 413,
242
+ 415,
243
+ 429,
244
+ 500,
245
+ 502,
246
+ 503,
247
+ 504
248
+ ].map((status) => [status, {
249
+ description: "Voice request failed.",
250
+ schema: Type.Object({
251
+ error: S,
252
+ code: O(S)
253
+ })
254
+ }]));
255
+ const route = (path, method, output, input, query = [], status = 200) => ({
256
+ id: `voice.${path.slice(1).replaceAll("/", ".")}`,
257
+ scope: "session",
258
+ basePath: "voice-media",
259
+ path,
260
+ method,
261
+ authentication: "owner",
262
+ description: `Voice media ${path}.`,
263
+ ...path.startsWith("/host/") || path.startsWith("/hub/") ? { availability: "Internal broker route; requires the host-issued bearer token for this route namespace." } : {},
264
+ parameters: [...query.map((name) => ({
265
+ name,
266
+ in: "query",
267
+ required: !["after", "wait"].includes(name),
268
+ schema: S
269
+ })), ...path.startsWith("/host/") || path.startsWith("/hub/") ? [{
270
+ name: "Authorization",
271
+ in: "header",
272
+ required: true,
273
+ schema: Type.String({ pattern: "^Bearer .+" })
274
+ }] : []],
275
+ ...input ? { body: {
276
+ required: true,
277
+ contentType: "application/json",
278
+ schema: input
279
+ } } : {},
280
+ responses: {
281
+ ...Errors,
282
+ [output ? status : 204]: {
283
+ description: output ? "Voice response." : "Accepted with no response body.",
284
+ ...output ? { schema: output } : {}
285
+ }
286
+ }
287
+ });
288
+ const pcm = (path, method, query) => {
289
+ const result = route(path, method, void 0, void 0, query);
290
+ result.description = "PCM signed 16-bit little-endian, 16000 Hz, mono. Chunks contain complete samples. Activity headers carry state, level, elapsed time, epoch and speech duration. A 204 response carries x-po-capture-state or x-po-playback-state when applicable.";
291
+ if (method === "POST") result.body = {
292
+ required: true,
293
+ contentType: "application/vnd.po.pcm-s16le",
294
+ schema: S
295
+ };
296
+ else result.responses["200"] = {
297
+ description: "PCM bytes.",
298
+ contentType: "application/vnd.po.pcm-s16le",
299
+ schema: S
300
+ };
301
+ return result;
302
+ };
303
+ const apiContracts = defineApiContract({
304
+ version: 1,
305
+ protocols: {
306
+ "voice-media": "6",
307
+ "voice-ownership": "3"
308
+ },
309
+ dynamic: ["Realtime event strings and SDP are provider-defined protocol documents passed through the media broker."],
310
+ http: [
311
+ {
312
+ id: "voice.status",
313
+ scope: "session",
314
+ basePath: "voice",
315
+ path: "/status",
316
+ method: "GET",
317
+ authentication: "owner",
318
+ description: "Voice session status and media readiness.",
319
+ responses: jsonApiResponses(Type.Object({
320
+ ...voiceControlMethod.output.properties,
321
+ media: Type.Object({
322
+ closed: B,
323
+ capture: B,
324
+ playback: B,
325
+ realtime: B
326
+ }),
327
+ readiness: Type.Object({
328
+ configured: B,
329
+ transcription: B,
330
+ error: O(S),
331
+ engine: O(S),
332
+ mode: O(S),
333
+ correctionModel: O(S)
334
+ })
335
+ }))
336
+ },
337
+ {
338
+ id: "voice.control.http",
339
+ scope: "session",
340
+ basePath: "voice",
341
+ path: "/control",
342
+ method: "POST",
343
+ authentication: "owner",
344
+ description: "Control the voice session.",
345
+ body: {
346
+ required: true,
347
+ contentType: "application/json",
348
+ schema: voiceControlMethod.input
349
+ },
350
+ responses: jsonApiResponses(voiceControlMethod.output)
351
+ },
352
+ route("/client/connect", "POST", Type.Object({
353
+ version: Type.Literal(6),
354
+ cursor: N,
355
+ eventEpoch: O(S),
356
+ heartbeatMs: O(N)
357
+ }), Type.Object({
358
+ version: Type.Literal(6),
359
+ ...Client,
360
+ clientKind: values(["browser", "native"]),
361
+ controlLocation: values(["local", "remote"]),
362
+ capabilities: Type.Object({
363
+ capture: B,
364
+ playback: B,
365
+ captureActivity: B,
366
+ autonomousOrchestration: B,
367
+ playbackDucking: O(B),
368
+ realtime: O(B)
369
+ })
370
+ })),
371
+ route("/client/disconnect", "POST", void 0, Type.Object(Client)),
372
+ route("/client/heartbeat", "POST", Wake, Type.Object(Client)),
373
+ {
374
+ ...route("/client/events", "GET", VoiceMediaEventSchema, void 0, [
375
+ "clientId",
376
+ "connectionId",
377
+ "after",
378
+ "wait"
379
+ ]),
380
+ responses: {
381
+ ...Errors,
382
+ "200": {
383
+ description: "Next event.",
384
+ schema: VoiceMediaEventSchema
385
+ },
386
+ "204": { description: "No pending event." }
387
+ }
388
+ },
389
+ pcm("/client/audio", "POST", [
390
+ "clientId",
391
+ "connectionId",
392
+ "captureId"
393
+ ]),
394
+ route("/client/capture-stopped", "POST", void 0, Type.Object({
395
+ ...Client,
396
+ captureId: S,
397
+ error: O(S)
398
+ })),
399
+ pcm("/client/playback-audio", "GET", [
400
+ "clientId",
401
+ "connectionId",
402
+ "playbackId"
403
+ ]),
404
+ route("/client/playback-result", "POST", void 0, Type.Object({
405
+ ...Client,
406
+ ...Playback
407
+ })),
408
+ route("/host/capture/start", "POST", Type.Object({ configuration: Configuration }), Type.Object({
409
+ captureId: S,
410
+ configuration: O(Configuration)
411
+ }), [], 201),
412
+ pcm("/host/capture/audio", "GET", ["captureId"]),
413
+ ...["stop", "abort"].map((action) => route(`/host/capture/${action}`, "POST", void 0, Type.Object({ captureId: S }))),
414
+ route("/host/playback/start", "POST", Type.Object({ delivery: values(["client", "streamed"]) }), Type.Object({
415
+ playbackId: S,
416
+ text: S,
417
+ voice: O(S),
418
+ rate: O(N)
419
+ }), [], 201),
420
+ pcm("/host/playback/audio", "POST", ["playbackId"]),
421
+ route("/host/playback/audio-end", "POST", void 0, Type.Object({
422
+ playbackId: S,
423
+ error: O(S)
424
+ })),
425
+ {
426
+ ...route("/host/playback/result", "GET", Type.Object(Playback), void 0, ["playbackId"]),
427
+ responses: {
428
+ ...Errors,
429
+ "200": {
430
+ description: "Playback outcome.",
431
+ schema: Type.Object(Playback)
432
+ },
433
+ "204": { description: "Playback is pending." }
434
+ }
435
+ },
436
+ ...["stop", "abort"].map((action) => route(`/host/playback/${action}`, "POST", void 0, Type.Object({ playbackId: S }))),
437
+ route("/hub/ownership/state", "GET", Snapshot),
438
+ route("/hub/ownership/command", "POST", Acknowledgement, Command),
439
+ route("/host/ownership/sync", "POST", Type.Object({ command: O(Command) }), Snapshot),
440
+ route("/host/realtime/start", "POST", Type.Object({}), Type.Object({
441
+ activationId: S,
442
+ instructions: Type.String({ maxLength: 16384 })
443
+ }), [], 201),
444
+ route("/host/realtime/stop", "POST", void 0, Type.Object({ activationId: S })),
445
+ route("/host/realtime/poll", "GET", RealtimeSnapshot, void 0, ["activationId", "after"]),
446
+ route("/host/realtime/send", "POST", void 0, Type.Object({
447
+ activationId: S,
448
+ messages: Type.Array(S, { maxItems: 64 })
449
+ })),
450
+ route("/host/realtime/control", "POST", void 0, Type.Object({
451
+ activationId: S,
452
+ action: Control
453
+ })),
454
+ route("/client/realtime/negotiate", "POST", Type.Object({ sdp: S }), Type.Object({
455
+ ...Client,
456
+ activationId: S,
457
+ sdp: S
458
+ })),
459
+ route("/client/realtime/event", "POST", void 0, Type.Object({
460
+ ...Client,
461
+ activationId: S,
462
+ event: S
463
+ })),
464
+ route("/client/realtime/state", "POST", void 0, Type.Object({
465
+ ...Client,
466
+ activationId: S,
467
+ state: Browser
468
+ })),
469
+ {
470
+ id: "voice.manual",
471
+ scope: "session",
472
+ basePath: "voice-media",
473
+ path: "/manual/transcribe",
474
+ method: "POST",
475
+ authentication: "owner",
476
+ description: "Transcribe at most 4 MiB of WebM/Opus or MP4/AAC audio, at most 300000 milliseconds.",
477
+ parameters: [{
478
+ name: "x-doom-audio-duration-ms",
479
+ in: "header",
480
+ required: true,
481
+ schema: Type.Integer({
482
+ minimum: 0,
483
+ maximum: 3e5
484
+ })
485
+ }],
486
+ body: {
487
+ required: true,
488
+ contentType: "audio/webm",
489
+ contentTypes: ["audio/webm", "audio/mp4"],
490
+ schema: S
491
+ },
492
+ responses: {
493
+ ...Errors,
494
+ "200": {
495
+ description: "Transcript.",
496
+ schema: Type.Object({ transcript: S })
497
+ }
498
+ }
499
+ },
500
+ ...[
501
+ [
502
+ "readiness",
503
+ "/live/agent",
504
+ "GET"
505
+ ],
506
+ [
507
+ "prepare",
508
+ "/live/agent/prepare",
509
+ "POST"
510
+ ],
511
+ [
512
+ "admit",
513
+ "/live/agent/admit",
514
+ "POST"
515
+ ],
516
+ [
517
+ "results",
518
+ "/live/agent/results",
519
+ "GET"
520
+ ],
521
+ [
522
+ "ack",
523
+ "/live/agent/results/ack",
524
+ "POST"
525
+ ],
526
+ [
527
+ "fence",
528
+ "/live/agent/fence",
529
+ "POST"
530
+ ],
531
+ [
532
+ "select",
533
+ "/live/agent/select",
534
+ "POST"
535
+ ],
536
+ [
537
+ "revoke",
538
+ "/live/agent/revoke",
539
+ "POST"
540
+ ]
541
+ ].map(([name, path, method]) => ({
542
+ id: `voice.agent.${name}`,
543
+ scope: "session",
544
+ basePath: "voice",
545
+ path,
546
+ method,
547
+ authentication: "owner",
548
+ description: `Native Voice agent ${name}. Only the host-issued hub bearer can access this route.`,
549
+ parameters: [{
550
+ name: "Authorization",
551
+ in: "header",
552
+ required: true,
553
+ schema: Type.String({ pattern: "^Bearer .+" })
554
+ }, ...name === "results" ? [
555
+ "activationId",
556
+ "routeGeneration",
557
+ "sessionIncarnation",
558
+ "after"
559
+ ].map((key) => ({
560
+ name: key,
561
+ in: "query",
562
+ required: key !== "after",
563
+ schema: S
564
+ })) : []],
565
+ ...method === "POST" ? { body: {
566
+ required: true,
567
+ contentType: "application/json",
568
+ schema: name === "select" ? Type.Object({
569
+ activationId: S,
570
+ routeGeneration: Type.Integer({ minimum: 1 }),
571
+ transactionId: S,
572
+ sessionIncarnation: S,
573
+ nativeTransferAllowed: B,
574
+ catalog: Type.Object({
575
+ revision: S,
576
+ targets: Type.Array(Type.Object({
577
+ order: Type.Integer({ minimum: 1 }),
578
+ label: S
579
+ }), { maxItems: 256 })
580
+ })
581
+ }) : name === "revoke" ? Type.Object({
582
+ activationId: S,
583
+ routeGeneration: Type.Integer({ minimum: 1 }),
584
+ transactionId: S,
585
+ sessionIncarnation: S
586
+ }) : Type.Unknown()
587
+ } } : {},
588
+ responses: {
589
+ ...jsonApiResponses(Type.Unknown()),
590
+ "204": { description: "Agent result acknowledged or route fenced." }
591
+ }
592
+ })),
593
+ {
594
+ id: "voice.peer",
595
+ scope: "global",
596
+ basePath: "voice",
597
+ path: "/peer",
598
+ method: "POST",
599
+ authentication: "none",
600
+ description: "Accept an HMAC-authenticated bounded Voice media relay request from a configured peer.",
601
+ body: {
602
+ required: true,
603
+ contentType: "application/json",
604
+ schema: Type.Unknown()
605
+ },
606
+ responses: jsonApiResponses(Type.Unknown())
607
+ },
608
+ {
609
+ id: "voice.peerOwnership",
610
+ scope: "global",
611
+ basePath: "voice",
612
+ path: "/peer-ownership",
613
+ method: "POST",
614
+ authentication: "none",
615
+ description: "Discover and stage Voice ownership through an HMAC-authenticated paired host.",
616
+ body: {
617
+ required: true,
618
+ contentType: "application/json",
619
+ schema: Type.Unknown()
620
+ },
621
+ responses: jsonApiResponses(Type.Unknown())
622
+ },
623
+ {
624
+ id: "voice.peerAgent",
625
+ scope: "global",
626
+ basePath: "voice",
627
+ path: "/peer-agent",
628
+ method: "POST",
629
+ authentication: "none",
630
+ description: "Accept a signed, replay-guarded, grant-scoped native Voice agent request from a configured peer.",
631
+ body: {
632
+ required: true,
633
+ contentType: "application/json",
634
+ schema: Type.Unknown()
635
+ },
636
+ responses: jsonApiResponses(Type.Unknown())
637
+ },
638
+ {
639
+ id: "voice.relayBinding",
640
+ scope: "global",
641
+ basePath: "voice",
642
+ path: "/relay-binding",
643
+ method: "POST",
644
+ authentication: "owner",
645
+ description: "Issue an expiring controller-bound handle for a granted paired Voice session.",
646
+ body: {
647
+ required: true,
648
+ contentType: "application/json",
649
+ schema: Type.Object({
650
+ target: S,
651
+ connectionId: S
652
+ })
653
+ },
654
+ responses: jsonApiResponses(Type.Object({
655
+ binding: S,
656
+ expiresAt: N
657
+ }))
658
+ },
659
+ {
660
+ id: "voice.relay",
661
+ scope: "global",
662
+ basePath: "voice",
663
+ path: "/relay",
664
+ method: "POST",
665
+ authentication: "owner",
666
+ description: "Relay a browser Voice media operation through an expiring controller-bound handle.",
667
+ parameters: [{
668
+ name: "binding",
669
+ in: "query",
670
+ required: true,
671
+ schema: S
672
+ }],
673
+ body: {
674
+ required: true,
675
+ contentType: "application/json",
676
+ schema: Type.Unknown()
677
+ },
678
+ responses: jsonApiResponses(Type.Unknown())
679
+ },
680
+ {
681
+ id: "voice.nativeTransfer",
682
+ scope: "global",
683
+ basePath: "voice",
684
+ path: "/live/native-transfer",
685
+ method: "POST",
686
+ authentication: "owner",
687
+ description: "Host-only revision-bound native Live transfer. Requires the host hub bearer.",
688
+ parameters: [{
689
+ name: "Authorization",
690
+ in: "header",
691
+ required: true,
692
+ schema: Type.String({ pattern: "^Bearer .+" })
693
+ }],
694
+ body: {
695
+ required: true,
696
+ contentType: "application/json",
697
+ schema: Type.Object({
698
+ sourceSessionId: S,
699
+ activationId: S,
700
+ routeGeneration: Type.Integer({ minimum: 0 }),
701
+ sessionIncarnation: S,
702
+ ordinal: Type.Integer({ minimum: 1 }),
703
+ catalogRevision: S
704
+ })
705
+ },
706
+ responses: {
707
+ ...Errors,
708
+ "202": {
709
+ description: "Transfer requested; source work drains before commit.",
710
+ schema: Type.Object({ requested: Type.Literal(true) })
711
+ }
712
+ }
713
+ },
714
+ {
715
+ id: "voice.liveStatus",
716
+ scope: "global",
717
+ basePath: "voice",
718
+ path: "/live/status",
719
+ method: "GET",
720
+ authentication: "owner",
721
+ description: "Read the host-global live companion state without activating media.",
722
+ responses: jsonApiResponses(GlobalLiveStatus)
723
+ },
724
+ {
725
+ id: "voice.liveControl",
726
+ scope: "global",
727
+ basePath: "voice",
728
+ path: "/live/control",
729
+ method: "POST",
730
+ authentication: "owner",
731
+ description: "Explicitly activate, transfer, mute, interrupt or end the host-global live companion.",
732
+ body: {
733
+ required: true,
734
+ contentType: "application/json",
735
+ schema: Type.Object({
736
+ action: values([
737
+ "activate",
738
+ "transfer",
739
+ "mute",
740
+ "unmute",
741
+ "interrupt",
742
+ "end"
743
+ ]),
744
+ sessionId: O(S),
745
+ expectedSourceSessionId: O(S)
746
+ })
747
+ },
748
+ responses: jsonApiResponses(GlobalLiveStatus)
749
+ },
750
+ {
751
+ id: "voice.readiness",
752
+ scope: "global",
753
+ basePath: "voice",
754
+ path: "/readiness",
755
+ method: "GET",
756
+ authentication: "owner",
757
+ description: "Read configured voice readiness.",
758
+ responses: jsonApiResponses(Type.Object({
759
+ configured: B,
760
+ transcription: B,
761
+ error: O(S),
762
+ engine: O(S),
763
+ mode: O(S),
764
+ correctionModel: O(S)
765
+ }))
766
+ }
767
+ ],
768
+ sockets: [{
769
+ id: "voice.control",
770
+ scope: "session",
771
+ service: voiceControlMethod.service,
772
+ member: voiceControlMethod.method,
773
+ kind: "method",
774
+ direction: "client-to-server",
775
+ description: "Voice session control through the scoped plugin service.",
776
+ input: voiceControlMethod.input,
777
+ output: voiceControlMethod.output
778
+ }, ...["global", "workspace"].flatMap((scope) => [{
779
+ id: "voice.wake",
780
+ scope,
781
+ service: "po.hub.v1",
782
+ member: "voice_media_wake",
783
+ kind: "channel",
784
+ direction: "server-to-client",
785
+ description: "Voice media wake channel payload.",
786
+ input: Wake
787
+ }, {
788
+ id: "voice.ownership",
789
+ scope,
790
+ service: "po.hub.v1",
791
+ member: "voice_ownership",
792
+ kind: "channel",
793
+ direction: "server-to-client",
794
+ description: "Browser media ownership channel payload.",
795
+ input: Type.Object({
796
+ type: Type.Literal("browser-media-session"),
797
+ ...Version,
798
+ activeSessionId: Type.Union([S, Type.Null()])
799
+ })
800
+ }])]
801
+ });
802
+ //#endregion
803
+ export { apiContracts, apiContracts as default };
804
+
805
+ //# sourceMappingURL=apiContracts.mjs.map