@kaana.ai/contracts 8.15.0 → 8.16.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.
@@ -30,10 +30,26 @@ export declare const MAX_REALTIME_RESUME_WINDOW_MS = 60000;
30
30
  * reads it here, never copies it.
31
31
  */
32
32
  export declare const MAX_REALTIME_ITEM_TEXT_CHARS = 1048576;
33
+ /**
34
+ * The most characters (UTF-16 code units) the text of one `delegation.reply` or
35
+ * `delegation.context` may hold (contract set 8.16.0). A client streams a long
36
+ * answer as several replies, sentence by sentence; Kaana splits each to its
37
+ * provider's own bound.
38
+ */
39
+ export declare const MAX_REALTIME_DELEGATION_TEXT_CHARS = 8192;
40
+ /** The most verbatim spans one `delegation.reply` may mark (contract set 8.16.0). */
41
+ export declare const MAX_REALTIME_VERBATIM_SPANS = 32;
42
+ /** The most characters (UTF-16 code units) one verbatim span may hold (contract set 8.16.0). */
43
+ export declare const MAX_REALTIME_VERBATIM_SPAN_CHARS = 256;
33
44
  /** A client-chosen command identity, unique within one session. */
34
45
  export declare const realtimeCommandIdSchema: z.ZodString;
35
46
  /** A conversation item's identity within one session. */
36
47
  export declare const realtimeItemIdSchema: z.ZodString;
48
+ /**
49
+ * A delegation's identity within one session: one turn a `live` session handed
50
+ * to its caller (contract set 8.16.0).
51
+ */
52
+ export declare const realtimeDelegationIdSchema: z.ZodString;
37
53
  /** A response's identity within one session. */
38
54
  export declare const realtimeResponseIdSchema: z.ZodString;
39
55
  /**
@@ -85,6 +101,10 @@ export declare const realtimeTurnDetectionSchema: z.ZodDiscriminatedUnion<[z.Zod
85
101
  * session: where the provider bills the transcription
86
102
  * apart from the session model, as `input_transcription_milliseconds` (see
87
103
  * `USAGE_UNITS`); where the session's own price includes it, as nothing more.
104
+ *
105
+ * A `live` session relays the caller's words whether or not it is set, because
106
+ * its delegation needs them; there it takes `language` only (contract set
107
+ * 8.16.0).
88
108
  */
89
109
  export declare const realtimeInputTranscriptionSchema: z.ZodObject<{
90
110
  language: z.ZodOptional<z.ZodString>;
@@ -95,6 +115,25 @@ export declare const realtimeInputTranscriptionSchema: z.ZodObject<{
95
115
  export declare const realtimeTranslationSchema: z.ZodObject<{
96
116
  targetLanguage: z.ZodString;
97
117
  }, z.core.$strict>;
118
+ /**
119
+ * Whether the voice of a `live` session acknowledges a turn it handed over:
120
+ * `auto` lets it say a short "one moment" while the caller's backend works;
121
+ * `none` keeps it silent until the first reply.
122
+ */
123
+ export declare const realtimeDelegationAcknowledgementSchema: z.ZodEnum<{
124
+ auto: "auto";
125
+ none: "none";
126
+ }>;
127
+ /**
128
+ * How a `live` session hands its turns to its caller (contract set 8.16.0,
129
+ * Kaana ADR 0012). Required for `live` and refused for every other kind.
130
+ */
131
+ export declare const realtimeDelegationConfigSchema: z.ZodObject<{
132
+ acknowledgement: z.ZodEnum<{
133
+ auto: "auto";
134
+ none: "none";
135
+ }>;
136
+ }, z.core.$strict>;
98
137
  /**
99
138
  * A function tool a session may call: the chat tool without `strict`, which no
100
139
  * realtime provider's session schema has (contract set 5.0.0).
@@ -174,6 +213,12 @@ export declare const realtimeSessionConfigSchema: z.ZodObject<{
174
213
  name: z.ZodString;
175
214
  }, z.core.$strict>]>>;
176
215
  maxOutputTokens: z.ZodOptional<z.ZodNumber>;
216
+ delegation: z.ZodOptional<z.ZodObject<{
217
+ acknowledgement: z.ZodEnum<{
218
+ auto: "auto";
219
+ none: "none";
220
+ }>;
221
+ }, z.core.$strict>>;
177
222
  }, z.core.$strict>;
178
223
  /**
179
224
  * What `session.update` may change mid-session.
@@ -531,7 +576,50 @@ export declare const realtimeSessionCloseCommandSchema: z.ZodObject<{
531
576
  requestId: z.ZodString;
532
577
  commandId: z.ZodString;
533
578
  }, z.core.$strip>;
534
- /** Every command a client can send. */
579
+ /**
580
+ * Speak this part of a delegated turn's answer (contract set 8.16.0). A client
581
+ * streams its answer sentence by sentence and marks the last part `final`;
582
+ * after it, nothing more is spoken for the delegation. Each `verbatim` span is
583
+ * a part of `text` the voice says exactly as written: numbers, addresses,
584
+ * names, codes. A reply to a delegation that is unknown, superseded, cancelled
585
+ * or already final is refused (`invalid_request`, param `delegationId`).
586
+ */
587
+ export declare const realtimeDelegationReplyCommandSchema: z.ZodObject<{
588
+ type: z.ZodLiteral<"delegation.reply">;
589
+ delegationId: z.ZodString;
590
+ text: z.ZodString;
591
+ verbatim: z.ZodOptional<z.ZodArray<z.ZodString>>;
592
+ final: z.ZodBoolean;
593
+ schemaVersion: z.ZodLiteral<1>;
594
+ requestId: z.ZodString;
595
+ commandId: z.ZodString;
596
+ }, z.core.$strip>;
597
+ /**
598
+ * Silent context the voice may use while a delegated turn is answered, for
599
+ * example "still checking your calendar" (contract set 8.16.0). Never spoken
600
+ * as written.
601
+ */
602
+ export declare const realtimeDelegationContextCommandSchema: z.ZodObject<{
603
+ type: z.ZodLiteral<"delegation.context">;
604
+ delegationId: z.ZodString;
605
+ text: z.ZodString;
606
+ schemaVersion: z.ZodLiteral<1>;
607
+ requestId: z.ZodString;
608
+ commandId: z.ZodString;
609
+ }, z.core.$strip>;
610
+ /** The client dropped a delegated turn: nothing more is spoken for it (contract set 8.16.0). */
611
+ export declare const realtimeDelegationCancelCommandSchema: z.ZodObject<{
612
+ type: z.ZodLiteral<"delegation.cancel">;
613
+ delegationId: z.ZodString;
614
+ schemaVersion: z.ZodLiteral<1>;
615
+ requestId: z.ZodString;
616
+ commandId: z.ZodString;
617
+ }, z.core.$strip>;
618
+ /**
619
+ * Every command a client can send. The three `delegation.*` commands are a
620
+ * `live` session's; `session.update`, `input_audio.commit` and
621
+ * `input_audio.clear` are refused on one (`invalid_request`, param `type`).
622
+ */
535
623
  export declare const realtimeClientCommandSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
536
624
  type: z.ZodLiteral<"session.update">;
537
625
  config: z.ZodObject<{
@@ -702,6 +790,28 @@ export declare const realtimeClientCommandSchema: z.ZodDiscriminatedUnion<[z.Zod
702
790
  schemaVersion: z.ZodLiteral<1>;
703
791
  requestId: z.ZodString;
704
792
  commandId: z.ZodString;
793
+ }, z.core.$strip>, z.ZodObject<{
794
+ type: z.ZodLiteral<"delegation.reply">;
795
+ delegationId: z.ZodString;
796
+ text: z.ZodString;
797
+ verbatim: z.ZodOptional<z.ZodArray<z.ZodString>>;
798
+ final: z.ZodBoolean;
799
+ schemaVersion: z.ZodLiteral<1>;
800
+ requestId: z.ZodString;
801
+ commandId: z.ZodString;
802
+ }, z.core.$strip>, z.ZodObject<{
803
+ type: z.ZodLiteral<"delegation.context">;
804
+ delegationId: z.ZodString;
805
+ text: z.ZodString;
806
+ schemaVersion: z.ZodLiteral<1>;
807
+ requestId: z.ZodString;
808
+ commandId: z.ZodString;
809
+ }, z.core.$strip>, z.ZodObject<{
810
+ type: z.ZodLiteral<"delegation.cancel">;
811
+ delegationId: z.ZodString;
812
+ schemaVersion: z.ZodLiteral<1>;
813
+ requestId: z.ZodString;
814
+ commandId: z.ZodString;
705
815
  }, z.core.$strip>], "type">;
706
816
  export declare const realtimeSessionUpdatedEventSchema: z.ZodObject<{
707
817
  type: z.ZodLiteral<"session.updated">;
@@ -765,6 +875,12 @@ export declare const realtimeSessionUpdatedEventSchema: z.ZodObject<{
765
875
  name: z.ZodString;
766
876
  }, z.core.$strict>]>>;
767
877
  maxOutputTokens: z.ZodOptional<z.ZodNumber>;
878
+ delegation: z.ZodOptional<z.ZodObject<{
879
+ acknowledgement: z.ZodEnum<{
880
+ auto: "auto";
881
+ none: "none";
882
+ }>;
883
+ }, z.core.$strict>>;
768
884
  }, z.core.$strict>;
769
885
  schemaVersion: z.ZodLiteral<1>;
770
886
  requestId: z.ZodString;
@@ -1067,6 +1183,35 @@ export declare const realtimeToolCallEventSchema: z.ZodObject<{
1067
1183
  sequence: z.ZodNumber;
1068
1184
  commandId: z.ZodOptional<z.ZodString>;
1069
1185
  }, z.core.$strip>;
1186
+ /**
1187
+ * A `live` session hands one turn to its caller (contract set 8.16.0). `text`
1188
+ * is the caller's words since the previous delegation, assembled by Kaana from
1189
+ * the input transcript, so no client stitches transcripts. Answer it with
1190
+ * `delegation.reply`; a newer delegation before its `final` reply supersedes
1191
+ * it.
1192
+ */
1193
+ export declare const realtimeDelegationRequestedEventSchema: z.ZodObject<{
1194
+ type: z.ZodLiteral<"delegation.requested">;
1195
+ delegationId: z.ZodString;
1196
+ text: z.ZodString;
1197
+ schemaVersion: z.ZodLiteral<1>;
1198
+ requestId: z.ZodString;
1199
+ sequence: z.ZodNumber;
1200
+ commandId: z.ZodOptional<z.ZodString>;
1201
+ }, z.core.$strip>;
1202
+ /**
1203
+ * The person moved on: a newer delegation opened before this one's `final`
1204
+ * reply (contract set 8.16.0). Its reply is no longer spoken, and a command
1205
+ * naming it is refused.
1206
+ */
1207
+ export declare const realtimeDelegationSupersededEventSchema: z.ZodObject<{
1208
+ type: z.ZodLiteral<"delegation.superseded">;
1209
+ delegationId: z.ZodString;
1210
+ schemaVersion: z.ZodLiteral<1>;
1211
+ requestId: z.ZodString;
1212
+ sequence: z.ZodNumber;
1213
+ commandId: z.ZodOptional<z.ZodString>;
1214
+ }, z.core.$strip>;
1070
1215
  /** How a response ended. */
1071
1216
  export declare const realtimeResponseStatusSchema: z.ZodEnum<{
1072
1217
  cancelled: "cancelled";
@@ -1098,6 +1243,16 @@ export interface RealtimeConfigIssue {
1098
1243
  * apply the same ones, and a session a client may open is one Kaana may run.
1099
1244
  */
1100
1245
  export declare function realtimeConfigIssues(kind: z.infer<typeof realtimeSessionKindSchema>, config: z.infer<typeof realtimeSessionConfigSchema>): RealtimeConfigIssue[];
1246
+ /**
1247
+ * Whether a session of this kind takes a command (contract set 8.16.0, Kaana
1248
+ * ADR 0012): a `live` session takes no `session.update`, `input_audio.commit`
1249
+ * or `input_audio.clear`, because its voice fixes the session at open and
1250
+ * detects the turns, and only a `live` session takes the `delegation.*`
1251
+ * commands. Kaana refuses any other with `invalid_request`, param `type`,
1252
+ * before acknowledging it. Whether the model serves a command it takes is the
1253
+ * model's to answer.
1254
+ */
1255
+ export declare function realtimeSessionTakes(kind: z.infer<typeof realtimeSessionKindSchema>, command: z.infer<typeof realtimeClientCommandSchema>['type']): boolean;
1101
1256
  /**
1102
1257
  * The customer's partial limits request: every signed limit, each filled from
1103
1258
  * Kaana's defaults when omitted, never above them.
@@ -1138,6 +1293,7 @@ export declare const realtimeSessionOpenSchema: z.ZodObject<{
1138
1293
  conversation: "conversation";
1139
1294
  transcription: "transcription";
1140
1295
  translation: "translation";
1296
+ live: "live";
1141
1297
  }>;
1142
1298
  transport: z.ZodOptional<z.ZodEnum<{
1143
1299
  websocket: "websocket";
@@ -1202,6 +1358,12 @@ export declare const realtimeSessionOpenSchema: z.ZodObject<{
1202
1358
  name: z.ZodString;
1203
1359
  }, z.core.$strict>]>>;
1204
1360
  maxOutputTokens: z.ZodOptional<z.ZodNumber>;
1361
+ delegation: z.ZodOptional<z.ZodObject<{
1362
+ acknowledgement: z.ZodEnum<{
1363
+ auto: "auto";
1364
+ none: "none";
1365
+ }>;
1366
+ }, z.core.$strict>>;
1205
1367
  }, z.core.$strict>;
1206
1368
  limits: z.ZodOptional<z.ZodObject<{
1207
1369
  maxDurationMs: z.ZodOptional<z.ZodNumber>;
@@ -1252,6 +1414,7 @@ export declare const realtimePublicSessionCreatedEventSchema: z.ZodObject<{
1252
1414
  conversation: "conversation";
1253
1415
  transcription: "transcription";
1254
1416
  translation: "translation";
1417
+ live: "live";
1255
1418
  }>;
1256
1419
  config: z.ZodObject<{
1257
1420
  instructions: z.ZodOptional<z.ZodString>;
@@ -1313,6 +1476,12 @@ export declare const realtimePublicSessionCreatedEventSchema: z.ZodObject<{
1313
1476
  name: z.ZodString;
1314
1477
  }, z.core.$strict>]>>;
1315
1478
  maxOutputTokens: z.ZodOptional<z.ZodNumber>;
1479
+ delegation: z.ZodOptional<z.ZodObject<{
1480
+ acknowledgement: z.ZodEnum<{
1481
+ auto: "auto";
1482
+ none: "none";
1483
+ }>;
1484
+ }, z.core.$strict>>;
1316
1485
  }, z.core.$strict>;
1317
1486
  limits: z.ZodObject<{
1318
1487
  maxDurationMs: z.ZodNumber;
@@ -1492,6 +1661,7 @@ export declare const realtimePublicServerEventSchema: z.ZodDiscriminatedUnion<[z
1492
1661
  conversation: "conversation";
1493
1662
  transcription: "transcription";
1494
1663
  translation: "translation";
1664
+ live: "live";
1495
1665
  }>;
1496
1666
  config: z.ZodObject<{
1497
1667
  instructions: z.ZodOptional<z.ZodString>;
@@ -1553,6 +1723,12 @@ export declare const realtimePublicServerEventSchema: z.ZodDiscriminatedUnion<[z
1553
1723
  name: z.ZodString;
1554
1724
  }, z.core.$strict>]>>;
1555
1725
  maxOutputTokens: z.ZodOptional<z.ZodNumber>;
1726
+ delegation: z.ZodOptional<z.ZodObject<{
1727
+ acknowledgement: z.ZodEnum<{
1728
+ auto: "auto";
1729
+ none: "none";
1730
+ }>;
1731
+ }, z.core.$strict>>;
1556
1732
  }, z.core.$strict>;
1557
1733
  limits: z.ZodObject<{
1558
1734
  maxDurationMs: z.ZodNumber;
@@ -1630,6 +1806,12 @@ export declare const realtimePublicServerEventSchema: z.ZodDiscriminatedUnion<[z
1630
1806
  name: z.ZodString;
1631
1807
  }, z.core.$strict>]>>;
1632
1808
  maxOutputTokens: z.ZodOptional<z.ZodNumber>;
1809
+ delegation: z.ZodOptional<z.ZodObject<{
1810
+ acknowledgement: z.ZodEnum<{
1811
+ auto: "auto";
1812
+ none: "none";
1813
+ }>;
1814
+ }, z.core.$strict>>;
1633
1815
  }, z.core.$strict>;
1634
1816
  schemaVersion: z.ZodLiteral<1>;
1635
1817
  requestId: z.ZodString;
@@ -1889,6 +2071,21 @@ export declare const realtimePublicServerEventSchema: z.ZodDiscriminatedUnion<[z
1889
2071
  requestId: z.ZodString;
1890
2072
  sequence: z.ZodNumber;
1891
2073
  commandId: z.ZodOptional<z.ZodString>;
2074
+ }, z.core.$strip>, z.ZodObject<{
2075
+ type: z.ZodLiteral<"delegation.requested">;
2076
+ delegationId: z.ZodString;
2077
+ text: z.ZodString;
2078
+ schemaVersion: z.ZodLiteral<1>;
2079
+ requestId: z.ZodString;
2080
+ sequence: z.ZodNumber;
2081
+ commandId: z.ZodOptional<z.ZodString>;
2082
+ }, z.core.$strip>, z.ZodObject<{
2083
+ type: z.ZodLiteral<"delegation.superseded">;
2084
+ delegationId: z.ZodString;
2085
+ schemaVersion: z.ZodLiteral<1>;
2086
+ requestId: z.ZodString;
2087
+ sequence: z.ZodNumber;
2088
+ commandId: z.ZodOptional<z.ZodString>;
1892
2089
  }, z.core.$strip>, z.ZodObject<{
1893
2090
  type: z.ZodLiteral<"response.done">;
1894
2091
  responseId: z.ZodString;
@@ -2041,6 +2238,13 @@ export type RealtimeTurnDetection = z.infer<typeof realtimeTurnDetectionSchema>;
2041
2238
  export type RealtimeInputTranscription = z.infer<typeof realtimeInputTranscriptionSchema>;
2042
2239
  export type RealtimeTranslation = z.infer<typeof realtimeTranslationSchema>;
2043
2240
  export type RealtimeSessionConfig = z.infer<typeof realtimeSessionConfigSchema>;
2241
+ export type RealtimeDelegationAcknowledgement = z.infer<typeof realtimeDelegationAcknowledgementSchema>;
2242
+ export type RealtimeDelegationConfig = z.infer<typeof realtimeDelegationConfigSchema>;
2243
+ export type RealtimeDelegationReplyCommand = z.infer<typeof realtimeDelegationReplyCommandSchema>;
2244
+ export type RealtimeDelegationContextCommand = z.infer<typeof realtimeDelegationContextCommandSchema>;
2245
+ export type RealtimeDelegationCancelCommand = z.infer<typeof realtimeDelegationCancelCommandSchema>;
2246
+ export type RealtimeDelegationRequestedEvent = z.infer<typeof realtimeDelegationRequestedEventSchema>;
2247
+ export type RealtimeDelegationSupersededEvent = z.infer<typeof realtimeDelegationSupersededEventSchema>;
2044
2248
  export type RealtimeSessionConfigUpdate = z.infer<typeof realtimeSessionConfigUpdateSchema>;
2045
2249
  export type RealtimeSessionLimits = z.infer<typeof realtimeSessionLimitsSchema>;
2046
2250
  export type RealtimeContentPart = z.infer<typeof realtimeContentPartSchema>;
@@ -36,6 +36,17 @@ export const MAX_REALTIME_RESUME_WINDOW_MS = 60_000;
36
36
  * reads it here, never copies it.
37
37
  */
38
38
  export const MAX_REALTIME_ITEM_TEXT_CHARS = 1_048_576;
39
+ /**
40
+ * The most characters (UTF-16 code units) the text of one `delegation.reply` or
41
+ * `delegation.context` may hold (contract set 8.16.0). A client streams a long
42
+ * answer as several replies, sentence by sentence; Kaana splits each to its
43
+ * provider's own bound.
44
+ */
45
+ export const MAX_REALTIME_DELEGATION_TEXT_CHARS = 8_192;
46
+ /** The most verbatim spans one `delegation.reply` may mark (contract set 8.16.0). */
47
+ export const MAX_REALTIME_VERBATIM_SPANS = 32;
48
+ /** The most characters (UTF-16 code units) one verbatim span may hold (contract set 8.16.0). */
49
+ export const MAX_REALTIME_VERBATIM_SPAN_CHARS = 256;
39
50
  /** A client-chosen command identity, unique within one session. */
40
51
  export const realtimeCommandIdSchema = z
41
52
  .string()
@@ -43,6 +54,14 @@ export const realtimeCommandIdSchema = z
43
54
  .check(maxUtf16Length(128));
44
55
  /** A conversation item's identity within one session. */
45
56
  export const realtimeItemIdSchema = z.string().check(minUtf16Length(1)).check(maxUtf16Length(128));
57
+ /**
58
+ * A delegation's identity within one session: one turn a `live` session handed
59
+ * to its caller (contract set 8.16.0).
60
+ */
61
+ export const realtimeDelegationIdSchema = z
62
+ .string()
63
+ .check(minUtf16Length(1))
64
+ .check(maxUtf16Length(128));
46
65
  /** A response's identity within one session. */
47
66
  export const realtimeResponseIdSchema = z
48
67
  .string()
@@ -105,6 +124,10 @@ export const realtimeTurnDetectionSchema = z.discriminatedUnion('type', [
105
124
  * session: where the provider bills the transcription
106
125
  * apart from the session model, as `input_transcription_milliseconds` (see
107
126
  * `USAGE_UNITS`); where the session's own price includes it, as nothing more.
127
+ *
128
+ * A `live` session relays the caller's words whether or not it is set, because
129
+ * its delegation needs them; there it takes `language` only (contract set
130
+ * 8.16.0).
108
131
  */
109
132
  export const realtimeInputTranscriptionSchema = z
110
133
  .object({
@@ -131,6 +154,21 @@ export const realtimeTranslationSchema = z
131
154
  targetLanguage: z.string().check(minUtf16Length(2)).check(maxUtf16Length(35)),
132
155
  })
133
156
  .strict();
157
+ /**
158
+ * Whether the voice of a `live` session acknowledges a turn it handed over:
159
+ * `auto` lets it say a short "one moment" while the caller's backend works;
160
+ * `none` keeps it silent until the first reply.
161
+ */
162
+ export const realtimeDelegationAcknowledgementSchema = z.enum(['auto', 'none']);
163
+ /**
164
+ * How a `live` session hands its turns to its caller (contract set 8.16.0,
165
+ * Kaana ADR 0012). Required for `live` and refused for every other kind.
166
+ */
167
+ export const realtimeDelegationConfigSchema = z
168
+ .object({
169
+ acknowledgement: realtimeDelegationAcknowledgementSchema,
170
+ })
171
+ .strict();
134
172
  /**
135
173
  * A function tool a session may call: the chat tool without `strict`, which no
136
174
  * realtime provider's session schema has (contract set 5.0.0).
@@ -162,6 +200,8 @@ export const realtimeSessionConfigSchema = z
162
200
  toolChoice: toolChoiceSchema.optional(),
163
201
  /** Per response, not per session: the session's ceiling is `limits`. */
164
202
  maxOutputTokens: z.number().int().positive().safe().optional(),
203
+ /** A `live` session's delegation; fixed at open (contract set 8.16.0). */
204
+ delegation: realtimeDelegationConfigSchema.optional(),
165
205
  })
166
206
  .strict();
167
207
  /**
@@ -184,6 +224,8 @@ export const realtimeSessionConfigUpdateSchema = z
184
224
  })
185
225
  .strict()
186
226
  .superRefine((update, ctx) => {
227
+ // A `live` session takes no update at all: its voice fixes everything at
228
+ // open, and Kaana refuses the command (`invalid_request`, param `type`).
187
229
  if (Object.keys(update).length === 0) {
188
230
  ctx.addIssue({
189
231
  code: 'custom',
@@ -377,8 +419,53 @@ export const realtimeSessionCloseCommandSchema = z.object({
377
419
  ...commandBase,
378
420
  type: z.literal('session.close'),
379
421
  });
380
- /** Every command a client can send. */
381
- export const realtimeClientCommandSchema = z.discriminatedUnion('type', [
422
+ const delegationTextSchema = z
423
+ .string()
424
+ .check(minUtf16Length(1))
425
+ .check(maxUtf16Length(MAX_REALTIME_DELEGATION_TEXT_CHARS));
426
+ /**
427
+ * Speak this part of a delegated turn's answer (contract set 8.16.0). A client
428
+ * streams its answer sentence by sentence and marks the last part `final`;
429
+ * after it, nothing more is spoken for the delegation. Each `verbatim` span is
430
+ * a part of `text` the voice says exactly as written: numbers, addresses,
431
+ * names, codes. A reply to a delegation that is unknown, superseded, cancelled
432
+ * or already final is refused (`invalid_request`, param `delegationId`).
433
+ */
434
+ export const realtimeDelegationReplyCommandSchema = z.object({
435
+ ...commandBase,
436
+ type: z.literal('delegation.reply'),
437
+ delegationId: realtimeDelegationIdSchema,
438
+ text: delegationTextSchema,
439
+ verbatim: z
440
+ .array(z.string().check(minUtf16Length(1)).check(maxUtf16Length(MAX_REALTIME_VERBATIM_SPAN_CHARS)))
441
+ .max(MAX_REALTIME_VERBATIM_SPANS)
442
+ .optional(),
443
+ final: z.boolean(),
444
+ });
445
+ /**
446
+ * Silent context the voice may use while a delegated turn is answered, for
447
+ * example "still checking your calendar" (contract set 8.16.0). Never spoken
448
+ * as written.
449
+ */
450
+ export const realtimeDelegationContextCommandSchema = z.object({
451
+ ...commandBase,
452
+ type: z.literal('delegation.context'),
453
+ delegationId: realtimeDelegationIdSchema,
454
+ text: delegationTextSchema,
455
+ });
456
+ /** The client dropped a delegated turn: nothing more is spoken for it (contract set 8.16.0). */
457
+ export const realtimeDelegationCancelCommandSchema = z.object({
458
+ ...commandBase,
459
+ type: z.literal('delegation.cancel'),
460
+ delegationId: realtimeDelegationIdSchema,
461
+ });
462
+ /**
463
+ * Every command a client can send. The three `delegation.*` commands are a
464
+ * `live` session's; `session.update`, `input_audio.commit` and
465
+ * `input_audio.clear` are refused on one (`invalid_request`, param `type`).
466
+ */
467
+ export const realtimeClientCommandSchema = z
468
+ .discriminatedUnion('type', [
382
469
  realtimeSessionUpdateCommandSchema,
383
470
  realtimeItemCreateCommandSchema,
384
471
  realtimeItemDeleteCommandSchema,
@@ -390,7 +477,25 @@ export const realtimeClientCommandSchema = z.discriminatedUnion('type', [
390
477
  realtimeResponseCancelCommandSchema,
391
478
  realtimeSessionResumeCommandSchema,
392
479
  realtimeSessionCloseCommandSchema,
393
- ]);
480
+ realtimeDelegationReplyCommandSchema,
481
+ realtimeDelegationContextCommandSchema,
482
+ realtimeDelegationCancelCommandSchema,
483
+ ])
484
+ .superRefine((command, ctx) => {
485
+ // Checked on the union because a discriminated union's options must stay
486
+ // plain objects.
487
+ if (command.type !== 'delegation.reply' || command.verbatim === undefined)
488
+ return;
489
+ for (const [index, span] of command.verbatim.entries()) {
490
+ if (!command.text.includes(span)) {
491
+ ctx.addIssue({
492
+ code: 'custom',
493
+ path: ['verbatim', index],
494
+ message: 'a verbatim span is a part of the reply text, exactly as written',
495
+ });
496
+ }
497
+ }
498
+ });
394
499
  const eventBase = {
395
500
  /** See `version.ts`: each event is a whole message on the wire. */
396
501
  schemaVersion: z.literal(1),
@@ -550,6 +655,29 @@ export const realtimeToolCallEventSchema = z.object({
550
655
  argumentsDelta: z.string().optional(),
551
656
  complete: z.boolean(),
552
657
  });
658
+ /**
659
+ * A `live` session hands one turn to its caller (contract set 8.16.0). `text`
660
+ * is the caller's words since the previous delegation, assembled by Kaana from
661
+ * the input transcript, so no client stitches transcripts. Answer it with
662
+ * `delegation.reply`; a newer delegation before its `final` reply supersedes
663
+ * it.
664
+ */
665
+ export const realtimeDelegationRequestedEventSchema = z.object({
666
+ ...eventBase,
667
+ type: z.literal('delegation.requested'),
668
+ delegationId: realtimeDelegationIdSchema,
669
+ text: z.string(),
670
+ });
671
+ /**
672
+ * The person moved on: a newer delegation opened before this one's `final`
673
+ * reply (contract set 8.16.0). Its reply is no longer spoken, and a command
674
+ * naming it is refused.
675
+ */
676
+ export const realtimeDelegationSupersededEventSchema = z.object({
677
+ ...eventBase,
678
+ type: z.literal('delegation.superseded'),
679
+ delegationId: realtimeDelegationIdSchema,
680
+ });
553
681
  /** How a response ended. */
554
682
  export const realtimeResponseStatusSchema = z.enum([
555
683
  'completed',
@@ -622,6 +750,39 @@ export function realtimeConfigIssues(kind, config) {
622
750
  found(['tools'], 'a translation session calls no tools');
623
751
  }
624
752
  break;
753
+ case 'live':
754
+ // Kaana ADR 0012 §1: the voice speaks, detects turns and hands each one
755
+ // over; the caller's backend answers it, with its own tools.
756
+ if (config.voice === undefined) {
757
+ found(['voice'], 'a live session speaks in a voice');
758
+ }
759
+ if (config.outputAudioFormat !== config.inputAudioFormat) {
760
+ found(['outputAudioFormat'], 'a live session speaks the audio format it hears');
761
+ }
762
+ if (config.turnDetection.type === 'none') {
763
+ found(['turnDetection'], 'the voice of a live session detects the turns');
764
+ }
765
+ if (config.delegation === undefined) {
766
+ found(['delegation'], 'a live session hands its turns over');
767
+ }
768
+ for (const field of [
769
+ 'outputModalities',
770
+ 'tools',
771
+ 'toolChoice',
772
+ 'maxOutputTokens',
773
+ 'translation',
774
+ ]) {
775
+ if (config[field] !== undefined) {
776
+ found([field], "a live session's answers and their tools are its caller's");
777
+ }
778
+ }
779
+ if (config.inputAudioTranscription?.prompt !== undefined) {
780
+ found(['inputAudioTranscription', 'prompt'], 'a live session transcribes with no prompt');
781
+ }
782
+ break;
783
+ }
784
+ if (kind !== 'live' && config.delegation !== undefined) {
785
+ found(['delegation'], 'only a live session hands its turns over');
625
786
  }
626
787
  if (kind !== 'transcription' && config.inputAudioTranscription?.interimResults === true) {
627
788
  found(['inputAudioTranscription', 'interimResults'], 'only a transcription session sends interim text');
@@ -641,6 +802,25 @@ export function realtimeConfigIssues(kind, config) {
641
802
  }
642
803
  return issues;
643
804
  }
805
+ const REFUSED_BY_LIVE = new Set([
806
+ 'session.update',
807
+ 'input_audio.commit',
808
+ 'input_audio.clear',
809
+ ]);
810
+ /**
811
+ * Whether a session of this kind takes a command (contract set 8.16.0, Kaana
812
+ * ADR 0012): a `live` session takes no `session.update`, `input_audio.commit`
813
+ * or `input_audio.clear`, because its voice fixes the session at open and
814
+ * detects the turns, and only a `live` session takes the `delegation.*`
815
+ * commands. Kaana refuses any other with `invalid_request`, param `type`,
816
+ * before acknowledging it. Whether the model serves a command it takes is the
817
+ * model's to answer.
818
+ */
819
+ export function realtimeSessionTakes(kind, command) {
820
+ if (kind === 'live')
821
+ return !REFUSED_BY_LIVE.has(command);
822
+ return !command.startsWith('delegation.');
823
+ }
644
824
  /* -------------------------------------------------------------------------- */
645
825
  /* Opening a session (`GET /v1/realtime`) */
646
826
  /* -------------------------------------------------------------------------- */
@@ -835,6 +1015,8 @@ export const realtimePublicServerEventSchema = z
835
1015
  realtimeTranscriptInterimEventSchema,
836
1016
  realtimeTextDeltaEventSchema,
837
1017
  realtimeToolCallEventSchema,
1018
+ realtimeDelegationRequestedEventSchema,
1019
+ realtimeDelegationSupersededEventSchema,
838
1020
  realtimePublicResponseDoneEventSchema,
839
1021
  realtimePublicErrorEventSchema,
840
1022
  realtimePublicSessionClosedEventSchema,
@@ -100,7 +100,7 @@
100
100
  * change to, say, the catalogue reject every in-flight inference request; the
101
101
  * per-shape `schemaVersion` is what a message is validated against.
102
102
  */
103
- export declare const INFERENCE_CONTRACT_VERSION = "8.15.0";
103
+ export declare const INFERENCE_CONTRACT_VERSION = "8.16.0";
104
104
  /**
105
105
  * Contract set 4.0.0 (Kaana ADR 0002) is the first published as
106
106
  * `@kaana.ai/contracts`. MAJOR because the set changed hands and split in two:
@@ -265,6 +265,17 @@ export declare const INFERENCE_CONTRACT_VERSION = "8.15.0";
265
265
  * `POST /v1/rerank` and emits the `rerank` operation for a model some deployment
266
266
  * can serve.
267
267
  */
268
+ /**
269
+ * Contract set 8.16.0 (Kaana ADR 0012) is additive: the realtime session kind
270
+ * `live`, a spoken conversation whose turns the caller's backend answers. Its
271
+ * `config.delegation` (`realtimeDelegationConfigSchema`), the commands
272
+ * `delegation.reply`, `delegation.context` and `delegation.cancel`, the events
273
+ * `delegation.requested` and `delegation.superseded`, and the catalogue's
274
+ * `capabilities.realtime.defaultKinds`, with at most one active default line per
275
+ * kind. Every 8.15.0 message parses the same; a consumer on 8.15.0 refuses a
276
+ * session, a command, an event or a catalogue carrying what is new, so Oxy reads
277
+ * them before Kaana serves a `live` line.
278
+ */
268
279
  /** The public API's one origin and version. */
269
280
  export declare const KAANA_API_BASE_URL = "https://kaana.ai/v1";
270
281
  /** The response header that carries the request id. */
@@ -100,7 +100,7 @@
100
100
  * change to, say, the catalogue reject every in-flight inference request; the
101
101
  * per-shape `schemaVersion` is what a message is validated against.
102
102
  */
103
- export const INFERENCE_CONTRACT_VERSION = '8.15.0';
103
+ export const INFERENCE_CONTRACT_VERSION = '8.16.0';
104
104
  /**
105
105
  * Contract set 4.0.0 (Kaana ADR 0002) is the first published as
106
106
  * `@kaana.ai/contracts`. MAJOR because the set changed hands and split in two:
@@ -265,6 +265,17 @@ export const INFERENCE_CONTRACT_VERSION = '8.15.0';
265
265
  * `POST /v1/rerank` and emits the `rerank` operation for a model some deployment
266
266
  * can serve.
267
267
  */
268
+ /**
269
+ * Contract set 8.16.0 (Kaana ADR 0012) is additive: the realtime session kind
270
+ * `live`, a spoken conversation whose turns the caller's backend answers. Its
271
+ * `config.delegation` (`realtimeDelegationConfigSchema`), the commands
272
+ * `delegation.reply`, `delegation.context` and `delegation.cancel`, the events
273
+ * `delegation.requested` and `delegation.superseded`, and the catalogue's
274
+ * `capabilities.realtime.defaultKinds`, with at most one active default line per
275
+ * kind. Every 8.15.0 message parses the same; a consumer on 8.15.0 refuses a
276
+ * session, a command, an event or a catalogue carrying what is new, so Oxy reads
277
+ * them before Kaana serves a `live` line.
278
+ */
268
279
  /** The public API's one origin and version. */
269
280
  export const KAANA_API_BASE_URL = 'https://kaana.ai/v1';
270
281
  /** The response header that carries the request id. */