@kaana.ai/contracts 8.5.0 → 8.7.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/internal/request.d.ts +12 -2
- package/dist/internal/streamEvents.d.ts +1 -0
- package/dist/public/anthropicMessages.d.ts +89 -14
- package/dist/public/anthropicMessages.js +116 -20
- package/dist/public/chatCompletions.d.ts +8 -0
- package/dist/public/messages.d.ts +57 -26
- package/dist/public/messages.js +74 -29
- package/dist/public/responses.d.ts +12 -2
- package/dist/public/streamEvents.d.ts +2 -0
- package/dist/public/streamEvents.js +8 -0
- package/dist/public/version.d.ts +10 -1
- package/dist/public/version.js +10 -1
- package/openapi.json +333 -14
- package/package.json +1 -1
|
@@ -95,6 +95,10 @@ export declare const inferenceInputSchema: z.ZodDiscriminatedUnion<[z.ZodObject<
|
|
|
95
95
|
}, z.core.$strict>, z.ZodObject<{
|
|
96
96
|
type: z.ZodLiteral<"refusal">;
|
|
97
97
|
text: z.ZodString;
|
|
98
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
99
|
+
type: z.ZodLiteral<"reasoning">;
|
|
100
|
+
text: z.ZodOptional<z.ZodString>;
|
|
101
|
+
opaque: z.ZodOptional<z.ZodString>;
|
|
98
102
|
}, z.core.$strict>], "type">>;
|
|
99
103
|
name: z.ZodOptional<z.ZodString>;
|
|
100
104
|
toolCallId: z.ZodOptional<z.ZodString>;
|
|
@@ -279,6 +283,10 @@ export declare const inferenceRequestSchema: z.ZodObject<{
|
|
|
279
283
|
}, z.core.$strict>, z.ZodObject<{
|
|
280
284
|
type: z.ZodLiteral<"refusal">;
|
|
281
285
|
text: z.ZodString;
|
|
286
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
287
|
+
type: z.ZodLiteral<"reasoning">;
|
|
288
|
+
text: z.ZodOptional<z.ZodString>;
|
|
289
|
+
opaque: z.ZodOptional<z.ZodString>;
|
|
282
290
|
}, z.core.$strict>], "type">>;
|
|
283
291
|
name: z.ZodOptional<z.ZodString>;
|
|
284
292
|
toolCallId: z.ZodOptional<z.ZodString>;
|
|
@@ -307,11 +315,13 @@ export declare const inferenceRequestSchema: z.ZodObject<{
|
|
|
307
315
|
stopSequences: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
308
316
|
}, z.core.$strict>;
|
|
309
317
|
reasoning: z.ZodOptional<z.ZodObject<{
|
|
310
|
-
effort: z.ZodEnum<{
|
|
318
|
+
effort: z.ZodOptional<z.ZodEnum<{
|
|
311
319
|
low: "low";
|
|
312
320
|
medium: "medium";
|
|
313
321
|
high: "high";
|
|
314
|
-
}
|
|
322
|
+
}>>;
|
|
323
|
+
maxTokens: z.ZodOptional<z.ZodNumber>;
|
|
324
|
+
exclude: z.ZodOptional<z.ZodBoolean>;
|
|
315
325
|
}, z.core.$strict>>;
|
|
316
326
|
speech: z.ZodOptional<z.ZodObject<{
|
|
317
327
|
voice: z.ZodString;
|
|
@@ -253,6 +253,7 @@ export declare const inferenceStreamEventSchema: z.ZodDiscriminatedUnion<[z.ZodO
|
|
|
253
253
|
output_audio_transcript: "output_audio_transcript";
|
|
254
254
|
}>;
|
|
255
255
|
text: z.ZodString;
|
|
256
|
+
opaque: z.ZodOptional<z.ZodString>;
|
|
256
257
|
}, z.core.$strip>, z.ZodObject<{
|
|
257
258
|
schemaVersion: z.ZodLiteral<1>;
|
|
258
259
|
type: z.ZodLiteral<"audio">;
|
|
@@ -11,24 +11,50 @@
|
|
|
11
11
|
*
|
|
12
12
|
* ## What is refused, and why
|
|
13
13
|
*
|
|
14
|
-
* - **`
|
|
15
|
-
*
|
|
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.
|
|
14
|
+
* - **`thinking.display`** and every other `thinking` member this file does
|
|
15
|
+
* not name.
|
|
26
16
|
* - **Server tools** (`web_search`, `bash`, `text_editor`, …), `mcp_servers`,
|
|
27
17
|
* `container`, `service_tier`, `disable_parallel_tool_use`, `document`
|
|
28
18
|
* blocks and any other member this file does not name.
|
|
29
19
|
* - **An image `url` source**: nothing fetches an image URL (ADR 0007); a
|
|
30
20
|
* `base64` source is carried inline under the image rules.
|
|
31
21
|
*
|
|
22
|
+
* ## `cache_control`: accepted and IGNORED
|
|
23
|
+
*
|
|
24
|
+
* Claude Code puts a `cache_control` marker on every request, so refusing it
|
|
25
|
+
* made the endpoint unusable by its main client. The marker is accepted wherever
|
|
26
|
+
* the dialect puts it (the request, `system`, a tool, a content block) and is
|
|
27
|
+
* NOT honoured: Kaana forwards no cache hint, so no cache write happens and the
|
|
28
|
+
* usage it reports stays exactly what the request cost. The only effect is the
|
|
29
|
+
* one the caller asked for and does not get: no prompt-cache discount on a write
|
|
30
|
+
* (reads that a provider caches on its own are still metered as
|
|
31
|
+
* `cache_read_input_tokens`). A request whose marker was ignored is answered
|
|
32
|
+
* with `Kaana-Ignored-Parameters: cache_control`. Honouring it needs a priced
|
|
33
|
+
* cache-write unit (`cache_write_input_tokens`, contract 8.4.0) that nothing
|
|
34
|
+
* emits yet.
|
|
35
|
+
*
|
|
36
|
+
* The same holds for three more members Claude Code sends: `context_management`,
|
|
37
|
+
* `thinking.display` and `tools[].defer_loading`. Each is a hint or a beta that
|
|
38
|
+
* changes how a provider trims, shows or loads, never what a request means or
|
|
39
|
+
* costs; each present one is named in `Kaana-Ignored-Parameters`. Any other
|
|
40
|
+
* member this file does not name is still refused.
|
|
41
|
+
*
|
|
42
|
+
* ## Reasoning (contract set 8.6.0, ADR 0009 decision 2)
|
|
43
|
+
*
|
|
44
|
+
* `thinking: {type: 'enabled', budget_tokens}` is the contract's
|
|
45
|
+
* `reasoning.maxTokens` and `thinking: {type: 'adaptive'}` opts in to reasoning
|
|
46
|
+
* with the route's own sizing; `output_config.effort` is `reasoning.effort`, and
|
|
47
|
+
* a budget beside an effort is refused (the contract treats them as
|
|
48
|
+
* alternatives). A route that cannot take a budget refuses it by name.
|
|
49
|
+
*
|
|
50
|
+
* An answer carries `thinking` blocks before its text and tool calls, and an
|
|
51
|
+
* assistant message sent back carries them again, UNMODIFIED, ahead of its
|
|
52
|
+
* `tool_use` blocks. The block's `signature` is the contract's opaque
|
|
53
|
+
* continuation token (the sealed string a `reasoning` part carries), which is
|
|
54
|
+
* why a stock Anthropic SDK continues a tool turn without knowing anything
|
|
55
|
+
* else: it returns what it received. `redacted_thinking` is accepted on the way
|
|
56
|
+
* in (its `data` is the same token) and never produced.
|
|
57
|
+
*
|
|
32
58
|
* `stop_reason: 'stop_sequence'` is never produced: the finish reason Kaana
|
|
33
59
|
* measures does not say WHICH stop sequence ended the turn, and `stop_sequence`
|
|
34
60
|
* would then have to name one. A turn that ended on a stop sequence reports
|
|
@@ -55,14 +81,17 @@ export declare const anthropicMessagesRequestSchema: z.ZodObject<{
|
|
|
55
81
|
max_tokens: z.ZodNumber;
|
|
56
82
|
messages: z.ZodArray<z.ZodObject<{
|
|
57
83
|
role: z.ZodEnum<{
|
|
84
|
+
system: "system";
|
|
58
85
|
user: "user";
|
|
59
86
|
assistant: "assistant";
|
|
60
87
|
}>;
|
|
61
88
|
content: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
|
|
62
89
|
type: z.ZodLiteral<"text">;
|
|
63
90
|
text: z.ZodString;
|
|
91
|
+
cache_control: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
64
92
|
}, z.core.$strict>, z.ZodObject<{
|
|
65
93
|
type: z.ZodLiteral<"image">;
|
|
94
|
+
cache_control: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
66
95
|
source: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
67
96
|
type: z.ZodLiteral<"base64">;
|
|
68
97
|
media_type: z.ZodString;
|
|
@@ -76,14 +105,17 @@ export declare const anthropicMessagesRequestSchema: z.ZodObject<{
|
|
|
76
105
|
id: z.ZodString;
|
|
77
106
|
name: z.ZodString;
|
|
78
107
|
input: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
108
|
+
cache_control: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
79
109
|
}, z.core.$strict>, z.ZodObject<{
|
|
80
110
|
type: z.ZodLiteral<"tool_result">;
|
|
81
111
|
tool_use_id: z.ZodString;
|
|
82
112
|
content: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
|
|
83
113
|
type: z.ZodLiteral<"text">;
|
|
84
114
|
text: z.ZodString;
|
|
115
|
+
cache_control: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
85
116
|
}, z.core.$strict>, z.ZodObject<{
|
|
86
117
|
type: z.ZodLiteral<"image">;
|
|
118
|
+
cache_control: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
87
119
|
source: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
88
120
|
type: z.ZodLiteral<"base64">;
|
|
89
121
|
media_type: z.ZodString;
|
|
@@ -94,12 +126,22 @@ export declare const anthropicMessagesRequestSchema: z.ZodObject<{
|
|
|
94
126
|
}, z.core.$strict>], "type">;
|
|
95
127
|
}, z.core.$strict>]>>]>>;
|
|
96
128
|
is_error: z.ZodOptional<z.ZodBoolean>;
|
|
129
|
+
cache_control: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
130
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
131
|
+
type: z.ZodLiteral<"thinking">;
|
|
132
|
+
thinking: z.ZodString;
|
|
133
|
+
signature: z.ZodString;
|
|
134
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
135
|
+
type: z.ZodLiteral<"redacted_thinking">;
|
|
136
|
+
data: z.ZodString;
|
|
97
137
|
}, z.core.$strict>]>>]>;
|
|
98
138
|
}, z.core.$strict>>;
|
|
99
139
|
system: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodObject<{
|
|
100
140
|
type: z.ZodLiteral<"text">;
|
|
101
141
|
text: z.ZodString;
|
|
142
|
+
cache_control: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
102
143
|
}, z.core.$strict>>]>>;
|
|
144
|
+
cache_control: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
103
145
|
temperature: z.ZodOptional<z.ZodNumber>;
|
|
104
146
|
top_p: z.ZodOptional<z.ZodNumber>;
|
|
105
147
|
top_k: z.ZodOptional<z.ZodNumber>;
|
|
@@ -111,6 +153,8 @@ export declare const anthropicMessagesRequestSchema: z.ZodObject<{
|
|
|
111
153
|
description: z.ZodOptional<z.ZodString>;
|
|
112
154
|
input_schema: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
113
155
|
strict: z.ZodOptional<z.ZodBoolean>;
|
|
156
|
+
cache_control: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
157
|
+
defer_loading: z.ZodOptional<z.ZodBoolean>;
|
|
114
158
|
}, z.core.$strict>>>;
|
|
115
159
|
tool_choice: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
116
160
|
type: z.ZodLiteral<"auto">;
|
|
@@ -122,9 +166,17 @@ export declare const anthropicMessagesRequestSchema: z.ZodObject<{
|
|
|
122
166
|
type: z.ZodLiteral<"tool">;
|
|
123
167
|
name: z.ZodString;
|
|
124
168
|
}, z.core.$strict>], "type">>;
|
|
125
|
-
thinking: z.ZodOptional<z.ZodObject<{
|
|
169
|
+
thinking: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
126
170
|
type: z.ZodLiteral<"disabled">;
|
|
127
|
-
}, z.core.$strict
|
|
171
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
172
|
+
type: z.ZodLiteral<"adaptive">;
|
|
173
|
+
display: z.ZodOptional<z.ZodString>;
|
|
174
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
175
|
+
type: z.ZodLiteral<"enabled">;
|
|
176
|
+
budget_tokens: z.ZodNumber;
|
|
177
|
+
display: z.ZodOptional<z.ZodString>;
|
|
178
|
+
}, z.core.$strict>], "type">>;
|
|
179
|
+
context_management: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
128
180
|
output_config: z.ZodOptional<z.ZodObject<{
|
|
129
181
|
effort: z.ZodOptional<z.ZodEnum<{
|
|
130
182
|
low: "low";
|
|
@@ -143,12 +195,18 @@ export declare const anthropicMessageSchema: z.ZodObject<{
|
|
|
143
195
|
role: z.ZodLiteral<"assistant">;
|
|
144
196
|
model: z.ZodString;
|
|
145
197
|
content: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
198
|
+
type: z.ZodLiteral<"thinking">;
|
|
199
|
+
thinking: z.ZodString;
|
|
200
|
+
signature: z.ZodString;
|
|
201
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
146
202
|
type: z.ZodLiteral<"text">;
|
|
147
203
|
text: z.ZodString;
|
|
204
|
+
cache_control: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
148
205
|
}, z.core.$strict>, z.ZodObject<{
|
|
149
206
|
type: z.ZodLiteral<"tool_use">;
|
|
150
207
|
id: z.ZodString;
|
|
151
208
|
name: z.ZodString;
|
|
209
|
+
cache_control: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
152
210
|
input: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
153
211
|
}, z.core.$strict>], "type">>;
|
|
154
212
|
stop_reason: z.ZodEnum<{
|
|
@@ -198,12 +256,18 @@ export declare const anthropicStreamEventSchema: z.ZodDiscriminatedUnion<[z.ZodO
|
|
|
198
256
|
role: z.ZodLiteral<"assistant">;
|
|
199
257
|
model: z.ZodString;
|
|
200
258
|
content: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
259
|
+
type: z.ZodLiteral<"thinking">;
|
|
260
|
+
thinking: z.ZodString;
|
|
261
|
+
signature: z.ZodString;
|
|
262
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
201
263
|
type: z.ZodLiteral<"text">;
|
|
202
264
|
text: z.ZodString;
|
|
265
|
+
cache_control: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
203
266
|
}, z.core.$strict>, z.ZodObject<{
|
|
204
267
|
type: z.ZodLiteral<"tool_use">;
|
|
205
268
|
id: z.ZodString;
|
|
206
269
|
name: z.ZodString;
|
|
270
|
+
cache_control: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
207
271
|
input: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
208
272
|
}, z.core.$strict>], "type">>;
|
|
209
273
|
stop_reason: z.ZodLiteral<null>;
|
|
@@ -218,12 +282,17 @@ export declare const anthropicStreamEventSchema: z.ZodDiscriminatedUnion<[z.ZodO
|
|
|
218
282
|
type: z.ZodLiteral<"content_block_start">;
|
|
219
283
|
index: z.ZodNumber;
|
|
220
284
|
content_block: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
285
|
+
type: z.ZodLiteral<"thinking">;
|
|
286
|
+
thinking: z.ZodLiteral<"">;
|
|
287
|
+
signature: z.ZodLiteral<"">;
|
|
288
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
221
289
|
type: z.ZodLiteral<"text">;
|
|
222
290
|
text: z.ZodLiteral<"">;
|
|
223
291
|
}, z.core.$strict>, z.ZodObject<{
|
|
224
292
|
type: z.ZodLiteral<"tool_use">;
|
|
225
293
|
id: z.ZodString;
|
|
226
294
|
name: z.ZodString;
|
|
295
|
+
cache_control: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
227
296
|
input: z.ZodObject<{}, z.core.$strict>;
|
|
228
297
|
}, z.core.$strict>], "type">;
|
|
229
298
|
}, z.core.$strict>, z.ZodObject<{
|
|
@@ -232,6 +301,12 @@ export declare const anthropicStreamEventSchema: z.ZodDiscriminatedUnion<[z.ZodO
|
|
|
232
301
|
delta: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
233
302
|
type: z.ZodLiteral<"text_delta">;
|
|
234
303
|
text: z.ZodString;
|
|
304
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
305
|
+
type: z.ZodLiteral<"thinking_delta">;
|
|
306
|
+
thinking: z.ZodString;
|
|
307
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
308
|
+
type: z.ZodLiteral<"signature_delta">;
|
|
309
|
+
signature: z.ZodString;
|
|
235
310
|
}, z.core.$strict>, z.ZodObject<{
|
|
236
311
|
type: z.ZodLiteral<"input_json_delta">;
|
|
237
312
|
partial_json: z.ZodString;
|
|
@@ -11,24 +11,50 @@
|
|
|
11
11
|
*
|
|
12
12
|
* ## What is refused, and why
|
|
13
13
|
*
|
|
14
|
-
* - **`
|
|
15
|
-
*
|
|
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.
|
|
14
|
+
* - **`thinking.display`** and every other `thinking` member this file does
|
|
15
|
+
* not name.
|
|
26
16
|
* - **Server tools** (`web_search`, `bash`, `text_editor`, …), `mcp_servers`,
|
|
27
17
|
* `container`, `service_tier`, `disable_parallel_tool_use`, `document`
|
|
28
18
|
* blocks and any other member this file does not name.
|
|
29
19
|
* - **An image `url` source**: nothing fetches an image URL (ADR 0007); a
|
|
30
20
|
* `base64` source is carried inline under the image rules.
|
|
31
21
|
*
|
|
22
|
+
* ## `cache_control`: accepted and IGNORED
|
|
23
|
+
*
|
|
24
|
+
* Claude Code puts a `cache_control` marker on every request, so refusing it
|
|
25
|
+
* made the endpoint unusable by its main client. The marker is accepted wherever
|
|
26
|
+
* the dialect puts it (the request, `system`, a tool, a content block) and is
|
|
27
|
+
* NOT honoured: Kaana forwards no cache hint, so no cache write happens and the
|
|
28
|
+
* usage it reports stays exactly what the request cost. The only effect is the
|
|
29
|
+
* one the caller asked for and does not get: no prompt-cache discount on a write
|
|
30
|
+
* (reads that a provider caches on its own are still metered as
|
|
31
|
+
* `cache_read_input_tokens`). A request whose marker was ignored is answered
|
|
32
|
+
* with `Kaana-Ignored-Parameters: cache_control`. Honouring it needs a priced
|
|
33
|
+
* cache-write unit (`cache_write_input_tokens`, contract 8.4.0) that nothing
|
|
34
|
+
* emits yet.
|
|
35
|
+
*
|
|
36
|
+
* The same holds for three more members Claude Code sends: `context_management`,
|
|
37
|
+
* `thinking.display` and `tools[].defer_loading`. Each is a hint or a beta that
|
|
38
|
+
* changes how a provider trims, shows or loads, never what a request means or
|
|
39
|
+
* costs; each present one is named in `Kaana-Ignored-Parameters`. Any other
|
|
40
|
+
* member this file does not name is still refused.
|
|
41
|
+
*
|
|
42
|
+
* ## Reasoning (contract set 8.6.0, ADR 0009 decision 2)
|
|
43
|
+
*
|
|
44
|
+
* `thinking: {type: 'enabled', budget_tokens}` is the contract's
|
|
45
|
+
* `reasoning.maxTokens` and `thinking: {type: 'adaptive'}` opts in to reasoning
|
|
46
|
+
* with the route's own sizing; `output_config.effort` is `reasoning.effort`, and
|
|
47
|
+
* a budget beside an effort is refused (the contract treats them as
|
|
48
|
+
* alternatives). A route that cannot take a budget refuses it by name.
|
|
49
|
+
*
|
|
50
|
+
* An answer carries `thinking` blocks before its text and tool calls, and an
|
|
51
|
+
* assistant message sent back carries them again, UNMODIFIED, ahead of its
|
|
52
|
+
* `tool_use` blocks. The block's `signature` is the contract's opaque
|
|
53
|
+
* continuation token (the sealed string a `reasoning` part carries), which is
|
|
54
|
+
* why a stock Anthropic SDK continues a tool turn without knowing anything
|
|
55
|
+
* else: it returns what it received. `redacted_thinking` is accepted on the way
|
|
56
|
+
* in (its `data` is the same token) and never produced.
|
|
57
|
+
*
|
|
32
58
|
* `stop_reason: 'stop_sequence'` is never produced: the finish reason Kaana
|
|
33
59
|
* measures does not say WHICH stop sequence ended the turn, and `stop_sequence`
|
|
34
60
|
* would then have to name one. A turn that ended on a stop sequence reports
|
|
@@ -46,10 +72,21 @@ import { maxUtf16Length, minUtf16Length } from '../stringBounds.js';
|
|
|
46
72
|
import { reasoningEffortSchema } from './catalogue.js';
|
|
47
73
|
import { modelTargetSchema } from './responses.js';
|
|
48
74
|
const nonEmpty = (max) => z.string().check(minUtf16Length(1)).check(maxUtf16Length(max));
|
|
49
|
-
|
|
75
|
+
/** Accepted and ignored, whatever members it carries (`type`, `ttl`, `scope`): see "`cache_control`" in the file comment. */
|
|
76
|
+
const cacheControlSchema = z.record(z.string(), z.unknown());
|
|
77
|
+
/** Accepted and ignored: how much reasoning text a client wants shown. */
|
|
78
|
+
const thinkingDisplaySchema = z.string();
|
|
79
|
+
const textBlockSchema = z
|
|
80
|
+
.object({
|
|
81
|
+
type: z.literal('text'),
|
|
82
|
+
text: z.string(),
|
|
83
|
+
cache_control: cacheControlSchema.optional(),
|
|
84
|
+
})
|
|
85
|
+
.strict();
|
|
50
86
|
const imageBlockSchema = z
|
|
51
87
|
.object({
|
|
52
88
|
type: z.literal('image'),
|
|
89
|
+
cache_control: cacheControlSchema.optional(),
|
|
53
90
|
source: z.discriminatedUnion('type', [
|
|
54
91
|
z
|
|
55
92
|
.object({
|
|
@@ -63,12 +100,28 @@ const imageBlockSchema = z
|
|
|
63
100
|
]),
|
|
64
101
|
})
|
|
65
102
|
.strict();
|
|
103
|
+
/**
|
|
104
|
+
* An assistant's reasoning. `thinking` is the readable text (empty when the
|
|
105
|
+
* model returned none); `signature` is the continuation token to return
|
|
106
|
+
* unmodified, empty only for a block that cannot be continued.
|
|
107
|
+
*/
|
|
108
|
+
const thinkingBlockSchema = z
|
|
109
|
+
.object({
|
|
110
|
+
type: z.literal('thinking'),
|
|
111
|
+
thinking: z.string(),
|
|
112
|
+
signature: z.string(),
|
|
113
|
+
})
|
|
114
|
+
.strict();
|
|
115
|
+
const redactedThinkingBlockSchema = z
|
|
116
|
+
.object({ type: z.literal('redacted_thinking'), data: nonEmpty(1_000_000) })
|
|
117
|
+
.strict();
|
|
66
118
|
const toolUseBlockSchema = z
|
|
67
119
|
.object({
|
|
68
120
|
type: z.literal('tool_use'),
|
|
69
121
|
id: nonEmpty(128),
|
|
70
122
|
name: nonEmpty(128),
|
|
71
123
|
input: z.record(z.string(), z.unknown()),
|
|
124
|
+
cache_control: cacheControlSchema.optional(),
|
|
72
125
|
})
|
|
73
126
|
.strict();
|
|
74
127
|
const toolResultBlockSchema = z
|
|
@@ -83,15 +136,24 @@ const toolResultBlockSchema = z
|
|
|
83
136
|
* own content is what the model reads; the flag is not forwarded.
|
|
84
137
|
*/
|
|
85
138
|
is_error: z.boolean().optional(),
|
|
139
|
+
cache_control: cacheControlSchema.optional(),
|
|
86
140
|
})
|
|
87
141
|
.strict();
|
|
88
142
|
const messageSchema = z
|
|
89
143
|
.object({
|
|
90
|
-
|
|
144
|
+
/** `system` is a mid-conversation instruction Claude Code sends: text blocks only. */
|
|
145
|
+
role: z.enum(['user', 'assistant', 'system']),
|
|
91
146
|
content: z.union([
|
|
92
147
|
z.string(),
|
|
93
148
|
z
|
|
94
|
-
.array(z.union([
|
|
149
|
+
.array(z.union([
|
|
150
|
+
textBlockSchema,
|
|
151
|
+
imageBlockSchema,
|
|
152
|
+
toolUseBlockSchema,
|
|
153
|
+
toolResultBlockSchema,
|
|
154
|
+
thinkingBlockSchema,
|
|
155
|
+
redactedThinkingBlockSchema,
|
|
156
|
+
]))
|
|
95
157
|
.min(1),
|
|
96
158
|
]),
|
|
97
159
|
})
|
|
@@ -100,9 +162,12 @@ const messageSchema = z
|
|
|
100
162
|
if (typeof message.content === 'string')
|
|
101
163
|
return;
|
|
102
164
|
for (const [index, block] of message.content.entries()) {
|
|
165
|
+
const reasoning = block.type === 'thinking' || block.type === 'redacted_thinking';
|
|
103
166
|
const allowed = message.role === 'assistant'
|
|
104
|
-
? block.type === 'text' || block.type === 'tool_use'
|
|
105
|
-
:
|
|
167
|
+
? block.type === 'text' || block.type === 'tool_use' || reasoning
|
|
168
|
+
: message.role === 'system'
|
|
169
|
+
? block.type === 'text'
|
|
170
|
+
: block.type !== 'tool_use' && !reasoning;
|
|
106
171
|
if (!allowed) {
|
|
107
172
|
ctx.addIssue({
|
|
108
173
|
code: 'custom',
|
|
@@ -119,6 +184,9 @@ const toolSchema = z
|
|
|
119
184
|
description: z.string().check(maxUtf16Length(32768)).optional(),
|
|
120
185
|
input_schema: z.record(z.string(), z.unknown()),
|
|
121
186
|
strict: z.boolean().optional(),
|
|
187
|
+
cache_control: cacheControlSchema.optional(),
|
|
188
|
+
/** Accepted and ignored: Kaana loads every tool it is sent. */
|
|
189
|
+
defer_loading: z.boolean().optional(),
|
|
122
190
|
})
|
|
123
191
|
.strict();
|
|
124
192
|
const toolChoiceSchema = z.discriminatedUnion('type', [
|
|
@@ -135,6 +203,7 @@ export const anthropicMessagesRequestSchema = z
|
|
|
135
203
|
max_tokens: z.number().int().positive().safe(),
|
|
136
204
|
messages: z.array(messageSchema).min(1),
|
|
137
205
|
system: z.union([z.string(), z.array(textBlockSchema)]).optional(),
|
|
206
|
+
cache_control: cacheControlSchema.optional(),
|
|
138
207
|
temperature: z.number().min(0).max(1).optional(),
|
|
139
208
|
top_p: z.number().min(0).max(1).optional(),
|
|
140
209
|
top_k: z.number().int().positive().safe().optional(),
|
|
@@ -142,11 +211,28 @@ export const anthropicMessagesRequestSchema = z
|
|
|
142
211
|
stream: z.boolean().optional(),
|
|
143
212
|
tools: z.array(toolSchema).max(128).optional(),
|
|
144
213
|
tool_choice: toolChoiceSchema.optional(),
|
|
145
|
-
/**
|
|
214
|
+
/**
|
|
215
|
+
* `disabled` asks for nothing; `adaptive` opts in to reasoning (the
|
|
216
|
+
* contract's `reasoning: {}`); `enabled` sets a token budget
|
|
217
|
+
* (`reasoning.maxTokens`). See the file comment.
|
|
218
|
+
*/
|
|
146
219
|
thinking: z
|
|
147
|
-
.
|
|
148
|
-
.strict()
|
|
220
|
+
.discriminatedUnion('type', [
|
|
221
|
+
z.object({ type: z.literal('disabled') }).strict(),
|
|
222
|
+
z
|
|
223
|
+
.object({ type: z.literal('adaptive'), display: thinkingDisplaySchema.optional() })
|
|
224
|
+
.strict(),
|
|
225
|
+
z
|
|
226
|
+
.object({
|
|
227
|
+
type: z.literal('enabled'),
|
|
228
|
+
budget_tokens: z.number().int().positive().safe(),
|
|
229
|
+
display: thinkingDisplaySchema.optional(),
|
|
230
|
+
})
|
|
231
|
+
.strict(),
|
|
232
|
+
])
|
|
149
233
|
.optional(),
|
|
234
|
+
/** Accepted and ignored (an Anthropic beta Claude Code sends). */
|
|
235
|
+
context_management: z.record(z.string(), z.unknown()).optional(),
|
|
150
236
|
/** `effort` is the contract's reasoning effort; no other member is carried. */
|
|
151
237
|
output_config: z.object({ effort: reasoningEffortSchema.optional() }).strict().optional(),
|
|
152
238
|
/** Accepted and not forwarded or stored. */
|
|
@@ -175,6 +261,7 @@ const usageSchema = z
|
|
|
175
261
|
.strict();
|
|
176
262
|
const stopReasonSchema = z.enum(['end_turn', 'max_tokens', 'tool_use', 'refusal']);
|
|
177
263
|
const outputBlockSchema = z.discriminatedUnion('type', [
|
|
264
|
+
thinkingBlockSchema,
|
|
178
265
|
textBlockSchema,
|
|
179
266
|
toolUseBlockSchema.extend({ input: z.record(z.string(), z.unknown()) }),
|
|
180
267
|
]);
|
|
@@ -243,6 +330,13 @@ export const anthropicStreamEventSchema = z.discriminatedUnion('type', [
|
|
|
243
330
|
type: z.literal('content_block_start'),
|
|
244
331
|
index: z.number().int().nonnegative(),
|
|
245
332
|
content_block: z.discriminatedUnion('type', [
|
|
333
|
+
z
|
|
334
|
+
.object({
|
|
335
|
+
type: z.literal('thinking'),
|
|
336
|
+
thinking: z.literal(''),
|
|
337
|
+
signature: z.literal(''),
|
|
338
|
+
})
|
|
339
|
+
.strict(),
|
|
246
340
|
z.object({ type: z.literal('text'), text: z.literal('') }).strict(),
|
|
247
341
|
toolUseBlockSchema.extend({ input: z.object({}).strict() }),
|
|
248
342
|
]),
|
|
@@ -254,6 +348,8 @@ export const anthropicStreamEventSchema = z.discriminatedUnion('type', [
|
|
|
254
348
|
index: z.number().int().nonnegative(),
|
|
255
349
|
delta: z.discriminatedUnion('type', [
|
|
256
350
|
z.object({ type: z.literal('text_delta'), text: z.string() }).strict(),
|
|
351
|
+
z.object({ type: z.literal('thinking_delta'), thinking: z.string() }).strict(),
|
|
352
|
+
z.object({ type: z.literal('signature_delta'), signature: z.string() }).strict(),
|
|
257
353
|
z.object({ type: z.literal('input_json_delta'), partial_json: z.string() }).strict(),
|
|
258
354
|
]),
|
|
259
355
|
})
|
|
@@ -70,6 +70,10 @@ export declare const chatCompletionMessageSchema: z.ZodObject<{
|
|
|
70
70
|
}, z.core.$strict>, z.ZodObject<{
|
|
71
71
|
type: z.ZodLiteral<"refusal">;
|
|
72
72
|
text: z.ZodString;
|
|
73
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
74
|
+
type: z.ZodLiteral<"reasoning">;
|
|
75
|
+
text: z.ZodOptional<z.ZodString>;
|
|
76
|
+
opaque: z.ZodOptional<z.ZodString>;
|
|
73
77
|
}, z.core.$strict>], "type">>]>>>;
|
|
74
78
|
name: z.ZodOptional<z.ZodString>;
|
|
75
79
|
tool_call_id: z.ZodOptional<z.ZodString>;
|
|
@@ -142,6 +146,10 @@ export declare const chatCompletionsRequestSchema: z.ZodObject<{
|
|
|
142
146
|
}, z.core.$strict>, z.ZodObject<{
|
|
143
147
|
type: z.ZodLiteral<"refusal">;
|
|
144
148
|
text: z.ZodString;
|
|
149
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
150
|
+
type: z.ZodLiteral<"reasoning">;
|
|
151
|
+
text: z.ZodOptional<z.ZodString>;
|
|
152
|
+
opaque: z.ZodOptional<z.ZodString>;
|
|
145
153
|
}, z.core.$strict>], "type">>]>>>;
|
|
146
154
|
name: z.ZodOptional<z.ZodString>;
|
|
147
155
|
tool_call_id: z.ZodOptional<z.ZodString>;
|
|
@@ -23,34 +23,44 @@ export declare const inferenceContentSourceSchema: z.ZodDiscriminatedUnion<[z.Zo
|
|
|
23
23
|
/**
|
|
24
24
|
* One part of a message's content. A message is always a list of parts.
|
|
25
25
|
*
|
|
26
|
-
* ## `refusal`
|
|
26
|
+
* ## `refusal` and `reasoning` are members, and neither is ever answer text
|
|
27
27
|
*
|
|
28
28
|
* A model that DECLINES says why, and those words are meant for the customer:
|
|
29
29
|
* they are the difference between "rephrase this" and "stop asking". Before this
|
|
30
30
|
* member existed there was nowhere in an {@link InferenceMessage} to put them, so
|
|
31
|
-
* a non-streaming fold kept `finishReason: 'refusal'` and dropped the sentence
|
|
32
|
-
*
|
|
33
|
-
*
|
|
31
|
+
* a non-streaming fold kept `finishReason: 'refusal'` and dropped the sentence.
|
|
32
|
+
* The part is a MEMBER rather than a field because a refusal need not have text:
|
|
33
|
+
* an Anthropic `stop_reason: "refusal"` maps to the finish reason and separates
|
|
34
|
+
* no words from the answer, while an OpenAI-compatible `refusal` does.
|
|
34
35
|
*
|
|
35
|
-
*
|
|
36
|
-
* working, and a `text` part is where somebody would put it — which renders
|
|
37
|
-
* private reasoning to the customer AS the answer, the product bug the delta
|
|
38
|
-
* channels exist to prevent. An opaque per-block reasoning blob crossing this
|
|
39
|
-
* boundary needs a home nobody has chosen yet, and inventing one here would
|
|
40
|
-
* choose it by accident.
|
|
36
|
+
* ## `reasoning` (contract set 8.6.0, Kaana ADR 0009 decision 2)
|
|
41
37
|
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
* standard-client parseability, and carrying reasoning would.
|
|
38
|
+
* Reasoning was deliberately absent until the owner chose its home, because an
|
|
39
|
+
* opaque per-block reasoning blob had none. The cost of that absence was
|
|
40
|
+
* correctness: a thinking model that calls a tool cannot be continued unless the
|
|
41
|
+
* assistant's reasoning blocks, with their signatures, come back to the provider
|
|
42
|
+
* unmodified and in order, and a customer who only ever received reasoning TEXT
|
|
43
|
+
* on the `reasoning` delta channel had nothing to send back.
|
|
49
44
|
*
|
|
50
|
-
* The part is
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
45
|
+
* The part is `{type: 'reasoning', text?, opaque?}`:
|
|
46
|
+
*
|
|
47
|
+
* - `text` is what a person may read. It is a display value and is never
|
|
48
|
+
* forwarded to a provider on its own.
|
|
49
|
+
* - `opaque` is a continuation token the customer MUST return UNMODIFIED, in the
|
|
50
|
+
* position it arrived. Its content is Kaana's to define and the customer's to
|
|
51
|
+
* treat as a sealed string: it is provider-neutral on the surface and carries
|
|
52
|
+
* whatever the serving provider needs to continue. Sealing is NOT
|
|
53
|
+
* cryptographic: a forged or edited token is no more than a request the
|
|
54
|
+
* provider refuses, so nothing may rely on it for trust.
|
|
55
|
+
* - at least one of the two is present.
|
|
56
|
+
*
|
|
57
|
+
* A reasoning part is the assistant's alone, exactly as a refusal is. It is
|
|
58
|
+
* never a `text` part, so no renderer can present private reasoning as the
|
|
59
|
+
* answer, and the delta channels keep reasoning apart for the same reason.
|
|
60
|
+
*
|
|
61
|
+
* What a route does with a token it cannot read (it was issued by another
|
|
62
|
+
* provider family, after a failover or a model switch) is drop it, never fail:
|
|
63
|
+
* the continuation is lost, the conversation is not.
|
|
54
64
|
*/
|
|
55
65
|
export declare const inferenceContentPartSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
56
66
|
type: z.ZodLiteral<"text">;
|
|
@@ -94,6 +104,10 @@ export declare const inferenceContentPartSchema: z.ZodDiscriminatedUnion<[z.ZodO
|
|
|
94
104
|
}, z.core.$strict>, z.ZodObject<{
|
|
95
105
|
type: z.ZodLiteral<"refusal">;
|
|
96
106
|
text: z.ZodString;
|
|
107
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
108
|
+
type: z.ZodLiteral<"reasoning">;
|
|
109
|
+
text: z.ZodOptional<z.ZodString>;
|
|
110
|
+
opaque: z.ZodOptional<z.ZodString>;
|
|
97
111
|
}, z.core.$strict>], "type">;
|
|
98
112
|
/**
|
|
99
113
|
* The image formats a request may carry. Every provider that serves image input
|
|
@@ -227,6 +241,10 @@ export declare const inferenceMessageSchema: z.ZodObject<{
|
|
|
227
241
|
}, z.core.$strict>, z.ZodObject<{
|
|
228
242
|
type: z.ZodLiteral<"refusal">;
|
|
229
243
|
text: z.ZodString;
|
|
244
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
245
|
+
type: z.ZodLiteral<"reasoning">;
|
|
246
|
+
text: z.ZodOptional<z.ZodString>;
|
|
247
|
+
opaque: z.ZodOptional<z.ZodString>;
|
|
230
248
|
}, z.core.$strict>], "type">>;
|
|
231
249
|
name: z.ZodOptional<z.ZodString>;
|
|
232
250
|
toolCallId: z.ZodOptional<z.ZodString>;
|
|
@@ -280,17 +298,30 @@ export declare const responseFormatSchema: z.ZodDiscriminatedUnion<[z.ZodObject<
|
|
|
280
298
|
}, z.core.$strict>], "type">;
|
|
281
299
|
/**
|
|
282
300
|
* The caller's reasoning control. Strict, like every leaf: a provider-specific
|
|
283
|
-
* knob (`
|
|
301
|
+
* knob (`summary`) is refused rather than silently dropped.
|
|
284
302
|
*
|
|
285
|
-
*
|
|
286
|
-
*
|
|
303
|
+
* - `effort` is how much to reason, in the catalogue's words. Oxy forwards it
|
|
304
|
+
* only after checking the resolved model advertises it in `reasoningEfforts`.
|
|
305
|
+
* - `maxTokens` is a thinking BUDGET in tokens. It is the other way to size
|
|
306
|
+
* reasoning, so it excludes `effort`. A route that cannot take a budget
|
|
307
|
+
* refuses it with `invalid_request` naming `reasoning.maxTokens`.
|
|
308
|
+
* - `exclude: true` means the model may still reason, and be billed for it, but
|
|
309
|
+
* no reasoning is returned: no `reasoning` delta, no reasoning part, no opaque
|
|
310
|
+
* token. A caller that excludes reasoning cannot continue it.
|
|
311
|
+
*
|
|
312
|
+
* Carrying `reasoning` at all, even as `{}`, opts in to receiving reasoning
|
|
313
|
+
* continuation tokens (the `opaque` field of a `reasoning` delta); a request
|
|
314
|
+
* without it never receives one, which is what keeps older readers of the
|
|
315
|
+
* stream unaffected.
|
|
287
316
|
*/
|
|
288
317
|
export declare const inferenceReasoningSchema: z.ZodObject<{
|
|
289
|
-
effort: z.ZodEnum<{
|
|
318
|
+
effort: z.ZodOptional<z.ZodEnum<{
|
|
290
319
|
low: "low";
|
|
291
320
|
medium: "medium";
|
|
292
321
|
high: "high";
|
|
293
|
-
}
|
|
322
|
+
}>>;
|
|
323
|
+
maxTokens: z.ZodOptional<z.ZodNumber>;
|
|
324
|
+
exclude: z.ZodOptional<z.ZodBoolean>;
|
|
294
325
|
}, z.core.$strict>;
|
|
295
326
|
/** Parameters for text-to-speech, preserved in the signed request. */
|
|
296
327
|
export declare const inferenceSpeechParametersSchema: z.ZodObject<{
|