@kaana.ai/contracts 8.4.0 → 8.6.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 +2 -2
- package/dist/internal/request.d.ts +12 -2
- package/dist/internal/streamEvents.d.ts +1 -0
- package/dist/public/anthropicMessages.d.ts +50 -8
- package/dist/public/anthropicMessages.js +69 -12
- package/dist/public/chatCompletions.d.ts +40 -3
- package/dist/public/chatCompletions.js +9 -3
- package/dist/public/messages.d.ts +57 -26
- package/dist/public/messages.js +74 -29
- package/dist/public/providerPreferences.d.ts +71 -0
- package/dist/public/providerPreferences.js +75 -0
- package/dist/public/responses.d.ts +40 -2
- package/dist/public/responses.js +5 -0
- package/dist/public/streamEvents.d.ts +2 -0
- package/dist/public/streamEvents.js +8 -0
- package/dist/public/version.d.ts +16 -1
- package/dist/public/version.js +16 -1
- package/openapi.json +322 -14
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -24,6 +24,7 @@ export * from './public/images.js';
|
|
|
24
24
|
export * from './public/messages.js';
|
|
25
25
|
export * from './public/money.js';
|
|
26
26
|
export * from './public/policy.js';
|
|
27
|
+
export * from './public/providerPreferences.js';
|
|
27
28
|
export * from './public/realtime.js';
|
|
28
29
|
export * from './public/responses.js';
|
|
29
30
|
export * from './public/streamEvents.js';
|
package/dist/index.js
CHANGED
|
@@ -24,6 +24,7 @@ export * from './public/images.js';
|
|
|
24
24
|
export * from './public/messages.js';
|
|
25
25
|
export * from './public/money.js';
|
|
26
26
|
export * from './public/policy.js';
|
|
27
|
+
export * from './public/providerPreferences.js';
|
|
27
28
|
export * from './public/realtime.js';
|
|
28
29
|
export * from './public/responses.js';
|
|
29
30
|
export * from './public/streamEvents.js';
|
|
@@ -314,10 +314,10 @@ export declare const routingProfileSchema: z.ZodObject<{
|
|
|
314
314
|
displayName: z.ZodString;
|
|
315
315
|
description: z.ZodOptional<z.ZodString>;
|
|
316
316
|
optimiseFor: z.ZodEnum<{
|
|
317
|
-
quality: "quality";
|
|
318
|
-
price: "price";
|
|
319
317
|
latency: "latency";
|
|
320
318
|
throughput: "throughput";
|
|
319
|
+
quality: "quality";
|
|
320
|
+
price: "price";
|
|
321
321
|
balanced: "balanced";
|
|
322
322
|
}>;
|
|
323
323
|
candidates: z.ZodArray<z.ZodObject<{
|
|
@@ -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">;
|
|
@@ -17,18 +17,30 @@
|
|
|
17
17
|
* over input, so honouring the marker while folding the write into
|
|
18
18
|
* `input_tokens` would report less than the request cost. The marker is
|
|
19
19
|
* refused, by name and path, instead of being dropped.
|
|
20
|
-
* - **`thinking
|
|
21
|
-
*
|
|
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.
|
|
20
|
+
* - **`thinking.display`** and every other `thinking` member this file does
|
|
21
|
+
* not name.
|
|
26
22
|
* - **Server tools** (`web_search`, `bash`, `text_editor`, …), `mcp_servers`,
|
|
27
23
|
* `container`, `service_tier`, `disable_parallel_tool_use`, `document`
|
|
28
24
|
* blocks and any other member this file does not name.
|
|
29
25
|
* - **An image `url` source**: nothing fetches an image URL (ADR 0007); a
|
|
30
26
|
* `base64` source is carried inline under the image rules.
|
|
31
27
|
*
|
|
28
|
+
* ## Reasoning (contract set 8.6.0, ADR 0009 decision 2)
|
|
29
|
+
*
|
|
30
|
+
* `thinking: {type: 'enabled', budget_tokens}` is the contract's
|
|
31
|
+
* `reasoning.maxTokens` and `thinking: {type: 'adaptive'}` opts in to reasoning
|
|
32
|
+
* with the route's own sizing; `output_config.effort` is `reasoning.effort`, and
|
|
33
|
+
* a budget beside an effort is refused (the contract treats them as
|
|
34
|
+
* alternatives). A route that cannot take a budget refuses it by name.
|
|
35
|
+
*
|
|
36
|
+
* An answer carries `thinking` blocks before its text and tool calls, and an
|
|
37
|
+
* assistant message sent back carries them again, UNMODIFIED, ahead of its
|
|
38
|
+
* `tool_use` blocks. The block's `signature` is the contract's opaque
|
|
39
|
+
* continuation token (the sealed string a `reasoning` part carries), which is
|
|
40
|
+
* why a stock Anthropic SDK continues a tool turn without knowing anything
|
|
41
|
+
* else: it returns what it received. `redacted_thinking` is accepted on the way
|
|
42
|
+
* in (its `data` is the same token) and never produced.
|
|
43
|
+
*
|
|
32
44
|
* `stop_reason: 'stop_sequence'` is never produced: the finish reason Kaana
|
|
33
45
|
* measures does not say WHICH stop sequence ended the turn, and `stop_sequence`
|
|
34
46
|
* would then have to name one. A turn that ended on a stop sequence reports
|
|
@@ -94,6 +106,13 @@ export declare const anthropicMessagesRequestSchema: z.ZodObject<{
|
|
|
94
106
|
}, z.core.$strict>], "type">;
|
|
95
107
|
}, z.core.$strict>]>>]>>;
|
|
96
108
|
is_error: z.ZodOptional<z.ZodBoolean>;
|
|
109
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
110
|
+
type: z.ZodLiteral<"thinking">;
|
|
111
|
+
thinking: z.ZodString;
|
|
112
|
+
signature: z.ZodString;
|
|
113
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
114
|
+
type: z.ZodLiteral<"redacted_thinking">;
|
|
115
|
+
data: z.ZodString;
|
|
97
116
|
}, z.core.$strict>]>>]>;
|
|
98
117
|
}, z.core.$strict>>;
|
|
99
118
|
system: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodObject<{
|
|
@@ -122,9 +141,14 @@ export declare const anthropicMessagesRequestSchema: z.ZodObject<{
|
|
|
122
141
|
type: z.ZodLiteral<"tool">;
|
|
123
142
|
name: z.ZodString;
|
|
124
143
|
}, z.core.$strict>], "type">>;
|
|
125
|
-
thinking: z.ZodOptional<z.ZodObject<{
|
|
144
|
+
thinking: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
126
145
|
type: z.ZodLiteral<"disabled">;
|
|
127
|
-
}, z.core.$strict
|
|
146
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
147
|
+
type: z.ZodLiteral<"adaptive">;
|
|
148
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
149
|
+
type: z.ZodLiteral<"enabled">;
|
|
150
|
+
budget_tokens: z.ZodNumber;
|
|
151
|
+
}, z.core.$strict>], "type">>;
|
|
128
152
|
output_config: z.ZodOptional<z.ZodObject<{
|
|
129
153
|
effort: z.ZodOptional<z.ZodEnum<{
|
|
130
154
|
low: "low";
|
|
@@ -143,6 +167,10 @@ export declare const anthropicMessageSchema: z.ZodObject<{
|
|
|
143
167
|
role: z.ZodLiteral<"assistant">;
|
|
144
168
|
model: z.ZodString;
|
|
145
169
|
content: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
170
|
+
type: z.ZodLiteral<"thinking">;
|
|
171
|
+
thinking: z.ZodString;
|
|
172
|
+
signature: z.ZodString;
|
|
173
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
146
174
|
type: z.ZodLiteral<"text">;
|
|
147
175
|
text: z.ZodString;
|
|
148
176
|
}, z.core.$strict>, z.ZodObject<{
|
|
@@ -198,6 +226,10 @@ export declare const anthropicStreamEventSchema: z.ZodDiscriminatedUnion<[z.ZodO
|
|
|
198
226
|
role: z.ZodLiteral<"assistant">;
|
|
199
227
|
model: z.ZodString;
|
|
200
228
|
content: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
229
|
+
type: z.ZodLiteral<"thinking">;
|
|
230
|
+
thinking: z.ZodString;
|
|
231
|
+
signature: z.ZodString;
|
|
232
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
201
233
|
type: z.ZodLiteral<"text">;
|
|
202
234
|
text: z.ZodString;
|
|
203
235
|
}, z.core.$strict>, z.ZodObject<{
|
|
@@ -218,6 +250,10 @@ export declare const anthropicStreamEventSchema: z.ZodDiscriminatedUnion<[z.ZodO
|
|
|
218
250
|
type: z.ZodLiteral<"content_block_start">;
|
|
219
251
|
index: z.ZodNumber;
|
|
220
252
|
content_block: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
253
|
+
type: z.ZodLiteral<"thinking">;
|
|
254
|
+
thinking: z.ZodLiteral<"">;
|
|
255
|
+
signature: z.ZodLiteral<"">;
|
|
256
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
221
257
|
type: z.ZodLiteral<"text">;
|
|
222
258
|
text: z.ZodLiteral<"">;
|
|
223
259
|
}, z.core.$strict>, z.ZodObject<{
|
|
@@ -232,6 +268,12 @@ export declare const anthropicStreamEventSchema: z.ZodDiscriminatedUnion<[z.ZodO
|
|
|
232
268
|
delta: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
233
269
|
type: z.ZodLiteral<"text_delta">;
|
|
234
270
|
text: z.ZodString;
|
|
271
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
272
|
+
type: z.ZodLiteral<"thinking_delta">;
|
|
273
|
+
thinking: z.ZodString;
|
|
274
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
275
|
+
type: z.ZodLiteral<"signature_delta">;
|
|
276
|
+
signature: z.ZodString;
|
|
235
277
|
}, z.core.$strict>, z.ZodObject<{
|
|
236
278
|
type: z.ZodLiteral<"input_json_delta">;
|
|
237
279
|
partial_json: z.ZodString;
|
|
@@ -17,18 +17,30 @@
|
|
|
17
17
|
* over input, so honouring the marker while folding the write into
|
|
18
18
|
* `input_tokens` would report less than the request cost. The marker is
|
|
19
19
|
* refused, by name and path, instead of being dropped.
|
|
20
|
-
* - **`thinking
|
|
21
|
-
*
|
|
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.
|
|
20
|
+
* - **`thinking.display`** and every other `thinking` member this file does
|
|
21
|
+
* not name.
|
|
26
22
|
* - **Server tools** (`web_search`, `bash`, `text_editor`, …), `mcp_servers`,
|
|
27
23
|
* `container`, `service_tier`, `disable_parallel_tool_use`, `document`
|
|
28
24
|
* blocks and any other member this file does not name.
|
|
29
25
|
* - **An image `url` source**: nothing fetches an image URL (ADR 0007); a
|
|
30
26
|
* `base64` source is carried inline under the image rules.
|
|
31
27
|
*
|
|
28
|
+
* ## Reasoning (contract set 8.6.0, ADR 0009 decision 2)
|
|
29
|
+
*
|
|
30
|
+
* `thinking: {type: 'enabled', budget_tokens}` is the contract's
|
|
31
|
+
* `reasoning.maxTokens` and `thinking: {type: 'adaptive'}` opts in to reasoning
|
|
32
|
+
* with the route's own sizing; `output_config.effort` is `reasoning.effort`, and
|
|
33
|
+
* a budget beside an effort is refused (the contract treats them as
|
|
34
|
+
* alternatives). A route that cannot take a budget refuses it by name.
|
|
35
|
+
*
|
|
36
|
+
* An answer carries `thinking` blocks before its text and tool calls, and an
|
|
37
|
+
* assistant message sent back carries them again, UNMODIFIED, ahead of its
|
|
38
|
+
* `tool_use` blocks. The block's `signature` is the contract's opaque
|
|
39
|
+
* continuation token (the sealed string a `reasoning` part carries), which is
|
|
40
|
+
* why a stock Anthropic SDK continues a tool turn without knowing anything
|
|
41
|
+
* else: it returns what it received. `redacted_thinking` is accepted on the way
|
|
42
|
+
* in (its `data` is the same token) and never produced.
|
|
43
|
+
*
|
|
32
44
|
* `stop_reason: 'stop_sequence'` is never produced: the finish reason Kaana
|
|
33
45
|
* measures does not say WHICH stop sequence ended the turn, and `stop_sequence`
|
|
34
46
|
* would then have to name one. A turn that ended on a stop sequence reports
|
|
@@ -63,6 +75,21 @@ const imageBlockSchema = z
|
|
|
63
75
|
]),
|
|
64
76
|
})
|
|
65
77
|
.strict();
|
|
78
|
+
/**
|
|
79
|
+
* An assistant's reasoning. `thinking` is the readable text (empty when the
|
|
80
|
+
* model returned none); `signature` is the continuation token to return
|
|
81
|
+
* unmodified, empty only for a block that cannot be continued.
|
|
82
|
+
*/
|
|
83
|
+
const thinkingBlockSchema = z
|
|
84
|
+
.object({
|
|
85
|
+
type: z.literal('thinking'),
|
|
86
|
+
thinking: z.string(),
|
|
87
|
+
signature: z.string(),
|
|
88
|
+
})
|
|
89
|
+
.strict();
|
|
90
|
+
const redactedThinkingBlockSchema = z
|
|
91
|
+
.object({ type: z.literal('redacted_thinking'), data: nonEmpty(1_000_000) })
|
|
92
|
+
.strict();
|
|
66
93
|
const toolUseBlockSchema = z
|
|
67
94
|
.object({
|
|
68
95
|
type: z.literal('tool_use'),
|
|
@@ -91,7 +118,14 @@ const messageSchema = z
|
|
|
91
118
|
content: z.union([
|
|
92
119
|
z.string(),
|
|
93
120
|
z
|
|
94
|
-
.array(z.union([
|
|
121
|
+
.array(z.union([
|
|
122
|
+
textBlockSchema,
|
|
123
|
+
imageBlockSchema,
|
|
124
|
+
toolUseBlockSchema,
|
|
125
|
+
toolResultBlockSchema,
|
|
126
|
+
thinkingBlockSchema,
|
|
127
|
+
redactedThinkingBlockSchema,
|
|
128
|
+
]))
|
|
95
129
|
.min(1),
|
|
96
130
|
]),
|
|
97
131
|
})
|
|
@@ -100,9 +134,10 @@ const messageSchema = z
|
|
|
100
134
|
if (typeof message.content === 'string')
|
|
101
135
|
return;
|
|
102
136
|
for (const [index, block] of message.content.entries()) {
|
|
137
|
+
const reasoning = block.type === 'thinking' || block.type === 'redacted_thinking';
|
|
103
138
|
const allowed = message.role === 'assistant'
|
|
104
|
-
? block.type === 'text' || block.type === 'tool_use'
|
|
105
|
-
: block.type !== 'tool_use';
|
|
139
|
+
? block.type === 'text' || block.type === 'tool_use' || reasoning
|
|
140
|
+
: block.type !== 'tool_use' && !reasoning;
|
|
106
141
|
if (!allowed) {
|
|
107
142
|
ctx.addIssue({
|
|
108
143
|
code: 'custom',
|
|
@@ -142,10 +177,22 @@ export const anthropicMessagesRequestSchema = z
|
|
|
142
177
|
stream: z.boolean().optional(),
|
|
143
178
|
tools: z.array(toolSchema).max(128).optional(),
|
|
144
179
|
tool_choice: toolChoiceSchema.optional(),
|
|
145
|
-
/**
|
|
180
|
+
/**
|
|
181
|
+
* `disabled` asks for nothing; `adaptive` opts in to reasoning (the
|
|
182
|
+
* contract's `reasoning: {}`); `enabled` sets a token budget
|
|
183
|
+
* (`reasoning.maxTokens`). See the file comment.
|
|
184
|
+
*/
|
|
146
185
|
thinking: z
|
|
147
|
-
.
|
|
148
|
-
.strict()
|
|
186
|
+
.discriminatedUnion('type', [
|
|
187
|
+
z.object({ type: z.literal('disabled') }).strict(),
|
|
188
|
+
z.object({ type: z.literal('adaptive') }).strict(),
|
|
189
|
+
z
|
|
190
|
+
.object({
|
|
191
|
+
type: z.literal('enabled'),
|
|
192
|
+
budget_tokens: z.number().int().positive().safe(),
|
|
193
|
+
})
|
|
194
|
+
.strict(),
|
|
195
|
+
])
|
|
149
196
|
.optional(),
|
|
150
197
|
/** `effort` is the contract's reasoning effort; no other member is carried. */
|
|
151
198
|
output_config: z.object({ effort: reasoningEffortSchema.optional() }).strict().optional(),
|
|
@@ -175,6 +222,7 @@ const usageSchema = z
|
|
|
175
222
|
.strict();
|
|
176
223
|
const stopReasonSchema = z.enum(['end_turn', 'max_tokens', 'tool_use', 'refusal']);
|
|
177
224
|
const outputBlockSchema = z.discriminatedUnion('type', [
|
|
225
|
+
thinkingBlockSchema,
|
|
178
226
|
textBlockSchema,
|
|
179
227
|
toolUseBlockSchema.extend({ input: z.record(z.string(), z.unknown()) }),
|
|
180
228
|
]);
|
|
@@ -243,6 +291,13 @@ export const anthropicStreamEventSchema = z.discriminatedUnion('type', [
|
|
|
243
291
|
type: z.literal('content_block_start'),
|
|
244
292
|
index: z.number().int().nonnegative(),
|
|
245
293
|
content_block: z.discriminatedUnion('type', [
|
|
294
|
+
z
|
|
295
|
+
.object({
|
|
296
|
+
type: z.literal('thinking'),
|
|
297
|
+
thinking: z.literal(''),
|
|
298
|
+
signature: z.literal(''),
|
|
299
|
+
})
|
|
300
|
+
.strict(),
|
|
246
301
|
z.object({ type: z.literal('text'), text: z.literal('') }).strict(),
|
|
247
302
|
toolUseBlockSchema.extend({ input: z.object({}).strict() }),
|
|
248
303
|
]),
|
|
@@ -254,6 +309,8 @@ export const anthropicStreamEventSchema = z.discriminatedUnion('type', [
|
|
|
254
309
|
index: z.number().int().nonnegative(),
|
|
255
310
|
delta: z.discriminatedUnion('type', [
|
|
256
311
|
z.object({ type: z.literal('text_delta'), text: z.string() }).strict(),
|
|
312
|
+
z.object({ type: z.literal('thinking_delta'), thinking: z.string() }).strict(),
|
|
313
|
+
z.object({ type: z.literal('signature_delta'), signature: z.string() }).strict(),
|
|
257
314
|
z.object({ type: z.literal('input_json_delta'), partial_json: z.string() }).strict(),
|
|
258
315
|
]),
|
|
259
316
|
})
|
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
* `POST /v1/chat/completions` — the OpenAI-compatible surface.
|
|
3
3
|
*
|
|
4
4
|
* It speaks the flat OpenAI request and response shapes so an unmodified OpenAI
|
|
5
|
-
* SDK works against `baseURL: 'https://kaana.ai/v1'` with an `oxy_sk_…` key
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* SDK works against `baseURL: 'https://kaana.ai/v1'` with an `oxy_sk_…` key. Its
|
|
6
|
+
* one extension is `provider`, the OpenRouter-style routing preference (ADR
|
|
7
|
+
* 0008); every other capability with no OpenAI representation lives on
|
|
8
|
+
* `/v1/responses`. `.strict()` everywhere: a stock SDK
|
|
8
9
|
* sending a parameter Kaana does not implement is told so rather than having it
|
|
9
10
|
* silently dropped.
|
|
10
11
|
*
|
|
@@ -69,6 +70,10 @@ export declare const chatCompletionMessageSchema: z.ZodObject<{
|
|
|
69
70
|
}, z.core.$strict>, z.ZodObject<{
|
|
70
71
|
type: z.ZodLiteral<"refusal">;
|
|
71
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>;
|
|
72
77
|
}, z.core.$strict>], "type">>]>>>;
|
|
73
78
|
name: z.ZodOptional<z.ZodString>;
|
|
74
79
|
tool_call_id: z.ZodOptional<z.ZodString>;
|
|
@@ -141,6 +146,10 @@ export declare const chatCompletionsRequestSchema: z.ZodObject<{
|
|
|
141
146
|
}, z.core.$strict>, z.ZodObject<{
|
|
142
147
|
type: z.ZodLiteral<"refusal">;
|
|
143
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>;
|
|
144
153
|
}, z.core.$strict>], "type">>]>>>;
|
|
145
154
|
name: z.ZodOptional<z.ZodString>;
|
|
146
155
|
tool_call_id: z.ZodOptional<z.ZodString>;
|
|
@@ -214,6 +223,34 @@ export declare const chatCompletionsRequestSchema: z.ZodObject<{
|
|
|
214
223
|
}>;
|
|
215
224
|
}, z.core.$strict>>;
|
|
216
225
|
user: z.ZodOptional<z.ZodString>;
|
|
226
|
+
provider: z.ZodOptional<z.ZodObject<{
|
|
227
|
+
order: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
228
|
+
only: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
229
|
+
ignore: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
230
|
+
allow_fallbacks: z.ZodOptional<z.ZodBoolean>;
|
|
231
|
+
require_parameters: z.ZodOptional<z.ZodBoolean>;
|
|
232
|
+
quantizations: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
233
|
+
unknown: "unknown";
|
|
234
|
+
int4: "int4";
|
|
235
|
+
int8: "int8";
|
|
236
|
+
fp4: "fp4";
|
|
237
|
+
mxfp4: "mxfp4";
|
|
238
|
+
nvfp4: "nvfp4";
|
|
239
|
+
fp6: "fp6";
|
|
240
|
+
fp8: "fp8";
|
|
241
|
+
mxfp8: "mxfp8";
|
|
242
|
+
fp16: "fp16";
|
|
243
|
+
bf16: "bf16";
|
|
244
|
+
fp32: "fp32";
|
|
245
|
+
}>>>;
|
|
246
|
+
sort: z.ZodOptional<z.ZodEnum<{
|
|
247
|
+
latency: "latency";
|
|
248
|
+
throughput: "throughput";
|
|
249
|
+
}>>;
|
|
250
|
+
preferred_max_latency: z.ZodOptional<z.ZodNumber>;
|
|
251
|
+
preferred_min_throughput: z.ZodOptional<z.ZodNumber>;
|
|
252
|
+
}, z.core.$strict>>;
|
|
253
|
+
prompt_cache_key: z.ZodOptional<z.ZodString>;
|
|
217
254
|
}, z.core.$strict>;
|
|
218
255
|
/** OpenAI's usage block, with the audio members only when audio tokens were metered. */
|
|
219
256
|
export declare const chatCompletionUsageSchema: z.ZodObject<{
|
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
* `POST /v1/chat/completions` — the OpenAI-compatible surface.
|
|
3
3
|
*
|
|
4
4
|
* It speaks the flat OpenAI request and response shapes so an unmodified OpenAI
|
|
5
|
-
* SDK works against `baseURL: 'https://kaana.ai/v1'` with an `oxy_sk_…` key
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* SDK works against `baseURL: 'https://kaana.ai/v1'` with an `oxy_sk_…` key. Its
|
|
6
|
+
* one extension is `provider`, the OpenRouter-style routing preference (ADR
|
|
7
|
+
* 0008); every other capability with no OpenAI representation lives on
|
|
8
|
+
* `/v1/responses`. `.strict()` everywhere: a stock SDK
|
|
8
9
|
* sending a parameter Kaana does not implement is told so rather than having it
|
|
9
10
|
* silently dropped.
|
|
10
11
|
*
|
|
@@ -18,6 +19,7 @@ import { maxUtf16Length, minUtf16Length } from '../stringBounds.js';
|
|
|
18
19
|
import { reasoningEffortSchema } from './catalogue.js';
|
|
19
20
|
import { publicErrorCodeSchema } from './errors.js';
|
|
20
21
|
import { inferenceContentPartSchema } from './messages.js';
|
|
22
|
+
import { promptCacheKeySchema, providerPreferencesSchema } from './providerPreferences.js';
|
|
21
23
|
import { modelTargetSchema } from './responses.js';
|
|
22
24
|
/** `stop` in the OpenAI dialect: one sequence or a list of them. */
|
|
23
25
|
const openAiStopSchema = z.union([
|
|
@@ -139,6 +141,10 @@ export const chatCompletionsRequestSchema = z
|
|
|
139
141
|
* only. `X-Oxy-User-Id` wins when both are present.
|
|
140
142
|
*/
|
|
141
143
|
user: z.string().check(minUtf16Length(1)).check(maxUtf16Length(64)).optional(),
|
|
144
|
+
/** Routing preferences that can only narrow what the grant admits (ADR 0008). */
|
|
145
|
+
provider: providerPreferencesSchema.optional(),
|
|
146
|
+
/** OpenAI's field: keeps requests sharing a prompt prefix on one deployment. */
|
|
147
|
+
prompt_cache_key: promptCacheKeySchema.optional(),
|
|
142
148
|
})
|
|
143
149
|
.strict()
|
|
144
150
|
.superRefine((request, ctx) => {
|
|
@@ -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<{
|