xo-harness 0.2.0 → 0.3.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 (115) hide show
  1. package/README.md +92 -5
  2. package/dist/browser/worklets/capture-processor.js +34 -0
  3. package/dist/browser/worklets/playback-processor.js +188 -0
  4. package/dist/browser.d.ts +1 -0
  5. package/dist/browser.js +1 -0
  6. package/dist/internal/browser/browser-voice-client.d.ts +33 -0
  7. package/dist/internal/browser/browser-voice-client.js +316 -0
  8. package/dist/internal/browser/index.d.ts +2 -0
  9. package/dist/internal/browser/index.js +1 -0
  10. package/dist/internal/harness/conversation-context.d.ts +45 -0
  11. package/dist/internal/harness/conversation-context.js +79 -0
  12. package/dist/internal/harness/conversation-projection.d.ts +55 -0
  13. package/dist/internal/harness/conversation-projection.js +145 -0
  14. package/dist/internal/harness/event-stream.d.ts +23 -2
  15. package/dist/internal/harness/event-stream.js +148 -18
  16. package/dist/internal/harness/index.d.ts +7 -1
  17. package/dist/internal/harness/index.js +7 -1
  18. package/dist/internal/harness/message.d.ts +24 -11
  19. package/dist/internal/harness/message.js +271 -77
  20. package/dist/internal/harness/report-diff.d.ts +3 -0
  21. package/dist/internal/harness/report-diff.js +10 -0
  22. package/dist/internal/harness/report.d.ts +17 -14
  23. package/dist/internal/harness/report.js +41 -24
  24. package/dist/internal/harness/runtime-limits.d.ts +18 -0
  25. package/dist/internal/harness/runtime-limits.js +19 -0
  26. package/dist/internal/harness/session-persistence.d.ts +16 -0
  27. package/dist/internal/harness/session-persistence.js +106 -0
  28. package/dist/internal/harness/shadow.d.ts +5 -5
  29. package/dist/internal/harness/shadow.js +214 -52
  30. package/dist/internal/harness/socket-bridge.d.ts +45 -4
  31. package/dist/internal/harness/socket-bridge.js +215 -46
  32. package/dist/internal/harness/task-supervisor.d.ts +6 -2
  33. package/dist/internal/harness/task-supervisor.js +97 -15
  34. package/dist/internal/harness/tool-calls.d.ts +40 -0
  35. package/dist/internal/harness/tool-calls.js +132 -0
  36. package/dist/internal/harness/tool-policy.d.ts +2 -2
  37. package/dist/internal/harness/tool-runtime.d.ts +2 -2
  38. package/dist/internal/harness/tool-runtime.js +37 -40
  39. package/dist/internal/harness/tools.d.ts +21 -0
  40. package/dist/internal/harness/tools.js +7 -1
  41. package/dist/internal/harness/usage-tracker.d.ts +39 -0
  42. package/dist/internal/harness/usage-tracker.js +104 -0
  43. package/dist/internal/harness/voice-session.d.ts +39 -8
  44. package/dist/internal/harness/voice-session.js +353 -58
  45. package/dist/internal/harness/xo.d.ts +7 -12
  46. package/dist/internal/harness/xo.js +25 -13
  47. package/dist/internal/protocol/async-queue.d.ts +22 -1
  48. package/dist/internal/protocol/async-queue.js +86 -12
  49. package/dist/internal/protocol/audio.d.ts +16 -2
  50. package/dist/internal/protocol/audio.js +23 -5
  51. package/dist/internal/protocol/backend-output.d.ts +70 -0
  52. package/dist/internal/protocol/backend-output.js +39 -0
  53. package/dist/internal/protocol/event-json.d.ts +3 -0
  54. package/dist/internal/protocol/event-json.js +15 -0
  55. package/dist/internal/protocol/events.d.ts +342 -4
  56. package/dist/internal/protocol/events.js +53 -25
  57. package/dist/internal/protocol/index.d.ts +5 -0
  58. package/dist/internal/protocol/index.js +5 -0
  59. package/dist/internal/protocol/output-source.d.ts +18 -0
  60. package/dist/internal/protocol/output-source.js +15 -0
  61. package/dist/internal/protocol/paced-audio.d.ts +27 -0
  62. package/dist/internal/protocol/paced-audio.js +117 -0
  63. package/dist/internal/protocol/parts.d.ts +154 -0
  64. package/dist/internal/protocol/parts.js +32 -6
  65. package/dist/internal/protocol/provider.d.ts +308 -1
  66. package/dist/internal/protocol/provider.js +102 -3
  67. package/dist/internal/protocol/records.d.ts +773 -0
  68. package/dist/internal/protocol/records.js +46 -0
  69. package/dist/internal/protocol/tools.d.ts +40 -0
  70. package/dist/internal/protocol/tools.js +12 -0
  71. package/dist/internal/protocol/transcript.d.ts +19 -0
  72. package/dist/internal/protocol/transcript.js +53 -0
  73. package/dist/internal/provider/contract.d.ts +25 -2
  74. package/dist/internal/provider/event-queue.d.ts +17 -0
  75. package/dist/internal/provider/event-queue.js +78 -0
  76. package/dist/internal/provider/grok-voice.d.ts +12 -9
  77. package/dist/internal/provider/grok-voice.js +26 -15
  78. package/dist/internal/provider/index.d.ts +1 -0
  79. package/dist/internal/provider/index.js +1 -0
  80. package/dist/internal/provider/live-session.d.ts +29 -0
  81. package/dist/internal/provider/live-session.js +840 -0
  82. package/dist/internal/provider/node-socket.js +6 -0
  83. package/dist/internal/provider/openai-live.d.ts +62 -0
  84. package/dist/internal/provider/openai-live.js +160 -0
  85. package/dist/internal/provider/openai-realtime.d.ts +9 -5
  86. package/dist/internal/provider/openai-realtime.js +24 -10
  87. package/dist/internal/provider/realtime-session.d.ts +12 -1
  88. package/dist/internal/provider/realtime-session.js +373 -70
  89. package/dist/internal/provider/realtime-socket.d.ts +3 -1
  90. package/dist/internal/provider/tool-status-context.d.ts +10 -0
  91. package/dist/internal/provider/tool-status-context.js +30 -0
  92. package/dist/internal/provider/workers-socket.js +63 -15
  93. package/dist/internal/provider/workers.d.ts +1 -0
  94. package/dist/internal/provider/workers.js +1 -0
  95. package/dist/internal/provider-fake/replay-voice-provider.d.ts +9 -11
  96. package/dist/internal/provider-fake/replay-voice-provider.js +47 -23
  97. package/dist/internal/storage/event-store.d.ts +22 -4
  98. package/dist/internal/storage/jsonl-event-store.d.ts +4 -4
  99. package/dist/internal/storage/jsonl-event-store.js +21 -16
  100. package/dist/internal/storage/memory-event-store.d.ts +4 -3
  101. package/dist/internal/storage/memory-event-store.js +8 -2
  102. package/dist/internal/storage/memory.d.ts +1 -1
  103. package/dist/internal/testkit/events.d.ts +14 -0
  104. package/dist/internal/testkit/events.js +33 -0
  105. package/dist/internal/testkit/runtime.d.ts +3 -0
  106. package/dist/internal/testkit/runtime.js +3 -0
  107. package/dist/internal/testkit/trajectory.d.ts +23 -0
  108. package/dist/internal/testkit/trajectory.js +58 -0
  109. package/dist/internal/tools-openai/index.d.ts +2 -0
  110. package/dist/internal/tools-openai/index.js +79 -72
  111. package/dist/internal/tools-openai/responses.d.ts +5 -1
  112. package/dist/internal/tools-openai/responses.js +53 -5
  113. package/dist/testing.d.ts +1 -0
  114. package/dist/testing.js +1 -0
  115. package/package.json +7 -1
@@ -1,9 +1,61 @@
1
1
  import { z } from "zod";
2
2
  /** Bounds for a typed user message, shared by the event, the session API, and wire schemas. */
3
3
  export declare const MessageInputTextSchema: z.ZodString;
4
+ export declare const InputAudioEventSchema: z.ZodObject<{
5
+ id: z.ZodString;
6
+ sessionId: z.ZodString;
7
+ sequence: z.ZodInt;
8
+ recordedAtMs: z.ZodNumber;
9
+ sessionTimeMs: z.ZodNumber;
10
+ correlationId: z.ZodOptional<z.ZodString>;
11
+ causationId: z.ZodOptional<z.ZodString>;
12
+ type: z.ZodLiteral<"audio.input">;
13
+ chunk: z.ZodObject<{
14
+ streamId: z.ZodString;
15
+ sequence: z.ZodInt;
16
+ encoding: z.ZodLiteral<"pcm_s16le">;
17
+ sampleRate: z.ZodInt;
18
+ channels: z.ZodInt;
19
+ startSample: z.ZodInt;
20
+ data: z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Array<ArrayBuffer>>;
21
+ }, z.core.$strict>;
22
+ syntheticSilence: z.ZodOptional<z.ZodBoolean>;
23
+ }, z.core.$strip>;
24
+ export declare const OutputAudioEventSchema: z.ZodObject<{
25
+ id: z.ZodString;
26
+ sessionId: z.ZodString;
27
+ sequence: z.ZodInt;
28
+ recordedAtMs: z.ZodNumber;
29
+ sessionTimeMs: z.ZodNumber;
30
+ correlationId: z.ZodOptional<z.ZodString>;
31
+ causationId: z.ZodOptional<z.ZodString>;
32
+ type: z.ZodLiteral<"audio.output">;
33
+ chunk: z.ZodObject<{
34
+ streamId: z.ZodString;
35
+ sequence: z.ZodInt;
36
+ encoding: z.ZodLiteral<"pcm_s16le">;
37
+ sampleRate: z.ZodInt;
38
+ channels: z.ZodInt;
39
+ startSample: z.ZodInt;
40
+ data: z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Array<ArrayBuffer>>;
41
+ }, z.core.$strict>;
42
+ source: z.ZodOptional<z.ZodObject<{
43
+ scope: z.ZodEnum<{
44
+ backend: "backend";
45
+ voice: "voice";
46
+ }>;
47
+ responseId: z.ZodOptional<z.ZodString>;
48
+ itemId: z.ZodOptional<z.ZodString>;
49
+ outputIndex: z.ZodOptional<z.ZodInt>;
50
+ contentIndex: z.ZodOptional<z.ZodInt>;
51
+ summaryIndex: z.ZodOptional<z.ZodInt>;
52
+ delegationId: z.ZodOptional<z.ZodString>;
53
+ }, z.core.$strip>>;
54
+ }, z.core.$strip>;
4
55
  /**
5
- * The authoritative session log: every observable fact of a conversation, in one flat,
6
- * durably ordered stream. There is deliberately no turn or message hierarchy here —
56
+ * Sequenced live facts of a conversation, in one flat, store-ordered stream. Retained
57
+ * HarnessRecord values preserve this envelope and may explicitly omit audio bytes.
58
+ * There is deliberately no turn or message hierarchy here —
7
59
  * duplex audio overlaps — conversation views are projections over this log.
8
60
  * The full catalog with ordering rules lives in docs/protocol.md.
9
61
  */
@@ -23,8 +75,25 @@ export declare const HarnessEventSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
23
75
  modelManagedFloor: z.ZodBoolean;
24
76
  supportsToolCalls: z.ZodBoolean;
25
77
  supportsAsyncContext: z.ZodBoolean;
78
+ supportsToolStatusContext: z.ZodOptional<z.ZodBoolean>;
26
79
  supportsPlayoutAcknowledgements: z.ZodBoolean;
27
80
  reportsResponseState: z.ZodOptional<z.ZodBoolean>;
81
+ inputCadence: z.ZodOptional<z.ZodEnum<{
82
+ continuous: "continuous";
83
+ "on-demand": "on-demand";
84
+ }>>;
85
+ outputLifecycle: z.ZodOptional<z.ZodEnum<{
86
+ continuous: "continuous";
87
+ response: "response";
88
+ }>>;
89
+ supportsAssistantTurn: z.ZodOptional<z.ZodBoolean>;
90
+ supportsTextOutput: z.ZodOptional<z.ZodBoolean>;
91
+ textInput: z.ZodOptional<z.ZodEnum<{
92
+ backend: "backend";
93
+ conversation: "conversation";
94
+ unsupported: "unsupported";
95
+ }>>;
96
+ maxContextUpdateBytes: z.ZodOptional<z.ZodInt>;
28
97
  }, z.core.$strip>;
29
98
  instructions: z.ZodOptional<z.ZodString>;
30
99
  outputModalities: z.ZodOptional<z.ZodArray<z.ZodEnum<{
@@ -118,6 +187,7 @@ export declare const HarnessEventSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
118
187
  causationId: z.ZodOptional<z.ZodString>;
119
188
  type: z.ZodLiteral<"provider.closed">;
120
189
  reason: z.ZodString;
190
+ finalized: z.ZodOptional<z.ZodBoolean>;
121
191
  }, z.core.$strip>, z.ZodObject<{
122
192
  id: z.ZodString;
123
193
  sessionId: z.ZodString;
@@ -152,6 +222,26 @@ export declare const HarnessEventSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
152
222
  url: z.ZodString;
153
223
  filename: z.ZodOptional<z.ZodString>;
154
224
  }, z.core.$strip>], "type">>>;
225
+ }, z.core.$strip>, z.ZodObject<{
226
+ id: z.ZodString;
227
+ sessionId: z.ZodString;
228
+ sequence: z.ZodInt;
229
+ recordedAtMs: z.ZodNumber;
230
+ sessionTimeMs: z.ZodNumber;
231
+ correlationId: z.ZodOptional<z.ZodString>;
232
+ causationId: z.ZodOptional<z.ZodString>;
233
+ type: z.ZodLiteral<"input.delivery">;
234
+ inputId: z.ZodString;
235
+ providerId: z.ZodString;
236
+ target: z.ZodEnum<{
237
+ backend: "backend";
238
+ conversation: "conversation";
239
+ }>;
240
+ phase: z.ZodEnum<{
241
+ failed: "failed";
242
+ submitted: "submitted";
243
+ }>;
244
+ error: z.ZodOptional<z.ZodString>;
155
245
  }, z.core.$strip>, z.ZodObject<{
156
246
  id: z.ZodString;
157
247
  sessionId: z.ZodString;
@@ -169,7 +259,8 @@ export declare const HarnessEventSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
169
259
  channels: z.ZodInt;
170
260
  startSample: z.ZodInt;
171
261
  data: z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Array<ArrayBuffer>>;
172
- }, z.core.$strip>;
262
+ }, z.core.$strict>;
263
+ syntheticSilence: z.ZodOptional<z.ZodBoolean>;
173
264
  }, z.core.$strip>, z.ZodObject<{
174
265
  id: z.ZodString;
175
266
  sessionId: z.ZodString;
@@ -187,7 +278,19 @@ export declare const HarnessEventSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
187
278
  channels: z.ZodInt;
188
279
  startSample: z.ZodInt;
189
280
  data: z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Array<ArrayBuffer>>;
190
- }, z.core.$strip>;
281
+ }, z.core.$strict>;
282
+ source: z.ZodOptional<z.ZodObject<{
283
+ scope: z.ZodEnum<{
284
+ backend: "backend";
285
+ voice: "voice";
286
+ }>;
287
+ responseId: z.ZodOptional<z.ZodString>;
288
+ itemId: z.ZodOptional<z.ZodString>;
289
+ outputIndex: z.ZodOptional<z.ZodInt>;
290
+ contentIndex: z.ZodOptional<z.ZodInt>;
291
+ summaryIndex: z.ZodOptional<z.ZodInt>;
292
+ delegationId: z.ZodOptional<z.ZodString>;
293
+ }, z.core.$strip>>;
191
294
  }, z.core.$strip>, z.ZodObject<{
192
295
  id: z.ZodString;
193
296
  sessionId: z.ZodString;
@@ -205,6 +308,18 @@ export declare const HarnessEventSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
205
308
  }>;
206
309
  text: z.ZodString;
207
310
  streamId: z.ZodOptional<z.ZodString>;
311
+ source: z.ZodOptional<z.ZodObject<{
312
+ scope: z.ZodEnum<{
313
+ backend: "backend";
314
+ voice: "voice";
315
+ }>;
316
+ responseId: z.ZodOptional<z.ZodString>;
317
+ itemId: z.ZodOptional<z.ZodString>;
318
+ outputIndex: z.ZodOptional<z.ZodInt>;
319
+ contentIndex: z.ZodOptional<z.ZodInt>;
320
+ summaryIndex: z.ZodOptional<z.ZodInt>;
321
+ delegationId: z.ZodOptional<z.ZodString>;
322
+ }, z.core.$strip>>;
208
323
  id: z.ZodString;
209
324
  sessionId: z.ZodString;
210
325
  sequence: z.ZodInt;
@@ -220,6 +335,18 @@ export declare const HarnessEventSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
220
335
  }>;
221
336
  delta: z.ZodString;
222
337
  streamId: z.ZodOptional<z.ZodString>;
338
+ source: z.ZodOptional<z.ZodObject<{
339
+ scope: z.ZodEnum<{
340
+ backend: "backend";
341
+ voice: "voice";
342
+ }>;
343
+ responseId: z.ZodOptional<z.ZodString>;
344
+ itemId: z.ZodOptional<z.ZodString>;
345
+ outputIndex: z.ZodOptional<z.ZodInt>;
346
+ contentIndex: z.ZodOptional<z.ZodInt>;
347
+ summaryIndex: z.ZodOptional<z.ZodInt>;
348
+ delegationId: z.ZodOptional<z.ZodString>;
349
+ }, z.core.$strip>>;
223
350
  id: z.ZodString;
224
351
  sessionId: z.ZodString;
225
352
  sequence: z.ZodInt;
@@ -229,6 +356,193 @@ export declare const HarnessEventSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
229
356
  causationId: z.ZodOptional<z.ZodString>;
230
357
  type: z.ZodLiteral<"transcript.delta">;
231
358
  }, z.core.$strip>, z.ZodObject<{
359
+ role: z.ZodEnum<{
360
+ assistant: "assistant";
361
+ user: "user";
362
+ }>;
363
+ text: z.ZodString;
364
+ fragmentId: z.ZodString;
365
+ startMs: z.ZodNumber;
366
+ endMs: z.ZodNumber;
367
+ timebase: z.ZodLiteral<"provider-session">;
368
+ id: z.ZodString;
369
+ sessionId: z.ZodString;
370
+ sequence: z.ZodInt;
371
+ recordedAtMs: z.ZodNumber;
372
+ sessionTimeMs: z.ZodNumber;
373
+ correlationId: z.ZodOptional<z.ZodString>;
374
+ causationId: z.ZodOptional<z.ZodString>;
375
+ type: z.ZodLiteral<"transcript.fragment">;
376
+ }, z.core.$strip>, z.ZodObject<{
377
+ kind: z.ZodEnum<{
378
+ reasoning_summary: "reasoning_summary";
379
+ refusal: "refusal";
380
+ text: "text";
381
+ }>;
382
+ source: z.ZodObject<{
383
+ delegationId: z.ZodOptional<z.ZodString>;
384
+ scope: z.ZodLiteral<"backend">;
385
+ responseId: z.ZodString;
386
+ itemId: z.ZodString;
387
+ outputIndex: z.ZodInt;
388
+ contentIndex: z.ZodOptional<z.ZodInt>;
389
+ summaryIndex: z.ZodOptional<z.ZodInt>;
390
+ }, z.core.$strip>;
391
+ delta: z.ZodString;
392
+ id: z.ZodString;
393
+ sessionId: z.ZodString;
394
+ sequence: z.ZodInt;
395
+ recordedAtMs: z.ZodNumber;
396
+ sessionTimeMs: z.ZodNumber;
397
+ correlationId: z.ZodOptional<z.ZodString>;
398
+ causationId: z.ZodOptional<z.ZodString>;
399
+ type: z.ZodLiteral<"backend.output.delta">;
400
+ }, z.core.$strip>, z.ZodObject<{
401
+ source: z.ZodObject<{
402
+ delegationId: z.ZodOptional<z.ZodString>;
403
+ scope: z.ZodLiteral<"backend">;
404
+ responseId: z.ZodString;
405
+ itemId: z.ZodString;
406
+ outputIndex: z.ZodInt;
407
+ }, z.core.$strip>;
408
+ content: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
409
+ kind: z.ZodEnum<{
410
+ refusal: "refusal";
411
+ text: "text";
412
+ }>;
413
+ text: z.ZodString;
414
+ contentIndex: z.ZodInt;
415
+ }, z.core.$strip>, z.ZodObject<{
416
+ kind: z.ZodLiteral<"reasoning_summary">;
417
+ text: z.ZodString;
418
+ summaryIndex: z.ZodInt;
419
+ }, z.core.$strip>], "kind">>;
420
+ status: z.ZodOptional<z.ZodEnum<{
421
+ cancelled: "cancelled";
422
+ completed: "completed";
423
+ failed: "failed";
424
+ in_progress: "in_progress";
425
+ incomplete: "incomplete";
426
+ }>>;
427
+ id: z.ZodString;
428
+ sessionId: z.ZodString;
429
+ sequence: z.ZodInt;
430
+ recordedAtMs: z.ZodNumber;
431
+ sessionTimeMs: z.ZodNumber;
432
+ correlationId: z.ZodOptional<z.ZodString>;
433
+ causationId: z.ZodOptional<z.ZodString>;
434
+ type: z.ZodLiteral<"backend.output">;
435
+ }, z.core.$strip>, z.ZodObject<{
436
+ delegationId: z.ZodOptional<z.ZodString>;
437
+ responseId: z.ZodString;
438
+ phase: z.ZodEnum<{
439
+ completed: "completed";
440
+ started: "started";
441
+ "waiting-for-tools": "waiting-for-tools";
442
+ }>;
443
+ status: z.ZodOptional<z.ZodString>;
444
+ id: z.ZodString;
445
+ sessionId: z.ZodString;
446
+ sequence: z.ZodInt;
447
+ recordedAtMs: z.ZodNumber;
448
+ sessionTimeMs: z.ZodNumber;
449
+ correlationId: z.ZodOptional<z.ZodString>;
450
+ causationId: z.ZodOptional<z.ZodString>;
451
+ type: z.ZodLiteral<"backend.response">;
452
+ }, z.core.$strip>, z.ZodObject<{
453
+ delegationId: z.ZodOptional<z.ZodString>;
454
+ responseId: z.ZodString;
455
+ toolId: z.ZodString;
456
+ outputIndex: z.ZodOptional<z.ZodInt>;
457
+ name: z.ZodString;
458
+ phase: z.ZodEnum<{
459
+ completed: "completed";
460
+ failed: "failed";
461
+ started: "started";
462
+ }>;
463
+ id: z.ZodString;
464
+ sessionId: z.ZodString;
465
+ sequence: z.ZodInt;
466
+ recordedAtMs: z.ZodNumber;
467
+ sessionTimeMs: z.ZodNumber;
468
+ correlationId: z.ZodOptional<z.ZodString>;
469
+ causationId: z.ZodOptional<z.ZodString>;
470
+ type: z.ZodLiteral<"backend.tool">;
471
+ }, z.core.$strip>, z.ZodObject<{
472
+ delegationId: z.ZodString;
473
+ target: z.ZodEnum<{
474
+ client: "client";
475
+ responses: "responses";
476
+ }>;
477
+ offsetMs: z.ZodNumber;
478
+ responseId: z.ZodOptional<z.ZodString>;
479
+ id: z.ZodString;
480
+ sessionId: z.ZodString;
481
+ sequence: z.ZodInt;
482
+ recordedAtMs: z.ZodNumber;
483
+ sessionTimeMs: z.ZodNumber;
484
+ correlationId: z.ZodOptional<z.ZodString>;
485
+ causationId: z.ZodOptional<z.ZodString>;
486
+ type: z.ZodLiteral<"delegation.created">;
487
+ }, z.core.$strip>, z.ZodObject<{
488
+ contextId: z.ZodString;
489
+ callId: z.ZodOptional<z.ZodString>;
490
+ taskId: z.ZodOptional<z.ZodString>;
491
+ phase: z.ZodEnum<{
492
+ acknowledged: "acknowledged";
493
+ failed: "failed";
494
+ submitted: "submitted";
495
+ }>;
496
+ kind: z.ZodEnum<{
497
+ commentary: "commentary";
498
+ instructions: "instructions";
499
+ thinking: "thinking";
500
+ }>;
501
+ startMs: z.ZodOptional<z.ZodNumber>;
502
+ endMs: z.ZodOptional<z.ZodNumber>;
503
+ message: z.ZodOptional<z.ZodString>;
504
+ id: z.ZodString;
505
+ sessionId: z.ZodString;
506
+ sequence: z.ZodInt;
507
+ recordedAtMs: z.ZodNumber;
508
+ sessionTimeMs: z.ZodNumber;
509
+ correlationId: z.ZodOptional<z.ZodString>;
510
+ causationId: z.ZodOptional<z.ZodString>;
511
+ type: z.ZodLiteral<"context.delivery">;
512
+ }, z.core.$strip>, z.ZodObject<{
513
+ seconds: z.ZodNumber;
514
+ final: z.ZodBoolean;
515
+ contextWindowUsageRatio: z.ZodOptional<z.ZodNumber>;
516
+ id: z.ZodString;
517
+ sessionId: z.ZodString;
518
+ sequence: z.ZodInt;
519
+ recordedAtMs: z.ZodNumber;
520
+ sessionTimeMs: z.ZodNumber;
521
+ correlationId: z.ZodOptional<z.ZodString>;
522
+ causationId: z.ZodOptional<z.ZodString>;
523
+ type: z.ZodLiteral<"usage.duration">;
524
+ }, z.core.$strip>, z.ZodObject<{
525
+ streamId: z.ZodString;
526
+ startSample: z.ZodInt;
527
+ endSample: z.ZodInt;
528
+ status: z.ZodEnum<{
529
+ discarded: "discarded";
530
+ played: "played";
531
+ }>;
532
+ id: z.ZodString;
533
+ sessionId: z.ZodString;
534
+ sequence: z.ZodInt;
535
+ recordedAtMs: z.ZodNumber;
536
+ sessionTimeMs: z.ZodNumber;
537
+ correlationId: z.ZodOptional<z.ZodString>;
538
+ causationId: z.ZodOptional<z.ZodString>;
539
+ type: z.ZodLiteral<"playout.range">;
540
+ }, z.core.$strip>, z.ZodObject<{
541
+ responseId: z.ZodOptional<z.ZodString>;
542
+ scope: z.ZodOptional<z.ZodEnum<{
543
+ backend: "backend";
544
+ voice: "voice";
545
+ }>>;
232
546
  inputTokens: z.ZodNumber;
233
547
  outputTokens: z.ZodNumber;
234
548
  totalTokens: z.ZodNumber;
@@ -268,6 +582,18 @@ export declare const HarnessEventSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
268
582
  callId: z.ZodString;
269
583
  name: z.ZodString;
270
584
  arguments: z.ZodRecord<z.ZodString, z.ZodUnknown>;
585
+ source: z.ZodOptional<z.ZodObject<{
586
+ scope: z.ZodEnum<{
587
+ backend: "backend";
588
+ voice: "voice";
589
+ }>;
590
+ responseId: z.ZodOptional<z.ZodString>;
591
+ itemId: z.ZodOptional<z.ZodString>;
592
+ outputIndex: z.ZodOptional<z.ZodInt>;
593
+ contentIndex: z.ZodOptional<z.ZodInt>;
594
+ summaryIndex: z.ZodOptional<z.ZodInt>;
595
+ delegationId: z.ZodOptional<z.ZodString>;
596
+ }, z.core.$strip>>;
271
597
  }, z.core.$strip>;
272
598
  }, z.core.$strip>, z.ZodObject<{
273
599
  id: z.ZodString;
@@ -356,6 +682,18 @@ export declare const HarnessEventSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
356
682
  type: z.ZodLiteral<"task.accepted">;
357
683
  taskId: z.ZodString;
358
684
  callId: z.ZodString;
685
+ }, z.core.$strip>, z.ZodObject<{
686
+ id: z.ZodString;
687
+ sessionId: z.ZodString;
688
+ sequence: z.ZodInt;
689
+ recordedAtMs: z.ZodNumber;
690
+ sessionTimeMs: z.ZodNumber;
691
+ correlationId: z.ZodOptional<z.ZodString>;
692
+ causationId: z.ZodOptional<z.ZodString>;
693
+ type: z.ZodLiteral<"task.cancellation_requested">;
694
+ taskId: z.ZodString;
695
+ callId: z.ZodString;
696
+ reason: z.ZodString;
359
697
  }, z.core.$strip>, z.ZodObject<{
360
698
  id: z.ZodString;
361
699
  sessionId: z.ZodString;
@@ -1,7 +1,10 @@
1
1
  import { z } from "zod";
2
2
  import { AudioChunkSchema } from "./audio.js";
3
+ import { BackendOutputDeltaSchema, BackendOutputSchema } from "./backend-output.js";
4
+ import { parseEventJson, stringifyEventJson } from "./event-json.js";
5
+ import { ProviderOutputSourceSchema } from "./output-source.js";
3
6
  import { InputPartSchema } from "./parts.js";
4
- import { OutputModalitySchema, ProviderCapabilitiesSchema, ProviderDiagnosticSchema, ResponseStateSchema, TranscriptDeltaPayloadSchema, TranscriptPayloadSchema, UsagePayloadSchema, } from "./provider.js";
7
+ import { BackendResponseSchema, BackendToolSchema, ContextDeliverySchema, DelegationCreatedSchema, DurationUsageSchema, OutputModalitySchema, PlayoutRangeSchema, ProviderCapabilitiesSchema, ProviderDiagnosticSchema, ResponseStateSchema, TranscriptDeltaPayloadSchema, TranscriptFragmentSchema, TranscriptPayloadSchema, UsagePayloadSchema, } from "./provider.js";
5
8
  import { JsonValueSchema, ToolCallSchema, ToolOutcomeSchema } from "./tools.js";
6
9
  /** Bounds for a typed user message, shared by the event, the session API, and wire schemas. */
7
10
  export const MessageInputTextSchema = z.string().min(1).max(8_000);
@@ -14,9 +17,20 @@ const EventBaseSchema = z.object({
14
17
  correlationId: z.string().min(1).optional(),
15
18
  causationId: z.string().min(1).optional(),
16
19
  });
20
+ export const InputAudioEventSchema = EventBaseSchema.extend({
21
+ type: z.literal("audio.input"),
22
+ chunk: AudioChunkSchema,
23
+ syntheticSilence: z.boolean().optional(),
24
+ });
25
+ export const OutputAudioEventSchema = EventBaseSchema.extend({
26
+ type: z.literal("audio.output"),
27
+ chunk: AudioChunkSchema,
28
+ source: ProviderOutputSourceSchema.optional(),
29
+ });
17
30
  /**
18
- * The authoritative session log: every observable fact of a conversation, in one flat,
19
- * durably ordered stream. There is deliberately no turn or message hierarchy here —
31
+ * Sequenced live facts of a conversation, in one flat, store-ordered stream. Retained
32
+ * HarnessRecord values preserve this envelope and may explicitly omit audio bytes.
33
+ * There is deliberately no turn or message hierarchy here —
20
34
  * duplex audio overlaps — conversation views are projections over this log.
21
35
  * The full catalog with ordering rules lives in docs/protocol.md.
22
36
  */
@@ -41,7 +55,11 @@ export const HarnessEventSchema = z.discriminatedUnion("type", [
41
55
  /** A host asked the ready provider to begin an assistant turn without fabricating user input. */
42
56
  EventBaseSchema.extend({ type: z.literal("assistant.turn.requested") }),
43
57
  /** The provider connection settled; the harness closes the session in response. */
44
- EventBaseSchema.extend({ type: z.literal("provider.closed"), reason: z.string().min(1) }),
58
+ EventBaseSchema.extend({
59
+ type: z.literal("provider.closed"),
60
+ reason: z.string().min(1),
61
+ finalized: z.boolean().optional(),
62
+ }),
45
63
  /** Provider-reported fault; recoverable errors leave the session running. */
46
64
  EventBaseSchema.extend({
47
65
  type: z.literal("provider.error"),
@@ -50,24 +68,42 @@ export const HarnessEventSchema = z.discriminatedUnion("type", [
50
68
  }),
51
69
  /**
52
70
  * A typed user message injected into the conversation (text mode or mixed mode).
53
- * `text` is the collapsed string realtime providers consume; `parts` preserves the
54
- * full multimodal input (text/image/file) for projection when one was given.
71
+ * This captures input, not delivery. Legacy logs may contain image/file parts that
72
+ * were never forwarded; current sendText rejects those before partial submission.
55
73
  */
56
74
  EventBaseSchema.extend({
57
75
  type: z.literal("message.input"),
58
76
  text: MessageInputTextSchema,
59
77
  parts: z.array(InputPartSchema).min(1).optional(),
60
78
  }),
79
+ /** Local provider submission outcome for a captured message; never proof of consumption or speech. */
80
+ EventBaseSchema.extend({
81
+ type: z.literal("input.delivery"),
82
+ inputId: z.string().min(1),
83
+ providerId: z.string().min(1),
84
+ target: z.enum(["conversation", "backend"]),
85
+ phase: z.enum(["submitted", "failed"]),
86
+ error: z.string().min(1).max(2000).optional(),
87
+ }),
61
88
  /** Microphone PCM as received; the append and the provider forward run in parallel. */
62
- EventBaseSchema.extend({ type: z.literal("audio.input"), chunk: AudioChunkSchema }),
89
+ InputAudioEventSchema,
63
90
  /** Model PCM as received; records are pipelined so bursts never stall the event pump. */
64
- EventBaseSchema.extend({ type: z.literal("audio.output"), chunk: AudioChunkSchema }),
91
+ OutputAudioEventSchema,
65
92
  /** User barge-in: clients must clear this output stream, including buffered audio. */
66
93
  EventBaseSchema.extend({ type: z.literal("audio.interrupted"), streamId: z.string().min(1) }),
67
94
  /** Final text for either speaker — speech-to-text, or the model's text output in text mode. */
68
95
  EventBaseSchema.extend({ type: z.literal("transcript"), ...TranscriptPayloadSchema.shape }),
69
96
  /** Incremental assistant text streamed before the final transcript; live-render only. */
70
97
  EventBaseSchema.extend({ type: z.literal("transcript.delta"), ...TranscriptDeltaPayloadSchema.shape }),
98
+ TranscriptFragmentSchema.safeExtend({ ...EventBaseSchema.shape, type: z.literal("transcript.fragment") }),
99
+ BackendOutputDeltaSchema.safeExtend({ ...EventBaseSchema.shape, type: z.literal("backend.output.delta") }),
100
+ EventBaseSchema.extend({ type: z.literal("backend.output"), ...BackendOutputSchema.shape }),
101
+ EventBaseSchema.extend({ type: z.literal("backend.response"), ...BackendResponseSchema.shape }),
102
+ EventBaseSchema.extend({ type: z.literal("backend.tool"), ...BackendToolSchema.shape }),
103
+ EventBaseSchema.extend({ type: z.literal("delegation.created"), ...DelegationCreatedSchema.shape }),
104
+ EventBaseSchema.extend({ type: z.literal("context.delivery"), ...ContextDeliverySchema.shape }),
105
+ EventBaseSchema.extend({ type: z.literal("usage.duration"), ...DurationUsageSchema.shape }),
106
+ PlayoutRangeSchema.safeExtend({ ...EventBaseSchema.shape, type: z.literal("playout.range") }),
71
107
  /** Provider-reported token accounting for one completed response. */
72
108
  EventBaseSchema.extend({ type: z.literal("usage"), ...UsagePayloadSchema.shape }),
73
109
  /** Client acknowledgement of playback position; the authority for barge-in truncation. */
@@ -121,6 +157,13 @@ export const HarnessEventSchema = z.discriminatedUnion("type", [
121
157
  taskId: z.string().min(1),
122
158
  callId: z.string().min(1),
123
159
  }),
160
+ /** Requested cancellation, not confirmation that the runner or a remote worker stopped. */
161
+ EventBaseSchema.extend({
162
+ type: z.literal("task.cancellation_requested"),
163
+ taskId: z.string().min(1),
164
+ callId: z.string().min(1),
165
+ reason: z.string().min(1),
166
+ }),
124
167
  /** Intermediate progress from a background task. */
125
168
  EventBaseSchema.extend({
126
169
  type: z.literal("task.progress"),
@@ -158,25 +201,10 @@ export const HarnessEventSchema = z.discriminatedUnion("type", [
158
201
  error: z.string().min(1),
159
202
  }),
160
203
  ]);
161
- const bytesMarker = "$xoBytes";
162
204
  export function stringifyHarnessEvent(event) {
163
205
  HarnessEventSchema.parse(event);
164
- return JSON.stringify(event, (_key, value) => {
165
- if (value instanceof Uint8Array) {
166
- return { [bytesMarker]: Array.from(value) };
167
- }
168
- return value;
169
- });
206
+ return stringifyEventJson(event);
170
207
  }
171
208
  export function parseHarnessEvent(serialized) {
172
- const value = JSON.parse(serialized, (_key, candidate) => {
173
- if (typeof candidate === "object" && candidate !== null && bytesMarker in candidate) {
174
- const encoded = candidate[bytesMarker];
175
- if (Array.isArray(encoded) && encoded.every((value) => typeof value === "number")) {
176
- return Uint8Array.from(encoded);
177
- }
178
- }
179
- return candidate;
180
- });
181
- return HarnessEventSchema.parse(value);
209
+ return HarnessEventSchema.parse(parseEventJson(serialized));
182
210
  }
@@ -1,6 +1,11 @@
1
1
  export * from "./async-queue.js";
2
2
  export * from "./audio.js";
3
+ export * from "./backend-output.js";
3
4
  export * from "./events.js";
5
+ export * from "./output-source.js";
6
+ export * from "./paced-audio.js";
4
7
  export * from "./parts.js";
5
8
  export * from "./provider.js";
9
+ export * from "./records.js";
6
10
  export * from "./tools.js";
11
+ export * from "./transcript.js";
@@ -1,6 +1,11 @@
1
1
  export * from "./async-queue.js";
2
2
  export * from "./audio.js";
3
+ export * from "./backend-output.js";
3
4
  export * from "./events.js";
5
+ export * from "./output-source.js";
6
+ export * from "./paced-audio.js";
4
7
  export * from "./parts.js";
5
8
  export * from "./provider.js";
9
+ export * from "./records.js";
6
10
  export * from "./tools.js";
11
+ export * from "./transcript.js";
@@ -0,0 +1,18 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * Native provenance, when the provider supplies it. Indices are local to the
4
+ * native response/item, not XO message order, event sequence, or completion.
5
+ */
6
+ export declare const ProviderOutputSourceSchema: z.ZodObject<{
7
+ scope: z.ZodEnum<{
8
+ backend: "backend";
9
+ voice: "voice";
10
+ }>;
11
+ responseId: z.ZodOptional<z.ZodString>;
12
+ itemId: z.ZodOptional<z.ZodString>;
13
+ outputIndex: z.ZodOptional<z.ZodInt>;
14
+ contentIndex: z.ZodOptional<z.ZodInt>;
15
+ summaryIndex: z.ZodOptional<z.ZodInt>;
16
+ delegationId: z.ZodOptional<z.ZodString>;
17
+ }, z.core.$strip>;
18
+ export type ProviderOutputSource = z.infer<typeof ProviderOutputSourceSchema>;
@@ -0,0 +1,15 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * Native provenance, when the provider supplies it. Indices are local to the
4
+ * native response/item, not XO message order, event sequence, or completion.
5
+ */
6
+ export const ProviderOutputSourceSchema = z.object({
7
+ scope: z.enum(["voice", "backend"]),
8
+ responseId: z.string().min(1).optional(),
9
+ itemId: z.string().min(1).optional(),
10
+ outputIndex: z.int().nonnegative().optional(),
11
+ contentIndex: z.int().nonnegative().optional(),
12
+ /** Native reasoning summary position, distinct from message content_index. */
13
+ summaryIndex: z.int().nonnegative().optional(),
14
+ delegationId: z.string().min(1).optional(),
15
+ });
@@ -0,0 +1,27 @@
1
+ /** One clock for a continuous PCM16 mono input, including time without a microphone or file. */
2
+ export declare class PacedAudioInput {
3
+ #private;
4
+ readonly options: {
5
+ send(data: Uint8Array, syntheticSilence: boolean): Promise<void>;
6
+ signal: AbortSignal;
7
+ sampleRate?: number;
8
+ frameMs?: number;
9
+ maxBufferedMs?: number;
10
+ onLate?(delayMs: number): void;
11
+ };
12
+ readonly done: Promise<void>;
13
+ constructor(options: {
14
+ send(data: Uint8Array, syntheticSilence: boolean): Promise<void>;
15
+ signal: AbortSignal;
16
+ sampleRate?: number;
17
+ frameMs?: number;
18
+ maxBufferedMs?: number;
19
+ onLate?(delayMs: number): void;
20
+ });
21
+ /**
22
+ * Resolves when these samples have been submitted. Capture sources enqueue at their
23
+ * capture cadence; file sources assemble full frames (100 ms by default) before
24
+ * awaiting writes. Awaiting each shorter packet would pad every packet with silence.
25
+ */
26
+ write(data: Uint8Array): Promise<void>;
27
+ }