@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.
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/internal/catalogue.d.ts +32 -1
- package/dist/internal/decisions.d.ts +2 -0
- package/dist/internal/grant.d.ts +3 -0
- package/dist/internal/realtime.d.ts +6 -2
- package/dist/internal/request.d.ts +2 -2
- package/dist/internal/settlement.d.ts +2 -0
- package/dist/internal/streamEvents.d.ts +2 -0
- package/dist/internal/usage.d.ts +1 -0
- package/dist/public/anthropicMessages.d.ts +284 -0
- package/dist/public/anthropicMessages.js +274 -0
- package/dist/public/audio.d.ts +3 -0
- package/dist/public/catalogue.d.ts +28 -0
- package/dist/public/catalogue.js +40 -0
- package/dist/public/chatCompletions.d.ts +2 -2
- package/dist/public/decisions.d.ts +1 -0
- package/dist/public/generations.d.ts +6 -0
- package/dist/public/messages.d.ts +2 -2
- package/dist/public/messages.js +1 -1
- package/dist/public/money.d.ts +16 -1
- package/dist/public/money.js +11 -0
- package/dist/public/realtime.d.ts +11 -7
- package/dist/public/responses.d.ts +3 -2
- package/dist/public/streamEvents.d.ts +2 -0
- package/dist/public/version.d.ts +14 -1
- package/dist/public/version.js +14 -1
- package/openapi.json +1313 -165
- package/package.json +1 -1
|
@@ -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
|
+
]);
|
package/dist/public/audio.d.ts
CHANGED
|
@@ -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;
|
package/dist/public/catalogue.js
CHANGED
|
@@ -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
|
}>;
|
package/dist/public/messages.js
CHANGED
|
@@ -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(
|
|
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(),
|
package/dist/public/money.d.ts
CHANGED
|
@@ -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>>;
|
package/dist/public/money.js
CHANGED
|
@@ -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
|
/**
|