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
@@ -8,8 +8,25 @@ export declare const ProviderCapabilitiesSchema: z.ZodObject<{
8
8
  modelManagedFloor: z.ZodBoolean;
9
9
  supportsToolCalls: z.ZodBoolean;
10
10
  supportsAsyncContext: z.ZodBoolean;
11
+ supportsToolStatusContext: z.ZodOptional<z.ZodBoolean>;
11
12
  supportsPlayoutAcknowledgements: z.ZodBoolean;
12
13
  reportsResponseState: z.ZodOptional<z.ZodBoolean>;
14
+ inputCadence: z.ZodOptional<z.ZodEnum<{
15
+ continuous: "continuous";
16
+ "on-demand": "on-demand";
17
+ }>>;
18
+ outputLifecycle: z.ZodOptional<z.ZodEnum<{
19
+ continuous: "continuous";
20
+ response: "response";
21
+ }>>;
22
+ supportsAssistantTurn: z.ZodOptional<z.ZodBoolean>;
23
+ supportsTextOutput: z.ZodOptional<z.ZodBoolean>;
24
+ textInput: z.ZodOptional<z.ZodEnum<{
25
+ backend: "backend";
26
+ conversation: "conversation";
27
+ unsupported: "unsupported";
28
+ }>>;
29
+ maxContextUpdateBytes: z.ZodOptional<z.ZodInt>;
13
30
  }, z.core.$strip>;
14
31
  export type ProviderCapabilities = z.infer<typeof ProviderCapabilitiesSchema>;
15
32
  export declare const PlayoutProgressSchema: z.ZodObject<{
@@ -17,6 +34,31 @@ export declare const PlayoutProgressSchema: z.ZodObject<{
17
34
  playedThroughSample: z.ZodInt;
18
35
  }, z.core.$strip>;
19
36
  export type PlayoutProgress = z.infer<typeof PlayoutProgressSchema>;
37
+ /** Local device evidence. Discarded ranges must never become played-through acknowledgements. */
38
+ export declare const PlayoutRangeSchema: z.ZodObject<{
39
+ streamId: z.ZodString;
40
+ startSample: z.ZodInt;
41
+ endSample: z.ZodInt;
42
+ status: z.ZodEnum<{
43
+ discarded: "discarded";
44
+ played: "played";
45
+ }>;
46
+ }, z.core.$strip>;
47
+ export type PlayoutRange = z.infer<typeof PlayoutRangeSchema>;
48
+ /** Application-authored context; typed user messages still use sendText. */
49
+ export declare const ConversationContextUpdateSchema: z.ZodObject<{
50
+ contextId: z.ZodString;
51
+ kind: z.ZodEnum<{
52
+ commentary: "commentary";
53
+ instructions: "instructions";
54
+ thinking: "thinking";
55
+ }>;
56
+ content: z.ZodString;
57
+ delegationId: z.ZodOptional<z.ZodString>;
58
+ callId: z.ZodOptional<z.ZodString>;
59
+ taskId: z.ZodOptional<z.ZodString>;
60
+ }, z.core.$strip>;
61
+ export type ConversationContextUpdate = z.infer<typeof ConversationContextUpdateSchema>;
20
62
  /** What the model may produce; ["text"] runs a session without audio output. */
21
63
  export declare const OutputModalitySchema: z.ZodEnum<{
22
64
  audio: "audio";
@@ -37,6 +79,11 @@ export type AssistantTurnRequest = z.infer<typeof AssistantTurnRequestSchema>;
37
79
  * the number that proves (and prices) cache effectiveness.
38
80
  */
39
81
  export declare const UsagePayloadSchema: z.ZodObject<{
82
+ responseId: z.ZodOptional<z.ZodString>;
83
+ scope: z.ZodOptional<z.ZodEnum<{
84
+ backend: "backend";
85
+ voice: "voice";
86
+ }>>;
40
87
  inputTokens: z.ZodNumber;
41
88
  outputTokens: z.ZodNumber;
42
89
  totalTokens: z.ZodNumber;
@@ -54,6 +101,18 @@ export declare const TranscriptPayloadSchema: z.ZodObject<{
54
101
  }>;
55
102
  text: z.ZodString;
56
103
  streamId: z.ZodOptional<z.ZodString>;
104
+ source: z.ZodOptional<z.ZodObject<{
105
+ scope: z.ZodEnum<{
106
+ backend: "backend";
107
+ voice: "voice";
108
+ }>;
109
+ responseId: z.ZodOptional<z.ZodString>;
110
+ itemId: z.ZodOptional<z.ZodString>;
111
+ outputIndex: z.ZodOptional<z.ZodInt>;
112
+ contentIndex: z.ZodOptional<z.ZodInt>;
113
+ summaryIndex: z.ZodOptional<z.ZodInt>;
114
+ delegationId: z.ZodOptional<z.ZodString>;
115
+ }, z.core.$strip>>;
57
116
  }, z.core.$strip>;
58
117
  export type TranscriptPayload = z.infer<typeof TranscriptPayloadSchema>;
59
118
  /** Incremental text from either speaker; finalized by a matching `transcript`. */
@@ -64,8 +123,88 @@ export declare const TranscriptDeltaPayloadSchema: z.ZodObject<{
64
123
  }>;
65
124
  delta: z.ZodString;
66
125
  streamId: z.ZodOptional<z.ZodString>;
126
+ source: z.ZodOptional<z.ZodObject<{
127
+ scope: z.ZodEnum<{
128
+ backend: "backend";
129
+ voice: "voice";
130
+ }>;
131
+ responseId: z.ZodOptional<z.ZodString>;
132
+ itemId: z.ZodOptional<z.ZodString>;
133
+ outputIndex: z.ZodOptional<z.ZodInt>;
134
+ contentIndex: z.ZodOptional<z.ZodInt>;
135
+ summaryIndex: z.ZodOptional<z.ZodInt>;
136
+ delegationId: z.ZodOptional<z.ZodString>;
137
+ }, z.core.$strip>>;
67
138
  }, z.core.$strip>;
68
139
  export type TranscriptDeltaPayload = z.infer<typeof TranscriptDeltaPayloadSchema>;
140
+ /** Native timed text, without an authoritative turn/item completion. */
141
+ export declare const TranscriptFragmentSchema: z.ZodObject<{
142
+ role: z.ZodEnum<{
143
+ assistant: "assistant";
144
+ user: "user";
145
+ }>;
146
+ text: z.ZodString;
147
+ fragmentId: z.ZodString;
148
+ startMs: z.ZodNumber;
149
+ endMs: z.ZodNumber;
150
+ timebase: z.ZodLiteral<"provider-session">;
151
+ }, z.core.$strip>;
152
+ export type TranscriptFragment = z.infer<typeof TranscriptFragmentSchema>;
153
+ export declare const BackendResponseSchema: z.ZodObject<{
154
+ delegationId: z.ZodOptional<z.ZodString>;
155
+ responseId: z.ZodString;
156
+ phase: z.ZodEnum<{
157
+ completed: "completed";
158
+ started: "started";
159
+ "waiting-for-tools": "waiting-for-tools";
160
+ }>;
161
+ status: z.ZodOptional<z.ZodString>;
162
+ }, z.core.$strip>;
163
+ export declare const BackendToolSchema: z.ZodObject<{
164
+ delegationId: z.ZodOptional<z.ZodString>;
165
+ responseId: z.ZodString;
166
+ toolId: z.ZodString;
167
+ outputIndex: z.ZodOptional<z.ZodInt>;
168
+ name: z.ZodString;
169
+ phase: z.ZodEnum<{
170
+ completed: "completed";
171
+ failed: "failed";
172
+ started: "started";
173
+ }>;
174
+ }, z.core.$strip>;
175
+ export declare const DelegationCreatedSchema: z.ZodObject<{
176
+ delegationId: z.ZodString;
177
+ target: z.ZodEnum<{
178
+ client: "client";
179
+ responses: "responses";
180
+ }>;
181
+ offsetMs: z.ZodNumber;
182
+ responseId: z.ZodOptional<z.ZodString>;
183
+ }, z.core.$strip>;
184
+ export declare const ContextDeliverySchema: z.ZodObject<{
185
+ contextId: z.ZodString;
186
+ callId: z.ZodOptional<z.ZodString>;
187
+ taskId: z.ZodOptional<z.ZodString>;
188
+ phase: z.ZodEnum<{
189
+ acknowledged: "acknowledged";
190
+ failed: "failed";
191
+ submitted: "submitted";
192
+ }>;
193
+ kind: z.ZodEnum<{
194
+ commentary: "commentary";
195
+ instructions: "instructions";
196
+ thinking: "thinking";
197
+ }>;
198
+ startMs: z.ZodOptional<z.ZodNumber>;
199
+ endMs: z.ZodOptional<z.ZodNumber>;
200
+ message: z.ZodOptional<z.ZodString>;
201
+ }, z.core.$strip>;
202
+ /** Cumulative session duration, never summed across snapshots. */
203
+ export declare const DurationUsageSchema: z.ZodObject<{
204
+ seconds: z.ZodNumber;
205
+ final: z.ZodBoolean;
206
+ contextWindowUsageRatio: z.ZodOptional<z.ZodNumber>;
207
+ }, z.core.$strip>;
69
208
  /** Generation state only: idle says nothing about buffered audio playback or background tasks. */
70
209
  export declare const ResponseStateSchema: z.ZodEnum<{
71
210
  idle: "idle";
@@ -161,7 +300,19 @@ export declare const ProviderEventSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
161
300
  channels: z.ZodInt;
162
301
  startSample: z.ZodInt;
163
302
  data: z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Array<ArrayBuffer>>;
164
- }, z.core.$strip>;
303
+ }, z.core.$strict>;
304
+ source: z.ZodOptional<z.ZodObject<{
305
+ scope: z.ZodEnum<{
306
+ backend: "backend";
307
+ voice: "voice";
308
+ }>;
309
+ responseId: z.ZodOptional<z.ZodString>;
310
+ itemId: z.ZodOptional<z.ZodString>;
311
+ outputIndex: z.ZodOptional<z.ZodInt>;
312
+ contentIndex: z.ZodOptional<z.ZodInt>;
313
+ summaryIndex: z.ZodOptional<z.ZodInt>;
314
+ delegationId: z.ZodOptional<z.ZodString>;
315
+ }, z.core.$strip>>;
165
316
  }, z.core.$strip>, z.ZodObject<{
166
317
  type: z.ZodLiteral<"audio.interrupted">;
167
318
  streamId: z.ZodString;
@@ -172,6 +323,18 @@ export declare const ProviderEventSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
172
323
  }>;
173
324
  text: z.ZodString;
174
325
  streamId: z.ZodOptional<z.ZodString>;
326
+ source: z.ZodOptional<z.ZodObject<{
327
+ scope: z.ZodEnum<{
328
+ backend: "backend";
329
+ voice: "voice";
330
+ }>;
331
+ responseId: z.ZodOptional<z.ZodString>;
332
+ itemId: z.ZodOptional<z.ZodString>;
333
+ outputIndex: z.ZodOptional<z.ZodInt>;
334
+ contentIndex: z.ZodOptional<z.ZodInt>;
335
+ summaryIndex: z.ZodOptional<z.ZodInt>;
336
+ delegationId: z.ZodOptional<z.ZodString>;
337
+ }, z.core.$strip>>;
175
338
  type: z.ZodLiteral<"transcript">;
176
339
  }, z.core.$strip>, z.ZodObject<{
177
340
  role: z.ZodEnum<{
@@ -180,15 +343,158 @@ export declare const ProviderEventSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
180
343
  }>;
181
344
  delta: z.ZodString;
182
345
  streamId: z.ZodOptional<z.ZodString>;
346
+ source: z.ZodOptional<z.ZodObject<{
347
+ scope: z.ZodEnum<{
348
+ backend: "backend";
349
+ voice: "voice";
350
+ }>;
351
+ responseId: z.ZodOptional<z.ZodString>;
352
+ itemId: z.ZodOptional<z.ZodString>;
353
+ outputIndex: z.ZodOptional<z.ZodInt>;
354
+ contentIndex: z.ZodOptional<z.ZodInt>;
355
+ summaryIndex: z.ZodOptional<z.ZodInt>;
356
+ delegationId: z.ZodOptional<z.ZodString>;
357
+ }, z.core.$strip>>;
183
358
  type: z.ZodLiteral<"transcript.delta">;
359
+ }, z.core.$strip>, z.ZodObject<{
360
+ role: z.ZodEnum<{
361
+ assistant: "assistant";
362
+ user: "user";
363
+ }>;
364
+ text: z.ZodString;
365
+ fragmentId: z.ZodString;
366
+ startMs: z.ZodNumber;
367
+ endMs: z.ZodNumber;
368
+ timebase: z.ZodLiteral<"provider-session">;
369
+ type: z.ZodLiteral<"transcript.fragment">;
370
+ }, z.core.$strip>, z.ZodObject<{
371
+ kind: z.ZodEnum<{
372
+ reasoning_summary: "reasoning_summary";
373
+ refusal: "refusal";
374
+ text: "text";
375
+ }>;
376
+ source: z.ZodObject<{
377
+ delegationId: z.ZodOptional<z.ZodString>;
378
+ scope: z.ZodLiteral<"backend">;
379
+ responseId: z.ZodString;
380
+ itemId: z.ZodString;
381
+ outputIndex: z.ZodInt;
382
+ contentIndex: z.ZodOptional<z.ZodInt>;
383
+ summaryIndex: z.ZodOptional<z.ZodInt>;
384
+ }, z.core.$strip>;
385
+ delta: z.ZodString;
386
+ type: z.ZodLiteral<"backend.output.delta">;
387
+ }, z.core.$strip>, z.ZodObject<{
388
+ source: z.ZodObject<{
389
+ delegationId: z.ZodOptional<z.ZodString>;
390
+ scope: z.ZodLiteral<"backend">;
391
+ responseId: z.ZodString;
392
+ itemId: z.ZodString;
393
+ outputIndex: z.ZodInt;
394
+ }, z.core.$strip>;
395
+ content: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
396
+ kind: z.ZodEnum<{
397
+ refusal: "refusal";
398
+ text: "text";
399
+ }>;
400
+ text: z.ZodString;
401
+ contentIndex: z.ZodInt;
402
+ }, z.core.$strip>, z.ZodObject<{
403
+ kind: z.ZodLiteral<"reasoning_summary">;
404
+ text: z.ZodString;
405
+ summaryIndex: z.ZodInt;
406
+ }, z.core.$strip>], "kind">>;
407
+ status: z.ZodOptional<z.ZodEnum<{
408
+ cancelled: "cancelled";
409
+ completed: "completed";
410
+ failed: "failed";
411
+ in_progress: "in_progress";
412
+ incomplete: "incomplete";
413
+ }>>;
414
+ type: z.ZodLiteral<"backend.output">;
415
+ }, z.core.$strip>, z.ZodObject<{
416
+ delegationId: z.ZodOptional<z.ZodString>;
417
+ responseId: z.ZodString;
418
+ phase: z.ZodEnum<{
419
+ completed: "completed";
420
+ started: "started";
421
+ "waiting-for-tools": "waiting-for-tools";
422
+ }>;
423
+ status: z.ZodOptional<z.ZodString>;
424
+ type: z.ZodLiteral<"backend.response">;
425
+ }, z.core.$strip>, z.ZodObject<{
426
+ delegationId: z.ZodOptional<z.ZodString>;
427
+ responseId: z.ZodString;
428
+ toolId: z.ZodString;
429
+ outputIndex: z.ZodOptional<z.ZodInt>;
430
+ name: z.ZodString;
431
+ phase: z.ZodEnum<{
432
+ completed: "completed";
433
+ failed: "failed";
434
+ started: "started";
435
+ }>;
436
+ type: z.ZodLiteral<"backend.tool">;
437
+ }, z.core.$strip>, z.ZodObject<{
438
+ delegationId: z.ZodString;
439
+ target: z.ZodEnum<{
440
+ client: "client";
441
+ responses: "responses";
442
+ }>;
443
+ offsetMs: z.ZodNumber;
444
+ responseId: z.ZodOptional<z.ZodString>;
445
+ type: z.ZodLiteral<"delegation.created">;
446
+ }, z.core.$strip>, z.ZodObject<{
447
+ contextId: z.ZodString;
448
+ callId: z.ZodOptional<z.ZodString>;
449
+ taskId: z.ZodOptional<z.ZodString>;
450
+ phase: z.ZodEnum<{
451
+ acknowledged: "acknowledged";
452
+ failed: "failed";
453
+ submitted: "submitted";
454
+ }>;
455
+ kind: z.ZodEnum<{
456
+ commentary: "commentary";
457
+ instructions: "instructions";
458
+ thinking: "thinking";
459
+ }>;
460
+ startMs: z.ZodOptional<z.ZodNumber>;
461
+ endMs: z.ZodOptional<z.ZodNumber>;
462
+ message: z.ZodOptional<z.ZodString>;
463
+ type: z.ZodLiteral<"context.delivery">;
464
+ }, z.core.$strip>, z.ZodObject<{
465
+ seconds: z.ZodNumber;
466
+ final: z.ZodBoolean;
467
+ contextWindowUsageRatio: z.ZodOptional<z.ZodNumber>;
468
+ type: z.ZodLiteral<"usage.duration">;
469
+ }, z.core.$strip>, z.ZodObject<{
470
+ type: z.ZodLiteral<"tool.delivery_failed">;
471
+ callId: z.ZodString;
472
+ error: z.ZodString;
184
473
  }, z.core.$strip>, z.ZodObject<{
185
474
  type: z.ZodLiteral<"tool.call">;
186
475
  call: z.ZodObject<{
187
476
  callId: z.ZodString;
188
477
  name: z.ZodString;
189
478
  arguments: z.ZodRecord<z.ZodString, z.ZodUnknown>;
479
+ source: z.ZodOptional<z.ZodObject<{
480
+ scope: z.ZodEnum<{
481
+ backend: "backend";
482
+ voice: "voice";
483
+ }>;
484
+ responseId: z.ZodOptional<z.ZodString>;
485
+ itemId: z.ZodOptional<z.ZodString>;
486
+ outputIndex: z.ZodOptional<z.ZodInt>;
487
+ contentIndex: z.ZodOptional<z.ZodInt>;
488
+ summaryIndex: z.ZodOptional<z.ZodInt>;
489
+ delegationId: z.ZodOptional<z.ZodString>;
490
+ }, z.core.$strip>>;
190
491
  }, z.core.$strip>;
191
492
  }, z.core.$strip>, z.ZodObject<{
493
+ responseId: z.ZodOptional<z.ZodString>;
494
+ scope: z.ZodOptional<z.ZodEnum<{
495
+ backend: "backend";
496
+ voice: "voice";
497
+ }>>;
192
498
  inputTokens: z.ZodNumber;
193
499
  outputTokens: z.ZodNumber;
194
500
  totalTokens: z.ZodNumber;
@@ -204,5 +510,6 @@ export declare const ProviderEventSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
204
510
  }, z.core.$strip>, z.ZodObject<{
205
511
  type: z.ZodLiteral<"closed">;
206
512
  reason: z.ZodString;
513
+ finalized: z.ZodOptional<z.ZodBoolean>;
207
514
  }, z.core.$strip>], "type">;
208
515
  export type ProviderEvent = z.infer<typeof ProviderEventSchema>;
@@ -1,5 +1,7 @@
1
1
  import { z } from "zod";
2
2
  import { AudioChunkSchema } from "./audio.js";
3
+ import { BackendOutputDeltaSchema, BackendOutputSchema } from "./backend-output.js";
4
+ import { ProviderOutputSourceSchema } from "./output-source.js";
3
5
  import { ToolCallSchema } from "./tools.js";
4
6
  /**
5
7
  * What a provider can actually do, declared at session start and recorded in
@@ -8,20 +10,53 @@ import { ToolCallSchema } from "./tools.js";
8
10
  export const ProviderCapabilitiesSchema = z.object({
9
11
  /** Microphone audio may keep flowing while the model is speaking (full duplex). */
10
12
  continuousInputDuringOutput: z.boolean(),
11
- /** The model decides when to speak (server VAD); the harness never gates turns. */
13
+ /** The provider decides when to speak, through VAD or a continuous model policy; the harness does not gate turns. */
12
14
  modelManagedFloor: z.boolean(),
13
15
  supportsToolCalls: z.boolean(),
14
16
  /** Accepts out-of-band context injections such as task settlement announcements. */
15
17
  supportsAsyncContext: z.boolean(),
18
+ /** Accepts derived tool.status context silently, without starting an assistant turn. */
19
+ supportsToolStatusContext: z.boolean().optional(),
16
20
  /** Honors playout acknowledgements for truncation-accurate barge-in. */
17
21
  supportsPlayoutAcknowledgements: z.boolean(),
18
22
  /** Emits response.state for pending generation and queued continuations. Optional for continuous models. */
19
23
  reportsResponseState: z.boolean().optional(),
24
+ /**
25
+ * Continuous input requires a paced audio clock, including silence between utterances.
26
+ * This is separate from listening during output. Missing means on-demand input.
27
+ */
28
+ inputCadence: z.enum(["continuous", "on-demand"]).optional(),
29
+ /** Continuous audio spans display messages; response audio has separate streams. Missing means response. */
30
+ outputLifecycle: z.enum(["continuous", "response"]).optional(),
31
+ supportsAssistantTurn: z.boolean().optional(),
32
+ supportsTextOutput: z.boolean().optional(),
33
+ /** Typed text destination. Missing preserves legacy conversation input; attachments are not implied. */
34
+ textInput: z.enum(["conversation", "backend", "unsupported"]).optional(),
35
+ /** Maximum UTF-8 bytes for one direct appendContext update, when bounded by the adapter. */
36
+ maxContextUpdateBytes: z.int().positive().optional(),
20
37
  });
21
38
  export const PlayoutProgressSchema = z.object({
22
39
  streamId: z.string().min(1),
23
40
  playedThroughSample: z.int().nonnegative(),
24
41
  });
42
+ /** Local device evidence. Discarded ranges must never become played-through acknowledgements. */
43
+ export const PlayoutRangeSchema = z
44
+ .object({
45
+ streamId: z.string().min(1),
46
+ startSample: z.int().nonnegative(),
47
+ endSample: z.int().nonnegative(),
48
+ status: z.enum(["played", "discarded"]),
49
+ })
50
+ .refine((range) => range.endSample > range.startSample, "Playout range must contain samples");
51
+ /** Application-authored context; typed user messages still use sendText. */
52
+ export const ConversationContextUpdateSchema = z.object({
53
+ contextId: z.string().min(1),
54
+ kind: z.enum(["thinking", "commentary", "instructions"]),
55
+ content: z.string().min(1).max(16_000),
56
+ delegationId: z.string().min(1).optional(),
57
+ callId: z.string().min(1).optional(),
58
+ taskId: z.string().min(1).optional(),
59
+ });
25
60
  /** What the model may produce; ["text"] runs a session without audio output. */
26
61
  export const OutputModalitySchema = z.enum(["audio", "text"]);
27
62
  /**
@@ -38,6 +73,8 @@ export const AssistantTurnRequestSchema = z.object({
38
73
  * the number that proves (and prices) cache effectiveness.
39
74
  */
40
75
  export const UsagePayloadSchema = z.object({
76
+ responseId: z.string().min(1).optional(),
77
+ scope: z.enum(["voice", "backend"]).optional(),
41
78
  inputTokens: z.number().int().nonnegative(),
42
79
  outputTokens: z.number().int().nonnegative(),
43
80
  totalTokens: z.number().int().nonnegative(),
@@ -51,12 +88,61 @@ export const TranscriptPayloadSchema = z.object({
51
88
  role: z.enum(["user", "assistant"]),
52
89
  text: z.string().min(1),
53
90
  streamId: z.string().min(1).optional(),
91
+ source: ProviderOutputSourceSchema.optional(),
54
92
  });
55
93
  /** Incremental text from either speaker; finalized by a matching `transcript`. */
56
94
  export const TranscriptDeltaPayloadSchema = z.object({
57
95
  role: z.enum(["user", "assistant"]),
58
96
  delta: z.string().min(1),
59
97
  streamId: z.string().min(1).optional(),
98
+ source: ProviderOutputSourceSchema.optional(),
99
+ });
100
+ /** Native timed text, without an authoritative turn/item completion. */
101
+ export const TranscriptFragmentSchema = z
102
+ .object({
103
+ role: z.enum(["user", "assistant"]),
104
+ text: z.string().min(1),
105
+ fragmentId: z.string().min(1),
106
+ startMs: z.number().nonnegative(),
107
+ endMs: z.number().nonnegative(),
108
+ timebase: z.literal("provider-session"),
109
+ })
110
+ .refine((fragment) => fragment.endMs >= fragment.startMs, "Transcript interval ends before it starts");
111
+ export const BackendResponseSchema = z.object({
112
+ delegationId: z.string().min(1).optional(),
113
+ responseId: z.string().min(1),
114
+ phase: z.enum(["started", "waiting-for-tools", "completed"]),
115
+ status: z.string().max(256).optional(),
116
+ });
117
+ export const BackendToolSchema = z.object({
118
+ delegationId: z.string().min(1).optional(),
119
+ responseId: z.string().min(1),
120
+ toolId: z.string().min(1),
121
+ outputIndex: z.int().nonnegative().optional(),
122
+ name: z.string().min(1),
123
+ phase: z.enum(["started", "completed", "failed"]),
124
+ });
125
+ export const DelegationCreatedSchema = z.object({
126
+ delegationId: z.string().min(1),
127
+ target: z.enum(["responses", "client"]),
128
+ offsetMs: z.number().nonnegative(),
129
+ responseId: z.string().min(1).optional(),
130
+ });
131
+ export const ContextDeliverySchema = z.object({
132
+ contextId: z.string().min(1),
133
+ callId: z.string().min(1).optional(),
134
+ taskId: z.string().min(1).optional(),
135
+ phase: z.enum(["submitted", "acknowledged", "failed"]),
136
+ kind: z.enum(["thinking", "commentary", "instructions"]),
137
+ startMs: z.number().nonnegative().optional(),
138
+ endMs: z.number().nonnegative().optional(),
139
+ message: z.string().max(2000).optional(),
140
+ });
141
+ /** Cumulative session duration, never summed across snapshots. */
142
+ export const DurationUsageSchema = z.object({
143
+ seconds: z.number().nonnegative(),
144
+ final: z.boolean(),
145
+ contextWindowUsageRatio: z.number().min(0).max(1).optional(),
60
146
  });
61
147
  /** Generation state only: idle says nothing about buffered audio playback or background tasks. */
62
148
  export const ResponseStateSchema = z.enum(["pending", "idle"]);
@@ -111,13 +197,26 @@ export const ProviderEventSchema = z.discriminatedUnion("type", [
111
197
  /** Optional allow-listed diagnostics for explaining provider behavior after the fact. */
112
198
  z.object({ type: z.literal("diagnostic"), diagnostic: ProviderDiagnosticSchema }),
113
199
  /** Model speech as sample-addressed PCM. */
114
- z.object({ type: z.literal("audio.output"), chunk: AudioChunkSchema }),
200
+ z.object({
201
+ type: z.literal("audio.output"),
202
+ chunk: AudioChunkSchema,
203
+ source: ProviderOutputSourceSchema.optional(),
204
+ }),
115
205
  /** Clear queued playback for this stream and ignore its subsequent audio chunks. */
116
206
  z.object({ type: z.literal("audio.interrupted"), streamId: z.string().min(1) }),
117
207
  /** Final transcript text for either role. */
118
208
  TranscriptPayloadSchema.extend({ type: z.literal("transcript") }),
119
209
  /** Incremental text from either speaker; assembled into a streaming text part. */
120
210
  TranscriptDeltaPayloadSchema.extend({ type: z.literal("transcript.delta") }),
211
+ TranscriptFragmentSchema.safeExtend({ type: z.literal("transcript.fragment") }),
212
+ BackendOutputDeltaSchema.safeExtend({ type: z.literal("backend.output.delta") }),
213
+ BackendOutputSchema.extend({ type: z.literal("backend.output") }),
214
+ BackendResponseSchema.extend({ type: z.literal("backend.response") }),
215
+ BackendToolSchema.extend({ type: z.literal("backend.tool") }),
216
+ DelegationCreatedSchema.extend({ type: z.literal("delegation.created") }),
217
+ ContextDeliverySchema.extend({ type: z.literal("context.delivery") }),
218
+ DurationUsageSchema.extend({ type: z.literal("usage.duration") }),
219
+ z.object({ type: z.literal("tool.delivery_failed"), callId: z.string().min(1), error: z.string().min(1) }),
121
220
  /** The model requested a tool invocation. */
122
221
  z.object({ type: z.literal("tool.call"), call: ToolCallSchema }),
123
222
  /** Token accounting for one completed response. */
@@ -129,5 +228,5 @@ export const ProviderEventSchema = z.discriminatedUnion("type", [
129
228
  recoverable: z.boolean(),
130
229
  }),
131
230
  /** Terminal: the provider connection is gone. Always the last event. */
132
- z.object({ type: z.literal("closed"), reason: z.string().min(1) }),
231
+ z.object({ type: z.literal("closed"), reason: z.string().min(1), finalized: z.boolean().optional() }),
133
232
  ]);