@kindgi/adapter-model-anthropic 0.1.2 → 0.1.3

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/cost.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import type Anthropic from '@anthropic-ai/sdk';
2
+ import type { UsageCounters } from '@kindgi/capabilities';
2
3
  /**
3
4
  * Cost multipliers for prompt-cache tokens. Anthropic prices cache
4
5
  * activity as a multiple of the base input rate:
@@ -39,19 +40,13 @@ export interface CostRates {
39
40
  */
40
41
  export declare function computeCostUsd(usage: Anthropic.Usage, rates: CostRates): number;
41
42
  /**
42
- * Roll up Anthropic's four-way token split into the framework's
43
- * `UsageCounters` shape.
43
+ * Anthropic's four-way token split as the framework's `UsageCounters`:
44
44
  *
45
- * - `promptTokens` = total tokens billed as input = regular +
46
- * cache-creation + cache-read.
47
- * - `completionTokens` = output tokens.
48
- * - `cachedTokens` = cache-read tokens (surfaced for observability;
49
- * the framework's cost meter uses `costUsd` directly, not this
50
- * field, so we don't need to bake cache math into `promptTokens`).
45
+ * - `promptTokens` = every input token = regular + cache-write +
46
+ * cache-read (`input_tokens` excludes both cache counts);
47
+ * - `cacheReadTokens` / `cacheWriteTokens` = the cache's parts of it;
48
+ * - `completionTokens` = output tokens. Anthropic counts thinking in
49
+ * them and doesn't report it apart, so there's no `reasoningTokens`.
51
50
  */
52
- export declare function toFrameworkUsage(usage: Anthropic.Usage): {
53
- readonly promptTokens: number;
54
- readonly completionTokens: number;
55
- readonly cachedTokens?: number;
56
- };
51
+ export declare function toFrameworkUsage(usage: Anthropic.Usage): UsageCounters;
57
52
  //# sourceMappingURL=cost.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"cost.d.ts","sourceRoot":"","sources":["../src/cost.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,SAAS,MAAM,mBAAmB,CAAC;AAE/C;;;;;;;;;;;;;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;CAC7C;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,SAAS,CAAC,KAAK,EAAE,KAAK,EAAE,SAAS,GAAG,MAAM,CAoB/E;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,SAAS,CAAC,KAAK,GAAG;IACxD,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;CAChC,CASA"}
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;CAC7C;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,SAAS,CAAC,KAAK,EAAE,KAAK,EAAE,SAAS,GAAG,MAAM,CAoB/E;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,SAAS,CAAC,KAAK,GAAG,aAAa,CAUtE"}
package/dist/cost.js CHANGED
@@ -49,24 +49,23 @@ export function computeCostUsd(usage, rates) {
49
49
  return inputCost + outputCost;
50
50
  }
51
51
  /**
52
- * Roll up Anthropic's four-way token split into the framework's
53
- * `UsageCounters` shape.
52
+ * Anthropic's four-way token split as the framework's `UsageCounters`:
54
53
  *
55
- * - `promptTokens` = total tokens billed as input = regular +
56
- * cache-creation + cache-read.
57
- * - `completionTokens` = output tokens.
58
- * - `cachedTokens` = cache-read tokens (surfaced for observability;
59
- * the framework's cost meter uses `costUsd` directly, not this
60
- * field, so we don't need to bake cache math into `promptTokens`).
54
+ * - `promptTokens` = every input token = regular + cache-write +
55
+ * cache-read (`input_tokens` excludes both cache counts);
56
+ * - `cacheReadTokens` / `cacheWriteTokens` = the cache's parts of it;
57
+ * - `completionTokens` = output tokens. Anthropic counts thinking in
58
+ * them and doesn't report it apart, so there's no `reasoningTokens`.
61
59
  */
62
60
  export function toFrameworkUsage(usage) {
63
- const cacheCreation = usage.cache_creation_input_tokens ?? 0;
64
- const cacheRead = usage.cache_read_input_tokens ?? 0;
65
- const promptTokens = usage.input_tokens + cacheCreation + cacheRead;
66
- const base = {
67
- promptTokens,
61
+ const cacheWrite = usage.cache_creation_input_tokens;
62
+ const cacheRead = usage.cache_read_input_tokens;
63
+ return {
64
+ promptTokens: usage.input_tokens + (cacheWrite ?? 0) + (cacheRead ?? 0),
68
65
  completionTokens: usage.output_tokens,
66
+ // A part the vendor reports is kept, 0 included.
67
+ ...(typeof cacheRead === 'number' && { cacheReadTokens: cacheRead }),
68
+ ...(typeof cacheWrite === 'number' && { cacheWriteTokens: cacheWrite }),
69
69
  };
70
- return cacheRead > 0 ? { ...base, cachedTokens: cacheRead } : base;
71
70
  }
72
71
  //# sourceMappingURL=cost.js.map
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;AAIjC;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,sCAAsC,GAAG,IAAI,CAAC;AAC3D,MAAM,CAAC,MAAM,6BAA6B,GAAG,GAAG,CAAC;AASjD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,cAAc,CAAC,KAAsB,EAAE,KAAgB;IACrE,MAAM,SAAS,GAAG,KAAK,CAAC,oBAAoB,CAAC;IAC7C,MAAM,UAAU,GAAG,KAAK,CAAC,wBAAwB,CAAC;IAClD,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;;;;;;;;;;GAUG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAsB;IAKrD,MAAM,aAAa,GAAG,KAAK,CAAC,2BAA2B,IAAI,CAAC,CAAC;IAC7D,MAAM,SAAS,GAAG,KAAK,CAAC,uBAAuB,IAAI,CAAC,CAAC;IACrD,MAAM,YAAY,GAAG,KAAK,CAAC,YAAY,GAAG,aAAa,GAAG,SAAS,CAAC;IACpE,MAAM,IAAI,GAAG;QACX,YAAY;QACZ,gBAAgB,EAAE,KAAK,CAAC,aAAa;KACtC,CAAC;IACF,OAAO,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,YAAY,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AACrE,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;AASjD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,cAAc,CAAC,KAAsB,EAAE,KAAgB;IACrE,MAAM,SAAS,GAAG,KAAK,CAAC,oBAAoB,CAAC;IAC7C,MAAM,UAAU,GAAG,KAAK,CAAC,wBAAwB,CAAC;IAClD,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"}
@@ -51,7 +51,7 @@ export interface AnthropicProviderOptions {
51
51
  * Additional SDK client options (timeouts, custom fetch, headers,
52
52
  * etc.). `apiKey` and `baseURL` from the top level always win.
53
53
  */
54
- readonly clientOptions?: Omit<ConstructorParameters<typeof Anthropic>[0], 'apiKey' | 'baseURL'>;
54
+ readonly clientOptions?: Omit<NonNullable<ConstructorParameters<typeof Anthropic>[0]>, 'apiKey' | 'baseURL'>;
55
55
  /**
56
56
  * Dependency-injected SDK client. When present, `apiKey` /
57
57
  * `baseURL` / `clientOptions` are ignored on construction (tests
@@ -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;AAU9B;;;;;;;;GAQG;AACH,MAAM,WAAW,kBAAmB,SAAQ,SAAS;IACnD,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC,GAAG;QACjC,QAAQ,CAAC,6BAA6B,CAAC,EAAE,MAAM,CAAC;QAChD,QAAQ,CAAC,yBAAyB,CAAC,EAAE,MAAM,CAAC;KAC7C,CAAC;CACH;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,CAAC,qBAAqB,CAAC,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC,CAAC;IAChG;;;;OAIG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,CAAC;CAC7B;AASD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,wBAAwB,GAAG,aAAa,CA4FxF"}
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;AAW9B;;;;;;;;GAQG;AACH,MAAM,WAAW,kBAAmB,SAAQ,SAAS;IACnD,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC,GAAG;QACjC,QAAQ,CAAC,6BAA6B,CAAC,EAAE,MAAM,CAAC;QAChD,QAAQ,CAAC,yBAAyB,CAAC,EAAE,MAAM,CAAC;KAC7C,CAAC;CACH;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,CA0GxF"}
package/dist/provider.js CHANGED
@@ -1,6 +1,7 @@
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 { createAttemptCounter } from '@kindgi/capabilities/attempts';
4
5
  import { computeCostUsd, toFrameworkUsage } from './cost.js';
5
6
  import { fromAnthropicResponse, mapStopReason, toAnthropicMessages, toAnthropicTools, } from './translate.js';
6
7
  /**
@@ -27,6 +28,9 @@ export function createAnthropicProvider(options) {
27
28
  // keepalive — throwing it away on every invoke would tank latency).
28
29
  // When the resolver returns a new value (key rotation), rebuild.
29
30
  let cached;
31
+ // Counts each call's HTTP attempts, the SDK's own retries included (its
32
+ // retry policy stays the SDK's), through the `fetch` the client sends with.
33
+ const attempts = createAttemptCounter(options.clientOptions?.fetch);
30
34
  if (options.client !== undefined) {
31
35
  // Dep-injected client — pin to sentinel key so resolveClient below
32
36
  // always returns the same instance regardless of what the resolver
@@ -48,6 +52,7 @@ export function createAnthropicProvider(options) {
48
52
  apiKey: key,
49
53
  ...(options.baseURL !== undefined && { baseURL: options.baseURL }),
50
54
  ...(options.clientOptions ?? {}),
55
+ fetch: attempts.fetch,
51
56
  });
52
57
  cached = { key, client };
53
58
  return client;
@@ -68,14 +73,15 @@ export function createAnthropicProvider(options) {
68
73
  : undefined;
69
74
  const requestOptions = input.abortSignal !== undefined ? { signal: input.abortSignal } : {};
70
75
  const maxTokens = input.maxOutputTokens ?? modelInfo.maxOutputTokens ?? DEFAULT_MAX_TOKENS;
71
- const response = await client.messages.create({
76
+ const counted = await attempts.count(() => client.messages.create({
72
77
  model: input.model,
73
78
  max_tokens: maxTokens,
74
79
  ...(system !== undefined && { system }),
75
80
  messages: [...messages],
76
81
  ...(tools !== undefined && { tools: [...tools] }),
77
82
  ...(input.temperature !== undefined && { temperature: input.temperature }),
78
- }, requestOptions);
83
+ }, requestOptions));
84
+ const response = counted.value;
79
85
  const durationMs = Date.now() - startedAt;
80
86
  const message = fromAnthropicResponse(response);
81
87
  const usage = toFrameworkUsage(response.usage);
@@ -87,6 +93,13 @@ export function createAnthropicProvider(options) {
87
93
  costUsd,
88
94
  durationMs,
89
95
  provider: { id: metadata.id, model: input.model },
96
+ ...(response.model !== undefined && { servedModel: response.model }),
97
+ ...(typeof response._request_id === 'string' && {
98
+ providerRequestId: response._request_id,
99
+ }),
100
+ // An injected client sends with its own fetch: nothing was counted.
101
+ ...(counted.attempts > 0 && { attempts: counted.attempts }),
102
+ rawUsage: { ...response.usage },
90
103
  };
91
104
  },
92
105
  };
@@ -1 +1 @@
1
- {"version":3,"file":"provider.js","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"provider.js","sourceRoot":"","sources":["../src/provider.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.2",
3
+ "version": "0.1.3",
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.2",
31
+ "@kindgi/capabilities": "0.1.3",
32
32
  "@anthropic-ai/sdk": "^0.68.0"
33
33
  },
34
34
  "engines": {
package/src/cost.ts CHANGED
@@ -2,6 +2,7 @@
2
2
  // Copyright (C) 2026 Kindgi Inc.
3
3
 
4
4
  import type Anthropic from '@anthropic-ai/sdk';
5
+ import type { UsageCounters } from '@kindgi/capabilities';
5
6
 
6
7
  /**
7
8
  * Cost multipliers for prompt-cache tokens. Anthropic prices cache
@@ -66,27 +67,22 @@ export function computeCostUsd(usage: Anthropic.Usage, rates: CostRates): number
66
67
  }
67
68
 
68
69
  /**
69
- * Roll up Anthropic's four-way token split into the framework's
70
- * `UsageCounters` shape.
70
+ * Anthropic's four-way token split as the framework's `UsageCounters`:
71
71
  *
72
- * - `promptTokens` = total tokens billed as input = regular +
73
- * cache-creation + cache-read.
74
- * - `completionTokens` = output tokens.
75
- * - `cachedTokens` = cache-read tokens (surfaced for observability;
76
- * the framework's cost meter uses `costUsd` directly, not this
77
- * field, so we don't need to bake cache math into `promptTokens`).
72
+ * - `promptTokens` = every input token = regular + cache-write +
73
+ * cache-read (`input_tokens` excludes both cache counts);
74
+ * - `cacheReadTokens` / `cacheWriteTokens` = the cache's parts of it;
75
+ * - `completionTokens` = output tokens. Anthropic counts thinking in
76
+ * them and doesn't report it apart, so there's no `reasoningTokens`.
78
77
  */
79
- export function toFrameworkUsage(usage: Anthropic.Usage): {
80
- readonly promptTokens: number;
81
- readonly completionTokens: number;
82
- readonly cachedTokens?: number;
83
- } {
84
- const cacheCreation = usage.cache_creation_input_tokens ?? 0;
85
- const cacheRead = usage.cache_read_input_tokens ?? 0;
86
- const promptTokens = usage.input_tokens + cacheCreation + cacheRead;
87
- const base = {
88
- promptTokens,
78
+ export function toFrameworkUsage(usage: Anthropic.Usage): UsageCounters {
79
+ const cacheWrite = usage.cache_creation_input_tokens;
80
+ const cacheRead = usage.cache_read_input_tokens;
81
+ return {
82
+ promptTokens: usage.input_tokens + (cacheWrite ?? 0) + (cacheRead ?? 0),
89
83
  completionTokens: usage.output_tokens,
84
+ // A part the vendor reports is kept, 0 included.
85
+ ...(typeof cacheRead === 'number' && { cacheReadTokens: cacheRead }),
86
+ ...(typeof cacheWrite === 'number' && { cacheWriteTokens: cacheWrite }),
90
87
  };
91
- return cacheRead > 0 ? { ...base, cachedTokens: cacheRead } : base;
92
88
  }
package/src/provider.ts CHANGED
@@ -10,6 +10,7 @@ import type {
10
10
  ModelProvider,
11
11
  ProviderMetadata,
12
12
  } from '@kindgi/capabilities';
13
+ import { createAttemptCounter } from '@kindgi/capabilities/attempts';
13
14
 
14
15
  import { computeCostUsd, toFrameworkUsage } from './cost.js';
15
16
  import {
@@ -71,7 +72,10 @@ export interface AnthropicProviderOptions {
71
72
  * Additional SDK client options (timeouts, custom fetch, headers,
72
73
  * etc.). `apiKey` and `baseURL` from the top level always win.
73
74
  */
74
- readonly clientOptions?: Omit<ConstructorParameters<typeof Anthropic>[0], 'apiKey' | 'baseURL'>;
75
+ readonly clientOptions?: Omit<
76
+ NonNullable<ConstructorParameters<typeof Anthropic>[0]>,
77
+ 'apiKey' | 'baseURL'
78
+ >;
75
79
  /**
76
80
  * Dependency-injected SDK client. When present, `apiKey` /
77
81
  * `baseURL` / `clientOptions` are ignored on construction (tests
@@ -110,6 +114,9 @@ export function createAnthropicProvider(options: AnthropicProviderOptions): Mode
110
114
  // keepalive — throwing it away on every invoke would tank latency).
111
115
  // When the resolver returns a new value (key rotation), rebuild.
112
116
  let cached: { readonly key: string; readonly client: Anthropic } | undefined;
117
+ // Counts each call's HTTP attempts, the SDK's own retries included (its
118
+ // retry policy stays the SDK's), through the `fetch` the client sends with.
119
+ const attempts = createAttemptCounter(options.clientOptions?.fetch);
113
120
  if (options.client !== undefined) {
114
121
  // Dep-injected client — pin to sentinel key so resolveClient below
115
122
  // always returns the same instance regardless of what the resolver
@@ -130,6 +137,7 @@ export function createAnthropicProvider(options: AnthropicProviderOptions): Mode
130
137
  apiKey: key,
131
138
  ...(options.baseURL !== undefined && { baseURL: options.baseURL }),
132
139
  ...(options.clientOptions ?? {}),
140
+ fetch: attempts.fetch,
133
141
  });
134
142
  cached = { key, client };
135
143
  return client;
@@ -158,17 +166,20 @@ export function createAnthropicProvider(options: AnthropicProviderOptions): Mode
158
166
  input.abortSignal !== undefined ? { signal: input.abortSignal } : {};
159
167
  const maxTokens = input.maxOutputTokens ?? modelInfo.maxOutputTokens ?? DEFAULT_MAX_TOKENS;
160
168
 
161
- const response = await client.messages.create(
162
- {
163
- model: input.model,
164
- max_tokens: maxTokens,
165
- ...(system !== undefined && { system }),
166
- messages: [...messages],
167
- ...(tools !== undefined && { tools: [...tools] }),
168
- ...(input.temperature !== undefined && { temperature: input.temperature }),
169
- },
170
- requestOptions,
169
+ const counted = await attempts.count(() =>
170
+ client.messages.create(
171
+ {
172
+ model: input.model,
173
+ max_tokens: maxTokens,
174
+ ...(system !== undefined && { system }),
175
+ messages: [...messages],
176
+ ...(tools !== undefined && { tools: [...tools] }),
177
+ ...(input.temperature !== undefined && { temperature: input.temperature }),
178
+ },
179
+ requestOptions,
180
+ ),
171
181
  );
182
+ const response = counted.value;
172
183
 
173
184
  const durationMs = Date.now() - startedAt;
174
185
  const message = fromAnthropicResponse(response);
@@ -182,6 +193,13 @@ export function createAnthropicProvider(options: AnthropicProviderOptions): Mode
182
193
  costUsd,
183
194
  durationMs,
184
195
  provider: { id: metadata.id, model: input.model },
196
+ ...(response.model !== undefined && { servedModel: response.model }),
197
+ ...(typeof response._request_id === 'string' && {
198
+ providerRequestId: response._request_id,
199
+ }),
200
+ // An injected client sends with its own fetch: nothing was counted.
201
+ ...(counted.attempts > 0 && { attempts: counted.attempts }),
202
+ rawUsage: { ...response.usage },
185
203
  };
186
204
  },
187
205
  };