@kaana.ai/contracts 8.2.0 → 8.4.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.
@@ -0,0 +1,274 @@
1
+ /**
2
+ * `POST /v1/messages` — the Anthropic-Messages-compatible surface.
3
+ *
4
+ * It speaks the flat Anthropic request, response and stream shapes so an
5
+ * unmodified Anthropic SDK or Claude Code works with
6
+ * `ANTHROPIC_BASE_URL=https://kaana.ai` and an `oxy_sk_…` key (sent as
7
+ * `x-api-key` or as `Authorization: Bearer`). Like `/v1/chat/completions` it
8
+ * gains NO Kaana-specific request field, and it is `.strict()` everywhere: a
9
+ * stock SDK sending a parameter Kaana does not implement is told so rather than
10
+ * having it silently dropped.
11
+ *
12
+ * ## What is refused, and why
13
+ *
14
+ * - **`cache_control`, anywhere** (on a block, a tool, `system` or the
15
+ * request). Kaana's usage units have no unit for a cache WRITE (see the
16
+ * Anthropic adapter's usage meter): a cache write is billed at a premium
17
+ * over input, so honouring the marker while folding the write into
18
+ * `input_tokens` would report less than the request cost. The marker is
19
+ * refused, by name and path, instead of being dropped.
20
+ * - **`thinking` other than `{ type: 'disabled' }`.** The contract's reasoning
21
+ * control is an effort (`low`, `medium`, `high`), not a token budget, and a
22
+ * thinking block has no part in a message: reasoning is private and is never
23
+ * returned. Reasoning effort is asked with `output_config.effort`, which
24
+ * maps one to one. A `thinking` or `redacted_thinking` block in a message is
25
+ * refused for the same reason.
26
+ * - **Server tools** (`web_search`, `bash`, `text_editor`, …), `mcp_servers`,
27
+ * `container`, `service_tier`, `disable_parallel_tool_use`, `document`
28
+ * blocks and any other member this file does not name.
29
+ * - **An image `url` source**: nothing fetches an image URL (ADR 0007); a
30
+ * `base64` source is carried inline under the image rules.
31
+ *
32
+ * `stop_reason: 'stop_sequence'` is never produced: the finish reason Kaana
33
+ * measures does not say WHICH stop sequence ended the turn, and `stop_sequence`
34
+ * would then have to name one. A turn that ended on a stop sequence reports
35
+ * `end_turn`.
36
+ *
37
+ * `metadata.user_id` is accepted and neither forwarded nor stored: it is an
38
+ * end-user identifier, and Kaana persists none.
39
+ *
40
+ * `usage` is derived from the measured units: `input_tokens`, `output_tokens`
41
+ * (reasoning included, as Anthropic counts it) and, only when the route
42
+ * measured it, `cache_read_input_tokens`. There is no `cache_creation_*`.
43
+ */
44
+ import { z } from 'zod';
45
+ import { maxUtf16Length, minUtf16Length } from '../stringBounds.js';
46
+ import { reasoningEffortSchema } from './catalogue.js';
47
+ import { modelTargetSchema } from './responses.js';
48
+ const nonEmpty = (max) => z.string().check(minUtf16Length(1)).check(maxUtf16Length(max));
49
+ const textBlockSchema = z.object({ type: z.literal('text'), text: z.string() }).strict();
50
+ const imageBlockSchema = z
51
+ .object({
52
+ type: z.literal('image'),
53
+ source: z.discriminatedUnion('type', [
54
+ z
55
+ .object({
56
+ type: z.literal('base64'),
57
+ media_type: nonEmpty(255),
58
+ data: z.string().check(minUtf16Length(1)),
59
+ })
60
+ .strict(),
61
+ /** Parses so the refusal can name it; Kaana fetches no image URL. */
62
+ z.object({ type: z.literal('url'), url: nonEmpty(4096) }).strict(),
63
+ ]),
64
+ })
65
+ .strict();
66
+ const toolUseBlockSchema = z
67
+ .object({
68
+ type: z.literal('tool_use'),
69
+ id: nonEmpty(128),
70
+ name: nonEmpty(128),
71
+ input: z.record(z.string(), z.unknown()),
72
+ })
73
+ .strict();
74
+ const toolResultBlockSchema = z
75
+ .object({
76
+ type: z.literal('tool_result'),
77
+ tool_use_id: nonEmpty(128),
78
+ content: z
79
+ .union([z.string(), z.array(z.union([textBlockSchema, imageBlockSchema]))])
80
+ .optional(),
81
+ /**
82
+ * Accepted. The contract's tool message has no error flag, so the result's
83
+ * own content is what the model reads; the flag is not forwarded.
84
+ */
85
+ is_error: z.boolean().optional(),
86
+ })
87
+ .strict();
88
+ const messageSchema = z
89
+ .object({
90
+ role: z.enum(['user', 'assistant']),
91
+ content: z.union([
92
+ z.string(),
93
+ z
94
+ .array(z.union([textBlockSchema, imageBlockSchema, toolUseBlockSchema, toolResultBlockSchema]))
95
+ .min(1),
96
+ ]),
97
+ })
98
+ .strict()
99
+ .superRefine((message, ctx) => {
100
+ if (typeof message.content === 'string')
101
+ return;
102
+ for (const [index, block] of message.content.entries()) {
103
+ const allowed = message.role === 'assistant'
104
+ ? block.type === 'text' || block.type === 'tool_use'
105
+ : block.type !== 'tool_use';
106
+ if (!allowed) {
107
+ ctx.addIssue({
108
+ code: 'custom',
109
+ path: ['content', index, 'type'],
110
+ message: `a ${message.role} message does not carry a ${block.type} block`,
111
+ });
112
+ }
113
+ }
114
+ });
115
+ const toolSchema = z
116
+ .object({
117
+ type: z.literal('custom').optional(),
118
+ name: nonEmpty(128),
119
+ description: z.string().check(maxUtf16Length(32768)).optional(),
120
+ input_schema: z.record(z.string(), z.unknown()),
121
+ strict: z.boolean().optional(),
122
+ })
123
+ .strict();
124
+ const toolChoiceSchema = z.discriminatedUnion('type', [
125
+ z.object({ type: z.literal('auto') }).strict(),
126
+ z.object({ type: z.literal('any') }).strict(),
127
+ z.object({ type: z.literal('none') }).strict(),
128
+ z.object({ type: z.literal('tool'), name: nonEmpty(128) }).strict(),
129
+ ]);
130
+ export const anthropicMessagesRequestSchema = z
131
+ .object({
132
+ /** A model reference (`publisher/model[@revision]`) or a power level. */
133
+ model: modelTargetSchema,
134
+ /** Required, as Anthropic requires it. */
135
+ max_tokens: z.number().int().positive().safe(),
136
+ messages: z.array(messageSchema).min(1),
137
+ system: z.union([z.string(), z.array(textBlockSchema)]).optional(),
138
+ temperature: z.number().min(0).max(1).optional(),
139
+ top_p: z.number().min(0).max(1).optional(),
140
+ top_k: z.number().int().positive().safe().optional(),
141
+ stop_sequences: z.array(nonEmpty(256)).max(8).optional(),
142
+ stream: z.boolean().optional(),
143
+ tools: z.array(toolSchema).max(128).optional(),
144
+ tool_choice: toolChoiceSchema.optional(),
145
+ /** Only "off" is accepted: see the file comment. */
146
+ thinking: z
147
+ .object({ type: z.literal('disabled') })
148
+ .strict()
149
+ .optional(),
150
+ /** `effort` is the contract's reasoning effort; no other member is carried. */
151
+ output_config: z.object({ effort: reasoningEffortSchema.optional() }).strict().optional(),
152
+ /** Accepted and not forwarded or stored. */
153
+ metadata: z
154
+ .object({ user_id: z.string().check(maxUtf16Length(512)).nullable().optional() })
155
+ .strict()
156
+ .optional(),
157
+ })
158
+ .strict()
159
+ .superRefine((request, ctx) => {
160
+ if (request.tool_choice !== undefined && (request.tools ?? []).length === 0) {
161
+ ctx.addIssue({
162
+ code: 'custom',
163
+ path: ['tool_choice'],
164
+ message: 'a tool choice requires at least one tool definition',
165
+ });
166
+ }
167
+ });
168
+ const usageSchema = z
169
+ .object({
170
+ input_tokens: z.number().int().nonnegative(),
171
+ output_tokens: z.number().int().nonnegative(),
172
+ /** Present only when the route measured a cache read. */
173
+ cache_read_input_tokens: z.number().int().nonnegative().optional(),
174
+ })
175
+ .strict();
176
+ const stopReasonSchema = z.enum(['end_turn', 'max_tokens', 'tool_use', 'refusal']);
177
+ const outputBlockSchema = z.discriminatedUnion('type', [
178
+ textBlockSchema,
179
+ toolUseBlockSchema.extend({ input: z.record(z.string(), z.unknown()) }),
180
+ ]);
181
+ const messageBodySchema = z.object({
182
+ id: nonEmpty(256),
183
+ type: z.literal('message'),
184
+ role: z.literal('assistant'),
185
+ /** The revision that served the request. */
186
+ model: nonEmpty(256),
187
+ });
188
+ /** The non-streaming body. The request id rides in `Kaana-Request-Id` and `Request-Id`. */
189
+ export const anthropicMessageSchema = messageBodySchema
190
+ .extend({
191
+ content: z.array(outputBlockSchema),
192
+ stop_reason: stopReasonSchema,
193
+ stop_sequence: z.literal(null),
194
+ usage: usageSchema,
195
+ })
196
+ .strict();
197
+ /** The error body, and the data of a stream's `event: error` frame. */
198
+ export const anthropicErrorSchema = z
199
+ .object({
200
+ type: z.literal('error'),
201
+ error: z
202
+ .object({
203
+ type: z.enum([
204
+ 'invalid_request_error',
205
+ 'authentication_error',
206
+ 'billing_error',
207
+ 'permission_error',
208
+ 'not_found_error',
209
+ 'request_too_large',
210
+ 'rate_limit_error',
211
+ 'timeout_error',
212
+ 'overloaded_error',
213
+ 'api_error',
214
+ ]),
215
+ message: nonEmpty(4096),
216
+ })
217
+ .strict(),
218
+ request_id: nonEmpty(256).optional(),
219
+ })
220
+ .strict();
221
+ /**
222
+ * One frame of a streamed message: `event: <type>` and this as its data. The
223
+ * input tokens are known only when the route reports usage, so `message_start`
224
+ * carries zeros and the final `message_delta` the measured totals. A stream that
225
+ * fails after its first frame ends with an `error` frame and no `message_stop`.
226
+ */
227
+ export const anthropicStreamEventSchema = z.discriminatedUnion('type', [
228
+ z
229
+ .object({
230
+ type: z.literal('message_start'),
231
+ message: messageBodySchema
232
+ .extend({
233
+ content: z.array(outputBlockSchema).length(0),
234
+ stop_reason: z.literal(null),
235
+ stop_sequence: z.literal(null),
236
+ usage: usageSchema,
237
+ })
238
+ .strict(),
239
+ })
240
+ .strict(),
241
+ z
242
+ .object({
243
+ type: z.literal('content_block_start'),
244
+ index: z.number().int().nonnegative(),
245
+ content_block: z.discriminatedUnion('type', [
246
+ z.object({ type: z.literal('text'), text: z.literal('') }).strict(),
247
+ toolUseBlockSchema.extend({ input: z.object({}).strict() }),
248
+ ]),
249
+ })
250
+ .strict(),
251
+ z
252
+ .object({
253
+ type: z.literal('content_block_delta'),
254
+ index: z.number().int().nonnegative(),
255
+ delta: z.discriminatedUnion('type', [
256
+ z.object({ type: z.literal('text_delta'), text: z.string() }).strict(),
257
+ z.object({ type: z.literal('input_json_delta'), partial_json: z.string() }).strict(),
258
+ ]),
259
+ })
260
+ .strict(),
261
+ z
262
+ .object({ type: z.literal('content_block_stop'), index: z.number().int().nonnegative() })
263
+ .strict(),
264
+ z
265
+ .object({
266
+ type: z.literal('message_delta'),
267
+ delta: z.object({ stop_reason: stopReasonSchema, stop_sequence: z.literal(null) }).strict(),
268
+ usage: usageSchema,
269
+ })
270
+ .strict(),
271
+ z.object({ type: z.literal('message_stop') }).strict(),
272
+ z.object({ type: z.literal('ping') }).strict(),
273
+ anthropicErrorSchema,
274
+ ]);
@@ -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({
@@ -21,9 +21,9 @@ import { z } from 'zod';
21
21
  */
22
22
  export declare const chatCompletionMessageSchema: z.ZodObject<{
23
23
  role: z.ZodEnum<{
24
- user: "user";
25
24
  system: "system";
26
25
  developer: "developer";
26
+ user: "user";
27
27
  assistant: "assistant";
28
28
  tool: "tool";
29
29
  }>;
@@ -93,9 +93,9 @@ export declare const chatCompletionsRequestSchema: z.ZodObject<{
93
93
  }>]>;
94
94
  messages: z.ZodArray<z.ZodObject<{
95
95
  role: z.ZodEnum<{
96
- user: "user";
97
96
  system: "system";
98
97
  developer: "developer";
98
+ user: "user";
99
99
  assistant: "assistant";
100
100
  tool: "tool";
101
101
  }>;
@@ -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>>;
@@ -163,9 +163,9 @@ export declare const inferenceToolCallSchema: z.ZodObject<{
163
163
  arguments: z.ZodString;
164
164
  }, z.core.$strict>;
165
165
  export declare const inferenceMessageRoleSchema: z.ZodEnum<{
166
- user: "user";
167
166
  system: "system";
168
167
  developer: "developer";
168
+ user: "user";
169
169
  assistant: "assistant";
170
170
  tool: "tool";
171
171
  }>;
@@ -179,9 +179,9 @@ export declare const inferenceMessageRoleSchema: z.ZodEnum<{
179
179
  */
180
180
  export declare const inferenceMessageSchema: z.ZodObject<{
181
181
  role: z.ZodEnum<{
182
- user: "user";
183
182
  system: "system";
184
183
  developer: "developer";
184
+ user: "user";
185
185
  assistant: "assistant";
186
186
  tool: "tool";
187
187
  }>;
@@ -296,7 +296,7 @@ export const toolDefinitionSchema = z
296
296
  .object({
297
297
  type: z.literal('function'),
298
298
  name: z.string().check(minUtf16Length(1)).check(maxUtf16Length(128)),
299
- description: z.string().check(maxUtf16Length(2000)).optional(),
299
+ description: z.string().check(maxUtf16Length(32768)).optional(),
300
300
  parameters: z.record(z.string(), z.unknown()),
301
301
  /** Ask the provider to enforce the schema, where it supports enforcement. */
302
302
  strict: z.boolean().optional(),
@@ -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
  /**