@rulvar/anthropic 1.0.0 → 1.2.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 +17 -12
- package/dist/index.js +106 -19
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -6,13 +6,13 @@ interface AnthropicModelInfo {
|
|
|
6
6
|
/**
|
|
7
7
|
* Wire thinking form: current models accept only adaptive; the
|
|
8
8
|
* enabled/budget form remains functional only on Opus 4.6 and Sonnet
|
|
9
|
-
* 4.6
|
|
9
|
+
* 4.6.
|
|
10
10
|
*/
|
|
11
11
|
thinkingForm: "adaptive" | "enabled-budget";
|
|
12
|
-
/** Minimum cacheable prefix in tokens
|
|
12
|
+
/** Minimum cacheable prefix in tokens. */
|
|
13
13
|
cacheMinTokens: number;
|
|
14
14
|
}
|
|
15
|
-
/** Static seed table
|
|
15
|
+
/** Static seed table naming the current model set. */
|
|
16
16
|
declare const ANTHROPIC_MODELS: Record<string, AnthropicModelInfo>;
|
|
17
17
|
/**
|
|
18
18
|
* Unknown Anthropic models are assumed current-generation: adaptive
|
|
@@ -22,7 +22,7 @@ declare const ANTHROPIC_MODELS: Record<string, AnthropicModelInfo>;
|
|
|
22
22
|
declare function anthropicModelInfo(model: string): AnthropicModelInfo;
|
|
23
23
|
//#endregion
|
|
24
24
|
//#region src/adapter.d.ts
|
|
25
|
-
/** pause_turn continuation cap
|
|
25
|
+
/** pause_turn continuation cap. */
|
|
26
26
|
declare const DEFAULT_PAUSE_TURN_MAX_CONTINUATIONS = 5;
|
|
27
27
|
/** The client sub-surface the adapter consumes; injectable for tests. */
|
|
28
28
|
interface AnthropicClientLike {
|
|
@@ -51,12 +51,12 @@ interface AnthropicAdapterOptions {
|
|
|
51
51
|
/**
|
|
52
52
|
* Creates the first-class Anthropic adapter (id 'anthropic'). SDK
|
|
53
53
|
* autoretries are disabled (max_retries 0): the core owns retries and
|
|
54
|
-
* wall-clock
|
|
54
|
+
* wall-clock.
|
|
55
55
|
*/
|
|
56
56
|
declare function anthropic(options?: AnthropicAdapterOptions): ProviderAdapter;
|
|
57
57
|
//#endregion
|
|
58
58
|
//#region src/wire.d.ts
|
|
59
|
-
/** Bijective canonical-to-wire tool-call id map
|
|
59
|
+
/** Bijective canonical-to-wire tool-call id map. */
|
|
60
60
|
declare class IdMap {
|
|
61
61
|
private readonly toWire;
|
|
62
62
|
private readonly toCanonical;
|
|
@@ -67,10 +67,15 @@ declare class IdMap {
|
|
|
67
67
|
}
|
|
68
68
|
type Block = Record<string, unknown>;
|
|
69
69
|
/**
|
|
70
|
+
* Returns a deep copy of the schema with the unsupported keywords
|
|
71
|
+
* removed at SCHEMA positions only: a property literally named
|
|
72
|
+
* "minimum" (a key inside `properties`) survives. The input is never
|
|
73
|
+
* mutated; unrecognized keywords are copied through untouched.
|
|
74
|
+
*/
|
|
75
|
+
/**
|
|
70
76
|
* Builds Messages API params from a ChatRequest. cacheHint compiles into
|
|
71
77
|
* cache_control breakpoints; beyond the provider cap of 4 the DEEPEST
|
|
72
|
-
* breakpoints are kept and the shallowest dropped, deterministically
|
|
73
|
-
* (docs/04, sections 1.7 and 4.4).
|
|
78
|
+
* breakpoints are kept and the shallowest dropped, deterministically.
|
|
74
79
|
*/
|
|
75
80
|
declare function buildAnthropicParams(req: ChatRequest, options: {
|
|
76
81
|
ids: IdMap;
|
|
@@ -86,14 +91,14 @@ interface MappedStop {
|
|
|
86
91
|
pauseTurn: boolean;
|
|
87
92
|
}
|
|
88
93
|
/**
|
|
89
|
-
* The
|
|
94
|
+
* The stop-reason table. pause_turn never surfaces as
|
|
90
95
|
* a canonical finish: the adapter continues internally.
|
|
91
96
|
*/
|
|
92
97
|
declare function mapStopReason(stopReason: string | null | undefined, stopDetails: Record<string, unknown> | null | undefined): MappedStop;
|
|
93
98
|
/**
|
|
94
99
|
* Normalizes Messages API usage under the Usage invariant: Anthropic
|
|
95
100
|
* reports input_tokens EXCLUDING cache reads and writes, so the canonical
|
|
96
|
-
* inputTokens is the sum of all three
|
|
101
|
+
* inputTokens is the sum of all three.
|
|
97
102
|
*/
|
|
98
103
|
declare function normalizeAnthropicUsage(raw: Record<string, unknown> | undefined): Usage;
|
|
99
104
|
interface TurnMapping {
|
|
@@ -109,7 +114,7 @@ interface TurnMapping {
|
|
|
109
114
|
* terminal finish unless the turn paused (pause_turn) or errored.
|
|
110
115
|
* `carryRetained` holds thinking blocks from earlier pause_turn
|
|
111
116
|
* continuations of the same turn so the terminal finish ships the whole
|
|
112
|
-
* turn's retention payload (
|
|
117
|
+
* turn's retention payload (M4-T02).
|
|
113
118
|
*/
|
|
114
119
|
declare function mapAnthropicStream(stream: AsyncIterable<AnthropicStreamEvent>, ids: IdMap, emit: (event: ChatEvent) => void, options?: {
|
|
115
120
|
carryRetained?: Block[];
|
|
@@ -118,7 +123,7 @@ declare function mapAnthropicStream(stream: AsyncIterable<AnthropicStreamEvent>,
|
|
|
118
123
|
* Projects an SDK/API error into the retryable WireError vocabulary:
|
|
119
124
|
* 429 rate limits surface retryAfterMs and the x-ratelimit-* buckets; 529
|
|
120
125
|
* overloaded and 5xx are retryable transport; everything else is terminal
|
|
121
|
-
* transport
|
|
126
|
+
* transport. Adapters never sleep internally.
|
|
122
127
|
*/
|
|
123
128
|
declare function anthropicErrorToWire(error: unknown): WireError;
|
|
124
129
|
//#endregion
|
package/dist/index.js
CHANGED
|
@@ -28,7 +28,7 @@ function current(contextWindow, maxOutputTokens, pricing, cacheMinTokens) {
|
|
|
28
28
|
cacheMinTokens
|
|
29
29
|
};
|
|
30
30
|
}
|
|
31
|
-
/** Static seed table
|
|
31
|
+
/** Static seed table naming the current model set. */
|
|
32
32
|
const ANTHROPIC_MODELS = {
|
|
33
33
|
"claude-fable-5": current(1e6, 128e3, {
|
|
34
34
|
in: 20,
|
|
@@ -54,6 +54,22 @@ const ANTHROPIC_MODELS = {
|
|
|
54
54
|
cacheRead: .3,
|
|
55
55
|
cacheWrite: 3.75
|
|
56
56
|
}, 2048),
|
|
57
|
+
"claude-haiku-4-5": (() => {
|
|
58
|
+
const base = current(2e5, 64e3, {
|
|
59
|
+
in: 1,
|
|
60
|
+
out: 5,
|
|
61
|
+
cacheRead: .1,
|
|
62
|
+
cacheWrite: 1.25
|
|
63
|
+
}, 2048);
|
|
64
|
+
return {
|
|
65
|
+
...base,
|
|
66
|
+
caps: {
|
|
67
|
+
...base.caps,
|
|
68
|
+
reasoningEfforts: []
|
|
69
|
+
},
|
|
70
|
+
thinkingForm: "enabled-budget"
|
|
71
|
+
};
|
|
72
|
+
})(),
|
|
57
73
|
"claude-opus-4-6": {
|
|
58
74
|
...current(2e5, 32e3, {
|
|
59
75
|
in: 15,
|
|
@@ -98,10 +114,10 @@ function anthropicModelInfo(model) {
|
|
|
98
114
|
* the SSE-to-ChatEvent stream mapper with pause_turn absorption, the full
|
|
99
115
|
* stop-reason table, and usage normalization under the Usage invariant.
|
|
100
116
|
*
|
|
101
|
-
*
|
|
117
|
+
* Adapter contract: https://docs.rulvar.com/guide/adapter-authors.
|
|
102
118
|
* Pure functions; the adapter glue in adapter.ts owns the SDK client.
|
|
103
119
|
*/
|
|
104
|
-
/** Bijective canonical-to-wire tool-call id map
|
|
120
|
+
/** Bijective canonical-to-wire tool-call id map. */
|
|
105
121
|
var IdMap = class {
|
|
106
122
|
toWire = /* @__PURE__ */ new Map();
|
|
107
123
|
toCanonical = /* @__PURE__ */ new Map();
|
|
@@ -126,6 +142,75 @@ var IdMap = class {
|
|
|
126
142
|
return wireId;
|
|
127
143
|
}
|
|
128
144
|
};
|
|
145
|
+
/**
|
|
146
|
+
* Keywords the constrained-decoding schema validator rejects with a
|
|
147
|
+
* live 400 ("For 'integer' type, property 'minimum' is not
|
|
148
|
+
* supported"): every numeric bound plus, asymmetrically, maxItems
|
|
149
|
+
* (minItems, the string bounds, pattern, format, enum and const all
|
|
150
|
+
* pass). The validator guards exactly two wire positions: tools sent
|
|
151
|
+
* with strict: true and output_config.format json_schema; plain tools
|
|
152
|
+
* accept full JSON Schema. Probed live on claude-sonnet-5, 2026-07-11.
|
|
153
|
+
* The engine still validates tool args and
|
|
154
|
+
* structured output against the UNSCRUBBED schema, so the dropped
|
|
155
|
+
* keywords stay enforced; only the model-side hint is lost.
|
|
156
|
+
*/
|
|
157
|
+
const CONSTRAINED_DECODING_UNSUPPORTED = /* @__PURE__ */ new Set([
|
|
158
|
+
"minimum",
|
|
159
|
+
"maximum",
|
|
160
|
+
"exclusiveMinimum",
|
|
161
|
+
"exclusiveMaximum",
|
|
162
|
+
"multipleOf",
|
|
163
|
+
"maxItems"
|
|
164
|
+
]);
|
|
165
|
+
/** Keywords whose value is a map of property NAMES to schemas. */
|
|
166
|
+
const SCHEMA_MAP_KEYWORDS = /* @__PURE__ */ new Set([
|
|
167
|
+
"properties",
|
|
168
|
+
"patternProperties",
|
|
169
|
+
"$defs",
|
|
170
|
+
"definitions"
|
|
171
|
+
]);
|
|
172
|
+
/** Keywords whose value is a schema or an array of schemas. */
|
|
173
|
+
const SCHEMA_VALUE_KEYWORDS = /* @__PURE__ */ new Set([
|
|
174
|
+
"items",
|
|
175
|
+
"prefixItems",
|
|
176
|
+
"additionalProperties",
|
|
177
|
+
"additionalItems",
|
|
178
|
+
"propertyNames",
|
|
179
|
+
"contains",
|
|
180
|
+
"anyOf",
|
|
181
|
+
"oneOf",
|
|
182
|
+
"allOf",
|
|
183
|
+
"not",
|
|
184
|
+
"if",
|
|
185
|
+
"then",
|
|
186
|
+
"else"
|
|
187
|
+
]);
|
|
188
|
+
/**
|
|
189
|
+
* Returns a deep copy of the schema with the unsupported keywords
|
|
190
|
+
* removed at SCHEMA positions only: a property literally named
|
|
191
|
+
* "minimum" (a key inside `properties`) survives. The input is never
|
|
192
|
+
* mutated; unrecognized keywords are copied through untouched.
|
|
193
|
+
*/
|
|
194
|
+
function scrubForConstrainedDecoding(schema) {
|
|
195
|
+
if (Array.isArray(schema)) return schema.map((entry) => scrubForConstrainedDecoding(entry));
|
|
196
|
+
if (schema === null || typeof schema !== "object") return schema;
|
|
197
|
+
const out = {};
|
|
198
|
+
for (const [key, value] of Object.entries(schema)) {
|
|
199
|
+
if (CONSTRAINED_DECODING_UNSUPPORTED.has(key)) continue;
|
|
200
|
+
if (SCHEMA_MAP_KEYWORDS.has(key) && value !== null && typeof value === "object") {
|
|
201
|
+
const map = {};
|
|
202
|
+
for (const [name, sub] of Object.entries(value)) map[name] = scrubForConstrainedDecoding(sub);
|
|
203
|
+
out[key] = map;
|
|
204
|
+
continue;
|
|
205
|
+
}
|
|
206
|
+
if (SCHEMA_VALUE_KEYWORDS.has(key)) {
|
|
207
|
+
out[key] = scrubForConstrainedDecoding(value);
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
out[key] = value;
|
|
211
|
+
}
|
|
212
|
+
return out;
|
|
213
|
+
}
|
|
129
214
|
function cacheControl(ttl) {
|
|
130
215
|
return ttl === "1h" ? {
|
|
131
216
|
type: "ephemeral",
|
|
@@ -135,8 +220,7 @@ function cacheControl(ttl) {
|
|
|
135
220
|
/**
|
|
136
221
|
* Builds Messages API params from a ChatRequest. cacheHint compiles into
|
|
137
222
|
* cache_control breakpoints; beyond the provider cap of 4 the DEEPEST
|
|
138
|
-
* breakpoints are kept and the shallowest dropped, deterministically
|
|
139
|
-
* (docs/04, sections 1.7 and 4.4).
|
|
223
|
+
* breakpoints are kept and the shallowest dropped, deterministically.
|
|
140
224
|
*/
|
|
141
225
|
function buildAnthropicParams(req, options) {
|
|
142
226
|
const systemBlocks = [];
|
|
@@ -203,12 +287,15 @@ function buildAnthropicParams(req, options) {
|
|
|
203
287
|
if (systemBlocks.length > 0) params.system = systemBlocks;
|
|
204
288
|
if (req.stopSequences !== void 0) params.stop_sequences = req.stopSequences;
|
|
205
289
|
if (req.tools !== void 0) {
|
|
206
|
-
params.tools = req.tools.map((tool) =>
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
290
|
+
params.tools = req.tools.map((tool) => {
|
|
291
|
+
const strict = isStrictCompatibleSchema(tool.parameters);
|
|
292
|
+
return {
|
|
293
|
+
name: tool.name,
|
|
294
|
+
description: tool.description,
|
|
295
|
+
input_schema: strict ? scrubForConstrainedDecoding(tool.parameters) : tool.parameters,
|
|
296
|
+
...strict ? { strict: true } : {}
|
|
297
|
+
};
|
|
298
|
+
});
|
|
212
299
|
if (req.toolChoice === "required") params.tool_choice = { type: "any" };
|
|
213
300
|
else if (typeof req.toolChoice === "object") params.tool_choice = {
|
|
214
301
|
type: "tool",
|
|
@@ -222,7 +309,7 @@ function buildAnthropicParams(req, options) {
|
|
|
222
309
|
if (req.effort !== void 0) outputConfig.effort = req.effort;
|
|
223
310
|
if (req.schema !== void 0) outputConfig.format = {
|
|
224
311
|
type: "json_schema",
|
|
225
|
-
schema: req.schema
|
|
312
|
+
schema: scrubForConstrainedDecoding(req.schema)
|
|
226
313
|
};
|
|
227
314
|
if (anthropicOptions.task_budget !== void 0) outputConfig.task_budget = anthropicOptions.task_budget;
|
|
228
315
|
if (Object.keys(outputConfig).length > 0) params.output_config = outputConfig;
|
|
@@ -264,7 +351,7 @@ function applyCacheHint(params, hint) {
|
|
|
264
351
|
}
|
|
265
352
|
}
|
|
266
353
|
/**
|
|
267
|
-
* The
|
|
354
|
+
* The stop-reason table. pause_turn never surfaces as
|
|
268
355
|
* a canonical finish: the adapter continues internally.
|
|
269
356
|
*/
|
|
270
357
|
function mapStopReason(stopReason, stopDetails) {
|
|
@@ -310,7 +397,7 @@ function mapStopReason(stopReason, stopDetails) {
|
|
|
310
397
|
/**
|
|
311
398
|
* Normalizes Messages API usage under the Usage invariant: Anthropic
|
|
312
399
|
* reports input_tokens EXCLUDING cache reads and writes, so the canonical
|
|
313
|
-
* inputTokens is the sum of all three
|
|
400
|
+
* inputTokens is the sum of all three.
|
|
314
401
|
*/
|
|
315
402
|
function normalizeAnthropicUsage(raw) {
|
|
316
403
|
const input = typeof raw?.input_tokens === "number" ? raw.input_tokens : 0;
|
|
@@ -330,7 +417,7 @@ function normalizeAnthropicUsage(raw) {
|
|
|
330
417
|
* terminal finish unless the turn paused (pause_turn) or errored.
|
|
331
418
|
* `carryRetained` holds thinking blocks from earlier pause_turn
|
|
332
419
|
* continuations of the same turn so the terminal finish ships the whole
|
|
333
|
-
* turn's retention payload (
|
|
420
|
+
* turn's retention payload (M4-T02).
|
|
334
421
|
*/
|
|
335
422
|
async function mapAnthropicStream(stream, ids, emit, options) {
|
|
336
423
|
const mapping = {
|
|
@@ -496,7 +583,7 @@ async function mapAnthropicStream(stream, ids, emit, options) {
|
|
|
496
583
|
* Projects an SDK/API error into the retryable WireError vocabulary:
|
|
497
584
|
* 429 rate limits surface retryAfterMs and the x-ratelimit-* buckets; 529
|
|
498
585
|
* overloaded and 5xx are retryable transport; everything else is terminal
|
|
499
|
-
* transport
|
|
586
|
+
* transport. Adapters never sleep internally.
|
|
500
587
|
*/
|
|
501
588
|
function anthropicErrorToWire(error) {
|
|
502
589
|
const record = error;
|
|
@@ -551,14 +638,14 @@ function anthropicErrorToWire(error) {
|
|
|
551
638
|
* wire mapping, with pause_turn absorption, SDK autoretries disabled, and
|
|
552
639
|
* refreshCaps from the capabilities-bearing model list.
|
|
553
640
|
*
|
|
554
|
-
*
|
|
641
|
+
* Full contract: https://docs.rulvar.com/guide/providers.
|
|
555
642
|
*/
|
|
556
|
-
/** pause_turn continuation cap
|
|
643
|
+
/** pause_turn continuation cap. */
|
|
557
644
|
const DEFAULT_PAUSE_TURN_MAX_CONTINUATIONS = 5;
|
|
558
645
|
/**
|
|
559
646
|
* Creates the first-class Anthropic adapter (id 'anthropic'). SDK
|
|
560
647
|
* autoretries are disabled (max_retries 0): the core owns retries and
|
|
561
|
-
* wall-clock
|
|
648
|
+
* wall-clock.
|
|
562
649
|
*/
|
|
563
650
|
function anthropic(options = {}) {
|
|
564
651
|
const client = options.client ?? new Anthropic({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rulvar/anthropic",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "rulvar first-class provider adapter over @anthropic-ai/sdk.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"@anthropic-ai/sdk": "^0.110.0",
|
|
26
|
-
"@rulvar/core": "1.
|
|
26
|
+
"@rulvar/core": "1.2.0"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@types/node": "^22.20.0",
|