@kaana.ai/contracts 8.0.0 → 8.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.
@@ -5,6 +5,7 @@
5
5
  * Moved from `@oxy.so/contracts` 4.12.0 (`src/inference/request.ts`) by Kaana ADR 0002.
6
6
  */
7
7
  import { z } from 'zod';
8
+ import { maxUtf16Length, minUtf16Length } from '../stringBounds.js';
8
9
  import { languageTagSchema } from './audioFormats.js';
9
10
  import { reasoningEffortSchema } from './catalogue.js';
10
11
  /**
@@ -15,12 +16,17 @@ import { reasoningEffortSchema } from './catalogue.js';
15
16
  * neither appears in a receipt, a log line or a telemetry event.
16
17
  */
17
18
  export const inferenceContentSourceSchema = z.discriminatedUnion('kind', [
18
- z.object({ kind: z.literal('url'), url: z.string().min(1).max(4096) }).strict(),
19
+ z
20
+ .object({
21
+ kind: z.literal('url'),
22
+ url: z.string().check(minUtf16Length(1)).check(maxUtf16Length(4096)),
23
+ })
24
+ .strict(),
19
25
  z
20
26
  .object({
21
27
  kind: z.literal('inline'),
22
- mediaType: z.string().min(1).max(255),
23
- data: z.string().min(1),
28
+ mediaType: z.string().check(minUtf16Length(1)).check(maxUtf16Length(255)),
29
+ data: z.string().check(minUtf16Length(1)),
24
30
  })
25
31
  .strict(),
26
32
  ]);
@@ -71,7 +77,7 @@ export const inferenceContentPartSchema = z.discriminatedUnion('type', [
71
77
  .object({
72
78
  type: z.literal('file'),
73
79
  source: inferenceContentSourceSchema,
74
- filename: z.string().max(255).optional(),
80
+ filename: z.string().check(maxUtf16Length(255)).optional(),
75
81
  })
76
82
  .strict(),
77
83
  /**
@@ -89,8 +95,8 @@ export const inferenceContentPartSchema = z.discriminatedUnion('type', [
89
95
  */
90
96
  export const inferenceToolCallSchema = z
91
97
  .object({
92
- id: z.string().min(1).max(128),
93
- name: z.string().min(1).max(128),
98
+ id: z.string().check(minUtf16Length(1)).check(maxUtf16Length(128)),
99
+ name: z.string().check(minUtf16Length(1)).check(maxUtf16Length(128)),
94
100
  arguments: z.string(),
95
101
  })
96
102
  .strict();
@@ -114,9 +120,9 @@ export const inferenceMessageSchema = z
114
120
  role: inferenceMessageRoleSchema,
115
121
  content: z.array(inferenceContentPartSchema),
116
122
  /** Participant name, where the dialect supports naming participants. */
117
- name: z.string().max(128).optional(),
123
+ name: z.string().check(maxUtf16Length(128)).optional(),
118
124
  /** The tool call this message answers. Required on, and only on, `tool`. */
119
- toolCallId: z.string().min(1).max(128).optional(),
125
+ toolCallId: z.string().check(minUtf16Length(1)).check(maxUtf16Length(128)).optional(),
120
126
  /** Tool calls the assistant made. Only on `assistant`. */
121
127
  toolCalls: z.array(inferenceToolCallSchema).optional(),
122
128
  })
@@ -168,7 +174,10 @@ export const samplingParametersSchema = z
168
174
  presencePenalty: z.number().min(-2).max(2).optional(),
169
175
  /** A seed makes a request reproducible on providers that honour one. */
170
176
  seed: z.number().int().safe().optional(),
171
- stopSequences: z.array(z.string().min(1).max(256)).max(8).optional(),
177
+ stopSequences: z
178
+ .array(z.string().check(minUtf16Length(1)).check(maxUtf16Length(256)))
179
+ .max(8)
180
+ .optional(),
172
181
  })
173
182
  .strict();
174
183
  /**
@@ -179,8 +188,8 @@ export const samplingParametersSchema = z
179
188
  export const toolDefinitionSchema = z
180
189
  .object({
181
190
  type: z.literal('function'),
182
- name: z.string().min(1).max(128),
183
- description: z.string().max(2000).optional(),
191
+ name: z.string().check(minUtf16Length(1)).check(maxUtf16Length(128)),
192
+ description: z.string().check(maxUtf16Length(2000)).optional(),
184
193
  parameters: z.record(z.string(), z.unknown()),
185
194
  /** Ask the provider to enforce the schema, where it supports enforcement. */
186
195
  strict: z.boolean().optional(),
@@ -189,7 +198,12 @@ export const toolDefinitionSchema = z
189
198
  /** Whether, and which, tool the model must call. */
190
199
  export const toolChoiceSchema = z.union([
191
200
  z.enum(['auto', 'none', 'required']),
192
- z.object({ type: z.literal('function'), name: z.string().min(1).max(128) }).strict(),
201
+ z
202
+ .object({
203
+ type: z.literal('function'),
204
+ name: z.string().check(minUtf16Length(1)).check(maxUtf16Length(128)),
205
+ })
206
+ .strict(),
193
207
  ]);
194
208
  /** Structured-output request: free text, any JSON object, or a named schema. */
195
209
  export const responseFormatSchema = z.discriminatedUnion('type', [
@@ -198,7 +212,7 @@ export const responseFormatSchema = z.discriminatedUnion('type', [
198
212
  z
199
213
  .object({
200
214
  type: z.literal('json_schema'),
201
- name: z.string().min(1).max(128),
215
+ name: z.string().check(minUtf16Length(1)).check(maxUtf16Length(128)),
202
216
  schema: z.record(z.string(), z.unknown()),
203
217
  strict: z.boolean(),
204
218
  })
@@ -215,7 +229,7 @@ export const inferenceReasoningSchema = z.object({ effort: reasoningEffortSchema
215
229
  /** Parameters for text-to-speech, preserved in the signed request. */
216
230
  export const inferenceSpeechParametersSchema = z
217
231
  .object({
218
- voice: z.string().min(1).max(64),
232
+ voice: z.string().check(minUtf16Length(1)).check(maxUtf16Length(64)),
219
233
  responseFormat: z.enum(['mp3', 'opus', 'aac', 'flac', 'wav', 'pcm']),
220
234
  speed: z.number().min(0.25).max(4).optional(),
221
235
  })
@@ -231,7 +245,7 @@ export const inferenceTranscriptionParametersSchema = z
231
245
  .object({
232
246
  language: languageTagSchema.optional(),
233
247
  /** Vocabulary or context, never an instruction (contract set 5.0.0). */
234
- prompt: z.string().max(4096).optional(),
248
+ prompt: z.string().check(maxUtf16Length(4096)).optional(),
235
249
  })
236
250
  .strict();
237
251
  /**
@@ -249,7 +263,7 @@ export const inferenceTranscriptionParametersSchema = z
249
263
  */
250
264
  export const inferenceAudioOutputParametersSchema = z
251
265
  .object({
252
- voice: z.string().min(1).max(64),
266
+ voice: z.string().check(minUtf16Length(1)).check(maxUtf16Length(64)),
253
267
  format: z.enum(['wav', 'mp3', 'flac', 'opus', 'pcm']),
254
268
  })
255
269
  .strict();
@@ -262,5 +276,5 @@ export const inferenceAudioOutputParametersSchema = z
262
276
  * Moved from the Oxy edge (`packages/api/src/schemas/inferenceEdge.schemas.ts`).
263
277
  */
264
278
  export const requestLabelsSchema = z
265
- .record(z.string(), z.string().max(256))
279
+ .record(z.string(), z.string().check(maxUtf16Length(256)))
266
280
  .refine((labels) => Object.keys(labels).length <= 16, 'at most 16 labels may be attached to one request');
@@ -6,6 +6,7 @@
6
6
  * itself stays in `@oxy.so/contracts`, because Oxy owns the price lists.
7
7
  */
8
8
  import { z } from 'zod';
9
+ import { maxUtf16Length, minUtf16Length } from '../stringBounds.js';
9
10
  /** ISO 4217 alpha-3 currency code, e.g. `USD`. */
10
11
  export const currencyCodeSchema = z
11
12
  .string()
@@ -219,7 +220,7 @@ export const unitPriceSchema = z
219
220
  */
220
221
  export const priceSnapshotSchema = z
221
222
  .object({
222
- priceVersionId: z.string().min(1).max(128),
223
+ priceVersionId: z.string().check(minUtf16Length(1)).check(maxUtf16Length(128)),
223
224
  currency: currencyCodeSchema,
224
225
  unitPrices: z.array(unitPriceSchema).min(1),
225
226
  })
@@ -7,6 +7,7 @@
7
7
  * Moved from `@oxy.so/contracts` 4.12.0 (`src/inference/routingPolicy.ts`) by Kaana ADR 0002.
8
8
  */
9
9
  import { z } from 'zod';
10
+ import { maxUtf16Length, minUtf16Length } from '../stringBounds.js';
10
11
  /**
11
12
  * The reference a request records: which policy, at which of the customer's own
12
13
  * revisions. Embedded in the request envelope and in the settled receipt, so a
@@ -14,7 +15,7 @@ import { z } from 'zod';
14
15
  */
15
16
  export const routingPolicyReferenceSchema = z
16
17
  .object({
17
- routingPolicyId: z.string().min(1).max(128),
18
+ routingPolicyId: z.string().check(minUtf16Length(1)).check(maxUtf16Length(128)),
18
19
  policyVersion: z.number().int().positive().safe(),
19
20
  })
20
21
  .strict();
@@ -89,6 +89,7 @@ export declare const realtimeTurnDetectionSchema: z.ZodDiscriminatedUnion<[z.Zod
89
89
  export declare const realtimeInputTranscriptionSchema: z.ZodObject<{
90
90
  language: z.ZodOptional<z.ZodString>;
91
91
  prompt: z.ZodOptional<z.ZodString>;
92
+ interimResults: z.ZodOptional<z.ZodBoolean>;
92
93
  }, z.core.$strict>;
93
94
  /** The target of a `translation` session. */
94
95
  export declare const realtimeTranslationSchema: z.ZodObject<{
@@ -153,6 +154,7 @@ export declare const realtimeSessionConfigSchema: z.ZodObject<{
153
154
  inputAudioTranscription: z.ZodOptional<z.ZodObject<{
154
155
  language: z.ZodOptional<z.ZodString>;
155
156
  prompt: z.ZodOptional<z.ZodString>;
157
+ interimResults: z.ZodOptional<z.ZodBoolean>;
156
158
  }, z.core.$strict>>;
157
159
  translation: z.ZodOptional<z.ZodObject<{
158
160
  targetLanguage: z.ZodString;
@@ -210,6 +212,7 @@ export declare const realtimeSessionConfigUpdateSchema: z.ZodObject<{
210
212
  inputAudioTranscription: z.ZodOptional<z.ZodObject<{
211
213
  language: z.ZodOptional<z.ZodString>;
212
214
  prompt: z.ZodOptional<z.ZodString>;
215
+ interimResults: z.ZodOptional<z.ZodBoolean>;
213
216
  }, z.core.$strict>>;
214
217
  tools: z.ZodOptional<z.ZodArray<z.ZodObject<{
215
218
  type: z.ZodLiteral<"function">;
@@ -369,6 +372,7 @@ export declare const realtimeSessionUpdateCommandSchema: z.ZodObject<{
369
372
  inputAudioTranscription: z.ZodOptional<z.ZodObject<{
370
373
  language: z.ZodOptional<z.ZodString>;
371
374
  prompt: z.ZodOptional<z.ZodString>;
375
+ interimResults: z.ZodOptional<z.ZodBoolean>;
372
376
  }, z.core.$strict>>;
373
377
  tools: z.ZodOptional<z.ZodArray<z.ZodObject<{
374
378
  type: z.ZodLiteral<"function">;
@@ -559,6 +563,7 @@ export declare const realtimeClientCommandSchema: z.ZodDiscriminatedUnion<[z.Zod
559
563
  inputAudioTranscription: z.ZodOptional<z.ZodObject<{
560
564
  language: z.ZodOptional<z.ZodString>;
561
565
  prompt: z.ZodOptional<z.ZodString>;
566
+ interimResults: z.ZodOptional<z.ZodBoolean>;
562
567
  }, z.core.$strict>>;
563
568
  tools: z.ZodOptional<z.ZodArray<z.ZodObject<{
564
569
  type: z.ZodLiteral<"function">;
@@ -740,6 +745,7 @@ export declare const realtimeSessionUpdatedEventSchema: z.ZodObject<{
740
745
  inputAudioTranscription: z.ZodOptional<z.ZodObject<{
741
746
  language: z.ZodOptional<z.ZodString>;
742
747
  prompt: z.ZodOptional<z.ZodString>;
748
+ interimResults: z.ZodOptional<z.ZodBoolean>;
743
749
  }, z.core.$strict>>;
744
750
  translation: z.ZodOptional<z.ZodObject<{
745
751
  targetLanguage: z.ZodString;
@@ -1017,6 +1023,24 @@ export declare const realtimeTranscriptDoneEventSchema: z.ZodObject<{
1017
1023
  sequence: z.ZodNumber;
1018
1024
  commandId: z.ZodOptional<z.ZodString>;
1019
1025
  }, z.core.$strip>;
1026
+ /**
1027
+ * The provisional text of an input item not yet final (contract set 8.1.0,
1028
+ * Kaana ADR 0006): sent only to a `transcription` session that asked for
1029
+ * `interimResults`. Each one REPLACES the item's previous interim text; it is
1030
+ * display state, never settled and never part of the item's transcript, and
1031
+ * the item's next `transcript.delta` or its `transcript.done` supersedes it.
1032
+ */
1033
+ export declare const realtimeTranscriptInterimEventSchema: z.ZodObject<{
1034
+ type: z.ZodLiteral<"transcript.interim">;
1035
+ source: z.ZodLiteral<"input_audio">;
1036
+ itemId: z.ZodString;
1037
+ contentIndex: z.ZodNumber;
1038
+ text: z.ZodString;
1039
+ schemaVersion: z.ZodLiteral<1>;
1040
+ requestId: z.ZodString;
1041
+ sequence: z.ZodNumber;
1042
+ commandId: z.ZodOptional<z.ZodString>;
1043
+ }, z.core.$strip>;
1020
1044
  /** Written output of a response (`outputModalities` including `text`). */
1021
1045
  export declare const realtimeTextDeltaEventSchema: z.ZodObject<{
1022
1046
  type: z.ZodLiteral<"text.delta">;
@@ -1158,6 +1182,7 @@ export declare const realtimeSessionOpenSchema: z.ZodObject<{
1158
1182
  inputAudioTranscription: z.ZodOptional<z.ZodObject<{
1159
1183
  language: z.ZodOptional<z.ZodString>;
1160
1184
  prompt: z.ZodOptional<z.ZodString>;
1185
+ interimResults: z.ZodOptional<z.ZodBoolean>;
1161
1186
  }, z.core.$strict>>;
1162
1187
  translation: z.ZodOptional<z.ZodObject<{
1163
1188
  targetLanguage: z.ZodString;
@@ -1268,6 +1293,7 @@ export declare const realtimePublicSessionCreatedEventSchema: z.ZodObject<{
1268
1293
  inputAudioTranscription: z.ZodOptional<z.ZodObject<{
1269
1294
  language: z.ZodOptional<z.ZodString>;
1270
1295
  prompt: z.ZodOptional<z.ZodString>;
1296
+ interimResults: z.ZodOptional<z.ZodBoolean>;
1271
1297
  }, z.core.$strict>>;
1272
1298
  translation: z.ZodOptional<z.ZodObject<{
1273
1299
  targetLanguage: z.ZodString;
@@ -1505,6 +1531,7 @@ export declare const realtimePublicServerEventSchema: z.ZodDiscriminatedUnion<[z
1505
1531
  inputAudioTranscription: z.ZodOptional<z.ZodObject<{
1506
1532
  language: z.ZodOptional<z.ZodString>;
1507
1533
  prompt: z.ZodOptional<z.ZodString>;
1534
+ interimResults: z.ZodOptional<z.ZodBoolean>;
1508
1535
  }, z.core.$strict>>;
1509
1536
  translation: z.ZodOptional<z.ZodObject<{
1510
1537
  targetLanguage: z.ZodString;
@@ -1581,6 +1608,7 @@ export declare const realtimePublicServerEventSchema: z.ZodDiscriminatedUnion<[z
1581
1608
  inputAudioTranscription: z.ZodOptional<z.ZodObject<{
1582
1609
  language: z.ZodOptional<z.ZodString>;
1583
1610
  prompt: z.ZodOptional<z.ZodString>;
1611
+ interimResults: z.ZodOptional<z.ZodBoolean>;
1584
1612
  }, z.core.$strict>>;
1585
1613
  translation: z.ZodOptional<z.ZodObject<{
1586
1614
  targetLanguage: z.ZodString;
@@ -1827,6 +1855,16 @@ export declare const realtimePublicServerEventSchema: z.ZodDiscriminatedUnion<[z
1827
1855
  requestId: z.ZodString;
1828
1856
  sequence: z.ZodNumber;
1829
1857
  commandId: z.ZodOptional<z.ZodString>;
1858
+ }, z.core.$strip>, z.ZodObject<{
1859
+ type: z.ZodLiteral<"transcript.interim">;
1860
+ source: z.ZodLiteral<"input_audio">;
1861
+ itemId: z.ZodString;
1862
+ contentIndex: z.ZodNumber;
1863
+ text: z.ZodString;
1864
+ schemaVersion: z.ZodLiteral<1>;
1865
+ requestId: z.ZodString;
1866
+ sequence: z.ZodNumber;
1867
+ commandId: z.ZodOptional<z.ZodString>;
1830
1868
  }, z.core.$strip>, z.ZodObject<{
1831
1869
  type: z.ZodLiteral<"text.delta">;
1832
1870
  responseId: z.ZodString;
@@ -4,6 +4,7 @@
4
4
  * Moved from `@oxy.so/contracts` 4.12.0 (`src/inference/realtime.ts`) by Kaana ADR 0002.
5
5
  */
6
6
  import { z } from 'zod';
7
+ import { maxUtf16Length, minUtf16Length } from '../stringBounds.js';
7
8
  import { realtimeAudioFormatSchema, realtimeOutputModalitySchema } from './audioFormats.js';
8
9
  import { realtimeSessionKindSchema, realtimeSessionTransportSchema, } from './catalogue.js';
9
10
  import { inferenceTimestampSchema, modelReferenceSchema, PADDED_BASE64_PATTERN, requestIdSchema, } from './identifiers.js';
@@ -36,15 +37,21 @@ export const MAX_REALTIME_RESUME_WINDOW_MS = 60_000;
36
37
  */
37
38
  export const MAX_REALTIME_ITEM_TEXT_CHARS = 1_048_576;
38
39
  /** A client-chosen command identity, unique within one session. */
39
- export const realtimeCommandIdSchema = z.string().min(1).max(128);
40
+ export const realtimeCommandIdSchema = z
41
+ .string()
42
+ .check(minUtf16Length(1))
43
+ .check(maxUtf16Length(128));
40
44
  /** A conversation item's identity within one session. */
41
- export const realtimeItemIdSchema = z.string().min(1).max(128);
45
+ export const realtimeItemIdSchema = z.string().check(minUtf16Length(1)).check(maxUtf16Length(128));
42
46
  /** A response's identity within one session. */
43
- export const realtimeResponseIdSchema = z.string().min(1).max(128);
47
+ export const realtimeResponseIdSchema = z
48
+ .string()
49
+ .check(minUtf16Length(1))
50
+ .check(maxUtf16Length(128));
44
51
  const audioFrameSchema = z
45
52
  .string()
46
- .min(4)
47
- .max(MAX_REALTIME_AUDIO_FRAME_BASE64_LENGTH)
53
+ .check(minUtf16Length(4))
54
+ .check(maxUtf16Length(MAX_REALTIME_AUDIO_FRAME_BASE64_LENGTH))
48
55
  .regex(PADDED_BASE64_PATTERN);
49
56
  const sequenceSchema = z.number().int().nonnegative().safe();
50
57
  const milliseconds = z.number().int().nonnegative().safe();
@@ -106,16 +113,22 @@ export const realtimeInputTranscriptionSchema = z
106
113
  * the provider its spelling of that language, or none for the model to
107
114
  * detect; it is never refused.
108
115
  */
109
- language: z.string().min(2).max(35).optional(),
116
+ language: z.string().check(minUtf16Length(2)).check(maxUtf16Length(35)).optional(),
110
117
  /** A hint — vocabulary or context — used where the model takes one. */
111
- prompt: z.string().max(4_096).optional(),
118
+ prompt: z.string().check(maxUtf16Length(4_096)).optional(),
119
+ /**
120
+ * Send `transcript.interim`: the model's provisional text of the current
121
+ * item, about every half second, before any of it is final (contract set
122
+ * 8.1.0, Kaana ADR 0006). Only a `transcription` session sends it.
123
+ */
124
+ interimResults: z.boolean().optional(),
112
125
  })
113
126
  .strict();
114
127
  /** The target of a `translation` session. */
115
128
  export const realtimeTranslationSchema = z
116
129
  .object({
117
130
  /** A BCP 47 tag. */
118
- targetLanguage: z.string().min(2).max(35),
131
+ targetLanguage: z.string().check(minUtf16Length(2)).check(maxUtf16Length(35)),
119
132
  })
120
133
  .strict();
121
134
  /**
@@ -134,9 +147,9 @@ export const realtimeToolDefinitionSchema = toolDefinitionSchema.omit({ strict:
134
147
  */
135
148
  export const realtimeSessionConfigSchema = z
136
149
  .object({
137
- instructions: z.string().max(32_768).optional(),
150
+ instructions: z.string().check(maxUtf16Length(32_768)).optional(),
138
151
  outputModalities: z.array(realtimeOutputModalitySchema).min(1).max(2).optional(),
139
- voice: z.string().min(1).max(64).optional(),
152
+ voice: z.string().check(minUtf16Length(1)).check(maxUtf16Length(64)).optional(),
140
153
  inputAudioFormat: realtimeAudioFormatSchema,
141
154
  outputAudioFormat: realtimeAudioFormatSchema.optional(),
142
155
  turnDetection: realtimeTurnDetectionSchema,
@@ -158,7 +171,7 @@ export const realtimeSessionConfigSchema = z
158
171
  */
159
172
  export const realtimeSessionConfigUpdateSchema = z
160
173
  .object({
161
- instructions: z.string().max(32_768).optional(),
174
+ instructions: z.string().check(maxUtf16Length(32_768)).optional(),
162
175
  outputModalities: z.array(realtimeOutputModalitySchema).min(1).max(2).optional(),
163
176
  turnDetection: realtimeTurnDetectionSchema.optional(),
164
177
  inputAudioTranscription: realtimeInputTranscriptionSchema.optional(),
@@ -199,7 +212,10 @@ export const realtimeSessionLimitsSchema = z
199
212
  */
200
213
  export const realtimeContentPartSchema = z.discriminatedUnion('type', [
201
214
  z
202
- .object({ type: z.literal('input_text'), text: z.string().max(MAX_REALTIME_ITEM_TEXT_CHARS) })
215
+ .object({
216
+ type: z.literal('input_text'),
217
+ text: z.string().check(maxUtf16Length(MAX_REALTIME_ITEM_TEXT_CHARS)),
218
+ })
203
219
  .strict(),
204
220
  z
205
221
  .object({
@@ -239,8 +255,8 @@ export const realtimeConversationItemSchema = z
239
255
  .object({
240
256
  type: z.literal('function_call'),
241
257
  itemId: realtimeItemIdSchema.optional(),
242
- callId: z.string().min(1).max(128),
243
- name: z.string().min(1).max(128),
258
+ callId: z.string().check(minUtf16Length(1)).check(maxUtf16Length(128)),
259
+ name: z.string().check(minUtf16Length(1)).check(maxUtf16Length(128)),
244
260
  arguments: z.string(),
245
261
  })
246
262
  .strict(),
@@ -248,8 +264,8 @@ export const realtimeConversationItemSchema = z
248
264
  .object({
249
265
  type: z.literal('function_call_output'),
250
266
  itemId: realtimeItemIdSchema.optional(),
251
- callId: z.string().min(1).max(128),
252
- output: z.string().max(MAX_REALTIME_ITEM_TEXT_CHARS),
267
+ callId: z.string().check(minUtf16Length(1)).check(maxUtf16Length(128)),
268
+ output: z.string().check(maxUtf16Length(MAX_REALTIME_ITEM_TEXT_CHARS)),
253
269
  })
254
270
  .strict(),
255
271
  ])
@@ -279,7 +295,7 @@ export const realtimeConversationItemSchema = z
279
295
  /** Per-response overrides for `response.create`. Absent fields keep the session's. */
280
296
  export const realtimeResponseParametersSchema = z
281
297
  .object({
282
- instructions: z.string().max(32_768).optional(),
298
+ instructions: z.string().check(maxUtf16Length(32_768)).optional(),
283
299
  outputModalities: z.array(realtimeOutputModalitySchema).min(1).max(2).optional(),
284
300
  maxOutputTokens: z.number().int().positive().safe().optional(),
285
301
  toolChoice: toolChoiceSchema.optional(),
@@ -496,6 +512,21 @@ export const realtimeTranscriptDoneEventSchema = z.object({
496
512
  responseId: realtimeResponseIdSchema.optional(),
497
513
  transcript: z.string(),
498
514
  });
515
+ /**
516
+ * The provisional text of an input item not yet final (contract set 8.1.0,
517
+ * Kaana ADR 0006): sent only to a `transcription` session that asked for
518
+ * `interimResults`. Each one REPLACES the item's previous interim text; it is
519
+ * display state, never settled and never part of the item's transcript, and
520
+ * the item's next `transcript.delta` or its `transcript.done` supersedes it.
521
+ */
522
+ export const realtimeTranscriptInterimEventSchema = z.object({
523
+ ...eventBase,
524
+ type: z.literal('transcript.interim'),
525
+ source: z.literal('input_audio'),
526
+ itemId: realtimeItemIdSchema,
527
+ contentIndex: z.number().int().nonnegative().safe(),
528
+ text: z.string(),
529
+ });
499
530
  /** Written output of a response (`outputModalities` including `text`). */
500
531
  export const realtimeTextDeltaEventSchema = z.object({
501
532
  ...eventBase,
@@ -511,8 +542,8 @@ export const realtimeToolCallEventSchema = z.object({
511
542
  type: z.literal('tool_call'),
512
543
  responseId: realtimeResponseIdSchema,
513
544
  itemId: realtimeItemIdSchema,
514
- toolCallId: z.string().min(1).max(128),
515
- name: z.string().min(1).max(128).optional(),
545
+ toolCallId: z.string().check(minUtf16Length(1)).check(maxUtf16Length(128)),
546
+ name: z.string().check(minUtf16Length(1)).check(maxUtf16Length(128)).optional(),
516
547
  argumentsDelta: z.string().optional(),
517
548
  complete: z.boolean(),
518
549
  });
@@ -589,6 +620,9 @@ export function realtimeConfigIssues(kind, config) {
589
620
  }
590
621
  break;
591
622
  }
623
+ if (kind !== 'transcription' && config.inputAudioTranscription?.interimResults === true) {
624
+ found(['inputAudioTranscription', 'interimResults'], 'only a transcription session sends interim text');
625
+ }
592
626
  if (config.toolChoice !== undefined && !hasTools) {
593
627
  found(['toolChoice'], 'a tool choice requires at least one tool definition');
594
628
  }
@@ -644,7 +678,7 @@ export const realtimeSessionOpenSchema = z
644
678
  config: realtimeSessionConfigSchema,
645
679
  limits: realtimeOpenLimitsSchema.optional(),
646
680
  /** The caller's own correlation id. */
647
- clientSessionId: z.string().min(1).max(128).optional(),
681
+ clientSessionId: z.string().check(minUtf16Length(1)).check(maxUtf16Length(128)).optional(),
648
682
  labels: requestLabelsSchema.optional(),
649
683
  })
650
684
  .strict()
@@ -795,6 +829,7 @@ export const realtimePublicServerEventSchema = z
795
829
  realtimeOutputAudioDoneEventSchema,
796
830
  realtimeTranscriptDeltaEventSchema,
797
831
  realtimeTranscriptDoneEventSchema,
832
+ realtimeTranscriptInterimEventSchema,
798
833
  realtimeTextDeltaEventSchema,
799
834
  realtimeToolCallEventSchema,
800
835
  realtimePublicResponseDoneEventSchema,
@@ -8,6 +8,7 @@
8
8
  * catalogue identities), and the response names no serving provider.
9
9
  */
10
10
  import { z } from 'zod';
11
+ import { maxUtf16Length, minUtf16Length } from '../stringBounds.js';
11
12
  import { powerLevelSchema } from './catalogue.js';
12
13
  import { generationIdSchema, modelReferenceSchema, requestIdSchema } from './identifiers.js';
13
14
  import { inferenceMessageSchema, inferenceReasoningSchema, requestLabelsSchema, responseFormatSchema, toolChoiceSchema, toolDefinitionSchema, } from './messages.js';
@@ -22,7 +23,10 @@ import { inferenceFinishReasonSchema } from './streamEvents.js';
22
23
  */
23
24
  export const modelTargetSchema = z.union([modelReferenceSchema, powerLevelSchema]);
24
25
  /** The message-or-text input `/v1/responses` accepts. */
25
- const responsesInputSchema = z.union([z.string().min(1), z.array(inferenceMessageSchema).min(1)]);
26
+ const responsesInputSchema = z.union([
27
+ z.string().check(minUtf16Length(1)),
28
+ z.array(inferenceMessageSchema).min(1),
29
+ ]);
26
30
  /**
27
31
  * The request. `model` may be absent: the application's routing policy in Oxy
28
32
  * Console may name a default target, and the request is refused only when it
@@ -44,7 +48,10 @@ export const responsesRequestSchema = z
44
48
  frequencyPenalty: z.number().min(-2).max(2).optional(),
45
49
  presencePenalty: z.number().min(-2).max(2).optional(),
46
50
  seed: z.number().int().safe().optional(),
47
- stopSequences: z.array(z.string().min(1).max(256)).max(8).optional(),
51
+ stopSequences: z
52
+ .array(z.string().check(minUtf16Length(1)).check(maxUtf16Length(256)))
53
+ .max(8)
54
+ .optional(),
48
55
  tools: z.array(toolDefinitionSchema).max(128).optional(),
49
56
  toolChoice: toolChoiceSchema.optional(),
50
57
  responseFormat: responseFormatSchema.optional(),
@@ -52,7 +59,7 @@ export const responsesRequestSchema = z
52
59
  reasoning: inferenceReasoningSchema.optional(),
53
60
  labels: requestLabelsSchema.optional(),
54
61
  /** The caller's own correlation id, echoed on the response. */
55
- clientRequestId: z.string().min(1).max(128).optional(),
62
+ clientRequestId: z.string().check(minUtf16Length(1)).check(maxUtf16Length(128)).optional(),
56
63
  })
57
64
  .strict()
58
65
  .superRefine((request, ctx) => {
@@ -5,6 +5,7 @@
5
5
  * Moved from `@oxy.so/contracts` 4.12.0 (`src/inference/streamEvents.ts`) by Kaana ADR 0002.
6
6
  */
7
7
  import { z } from 'zod';
8
+ import { maxUtf16Length, minUtf16Length } from '../stringBounds.js';
8
9
  import { generationIdSchema, inferenceTimestampSchema, modelReferenceSchema, PADDED_BASE64_PATTERN, requestIdSchema, } from './identifiers.js';
9
10
  import { publicErrorSchema } from './errors.js';
10
11
  import { usageQuantitySchema, usageSourceSchema } from './money.js';
@@ -51,7 +52,11 @@ export const inferenceStreamAudioEventSchema = z.object({
51
52
  sequence: z.number().int().nonnegative().safe(),
52
53
  outputIndex: z.number().int().nonnegative().safe(),
53
54
  mediaType: inferenceAudioMediaTypeSchema,
54
- data: z.string().min(4).max(65536).regex(PADDED_BASE64_PATTERN),
55
+ data: z
56
+ .string()
57
+ .check(minUtf16Length(4))
58
+ .check(maxUtf16Length(65536))
59
+ .regex(PADDED_BASE64_PATTERN),
55
60
  });
56
61
  /**
57
62
  * A tool call being streamed.
@@ -65,9 +70,9 @@ export const inferenceStreamToolCallEventSchema = z.object({
65
70
  type: z.literal('tool_call'),
66
71
  requestId: requestIdSchema,
67
72
  sequence: z.number().int().nonnegative().safe(),
68
- toolCallId: z.string().min(1).max(128),
73
+ toolCallId: z.string().check(minUtf16Length(1)).check(maxUtf16Length(128)),
69
74
  /** Present on the first event of a call. */
70
- name: z.string().min(1).max(128).optional(),
75
+ name: z.string().check(minUtf16Length(1)).check(maxUtf16Length(128)).optional(),
71
76
  argumentsDelta: z.string().optional(),
72
77
  complete: z.boolean(),
73
78
  });
@@ -103,7 +108,7 @@ export const inferenceStreamDoneEventSchema = z.object({
103
108
  sequence: z.number().int().nonnegative().safe(),
104
109
  generationId: generationIdSchema.optional(),
105
110
  finishReason: inferenceFinishReasonSchema,
106
- receiptId: z.string().min(1).max(128).optional(),
111
+ receiptId: z.string().check(minUtf16Length(1)).check(maxUtf16Length(128)).optional(),
107
112
  completedAt: inferenceTimestampSchema,
108
113
  });
109
114
  /* -------------------------------------------------------------------------- */
@@ -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.0.0";
103
+ export declare const INFERENCE_CONTRACT_VERSION = "8.1.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:
@@ -181,6 +181,12 @@ export declare const INFERENCE_CONTRACT_VERSION = "8.0.0";
181
181
  * envelopes v3 and v4 (`scopedExecutionSchema`, `privateAutoExecutionSchema`
182
182
  * and every shape under them) and a deployment's `scopedExecution`. A grant
183
183
  * or a request that parsed under 6.0.0 without them still parses the same.
184
+ *
185
+ * Contract set 8.1.0 (Kaana ADR 0006) is additive: a `transcription`
186
+ * session's `inputAudioTranscription.interimResults`, and the
187
+ * `transcript.interim` event it asks for, the provisional text of an input
188
+ * item that the item's deltas and its `transcript.done` supersede. Any other
189
+ * kind asking for interim text is refused. Nothing in 8.0.0 changes.
184
190
  */
185
191
  /** The public API's one origin and version. */
186
192
  export declare const KAANA_API_BASE_URL = "https://kaana.ai/v1";
@@ -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.0.0';
103
+ export const INFERENCE_CONTRACT_VERSION = '8.1.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:
@@ -181,6 +181,12 @@ export const INFERENCE_CONTRACT_VERSION = '8.0.0';
181
181
  * envelopes v3 and v4 (`scopedExecutionSchema`, `privateAutoExecutionSchema`
182
182
  * and every shape under them) and a deployment's `scopedExecution`. A grant
183
183
  * or a request that parsed under 6.0.0 without them still parses the same.
184
+ *
185
+ * Contract set 8.1.0 (Kaana ADR 0006) is additive: a `transcription`
186
+ * session's `inputAudioTranscription.interimResults`, and the
187
+ * `transcript.interim` event it asks for, the provisional text of an input
188
+ * item that the item's deltas and its `transcript.done` supersede. Any other
189
+ * kind asking for interim text is refused. Nothing in 8.0.0 changes.
184
190
  */
185
191
  /** The public API's one origin and version. */
186
192
  export const KAANA_API_BASE_URL = 'https://kaana.ai/v1';
@@ -0,0 +1,11 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Kaana's frozen wire contract measures strings in UTF-16 code units, as Go's
4
+ * utf16Length does. Zod >=4.5 measures its built-in string bounds in code points.
5
+ * These per-schema checks retain the standard bound metadata used by the Go
6
+ * descriptor and JSON Schema generators, with the contract's explicit measure.
7
+ * No Zod constructor, prototype, shared check or array validation is changed.
8
+ */
9
+ export declare function minUtf16Length(minimum: number): z.core.$ZodCheck<string>;
10
+ export declare function maxUtf16Length(maximum: number): z.core.$ZodCheck<string>;
11
+ export declare function utf16Length(length: number): z.core.$ZodCheck<string>;