@kindgi/adapter-model-anthropic 0.1.4-rc.5 → 0.1.5-rc.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 +10 -3
- package/dist/cache.d.ts +42 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +67 -0
- package/dist/cache.js.map +1 -0
- package/dist/cost.d.ts +11 -0
- package/dist/cost.d.ts.map +1 -1
- package/dist/cost.js +8 -2
- package/dist/cost.js.map +1 -1
- package/dist/entry.d.ts +18 -0
- package/dist/entry.d.ts.map +1 -0
- package/dist/entry.js +42 -0
- package/dist/entry.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/provider.d.ts +4 -5
- package/dist/provider.d.ts.map +1 -1
- package/dist/provider.js +47 -9
- package/dist/provider.js.map +1 -1
- package/dist/translate.d.ts +5 -0
- package/dist/translate.d.ts.map +1 -1
- package/dist/translate.js +5 -0
- package/dist/translate.js.map +1 -1
- package/package.json +2 -2
- package/src/cache.ts +96 -0
- package/src/cost.ts +21 -2
- package/src/entry.ts +55 -0
- package/src/index.ts +8 -0
- package/src/provider.ts +55 -17
- package/src/translate.ts +6 -0
package/README.md
CHANGED
|
@@ -6,16 +6,23 @@ Anthropic `ModelProvider` for [`@kindgi/capabilities`](../../capabilities/). Wra
|
|
|
6
6
|
|
|
7
7
|
Translate between the framework's `ModelCallInput` / `ModelCallResult` and a non-streaming `messages.create` call:
|
|
8
8
|
|
|
9
|
-
- `system` messages are lifted into the top-level `system` parameter
|
|
9
|
+
- `system` messages are lifted into the top-level `system` parameter, each its own text block, in order. `tool` messages become `tool_result` blocks folded into user turns, and assistant `toolCalls` become `tool_use` blocks.
|
|
10
10
|
- Tool names are encoded `.` → `__` on send and decoded on receive, because the Messages API rejects dots in tool names (`acme.orders.lookup` ↔ `acme__orders__lookup`). Tool ids must not contain a literal `__`.
|
|
11
11
|
- `max_tokens` is always sent, since Anthropic requires it: `input.maxOutputTokens`, else the model's `ModelInfo.maxOutputTokens`, else `4096`. `temperature` is sent when set, and `abortSignal` is passed to the request.
|
|
12
12
|
- `stop_reason` maps `end_turn` / `stop_sequence` / `pause_turn` → `stop`, `max_tokens` → `length`, `tool_use` → `tool-use`, `refusal` → `content-filter`, anything else → `stop`.
|
|
13
13
|
- Cost accounting that includes prompt caching. Anthropic reports four counters (`input_tokens`, `output_tokens`, `cache_creation_input_tokens`, `cache_read_input_tokens`), and `costUsd` bills each at its own rate:
|
|
14
14
|
`(input × rate + cacheCreation × rate × creationMultiplier + cacheRead × rate × readMultiplier + output × outputRate) / 1000`.
|
|
15
|
-
The multiplier defaults match the 5-minute cache tier (creation `1.25`, read `0.1`)
|
|
15
|
+
The multiplier defaults match the 5-minute cache tier (creation `1.25`, read `0.1`). Claude Opus 5.5 and Sonnet 5.5 read at `0.05`: set `promptCacheReadMultiplier: 0.05` in their `cost` (the `anthropic` preset does). `usage.promptTokens` includes cache writes and reads; `usage.cacheReadTokens` and `usage.cacheWriteTokens` report them.
|
|
16
|
+
- **Prompt caching.** Anthropic caches only the prefixes a request marks with `cache_control`, so the adapter marks up to three (`withPromptCache`), each with the 5-minute cache:
|
|
17
|
+
- the last tool (the tool definitions);
|
|
18
|
+
- the first system block (the agent's prompt; later system blocks, such as retrieved context, change from turn to turn);
|
|
19
|
+
- the last block of the last message, when another call will send this prefix again: the call has tools (the next step of a tool loop) or the conversation has an earlier answer (its next turn). A one-off call (no tools, no earlier answer, e.g. a judge) leaves its message unmarked: writing a tail that's never read again would only cost more.
|
|
20
|
+
|
|
21
|
+
The next call in a turn then reads the prefix at the read rate and writes only what's new. A prefix shorter than the model's minimum (from 512 tokens on the Claude 5.5 models) isn't cached and costs nothing extra. How Anthropic keeps cached prompts, and their eligibility for zero data retention: Anthropic's [prompt caching](https://platform.claude.com/docs/en/build-with-claude/prompt-caching) and [API and data retention](https://platform.claude.com/docs/en/manage-claude/api-and-data-retention) pages.
|
|
16
22
|
|
|
17
23
|
## Exports
|
|
18
24
|
|
|
25
|
+
- **`anthropicAdapterEntry`** (`ANTHROPIC_ADAPTER_ID`) — the `AdapterFactoryEntry` a runtime registers. **`anthropicAdapterFactory`** builds the provider from a registration whose `secret_ref` names its Anthropic API key (resolved on every call); without one it throws, and **`anthropicCheckConfig(input)`** reports the same problem (`secret_ref`) without building anything.
|
|
19
26
|
- **`createAnthropicProvider(options)`** — returns a `ModelProvider` whose `metadata` is `options.metadata`. `invoke()` throws when `input.model` is not one of `metadata.models[].name`.
|
|
20
27
|
- **`AnthropicProviderOptions`**:
|
|
21
28
|
- `apiKey: string | (() => string | Promise<string>)` — a static key, or a resolver called on every `invoke()`. The SDK client is cached and rebuilt only when the resolved key changes, so a rotated secret takes effect on the next call. A per-tenant registry can register one provider per tenant whose resolver reads that tenant's secret.
|
|
@@ -74,7 +81,7 @@ A single-key deployment passes `apiKey: process.env.ANTHROPIC_API_KEY` (checked
|
|
|
74
81
|
- **Streaming.** `invoke()` resolves with the complete response; streaming would need a different `ModelProvider` interface.
|
|
75
82
|
- **Extended thinking.** `ModelMessage` has no thinking field; `thinking` blocks in responses are dropped.
|
|
76
83
|
- **Image inputs.** `ModelMessage` content is text only.
|
|
77
|
-
- **Structured output.** `structuredOutput` on `ModelCallInput` is ignored.
|
|
84
|
+
- **Structured output.** `structuredOutput` on `ModelCallInput` is ignored. No Kindgi caller sends it today: an agent's typed output is checked by parse and repair on every provider, so the anthropic preset's models still declare `structured-output` (they can follow a JSON schema natively).
|
|
78
85
|
- **Retry logic in the adapter.** Retries and timeouts are the SDK client's (`clientOptions.maxRetries`, `clientOptions.timeout`).
|
|
79
86
|
|
|
80
87
|
## Related
|
package/dist/cache.d.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type Anthropic from '@anthropic-ai/sdk';
|
|
2
|
+
/**
|
|
3
|
+
* Prompt caching. Anthropic caches only the prompt prefixes a request
|
|
4
|
+
* marks with `cache_control`, and a later request that starts with the
|
|
5
|
+
* same bytes reads them at a fraction of the input price (0.1x; 0.05x on
|
|
6
|
+
* Claude Opus 5.5 and Sonnet 5.5). A marked prefix costs 1.25x the first
|
|
7
|
+
* time it's written. The prompt renders in the order tools, system,
|
|
8
|
+
* messages, and the adapter marks up to three breakpoints:
|
|
9
|
+
*
|
|
10
|
+
* - the last tool: the tool definitions, the same for every call an
|
|
11
|
+
* agent makes;
|
|
12
|
+
* - the first system block: the agent's own prompt. Later system blocks
|
|
13
|
+
* (retrieved context) change from turn to turn, so they stay after it;
|
|
14
|
+
* - the last block of the last message, when another call will re-send
|
|
15
|
+
* this prefix: a call with tools (the next step of a tool loop sends
|
|
16
|
+
* everything again plus the results) or a conversation with an earlier
|
|
17
|
+
* answer (its next turn does). A one-off call (no tools, no earlier
|
|
18
|
+
* answer, e.g. a judge) leaves its message unmarked: its tail is never
|
|
19
|
+
* sent again, so a write would only cost more.
|
|
20
|
+
*
|
|
21
|
+
* Each breakpoint uses the 5-minute cache (the default `ephemeral` TTL);
|
|
22
|
+
* the steps of an agent turn are seconds apart. A prefix shorter than the
|
|
23
|
+
* model's minimum (512 to 4,096 tokens) isn't cached and costs nothing
|
|
24
|
+
* extra. How Anthropic keeps cached prompts, and their eligibility for
|
|
25
|
+
* zero data retention: https://platform.claude.com/docs/en/build-with-claude/prompt-caching
|
|
26
|
+
* and https://platform.claude.com/docs/en/manage-claude/api-and-data-retention.
|
|
27
|
+
*/
|
|
28
|
+
export declare const PROMPT_CACHE: Anthropic.CacheControlEphemeral;
|
|
29
|
+
export interface CacheableRequest {
|
|
30
|
+
/** The call's system messages, in order, each its own block. */
|
|
31
|
+
readonly systemParts: readonly string[];
|
|
32
|
+
readonly tools: readonly Anthropic.Tool[] | undefined;
|
|
33
|
+
readonly messages: readonly Anthropic.MessageParam[];
|
|
34
|
+
}
|
|
35
|
+
export interface CachedRequest {
|
|
36
|
+
readonly system: Anthropic.TextBlockParam[] | undefined;
|
|
37
|
+
readonly tools: Anthropic.Tool[] | undefined;
|
|
38
|
+
readonly messages: Anthropic.MessageParam[];
|
|
39
|
+
}
|
|
40
|
+
/** The request's parts, with the cache breakpoints above. The inputs aren't changed. */
|
|
41
|
+
export declare function withPromptCache(request: CacheableRequest): CachedRequest;
|
|
42
|
+
//# sourceMappingURL=cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,SAAS,MAAM,mBAAmB,CAAC;AAE/C;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,YAAY,EAAE,SAAS,CAAC,qBAA6C,CAAC;AAEnF,MAAM,WAAW,gBAAgB;IAC/B,gEAAgE;IAChE,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IACxC,QAAQ,CAAC,KAAK,EAAE,SAAS,SAAS,CAAC,IAAI,EAAE,GAAG,SAAS,CAAC;IACtD,QAAQ,CAAC,QAAQ,EAAE,SAAS,SAAS,CAAC,YAAY,EAAE,CAAC;CACtD;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC,cAAc,EAAE,GAAG,SAAS,CAAC;IACxD,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,IAAI,EAAE,GAAG,SAAS,CAAC;IAC7C,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC,YAAY,EAAE,CAAC;CAC7C;AAED,wFAAwF;AACxF,wBAAgB,eAAe,CAAC,OAAO,EAAE,gBAAgB,GAAG,aAAa,CAiBxE"}
|
package/dist/cache.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright (C) 2026 Kindgi Inc.
|
|
3
|
+
/**
|
|
4
|
+
* Prompt caching. Anthropic caches only the prompt prefixes a request
|
|
5
|
+
* marks with `cache_control`, and a later request that starts with the
|
|
6
|
+
* same bytes reads them at a fraction of the input price (0.1x; 0.05x on
|
|
7
|
+
* Claude Opus 5.5 and Sonnet 5.5). A marked prefix costs 1.25x the first
|
|
8
|
+
* time it's written. The prompt renders in the order tools, system,
|
|
9
|
+
* messages, and the adapter marks up to three breakpoints:
|
|
10
|
+
*
|
|
11
|
+
* - the last tool: the tool definitions, the same for every call an
|
|
12
|
+
* agent makes;
|
|
13
|
+
* - the first system block: the agent's own prompt. Later system blocks
|
|
14
|
+
* (retrieved context) change from turn to turn, so they stay after it;
|
|
15
|
+
* - the last block of the last message, when another call will re-send
|
|
16
|
+
* this prefix: a call with tools (the next step of a tool loop sends
|
|
17
|
+
* everything again plus the results) or a conversation with an earlier
|
|
18
|
+
* answer (its next turn does). A one-off call (no tools, no earlier
|
|
19
|
+
* answer, e.g. a judge) leaves its message unmarked: its tail is never
|
|
20
|
+
* sent again, so a write would only cost more.
|
|
21
|
+
*
|
|
22
|
+
* Each breakpoint uses the 5-minute cache (the default `ephemeral` TTL);
|
|
23
|
+
* the steps of an agent turn are seconds apart. A prefix shorter than the
|
|
24
|
+
* model's minimum (512 to 4,096 tokens) isn't cached and costs nothing
|
|
25
|
+
* extra. How Anthropic keeps cached prompts, and their eligibility for
|
|
26
|
+
* zero data retention: https://platform.claude.com/docs/en/build-with-claude/prompt-caching
|
|
27
|
+
* and https://platform.claude.com/docs/en/manage-claude/api-and-data-retention.
|
|
28
|
+
*/
|
|
29
|
+
export const PROMPT_CACHE = { type: 'ephemeral' };
|
|
30
|
+
/** The request's parts, with the cache breakpoints above. The inputs aren't changed. */
|
|
31
|
+
export function withPromptCache(request) {
|
|
32
|
+
const tools = request.tools === undefined || request.tools.length === 0
|
|
33
|
+
? undefined
|
|
34
|
+
: request.tools.map((tool, i, all) => i === all.length - 1 ? { ...tool, cache_control: PROMPT_CACHE } : tool);
|
|
35
|
+
const system = request.systemParts.length === 0
|
|
36
|
+
? undefined
|
|
37
|
+
: request.systemParts.map((text, i) => i === 0 ? { type: 'text', text, cache_control: PROMPT_CACHE } : { type: 'text', text });
|
|
38
|
+
const continues = tools !== undefined || request.messages.some((m) => m.role === 'assistant');
|
|
39
|
+
const messages = continues ? markLastMessage(request.messages) : [...request.messages];
|
|
40
|
+
return { system, tools, messages };
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* The messages with a breakpoint on the last block of the last one that
|
|
44
|
+
* can carry it: text (not empty), a tool call, a tool result.
|
|
45
|
+
*/
|
|
46
|
+
function markLastMessage(messages) {
|
|
47
|
+
const out = [...messages];
|
|
48
|
+
const last = out[out.length - 1];
|
|
49
|
+
if (last === undefined)
|
|
50
|
+
return out;
|
|
51
|
+
const blocks = typeof last.content === 'string' ? [{ type: 'text', text: last.content }] : [...last.content];
|
|
52
|
+
for (let i = blocks.length - 1; i >= 0; i -= 1) {
|
|
53
|
+
const block = blocks[i];
|
|
54
|
+
if (cacheable(block)) {
|
|
55
|
+
blocks[i] = { ...block, cache_control: PROMPT_CACHE };
|
|
56
|
+
out[out.length - 1] = { ...last, content: blocks };
|
|
57
|
+
return out;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return out;
|
|
61
|
+
}
|
|
62
|
+
function cacheable(block) {
|
|
63
|
+
if (block.type === 'text')
|
|
64
|
+
return block.text.length > 0;
|
|
65
|
+
return block.type === 'tool_use' || block.type === 'tool_result';
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"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"}
|
package/dist/cost.d.ts
CHANGED
|
@@ -21,6 +21,17 @@ export interface CostRates {
|
|
|
21
21
|
readonly completionUsdPer1kTokens: number;
|
|
22
22
|
readonly promptCacheCreationMultiplier?: number;
|
|
23
23
|
readonly promptCacheReadMultiplier?: number;
|
|
24
|
+
/**
|
|
25
|
+
* Long-context pricing: when a call's prompt (regular, cache-write and
|
|
26
|
+
* cache-read tokens together) exceeds `thresholdTokens`, the whole call
|
|
27
|
+
* bills at these rates, the cache multipliers applying to the long
|
|
28
|
+
* prompt rate. Claude Haiku 5.5 is 5x past a 100,000-token prompt.
|
|
29
|
+
*/
|
|
30
|
+
readonly longContext?: {
|
|
31
|
+
readonly thresholdTokens: number;
|
|
32
|
+
readonly promptUsdPer1kTokens: number;
|
|
33
|
+
readonly completionUsdPer1kTokens: number;
|
|
34
|
+
};
|
|
24
35
|
}
|
|
25
36
|
/**
|
|
26
37
|
* Compute the USD cost of a single Anthropic invocation from the
|
package/dist/cost.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cost.d.ts","sourceRoot":"","sources":["../src/cost.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,SAAS,MAAM,mBAAmB,CAAC;AAC/C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE1D;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,sCAAsC,OAAO,CAAC;AAC3D,eAAO,MAAM,6BAA6B,MAAM,CAAC;AAEjD,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC;IACtC,QAAQ,CAAC,wBAAwB,EAAE,MAAM,CAAC;IAC1C,QAAQ,CAAC,6BAA6B,CAAC,EAAE,MAAM,CAAC;IAChD,QAAQ,CAAC,yBAAyB,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"cost.d.ts","sourceRoot":"","sources":["../src/cost.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,SAAS,MAAM,mBAAmB,CAAC;AAC/C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE1D;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,sCAAsC,OAAO,CAAC;AAC3D,eAAO,MAAM,6BAA6B,MAAM,CAAC;AAEjD,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC;IACtC,QAAQ,CAAC,wBAAwB,EAAE,MAAM,CAAC;IAC1C,QAAQ,CAAC,6BAA6B,CAAC,EAAE,MAAM,CAAC;IAChD,QAAQ,CAAC,yBAAyB,CAAC,EAAE,MAAM,CAAC;IAC5C;;;;;OAKG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE;QACrB,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;QACjC,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC;QACtC,QAAQ,CAAC,wBAAwB,EAAE,MAAM,CAAC;KAC3C,CAAC;CACH;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,SAAS,CAAC,KAAK,EAAE,KAAK,EAAE,SAAS,GAAG,MAAM,CA4B/E;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,SAAS,CAAC,KAAK,GAAG,aAAa,CAUtE"}
|
package/dist/cost.js
CHANGED
|
@@ -33,8 +33,14 @@ export const DEFAULT_CACHE_READ_MULTIPLIER = 0.1;
|
|
|
33
33
|
* rates without double-counting.
|
|
34
34
|
*/
|
|
35
35
|
export function computeCostUsd(usage, rates) {
|
|
36
|
-
const
|
|
37
|
-
|
|
36
|
+
const promptTokens = usage.input_tokens +
|
|
37
|
+
(usage.cache_creation_input_tokens ?? 0) +
|
|
38
|
+
(usage.cache_read_input_tokens ?? 0);
|
|
39
|
+
const long = rates.longContext !== undefined && promptTokens > rates.longContext.thresholdTokens
|
|
40
|
+
? rates.longContext
|
|
41
|
+
: undefined;
|
|
42
|
+
const inputRate = long?.promptUsdPer1kTokens ?? rates.promptUsdPer1kTokens;
|
|
43
|
+
const outputRate = long?.completionUsdPer1kTokens ?? rates.completionUsdPer1kTokens;
|
|
38
44
|
const creationMultiplier = rates.promptCacheCreationMultiplier ?? DEFAULT_CACHE_CREATION_MULTIPLIER_5MIN;
|
|
39
45
|
const readMultiplier = rates.promptCacheReadMultiplier ?? DEFAULT_CACHE_READ_MULTIPLIER;
|
|
40
46
|
const inputTokens = usage.input_tokens;
|
package/dist/cost.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cost.js","sourceRoot":"","sources":["../src/cost.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,iCAAiC;AAKjC;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,sCAAsC,GAAG,IAAI,CAAC;AAC3D,MAAM,CAAC,MAAM,6BAA6B,GAAG,GAAG,CAAC;
|
|
1
|
+
{"version":3,"file":"cost.js","sourceRoot":"","sources":["../src/cost.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,iCAAiC;AAKjC;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,sCAAsC,GAAG,IAAI,CAAC;AAC3D,MAAM,CAAC,MAAM,6BAA6B,GAAG,GAAG,CAAC;AAoBjD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,cAAc,CAAC,KAAsB,EAAE,KAAgB;IACrE,MAAM,YAAY,GAChB,KAAK,CAAC,YAAY;QAClB,CAAC,KAAK,CAAC,2BAA2B,IAAI,CAAC,CAAC;QACxC,CAAC,KAAK,CAAC,uBAAuB,IAAI,CAAC,CAAC,CAAC;IACvC,MAAM,IAAI,GACR,KAAK,CAAC,WAAW,KAAK,SAAS,IAAI,YAAY,GAAG,KAAK,CAAC,WAAW,CAAC,eAAe;QACjF,CAAC,CAAC,KAAK,CAAC,WAAW;QACnB,CAAC,CAAC,SAAS,CAAC;IAChB,MAAM,SAAS,GAAG,IAAI,EAAE,oBAAoB,IAAI,KAAK,CAAC,oBAAoB,CAAC;IAC3E,MAAM,UAAU,GAAG,IAAI,EAAE,wBAAwB,IAAI,KAAK,CAAC,wBAAwB,CAAC;IACpF,MAAM,kBAAkB,GACtB,KAAK,CAAC,6BAA6B,IAAI,sCAAsC,CAAC;IAChF,MAAM,cAAc,GAAG,KAAK,CAAC,yBAAyB,IAAI,6BAA6B,CAAC;IAExF,MAAM,WAAW,GAAG,KAAK,CAAC,YAAY,CAAC;IACvC,MAAM,YAAY,GAAG,KAAK,CAAC,aAAa,CAAC;IACzC,MAAM,aAAa,GAAG,KAAK,CAAC,2BAA2B,IAAI,CAAC,CAAC;IAC7D,MAAM,SAAS,GAAG,KAAK,CAAC,uBAAuB,IAAI,CAAC,CAAC;IAErD,MAAM,SAAS,GACb,CAAC,WAAW,GAAG,SAAS;QACtB,aAAa,GAAG,SAAS,GAAG,kBAAkB;QAC9C,SAAS,GAAG,SAAS,GAAG,cAAc,CAAC;QACzC,IAAI,CAAC;IACP,MAAM,UAAU,GAAG,CAAC,YAAY,GAAG,UAAU,CAAC,GAAG,IAAI,CAAC;IAEtD,OAAO,SAAS,GAAG,UAAU,CAAC;AAChC,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAsB;IACrD,MAAM,UAAU,GAAG,KAAK,CAAC,2BAA2B,CAAC;IACrD,MAAM,SAAS,GAAG,KAAK,CAAC,uBAAuB,CAAC;IAChD,OAAO;QACL,YAAY,EAAE,KAAK,CAAC,YAAY,GAAG,CAAC,UAAU,IAAI,CAAC,CAAC,GAAG,CAAC,SAAS,IAAI,CAAC,CAAC;QACvE,gBAAgB,EAAE,KAAK,CAAC,aAAa;QACrC,iDAAiD;QACjD,GAAG,CAAC,OAAO,SAAS,KAAK,QAAQ,IAAI,EAAE,eAAe,EAAE,SAAS,EAAE,CAAC;QACpE,GAAG,CAAC,OAAO,UAAU,KAAK,QAAQ,IAAI,EAAE,gBAAgB,EAAE,UAAU,EAAE,CAAC;KACxE,CAAC;AACJ,CAAC"}
|
package/dist/entry.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type AdapterConfigCheckInput, type AdapterConfigProblem, type AdapterFactory, type AdapterFactoryEntry } from '@kindgi/capabilities';
|
|
2
|
+
/** The id the runtime registers this adapter under. */
|
|
3
|
+
export declare const ANTHROPIC_ADAPTER_ID = "@kindgi/adapter-model-anthropic";
|
|
4
|
+
/**
|
|
5
|
+
* The runtime's factory. A provider registered with it names its Anthropic
|
|
6
|
+
* API key in `secret_ref`, resolved on every call, so a rotated key takes
|
|
7
|
+
* effect on the next one.
|
|
8
|
+
*/
|
|
9
|
+
export declare const anthropicAdapterFactory: AdapterFactory;
|
|
10
|
+
/**
|
|
11
|
+
* What's wrong with a registration for this adapter, read without building
|
|
12
|
+
* it (`AdapterFactoryEntry.checkConfig`): it needs a `secret_ref`. The
|
|
13
|
+
* problem's message is the error the factory throws for it.
|
|
14
|
+
*/
|
|
15
|
+
export declare function anthropicCheckConfig(input: AdapterConfigCheckInput): readonly AdapterConfigProblem[];
|
|
16
|
+
/** The entry a runtime registers: the factory, and its static check. */
|
|
17
|
+
export declare const anthropicAdapterEntry: AdapterFactoryEntry;
|
|
18
|
+
//# sourceMappingURL=entry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entry.d.ts","sourceRoot":"","sources":["../src/entry.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,KAAK,uBAAuB,EAC5B,KAAK,oBAAoB,EACzB,KAAK,cAAc,EACnB,KAAK,mBAAmB,EAEzB,MAAM,sBAAsB,CAAC;AAI9B,uDAAuD;AACvD,eAAO,MAAM,oBAAoB,oCAAoC,CAAC;AAEtE;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,EAAE,cAQrC,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,uBAAuB,GAC7B,SAAS,oBAAoB,EAAE,CAGjC;AAED,wEAAwE;AACxE,eAAO,MAAM,qBAAqB,EAAE,mBAKnC,CAAC"}
|
package/dist/entry.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright (C) 2026 Kindgi Inc.
|
|
3
|
+
import { adapterConfigError, } from '@kindgi/capabilities';
|
|
4
|
+
import { createAnthropicProvider } from './provider.js';
|
|
5
|
+
/** The id the runtime registers this adapter under. */
|
|
6
|
+
export const ANTHROPIC_ADAPTER_ID = '@kindgi/adapter-model-anthropic';
|
|
7
|
+
/**
|
|
8
|
+
* The runtime's factory. A provider registered with it names its Anthropic
|
|
9
|
+
* API key in `secret_ref`, resolved on every call, so a rotated key takes
|
|
10
|
+
* effect on the next one.
|
|
11
|
+
*/
|
|
12
|
+
export const anthropicAdapterFactory = (input) => {
|
|
13
|
+
const problem = keyProblem(input.resolveApiKey !== undefined);
|
|
14
|
+
if (problem !== undefined)
|
|
15
|
+
throw adapterConfigError(ANTHROPIC_ADAPTER_ID, input.metadata.id, problem);
|
|
16
|
+
return createAnthropicProvider({
|
|
17
|
+
apiKey: input.resolveApiKey,
|
|
18
|
+
metadata: input.metadata,
|
|
19
|
+
});
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* What's wrong with a registration for this adapter, read without building
|
|
23
|
+
* it (`AdapterFactoryEntry.checkConfig`): it needs a `secret_ref`. The
|
|
24
|
+
* problem's message is the error the factory throws for it.
|
|
25
|
+
*/
|
|
26
|
+
export function anthropicCheckConfig(input) {
|
|
27
|
+
const problem = keyProblem(input.hasSecretRef);
|
|
28
|
+
return problem !== undefined ? [problem] : [];
|
|
29
|
+
}
|
|
30
|
+
/** The entry a runtime registers: the factory, and its static check. */
|
|
31
|
+
export const anthropicAdapterEntry = {
|
|
32
|
+
adapterId: ANTHROPIC_ADAPTER_ID,
|
|
33
|
+
capabilityKind: 'llm-inference',
|
|
34
|
+
factory: anthropicAdapterFactory,
|
|
35
|
+
checkConfig: anthropicCheckConfig,
|
|
36
|
+
};
|
|
37
|
+
function keyProblem(hasSecretRef) {
|
|
38
|
+
if (hasSecretRef)
|
|
39
|
+
return undefined;
|
|
40
|
+
return { path: '/secret_ref', message: 'needs secret_ref: its Anthropic API key.' };
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=entry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entry.js","sourceRoot":"","sources":["../src/entry.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,iCAAiC;AAEjC,OAAO,EAKL,kBAAkB,GACnB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAExD,uDAAuD;AACvD,MAAM,CAAC,MAAM,oBAAoB,GAAG,iCAAiC,CAAC;AAEtE;;;;GAIG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAmB,CAAC,KAAK,EAAE,EAAE;IAC/D,MAAM,OAAO,GAAG,UAAU,CAAC,KAAK,CAAC,aAAa,KAAK,SAAS,CAAC,CAAC;IAC9D,IAAI,OAAO,KAAK,SAAS;QACvB,MAAM,kBAAkB,CAAC,oBAAoB,EAAE,KAAK,CAAC,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;IAC7E,OAAO,uBAAuB,CAAC;QAC7B,MAAM,EAAE,KAAK,CAAC,aAAsC;QACpD,QAAQ,EAAE,KAAK,CAAC,QAAQ;KACzB,CAAC,CAAC;AACL,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAClC,KAA8B;IAE9B,MAAM,OAAO,GAAG,UAAU,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;IAC/C,OAAO,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AAChD,CAAC;AAED,wEAAwE;AACxE,MAAM,CAAC,MAAM,qBAAqB,GAAwB;IACxD,SAAS,EAAE,oBAAoB;IAC/B,cAAc,EAAE,eAAe;IAC/B,OAAO,EAAE,uBAAuB;IAChC,WAAW,EAAE,oBAAoB;CAClC,CAAC;AAEF,SAAS,UAAU,CAAC,YAAqB;IACvC,IAAI,YAAY;QAAE,OAAO,SAAS,CAAC;IACnC,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,0CAA0C,EAAE,CAAC;AACtF,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
export { createAnthropicProvider } from './provider.js';
|
|
2
|
+
export { ANTHROPIC_ADAPTER_ID, anthropicAdapterEntry, anthropicAdapterFactory, anthropicCheckConfig, } from './entry.js';
|
|
2
3
|
export type { AnthropicModelInfo, AnthropicProviderOptions } from './provider.js';
|
|
3
4
|
export { DEFAULT_CACHE_CREATION_MULTIPLIER_5MIN, DEFAULT_CACHE_READ_MULTIPLIER, computeCostUsd, toFrameworkUsage, } from './cost.js';
|
|
4
5
|
export type { CostRates } from './cost.js';
|
|
6
|
+
export { PROMPT_CACHE, withPromptCache } from './cache.js';
|
|
7
|
+
export type { CacheableRequest, CachedRequest } from './cache.js';
|
|
5
8
|
export { fromAnthropicResponse, mapStopReason, toAnthropicMessages, toAnthropicTools, } from './translate.js';
|
|
6
9
|
export type { ModelProvider } from '@kindgi/capabilities';
|
|
7
10
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AACxD,YAAY,EAAE,kBAAkB,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AAClF,OAAO,EACL,sCAAsC,EACtC,6BAA6B,EAC7B,cAAc,EACd,gBAAgB,GACjB,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EACL,qBAAqB,EACrB,aAAa,EACb,mBAAmB,EACnB,gBAAgB,GACjB,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,kBAAkB,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AAClF,OAAO,EACL,sCAAsC,EACtC,6BAA6B,EAC7B,cAAc,EACd,gBAAgB,GACjB,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC3D,YAAY,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAClE,OAAO,EACL,qBAAqB,EACrB,aAAa,EACb,mBAAmB,EACnB,gBAAgB,GACjB,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
// SPDX-License-Identifier: Apache-2.0
|
|
2
2
|
// Copyright (C) 2026 Kindgi Inc.
|
|
3
3
|
export { createAnthropicProvider } from './provider.js';
|
|
4
|
+
export { ANTHROPIC_ADAPTER_ID, anthropicAdapterEntry, anthropicAdapterFactory, anthropicCheckConfig, } from './entry.js';
|
|
4
5
|
export { DEFAULT_CACHE_CREATION_MULTIPLIER_5MIN, DEFAULT_CACHE_READ_MULTIPLIER, computeCostUsd, toFrameworkUsage, } from './cost.js';
|
|
6
|
+
export { PROMPT_CACHE, withPromptCache } from './cache.js';
|
|
5
7
|
export { fromAnthropicResponse, mapStopReason, toAnthropicMessages, toAnthropicTools, } from './translate.js';
|
|
6
8
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,iCAAiC;AAEjC,OAAO,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,iCAAiC;AAEjC,OAAO,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,sCAAsC,EACtC,6BAA6B,EAC7B,cAAc,EACd,gBAAgB,GACjB,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE3D,OAAO,EACL,qBAAqB,EACrB,aAAa,EACb,mBAAmB,EACnB,gBAAgB,GACjB,MAAM,gBAAgB,CAAC"}
|
package/dist/provider.d.ts
CHANGED
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
import Anthropic from '@anthropic-ai/sdk';
|
|
2
2
|
import type { ModelInfo, ModelProvider, ProviderMetadata } from '@kindgi/capabilities';
|
|
3
|
+
import { type CostRates } from './cost.js';
|
|
3
4
|
/**
|
|
4
5
|
* Anthropic-specific `ModelInfo` extension. Widens the framework's
|
|
5
6
|
* `ModelInfo.cost` with the two Anthropic prompt-cache multipliers
|
|
6
7
|
* (`promptCacheCreationMultiplier`, `promptCacheReadMultiplier`) that
|
|
7
|
-
* `computeCostUsd` uses to bill cache activity per invocation
|
|
8
|
+
* `computeCostUsd` uses to bill cache activity per invocation, and a
|
|
9
|
+
* `longContext` tier for a model that prices long prompts higher.
|
|
8
10
|
*
|
|
9
11
|
* When either multiplier is omitted the framework falls back to
|
|
10
12
|
* Anthropic's 5-minute-tier defaults (1.25 / 0.1) inside `cost.ts`.
|
|
11
13
|
*/
|
|
12
14
|
export interface AnthropicModelInfo extends ModelInfo {
|
|
13
|
-
readonly cost: ModelInfo['cost'] &
|
|
14
|
-
readonly promptCacheCreationMultiplier?: number;
|
|
15
|
-
readonly promptCacheReadMultiplier?: number;
|
|
16
|
-
};
|
|
15
|
+
readonly cost: ModelInfo['cost'] & Omit<CostRates, keyof ModelInfo['cost']>;
|
|
17
16
|
}
|
|
18
17
|
/**
|
|
19
18
|
* Configuration for the Anthropic `ModelProvider`.
|
package/dist/provider.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AAGA,OAAO,SAAS,MAAM,mBAAmB,CAAC;AAE1C,OAAO,KAAK,EAGV,SAAS,EACT,aAAa,EACb,gBAAgB,EACjB,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AAGA,OAAO,SAAS,MAAM,mBAAmB,CAAC;AAE1C,OAAO,KAAK,EAGV,SAAS,EACT,aAAa,EACb,gBAAgB,EACjB,MAAM,sBAAsB,CAAC;AAM9B,OAAO,EAAE,KAAK,SAAS,EAAoC,MAAM,WAAW,CAAC;AAS7E;;;;;;;;;GASG;AACH,MAAM,WAAW,kBAAmB,SAAQ,SAAS;IACnD,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,SAAS,EAAE,MAAM,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;CAC7E;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,CAAC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;IAC3D;;;;;;OAMG;IACH,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,gBAAgB,EAAE,QAAQ,CAAC,GAAG;QACpD,QAAQ,CAAC,MAAM,EAAE,SAAS,kBAAkB,EAAE,CAAC;KAChD,CAAC;IACF,8DAA8D;IAC9D,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B;;;OAGG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,IAAI,CAC3B,WAAW,CAAC,qBAAqB,CAAC,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,EACvD,QAAQ,GAAG,SAAS,CACrB,CAAC;IACF;;;;OAIG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,CAAC;CAC7B;AASD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,wBAAwB,GAAG,aAAa,CA6HxF"}
|
package/dist/provider.js
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
// SPDX-License-Identifier: Apache-2.0
|
|
2
2
|
// Copyright (C) 2026 Kindgi Inc.
|
|
3
3
|
import Anthropic from '@anthropic-ai/sdk';
|
|
4
|
+
import { samplingFor } from '@kindgi/capabilities';
|
|
4
5
|
import { createAttemptCounter } from '@kindgi/capabilities/attempts';
|
|
6
|
+
import { nameToolsAsSent } from '@kindgi/capabilities/tool-names';
|
|
7
|
+
import { withPromptCache } from './cache.js';
|
|
5
8
|
import { computeCostUsd, toFrameworkUsage } from './cost.js';
|
|
6
|
-
import { fromAnthropicResponse, mapStopReason, toAnthropicMessages, toAnthropicTools, } from './translate.js';
|
|
9
|
+
import { encodeToolName, fromAnthropicResponse, mapStopReason, toAnthropicMessages, toAnthropicTools, } from './translate.js';
|
|
7
10
|
/**
|
|
8
11
|
* Adapter-level fallback when neither `ModelCallInput.maxOutputTokens`
|
|
9
12
|
* nor the picked `ModelInfo.maxOutputTokens` is set. Anthropic requires
|
|
@@ -67,19 +70,36 @@ export function createAnthropicProvider(options) {
|
|
|
67
70
|
}
|
|
68
71
|
const startedAt = Date.now();
|
|
69
72
|
const client = await resolveClient();
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
73
|
+
const translated = toAnthropicMessages(input.messages);
|
|
74
|
+
// The system prompt names the call's tools as they're sent (`acme__lookup_order`):
|
|
75
|
+
// a model told to call `acme.lookup_order` calls a name it wasn't given (T311).
|
|
76
|
+
const toolNames = input.tools?.map((t) => t.name) ?? [];
|
|
77
|
+
// Cache breakpoints on the tools, the agent's prompt and, when the call
|
|
78
|
+
// can continue, the conversation so far (`withPromptCache`).
|
|
79
|
+
const { system, tools, messages } = withPromptCache({
|
|
80
|
+
systemParts: translated.systemParts.map((part) => nameToolsAsSent(part, toolNames, encodeToolName)),
|
|
81
|
+
tools: input.tools !== undefined && input.tools.length > 0
|
|
82
|
+
? toAnthropicTools(input.tools)
|
|
83
|
+
: undefined,
|
|
84
|
+
messages: translated.messages,
|
|
85
|
+
});
|
|
86
|
+
// `traceparent` is a header on this request only, when the caller
|
|
87
|
+
// sets it (the provider's registration opted in); never logged.
|
|
88
|
+
const requestOptions = {
|
|
89
|
+
...(input.abortSignal !== undefined && { signal: input.abortSignal }),
|
|
90
|
+
...(input.traceparent !== undefined && { headers: { traceparent: input.traceparent } }),
|
|
91
|
+
};
|
|
75
92
|
const maxTokens = input.maxOutputTokens ?? modelInfo.maxOutputTokens ?? DEFAULT_MAX_TOKENS;
|
|
93
|
+
const sampling = samplingFor(modelInfo, input);
|
|
94
|
+
const thinking = input.thinking === 'lowest' ? lowestThinking(modelInfo) : {};
|
|
76
95
|
const counted = await attempts.count(() => client.messages.create({
|
|
77
96
|
model: input.model,
|
|
78
97
|
max_tokens: maxTokens,
|
|
79
98
|
...(system !== undefined && { system }),
|
|
80
|
-
messages
|
|
81
|
-
...(tools !== undefined && { tools
|
|
82
|
-
...(
|
|
99
|
+
messages,
|
|
100
|
+
...(tools !== undefined && { tools }),
|
|
101
|
+
...(sampling.temperature !== undefined && { temperature: sampling.temperature }),
|
|
102
|
+
...thinking,
|
|
83
103
|
}, requestOptions));
|
|
84
104
|
const response = counted.value;
|
|
85
105
|
const durationMs = Date.now() - startedAt;
|
|
@@ -100,8 +120,26 @@ export function createAnthropicProvider(options) {
|
|
|
100
120
|
// An injected client sends with its own fetch: nothing was counted.
|
|
101
121
|
...(counted.attempts > 0 && { attempts: counted.attempts }),
|
|
102
122
|
rawUsage: { ...response.usage },
|
|
123
|
+
...(sampling.warnings.length > 0 && { warnings: sampling.warnings }),
|
|
103
124
|
};
|
|
104
125
|
},
|
|
105
126
|
};
|
|
106
127
|
}
|
|
128
|
+
/**
|
|
129
|
+
* The request fields for a model's least thinking (`ModelCallInput.thinking:
|
|
130
|
+
* 'lowest'`). A thinking type that turns it off (Haiku 5.5's `disabled`,
|
|
131
|
+
* Sonnet 5.5's `between_tools`) is taken only at effort `high` or below,
|
|
132
|
+
* so it goes with effort `low`; a model that always thinks (Opus 5.5) gets
|
|
133
|
+
* the effort alone. The SDK's types predate both fields; the API takes them
|
|
134
|
+
* as sent.
|
|
135
|
+
*/
|
|
136
|
+
function lowestThinking(model) {
|
|
137
|
+
const lowest = model.thinking?.lowest;
|
|
138
|
+
if (lowest === undefined)
|
|
139
|
+
return {};
|
|
140
|
+
if (lowest === 'disabled' || lowest === 'between_tools') {
|
|
141
|
+
return { thinking: { type: lowest }, output_config: { effort: 'low' } };
|
|
142
|
+
}
|
|
143
|
+
return { output_config: { effort: lowest } };
|
|
144
|
+
}
|
|
107
145
|
//# sourceMappingURL=provider.js.map
|
package/dist/provider.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,iCAAiC;AAEjC,OAAO,SAAS,MAAM,mBAAmB,CAAC;AAS1C,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"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"}
|
package/dist/translate.d.ts
CHANGED
|
@@ -31,9 +31,14 @@ export declare function decodeToolName(name: string): string;
|
|
|
31
31
|
* merge into a single user message (matching the framework's
|
|
32
32
|
* dispatch-tools handler which appends one tool message per call
|
|
33
33
|
* after an assistant `tool_use` turn).
|
|
34
|
+
*
|
|
35
|
+
* `systemParts` keeps the system messages apart, in order, so each can be
|
|
36
|
+
* its own block: the first (the agent's prompt) is the stable one a cache
|
|
37
|
+
* breakpoint goes on (`withPromptCache`).
|
|
34
38
|
*/
|
|
35
39
|
export declare function toAnthropicMessages(messages: readonly ModelMessage[]): {
|
|
36
40
|
readonly system: string | undefined;
|
|
41
|
+
readonly systemParts: readonly string[];
|
|
37
42
|
readonly messages: readonly Anthropic.MessageParam[];
|
|
38
43
|
};
|
|
39
44
|
/**
|
package/dist/translate.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"translate.d.ts","sourceRoot":"","sources":["../src/translate.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,SAAS,MAAM,mBAAmB,CAAC;AAE/C,OAAO,KAAK,EACV,eAAe,EACf,YAAY,EAEZ,mBAAmB,EACpB,MAAM,sBAAsB,CAAC;AAE9B;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED
|
|
1
|
+
{"version":3,"file":"translate.d.ts","sourceRoot":"","sources":["../src/translate.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,SAAS,MAAM,mBAAmB,CAAC;AAE/C,OAAO,KAAK,EACV,eAAe,EACf,YAAY,EAEZ,mBAAmB,EACpB,MAAM,sBAAsB,CAAC;AAE9B;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,SAAS,YAAY,EAAE,GAAG;IACtE,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IACxC,QAAQ,CAAC,QAAQ,EAAE,SAAS,SAAS,CAAC,YAAY,EAAE,CAAC;CACtD,CAoDA;AAsBD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,SAAS,mBAAmB,EAAE,GAAG,SAAS,SAAS,CAAC,IAAI,EAAE,CAMjG;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,SAAS,CAAC,OAAO,GAAG,YAAY,CAyB/E;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,SAAS,CAAC,OAAO,CAAC,aAAa,CAAC,GACvC,eAAe,CAAC,cAAc,CAAC,CAejC"}
|
package/dist/translate.js
CHANGED
|
@@ -35,6 +35,10 @@ export function decodeToolName(name) {
|
|
|
35
35
|
* merge into a single user message (matching the framework's
|
|
36
36
|
* dispatch-tools handler which appends one tool message per call
|
|
37
37
|
* after an assistant `tool_use` turn).
|
|
38
|
+
*
|
|
39
|
+
* `systemParts` keeps the system messages apart, in order, so each can be
|
|
40
|
+
* its own block: the first (the agent's prompt) is the stable one a cache
|
|
41
|
+
* breakpoint goes on (`withPromptCache`).
|
|
38
42
|
*/
|
|
39
43
|
export function toAnthropicMessages(messages) {
|
|
40
44
|
const systemParts = [];
|
|
@@ -85,6 +89,7 @@ export function toAnthropicMessages(messages) {
|
|
|
85
89
|
}
|
|
86
90
|
return {
|
|
87
91
|
system: systemParts.length > 0 ? systemParts.join('\n\n') : undefined,
|
|
92
|
+
systemParts,
|
|
88
93
|
messages: out,
|
|
89
94
|
};
|
|
90
95
|
}
|
package/dist/translate.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"translate.js","sourceRoot":"","sources":["../src/translate.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,iCAAiC;AAWjC;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;AAClC,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"translate.js","sourceRoot":"","sources":["../src/translate.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kindgi/adapter-model-anthropic",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5-rc.0",
|
|
4
4
|
"description": "Anthropic ModelProvider for @kindgi/capabilities. Wraps @anthropic-ai/sdk with the framework's provider-neutral interface: message-trail ↔ Messages API translation, prompt-caching-aware cost accounting, and lazy API-key resolution so per-tenant registries can close over a SecretStore scope. Non-streaming, tool-use enabled. Wire per-tenant in the provider registry (see @kindgi/capabilities).",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"README.md"
|
|
29
29
|
],
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@kindgi/capabilities": "0.1.
|
|
31
|
+
"@kindgi/capabilities": "0.1.5-rc.0",
|
|
32
32
|
"@anthropic-ai/sdk": "^0.68.0"
|
|
33
33
|
},
|
|
34
34
|
"engines": {
|
package/src/cache.ts
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright (C) 2026 Kindgi Inc.
|
|
3
|
+
|
|
4
|
+
import type Anthropic from '@anthropic-ai/sdk';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Prompt caching. Anthropic caches only the prompt prefixes a request
|
|
8
|
+
* marks with `cache_control`, and a later request that starts with the
|
|
9
|
+
* same bytes reads them at a fraction of the input price (0.1x; 0.05x on
|
|
10
|
+
* Claude Opus 5.5 and Sonnet 5.5). A marked prefix costs 1.25x the first
|
|
11
|
+
* time it's written. The prompt renders in the order tools, system,
|
|
12
|
+
* messages, and the adapter marks up to three breakpoints:
|
|
13
|
+
*
|
|
14
|
+
* - the last tool: the tool definitions, the same for every call an
|
|
15
|
+
* agent makes;
|
|
16
|
+
* - the first system block: the agent's own prompt. Later system blocks
|
|
17
|
+
* (retrieved context) change from turn to turn, so they stay after it;
|
|
18
|
+
* - the last block of the last message, when another call will re-send
|
|
19
|
+
* this prefix: a call with tools (the next step of a tool loop sends
|
|
20
|
+
* everything again plus the results) or a conversation with an earlier
|
|
21
|
+
* answer (its next turn does). A one-off call (no tools, no earlier
|
|
22
|
+
* answer, e.g. a judge) leaves its message unmarked: its tail is never
|
|
23
|
+
* sent again, so a write would only cost more.
|
|
24
|
+
*
|
|
25
|
+
* Each breakpoint uses the 5-minute cache (the default `ephemeral` TTL);
|
|
26
|
+
* the steps of an agent turn are seconds apart. A prefix shorter than the
|
|
27
|
+
* model's minimum (512 to 4,096 tokens) isn't cached and costs nothing
|
|
28
|
+
* extra. How Anthropic keeps cached prompts, and their eligibility for
|
|
29
|
+
* zero data retention: https://platform.claude.com/docs/en/build-with-claude/prompt-caching
|
|
30
|
+
* and https://platform.claude.com/docs/en/manage-claude/api-and-data-retention.
|
|
31
|
+
*/
|
|
32
|
+
export const PROMPT_CACHE: Anthropic.CacheControlEphemeral = { type: 'ephemeral' };
|
|
33
|
+
|
|
34
|
+
export interface CacheableRequest {
|
|
35
|
+
/** The call's system messages, in order, each its own block. */
|
|
36
|
+
readonly systemParts: readonly string[];
|
|
37
|
+
readonly tools: readonly Anthropic.Tool[] | undefined;
|
|
38
|
+
readonly messages: readonly Anthropic.MessageParam[];
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface CachedRequest {
|
|
42
|
+
readonly system: Anthropic.TextBlockParam[] | undefined;
|
|
43
|
+
readonly tools: Anthropic.Tool[] | undefined;
|
|
44
|
+
readonly messages: Anthropic.MessageParam[];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** The request's parts, with the cache breakpoints above. The inputs aren't changed. */
|
|
48
|
+
export function withPromptCache(request: CacheableRequest): CachedRequest {
|
|
49
|
+
const tools =
|
|
50
|
+
request.tools === undefined || request.tools.length === 0
|
|
51
|
+
? undefined
|
|
52
|
+
: request.tools.map((tool, i, all) =>
|
|
53
|
+
i === all.length - 1 ? { ...tool, cache_control: PROMPT_CACHE } : tool,
|
|
54
|
+
);
|
|
55
|
+
const system =
|
|
56
|
+
request.systemParts.length === 0
|
|
57
|
+
? undefined
|
|
58
|
+
: request.systemParts.map(
|
|
59
|
+
(text, i): Anthropic.TextBlockParam =>
|
|
60
|
+
i === 0 ? { type: 'text', text, cache_control: PROMPT_CACHE } : { type: 'text', text },
|
|
61
|
+
);
|
|
62
|
+
const continues = tools !== undefined || request.messages.some((m) => m.role === 'assistant');
|
|
63
|
+
const messages = continues ? markLastMessage(request.messages) : [...request.messages];
|
|
64
|
+
return { system, tools, messages };
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* The messages with a breakpoint on the last block of the last one that
|
|
69
|
+
* can carry it: text (not empty), a tool call, a tool result.
|
|
70
|
+
*/
|
|
71
|
+
function markLastMessage(messages: readonly Anthropic.MessageParam[]): Anthropic.MessageParam[] {
|
|
72
|
+
const out = [...messages];
|
|
73
|
+
const last = out[out.length - 1];
|
|
74
|
+
if (last === undefined) return out;
|
|
75
|
+
const blocks: Anthropic.ContentBlockParam[] =
|
|
76
|
+
typeof last.content === 'string' ? [{ type: 'text', text: last.content }] : [...last.content];
|
|
77
|
+
for (let i = blocks.length - 1; i >= 0; i -= 1) {
|
|
78
|
+
const block = blocks[i] as Anthropic.ContentBlockParam;
|
|
79
|
+
if (cacheable(block)) {
|
|
80
|
+
blocks[i] = { ...block, cache_control: PROMPT_CACHE };
|
|
81
|
+
out[out.length - 1] = { ...last, content: blocks };
|
|
82
|
+
return out;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return out;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function cacheable(
|
|
89
|
+
block: Anthropic.ContentBlockParam,
|
|
90
|
+
): block is
|
|
91
|
+
| Anthropic.TextBlockParam
|
|
92
|
+
| Anthropic.ToolUseBlockParam
|
|
93
|
+
| Anthropic.ToolResultBlockParam {
|
|
94
|
+
if (block.type === 'text') return block.text.length > 0;
|
|
95
|
+
return block.type === 'tool_use' || block.type === 'tool_result';
|
|
96
|
+
}
|
package/src/cost.ts
CHANGED
|
@@ -26,6 +26,17 @@ export interface CostRates {
|
|
|
26
26
|
readonly completionUsdPer1kTokens: number;
|
|
27
27
|
readonly promptCacheCreationMultiplier?: number;
|
|
28
28
|
readonly promptCacheReadMultiplier?: number;
|
|
29
|
+
/**
|
|
30
|
+
* Long-context pricing: when a call's prompt (regular, cache-write and
|
|
31
|
+
* cache-read tokens together) exceeds `thresholdTokens`, the whole call
|
|
32
|
+
* bills at these rates, the cache multipliers applying to the long
|
|
33
|
+
* prompt rate. Claude Haiku 5.5 is 5x past a 100,000-token prompt.
|
|
34
|
+
*/
|
|
35
|
+
readonly longContext?: {
|
|
36
|
+
readonly thresholdTokens: number;
|
|
37
|
+
readonly promptUsdPer1kTokens: number;
|
|
38
|
+
readonly completionUsdPer1kTokens: number;
|
|
39
|
+
};
|
|
29
40
|
}
|
|
30
41
|
|
|
31
42
|
/**
|
|
@@ -45,8 +56,16 @@ export interface CostRates {
|
|
|
45
56
|
* rates without double-counting.
|
|
46
57
|
*/
|
|
47
58
|
export function computeCostUsd(usage: Anthropic.Usage, rates: CostRates): number {
|
|
48
|
-
const
|
|
49
|
-
|
|
59
|
+
const promptTokens =
|
|
60
|
+
usage.input_tokens +
|
|
61
|
+
(usage.cache_creation_input_tokens ?? 0) +
|
|
62
|
+
(usage.cache_read_input_tokens ?? 0);
|
|
63
|
+
const long =
|
|
64
|
+
rates.longContext !== undefined && promptTokens > rates.longContext.thresholdTokens
|
|
65
|
+
? rates.longContext
|
|
66
|
+
: undefined;
|
|
67
|
+
const inputRate = long?.promptUsdPer1kTokens ?? rates.promptUsdPer1kTokens;
|
|
68
|
+
const outputRate = long?.completionUsdPer1kTokens ?? rates.completionUsdPer1kTokens;
|
|
50
69
|
const creationMultiplier =
|
|
51
70
|
rates.promptCacheCreationMultiplier ?? DEFAULT_CACHE_CREATION_MULTIPLIER_5MIN;
|
|
52
71
|
const readMultiplier = rates.promptCacheReadMultiplier ?? DEFAULT_CACHE_READ_MULTIPLIER;
|
package/src/entry.ts
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright (C) 2026 Kindgi Inc.
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
type AdapterConfigCheckInput,
|
|
6
|
+
type AdapterConfigProblem,
|
|
7
|
+
type AdapterFactory,
|
|
8
|
+
type AdapterFactoryEntry,
|
|
9
|
+
adapterConfigError,
|
|
10
|
+
} from '@kindgi/capabilities';
|
|
11
|
+
|
|
12
|
+
import { createAnthropicProvider } from './provider.js';
|
|
13
|
+
|
|
14
|
+
/** The id the runtime registers this adapter under. */
|
|
15
|
+
export const ANTHROPIC_ADAPTER_ID = '@kindgi/adapter-model-anthropic';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* The runtime's factory. A provider registered with it names its Anthropic
|
|
19
|
+
* API key in `secret_ref`, resolved on every call, so a rotated key takes
|
|
20
|
+
* effect on the next one.
|
|
21
|
+
*/
|
|
22
|
+
export const anthropicAdapterFactory: AdapterFactory = (input) => {
|
|
23
|
+
const problem = keyProblem(input.resolveApiKey !== undefined);
|
|
24
|
+
if (problem !== undefined)
|
|
25
|
+
throw adapterConfigError(ANTHROPIC_ADAPTER_ID, input.metadata.id, problem);
|
|
26
|
+
return createAnthropicProvider({
|
|
27
|
+
apiKey: input.resolveApiKey as () => Promise<string>,
|
|
28
|
+
metadata: input.metadata,
|
|
29
|
+
});
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* What's wrong with a registration for this adapter, read without building
|
|
34
|
+
* it (`AdapterFactoryEntry.checkConfig`): it needs a `secret_ref`. The
|
|
35
|
+
* problem's message is the error the factory throws for it.
|
|
36
|
+
*/
|
|
37
|
+
export function anthropicCheckConfig(
|
|
38
|
+
input: AdapterConfigCheckInput,
|
|
39
|
+
): readonly AdapterConfigProblem[] {
|
|
40
|
+
const problem = keyProblem(input.hasSecretRef);
|
|
41
|
+
return problem !== undefined ? [problem] : [];
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** The entry a runtime registers: the factory, and its static check. */
|
|
45
|
+
export const anthropicAdapterEntry: AdapterFactoryEntry = {
|
|
46
|
+
adapterId: ANTHROPIC_ADAPTER_ID,
|
|
47
|
+
capabilityKind: 'llm-inference',
|
|
48
|
+
factory: anthropicAdapterFactory,
|
|
49
|
+
checkConfig: anthropicCheckConfig,
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
function keyProblem(hasSecretRef: boolean): AdapterConfigProblem | undefined {
|
|
53
|
+
if (hasSecretRef) return undefined;
|
|
54
|
+
return { path: '/secret_ref', message: 'needs secret_ref: its Anthropic API key.' };
|
|
55
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
// Copyright (C) 2026 Kindgi Inc.
|
|
3
3
|
|
|
4
4
|
export { createAnthropicProvider } from './provider.js';
|
|
5
|
+
export {
|
|
6
|
+
ANTHROPIC_ADAPTER_ID,
|
|
7
|
+
anthropicAdapterEntry,
|
|
8
|
+
anthropicAdapterFactory,
|
|
9
|
+
anthropicCheckConfig,
|
|
10
|
+
} from './entry.js';
|
|
5
11
|
export type { AnthropicModelInfo, AnthropicProviderOptions } from './provider.js';
|
|
6
12
|
export {
|
|
7
13
|
DEFAULT_CACHE_CREATION_MULTIPLIER_5MIN,
|
|
@@ -10,6 +16,8 @@ export {
|
|
|
10
16
|
toFrameworkUsage,
|
|
11
17
|
} from './cost.js';
|
|
12
18
|
export type { CostRates } from './cost.js';
|
|
19
|
+
export { PROMPT_CACHE, withPromptCache } from './cache.js';
|
|
20
|
+
export type { CacheableRequest, CachedRequest } from './cache.js';
|
|
13
21
|
export {
|
|
14
22
|
fromAnthropicResponse,
|
|
15
23
|
mapStopReason,
|
package/src/provider.ts
CHANGED
|
@@ -10,10 +10,14 @@ import type {
|
|
|
10
10
|
ModelProvider,
|
|
11
11
|
ProviderMetadata,
|
|
12
12
|
} from '@kindgi/capabilities';
|
|
13
|
+
import { samplingFor } from '@kindgi/capabilities';
|
|
13
14
|
import { createAttemptCounter } from '@kindgi/capabilities/attempts';
|
|
15
|
+
import { nameToolsAsSent } from '@kindgi/capabilities/tool-names';
|
|
14
16
|
|
|
15
|
-
import {
|
|
17
|
+
import { withPromptCache } from './cache.js';
|
|
18
|
+
import { type CostRates, computeCostUsd, toFrameworkUsage } from './cost.js';
|
|
16
19
|
import {
|
|
20
|
+
encodeToolName,
|
|
17
21
|
fromAnthropicResponse,
|
|
18
22
|
mapStopReason,
|
|
19
23
|
toAnthropicMessages,
|
|
@@ -24,16 +28,14 @@ import {
|
|
|
24
28
|
* Anthropic-specific `ModelInfo` extension. Widens the framework's
|
|
25
29
|
* `ModelInfo.cost` with the two Anthropic prompt-cache multipliers
|
|
26
30
|
* (`promptCacheCreationMultiplier`, `promptCacheReadMultiplier`) that
|
|
27
|
-
* `computeCostUsd` uses to bill cache activity per invocation
|
|
31
|
+
* `computeCostUsd` uses to bill cache activity per invocation, and a
|
|
32
|
+
* `longContext` tier for a model that prices long prompts higher.
|
|
28
33
|
*
|
|
29
34
|
* When either multiplier is omitted the framework falls back to
|
|
30
35
|
* Anthropic's 5-minute-tier defaults (1.25 / 0.1) inside `cost.ts`.
|
|
31
36
|
*/
|
|
32
37
|
export interface AnthropicModelInfo extends ModelInfo {
|
|
33
|
-
readonly cost: ModelInfo['cost'] &
|
|
34
|
-
readonly promptCacheCreationMultiplier?: number;
|
|
35
|
-
readonly promptCacheReadMultiplier?: number;
|
|
36
|
-
};
|
|
38
|
+
readonly cost: ModelInfo['cost'] & Omit<CostRates, keyof ModelInfo['cost']>;
|
|
37
39
|
}
|
|
38
40
|
|
|
39
41
|
/**
|
|
@@ -156,15 +158,32 @@ export function createAnthropicProvider(options: AnthropicProviderOptions): Mode
|
|
|
156
158
|
const startedAt = Date.now();
|
|
157
159
|
const client = await resolveClient();
|
|
158
160
|
|
|
159
|
-
const
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
const
|
|
166
|
-
|
|
161
|
+
const translated = toAnthropicMessages(input.messages);
|
|
162
|
+
// The system prompt names the call's tools as they're sent (`acme__lookup_order`):
|
|
163
|
+
// a model told to call `acme.lookup_order` calls a name it wasn't given (T311).
|
|
164
|
+
const toolNames = input.tools?.map((t) => t.name) ?? [];
|
|
165
|
+
// Cache breakpoints on the tools, the agent's prompt and, when the call
|
|
166
|
+
// can continue, the conversation so far (`withPromptCache`).
|
|
167
|
+
const { system, tools, messages } = withPromptCache({
|
|
168
|
+
systemParts: translated.systemParts.map((part) =>
|
|
169
|
+
nameToolsAsSent(part, toolNames, encodeToolName),
|
|
170
|
+
),
|
|
171
|
+
tools:
|
|
172
|
+
input.tools !== undefined && input.tools.length > 0
|
|
173
|
+
? toAnthropicTools(input.tools)
|
|
174
|
+
: undefined,
|
|
175
|
+
messages: translated.messages,
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
// `traceparent` is a header on this request only, when the caller
|
|
179
|
+
// sets it (the provider's registration opted in); never logged.
|
|
180
|
+
const requestOptions: Record<string, unknown> = {
|
|
181
|
+
...(input.abortSignal !== undefined && { signal: input.abortSignal }),
|
|
182
|
+
...(input.traceparent !== undefined && { headers: { traceparent: input.traceparent } }),
|
|
183
|
+
};
|
|
167
184
|
const maxTokens = input.maxOutputTokens ?? modelInfo.maxOutputTokens ?? DEFAULT_MAX_TOKENS;
|
|
185
|
+
const sampling = samplingFor(modelInfo, input);
|
|
186
|
+
const thinking = input.thinking === 'lowest' ? lowestThinking(modelInfo) : {};
|
|
168
187
|
|
|
169
188
|
const counted = await attempts.count(() =>
|
|
170
189
|
client.messages.create(
|
|
@@ -172,9 +191,10 @@ export function createAnthropicProvider(options: AnthropicProviderOptions): Mode
|
|
|
172
191
|
model: input.model,
|
|
173
192
|
max_tokens: maxTokens,
|
|
174
193
|
...(system !== undefined && { system }),
|
|
175
|
-
messages
|
|
176
|
-
...(tools !== undefined && { tools
|
|
177
|
-
...(
|
|
194
|
+
messages,
|
|
195
|
+
...(tools !== undefined && { tools }),
|
|
196
|
+
...(sampling.temperature !== undefined && { temperature: sampling.temperature }),
|
|
197
|
+
...thinking,
|
|
178
198
|
},
|
|
179
199
|
requestOptions,
|
|
180
200
|
),
|
|
@@ -200,7 +220,25 @@ export function createAnthropicProvider(options: AnthropicProviderOptions): Mode
|
|
|
200
220
|
// An injected client sends with its own fetch: nothing was counted.
|
|
201
221
|
...(counted.attempts > 0 && { attempts: counted.attempts }),
|
|
202
222
|
rawUsage: { ...response.usage },
|
|
223
|
+
...(sampling.warnings.length > 0 && { warnings: sampling.warnings }),
|
|
203
224
|
};
|
|
204
225
|
},
|
|
205
226
|
};
|
|
206
227
|
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* The request fields for a model's least thinking (`ModelCallInput.thinking:
|
|
231
|
+
* 'lowest'`). A thinking type that turns it off (Haiku 5.5's `disabled`,
|
|
232
|
+
* Sonnet 5.5's `between_tools`) is taken only at effort `high` or below,
|
|
233
|
+
* so it goes with effort `low`; a model that always thinks (Opus 5.5) gets
|
|
234
|
+
* the effort alone. The SDK's types predate both fields; the API takes them
|
|
235
|
+
* as sent.
|
|
236
|
+
*/
|
|
237
|
+
function lowestThinking(model: ModelInfo): Record<string, unknown> {
|
|
238
|
+
const lowest = model.thinking?.lowest;
|
|
239
|
+
if (lowest === undefined) return {};
|
|
240
|
+
if (lowest === 'disabled' || lowest === 'between_tools') {
|
|
241
|
+
return { thinking: { type: lowest }, output_config: { effort: 'low' } };
|
|
242
|
+
}
|
|
243
|
+
return { output_config: { effort: lowest } };
|
|
244
|
+
}
|
package/src/translate.ts
CHANGED
|
@@ -47,9 +47,14 @@ export function decodeToolName(name: string): string {
|
|
|
47
47
|
* merge into a single user message (matching the framework's
|
|
48
48
|
* dispatch-tools handler which appends one tool message per call
|
|
49
49
|
* after an assistant `tool_use` turn).
|
|
50
|
+
*
|
|
51
|
+
* `systemParts` keeps the system messages apart, in order, so each can be
|
|
52
|
+
* its own block: the first (the agent's prompt) is the stable one a cache
|
|
53
|
+
* breakpoint goes on (`withPromptCache`).
|
|
50
54
|
*/
|
|
51
55
|
export function toAnthropicMessages(messages: readonly ModelMessage[]): {
|
|
52
56
|
readonly system: string | undefined;
|
|
57
|
+
readonly systemParts: readonly string[];
|
|
53
58
|
readonly messages: readonly Anthropic.MessageParam[];
|
|
54
59
|
} {
|
|
55
60
|
const systemParts: string[] = [];
|
|
@@ -100,6 +105,7 @@ export function toAnthropicMessages(messages: readonly ModelMessage[]): {
|
|
|
100
105
|
|
|
101
106
|
return {
|
|
102
107
|
system: systemParts.length > 0 ? systemParts.join('\n\n') : undefined,
|
|
108
|
+
systemParts,
|
|
103
109
|
messages: out,
|
|
104
110
|
};
|
|
105
111
|
}
|