@kaana.ai/contracts 8.2.0 → 8.3.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
@@ -10,6 +10,7 @@
10
10
  * Accounts, applications, `oxy_sk_…` keys, limits and billing are managed in
11
11
  * Oxy Console (`https://console.oxy.so`), never here.
12
12
  */
13
+ export * from './public/anthropicMessages.js';
13
14
  export * from './public/audio.js';
14
15
  export * from './public/audioFormats.js';
15
16
  export * from './public/catalogue.js';
package/dist/index.js CHANGED
@@ -10,6 +10,7 @@
10
10
  * Accounts, applications, `oxy_sk_…` keys, limits and billing are managed in
11
11
  * Oxy Console (`https://console.oxy.so`), never here.
12
12
  */
13
+ export * from './public/anthropicMessages.js';
13
14
  export * from './public/audio.js';
14
15
  export * from './public/audioFormats.js';
15
16
  export * from './public/catalogue.js';
@@ -254,8 +254,8 @@ export declare const modelDeploymentSchema: z.ZodObject<{
254
254
  status: z.ZodEnum<{
255
255
  active: "active";
256
256
  retired: "retired";
257
- degraded: "degraded";
258
257
  disabled: "disabled";
258
+ degraded: "degraded";
259
259
  }>;
260
260
  dedicatedCapacity: z.ZodBoolean;
261
261
  priceVersionId: z.ZodOptional<z.ZodString>;
@@ -631,8 +631,8 @@ export declare const realtimeServerEventSchema: z.ZodDiscriminatedUnion<[z.ZodOb
631
631
  type: z.ZodLiteral<"message">;
632
632
  itemId: z.ZodOptional<z.ZodString>;
633
633
  role: z.ZodEnum<{
634
- user: "user";
635
634
  system: "system";
635
+ user: "user";
636
636
  assistant: "assistant";
637
637
  }>;
638
638
  content: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
@@ -682,8 +682,8 @@ export declare const realtimeServerEventSchema: z.ZodDiscriminatedUnion<[z.ZodOb
682
682
  type: z.ZodLiteral<"message">;
683
683
  itemId: z.ZodOptional<z.ZodString>;
684
684
  role: z.ZodEnum<{
685
- user: "user";
686
685
  system: "system";
686
+ user: "user";
687
687
  assistant: "assistant";
688
688
  }>;
689
689
  content: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
@@ -47,9 +47,9 @@ export declare const inferenceInputSchema: z.ZodDiscriminatedUnion<[z.ZodObject<
47
47
  format: z.ZodLiteral<"messages">;
48
48
  messages: z.ZodArray<z.ZodObject<{
49
49
  role: z.ZodEnum<{
50
- user: "user";
51
50
  system: "system";
52
51
  developer: "developer";
52
+ user: "user";
53
53
  assistant: "assistant";
54
54
  tool: "tool";
55
55
  }>;
@@ -231,9 +231,9 @@ export declare const inferenceRequestSchema: z.ZodObject<{
231
231
  format: z.ZodLiteral<"messages">;
232
232
  messages: z.ZodArray<z.ZodObject<{
233
233
  role: z.ZodEnum<{
234
- user: "user";
235
234
  system: "system";
236
235
  developer: "developer";
236
+ user: "user";
237
237
  assistant: "assistant";
238
238
  tool: "tool";
239
239
  }>;
@@ -0,0 +1,284 @@
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
+ export declare const anthropicMessagesRequestSchema: z.ZodObject<{
46
+ model: z.ZodUnion<readonly [z.ZodString, z.ZodEnum<{
47
+ medium: "medium";
48
+ high: "high";
49
+ auto: "auto";
50
+ instant: "instant";
51
+ xhigh: "xhigh";
52
+ pro: "pro";
53
+ ultra: "ultra";
54
+ }>]>;
55
+ max_tokens: z.ZodNumber;
56
+ messages: z.ZodArray<z.ZodObject<{
57
+ role: z.ZodEnum<{
58
+ user: "user";
59
+ assistant: "assistant";
60
+ }>;
61
+ content: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
62
+ type: z.ZodLiteral<"text">;
63
+ text: z.ZodString;
64
+ }, z.core.$strict>, z.ZodObject<{
65
+ type: z.ZodLiteral<"image">;
66
+ source: z.ZodDiscriminatedUnion<[z.ZodObject<{
67
+ type: z.ZodLiteral<"base64">;
68
+ media_type: z.ZodString;
69
+ data: z.ZodString;
70
+ }, z.core.$strict>, z.ZodObject<{
71
+ type: z.ZodLiteral<"url">;
72
+ url: z.ZodString;
73
+ }, z.core.$strict>], "type">;
74
+ }, z.core.$strict>, z.ZodObject<{
75
+ type: z.ZodLiteral<"tool_use">;
76
+ id: z.ZodString;
77
+ name: z.ZodString;
78
+ input: z.ZodRecord<z.ZodString, z.ZodUnknown>;
79
+ }, z.core.$strict>, z.ZodObject<{
80
+ type: z.ZodLiteral<"tool_result">;
81
+ tool_use_id: z.ZodString;
82
+ content: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
83
+ type: z.ZodLiteral<"text">;
84
+ text: z.ZodString;
85
+ }, z.core.$strict>, z.ZodObject<{
86
+ type: z.ZodLiteral<"image">;
87
+ source: z.ZodDiscriminatedUnion<[z.ZodObject<{
88
+ type: z.ZodLiteral<"base64">;
89
+ media_type: z.ZodString;
90
+ data: z.ZodString;
91
+ }, z.core.$strict>, z.ZodObject<{
92
+ type: z.ZodLiteral<"url">;
93
+ url: z.ZodString;
94
+ }, z.core.$strict>], "type">;
95
+ }, z.core.$strict>]>>]>>;
96
+ is_error: z.ZodOptional<z.ZodBoolean>;
97
+ }, z.core.$strict>]>>]>;
98
+ }, z.core.$strict>>;
99
+ system: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodObject<{
100
+ type: z.ZodLiteral<"text">;
101
+ text: z.ZodString;
102
+ }, z.core.$strict>>]>>;
103
+ temperature: z.ZodOptional<z.ZodNumber>;
104
+ top_p: z.ZodOptional<z.ZodNumber>;
105
+ top_k: z.ZodOptional<z.ZodNumber>;
106
+ stop_sequences: z.ZodOptional<z.ZodArray<z.ZodString>>;
107
+ stream: z.ZodOptional<z.ZodBoolean>;
108
+ tools: z.ZodOptional<z.ZodArray<z.ZodObject<{
109
+ type: z.ZodOptional<z.ZodLiteral<"custom">>;
110
+ name: z.ZodString;
111
+ description: z.ZodOptional<z.ZodString>;
112
+ input_schema: z.ZodRecord<z.ZodString, z.ZodUnknown>;
113
+ strict: z.ZodOptional<z.ZodBoolean>;
114
+ }, z.core.$strict>>>;
115
+ tool_choice: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
116
+ type: z.ZodLiteral<"auto">;
117
+ }, z.core.$strict>, z.ZodObject<{
118
+ type: z.ZodLiteral<"any">;
119
+ }, z.core.$strict>, z.ZodObject<{
120
+ type: z.ZodLiteral<"none">;
121
+ }, z.core.$strict>, z.ZodObject<{
122
+ type: z.ZodLiteral<"tool">;
123
+ name: z.ZodString;
124
+ }, z.core.$strict>], "type">>;
125
+ thinking: z.ZodOptional<z.ZodObject<{
126
+ type: z.ZodLiteral<"disabled">;
127
+ }, z.core.$strict>>;
128
+ output_config: z.ZodOptional<z.ZodObject<{
129
+ effort: z.ZodOptional<z.ZodEnum<{
130
+ low: "low";
131
+ medium: "medium";
132
+ high: "high";
133
+ }>>;
134
+ }, z.core.$strict>>;
135
+ metadata: z.ZodOptional<z.ZodObject<{
136
+ user_id: z.ZodOptional<z.ZodNullable<z.ZodString>>;
137
+ }, z.core.$strict>>;
138
+ }, z.core.$strict>;
139
+ /** The non-streaming body. The request id rides in `Kaana-Request-Id` and `Request-Id`. */
140
+ export declare const anthropicMessageSchema: z.ZodObject<{
141
+ id: z.ZodString;
142
+ type: z.ZodLiteral<"message">;
143
+ role: z.ZodLiteral<"assistant">;
144
+ model: z.ZodString;
145
+ content: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
146
+ type: z.ZodLiteral<"text">;
147
+ text: z.ZodString;
148
+ }, z.core.$strict>, z.ZodObject<{
149
+ type: z.ZodLiteral<"tool_use">;
150
+ id: z.ZodString;
151
+ name: z.ZodString;
152
+ input: z.ZodRecord<z.ZodString, z.ZodUnknown>;
153
+ }, z.core.$strict>], "type">>;
154
+ stop_reason: z.ZodEnum<{
155
+ refusal: "refusal";
156
+ tool_use: "tool_use";
157
+ max_tokens: "max_tokens";
158
+ end_turn: "end_turn";
159
+ }>;
160
+ stop_sequence: z.ZodLiteral<null>;
161
+ usage: z.ZodObject<{
162
+ input_tokens: z.ZodNumber;
163
+ output_tokens: z.ZodNumber;
164
+ cache_read_input_tokens: z.ZodOptional<z.ZodNumber>;
165
+ }, z.core.$strict>;
166
+ }, z.core.$strict>;
167
+ /** The error body, and the data of a stream's `event: error` frame. */
168
+ export declare const anthropicErrorSchema: z.ZodObject<{
169
+ type: z.ZodLiteral<"error">;
170
+ error: z.ZodObject<{
171
+ type: z.ZodEnum<{
172
+ request_too_large: "request_too_large";
173
+ invalid_request_error: "invalid_request_error";
174
+ authentication_error: "authentication_error";
175
+ billing_error: "billing_error";
176
+ permission_error: "permission_error";
177
+ not_found_error: "not_found_error";
178
+ rate_limit_error: "rate_limit_error";
179
+ timeout_error: "timeout_error";
180
+ overloaded_error: "overloaded_error";
181
+ api_error: "api_error";
182
+ }>;
183
+ message: z.ZodString;
184
+ }, z.core.$strict>;
185
+ request_id: z.ZodOptional<z.ZodString>;
186
+ }, z.core.$strict>;
187
+ /**
188
+ * One frame of a streamed message: `event: <type>` and this as its data. The
189
+ * input tokens are known only when the route reports usage, so `message_start`
190
+ * carries zeros and the final `message_delta` the measured totals. A stream that
191
+ * fails after its first frame ends with an `error` frame and no `message_stop`.
192
+ */
193
+ export declare const anthropicStreamEventSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
194
+ type: z.ZodLiteral<"message_start">;
195
+ message: z.ZodObject<{
196
+ id: z.ZodString;
197
+ type: z.ZodLiteral<"message">;
198
+ role: z.ZodLiteral<"assistant">;
199
+ model: z.ZodString;
200
+ content: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
201
+ type: z.ZodLiteral<"text">;
202
+ text: z.ZodString;
203
+ }, z.core.$strict>, z.ZodObject<{
204
+ type: z.ZodLiteral<"tool_use">;
205
+ id: z.ZodString;
206
+ name: z.ZodString;
207
+ input: z.ZodRecord<z.ZodString, z.ZodUnknown>;
208
+ }, z.core.$strict>], "type">>;
209
+ stop_reason: z.ZodLiteral<null>;
210
+ stop_sequence: z.ZodLiteral<null>;
211
+ usage: z.ZodObject<{
212
+ input_tokens: z.ZodNumber;
213
+ output_tokens: z.ZodNumber;
214
+ cache_read_input_tokens: z.ZodOptional<z.ZodNumber>;
215
+ }, z.core.$strict>;
216
+ }, z.core.$strict>;
217
+ }, z.core.$strict>, z.ZodObject<{
218
+ type: z.ZodLiteral<"content_block_start">;
219
+ index: z.ZodNumber;
220
+ content_block: z.ZodDiscriminatedUnion<[z.ZodObject<{
221
+ type: z.ZodLiteral<"text">;
222
+ text: z.ZodLiteral<"">;
223
+ }, z.core.$strict>, z.ZodObject<{
224
+ type: z.ZodLiteral<"tool_use">;
225
+ id: z.ZodString;
226
+ name: z.ZodString;
227
+ input: z.ZodObject<{}, z.core.$strict>;
228
+ }, z.core.$strict>], "type">;
229
+ }, z.core.$strict>, z.ZodObject<{
230
+ type: z.ZodLiteral<"content_block_delta">;
231
+ index: z.ZodNumber;
232
+ delta: z.ZodDiscriminatedUnion<[z.ZodObject<{
233
+ type: z.ZodLiteral<"text_delta">;
234
+ text: z.ZodString;
235
+ }, z.core.$strict>, z.ZodObject<{
236
+ type: z.ZodLiteral<"input_json_delta">;
237
+ partial_json: z.ZodString;
238
+ }, z.core.$strict>], "type">;
239
+ }, z.core.$strict>, z.ZodObject<{
240
+ type: z.ZodLiteral<"content_block_stop">;
241
+ index: z.ZodNumber;
242
+ }, z.core.$strict>, z.ZodObject<{
243
+ type: z.ZodLiteral<"message_delta">;
244
+ delta: z.ZodObject<{
245
+ stop_reason: z.ZodEnum<{
246
+ refusal: "refusal";
247
+ tool_use: "tool_use";
248
+ max_tokens: "max_tokens";
249
+ end_turn: "end_turn";
250
+ }>;
251
+ stop_sequence: z.ZodLiteral<null>;
252
+ }, z.core.$strict>;
253
+ usage: z.ZodObject<{
254
+ input_tokens: z.ZodNumber;
255
+ output_tokens: z.ZodNumber;
256
+ cache_read_input_tokens: z.ZodOptional<z.ZodNumber>;
257
+ }, z.core.$strict>;
258
+ }, z.core.$strict>, z.ZodObject<{
259
+ type: z.ZodLiteral<"message_stop">;
260
+ }, z.core.$strict>, z.ZodObject<{
261
+ type: z.ZodLiteral<"ping">;
262
+ }, z.core.$strict>, z.ZodObject<{
263
+ type: z.ZodLiteral<"error">;
264
+ error: z.ZodObject<{
265
+ type: z.ZodEnum<{
266
+ request_too_large: "request_too_large";
267
+ invalid_request_error: "invalid_request_error";
268
+ authentication_error: "authentication_error";
269
+ billing_error: "billing_error";
270
+ permission_error: "permission_error";
271
+ not_found_error: "not_found_error";
272
+ rate_limit_error: "rate_limit_error";
273
+ timeout_error: "timeout_error";
274
+ overloaded_error: "overloaded_error";
275
+ api_error: "api_error";
276
+ }>;
277
+ message: z.ZodString;
278
+ }, z.core.$strict>;
279
+ request_id: z.ZodOptional<z.ZodString>;
280
+ }, z.core.$strict>], "type">;
281
+ export type AnthropicMessagesRequest = z.infer<typeof anthropicMessagesRequestSchema>;
282
+ export type AnthropicMessage = z.infer<typeof anthropicMessageSchema>;
283
+ export type AnthropicError = z.infer<typeof anthropicErrorSchema>;
284
+ export type AnthropicStreamEvent = z.infer<typeof anthropicStreamEventSchema>;
@@ -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
+ ]);
@@ -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
  }>;
@@ -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(),