@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
package/dist/public/messages.js
CHANGED
|
@@ -33,34 +33,44 @@ export const inferenceContentSourceSchema = z.discriminatedUnion('kind', [
|
|
|
33
33
|
/**
|
|
34
34
|
* One part of a message's content. A message is always a list of parts.
|
|
35
35
|
*
|
|
36
|
-
* ## `refusal`
|
|
36
|
+
* ## `refusal` and `reasoning` are members, and neither is ever answer text
|
|
37
37
|
*
|
|
38
38
|
* A model that DECLINES says why, and those words are meant for the customer:
|
|
39
39
|
* they are the difference between "rephrase this" and "stop asking". Before this
|
|
40
40
|
* member existed there was nowhere in an {@link InferenceMessage} to put them, so
|
|
41
|
-
* a non-streaming fold kept `finishReason: 'refusal'` and dropped the sentence
|
|
42
|
-
*
|
|
43
|
-
*
|
|
41
|
+
* a non-streaming fold kept `finishReason: 'refusal'` and dropped the sentence.
|
|
42
|
+
* The part is a MEMBER rather than a field because a refusal need not have text:
|
|
43
|
+
* an Anthropic `stop_reason: "refusal"` maps to the finish reason and separates
|
|
44
|
+
* no words from the answer, while an OpenAI-compatible `refusal` does.
|
|
44
45
|
*
|
|
45
|
-
*
|
|
46
|
-
* working, and a `text` part is where somebody would put it — which renders
|
|
47
|
-
* private reasoning to the customer AS the answer, the product bug the delta
|
|
48
|
-
* channels exist to prevent. An opaque per-block reasoning blob crossing this
|
|
49
|
-
* boundary needs a home nobody has chosen yet, and inventing one here would
|
|
50
|
-
* choose it by accident.
|
|
46
|
+
* ## `reasoning` (contract set 8.6.0, Kaana ADR 0009 decision 2)
|
|
51
47
|
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
* standard-client parseability, and carrying reasoning would.
|
|
48
|
+
* Reasoning was deliberately absent until the owner chose its home, because an
|
|
49
|
+
* opaque per-block reasoning blob had none. The cost of that absence was
|
|
50
|
+
* correctness: a thinking model that calls a tool cannot be continued unless the
|
|
51
|
+
* assistant's reasoning blocks, with their signatures, come back to the provider
|
|
52
|
+
* unmodified and in order, and a customer who only ever received reasoning TEXT
|
|
53
|
+
* on the `reasoning` delta channel had nothing to send back.
|
|
59
54
|
*
|
|
60
|
-
* The part is
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
55
|
+
* The part is `{type: 'reasoning', text?, opaque?}`:
|
|
56
|
+
*
|
|
57
|
+
* - `text` is what a person may read. It is a display value and is never
|
|
58
|
+
* forwarded to a provider on its own.
|
|
59
|
+
* - `opaque` is a continuation token the customer MUST return UNMODIFIED, in the
|
|
60
|
+
* position it arrived. Its content is Kaana's to define and the customer's to
|
|
61
|
+
* treat as a sealed string: it is provider-neutral on the surface and carries
|
|
62
|
+
* whatever the serving provider needs to continue. Sealing is NOT
|
|
63
|
+
* cryptographic: a forged or edited token is no more than a request the
|
|
64
|
+
* provider refuses, so nothing may rely on it for trust.
|
|
65
|
+
* - at least one of the two is present.
|
|
66
|
+
*
|
|
67
|
+
* A reasoning part is the assistant's alone, exactly as a refusal is. It is
|
|
68
|
+
* never a `text` part, so no renderer can present private reasoning as the
|
|
69
|
+
* answer, and the delta channels keep reasoning apart for the same reason.
|
|
70
|
+
*
|
|
71
|
+
* What a route does with a token it cannot read (it was issued by another
|
|
72
|
+
* provider family, after a failover or a model switch) is drop it, never fail:
|
|
73
|
+
* the continuation is lost, the conversation is not.
|
|
64
74
|
*/
|
|
65
75
|
export const inferenceContentPartSchema = z.discriminatedUnion('type', [
|
|
66
76
|
z.object({ type: z.literal('text'), text: z.string() }).strict(),
|
|
@@ -85,6 +95,20 @@ export const inferenceContentPartSchema = z.discriminatedUnion('type', [
|
|
|
85
95
|
* renderer can present a refusal as the answer that was asked for.
|
|
86
96
|
*/
|
|
87
97
|
z.object({ type: z.literal('refusal'), text: z.string() }).strict(),
|
|
98
|
+
/**
|
|
99
|
+
* The assistant's reasoning, readable and/or as an opaque continuation token
|
|
100
|
+
* to return unmodified. See the member note above.
|
|
101
|
+
*/
|
|
102
|
+
z
|
|
103
|
+
.object({
|
|
104
|
+
type: z.literal('reasoning'),
|
|
105
|
+
text: z.string().optional(),
|
|
106
|
+
opaque: z.string().check(minUtf16Length(1)).optional(),
|
|
107
|
+
})
|
|
108
|
+
.strict()
|
|
109
|
+
.refine((part) => part.text !== undefined || part.opaque !== undefined, {
|
|
110
|
+
message: 'a reasoning part carries text, an opaque token, or both',
|
|
111
|
+
}),
|
|
88
112
|
]);
|
|
89
113
|
/* -------------------------------------------------------------------------- */
|
|
90
114
|
/* Image input (contract set 8.2.0, Kaana ADR 0007) */
|
|
@@ -257,15 +281,15 @@ export const inferenceMessageSchema = z
|
|
|
257
281
|
});
|
|
258
282
|
}
|
|
259
283
|
// Same rule as `toolCalls`, for the same reason: only the assistant can
|
|
260
|
-
// decline, so
|
|
261
|
-
// silently ignore — and one a renderer might not.
|
|
284
|
+
// decline or reason, so either part on any other role is one every provider
|
|
285
|
+
// would silently ignore — and one a renderer might not.
|
|
262
286
|
if (message.role !== 'assistant') {
|
|
263
287
|
for (const [index, part] of message.content.entries()) {
|
|
264
|
-
if (part.type === 'refusal') {
|
|
288
|
+
if (part.type === 'refusal' || part.type === 'reasoning') {
|
|
265
289
|
ctx.addIssue({
|
|
266
290
|
code: 'custom',
|
|
267
291
|
path: ['content', index, 'type'],
|
|
268
|
-
message:
|
|
292
|
+
message: `only an assistant message carries a ${part.type}`,
|
|
269
293
|
});
|
|
270
294
|
}
|
|
271
295
|
}
|
|
@@ -327,12 +351,33 @@ export const responseFormatSchema = z.discriminatedUnion('type', [
|
|
|
327
351
|
]);
|
|
328
352
|
/**
|
|
329
353
|
* The caller's reasoning control. Strict, like every leaf: a provider-specific
|
|
330
|
-
* knob (`
|
|
354
|
+
* knob (`summary`) is refused rather than silently dropped.
|
|
355
|
+
*
|
|
356
|
+
* - `effort` is how much to reason, in the catalogue's words. Oxy forwards it
|
|
357
|
+
* only after checking the resolved model advertises it in `reasoningEfforts`.
|
|
358
|
+
* - `maxTokens` is a thinking BUDGET in tokens. It is the other way to size
|
|
359
|
+
* reasoning, so it excludes `effort`. A route that cannot take a budget
|
|
360
|
+
* refuses it with `invalid_request` naming `reasoning.maxTokens`.
|
|
361
|
+
* - `exclude: true` means the model may still reason, and be billed for it, but
|
|
362
|
+
* no reasoning is returned: no `reasoning` delta, no reasoning part, no opaque
|
|
363
|
+
* token. A caller that excludes reasoning cannot continue it.
|
|
331
364
|
*
|
|
332
|
-
*
|
|
333
|
-
*
|
|
365
|
+
* Carrying `reasoning` at all, even as `{}`, opts in to receiving reasoning
|
|
366
|
+
* continuation tokens (the `opaque` field of a `reasoning` delta); a request
|
|
367
|
+
* without it never receives one, which is what keeps older readers of the
|
|
368
|
+
* stream unaffected.
|
|
334
369
|
*/
|
|
335
|
-
export const inferenceReasoningSchema = z
|
|
370
|
+
export const inferenceReasoningSchema = z
|
|
371
|
+
.object({
|
|
372
|
+
effort: reasoningEffortSchema.optional(),
|
|
373
|
+
maxTokens: z.number().int().min(1).max(2_147_483_647).optional(),
|
|
374
|
+
exclude: z.boolean().optional(),
|
|
375
|
+
})
|
|
376
|
+
.strict()
|
|
377
|
+
.refine((reasoning) => reasoning.effort === undefined || reasoning.maxTokens === undefined, {
|
|
378
|
+
message: 'reasoning takes an effort or a maxTokens budget, not both',
|
|
379
|
+
path: ['maxTokens'],
|
|
380
|
+
});
|
|
336
381
|
/** Parameters for text-to-speech, preserved in the signed request. */
|
|
337
382
|
export const inferenceSpeechParametersSchema = z
|
|
338
383
|
.object({
|
|
@@ -92,6 +92,10 @@ export declare const responsesRequestSchema: z.ZodObject<{
|
|
|
92
92
|
}, z.core.$strict>, z.ZodObject<{
|
|
93
93
|
type: z.ZodLiteral<"refusal">;
|
|
94
94
|
text: z.ZodString;
|
|
95
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
96
|
+
type: z.ZodLiteral<"reasoning">;
|
|
97
|
+
text: z.ZodOptional<z.ZodString>;
|
|
98
|
+
opaque: z.ZodOptional<z.ZodString>;
|
|
95
99
|
}, z.core.$strict>], "type">>;
|
|
96
100
|
name: z.ZodOptional<z.ZodString>;
|
|
97
101
|
toolCallId: z.ZodOptional<z.ZodString>;
|
|
@@ -136,11 +140,13 @@ export declare const responsesRequestSchema: z.ZodObject<{
|
|
|
136
140
|
strict: z.ZodBoolean;
|
|
137
141
|
}, z.core.$strict>], "type">>;
|
|
138
142
|
reasoning: z.ZodOptional<z.ZodObject<{
|
|
139
|
-
effort: z.ZodEnum<{
|
|
143
|
+
effort: z.ZodOptional<z.ZodEnum<{
|
|
140
144
|
low: "low";
|
|
141
145
|
medium: "medium";
|
|
142
146
|
high: "high";
|
|
143
|
-
}
|
|
147
|
+
}>>;
|
|
148
|
+
maxTokens: z.ZodOptional<z.ZodNumber>;
|
|
149
|
+
exclude: z.ZodOptional<z.ZodBoolean>;
|
|
144
150
|
}, z.core.$strict>>;
|
|
145
151
|
labels: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
146
152
|
clientRequestId: z.ZodOptional<z.ZodString>;
|
|
@@ -240,6 +246,10 @@ export declare const responseSchema: z.ZodObject<{
|
|
|
240
246
|
}, z.core.$strict>, z.ZodObject<{
|
|
241
247
|
type: z.ZodLiteral<"refusal">;
|
|
242
248
|
text: z.ZodString;
|
|
249
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
250
|
+
type: z.ZodLiteral<"reasoning">;
|
|
251
|
+
text: z.ZodOptional<z.ZodString>;
|
|
252
|
+
opaque: z.ZodOptional<z.ZodString>;
|
|
243
253
|
}, z.core.$strict>], "type">>;
|
|
244
254
|
name: z.ZodOptional<z.ZodString>;
|
|
245
255
|
toolCallId: z.ZodOptional<z.ZodString>;
|
|
@@ -25,6 +25,7 @@ export declare const inferenceStreamDeltaEventSchema: z.ZodObject<{
|
|
|
25
25
|
output_audio_transcript: "output_audio_transcript";
|
|
26
26
|
}>;
|
|
27
27
|
text: z.ZodString;
|
|
28
|
+
opaque: z.ZodOptional<z.ZodString>;
|
|
28
29
|
}, z.core.$strip>;
|
|
29
30
|
/** The encodings an audio output may carry. */
|
|
30
31
|
export declare const inferenceAudioMediaTypeSchema: z.ZodEnum<{
|
|
@@ -238,6 +239,7 @@ export declare const responseStreamEventSchema: z.ZodDiscriminatedUnion<[z.ZodOb
|
|
|
238
239
|
output_audio_transcript: "output_audio_transcript";
|
|
239
240
|
}>;
|
|
240
241
|
text: z.ZodString;
|
|
242
|
+
opaque: z.ZodOptional<z.ZodString>;
|
|
241
243
|
}, z.core.$strip>, z.ZodObject<{
|
|
242
244
|
schemaVersion: z.ZodLiteral<1>;
|
|
243
245
|
type: z.ZodLiteral<"audio">;
|
|
@@ -32,6 +32,14 @@ export const inferenceStreamDeltaEventSchema = z.object({
|
|
|
32
32
|
*/
|
|
33
33
|
channel: z.enum(['output_text', 'reasoning', 'refusal', 'output_audio_transcript']),
|
|
34
34
|
text: z.string(),
|
|
35
|
+
/**
|
|
36
|
+
* Contract set 8.6.0. On the `reasoning` channel only: the continuation token
|
|
37
|
+
* of one finished reasoning block, which the customer returns UNMODIFIED as the
|
|
38
|
+
* `opaque` of a `reasoning` content part, in the order the blocks arrived.
|
|
39
|
+
* Emitted once per block, after the block's text deltas (with empty `text`),
|
|
40
|
+
* and only to a request that carried `reasoning` and did not `exclude` it.
|
|
41
|
+
*/
|
|
42
|
+
opaque: z.string().check(minUtf16Length(1)).optional(),
|
|
35
43
|
});
|
|
36
44
|
/** The encodings an audio output may carry. */
|
|
37
45
|
export const inferenceAudioMediaTypeSchema = z.enum([
|
package/dist/public/version.d.ts
CHANGED
|
@@ -100,7 +100,7 @@
|
|
|
100
100
|
* change to, say, the catalogue reject every in-flight inference request; the
|
|
101
101
|
* per-shape `schemaVersion` is what a message is validated against.
|
|
102
102
|
*/
|
|
103
|
-
export declare const INFERENCE_CONTRACT_VERSION = "8.
|
|
103
|
+
export declare const INFERENCE_CONTRACT_VERSION = "8.7.0";
|
|
104
104
|
/**
|
|
105
105
|
* Contract set 4.0.0 (Kaana ADR 0002) is the first published as
|
|
106
106
|
* `@kaana.ai/contracts`. MAJOR because the set changed hands and split in two:
|
|
@@ -214,6 +214,15 @@ export declare const INFERENCE_CONTRACT_VERSION = "8.5.0";
|
|
|
214
214
|
* `promptCacheKey`) on `POST /v1/chat/completions` and `POST /v1/responses`
|
|
215
215
|
* (Kaana ADR 0008). The preference only narrows what the grant admits. Nothing
|
|
216
216
|
* in 8.4.0 changes and the signed grant and envelope are untouched.
|
|
217
|
+
*
|
|
218
|
+
* Contract set 8.6.0 is additive: reasoning continuity (Kaana ADR 0009 decision
|
|
219
|
+
* 2). `reasoning` takes `maxTokens` and `exclude` beside `effort` (all optional;
|
|
220
|
+
* `effort` and `maxTokens` are exclusive), a message's content gains the
|
|
221
|
+
* assistant-only `reasoning` part (`text?`, `opaque?`), and a `reasoning` delta
|
|
222
|
+
* may carry `opaque`. Every 8.5.0 message parses the same; the delta's `opaque`
|
|
223
|
+
* is emitted only to a request that carried `reasoning`. A consumer on 8.5.0 or
|
|
224
|
+
* earlier (Oxy's legacy signed lane) refuses a message or request that carries
|
|
225
|
+
* what is new, so Oxy reads it before a customer sends it.
|
|
217
226
|
*/
|
|
218
227
|
/** The public API's one origin and version. */
|
|
219
228
|
export declare const KAANA_API_BASE_URL = "https://kaana.ai/v1";
|
package/dist/public/version.js
CHANGED
|
@@ -100,7 +100,7 @@
|
|
|
100
100
|
* change to, say, the catalogue reject every in-flight inference request; the
|
|
101
101
|
* per-shape `schemaVersion` is what a message is validated against.
|
|
102
102
|
*/
|
|
103
|
-
export const INFERENCE_CONTRACT_VERSION = '8.
|
|
103
|
+
export const INFERENCE_CONTRACT_VERSION = '8.7.0';
|
|
104
104
|
/**
|
|
105
105
|
* Contract set 4.0.0 (Kaana ADR 0002) is the first published as
|
|
106
106
|
* `@kaana.ai/contracts`. MAJOR because the set changed hands and split in two:
|
|
@@ -214,6 +214,15 @@ export const INFERENCE_CONTRACT_VERSION = '8.5.0';
|
|
|
214
214
|
* `promptCacheKey`) on `POST /v1/chat/completions` and `POST /v1/responses`
|
|
215
215
|
* (Kaana ADR 0008). The preference only narrows what the grant admits. Nothing
|
|
216
216
|
* in 8.4.0 changes and the signed grant and envelope are untouched.
|
|
217
|
+
*
|
|
218
|
+
* Contract set 8.6.0 is additive: reasoning continuity (Kaana ADR 0009 decision
|
|
219
|
+
* 2). `reasoning` takes `maxTokens` and `exclude` beside `effort` (all optional;
|
|
220
|
+
* `effort` and `maxTokens` are exclusive), a message's content gains the
|
|
221
|
+
* assistant-only `reasoning` part (`text?`, `opaque?`), and a `reasoning` delta
|
|
222
|
+
* may carry `opaque`. Every 8.5.0 message parses the same; the delta's `opaque`
|
|
223
|
+
* is emitted only to a request that carried `reasoning`. A consumer on 8.5.0 or
|
|
224
|
+
* earlier (Oxy's legacy signed lane) refuses a message or request that carries
|
|
225
|
+
* what is new, so Oxy reads it before a customer sends it.
|
|
217
226
|
*/
|
|
218
227
|
/** The public API's one origin and version. */
|
|
219
228
|
export const KAANA_API_BASE_URL = 'https://kaana.ai/v1';
|