@kaana.ai/contracts 5.0.0 → 6.0.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.
@@ -5,8 +5,7 @@
5
5
  */
6
6
  import { z } from 'zod';
7
7
  import { realtimeOutputModalitySchema } from './audioFormats.js';
8
- import { type ModelAudioCapabilities, type ModelCapabilities, type RealtimeParameters, realtimeSessionKindSchema } from './catalogue.js';
9
- import { toolChoiceSchema } from './messages.js';
8
+ import { type ModelAudioCapabilities, type ModelCapabilities, realtimeSessionKindSchema } from './catalogue.js';
10
9
  /**
11
10
  * The most base64 characters one audio frame may carry: 49 152 bytes of audio,
12
11
  * about one second of 24 kHz mono PCM16. Bounded so no frame is large enough to
@@ -38,6 +37,10 @@ export declare const realtimeResponseIdSchema: z.ZodString;
38
37
  * them: whether the model answers on its own, and whether new speech cuts it
39
38
  * off, are the two behaviours a caller most needs to have chosen, and a default
40
39
  * would choose them silently — and differently per provider.
40
+ *
41
+ * A `server_vad` that names no `silenceDurationMs` waits Kaana's
42
+ * {@link REALTIME_DEFAULT_SILENCE_DURATION_MS}, on every provider (contract set
43
+ * 6.0.0), never the provider's own default.
41
44
  */
42
45
  export declare const realtimeTurnDetectionSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
43
46
  type: z.ZodLiteral<"none">;
@@ -66,13 +69,12 @@ export declare const realtimeTurnDetectionSchema: z.ZodDiscriminatedUnion<[z.Zod
66
69
  *
67
70
  * In a `conversation` it is served only by a model whose catalogue entry says
68
71
  * so (`capabilities.realtime.inputAudioTranscription`, contract set 4.1.0),
69
- * and each transcribed turn arrives as `transcript.delta` / `transcript.done`
70
- * with `source: 'input_audio'`. What it costs is settled with the session:
71
- * where the provider bills the transcription apart from the session model, as
72
- * `input_transcription_milliseconds` (see `USAGE_UNITS`); where the session's
73
- * own price includes it, as nothing more.
74
- *
75
- * `language`, when given, is one of the model's published `audio.languages`.
72
+ * and each transcribed turn arrives as deltas that only append and EXACTLY
73
+ * ONE `transcript.done` with `source: 'input_audio'`, the final transcript of
74
+ * that item (contract set 6.0.0), whatever its provider sends. What it costs
75
+ * is settled with the session: where the provider bills the transcription
76
+ * apart from the session model, as `input_transcription_milliseconds` (see
77
+ * `USAGE_UNITS`); where the session's own price includes it, as nothing more.
76
78
  */
77
79
  export declare const realtimeInputTranscriptionSchema: z.ZodObject<{
78
80
  language: z.ZodOptional<z.ZodString>;
@@ -89,8 +91,8 @@ export declare const realtimeTranslationSchema: z.ZodObject<{
89
91
  export declare const realtimeToolDefinitionSchema: z.ZodObject<{
90
92
  type: z.ZodLiteral<"function">;
91
93
  name: z.ZodString;
92
- parameters: z.ZodRecord<z.ZodString, z.ZodUnknown>;
93
94
  description: z.ZodOptional<z.ZodString>;
95
+ parameters: z.ZodRecord<z.ZodString, z.ZodUnknown>;
94
96
  }, z.core.$strict>;
95
97
  /**
96
98
  * A session's full configuration, as signed at open and as echoed back by
@@ -148,12 +150,12 @@ export declare const realtimeSessionConfigSchema: z.ZodObject<{
148
150
  tools: z.ZodOptional<z.ZodArray<z.ZodObject<{
149
151
  type: z.ZodLiteral<"function">;
150
152
  name: z.ZodString;
151
- parameters: z.ZodRecord<z.ZodString, z.ZodUnknown>;
152
153
  description: z.ZodOptional<z.ZodString>;
154
+ parameters: z.ZodRecord<z.ZodString, z.ZodUnknown>;
153
155
  }, z.core.$strict>>>;
154
156
  toolChoice: z.ZodOptional<z.ZodUnion<readonly [z.ZodEnum<{
155
- none: "none";
156
157
  auto: "auto";
158
+ none: "none";
157
159
  required: "required";
158
160
  }>, z.ZodObject<{
159
161
  type: z.ZodLiteral<"function">;
@@ -202,12 +204,12 @@ export declare const realtimeSessionConfigUpdateSchema: z.ZodObject<{
202
204
  tools: z.ZodOptional<z.ZodArray<z.ZodObject<{
203
205
  type: z.ZodLiteral<"function">;
204
206
  name: z.ZodString;
205
- parameters: z.ZodRecord<z.ZodString, z.ZodUnknown>;
206
207
  description: z.ZodOptional<z.ZodString>;
208
+ parameters: z.ZodRecord<z.ZodString, z.ZodUnknown>;
207
209
  }, z.core.$strict>>>;
208
210
  toolChoice: z.ZodOptional<z.ZodUnion<readonly [z.ZodEnum<{
209
- none: "none";
210
211
  auto: "auto";
212
+ none: "none";
211
213
  required: "required";
212
214
  }>, z.ZodObject<{
213
215
  type: z.ZodLiteral<"function">;
@@ -318,8 +320,8 @@ export declare const realtimeResponseParametersSchema: z.ZodObject<{
318
320
  }>>>;
319
321
  maxOutputTokens: z.ZodOptional<z.ZodNumber>;
320
322
  toolChoice: z.ZodOptional<z.ZodUnion<readonly [z.ZodEnum<{
321
- none: "none";
322
323
  auto: "auto";
324
+ none: "none";
323
325
  required: "required";
324
326
  }>, z.ZodObject<{
325
327
  type: z.ZodLiteral<"function">;
@@ -361,12 +363,12 @@ export declare const realtimeSessionUpdateCommandSchema: z.ZodObject<{
361
363
  tools: z.ZodOptional<z.ZodArray<z.ZodObject<{
362
364
  type: z.ZodLiteral<"function">;
363
365
  name: z.ZodString;
364
- parameters: z.ZodRecord<z.ZodString, z.ZodUnknown>;
365
366
  description: z.ZodOptional<z.ZodString>;
367
+ parameters: z.ZodRecord<z.ZodString, z.ZodUnknown>;
366
368
  }, z.core.$strict>>>;
367
369
  toolChoice: z.ZodOptional<z.ZodUnion<readonly [z.ZodEnum<{
368
- none: "none";
369
370
  auto: "auto";
371
+ none: "none";
370
372
  required: "required";
371
373
  }>, z.ZodObject<{
372
374
  type: z.ZodLiteral<"function">;
@@ -479,8 +481,8 @@ export declare const realtimeResponseCreateCommandSchema: z.ZodObject<{
479
481
  }>>>;
480
482
  maxOutputTokens: z.ZodOptional<z.ZodNumber>;
481
483
  toolChoice: z.ZodOptional<z.ZodUnion<readonly [z.ZodEnum<{
482
- none: "none";
483
484
  auto: "auto";
485
+ none: "none";
484
486
  required: "required";
485
487
  }>, z.ZodObject<{
486
488
  type: z.ZodLiteral<"function">;
@@ -551,12 +553,12 @@ export declare const realtimeClientCommandSchema: z.ZodDiscriminatedUnion<[z.Zod
551
553
  tools: z.ZodOptional<z.ZodArray<z.ZodObject<{
552
554
  type: z.ZodLiteral<"function">;
553
555
  name: z.ZodString;
554
- parameters: z.ZodRecord<z.ZodString, z.ZodUnknown>;
555
556
  description: z.ZodOptional<z.ZodString>;
557
+ parameters: z.ZodRecord<z.ZodString, z.ZodUnknown>;
556
558
  }, z.core.$strict>>>;
557
559
  toolChoice: z.ZodOptional<z.ZodUnion<readonly [z.ZodEnum<{
558
- none: "none";
559
560
  auto: "auto";
561
+ none: "none";
560
562
  required: "required";
561
563
  }>, z.ZodObject<{
562
564
  type: z.ZodLiteral<"function">;
@@ -657,8 +659,8 @@ export declare const realtimeClientCommandSchema: z.ZodDiscriminatedUnion<[z.Zod
657
659
  }>>>;
658
660
  maxOutputTokens: z.ZodOptional<z.ZodNumber>;
659
661
  toolChoice: z.ZodOptional<z.ZodUnion<readonly [z.ZodEnum<{
660
- none: "none";
661
662
  auto: "auto";
663
+ none: "none";
662
664
  required: "required";
663
665
  }>, z.ZodObject<{
664
666
  type: z.ZodLiteral<"function">;
@@ -735,12 +737,12 @@ export declare const realtimeSessionUpdatedEventSchema: z.ZodObject<{
735
737
  tools: z.ZodOptional<z.ZodArray<z.ZodObject<{
736
738
  type: z.ZodLiteral<"function">;
737
739
  name: z.ZodString;
738
- parameters: z.ZodRecord<z.ZodString, z.ZodUnknown>;
739
740
  description: z.ZodOptional<z.ZodString>;
741
+ parameters: z.ZodRecord<z.ZodString, z.ZodUnknown>;
740
742
  }, z.core.$strict>>>;
741
743
  toolChoice: z.ZodOptional<z.ZodUnion<readonly [z.ZodEnum<{
742
- none: "none";
743
744
  auto: "auto";
745
+ none: "none";
744
746
  required: "required";
745
747
  }>, z.ZodObject<{
746
748
  type: z.ZodLiteral<"function">;
@@ -1079,6 +1081,16 @@ export declare const realtimeOpenLimitsSchema: z.ZodObject<{
1079
1081
  * frame closes the connection before it is read.
1080
1082
  */
1081
1083
  export declare const MAX_REALTIME_OPEN_FRAME_BYTES: number;
1084
+ /**
1085
+ * The silence, in milliseconds, after which `server_vad` ends a caller's turn
1086
+ * when the session names none (contract set 6.0.0, Kaana ADR 0003). Kaana
1087
+ * sends it to every provider, so a turn ends the same way whichever serves
1088
+ * the session. Measured on x-ai/grok-voice-3.0 (2026-10-16): with xAI's own
1089
+ * default a phrase with pauses of 0.56 s and 0.79 s was cut into three
1090
+ * responses, two cancelled, the model speaking before the phrase ended; at
1091
+ * 500 ms it was one response, answered 490–576 ms after the phrase.
1092
+ */
1093
+ export declare const REALTIME_DEFAULT_SILENCE_DURATION_MS = 500;
1082
1094
  /**
1083
1095
  * The first frame a client sends on `GET /v1/realtime?model=…` to OPEN a
1084
1096
  * session (a reconnection instead sends `session.resume`). One grant covers the
@@ -1143,12 +1155,12 @@ export declare const realtimeSessionOpenSchema: z.ZodObject<{
1143
1155
  tools: z.ZodOptional<z.ZodArray<z.ZodObject<{
1144
1156
  type: z.ZodLiteral<"function">;
1145
1157
  name: z.ZodString;
1146
- parameters: z.ZodRecord<z.ZodString, z.ZodUnknown>;
1147
1158
  description: z.ZodOptional<z.ZodString>;
1159
+ parameters: z.ZodRecord<z.ZodString, z.ZodUnknown>;
1148
1160
  }, z.core.$strict>>>;
1149
1161
  toolChoice: z.ZodOptional<z.ZodUnion<readonly [z.ZodEnum<{
1150
- none: "none";
1151
1162
  auto: "auto";
1163
+ none: "none";
1152
1164
  required: "required";
1153
1165
  }>, z.ZodObject<{
1154
1166
  type: z.ZodLiteral<"function">;
@@ -1192,28 +1204,6 @@ export declare function checkRealtimeSessionOpen(open: z.infer<typeof realtimeSe
1192
1204
  readonly capabilities: ModelCapabilities;
1193
1205
  readonly audio?: ModelAudioCapabilities;
1194
1206
  }): RealtimeOpenIssue[];
1195
- /**
1196
- * The part of a session configuration, of a `session.update` or of a
1197
- * `response.create` that a model's {@link RealtimeParameters} govern.
1198
- */
1199
- export interface RealtimeGovernedFields {
1200
- readonly outputModalities?: readonly RealtimeOutputModality[];
1201
- readonly turnDetection?: RealtimeTurnDetection;
1202
- readonly inputAudioTranscription?: {
1203
- readonly prompt?: string;
1204
- };
1205
- readonly toolChoice?: z.infer<typeof toolChoiceSchema>;
1206
- readonly maxOutputTokens?: number;
1207
- }
1208
- /**
1209
- * Every field that `parameters` do not serve, each with the `param` Kaana's
1210
- * refusal names (`prefix` is `config` for an open or a `session.update`,
1211
- * `response` for a `response.create`), in the order Kaana checks them. It is
1212
- * exactly Kaana's own check (Go's `RealtimeParameters.Issues`, held to the
1213
- * same vectors), so a client that builds its session from a model's
1214
- * parameters, or filters models with this, is never refused for one.
1215
- */
1216
- export declare function realtimeParameterIssues(prefix: 'config' | 'response', fields: RealtimeGovernedFields, parameters: RealtimeParameters): RealtimeOpenIssue[];
1217
1207
  /**
1218
1208
  * The session opened: the revision-pinned model, fixed for the rest of the
1219
1209
  * session, and the effective configuration and limits. The signed lane's
@@ -1275,12 +1265,12 @@ export declare const realtimePublicSessionCreatedEventSchema: z.ZodObject<{
1275
1265
  tools: z.ZodOptional<z.ZodArray<z.ZodObject<{
1276
1266
  type: z.ZodLiteral<"function">;
1277
1267
  name: z.ZodString;
1278
- parameters: z.ZodRecord<z.ZodString, z.ZodUnknown>;
1279
1268
  description: z.ZodOptional<z.ZodString>;
1269
+ parameters: z.ZodRecord<z.ZodString, z.ZodUnknown>;
1280
1270
  }, z.core.$strict>>>;
1281
1271
  toolChoice: z.ZodOptional<z.ZodUnion<readonly [z.ZodEnum<{
1282
- none: "none";
1283
1272
  auto: "auto";
1273
+ none: "none";
1284
1274
  required: "required";
1285
1275
  }>, z.ZodObject<{
1286
1276
  type: z.ZodLiteral<"function">;
@@ -1512,12 +1502,12 @@ export declare const realtimePublicServerEventSchema: z.ZodDiscriminatedUnion<[z
1512
1502
  tools: z.ZodOptional<z.ZodArray<z.ZodObject<{
1513
1503
  type: z.ZodLiteral<"function">;
1514
1504
  name: z.ZodString;
1515
- parameters: z.ZodRecord<z.ZodString, z.ZodUnknown>;
1516
1505
  description: z.ZodOptional<z.ZodString>;
1506
+ parameters: z.ZodRecord<z.ZodString, z.ZodUnknown>;
1517
1507
  }, z.core.$strict>>>;
1518
1508
  toolChoice: z.ZodOptional<z.ZodUnion<readonly [z.ZodEnum<{
1519
- none: "none";
1520
1509
  auto: "auto";
1510
+ none: "none";
1521
1511
  required: "required";
1522
1512
  }>, z.ZodObject<{
1523
1513
  type: z.ZodLiteral<"function">;
@@ -1588,12 +1578,12 @@ export declare const realtimePublicServerEventSchema: z.ZodDiscriminatedUnion<[z
1588
1578
  tools: z.ZodOptional<z.ZodArray<z.ZodObject<{
1589
1579
  type: z.ZodLiteral<"function">;
1590
1580
  name: z.ZodString;
1591
- parameters: z.ZodRecord<z.ZodString, z.ZodUnknown>;
1592
1581
  description: z.ZodOptional<z.ZodString>;
1582
+ parameters: z.ZodRecord<z.ZodString, z.ZodUnknown>;
1593
1583
  }, z.core.$strict>>>;
1594
1584
  toolChoice: z.ZodOptional<z.ZodUnion<readonly [z.ZodEnum<{
1595
- none: "none";
1596
1585
  auto: "auto";
1586
+ none: "none";
1597
1587
  required: "required";
1598
1588
  }>, z.ZodObject<{
1599
1589
  type: z.ZodLiteral<"function">;
@@ -49,6 +49,10 @@ const milliseconds = z.number().int().nonnegative().safe();
49
49
  * them: whether the model answers on its own, and whether new speech cuts it
50
50
  * off, are the two behaviours a caller most needs to have chosen, and a default
51
51
  * would choose them silently — and differently per provider.
52
+ *
53
+ * A `server_vad` that names no `silenceDurationMs` waits Kaana's
54
+ * {@link REALTIME_DEFAULT_SILENCE_DURATION_MS}, on every provider (contract set
55
+ * 6.0.0), never the provider's own default.
52
56
  */
53
57
  export const realtimeTurnDetectionSchema = z.discriminatedUnion('type', [
54
58
  z.object({ type: z.literal('none') }).strict(),
@@ -78,18 +82,22 @@ export const realtimeTurnDetectionSchema = z.discriminatedUnion('type', [
78
82
  *
79
83
  * In a `conversation` it is served only by a model whose catalogue entry says
80
84
  * so (`capabilities.realtime.inputAudioTranscription`, contract set 4.1.0),
81
- * and each transcribed turn arrives as `transcript.delta` / `transcript.done`
82
- * with `source: 'input_audio'`. What it costs is settled with the session:
83
- * where the provider bills the transcription apart from the session model, as
84
- * `input_transcription_milliseconds` (see `USAGE_UNITS`); where the session's
85
- * own price includes it, as nothing more.
86
- *
87
- * `language`, when given, is one of the model's published `audio.languages`.
85
+ * and each transcribed turn arrives as deltas that only append and EXACTLY
86
+ * ONE `transcript.done` with `source: 'input_audio'`, the final transcript of
87
+ * that item (contract set 6.0.0), whatever its provider sends. What it costs
88
+ * is settled with the session: where the provider bills the transcription
89
+ * apart from the session model, as `input_transcription_milliseconds` (see
90
+ * `USAGE_UNITS`); where the session's own price includes it, as nothing more.
88
91
  */
89
92
  export const realtimeInputTranscriptionSchema = z
90
93
  .object({
91
- /** A BCP 47 tag, when the caller knows the language. */
94
+ /**
95
+ * The client's own BCP 47 tag, when it knows the language. Kaana sends
96
+ * the provider its spelling of that language, or none for the model to
97
+ * detect; it is never refused.
98
+ */
92
99
  language: z.string().min(2).max(35).optional(),
100
+ /** A hint — vocabulary or context — used where the model takes one. */
93
101
  prompt: z.string().max(4_096).optional(),
94
102
  })
95
103
  .strict();
@@ -598,6 +606,16 @@ export const realtimeOpenLimitsSchema = realtimeSessionLimitsSchema.partial().st
598
606
  * frame closes the connection before it is read.
599
607
  */
600
608
  export const MAX_REALTIME_OPEN_FRAME_BYTES = 1024 * 1024;
609
+ /**
610
+ * The silence, in milliseconds, after which `server_vad` ends a caller's turn
611
+ * when the session names none (contract set 6.0.0, Kaana ADR 0003). Kaana
612
+ * sends it to every provider, so a turn ends the same way whichever serves
613
+ * the session. Measured on x-ai/grok-voice-3.0 (2026-10-16): with xAI's own
614
+ * default a phrase with pauses of 0.56 s and 0.79 s was cut into three
615
+ * responses, two cancelled, the model speaking before the phrase ended; at
616
+ * 500 ms it was one response, answered 490–576 ms after the phrase.
617
+ */
618
+ export const REALTIME_DEFAULT_SILENCE_DURATION_MS = 500;
601
619
  /**
602
620
  * The first frame a client sends on `GET /v1/realtime?model=…` to OPEN a
603
621
  * session (a reconnection instead sends `session.resume`). One grant covers the
@@ -693,84 +711,6 @@ export function checkRealtimeSessionOpen(open, model) {
693
711
  message: 'this model does not transcribe its input inside a conversation',
694
712
  });
695
713
  }
696
- if (transcription?.language !== undefined &&
697
- audio !== undefined &&
698
- !audio.languages.includes(transcription.language)) {
699
- issues.push({
700
- param: 'config.inputAudioTranscription.language',
701
- message: `this model does not declare the language ${transcription.language}` +
702
- (audio.detectsLanguage === true ? '; omit it to let the model detect the language' : ''),
703
- });
704
- }
705
- if (realtime.parameters !== undefined) {
706
- issues.push(...realtimeParameterIssues('config', config, realtime.parameters));
707
- }
708
- return issues;
709
- }
710
- function toolChoiceKind(choice) {
711
- return typeof choice === 'string' ? choice : 'function';
712
- }
713
- function sameModalities(a, b) {
714
- const left = [...a].sort();
715
- const right = [...b].sort();
716
- return left.length === right.length && left.every((value, index) => value === right[index]);
717
- }
718
- /**
719
- * Every field that `parameters` do not serve, each with the `param` Kaana's
720
- * refusal names (`prefix` is `config` for an open or a `session.update`,
721
- * `response` for a `response.create`), in the order Kaana checks them. It is
722
- * exactly Kaana's own check (Go's `RealtimeParameters.Issues`, held to the
723
- * same vectors), so a client that builds its session from a model's
724
- * parameters, or filters models with this, is never refused for one.
725
- */
726
- export function realtimeParameterIssues(prefix, fields, parameters) {
727
- const issues = [];
728
- const issue = (param, message) => issues.push({ param: `${prefix}.${param}`, message });
729
- if (fields.outputModalities !== undefined &&
730
- !parameters.outputModalities.some((set) => sameModalities(set, fields.outputModalities ?? []))) {
731
- issue('outputModalities', `this model produces ${parameters.outputModalities.map((set) => `[${set.join(' ')}]`).join(' or ')} in one response`);
732
- }
733
- const detection = fields.turnDetection;
734
- if (detection !== undefined) {
735
- const served = parameters.turnDetection.find((candidate) => candidate.type === detection.type);
736
- if (served === undefined) {
737
- issue('turnDetection', `this model has no ${detection.type} turn detection`);
738
- }
739
- else {
740
- if (served.fixedResponses && detection.type !== 'none') {
741
- if (!detection.createResponse) {
742
- issue('turnDetection.createResponse', `this model's ${detection.type} always answers the turn it detected; createResponse must be true`);
743
- }
744
- if (!detection.interruptResponse) {
745
- issue('turnDetection.interruptResponse', `this model's ${detection.type} lets the caller's speech interrupt an answer; interruptResponse must be true`);
746
- }
747
- }
748
- if (detection.type === 'server_vad') {
749
- const threshold = served.threshold;
750
- if (threshold !== undefined &&
751
- detection.threshold !== undefined &&
752
- (detection.threshold < threshold.min || detection.threshold > threshold.max)) {
753
- issue('turnDetection.threshold', `this model's ${detection.type} threshold is ${threshold.min} to ${threshold.max}`);
754
- }
755
- }
756
- }
757
- }
758
- if (fields.inputAudioTranscription?.prompt !== undefined &&
759
- !parameters.inputTranscriptionPrompt) {
760
- issue('inputAudioTranscription.prompt', "this model's input transcription takes no prompt");
761
- }
762
- if (fields.toolChoice !== undefined &&
763
- !parameters.toolChoice.includes(toolChoiceKind(fields.toolChoice))) {
764
- issue('toolChoice', `this model serves the tool choices ${parameters.toolChoice.join(', ')}`);
765
- }
766
- if (fields.maxOutputTokens !== undefined) {
767
- if (parameters.maxOutputTokens === undefined) {
768
- issue('maxOutputTokens', 'this model has no output token cap');
769
- }
770
- else if (fields.maxOutputTokens > parameters.maxOutputTokens) {
771
- issue('maxOutputTokens', `this model caps a response at most at ${parameters.maxOutputTokens} output tokens`);
772
- }
773
- }
774
714
  return issues;
775
715
  }
776
716
  /* -------------------------------------------------------------------------- */
@@ -118,8 +118,8 @@ export declare const responsesRequestSchema: z.ZodObject<{
118
118
  strict: z.ZodOptional<z.ZodBoolean>;
119
119
  }, z.core.$strict>>>;
120
120
  toolChoice: z.ZodOptional<z.ZodUnion<readonly [z.ZodEnum<{
121
- none: "none";
122
121
  auto: "auto";
122
+ none: "none";
123
123
  required: "required";
124
124
  }>, z.ZodObject<{
125
125
  type: z.ZodLiteral<"function">;
@@ -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 = "5.0.0";
103
+ export declare const INFERENCE_CONTRACT_VERSION = "6.0.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:
@@ -155,6 +155,21 @@ export declare const INFERENCE_CONTRACT_VERSION = "5.0.0";
155
155
  * `MAX_REALTIME_TEXT_ITEMS`, and a transcription's `timestamps`, `segments`
156
156
  * and `words`. A request that parsed under 4.5.0 and that Kaana served
157
157
  * still parses and is served the same.
158
+ *
159
+ * Contract set 6.0.0 (Kaana ADR 0003) is one canonical API: no provider's
160
+ * variant reaches a client. Kaana translates or emulates every value the
161
+ * contract offers on every model, so the catalogue publishes product
162
+ * capabilities only. MAJOR because it REMOVES what 5.0.0 published of each
163
+ * provider's wire: `capabilities.realtime.parameters`
164
+ * (`realtimeParametersSchema`, `realtimeTurnDetectionParametersSchema`,
165
+ * `numberRangeSchema`, `realtimeToolChoiceKindSchema`),
166
+ * `realtimeParameterIssues`, `audio.detectsLanguage` and
167
+ * `audio.transcriptionPrompt`; and `checkTranscriptionRequest` takes the
168
+ * upload's media type alone, since a language or a prompt is never refused.
169
+ * Additive: a model's `pricePerMinute`, exactly one input `transcript.done`
170
+ * per item, and `REALTIME_DEFAULT_SILENCE_DURATION_MS`, the silence a
171
+ * `server_vad` that names none waits on every provider. A client on 5.0.0
172
+ * parses every 6.0.0 response.
158
173
  */
159
174
  /** The public API's one origin and version. */
160
175
  export declare const KAANA_API_BASE_URL = "https://kaana.ai/v1";
@@ -163,9 +178,8 @@ export declare const KAANA_REQUEST_ID_HEADER = "Kaana-Request-Id";
163
178
  /**
164
179
  * The header that carries {@link INFERENCE_CONTRACT_VERSION}: on every
165
180
  * response, the set Kaana serves; on a request (`@kaana.ai/sdk` 2.0.0 and
166
- * later), the set the client parses. The catalogue's leaves are strict, so
167
- * Kaana renders `GET /v1/models` in the shape of the client's set: a client
168
- * that states none is served the 4.x shape, without what set 5.0.0 added.
181
+ * later), the set the client parses. Every set since 4.0.0 parses the
182
+ * catalogue Kaana serves.
169
183
  */
170
184
  export declare const KAANA_CONTRACT_VERSION_HEADER = "Kaana-Contract-Version";
171
185
  /**
@@ -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 = '5.0.0';
103
+ export const INFERENCE_CONTRACT_VERSION = '6.0.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:
@@ -155,6 +155,21 @@ export const INFERENCE_CONTRACT_VERSION = '5.0.0';
155
155
  * `MAX_REALTIME_TEXT_ITEMS`, and a transcription's `timestamps`, `segments`
156
156
  * and `words`. A request that parsed under 4.5.0 and that Kaana served
157
157
  * still parses and is served the same.
158
+ *
159
+ * Contract set 6.0.0 (Kaana ADR 0003) is one canonical API: no provider's
160
+ * variant reaches a client. Kaana translates or emulates every value the
161
+ * contract offers on every model, so the catalogue publishes product
162
+ * capabilities only. MAJOR because it REMOVES what 5.0.0 published of each
163
+ * provider's wire: `capabilities.realtime.parameters`
164
+ * (`realtimeParametersSchema`, `realtimeTurnDetectionParametersSchema`,
165
+ * `numberRangeSchema`, `realtimeToolChoiceKindSchema`),
166
+ * `realtimeParameterIssues`, `audio.detectsLanguage` and
167
+ * `audio.transcriptionPrompt`; and `checkTranscriptionRequest` takes the
168
+ * upload's media type alone, since a language or a prompt is never refused.
169
+ * Additive: a model's `pricePerMinute`, exactly one input `transcript.done`
170
+ * per item, and `REALTIME_DEFAULT_SILENCE_DURATION_MS`, the silence a
171
+ * `server_vad` that names none waits on every provider. A client on 5.0.0
172
+ * parses every 6.0.0 response.
158
173
  */
159
174
  /** The public API's one origin and version. */
160
175
  export const KAANA_API_BASE_URL = 'https://kaana.ai/v1';
@@ -163,9 +178,8 @@ export const KAANA_REQUEST_ID_HEADER = 'Kaana-Request-Id';
163
178
  /**
164
179
  * The header that carries {@link INFERENCE_CONTRACT_VERSION}: on every
165
180
  * response, the set Kaana serves; on a request (`@kaana.ai/sdk` 2.0.0 and
166
- * later), the set the client parses. The catalogue's leaves are strict, so
167
- * Kaana renders `GET /v1/models` in the shape of the client's set: a client
168
- * that states none is served the 4.x shape, without what set 5.0.0 added.
181
+ * later), the set the client parses. Every set since 4.0.0 parses the
182
+ * catalogue Kaana serves.
169
183
  */
170
184
  export const KAANA_CONTRACT_VERSION_HEADER = 'Kaana-Contract-Version';
171
185
  /**