@kaana.ai/contracts 5.0.0 → 6.1.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.
- package/dist/internal/catalogue.d.ts +8 -180
- package/dist/internal/realtime.d.ts +8 -8
- package/dist/internal/request.d.ts +11 -11
- package/dist/public/audio.d.ts +9 -13
- package/dist/public/audio.js +15 -28
- package/dist/public/audioFormats.d.ts +2 -13
- package/dist/public/audioFormats.js +2 -9
- package/dist/public/catalogue.d.ts +13 -310
- package/dist/public/catalogue.js +15 -78
- package/dist/public/chatCompletions.d.ts +1 -1
- package/dist/public/messages.d.ts +1 -1
- package/dist/public/realtime.d.ts +53 -53
- package/dist/public/realtime.js +40 -88
- package/dist/public/responses.d.ts +1 -1
- package/dist/public/version.d.ts +18 -4
- package/dist/public/version.js +18 -4
- package/openapi.json +4 -116
- package/package.json +1 -1
|
@@ -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,
|
|
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
|
|
@@ -24,6 +23,13 @@ export declare const MAX_REALTIME_SESSION_DURATION_MS = 3600000;
|
|
|
24
23
|
export declare const MAX_REALTIME_SESSION_AUDIO_BYTES = 172800000;
|
|
25
24
|
/** The longest a dropped connection may be resumed after: one minute. */
|
|
26
25
|
export declare const MAX_REALTIME_RESUME_WINDOW_MS = 60000;
|
|
26
|
+
/**
|
|
27
|
+
* The most characters (UTF-16 code units, a JavaScript string's `length`) the
|
|
28
|
+
* text of one conversation item may hold: an `input_text` part, or a
|
|
29
|
+
* `function_call_output`'s `output`. A client that bounds a tool's result
|
|
30
|
+
* reads it here, never copies it.
|
|
31
|
+
*/
|
|
32
|
+
export declare const MAX_REALTIME_ITEM_TEXT_CHARS = 1048576;
|
|
27
33
|
/** A client-chosen command identity, unique within one session. */
|
|
28
34
|
export declare const realtimeCommandIdSchema: z.ZodString;
|
|
29
35
|
/** A conversation item's identity within one session. */
|
|
@@ -38,6 +44,10 @@ export declare const realtimeResponseIdSchema: z.ZodString;
|
|
|
38
44
|
* them: whether the model answers on its own, and whether new speech cuts it
|
|
39
45
|
* off, are the two behaviours a caller most needs to have chosen, and a default
|
|
40
46
|
* would choose them silently — and differently per provider.
|
|
47
|
+
*
|
|
48
|
+
* A `server_vad` that names no `silenceDurationMs` waits Kaana's
|
|
49
|
+
* {@link REALTIME_DEFAULT_SILENCE_DURATION_MS}, on every provider (contract set
|
|
50
|
+
* 6.0.0), never the provider's own default.
|
|
41
51
|
*/
|
|
42
52
|
export declare const realtimeTurnDetectionSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
43
53
|
type: z.ZodLiteral<"none">;
|
|
@@ -66,13 +76,15 @@ export declare const realtimeTurnDetectionSchema: z.ZodDiscriminatedUnion<[z.Zod
|
|
|
66
76
|
*
|
|
67
77
|
* In a `conversation` it is served only by a model whose catalogue entry says
|
|
68
78
|
* so (`capabilities.realtime.inputAudioTranscription`, contract set 4.1.0),
|
|
69
|
-
* and each transcribed turn arrives as
|
|
70
|
-
* with `source: 'input_audio'
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
79
|
+
* and each transcribed turn arrives as deltas that only append and EXACTLY
|
|
80
|
+
* ONE `transcript.done` with `source: 'input_audio'`, the final transcript of
|
|
81
|
+
* that item (contract set 6.0.0), whatever its provider sends. Both hold only
|
|
82
|
+
* the words of that item's own audio, never an earlier item's
|
|
83
|
+
* (`@kaana.ai/contracts` 6.1.0), even where the provider transcribes a turn
|
|
84
|
+
* the caller went on with as one text. What it costs is settled with the
|
|
85
|
+
* session: where the provider bills the transcription
|
|
86
|
+
* apart from the session model, as `input_transcription_milliseconds` (see
|
|
87
|
+
* `USAGE_UNITS`); where the session's own price includes it, as nothing more.
|
|
76
88
|
*/
|
|
77
89
|
export declare const realtimeInputTranscriptionSchema: z.ZodObject<{
|
|
78
90
|
language: z.ZodOptional<z.ZodString>;
|
|
@@ -89,8 +101,8 @@ export declare const realtimeTranslationSchema: z.ZodObject<{
|
|
|
89
101
|
export declare const realtimeToolDefinitionSchema: z.ZodObject<{
|
|
90
102
|
type: z.ZodLiteral<"function">;
|
|
91
103
|
name: z.ZodString;
|
|
92
|
-
parameters: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
93
104
|
description: z.ZodOptional<z.ZodString>;
|
|
105
|
+
parameters: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
94
106
|
}, z.core.$strict>;
|
|
95
107
|
/**
|
|
96
108
|
* A session's full configuration, as signed at open and as echoed back by
|
|
@@ -148,12 +160,12 @@ export declare const realtimeSessionConfigSchema: z.ZodObject<{
|
|
|
148
160
|
tools: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
149
161
|
type: z.ZodLiteral<"function">;
|
|
150
162
|
name: z.ZodString;
|
|
151
|
-
parameters: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
152
163
|
description: z.ZodOptional<z.ZodString>;
|
|
164
|
+
parameters: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
153
165
|
}, z.core.$strict>>>;
|
|
154
166
|
toolChoice: z.ZodOptional<z.ZodUnion<readonly [z.ZodEnum<{
|
|
155
|
-
none: "none";
|
|
156
167
|
auto: "auto";
|
|
168
|
+
none: "none";
|
|
157
169
|
required: "required";
|
|
158
170
|
}>, z.ZodObject<{
|
|
159
171
|
type: z.ZodLiteral<"function">;
|
|
@@ -202,12 +214,12 @@ export declare const realtimeSessionConfigUpdateSchema: z.ZodObject<{
|
|
|
202
214
|
tools: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
203
215
|
type: z.ZodLiteral<"function">;
|
|
204
216
|
name: z.ZodString;
|
|
205
|
-
parameters: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
206
217
|
description: z.ZodOptional<z.ZodString>;
|
|
218
|
+
parameters: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
207
219
|
}, z.core.$strict>>>;
|
|
208
220
|
toolChoice: z.ZodOptional<z.ZodUnion<readonly [z.ZodEnum<{
|
|
209
|
-
none: "none";
|
|
210
221
|
auto: "auto";
|
|
222
|
+
none: "none";
|
|
211
223
|
required: "required";
|
|
212
224
|
}>, z.ZodObject<{
|
|
213
225
|
type: z.ZodLiteral<"function">;
|
|
@@ -318,8 +330,8 @@ export declare const realtimeResponseParametersSchema: z.ZodObject<{
|
|
|
318
330
|
}>>>;
|
|
319
331
|
maxOutputTokens: z.ZodOptional<z.ZodNumber>;
|
|
320
332
|
toolChoice: z.ZodOptional<z.ZodUnion<readonly [z.ZodEnum<{
|
|
321
|
-
none: "none";
|
|
322
333
|
auto: "auto";
|
|
334
|
+
none: "none";
|
|
323
335
|
required: "required";
|
|
324
336
|
}>, z.ZodObject<{
|
|
325
337
|
type: z.ZodLiteral<"function">;
|
|
@@ -361,12 +373,12 @@ export declare const realtimeSessionUpdateCommandSchema: z.ZodObject<{
|
|
|
361
373
|
tools: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
362
374
|
type: z.ZodLiteral<"function">;
|
|
363
375
|
name: z.ZodString;
|
|
364
|
-
parameters: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
365
376
|
description: z.ZodOptional<z.ZodString>;
|
|
377
|
+
parameters: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
366
378
|
}, z.core.$strict>>>;
|
|
367
379
|
toolChoice: z.ZodOptional<z.ZodUnion<readonly [z.ZodEnum<{
|
|
368
|
-
none: "none";
|
|
369
380
|
auto: "auto";
|
|
381
|
+
none: "none";
|
|
370
382
|
required: "required";
|
|
371
383
|
}>, z.ZodObject<{
|
|
372
384
|
type: z.ZodLiteral<"function">;
|
|
@@ -479,8 +491,8 @@ export declare const realtimeResponseCreateCommandSchema: z.ZodObject<{
|
|
|
479
491
|
}>>>;
|
|
480
492
|
maxOutputTokens: z.ZodOptional<z.ZodNumber>;
|
|
481
493
|
toolChoice: z.ZodOptional<z.ZodUnion<readonly [z.ZodEnum<{
|
|
482
|
-
none: "none";
|
|
483
494
|
auto: "auto";
|
|
495
|
+
none: "none";
|
|
484
496
|
required: "required";
|
|
485
497
|
}>, z.ZodObject<{
|
|
486
498
|
type: z.ZodLiteral<"function">;
|
|
@@ -551,12 +563,12 @@ export declare const realtimeClientCommandSchema: z.ZodDiscriminatedUnion<[z.Zod
|
|
|
551
563
|
tools: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
552
564
|
type: z.ZodLiteral<"function">;
|
|
553
565
|
name: z.ZodString;
|
|
554
|
-
parameters: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
555
566
|
description: z.ZodOptional<z.ZodString>;
|
|
567
|
+
parameters: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
556
568
|
}, z.core.$strict>>>;
|
|
557
569
|
toolChoice: z.ZodOptional<z.ZodUnion<readonly [z.ZodEnum<{
|
|
558
|
-
none: "none";
|
|
559
570
|
auto: "auto";
|
|
571
|
+
none: "none";
|
|
560
572
|
required: "required";
|
|
561
573
|
}>, z.ZodObject<{
|
|
562
574
|
type: z.ZodLiteral<"function">;
|
|
@@ -657,8 +669,8 @@ export declare const realtimeClientCommandSchema: z.ZodDiscriminatedUnion<[z.Zod
|
|
|
657
669
|
}>>>;
|
|
658
670
|
maxOutputTokens: z.ZodOptional<z.ZodNumber>;
|
|
659
671
|
toolChoice: z.ZodOptional<z.ZodUnion<readonly [z.ZodEnum<{
|
|
660
|
-
none: "none";
|
|
661
672
|
auto: "auto";
|
|
673
|
+
none: "none";
|
|
662
674
|
required: "required";
|
|
663
675
|
}>, z.ZodObject<{
|
|
664
676
|
type: z.ZodLiteral<"function">;
|
|
@@ -735,12 +747,12 @@ export declare const realtimeSessionUpdatedEventSchema: z.ZodObject<{
|
|
|
735
747
|
tools: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
736
748
|
type: z.ZodLiteral<"function">;
|
|
737
749
|
name: z.ZodString;
|
|
738
|
-
parameters: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
739
750
|
description: z.ZodOptional<z.ZodString>;
|
|
751
|
+
parameters: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
740
752
|
}, z.core.$strict>>>;
|
|
741
753
|
toolChoice: z.ZodOptional<z.ZodUnion<readonly [z.ZodEnum<{
|
|
742
|
-
none: "none";
|
|
743
754
|
auto: "auto";
|
|
755
|
+
none: "none";
|
|
744
756
|
required: "required";
|
|
745
757
|
}>, z.ZodObject<{
|
|
746
758
|
type: z.ZodLiteral<"function">;
|
|
@@ -1079,6 +1091,16 @@ export declare const realtimeOpenLimitsSchema: z.ZodObject<{
|
|
|
1079
1091
|
* frame closes the connection before it is read.
|
|
1080
1092
|
*/
|
|
1081
1093
|
export declare const MAX_REALTIME_OPEN_FRAME_BYTES: number;
|
|
1094
|
+
/**
|
|
1095
|
+
* The silence, in milliseconds, after which `server_vad` ends a caller's turn
|
|
1096
|
+
* when the session names none (contract set 6.0.0, Kaana ADR 0003). Kaana
|
|
1097
|
+
* sends it to every provider, so a turn ends the same way whichever serves
|
|
1098
|
+
* the session. Measured on x-ai/grok-voice-3.0 (2026-10-16): with xAI's own
|
|
1099
|
+
* default a phrase with pauses of 0.56 s and 0.79 s was cut into three
|
|
1100
|
+
* responses, two cancelled, the model speaking before the phrase ended; at
|
|
1101
|
+
* 500 ms it was one response, answered 490–576 ms after the phrase.
|
|
1102
|
+
*/
|
|
1103
|
+
export declare const REALTIME_DEFAULT_SILENCE_DURATION_MS = 500;
|
|
1082
1104
|
/**
|
|
1083
1105
|
* The first frame a client sends on `GET /v1/realtime?model=…` to OPEN a
|
|
1084
1106
|
* session (a reconnection instead sends `session.resume`). One grant covers the
|
|
@@ -1143,12 +1165,12 @@ export declare const realtimeSessionOpenSchema: z.ZodObject<{
|
|
|
1143
1165
|
tools: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
1144
1166
|
type: z.ZodLiteral<"function">;
|
|
1145
1167
|
name: z.ZodString;
|
|
1146
|
-
parameters: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
1147
1168
|
description: z.ZodOptional<z.ZodString>;
|
|
1169
|
+
parameters: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
1148
1170
|
}, z.core.$strict>>>;
|
|
1149
1171
|
toolChoice: z.ZodOptional<z.ZodUnion<readonly [z.ZodEnum<{
|
|
1150
|
-
none: "none";
|
|
1151
1172
|
auto: "auto";
|
|
1173
|
+
none: "none";
|
|
1152
1174
|
required: "required";
|
|
1153
1175
|
}>, z.ZodObject<{
|
|
1154
1176
|
type: z.ZodLiteral<"function">;
|
|
@@ -1192,28 +1214,6 @@ export declare function checkRealtimeSessionOpen(open: z.infer<typeof realtimeSe
|
|
|
1192
1214
|
readonly capabilities: ModelCapabilities;
|
|
1193
1215
|
readonly audio?: ModelAudioCapabilities;
|
|
1194
1216
|
}): 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
1217
|
/**
|
|
1218
1218
|
* The session opened: the revision-pinned model, fixed for the rest of the
|
|
1219
1219
|
* session, and the effective configuration and limits. The signed lane's
|
|
@@ -1275,12 +1275,12 @@ export declare const realtimePublicSessionCreatedEventSchema: z.ZodObject<{
|
|
|
1275
1275
|
tools: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
1276
1276
|
type: z.ZodLiteral<"function">;
|
|
1277
1277
|
name: z.ZodString;
|
|
1278
|
-
parameters: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
1279
1278
|
description: z.ZodOptional<z.ZodString>;
|
|
1279
|
+
parameters: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
1280
1280
|
}, z.core.$strict>>>;
|
|
1281
1281
|
toolChoice: z.ZodOptional<z.ZodUnion<readonly [z.ZodEnum<{
|
|
1282
|
-
none: "none";
|
|
1283
1282
|
auto: "auto";
|
|
1283
|
+
none: "none";
|
|
1284
1284
|
required: "required";
|
|
1285
1285
|
}>, z.ZodObject<{
|
|
1286
1286
|
type: z.ZodLiteral<"function">;
|
|
@@ -1512,12 +1512,12 @@ export declare const realtimePublicServerEventSchema: z.ZodDiscriminatedUnion<[z
|
|
|
1512
1512
|
tools: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
1513
1513
|
type: z.ZodLiteral<"function">;
|
|
1514
1514
|
name: z.ZodString;
|
|
1515
|
-
parameters: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
1516
1515
|
description: z.ZodOptional<z.ZodString>;
|
|
1516
|
+
parameters: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
1517
1517
|
}, z.core.$strict>>>;
|
|
1518
1518
|
toolChoice: z.ZodOptional<z.ZodUnion<readonly [z.ZodEnum<{
|
|
1519
|
-
none: "none";
|
|
1520
1519
|
auto: "auto";
|
|
1520
|
+
none: "none";
|
|
1521
1521
|
required: "required";
|
|
1522
1522
|
}>, z.ZodObject<{
|
|
1523
1523
|
type: z.ZodLiteral<"function">;
|
|
@@ -1588,12 +1588,12 @@ export declare const realtimePublicServerEventSchema: z.ZodDiscriminatedUnion<[z
|
|
|
1588
1588
|
tools: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
1589
1589
|
type: z.ZodLiteral<"function">;
|
|
1590
1590
|
name: z.ZodString;
|
|
1591
|
-
parameters: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
1592
1591
|
description: z.ZodOptional<z.ZodString>;
|
|
1592
|
+
parameters: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
1593
1593
|
}, z.core.$strict>>>;
|
|
1594
1594
|
toolChoice: z.ZodOptional<z.ZodUnion<readonly [z.ZodEnum<{
|
|
1595
|
-
none: "none";
|
|
1596
1595
|
auto: "auto";
|
|
1596
|
+
none: "none";
|
|
1597
1597
|
required: "required";
|
|
1598
1598
|
}>, z.ZodObject<{
|
|
1599
1599
|
type: z.ZodLiteral<"function">;
|
package/dist/public/realtime.js
CHANGED
|
@@ -28,6 +28,13 @@ export const MAX_REALTIME_SESSION_DURATION_MS = 3_600_000;
|
|
|
28
28
|
export const MAX_REALTIME_SESSION_AUDIO_BYTES = 172_800_000;
|
|
29
29
|
/** The longest a dropped connection may be resumed after: one minute. */
|
|
30
30
|
export const MAX_REALTIME_RESUME_WINDOW_MS = 60_000;
|
|
31
|
+
/**
|
|
32
|
+
* The most characters (UTF-16 code units, a JavaScript string's `length`) the
|
|
33
|
+
* text of one conversation item may hold: an `input_text` part, or a
|
|
34
|
+
* `function_call_output`'s `output`. A client that bounds a tool's result
|
|
35
|
+
* reads it here, never copies it.
|
|
36
|
+
*/
|
|
37
|
+
export const MAX_REALTIME_ITEM_TEXT_CHARS = 1_048_576;
|
|
31
38
|
/** A client-chosen command identity, unique within one session. */
|
|
32
39
|
export const realtimeCommandIdSchema = z.string().min(1).max(128);
|
|
33
40
|
/** A conversation item's identity within one session. */
|
|
@@ -49,6 +56,10 @@ const milliseconds = z.number().int().nonnegative().safe();
|
|
|
49
56
|
* them: whether the model answers on its own, and whether new speech cuts it
|
|
50
57
|
* off, are the two behaviours a caller most needs to have chosen, and a default
|
|
51
58
|
* would choose them silently — and differently per provider.
|
|
59
|
+
*
|
|
60
|
+
* A `server_vad` that names no `silenceDurationMs` waits Kaana's
|
|
61
|
+
* {@link REALTIME_DEFAULT_SILENCE_DURATION_MS}, on every provider (contract set
|
|
62
|
+
* 6.0.0), never the provider's own default.
|
|
52
63
|
*/
|
|
53
64
|
export const realtimeTurnDetectionSchema = z.discriminatedUnion('type', [
|
|
54
65
|
z.object({ type: z.literal('none') }).strict(),
|
|
@@ -78,18 +89,25 @@ export const realtimeTurnDetectionSchema = z.discriminatedUnion('type', [
|
|
|
78
89
|
*
|
|
79
90
|
* In a `conversation` it is served only by a model whose catalogue entry says
|
|
80
91
|
* so (`capabilities.realtime.inputAudioTranscription`, contract set 4.1.0),
|
|
81
|
-
* and each transcribed turn arrives as
|
|
82
|
-
* with `source: 'input_audio'
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
92
|
+
* and each transcribed turn arrives as deltas that only append and EXACTLY
|
|
93
|
+
* ONE `transcript.done` with `source: 'input_audio'`, the final transcript of
|
|
94
|
+
* that item (contract set 6.0.0), whatever its provider sends. Both hold only
|
|
95
|
+
* the words of that item's own audio, never an earlier item's
|
|
96
|
+
* (`@kaana.ai/contracts` 6.1.0), even where the provider transcribes a turn
|
|
97
|
+
* the caller went on with as one text. What it costs is settled with the
|
|
98
|
+
* session: where the provider bills the transcription
|
|
99
|
+
* apart from the session model, as `input_transcription_milliseconds` (see
|
|
100
|
+
* `USAGE_UNITS`); where the session's own price includes it, as nothing more.
|
|
88
101
|
*/
|
|
89
102
|
export const realtimeInputTranscriptionSchema = z
|
|
90
103
|
.object({
|
|
91
|
-
/**
|
|
104
|
+
/**
|
|
105
|
+
* The client's own BCP 47 tag, when it knows the language. Kaana sends
|
|
106
|
+
* the provider its spelling of that language, or none for the model to
|
|
107
|
+
* detect; it is never refused.
|
|
108
|
+
*/
|
|
92
109
|
language: z.string().min(2).max(35).optional(),
|
|
110
|
+
/** A hint — vocabulary or context — used where the model takes one. */
|
|
93
111
|
prompt: z.string().max(4_096).optional(),
|
|
94
112
|
})
|
|
95
113
|
.strict();
|
|
@@ -180,7 +198,9 @@ export const realtimeSessionLimitsSchema = z
|
|
|
180
198
|
* item echoing it carries only the format and, once known, the transcript.
|
|
181
199
|
*/
|
|
182
200
|
export const realtimeContentPartSchema = z.discriminatedUnion('type', [
|
|
183
|
-
z
|
|
201
|
+
z
|
|
202
|
+
.object({ type: z.literal('input_text'), text: z.string().max(MAX_REALTIME_ITEM_TEXT_CHARS) })
|
|
203
|
+
.strict(),
|
|
184
204
|
z
|
|
185
205
|
.object({
|
|
186
206
|
type: z.literal('input_audio'),
|
|
@@ -229,7 +249,7 @@ export const realtimeConversationItemSchema = z
|
|
|
229
249
|
type: z.literal('function_call_output'),
|
|
230
250
|
itemId: realtimeItemIdSchema.optional(),
|
|
231
251
|
callId: z.string().min(1).max(128),
|
|
232
|
-
output: z.string().max(
|
|
252
|
+
output: z.string().max(MAX_REALTIME_ITEM_TEXT_CHARS),
|
|
233
253
|
})
|
|
234
254
|
.strict(),
|
|
235
255
|
])
|
|
@@ -598,6 +618,16 @@ export const realtimeOpenLimitsSchema = realtimeSessionLimitsSchema.partial().st
|
|
|
598
618
|
* frame closes the connection before it is read.
|
|
599
619
|
*/
|
|
600
620
|
export const MAX_REALTIME_OPEN_FRAME_BYTES = 1024 * 1024;
|
|
621
|
+
/**
|
|
622
|
+
* The silence, in milliseconds, after which `server_vad` ends a caller's turn
|
|
623
|
+
* when the session names none (contract set 6.0.0, Kaana ADR 0003). Kaana
|
|
624
|
+
* sends it to every provider, so a turn ends the same way whichever serves
|
|
625
|
+
* the session. Measured on x-ai/grok-voice-3.0 (2026-10-16): with xAI's own
|
|
626
|
+
* default a phrase with pauses of 0.56 s and 0.79 s was cut into three
|
|
627
|
+
* responses, two cancelled, the model speaking before the phrase ended; at
|
|
628
|
+
* 500 ms it was one response, answered 490–576 ms after the phrase.
|
|
629
|
+
*/
|
|
630
|
+
export const REALTIME_DEFAULT_SILENCE_DURATION_MS = 500;
|
|
601
631
|
/**
|
|
602
632
|
* The first frame a client sends on `GET /v1/realtime?model=…` to OPEN a
|
|
603
633
|
* session (a reconnection instead sends `session.resume`). One grant covers the
|
|
@@ -693,84 +723,6 @@ export function checkRealtimeSessionOpen(open, model) {
|
|
|
693
723
|
message: 'this model does not transcribe its input inside a conversation',
|
|
694
724
|
});
|
|
695
725
|
}
|
|
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
726
|
return issues;
|
|
775
727
|
}
|
|
776
728
|
/* -------------------------------------------------------------------------- */
|
|
@@ -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">;
|
package/dist/public/version.d.ts
CHANGED
|
@@ -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 = "
|
|
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.
|
|
167
|
-
* Kaana
|
|
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
|
/**
|
package/dist/public/version.js
CHANGED
|
@@ -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 = '
|
|
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.
|
|
167
|
-
* Kaana
|
|
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
|
/**
|