@kaana.ai/contracts 8.3.0 → 8.5.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/index.d.ts CHANGED
@@ -24,6 +24,7 @@ export * from './public/images.js';
24
24
  export * from './public/messages.js';
25
25
  export * from './public/money.js';
26
26
  export * from './public/policy.js';
27
+ export * from './public/providerPreferences.js';
27
28
  export * from './public/realtime.js';
28
29
  export * from './public/responses.js';
29
30
  export * from './public/streamEvents.js';
package/dist/index.js CHANGED
@@ -24,6 +24,7 @@ export * from './public/images.js';
24
24
  export * from './public/messages.js';
25
25
  export * from './public/money.js';
26
26
  export * from './public/policy.js';
27
+ export * from './public/providerPreferences.js';
27
28
  export * from './public/realtime.js';
28
29
  export * from './public/responses.js';
29
30
  export * from './public/streamEvents.js';
@@ -113,6 +113,13 @@ export declare const catalogueModelSchema: z.ZodObject<{
113
113
  }>>;
114
114
  }, z.core.$strict>>;
115
115
  }, z.core.$strict>>;
116
+ unreported: z.ZodOptional<z.ZodArray<z.ZodEnum<{
117
+ tools: "tools";
118
+ parallelToolCalls: "parallelToolCalls";
119
+ structuredOutput: "structuredOutput";
120
+ jsonMode: "jsonMode";
121
+ promptCaching: "promptCaching";
122
+ }>>>;
116
123
  }, z.core.$strict>;
117
124
  license: z.ZodObject<{
118
125
  licenseId: z.ZodString;
@@ -307,10 +314,10 @@ export declare const routingProfileSchema: z.ZodObject<{
307
314
  displayName: z.ZodString;
308
315
  description: z.ZodOptional<z.ZodString>;
309
316
  optimiseFor: z.ZodEnum<{
310
- quality: "quality";
311
- price: "price";
312
317
  latency: "latency";
313
318
  throughput: "throughput";
319
+ quality: "quality";
320
+ price: "price";
314
321
  balanced: "balanced";
315
322
  }>;
316
323
  candidates: z.ZodArray<z.ZodObject<{
@@ -436,6 +443,13 @@ export declare const modelCatalogueEntrySchema: z.ZodObject<{
436
443
  }>>;
437
444
  }, z.core.$strict>>;
438
445
  }, z.core.$strict>>;
446
+ unreported: z.ZodOptional<z.ZodArray<z.ZodEnum<{
447
+ tools: "tools";
448
+ parallelToolCalls: "parallelToolCalls";
449
+ structuredOutput: "structuredOutput";
450
+ jsonMode: "jsonMode";
451
+ promptCaching: "promptCaching";
452
+ }>>>;
439
453
  }, z.core.$strict>;
440
454
  license: z.ZodObject<{
441
455
  licenseId: z.ZodString;
@@ -501,6 +515,7 @@ export declare const modelCatalogueEntrySchema: z.ZodObject<{
501
515
  audio_output_tokens: "audio_output_tokens";
502
516
  session_milliseconds: "session_milliseconds";
503
517
  input_transcription_milliseconds: "input_transcription_milliseconds";
518
+ cache_write_input_tokens: "cache_write_input_tokens";
504
519
  }>;
505
520
  amount: z.core.$ZodBranded<z.ZodString, "ExactDecimal", "out">;
506
521
  per: z.ZodNumber;
@@ -704,6 +719,13 @@ export declare const declaredModelSchema: z.ZodObject<{
704
719
  }>>;
705
720
  }, z.core.$strict>>;
706
721
  }, z.core.$strict>>;
722
+ unreported: z.ZodOptional<z.ZodArray<z.ZodEnum<{
723
+ tools: "tools";
724
+ parallelToolCalls: "parallelToolCalls";
725
+ structuredOutput: "structuredOutput";
726
+ jsonMode: "jsonMode";
727
+ promptCaching: "promptCaching";
728
+ }>>>;
707
729
  }, z.core.$strict>;
708
730
  license: z.ZodObject<{
709
731
  licenseId: z.ZodString;
@@ -767,6 +789,7 @@ export declare const declaredModelSchema: z.ZodObject<{
767
789
  audio_output_tokens: "audio_output_tokens";
768
790
  session_milliseconds: "session_milliseconds";
769
791
  input_transcription_milliseconds: "input_transcription_milliseconds";
792
+ cache_write_input_tokens: "cache_write_input_tokens";
770
793
  }>;
771
794
  amount: z.core.$ZodBranded<z.ZodString, "ExactDecimal", "out">;
772
795
  per: z.ZodNumber;
@@ -935,6 +958,13 @@ export declare const declaredCatalogueSchema: z.ZodObject<{
935
958
  }>>;
936
959
  }, z.core.$strict>>;
937
960
  }, z.core.$strict>>;
961
+ unreported: z.ZodOptional<z.ZodArray<z.ZodEnum<{
962
+ tools: "tools";
963
+ parallelToolCalls: "parallelToolCalls";
964
+ structuredOutput: "structuredOutput";
965
+ jsonMode: "jsonMode";
966
+ promptCaching: "promptCaching";
967
+ }>>>;
938
968
  }, z.core.$strict>;
939
969
  license: z.ZodObject<{
940
970
  licenseId: z.ZodString;
@@ -998,6 +1028,7 @@ export declare const declaredCatalogueSchema: z.ZodObject<{
998
1028
  audio_output_tokens: "audio_output_tokens";
999
1029
  session_milliseconds: "session_milliseconds";
1000
1030
  input_transcription_milliseconds: "input_transcription_milliseconds";
1031
+ cache_write_input_tokens: "cache_write_input_tokens";
1001
1032
  }>;
1002
1033
  amount: z.core.$ZodBranded<z.ZodString, "ExactDecimal", "out">;
1003
1034
  per: z.ZodNumber;
@@ -72,6 +72,7 @@ export declare const decisionResultSchema: z.ZodObject<{
72
72
  audio_output_tokens: "audio_output_tokens";
73
73
  session_milliseconds: "session_milliseconds";
74
74
  input_transcription_milliseconds: "input_transcription_milliseconds";
75
+ cache_write_input_tokens: "cache_write_input_tokens";
75
76
  }>;
76
77
  quantity: z.ZodNumber;
77
78
  }, z.core.$strict>>;
@@ -245,6 +246,7 @@ export declare const decisionFailureSchema: z.ZodObject<{
245
246
  audio_output_tokens: "audio_output_tokens";
246
247
  session_milliseconds: "session_milliseconds";
247
248
  input_transcription_milliseconds: "input_transcription_milliseconds";
249
+ cache_write_input_tokens: "cache_write_input_tokens";
248
250
  }>;
249
251
  quantity: z.ZodNumber;
250
252
  }, z.core.$strict>>;
@@ -561,6 +561,7 @@ export declare const receiptAccessSchema: z.ZodObject<{
561
561
  audio_output_tokens: "audio_output_tokens";
562
562
  session_milliseconds: "session_milliseconds";
563
563
  input_transcription_milliseconds: "input_transcription_milliseconds";
564
+ cache_write_input_tokens: "cache_write_input_tokens";
564
565
  }>;
565
566
  amount: z.core.$ZodBranded<z.ZodString, "ExactDecimal", "out">;
566
567
  per: z.ZodNumber;
@@ -610,6 +611,7 @@ export declare const receiptAccessSchema: z.ZodObject<{
610
611
  audio_output_tokens: "audio_output_tokens";
611
612
  session_milliseconds: "session_milliseconds";
612
613
  input_transcription_milliseconds: "input_transcription_milliseconds";
614
+ cache_write_input_tokens: "cache_write_input_tokens";
613
615
  }>;
614
616
  quantity: z.ZodNumber;
615
617
  }, z.core.$strict>>;
@@ -672,6 +674,7 @@ export declare const receiptAccessSchema: z.ZodObject<{
672
674
  audio_output_tokens: "audio_output_tokens";
673
675
  session_milliseconds: "session_milliseconds";
674
676
  input_transcription_milliseconds: "input_transcription_milliseconds";
677
+ cache_write_input_tokens: "cache_write_input_tokens";
675
678
  }>;
676
679
  quantity: z.ZodNumber;
677
680
  }, z.core.$strict>>;
@@ -326,6 +326,7 @@ export declare const realtimeResponseDoneEventSchema: z.ZodObject<{
326
326
  audio_output_tokens: "audio_output_tokens";
327
327
  session_milliseconds: "session_milliseconds";
328
328
  input_transcription_milliseconds: "input_transcription_milliseconds";
329
+ cache_write_input_tokens: "cache_write_input_tokens";
329
330
  }>;
330
331
  quantity: z.ZodNumber;
331
332
  }, z.core.$strict>>;
@@ -442,6 +443,7 @@ export declare const realtimeSessionClosedEventSchema: z.ZodObject<{
442
443
  audio_output_tokens: "audio_output_tokens";
443
444
  session_milliseconds: "session_milliseconds";
444
445
  input_transcription_milliseconds: "input_transcription_milliseconds";
446
+ cache_write_input_tokens: "cache_write_input_tokens";
445
447
  }>;
446
448
  quantity: z.ZodNumber;
447
449
  }, z.core.$strict>>;
@@ -899,6 +901,7 @@ export declare const realtimeServerEventSchema: z.ZodDiscriminatedUnion<[z.ZodOb
899
901
  audio_output_tokens: "audio_output_tokens";
900
902
  session_milliseconds: "session_milliseconds";
901
903
  input_transcription_milliseconds: "input_transcription_milliseconds";
904
+ cache_write_input_tokens: "cache_write_input_tokens";
902
905
  }>;
903
906
  quantity: z.ZodNumber;
904
907
  }, z.core.$strict>>;
@@ -1005,6 +1008,7 @@ export declare const realtimeServerEventSchema: z.ZodDiscriminatedUnion<[z.ZodOb
1005
1008
  audio_output_tokens: "audio_output_tokens";
1006
1009
  session_milliseconds: "session_milliseconds";
1007
1010
  input_transcription_milliseconds: "input_transcription_milliseconds";
1011
+ cache_write_input_tokens: "cache_write_input_tokens";
1008
1012
  }>;
1009
1013
  quantity: z.ZodNumber;
1010
1014
  }, z.core.$strict>>;
@@ -92,6 +92,7 @@ export declare const settlementSchema: z.ZodObject<{
92
92
  audio_output_tokens: "audio_output_tokens";
93
93
  session_milliseconds: "session_milliseconds";
94
94
  input_transcription_milliseconds: "input_transcription_milliseconds";
95
+ cache_write_input_tokens: "cache_write_input_tokens";
95
96
  }>;
96
97
  quantity: z.ZodNumber;
97
98
  }, z.core.$strict>>;
@@ -216,6 +217,7 @@ export declare const settlementPageSchema: z.ZodObject<{
216
217
  audio_output_tokens: "audio_output_tokens";
217
218
  session_milliseconds: "session_milliseconds";
218
219
  input_transcription_milliseconds: "input_transcription_milliseconds";
220
+ cache_write_input_tokens: "cache_write_input_tokens";
219
221
  }>;
220
222
  quantity: z.ZodNumber;
221
223
  }, z.core.$strict>>;
@@ -82,6 +82,7 @@ export declare const inferenceStreamUsageEventSchema: z.ZodObject<{
82
82
  audio_output_tokens: "audio_output_tokens";
83
83
  session_milliseconds: "session_milliseconds";
84
84
  input_transcription_milliseconds: "input_transcription_milliseconds";
85
+ cache_write_input_tokens: "cache_write_input_tokens";
85
86
  }>;
86
87
  quantity: z.ZodNumber;
87
88
  }, z.core.$strict>>;
@@ -300,6 +301,7 @@ export declare const inferenceStreamEventSchema: z.ZodDiscriminatedUnion<[z.ZodO
300
301
  audio_output_tokens: "audio_output_tokens";
301
302
  session_milliseconds: "session_milliseconds";
302
303
  input_transcription_milliseconds: "input_transcription_milliseconds";
304
+ cache_write_input_tokens: "cache_write_input_tokens";
303
305
  }>;
304
306
  quantity: z.ZodNumber;
305
307
  }, z.core.$strict>>;
@@ -116,6 +116,7 @@ export declare const normalizedUsageReportSchema: z.ZodObject<{
116
116
  audio_output_tokens: "audio_output_tokens";
117
117
  session_milliseconds: "session_milliseconds";
118
118
  input_transcription_milliseconds: "input_transcription_milliseconds";
119
+ cache_write_input_tokens: "cache_write_input_tokens";
119
120
  }>;
120
121
  quantity: z.ZodNumber;
121
122
  }, z.core.$strict>>;
@@ -85,6 +85,7 @@ export declare const speechAudioDoneEventSchema: z.ZodObject<{
85
85
  audio_output_tokens: "audio_output_tokens";
86
86
  session_milliseconds: "session_milliseconds";
87
87
  input_transcription_milliseconds: "input_transcription_milliseconds";
88
+ cache_write_input_tokens: "cache_write_input_tokens";
88
89
  }>;
89
90
  quantity: z.ZodNumber;
90
91
  }, z.core.$strict>>;
@@ -168,6 +169,7 @@ export declare const speechStreamEventSchema: z.ZodDiscriminatedUnion<[z.ZodObje
168
169
  audio_output_tokens: "audio_output_tokens";
169
170
  session_milliseconds: "session_milliseconds";
170
171
  input_transcription_milliseconds: "input_transcription_milliseconds";
172
+ cache_write_input_tokens: "cache_write_input_tokens";
171
173
  }>;
172
174
  quantity: z.ZodNumber;
173
175
  }, z.core.$strict>>;
@@ -313,6 +315,7 @@ export declare const transcriptionSchema: z.ZodObject<{
313
315
  audio_output_tokens: "audio_output_tokens";
314
316
  session_milliseconds: "session_milliseconds";
315
317
  input_transcription_milliseconds: "input_transcription_milliseconds";
318
+ cache_write_input_tokens: "cache_write_input_tokens";
316
319
  }>;
317
320
  quantity: z.ZodNumber;
318
321
  }, z.core.$strict>>;
@@ -157,6 +157,11 @@ export declare const modelRealtimeCapabilitiesSchema: z.ZodObject<{
157
157
  }>>;
158
158
  }, z.core.$strict>>;
159
159
  }, z.core.$strict>;
160
+ /**
161
+ * The boolean capabilities that may be listed as unreported (contract set
162
+ * 8.4.0): the five whose `false` has so far meant both "no" and "not recorded".
163
+ */
164
+ export declare const UNREPORTED_CAPABILITY_KEYS: readonly ["tools", "parallelToolCalls", "structuredOutput", "jsonMode", "promptCaching"];
160
165
  /**
161
166
  * What a model can do, in the terms a caller has to decide against before
162
167
  * sending a request: can it call tools, does it accept images, will it honour a
@@ -226,6 +231,13 @@ export declare const modelCapabilitiesSchema: z.ZodObject<{
226
231
  }>>;
227
232
  }, z.core.$strict>>;
228
233
  }, z.core.$strict>>;
234
+ unreported: z.ZodOptional<z.ZodArray<z.ZodEnum<{
235
+ tools: "tools";
236
+ parallelToolCalls: "parallelToolCalls";
237
+ structuredOutput: "structuredOutput";
238
+ jsonMode: "jsonMode";
239
+ promptCaching: "promptCaching";
240
+ }>>>;
229
241
  }, z.core.$strict>;
230
242
  /**
231
243
  * License terms, including the two questions that decide whether Oxy may serve
@@ -483,6 +495,13 @@ export declare const modelSchema: z.ZodObject<{
483
495
  }>>;
484
496
  }, z.core.$strict>>;
485
497
  }, z.core.$strict>>;
498
+ unreported: z.ZodOptional<z.ZodArray<z.ZodEnum<{
499
+ tools: "tools";
500
+ parallelToolCalls: "parallelToolCalls";
501
+ structuredOutput: "structuredOutput";
502
+ jsonMode: "jsonMode";
503
+ promptCaching: "promptCaching";
504
+ }>>>;
486
505
  }, z.core.$strict>;
487
506
  audio: z.ZodOptional<z.ZodObject<{
488
507
  voices: z.ZodArray<z.ZodObject<{
@@ -573,6 +592,7 @@ export declare const modelSchema: z.ZodObject<{
573
592
  audio_output_tokens: "audio_output_tokens";
574
593
  session_milliseconds: "session_milliseconds";
575
594
  input_transcription_milliseconds: "input_transcription_milliseconds";
595
+ cache_write_input_tokens: "cache_write_input_tokens";
576
596
  }>;
577
597
  amount: z.core.$ZodBranded<z.ZodString, "ExactDecimal", "out">;
578
598
  per: z.ZodNumber;
@@ -702,6 +722,13 @@ export declare const modelListSchema: z.ZodObject<{
702
722
  }>>;
703
723
  }, z.core.$strict>>;
704
724
  }, z.core.$strict>>;
725
+ unreported: z.ZodOptional<z.ZodArray<z.ZodEnum<{
726
+ tools: "tools";
727
+ parallelToolCalls: "parallelToolCalls";
728
+ structuredOutput: "structuredOutput";
729
+ jsonMode: "jsonMode";
730
+ promptCaching: "promptCaching";
731
+ }>>>;
705
732
  }, z.core.$strict>;
706
733
  audio: z.ZodOptional<z.ZodObject<{
707
734
  voices: z.ZodArray<z.ZodObject<{
@@ -792,6 +819,7 @@ export declare const modelListSchema: z.ZodObject<{
792
819
  audio_output_tokens: "audio_output_tokens";
793
820
  session_milliseconds: "session_milliseconds";
794
821
  input_transcription_milliseconds: "input_transcription_milliseconds";
822
+ cache_write_input_tokens: "cache_write_input_tokens";
795
823
  }>;
796
824
  amount: z.core.$ZodBranded<z.ZodString, "ExactDecimal", "out">;
797
825
  per: z.ZodNumber;
@@ -127,6 +127,17 @@ export const modelRealtimeCapabilitiesSchema = z
127
127
  .optional(),
128
128
  })
129
129
  .strict();
130
+ /**
131
+ * The boolean capabilities that may be listed as unreported (contract set
132
+ * 8.4.0): the five whose `false` has so far meant both "no" and "not recorded".
133
+ */
134
+ export const UNREPORTED_CAPABILITY_KEYS = [
135
+ 'tools',
136
+ 'parallelToolCalls',
137
+ 'structuredOutput',
138
+ 'jsonMode',
139
+ 'promptCaching',
140
+ ];
130
141
  /**
131
142
  * What a model can do, in the terms a caller has to decide against before
132
143
  * sending a request: can it call tools, does it accept images, will it honour a
@@ -168,9 +179,38 @@ export const modelCapabilitiesSchema = z
168
179
  apiFormats: z.array(inferenceApiFormatSchema).min(1).optional(),
169
180
  /** Realtime sessions this model holds; absent means none. Contract set 3.2.0. */
170
181
  realtime: modelRealtimeCapabilitiesSchema.optional(),
182
+ /**
183
+ * The boolean capabilities whose value is NOT evidence: nobody recorded an
184
+ * answer, so `false` there means "not stated as true", not "known absent".
185
+ * Added in contract set 8.4.0 so the five required booleans keep their
186
+ * shape for every deployed reader while a producer can still say which of
187
+ * them it never established. A listed key is always `false`. ABSENT means
188
+ * undeclared (a catalogue from an older producer): every boolean is read
189
+ * as it was before this field existed.
190
+ */
191
+ unreported: z.array(z.enum(UNREPORTED_CAPABILITY_KEYS)).optional(),
171
192
  })
172
193
  .strict()
173
194
  .superRefine((capabilities, ctx) => {
195
+ const unreported = capabilities.unreported;
196
+ if (unreported !== undefined) {
197
+ if (new Set(unreported).size !== unreported.length) {
198
+ ctx.addIssue({
199
+ code: 'custom',
200
+ path: ['unreported'],
201
+ message: 'each unreported capability is listed at most once',
202
+ });
203
+ }
204
+ for (const [index, key] of unreported.entries()) {
205
+ if (capabilities[key]) {
206
+ ctx.addIssue({
207
+ code: 'custom',
208
+ path: ['unreported', index],
209
+ message: `${key} is true, so it is reported: an unreported capability is false`,
210
+ });
211
+ }
212
+ }
213
+ }
174
214
  const formats = capabilities.apiFormats;
175
215
  if (formats !== undefined && new Set(formats).size !== formats.length) {
176
216
  ctx.addIssue({
@@ -2,9 +2,10 @@
2
2
  * `POST /v1/chat/completions` — the OpenAI-compatible surface.
3
3
  *
4
4
  * It speaks the flat OpenAI request and response shapes so an unmodified OpenAI
5
- * SDK works against `baseURL: 'https://kaana.ai/v1'` with an `oxy_sk_…` key, and
6
- * it gains NO Kaana-specific request field: a capability with no OpenAI
7
- * representation lives on `/v1/responses`. `.strict()` everywhere: a stock SDK
5
+ * SDK works against `baseURL: 'https://kaana.ai/v1'` with an `oxy_sk_…` key. Its
6
+ * one extension is `provider`, the OpenRouter-style routing preference (ADR
7
+ * 0008); every other capability with no OpenAI representation lives on
8
+ * `/v1/responses`. `.strict()` everywhere: a stock SDK
8
9
  * sending a parameter Kaana does not implement is told so rather than having it
9
10
  * silently dropped.
10
11
  *
@@ -214,6 +215,34 @@ export declare const chatCompletionsRequestSchema: z.ZodObject<{
214
215
  }>;
215
216
  }, z.core.$strict>>;
216
217
  user: z.ZodOptional<z.ZodString>;
218
+ provider: z.ZodOptional<z.ZodObject<{
219
+ order: z.ZodOptional<z.ZodArray<z.ZodString>>;
220
+ only: z.ZodOptional<z.ZodArray<z.ZodString>>;
221
+ ignore: z.ZodOptional<z.ZodArray<z.ZodString>>;
222
+ allow_fallbacks: z.ZodOptional<z.ZodBoolean>;
223
+ require_parameters: z.ZodOptional<z.ZodBoolean>;
224
+ quantizations: z.ZodOptional<z.ZodArray<z.ZodEnum<{
225
+ unknown: "unknown";
226
+ int4: "int4";
227
+ int8: "int8";
228
+ fp4: "fp4";
229
+ mxfp4: "mxfp4";
230
+ nvfp4: "nvfp4";
231
+ fp6: "fp6";
232
+ fp8: "fp8";
233
+ mxfp8: "mxfp8";
234
+ fp16: "fp16";
235
+ bf16: "bf16";
236
+ fp32: "fp32";
237
+ }>>>;
238
+ sort: z.ZodOptional<z.ZodEnum<{
239
+ latency: "latency";
240
+ throughput: "throughput";
241
+ }>>;
242
+ preferred_max_latency: z.ZodOptional<z.ZodNumber>;
243
+ preferred_min_throughput: z.ZodOptional<z.ZodNumber>;
244
+ }, z.core.$strict>>;
245
+ prompt_cache_key: z.ZodOptional<z.ZodString>;
217
246
  }, z.core.$strict>;
218
247
  /** OpenAI's usage block, with the audio members only when audio tokens were metered. */
219
248
  export declare const chatCompletionUsageSchema: z.ZodObject<{
@@ -2,9 +2,10 @@
2
2
  * `POST /v1/chat/completions` — the OpenAI-compatible surface.
3
3
  *
4
4
  * It speaks the flat OpenAI request and response shapes so an unmodified OpenAI
5
- * SDK works against `baseURL: 'https://kaana.ai/v1'` with an `oxy_sk_…` key, and
6
- * it gains NO Kaana-specific request field: a capability with no OpenAI
7
- * representation lives on `/v1/responses`. `.strict()` everywhere: a stock SDK
5
+ * SDK works against `baseURL: 'https://kaana.ai/v1'` with an `oxy_sk_…` key. Its
6
+ * one extension is `provider`, the OpenRouter-style routing preference (ADR
7
+ * 0008); every other capability with no OpenAI representation lives on
8
+ * `/v1/responses`. `.strict()` everywhere: a stock SDK
8
9
  * sending a parameter Kaana does not implement is told so rather than having it
9
10
  * silently dropped.
10
11
  *
@@ -18,6 +19,7 @@ import { maxUtf16Length, minUtf16Length } from '../stringBounds.js';
18
19
  import { reasoningEffortSchema } from './catalogue.js';
19
20
  import { publicErrorCodeSchema } from './errors.js';
20
21
  import { inferenceContentPartSchema } from './messages.js';
22
+ import { promptCacheKeySchema, providerPreferencesSchema } from './providerPreferences.js';
21
23
  import { modelTargetSchema } from './responses.js';
22
24
  /** `stop` in the OpenAI dialect: one sequence or a list of them. */
23
25
  const openAiStopSchema = z.union([
@@ -139,6 +141,10 @@ export const chatCompletionsRequestSchema = z
139
141
  * only. `X-Oxy-User-Id` wins when both are present.
140
142
  */
141
143
  user: z.string().check(minUtf16Length(1)).check(maxUtf16Length(64)).optional(),
144
+ /** Routing preferences that can only narrow what the grant admits (ADR 0008). */
145
+ provider: providerPreferencesSchema.optional(),
146
+ /** OpenAI's field: keeps requests sharing a prompt prefix on one deployment. */
147
+ prompt_cache_key: promptCacheKeySchema.optional(),
142
148
  })
143
149
  .strict()
144
150
  .superRefine((request, ctx) => {
@@ -145,6 +145,7 @@ export declare const decisionSuccessSchema: z.ZodObject<{
145
145
  audio_output_tokens: "audio_output_tokens";
146
146
  session_milliseconds: "session_milliseconds";
147
147
  input_transcription_milliseconds: "input_transcription_milliseconds";
148
+ cache_write_input_tokens: "cache_write_input_tokens";
148
149
  }>;
149
150
  quantity: z.ZodNumber;
150
151
  }, z.core.$strict>>;
@@ -57,6 +57,7 @@ export declare const chargedGenerationRecordSchema: z.ZodObject<{
57
57
  audio_output_tokens: "audio_output_tokens";
58
58
  session_milliseconds: "session_milliseconds";
59
59
  input_transcription_milliseconds: "input_transcription_milliseconds";
60
+ cache_write_input_tokens: "cache_write_input_tokens";
60
61
  }>;
61
62
  amount: z.core.$ZodBranded<z.ZodString, "ExactDecimal", "out">;
62
63
  per: z.ZodNumber;
@@ -106,6 +107,7 @@ export declare const chargedGenerationRecordSchema: z.ZodObject<{
106
107
  audio_output_tokens: "audio_output_tokens";
107
108
  session_milliseconds: "session_milliseconds";
108
109
  input_transcription_milliseconds: "input_transcription_milliseconds";
110
+ cache_write_input_tokens: "cache_write_input_tokens";
109
111
  }>;
110
112
  quantity: z.ZodNumber;
111
113
  }, z.core.$strict>>;
@@ -174,6 +176,7 @@ export declare const meteredGenerationRecordSchema: z.ZodObject<{
174
176
  audio_output_tokens: "audio_output_tokens";
175
177
  session_milliseconds: "session_milliseconds";
176
178
  input_transcription_milliseconds: "input_transcription_milliseconds";
179
+ cache_write_input_tokens: "cache_write_input_tokens";
177
180
  }>;
178
181
  quantity: z.ZodNumber;
179
182
  }, z.core.$strict>>;
@@ -206,6 +209,7 @@ export declare const generationRecordSchema: z.ZodDiscriminatedUnion<[z.ZodObjec
206
209
  audio_output_tokens: "audio_output_tokens";
207
210
  session_milliseconds: "session_milliseconds";
208
211
  input_transcription_milliseconds: "input_transcription_milliseconds";
212
+ cache_write_input_tokens: "cache_write_input_tokens";
209
213
  }>;
210
214
  amount: z.core.$ZodBranded<z.ZodString, "ExactDecimal", "out">;
211
215
  per: z.ZodNumber;
@@ -255,6 +259,7 @@ export declare const generationRecordSchema: z.ZodDiscriminatedUnion<[z.ZodObjec
255
259
  audio_output_tokens: "audio_output_tokens";
256
260
  session_milliseconds: "session_milliseconds";
257
261
  input_transcription_milliseconds: "input_transcription_milliseconds";
262
+ cache_write_input_tokens: "cache_write_input_tokens";
258
263
  }>;
259
264
  quantity: z.ZodNumber;
260
265
  }, z.core.$strict>>;
@@ -317,6 +322,7 @@ export declare const generationRecordSchema: z.ZodDiscriminatedUnion<[z.ZodObjec
317
322
  audio_output_tokens: "audio_output_tokens";
318
323
  session_milliseconds: "session_milliseconds";
319
324
  input_transcription_milliseconds: "input_transcription_milliseconds";
325
+ cache_write_input_tokens: "cache_write_input_tokens";
320
326
  }>;
321
327
  quantity: z.ZodNumber;
322
328
  }, z.core.$strict>>;
@@ -142,12 +142,22 @@ export declare const moneySchema: z.ZodObject<{
142
142
  * (`routes/inferenceEdge.ts` renders `prompt_tokens` as
143
143
  * `input_tokens + cached_input_tokens`).
144
144
  *
145
+ * **`cache_write_input_tokens` is the first-request premium** (added in contract
146
+ * set 8.4.0): input tokens written to a prompt cache on THIS request, which a
147
+ * provider bills above the base input rate (Anthropic's 5-minute write is 1.25x
148
+ * input). It is a sibling under the partition rule, never inside `input_tokens`
149
+ * or `cached_input_tokens`: a cache read and a cache write of the same token
150
+ * cannot both happen, so the three never count one token twice. It covers the
151
+ * provider's DEFAULT time-to-live only; a longer TTL is a different price and
152
+ * is not expressible by this unit, so a route that cannot price it refuses it.
153
+ * Declared before anything emits it: Oxy must accept the unit first.
154
+ *
145
155
  * Time is carried in integer MILLISECONDS rather than seconds so that no unit
146
156
  * quantity is ever fractional: a 12.5-second transcription is `12500`, exactly,
147
157
  * and the "units are integers" rule holds for every modality instead of holding
148
158
  * for tokens and being quietly broken by audio.
149
159
  */
150
- export declare const USAGE_UNITS: readonly ["input_tokens", "cached_input_tokens", "output_tokens", "reasoning_tokens", "requests", "images", "audio_input_milliseconds", "audio_output_milliseconds", "video_milliseconds", "characters", "embeddings", "audio_input_tokens", "cached_audio_input_tokens", "audio_output_tokens", "session_milliseconds", "input_transcription_milliseconds"];
160
+ export declare const USAGE_UNITS: readonly ["input_tokens", "cached_input_tokens", "output_tokens", "reasoning_tokens", "requests", "images", "audio_input_milliseconds", "audio_output_milliseconds", "video_milliseconds", "characters", "embeddings", "audio_input_tokens", "cached_audio_input_tokens", "audio_output_tokens", "session_milliseconds", "input_transcription_milliseconds", "cache_write_input_tokens"];
151
161
  export declare const usageUnitSchema: z.ZodEnum<{
152
162
  input_tokens: "input_tokens";
153
163
  cached_input_tokens: "cached_input_tokens";
@@ -165,6 +175,7 @@ export declare const usageUnitSchema: z.ZodEnum<{
165
175
  audio_output_tokens: "audio_output_tokens";
166
176
  session_milliseconds: "session_milliseconds";
167
177
  input_transcription_milliseconds: "input_transcription_milliseconds";
178
+ cache_write_input_tokens: "cache_write_input_tokens";
168
179
  }>;
169
180
  /**
170
181
  * A metered quantity of ONE unit. Never money — a quantity carries no price and
@@ -188,6 +199,7 @@ export declare const usageQuantitySchema: z.ZodObject<{
188
199
  audio_output_tokens: "audio_output_tokens";
189
200
  session_milliseconds: "session_milliseconds";
190
201
  input_transcription_milliseconds: "input_transcription_milliseconds";
202
+ cache_write_input_tokens: "cache_write_input_tokens";
191
203
  }>;
192
204
  quantity: z.ZodNumber;
193
205
  }, z.core.$strict>;
@@ -231,6 +243,7 @@ export declare const unitPriceSchema: z.ZodObject<{
231
243
  audio_output_tokens: "audio_output_tokens";
232
244
  session_milliseconds: "session_milliseconds";
233
245
  input_transcription_milliseconds: "input_transcription_milliseconds";
246
+ cache_write_input_tokens: "cache_write_input_tokens";
234
247
  }>;
235
248
  amount: z.core.$ZodBranded<z.ZodString, "ExactDecimal", "out">;
236
249
  per: z.ZodNumber;
@@ -265,6 +278,7 @@ export declare const priceSnapshotSchema: z.ZodObject<{
265
278
  audio_output_tokens: "audio_output_tokens";
266
279
  session_milliseconds: "session_milliseconds";
267
280
  input_transcription_milliseconds: "input_transcription_milliseconds";
281
+ cache_write_input_tokens: "cache_write_input_tokens";
268
282
  }>;
269
283
  amount: z.core.$ZodBranded<z.ZodString, "ExactDecimal", "out">;
270
284
  per: z.ZodNumber;
@@ -294,6 +308,7 @@ export declare const usageSchema: z.ZodArray<z.ZodObject<{
294
308
  audio_output_tokens: "audio_output_tokens";
295
309
  session_milliseconds: "session_milliseconds";
296
310
  input_transcription_milliseconds: "input_transcription_milliseconds";
311
+ cache_write_input_tokens: "cache_write_input_tokens";
297
312
  }>;
298
313
  quantity: z.ZodNumber;
299
314
  }, z.core.$strict>>;
@@ -150,6 +150,16 @@ export const moneySchema = z
150
150
  * (`routes/inferenceEdge.ts` renders `prompt_tokens` as
151
151
  * `input_tokens + cached_input_tokens`).
152
152
  *
153
+ * **`cache_write_input_tokens` is the first-request premium** (added in contract
154
+ * set 8.4.0): input tokens written to a prompt cache on THIS request, which a
155
+ * provider bills above the base input rate (Anthropic's 5-minute write is 1.25x
156
+ * input). It is a sibling under the partition rule, never inside `input_tokens`
157
+ * or `cached_input_tokens`: a cache read and a cache write of the same token
158
+ * cannot both happen, so the three never count one token twice. It covers the
159
+ * provider's DEFAULT time-to-live only; a longer TTL is a different price and
160
+ * is not expressible by this unit, so a route that cannot price it refuses it.
161
+ * Declared before anything emits it: Oxy must accept the unit first.
162
+ *
153
163
  * Time is carried in integer MILLISECONDS rather than seconds so that no unit
154
164
  * quantity is ever fractional: a 12.5-second transcription is `12500`, exactly,
155
165
  * and the "units are integers" rule holds for every modality instead of holding
@@ -172,6 +182,7 @@ export const USAGE_UNITS = [
172
182
  'audio_output_tokens',
173
183
  'session_milliseconds',
174
184
  'input_transcription_milliseconds',
185
+ 'cache_write_input_tokens',
175
186
  ];
176
187
  export const usageUnitSchema = z.enum(USAGE_UNITS);
177
188
  /**
@@ -0,0 +1,71 @@
1
+ /**
2
+ * The `provider` object a caller may send on `POST /v1/chat/completions` and
3
+ * `POST /v1/responses` (Kaana ADR 0008, decision 6).
4
+ *
5
+ * It is a preference that can only NARROW. Oxy signs what a request may use and
6
+ * Kaana resolves the grant into routes; this object filters or reorders what
7
+ * the grant already admitted. It cannot add a provider, region, funding tier or
8
+ * price the grant did not, and a request it leaves with no route is refused
9
+ * rather than widened.
10
+ *
11
+ * The names are OpenRouter's, so a client written for OpenRouter's `provider`
12
+ * object works, and only the controls Kaana can honour are accepted:
13
+ * `sort: "price"`, `max_price`, `zdr`, `data_collection`, `preferred_*` with a
14
+ * percentile object, and `enforce_distillable_text` are refused by `.strict()`
15
+ * rather than silently ignored. `max_price` and the data policy stay Oxy's:
16
+ * Kaana never prices, and Oxy applies data policy when it computes the grant.
17
+ *
18
+ * Provider names here are Kaana provider slugs as a caller sees them in the
19
+ * catalogue. A response never names one.
20
+ */
21
+ import { z } from 'zod';
22
+ /** Quantization levels a route can be published at (the OpenRouter vocabulary). */
23
+ export declare const providerQuantizationSchema: z.ZodEnum<{
24
+ unknown: "unknown";
25
+ int4: "int4";
26
+ int8: "int8";
27
+ fp4: "fp4";
28
+ mxfp4: "mxfp4";
29
+ nvfp4: "nvfp4";
30
+ fp6: "fp6";
31
+ fp8: "fp8";
32
+ mxfp8: "mxfp8";
33
+ fp16: "fp16";
34
+ bf16: "bf16";
35
+ fp32: "fp32";
36
+ }>;
37
+ export declare const providerPreferencesSchema: z.ZodObject<{
38
+ order: z.ZodOptional<z.ZodArray<z.ZodString>>;
39
+ only: z.ZodOptional<z.ZodArray<z.ZodString>>;
40
+ ignore: z.ZodOptional<z.ZodArray<z.ZodString>>;
41
+ allow_fallbacks: z.ZodOptional<z.ZodBoolean>;
42
+ require_parameters: z.ZodOptional<z.ZodBoolean>;
43
+ quantizations: z.ZodOptional<z.ZodArray<z.ZodEnum<{
44
+ unknown: "unknown";
45
+ int4: "int4";
46
+ int8: "int8";
47
+ fp4: "fp4";
48
+ mxfp4: "mxfp4";
49
+ nvfp4: "nvfp4";
50
+ fp6: "fp6";
51
+ fp8: "fp8";
52
+ mxfp8: "mxfp8";
53
+ fp16: "fp16";
54
+ bf16: "bf16";
55
+ fp32: "fp32";
56
+ }>>>;
57
+ sort: z.ZodOptional<z.ZodEnum<{
58
+ latency: "latency";
59
+ throughput: "throughput";
60
+ }>>;
61
+ preferred_max_latency: z.ZodOptional<z.ZodNumber>;
62
+ preferred_min_throughput: z.ZodOptional<z.ZodNumber>;
63
+ }, z.core.$strict>;
64
+ export type ProviderPreferences = z.infer<typeof providerPreferencesSchema>;
65
+ /**
66
+ * An opaque caller-chosen string that groups requests sharing a prompt prefix.
67
+ * Kaana keeps such requests on the deployment that last served them while it is
68
+ * still admitted, so the provider's prompt cache stays warm. It is never stored
69
+ * with a prompt and never leaves Kaana.
70
+ */
71
+ export declare const promptCacheKeySchema: z.ZodString;
@@ -0,0 +1,75 @@
1
+ /**
2
+ * The `provider` object a caller may send on `POST /v1/chat/completions` and
3
+ * `POST /v1/responses` (Kaana ADR 0008, decision 6).
4
+ *
5
+ * It is a preference that can only NARROW. Oxy signs what a request may use and
6
+ * Kaana resolves the grant into routes; this object filters or reorders what
7
+ * the grant already admitted. It cannot add a provider, region, funding tier or
8
+ * price the grant did not, and a request it leaves with no route is refused
9
+ * rather than widened.
10
+ *
11
+ * The names are OpenRouter's, so a client written for OpenRouter's `provider`
12
+ * object works, and only the controls Kaana can honour are accepted:
13
+ * `sort: "price"`, `max_price`, `zdr`, `data_collection`, `preferred_*` with a
14
+ * percentile object, and `enforce_distillable_text` are refused by `.strict()`
15
+ * rather than silently ignored. `max_price` and the data policy stay Oxy's:
16
+ * Kaana never prices, and Oxy applies data policy when it computes the grant.
17
+ *
18
+ * Provider names here are Kaana provider slugs as a caller sees them in the
19
+ * catalogue. A response never names one.
20
+ */
21
+ import { z } from 'zod';
22
+ import { maxUtf16Length, minUtf16Length } from '../stringBounds.js';
23
+ const providerSlugSchema = z
24
+ .string()
25
+ .check(minUtf16Length(1))
26
+ .check(maxUtf16Length(64))
27
+ .regex(/^[a-z0-9][a-z0-9._-]*$/);
28
+ const providerListSchema = z.array(providerSlugSchema).min(1).max(16);
29
+ /** Quantization levels a route can be published at (the OpenRouter vocabulary). */
30
+ export const providerQuantizationSchema = z.enum([
31
+ 'int4',
32
+ 'int8',
33
+ 'fp4',
34
+ 'mxfp4',
35
+ 'nvfp4',
36
+ 'fp6',
37
+ 'fp8',
38
+ 'mxfp8',
39
+ 'fp16',
40
+ 'bf16',
41
+ 'fp32',
42
+ 'unknown',
43
+ ]);
44
+ export const providerPreferencesSchema = z
45
+ .object({
46
+ /** Providers to try first, in this order. Others still follow unless `allow_fallbacks` is false. */
47
+ order: providerListSchema.optional(),
48
+ /** Allow-list: only these providers may serve the request. */
49
+ only: providerListSchema.optional(),
50
+ /** Skip-list: these providers never serve the request. */
51
+ ignore: providerListSchema.optional(),
52
+ /**
53
+ * False keeps a single provider: the first of `order` that is admitted, or
54
+ * the best-ranked one. The request is never moved to another.
55
+ */
56
+ allow_fallbacks: z.boolean().optional(),
57
+ /** True keeps only routes that accept every parameter the request carries. */
58
+ require_parameters: z.boolean().optional(),
59
+ /** Keep only routes published at one of these quantizations; `unknown` admits unstated ones. */
60
+ quantizations: z.array(providerQuantizationSchema).min(1).max(12).optional(),
61
+ /** Prefer the route with the lowest recent latency or the highest recent throughput. */
62
+ sort: z.enum(['latency', 'throughput']).optional(),
63
+ /** Seconds. A route slower than this recently is tried later, never excluded (p50). */
64
+ preferred_max_latency: z.number().positive().max(600).optional(),
65
+ /** Output tokens per second. A route slower than this recently is tried later, never excluded (p50). */
66
+ preferred_min_throughput: z.number().positive().max(100_000).optional(),
67
+ })
68
+ .strict();
69
+ /**
70
+ * An opaque caller-chosen string that groups requests sharing a prompt prefix.
71
+ * Kaana keeps such requests on the deployment that last served them while it is
72
+ * still admitted, so the provider's prompt cache stays warm. It is never stored
73
+ * with a prompt and never leaves Kaana.
74
+ */
75
+ export const promptCacheKeySchema = z.string().check(minUtf16Length(1)).check(maxUtf16Length(256));
@@ -1365,6 +1365,7 @@ export declare const realtimePublicResponseDoneEventSchema: z.ZodObject<{
1365
1365
  audio_output_tokens: "audio_output_tokens";
1366
1366
  session_milliseconds: "session_milliseconds";
1367
1367
  input_transcription_milliseconds: "input_transcription_milliseconds";
1368
+ cache_write_input_tokens: "cache_write_input_tokens";
1368
1369
  }>;
1369
1370
  quantity: z.ZodNumber;
1370
1371
  }, z.core.$strict>>;
@@ -1468,6 +1469,7 @@ export declare const realtimePublicSessionClosedEventSchema: z.ZodObject<{
1468
1469
  audio_output_tokens: "audio_output_tokens";
1469
1470
  session_milliseconds: "session_milliseconds";
1470
1471
  input_transcription_milliseconds: "input_transcription_milliseconds";
1472
+ cache_write_input_tokens: "cache_write_input_tokens";
1471
1473
  }>;
1472
1474
  quantity: z.ZodNumber;
1473
1475
  }, z.core.$strict>>;
@@ -1922,6 +1924,7 @@ export declare const realtimePublicServerEventSchema: z.ZodDiscriminatedUnion<[z
1922
1924
  audio_output_tokens: "audio_output_tokens";
1923
1925
  session_milliseconds: "session_milliseconds";
1924
1926
  input_transcription_milliseconds: "input_transcription_milliseconds";
1927
+ cache_write_input_tokens: "cache_write_input_tokens";
1925
1928
  }>;
1926
1929
  quantity: z.ZodNumber;
1927
1930
  }, z.core.$strict>>;
@@ -2018,6 +2021,7 @@ export declare const realtimePublicServerEventSchema: z.ZodDiscriminatedUnion<[z
2018
2021
  audio_output_tokens: "audio_output_tokens";
2019
2022
  session_milliseconds: "session_milliseconds";
2020
2023
  input_transcription_milliseconds: "input_transcription_milliseconds";
2024
+ cache_write_input_tokens: "cache_write_input_tokens";
2021
2025
  }>;
2022
2026
  quantity: z.ZodNumber;
2023
2027
  }, z.core.$strict>>;
@@ -144,6 +144,34 @@ export declare const responsesRequestSchema: z.ZodObject<{
144
144
  }, z.core.$strict>>;
145
145
  labels: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
146
146
  clientRequestId: z.ZodOptional<z.ZodString>;
147
+ provider: z.ZodOptional<z.ZodObject<{
148
+ order: z.ZodOptional<z.ZodArray<z.ZodString>>;
149
+ only: z.ZodOptional<z.ZodArray<z.ZodString>>;
150
+ ignore: z.ZodOptional<z.ZodArray<z.ZodString>>;
151
+ allow_fallbacks: z.ZodOptional<z.ZodBoolean>;
152
+ require_parameters: z.ZodOptional<z.ZodBoolean>;
153
+ quantizations: z.ZodOptional<z.ZodArray<z.ZodEnum<{
154
+ unknown: "unknown";
155
+ int4: "int4";
156
+ int8: "int8";
157
+ fp4: "fp4";
158
+ mxfp4: "mxfp4";
159
+ nvfp4: "nvfp4";
160
+ fp6: "fp6";
161
+ fp8: "fp8";
162
+ mxfp8: "mxfp8";
163
+ fp16: "fp16";
164
+ bf16: "bf16";
165
+ fp32: "fp32";
166
+ }>>>;
167
+ sort: z.ZodOptional<z.ZodEnum<{
168
+ latency: "latency";
169
+ throughput: "throughput";
170
+ }>>;
171
+ preferred_max_latency: z.ZodOptional<z.ZodNumber>;
172
+ preferred_min_throughput: z.ZodOptional<z.ZodNumber>;
173
+ }, z.core.$strict>>;
174
+ promptCacheKey: z.ZodOptional<z.ZodString>;
147
175
  }, z.core.$strict>;
148
176
  /**
149
177
  * The non-streaming body. A streamed request answers with
@@ -239,6 +267,7 @@ export declare const responseSchema: z.ZodObject<{
239
267
  audio_output_tokens: "audio_output_tokens";
240
268
  session_milliseconds: "session_milliseconds";
241
269
  input_transcription_milliseconds: "input_transcription_milliseconds";
270
+ cache_write_input_tokens: "cache_write_input_tokens";
242
271
  }>;
243
272
  quantity: z.ZodNumber;
244
273
  }, z.core.$strict>>;
@@ -14,6 +14,7 @@ import { generationIdSchema, modelReferenceSchema, requestIdSchema } from './ide
14
14
  import { inferenceMessageSchema, inferenceReasoningSchema, requestLabelsSchema, responseFormatSchema, toolChoiceSchema, toolDefinitionSchema, } from './messages.js';
15
15
  import { usageQuantitySchema } from './money.js';
16
16
  import { routingPolicyReferenceSchema } from './policy.js';
17
+ import { promptCacheKeySchema, providerPreferencesSchema } from './providerPreferences.js';
17
18
  import { inferenceFinishReasonSchema } from './streamEvents.js';
18
19
  /**
19
20
  * What a `model` field may name: a concrete model reference
@@ -60,6 +61,10 @@ export const responsesRequestSchema = z
60
61
  labels: requestLabelsSchema.optional(),
61
62
  /** The caller's own correlation id, echoed on the response. */
62
63
  clientRequestId: z.string().check(minUtf16Length(1)).check(maxUtf16Length(128)).optional(),
64
+ /** Routing preferences that can only narrow what the grant admits (ADR 0008). */
65
+ provider: providerPreferencesSchema.optional(),
66
+ /** Keeps requests sharing a prompt prefix on one deployment while its cache is warm. */
67
+ promptCacheKey: promptCacheKeySchema.optional(),
63
68
  })
64
69
  .strict()
65
70
  .superRefine((request, ctx) => {
@@ -153,6 +153,7 @@ export declare const responseStreamUsageEventSchema: z.ZodObject<{
153
153
  audio_output_tokens: "audio_output_tokens";
154
154
  session_milliseconds: "session_milliseconds";
155
155
  input_transcription_milliseconds: "input_transcription_milliseconds";
156
+ cache_write_input_tokens: "cache_write_input_tokens";
156
157
  }>;
157
158
  quantity: z.ZodNumber;
158
159
  }, z.core.$strict>>;
@@ -284,6 +285,7 @@ export declare const responseStreamEventSchema: z.ZodDiscriminatedUnion<[z.ZodOb
284
285
  audio_output_tokens: "audio_output_tokens";
285
286
  session_milliseconds: "session_milliseconds";
286
287
  input_transcription_milliseconds: "input_transcription_milliseconds";
288
+ cache_write_input_tokens: "cache_write_input_tokens";
287
289
  }>;
288
290
  quantity: z.ZodNumber;
289
291
  }, z.core.$strict>>;
@@ -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.3.0";
103
+ export declare const INFERENCE_CONTRACT_VERSION = "8.5.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:
@@ -201,6 +201,19 @@ export declare const INFERENCE_CONTRACT_VERSION = "8.3.0";
201
201
  * `anthropicMessageSchema`, `anthropicStreamEventSchema`,
202
202
  * `anthropicErrorSchema`). Nothing in 8.2.0 changes, and the signed grant and
203
203
  * envelope are untouched: the endpoint is served as the `responses` operation.
204
+ *
205
+ * Contract set 8.4.0 is additive: the usage unit `cache_write_input_tokens`
206
+ * (input tokens written to a prompt cache, a sibling under the partition rule,
207
+ * default TTL only) and the optional `capabilities.unreported` (the boolean
208
+ * capabilities whose `false` is not evidence). Nothing in 8.3.0 changes and
209
+ * nothing emits either yet: a consumer on 8.3.0 refuses a usage report carrying
210
+ * the unit and a catalogue carrying the field, so Oxy reads them first.
211
+ *
212
+ * Contract set 8.5.0 is additive: the optional `provider` routing preference
213
+ * (`providerPreferencesSchema`) and the prompt-cache key (`prompt_cache_key`,
214
+ * `promptCacheKey`) on `POST /v1/chat/completions` and `POST /v1/responses`
215
+ * (Kaana ADR 0008). The preference only narrows what the grant admits. Nothing
216
+ * in 8.4.0 changes and the signed grant and envelope are untouched.
204
217
  */
205
218
  /** The public API's one origin and version. */
206
219
  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.3.0';
103
+ export const INFERENCE_CONTRACT_VERSION = '8.5.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:
@@ -201,6 +201,19 @@ export const INFERENCE_CONTRACT_VERSION = '8.3.0';
201
201
  * `anthropicMessageSchema`, `anthropicStreamEventSchema`,
202
202
  * `anthropicErrorSchema`). Nothing in 8.2.0 changes, and the signed grant and
203
203
  * envelope are untouched: the endpoint is served as the `responses` operation.
204
+ *
205
+ * Contract set 8.4.0 is additive: the usage unit `cache_write_input_tokens`
206
+ * (input tokens written to a prompt cache, a sibling under the partition rule,
207
+ * default TTL only) and the optional `capabilities.unreported` (the boolean
208
+ * capabilities whose `false` is not evidence). Nothing in 8.3.0 changes and
209
+ * nothing emits either yet: a consumer on 8.3.0 refuses a usage report carrying
210
+ * the unit and a catalogue carrying the field, so Oxy reads them first.
211
+ *
212
+ * Contract set 8.5.0 is additive: the optional `provider` routing preference
213
+ * (`providerPreferencesSchema`) and the prompt-cache key (`prompt_cache_key`,
214
+ * `promptCacheKey`) on `POST /v1/chat/completions` and `POST /v1/responses`
215
+ * (Kaana ADR 0008). The preference only narrows what the grant admits. Nothing
216
+ * in 8.4.0 changes and the signed grant and envelope are untouched.
204
217
  */
205
218
  /** The public API's one origin and version. */
206
219
  export const KAANA_API_BASE_URL = 'https://kaana.ai/v1';
package/openapi.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "openapi": "3.1.0",
3
3
  "info": {
4
4
  "title": "Kaana API",
5
- "version": "8.3.0",
5
+ "version": "8.5.0",
6
6
  "description": "Kaana inference API. Generated from @kaana.ai/contracts; the Zod source is the authority. Accounts, applications, oxy_sk_ keys, limits and billing are managed in Oxy Console: https://console.oxy.so"
7
7
  },
8
8
  "servers": [
@@ -3118,6 +3118,12 @@
3118
3118
  "type": "string",
3119
3119
  "minLength": 1,
3120
3120
  "maxLength": 64
3121
+ },
3122
+ "provider": {
3123
+ "$ref": "#/components/schemas/ProviderPreferences"
3124
+ },
3125
+ "prompt_cache_key": {
3126
+ "$ref": "#/components/schemas/PromptCacheKey"
3121
3127
  }
3122
3128
  },
3123
3129
  "required": [
@@ -4615,6 +4621,19 @@
4615
4621
  },
4616
4622
  "realtime": {
4617
4623
  "$ref": "#/components/schemas/ModelRealtimeCapabilities"
4624
+ },
4625
+ "unreported": {
4626
+ "type": "array",
4627
+ "items": {
4628
+ "type": "string",
4629
+ "enum": [
4630
+ "tools",
4631
+ "parallelToolCalls",
4632
+ "structuredOutput",
4633
+ "jsonMode",
4634
+ "promptCaching"
4635
+ ]
4636
+ }
4618
4637
  }
4619
4638
  },
4620
4639
  "required": [
@@ -5101,6 +5120,98 @@
5101
5120
  ],
5102
5121
  "additionalProperties": false
5103
5122
  },
5123
+ "PromptCacheKey": {
5124
+ "type": "string",
5125
+ "minLength": 1,
5126
+ "maxLength": 256
5127
+ },
5128
+ "ProviderPreferences": {
5129
+ "type": "object",
5130
+ "properties": {
5131
+ "order": {
5132
+ "minItems": 1,
5133
+ "maxItems": 16,
5134
+ "type": "array",
5135
+ "items": {
5136
+ "type": "string",
5137
+ "minLength": 1,
5138
+ "maxLength": 64,
5139
+ "pattern": "^[a-z0-9][a-z0-9._-]*$"
5140
+ }
5141
+ },
5142
+ "only": {
5143
+ "minItems": 1,
5144
+ "maxItems": 16,
5145
+ "type": "array",
5146
+ "items": {
5147
+ "type": "string",
5148
+ "minLength": 1,
5149
+ "maxLength": 64,
5150
+ "pattern": "^[a-z0-9][a-z0-9._-]*$"
5151
+ }
5152
+ },
5153
+ "ignore": {
5154
+ "minItems": 1,
5155
+ "maxItems": 16,
5156
+ "type": "array",
5157
+ "items": {
5158
+ "type": "string",
5159
+ "minLength": 1,
5160
+ "maxLength": 64,
5161
+ "pattern": "^[a-z0-9][a-z0-9._-]*$"
5162
+ }
5163
+ },
5164
+ "allow_fallbacks": {
5165
+ "type": "boolean"
5166
+ },
5167
+ "require_parameters": {
5168
+ "type": "boolean"
5169
+ },
5170
+ "quantizations": {
5171
+ "minItems": 1,
5172
+ "maxItems": 12,
5173
+ "type": "array",
5174
+ "items": {
5175
+ "$ref": "#/components/schemas/ProviderQuantization"
5176
+ }
5177
+ },
5178
+ "sort": {
5179
+ "type": "string",
5180
+ "enum": [
5181
+ "latency",
5182
+ "throughput"
5183
+ ]
5184
+ },
5185
+ "preferred_max_latency": {
5186
+ "type": "number",
5187
+ "exclusiveMinimum": 0,
5188
+ "maximum": 600
5189
+ },
5190
+ "preferred_min_throughput": {
5191
+ "type": "number",
5192
+ "exclusiveMinimum": 0,
5193
+ "maximum": 100000
5194
+ }
5195
+ },
5196
+ "additionalProperties": false
5197
+ },
5198
+ "ProviderQuantization": {
5199
+ "type": "string",
5200
+ "enum": [
5201
+ "int4",
5202
+ "int8",
5203
+ "fp4",
5204
+ "mxfp4",
5205
+ "nvfp4",
5206
+ "fp6",
5207
+ "fp8",
5208
+ "mxfp8",
5209
+ "fp16",
5210
+ "bf16",
5211
+ "fp32",
5212
+ "unknown"
5213
+ ]
5214
+ },
5104
5215
  "PublicErrorCode": {
5105
5216
  "type": "string",
5106
5217
  "enum": [
@@ -7599,6 +7710,12 @@
7599
7710
  "type": "string",
7600
7711
  "minLength": 1,
7601
7712
  "maxLength": 128
7713
+ },
7714
+ "provider": {
7715
+ "$ref": "#/components/schemas/ProviderPreferences"
7716
+ },
7717
+ "promptCacheKey": {
7718
+ "$ref": "#/components/schemas/PromptCacheKey"
7602
7719
  }
7603
7720
  },
7604
7721
  "required": [
@@ -8066,7 +8183,8 @@
8066
8183
  "cached_audio_input_tokens",
8067
8184
  "audio_output_tokens",
8068
8185
  "session_milliseconds",
8069
- "input_transcription_milliseconds"
8186
+ "input_transcription_milliseconds",
8187
+ "cache_write_input_tokens"
8070
8188
  ]
8071
8189
  },
8072
8190
  "Voice": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kaana.ai/contracts",
3
- "version": "8.3.0",
3
+ "version": "8.5.0",
4
4
  "description": "Kaana inference contract: the Zod schemas of the public API at https://kaana.ai/v1 and, under /internal, of the Oxy-Kaana grant, settlement and signed lane.",
5
5
  "type": "module",
6
6
  "sideEffects": false,