@rulvar/anthropic 1.5.2 → 1.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/README.md +1 -1
- package/dist/index.d.ts +18 -10
- package/dist/index.js +49 -40
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@ compilation, `pause_turn` continuation, typed refusal outcomes, and
|
|
|
6
6
|
usage normalization. Exports the `anthropic` adapter factory; models are
|
|
7
7
|
addressed as `'anthropic:<model>'` in routing.
|
|
8
8
|
|
|
9
|
-
Part of [
|
|
9
|
+
Part of [Rulvar](https://rulvar.com), an embeddable TypeScript engine
|
|
10
10
|
for durable, budget-bounded multi-agent LLM workflows, where a completed
|
|
11
11
|
LLM call is never paid for twice. Full documentation:
|
|
12
12
|
[docs.rulvar.com](https://docs.rulvar.com).
|
package/dist/index.d.ts
CHANGED
|
@@ -17,7 +17,12 @@ declare const ANTHROPIC_MODELS: Record<string, AnthropicModelInfo>;
|
|
|
17
17
|
/**
|
|
18
18
|
* Unknown Anthropic models are assumed current-generation: adaptive
|
|
19
19
|
* thinking, native structured outputs, no sampling parameters. refreshCaps
|
|
20
|
-
* corrects window/output figures from the live model list.
|
|
20
|
+
* corrects window/output figures from the live model list. Pricing stays
|
|
21
|
+
* ABSENT for an unknown model: a fabricated row silently misprices every
|
|
22
|
+
* model newer than this table. Hosts price it via a versioned
|
|
23
|
+
* createEngine({ pricing }) row; until then its usage surfaces in
|
|
24
|
+
* CostReport.unpriced and a run ceiling warns that it cannot bound the
|
|
25
|
+
* model.
|
|
21
26
|
*/
|
|
22
27
|
declare function anthropicModelInfo(model: string): AnthropicModelInfo;
|
|
23
28
|
//#endregion
|
|
@@ -102,23 +107,26 @@ declare function mapStopReason(stopReason: string | null | undefined, stopDetail
|
|
|
102
107
|
*/
|
|
103
108
|
declare function normalizeAnthropicUsage(raw: Record<string, unknown> | undefined): Usage;
|
|
104
109
|
interface TurnMapping {
|
|
105
|
-
events: ChatEvent[];
|
|
106
110
|
/** Assistant content blocks collected verbatim (pause_turn continuation). */
|
|
107
111
|
assistantContent: Block[];
|
|
108
112
|
pauseTurn: boolean;
|
|
109
113
|
finished: boolean;
|
|
110
114
|
}
|
|
111
115
|
/**
|
|
112
|
-
* Maps one Messages API stream into ChatEvents
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
*
|
|
116
|
+
* Maps one Messages API stream into ChatEvents, yielding each canonical
|
|
117
|
+
* event AS the corresponding provider event is consumed: the consumer's
|
|
118
|
+
* pull drives the provider read (natural backpressure, no buffering, no
|
|
119
|
+
* detached work). The generator's RETURN value carries the accumulated
|
|
120
|
+
* turn state the adapter needs for pause_turn continuation. Yields an
|
|
121
|
+
* early usage event from message_start (the input side is known
|
|
122
|
+
* immediately) and exactly one terminal finish unless the turn paused
|
|
123
|
+
* (pause_turn) or errored. `carryRetained` holds thinking blocks from
|
|
124
|
+
* earlier pause_turn continuations of the same turn so the terminal
|
|
125
|
+
* finish ships the whole turn's retention payload (M4-T02).
|
|
118
126
|
*/
|
|
119
|
-
declare function mapAnthropicStream(stream: AsyncIterable<AnthropicStreamEvent>, ids: IdMap,
|
|
127
|
+
declare function mapAnthropicStream(stream: AsyncIterable<AnthropicStreamEvent>, ids: IdMap, options?: {
|
|
120
128
|
carryRetained?: Block[];
|
|
121
|
-
}):
|
|
129
|
+
}): AsyncGenerator<ChatEvent, TurnMapping>;
|
|
122
130
|
/**
|
|
123
131
|
* Projects an SDK/API error into the retryable WireError vocabulary:
|
|
124
132
|
* 429 rate limits surface retryAfterMs and the x-ratelimit-* buckets; 529
|
package/dist/index.js
CHANGED
|
@@ -17,12 +17,12 @@ function current(contextWindow, maxOutputTokens, pricing, cacheMinTokens) {
|
|
|
17
17
|
reasoningEfforts: ALL_EFFORTS,
|
|
18
18
|
contextWindow,
|
|
19
19
|
maxOutputTokens,
|
|
20
|
-
pricing: {
|
|
20
|
+
...pricing === void 0 ? {} : { pricing: {
|
|
21
21
|
inputUsdPerMTok: pricing.in,
|
|
22
22
|
outputUsdPerMTok: pricing.out,
|
|
23
23
|
cacheReadUsdPerMTok: pricing.cacheRead,
|
|
24
24
|
cacheWriteUsdPerMTok: pricing.cacheWrite
|
|
25
|
-
}
|
|
25
|
+
} }
|
|
26
26
|
},
|
|
27
27
|
thinkingForm: "adaptive",
|
|
28
28
|
cacheMinTokens
|
|
@@ -92,18 +92,23 @@ const ANTHROPIC_MODELS = {
|
|
|
92
92
|
/**
|
|
93
93
|
* Unknown Anthropic models are assumed current-generation: adaptive
|
|
94
94
|
* thinking, native structured outputs, no sampling parameters. refreshCaps
|
|
95
|
-
* corrects window/output figures from the live model list.
|
|
95
|
+
* corrects window/output figures from the live model list. Pricing stays
|
|
96
|
+
* ABSENT for an unknown model: a fabricated row silently misprices every
|
|
97
|
+
* model newer than this table. Hosts price it via a versioned
|
|
98
|
+
* createEngine({ pricing }) row; until then its usage surfaces in
|
|
99
|
+
* CostReport.unpriced and a run ceiling warns that it cannot bound the
|
|
100
|
+
* model.
|
|
96
101
|
*/
|
|
97
102
|
function anthropicModelInfo(model) {
|
|
98
103
|
const exact = ANTHROPIC_MODELS[model];
|
|
99
104
|
if (exact !== void 0) return exact;
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
105
|
+
let best;
|
|
106
|
+
for (const [name, info] of Object.entries(ANTHROPIC_MODELS)) if (model.startsWith(`${name}-`) && (best === void 0 || name.length > best.name.length)) best = {
|
|
107
|
+
name,
|
|
108
|
+
info
|
|
109
|
+
};
|
|
110
|
+
if (best !== void 0) return best.info;
|
|
111
|
+
return current(4e5, 64e3, void 0, 4096);
|
|
107
112
|
}
|
|
108
113
|
//#endregion
|
|
109
114
|
//#region src/wire.ts
|
|
@@ -412,24 +417,23 @@ function normalizeAnthropicUsage(raw) {
|
|
|
412
417
|
};
|
|
413
418
|
}
|
|
414
419
|
/**
|
|
415
|
-
* Maps one Messages API stream into ChatEvents
|
|
416
|
-
*
|
|
417
|
-
*
|
|
418
|
-
*
|
|
419
|
-
*
|
|
420
|
-
*
|
|
420
|
+
* Maps one Messages API stream into ChatEvents, yielding each canonical
|
|
421
|
+
* event AS the corresponding provider event is consumed: the consumer's
|
|
422
|
+
* pull drives the provider read (natural backpressure, no buffering, no
|
|
423
|
+
* detached work). The generator's RETURN value carries the accumulated
|
|
424
|
+
* turn state the adapter needs for pause_turn continuation. Yields an
|
|
425
|
+
* early usage event from message_start (the input side is known
|
|
426
|
+
* immediately) and exactly one terminal finish unless the turn paused
|
|
427
|
+
* (pause_turn) or errored. `carryRetained` holds thinking blocks from
|
|
428
|
+
* earlier pause_turn continuations of the same turn so the terminal
|
|
429
|
+
* finish ships the whole turn's retention payload (M4-T02).
|
|
421
430
|
*/
|
|
422
|
-
async function mapAnthropicStream(stream, ids,
|
|
431
|
+
async function* mapAnthropicStream(stream, ids, options) {
|
|
423
432
|
const mapping = {
|
|
424
|
-
events: [],
|
|
425
433
|
assistantContent: [],
|
|
426
434
|
pauseTurn: false,
|
|
427
435
|
finished: false
|
|
428
436
|
};
|
|
429
|
-
const push = (event) => {
|
|
430
|
-
mapping.events.push(event);
|
|
431
|
-
emit(event);
|
|
432
|
-
};
|
|
433
437
|
let usage = {
|
|
434
438
|
inputTokens: 0,
|
|
435
439
|
outputTokens: 0,
|
|
@@ -446,10 +450,10 @@ async function mapAnthropicStream(stream, ids, emit, options) {
|
|
|
446
450
|
const message = event.message;
|
|
447
451
|
responseId = typeof message?.id === "string" ? message.id : void 0;
|
|
448
452
|
usage = normalizeAnthropicUsage(message?.usage);
|
|
449
|
-
|
|
453
|
+
yield {
|
|
450
454
|
type: "usage",
|
|
451
455
|
usage: { ...usage }
|
|
452
|
-
}
|
|
456
|
+
};
|
|
453
457
|
break;
|
|
454
458
|
}
|
|
455
459
|
case "content_block_start": {
|
|
@@ -465,11 +469,11 @@ async function mapAnthropicStream(stream, ids, emit, options) {
|
|
|
465
469
|
json: "",
|
|
466
470
|
block: { ...block }
|
|
467
471
|
});
|
|
468
|
-
|
|
472
|
+
yield {
|
|
469
473
|
type: "tool-call-start",
|
|
470
474
|
id: canonicalId,
|
|
471
475
|
name: block.name
|
|
472
|
-
}
|
|
476
|
+
};
|
|
473
477
|
} else if (type === "thinking" || type === "redacted_thinking") openBlocks.set(index, {
|
|
474
478
|
kind: "thinking",
|
|
475
479
|
json: "",
|
|
@@ -498,25 +502,25 @@ async function mapAnthropicStream(stream, ids, emit, options) {
|
|
|
498
502
|
if (delta.type === "text_delta") {
|
|
499
503
|
const text = delta.text;
|
|
500
504
|
open.block.text = `${open.block.text ?? ""}${text}`;
|
|
501
|
-
|
|
505
|
+
yield {
|
|
502
506
|
type: "text-delta",
|
|
503
507
|
text
|
|
504
|
-
}
|
|
508
|
+
};
|
|
505
509
|
} else if (delta.type === "thinking_delta") {
|
|
506
510
|
const text = delta.thinking;
|
|
507
511
|
open.block.thinking = `${open.block.thinking ?? ""}${text}`;
|
|
508
|
-
|
|
512
|
+
yield {
|
|
509
513
|
type: "reasoning-delta",
|
|
510
514
|
text
|
|
511
|
-
}
|
|
515
|
+
};
|
|
512
516
|
} else if (delta.type === "input_json_delta") {
|
|
513
517
|
const partial = delta.partial_json;
|
|
514
518
|
open.json += partial;
|
|
515
|
-
if (open.canonicalId !== void 0)
|
|
519
|
+
if (open.canonicalId !== void 0) yield {
|
|
516
520
|
type: "tool-call-delta",
|
|
517
521
|
id: open.canonicalId,
|
|
518
522
|
argsTextDelta: partial
|
|
519
|
-
}
|
|
523
|
+
};
|
|
520
524
|
} else if (delta.type === "signature_delta") open.block.signature = `${open.block.signature ?? ""}${delta.signature}`;
|
|
521
525
|
break;
|
|
522
526
|
}
|
|
@@ -533,11 +537,11 @@ async function mapAnthropicStream(stream, ids, emit, options) {
|
|
|
533
537
|
args = { __unparsed: open.json };
|
|
534
538
|
}
|
|
535
539
|
open.block.input = args;
|
|
536
|
-
|
|
540
|
+
yield {
|
|
537
541
|
type: "tool-call-end",
|
|
538
542
|
id: open.canonicalId,
|
|
539
543
|
args
|
|
540
|
-
}
|
|
544
|
+
};
|
|
541
545
|
}
|
|
542
546
|
mapping.assistantContent.push(open.block);
|
|
543
547
|
break;
|
|
@@ -566,12 +570,12 @@ async function mapAnthropicStream(stream, ids, emit, options) {
|
|
|
566
570
|
if (stopSequence !== void 0) meta.stopSequence = stopSequence;
|
|
567
571
|
const retained = [...options?.carryRetained ?? [], ...mapping.assistantContent.filter((block) => block.type === "thinking" || block.type === "redacted_thinking")];
|
|
568
572
|
if (retained.length > 0) meta.retainedParts = retained;
|
|
569
|
-
|
|
573
|
+
yield {
|
|
570
574
|
type: "finish",
|
|
571
575
|
finish: mapped.finish ?? { reason: "stop" },
|
|
572
576
|
usage,
|
|
573
577
|
providerMetadata
|
|
574
|
-
}
|
|
578
|
+
};
|
|
575
579
|
mapping.finished = true;
|
|
576
580
|
return mapping;
|
|
577
581
|
}
|
|
@@ -696,7 +700,6 @@ function anthropic(options = {}) {
|
|
|
696
700
|
maxOutputTokens: info.caps.maxOutputTokens,
|
|
697
701
|
thinkingForm: info.thinkingForm
|
|
698
702
|
});
|
|
699
|
-
const pending = [];
|
|
700
703
|
let continuations = 0;
|
|
701
704
|
const carryRetained = [];
|
|
702
705
|
while (true) {
|
|
@@ -713,9 +716,17 @@ function anthropic(options = {}) {
|
|
|
713
716
|
};
|
|
714
717
|
return;
|
|
715
718
|
}
|
|
719
|
+
const mapper = mapAnthropicStream(stream, ids, { carryRetained });
|
|
716
720
|
let mapping;
|
|
717
721
|
try {
|
|
718
|
-
|
|
722
|
+
while (true) {
|
|
723
|
+
const next = await mapper.next();
|
|
724
|
+
if (next.done === true) {
|
|
725
|
+
mapping = next.value;
|
|
726
|
+
break;
|
|
727
|
+
}
|
|
728
|
+
yield next.value;
|
|
729
|
+
}
|
|
719
730
|
} catch (thrown) {
|
|
720
731
|
if (signal?.aborted === true) return;
|
|
721
732
|
yield {
|
|
@@ -724,8 +735,6 @@ function anthropic(options = {}) {
|
|
|
724
735
|
};
|
|
725
736
|
return;
|
|
726
737
|
}
|
|
727
|
-
for (const event of pending) yield event;
|
|
728
|
-
pending.length = 0;
|
|
729
738
|
if (!mapping.pauseTurn) return;
|
|
730
739
|
carryRetained.push(...mapping.assistantContent.filter((block) => block.type === "thinking" || block.type === "redacted_thinking"));
|
|
731
740
|
continuations += 1;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rulvar/anthropic",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.7.0",
|
|
4
|
+
"description": "Rulvar first-class provider adapter over @anthropic-ai/sdk.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
7
7
|
"engines": {
|
|
@@ -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.7.0"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@types/node": "^22.20.0",
|