@warlock.js/ai-anthropic 5.29.0 → 5.31.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/CHANGELOG.md +63 -0
- package/cjs/index.cjs +1124 -147
- package/cjs/index.cjs.map +1 -1
- package/esm/config.type.d.mts +170 -3
- package/esm/config.type.d.mts.map +1 -1
- package/esm/index.d.mts +9 -3
- package/esm/index.mjs +8 -1
- package/esm/known-output-limits.mjs +46 -0
- package/esm/known-output-limits.mjs.map +1 -0
- package/esm/known-pricing.d.mts +58 -0
- package/esm/known-pricing.d.mts.map +1 -0
- package/esm/known-pricing.mjs +165 -0
- package/esm/known-pricing.mjs.map +1 -0
- package/esm/known-vision-models.mjs +1 -1
- package/esm/known-vision-models.mjs.map +1 -1
- package/esm/model.d.mts +322 -0
- package/esm/model.d.mts.map +1 -0
- package/esm/model.mjs +523 -73
- package/esm/model.mjs.map +1 -1
- package/esm/request.type.d.mts +25 -0
- package/esm/request.type.d.mts.map +1 -0
- package/esm/sdk.d.mts +7 -6
- package/esm/sdk.d.mts.map +1 -1
- package/esm/sdk.mjs +4 -4
- package/esm/sdk.mjs.map +1 -1
- package/esm/thinking-mode.d.mts +15 -2
- package/esm/thinking-mode.d.mts.map +1 -1
- package/esm/thinking-mode.mjs +128 -2
- package/esm/thinking-mode.mjs.map +1 -1
- package/esm/utils/cache-usage.mjs +62 -0
- package/esm/utils/cache-usage.mjs.map +1 -0
- package/esm/utils/index.d.mts +3 -0
- package/esm/utils/index.mjs +1 -0
- package/esm/utils/map-stop-reason.d.mts +1 -0
- package/esm/utils/map-stop-reason.mjs +17 -13
- package/esm/utils/map-stop-reason.mjs.map +1 -1
- package/esm/utils/provider-blocks.d.mts +39 -0
- package/esm/utils/provider-blocks.d.mts.map +1 -0
- package/esm/utils/provider-blocks.mjs +83 -0
- package/esm/utils/provider-blocks.mjs.map +1 -0
- package/esm/utils/to-anthropic-messages.d.mts +71 -0
- package/esm/utils/to-anthropic-messages.d.mts.map +1 -0
- package/esm/utils/to-anthropic-messages.mjs +53 -13
- package/esm/utils/to-anthropic-messages.mjs.map +1 -1
- package/esm/utils/to-anthropic-tools.d.mts +19 -0
- package/esm/utils/to-anthropic-tools.d.mts.map +1 -0
- package/esm/utils/to-anthropic-tools.mjs +1 -1
- package/esm/utils/to-anthropic-tools.mjs.map +1 -1
- package/esm/utils/wrap-anthropic-error.d.mts +1 -0
- package/esm/utils/wrap-anthropic-error.mjs +7 -2
- package/esm/utils/wrap-anthropic-error.mjs.map +1 -1
- package/llms-full.txt +273 -27
- package/llms.txt +1 -1
- package/package.json +5 -4
- package/skills/README.md +1 -1
- package/skills/setup-anthropic/SKILL.md +273 -27
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { extractJsonSchema } from "@warlock.js/ai";
|
|
2
2
|
|
|
3
|
-
//#region
|
|
3
|
+
//#region ../../packages/ai-anthropic/src/utils/to-anthropic-tools.ts
|
|
4
4
|
/**
|
|
5
5
|
* Convert vendor-neutral `ToolConfig[]` into Anthropic's `tools` array.
|
|
6
6
|
* Uses the shared `extractJsonSchema` helper; Anthropic requires the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"to-anthropic-tools.mjs","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"to-anthropic-tools.mjs","names":[],"sources":["../../../../../../../../packages/ai-anthropic/src/utils/to-anthropic-tools.ts"],"sourcesContent":["import { extractJsonSchema, type ToolConfig } from \"@warlock.js/ai\";\nimport type Anthropic from \"@anthropic-ai/sdk\";\n\n/**\n * Convert vendor-neutral `ToolConfig[]` into Anthropic's `tools` array.\n * Uses the shared `extractJsonSchema` helper; Anthropic requires the\n * input schema to be a JSON-Schema object, so a non-object extraction\n * is coerced into an empty-object schema rather than rejected — the\n * tool still registers and the model simply sees no parameters.\n *\n * @example\n * const tools = toAnthropicTools([weatherTool, calculatorTool]);\n * await client.messages.create({ model, max_tokens, messages, tools });\n */\nexport function toAnthropicTools(\n tools: ToolConfig<unknown, unknown>[] | undefined,\n): Anthropic.Tool[] | undefined {\n if (!tools || tools.length === 0) {\n return undefined;\n }\n\n return tools.map((tool) => ({\n name: tool.name,\n description: tool.description,\n input_schema: toInputSchema(tool.input),\n }));\n}\n\n/**\n * Coerce the extracted JSON Schema into Anthropic's `Tool.InputSchema`\n * shape (root must be `{ type: \"object\" }`). Anything that isn't an\n * object schema degrades to a parameterless object so registration\n * never fails on a malformed extractor result.\n */\nfunction toInputSchema(input: ToolConfig<unknown, unknown>[\"input\"]): Anthropic.Tool.InputSchema {\n const schema = extractJsonSchema(input);\n\n if (schema && schema.type === \"object\") {\n return schema as Anthropic.Tool.InputSchema;\n }\n\n return { type: \"object\" };\n}\n"],"mappings":";;;;;;;;;;;;;;AAcA,SAAgB,iBACd,OAC8B;CAC9B,IAAI,CAAC,SAAS,MAAM,WAAW,GAC7B;CAGF,OAAO,MAAM,KAAK,UAAU;EAC1B,MAAM,KAAK;EACX,aAAa,KAAK;EAClB,cAAc,cAAc,KAAK,KAAK;CACxC,EAAE;AACJ;;;;;;;AAQA,SAAS,cAAc,OAA0E;CAC/F,MAAM,SAAS,kBAAkB,KAAK;CAEtC,IAAI,UAAU,OAAO,SAAS,UAC5B,OAAO;CAGT,OAAO,EAAE,MAAM,SAAS;AAC1B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import { AIError } from "@warlock.js/ai";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { APIConnectionTimeoutError, APIError } from "@anthropic-ai/sdk";
|
|
2
|
-
import { AIError, ContextLengthExceededError, InvalidRequestError, ProviderAuthError, ProviderError, ProviderRateLimitError, ProviderTimeoutError, QuotaExceededError } from "@warlock.js/ai";
|
|
2
|
+
import { AIError, ContextLengthExceededError, InvalidRequestError, ProviderAuthError, ProviderError, ProviderOverloadedError, ProviderRateLimitError, ProviderTimeoutError, QuotaExceededError } from "@warlock.js/ai";
|
|
3
3
|
|
|
4
|
-
//#region
|
|
4
|
+
//#region ../../packages/ai-anthropic/src/utils/wrap-anthropic-error.ts
|
|
5
5
|
/**
|
|
6
6
|
* Wrap any thrown value caught inside the Anthropic adapter into the
|
|
7
7
|
* appropriate `@warlock.js/ai` `AIError` subclass.
|
|
@@ -51,6 +51,11 @@ function wrapAnthropicError(thrown) {
|
|
|
51
51
|
context,
|
|
52
52
|
retryAfter: parseRetryAfter(shape.headers)
|
|
53
53
|
});
|
|
54
|
+
if (shape.type === "overloaded_error" || shape.status === 529) return new ProviderOverloadedError(message, {
|
|
55
|
+
cause: thrown,
|
|
56
|
+
context,
|
|
57
|
+
retryAfter: parseRetryAfter(shape.headers)
|
|
58
|
+
});
|
|
54
59
|
if (shape.type === "invalid_request_error" || isClientStatus(shape.status)) {
|
|
55
60
|
if (/prompt is too long/i.test(message)) return new ContextLengthExceededError(message, {
|
|
56
61
|
cause: thrown,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wrap-anthropic-error.mjs","names":[],"sources":["../../../../../../../ai-anthropic/src/utils/wrap-anthropic-error.ts"],"sourcesContent":["import {\n AIError,\n ContextLengthExceededError,\n InvalidRequestError,\n ProviderAuthError,\n ProviderError,\n ProviderRateLimitError,\n ProviderTimeoutError,\n QuotaExceededError,\n} from \"@warlock.js/ai\";\nimport { APIConnectionTimeoutError, APIError } from \"@anthropic-ai/sdk\";\n\n/**\n * Raw-error fields the wrapper reads off an Anthropic SDK error.\n *\n * `APIError` exposes `status`, `type` (the `error.type` from the\n * response body, e.g. `\"rate_limit_error\"`), `message`, `headers`, and\n * `requestID`. We duck-type because wrapped retries, proxied errors,\n * and custom subclasses sometimes lose the `instanceof` relationship.\n */\ntype AnthropicErrorShape = {\n status?: number;\n type?: string | null;\n message?: string;\n headers?: HeaderBag | undefined;\n name?: string;\n requestId?: string;\n};\n\n/** Either a fetch `Headers` instance or a plain record (duck-typed tests). */\ntype HeaderBag = Headers | Record<string, string>;\n\n/**\n * Wrap any thrown value caught inside the Anthropic adapter into the\n * appropriate `@warlock.js/ai` `AIError` subclass.\n *\n * **Dispatch strategy.** Anthropic has no per-error machine `code`; the\n * stable identifier is `error.type` on the response body (surfaced as\n * `APIError.type`). Dispatch prefers `type`, falls back to `status`\n * when the body was stripped (common with proxies). Name-based\n * detection catches transport-layer timeouts that never produced an\n * HTTP response. The `invalid_request_error` branch additionally\n * sniffs the message for Anthropic's \"prompt is too long\" phrasing,\n * which is the only signal that a 400 was a context-length overflow.\n *\n * `AIError` instances pass through unchanged so `catch/throw wrap(e)`\n * pipelines never double-wrap.\n *\n * @example\n * try {\n * return await this.client.messages.create(...);\n * } catch (thrown) {\n * throw wrapAnthropicError(thrown);\n * }\n */\nexport function wrapAnthropicError(thrown: unknown): AIError {\n if (thrown instanceof AIError) {\n return thrown;\n }\n\n const shape = toShape(thrown);\n const context = buildContext(shape);\n const message = shape.message ?? (thrown instanceof Error ? thrown.message : String(thrown));\n\n if (isTimeout(thrown, shape)) {\n return new ProviderTimeoutError(message, { cause: thrown, context });\n }\n\n if (shape.type === \"authentication_error\" || shape.type === \"permission_error\") {\n return new ProviderAuthError(message, { cause: thrown, context });\n }\n\n if (shape.status === 401 || shape.status === 403) {\n return new ProviderAuthError(message, { cause: thrown, context });\n }\n\n if (shape.type === \"billing_error\") {\n return new QuotaExceededError(message, { cause: thrown, context });\n }\n\n if (shape.type === \"rate_limit_error\" || shape.status === 429) {\n return new ProviderRateLimitError(message, {\n cause: thrown,\n context,\n retryAfter: parseRetryAfter(shape.headers),\n });\n }\n\n if (shape.type === \"invalid_request_error\" || isClientStatus(shape.status)) {\n if (/prompt is too long/i.test(message)) {\n return new ContextLengthExceededError(message, { cause: thrown, context });\n }\n\n return new InvalidRequestError(message, { cause: thrown, context });\n }\n\n return new ProviderError(message, { cause: thrown, context });\n}\n\n/**\n * Read the raw error shape without depending on `instanceof APIError`\n * — proxies and re-wrappers strip the prototype chain. Duck-typing on\n * the visible fields is resilient to both.\n */\nfunction toShape(thrown: unknown): AnthropicErrorShape {\n if (thrown instanceof APIError) {\n return {\n status: typeof thrown.status === \"number\" ? thrown.status : undefined,\n type: thrown.type,\n message: thrown.message,\n headers: thrown.headers,\n name: thrown.name,\n requestId: thrown.requestID ?? undefined,\n };\n }\n\n if (typeof thrown === \"object\" && thrown !== null) {\n const raw = thrown as Record<string, unknown>;\n\n return {\n status: typeof raw.status === \"number\" ? raw.status : undefined,\n type: typeof raw.type === \"string\" ? raw.type : undefined,\n message: typeof raw.message === \"string\" ? raw.message : undefined,\n headers: isHeaderBag(raw.headers) ? raw.headers : undefined,\n name: typeof raw.name === \"string\" ? raw.name : undefined,\n requestId: readRequestId(raw),\n };\n }\n\n return {};\n}\n\n/**\n * Decide whether the thrown value represents a timeout. The Anthropic\n * SDK throws `APIConnectionTimeoutError` for transport-level timeouts;\n * Node surfaces `ETIMEDOUT` / `ECONNABORTED` on the socket layer.\n * Either signal counts.\n */\nfunction isTimeout(thrown: unknown, shape: AnthropicErrorShape): boolean {\n if (thrown instanceof APIConnectionTimeoutError) {\n return true;\n }\n\n if (shape.name === \"APIConnectionTimeoutError\") {\n return true;\n }\n\n if (typeof thrown === \"object\" && thrown !== null) {\n const code = (thrown as Record<string, unknown>).code;\n\n if (code === \"ETIMEDOUT\" || code === \"ECONNABORTED\") {\n return true;\n }\n }\n\n return false;\n}\n\n/** True for HTTP 4xx — a client-side request problem, not a server fault. */\nfunction isClientStatus(status: number | undefined): boolean {\n return typeof status === \"number\" && status >= 400 && status < 500;\n}\n\n/**\n * Attach the raw diagnostic fields to `error.context` so consumers\n * have everything the provider surfaced without each subclass having\n * to redeclare them. Never includes `cause` — that lives on\n * `error.cause`.\n */\nfunction buildContext(shape: AnthropicErrorShape): Record<string, unknown> {\n const context: Record<string, unknown> = {};\n\n if (shape.status !== undefined) {\n context.status = shape.status;\n }\n\n if (shape.type) {\n context.type = shape.type;\n }\n\n if (shape.requestId) {\n context.requestId = shape.requestId;\n }\n\n return context;\n}\n\n/** Anthropic exposes the request id as `requestID`; some proxies use `request_id`. */\nfunction readRequestId(raw: Record<string, unknown>): string | undefined {\n if (typeof raw.requestID === \"string\") {\n return raw.requestID;\n }\n\n if (typeof raw.request_id === \"string\") {\n return raw.request_id;\n }\n\n return undefined;\n}\n\nfunction isHeaderBag(value: unknown): value is HeaderBag {\n return typeof value === \"object\" && value !== null;\n}\n\n/** Read a header value from either a `Headers` instance or a plain record. */\nfunction readHeader(headers: HeaderBag, name: string): string | undefined {\n if (typeof (headers as Headers).get === \"function\") {\n return (headers as Headers).get(name) ?? undefined;\n }\n\n const record = headers as Record<string, string>;\n\n return record[name] ?? record[name.toLowerCase()];\n}\n\n/**\n * Parse the `Retry-After` response header (seconds per HTTP spec) into\n * milliseconds so consumers can feed it straight to `setTimeout`.\n * Returns `undefined` when missing or unparseable.\n */\nfunction parseRetryAfter(headers: HeaderBag | undefined): number | undefined {\n if (!headers) {\n return undefined;\n }\n\n const raw = readHeader(headers, \"retry-after\") ?? readHeader(headers, \"Retry-After\");\n\n if (!raw) {\n return undefined;\n }\n\n const seconds = Number(raw);\n\n if (!Number.isFinite(seconds) || seconds < 0) {\n return undefined;\n }\n\n return Math.round(seconds * 1000);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"wrap-anthropic-error.mjs","names":[],"sources":["../../../../../../../../packages/ai-anthropic/src/utils/wrap-anthropic-error.ts"],"sourcesContent":["import {\n AIError,\n ContextLengthExceededError,\n InvalidRequestError,\n ProviderAuthError,\n ProviderError,\n ProviderOverloadedError,\n ProviderRateLimitError,\n ProviderTimeoutError,\n QuotaExceededError,\n} from \"@warlock.js/ai\";\nimport { APIConnectionTimeoutError, APIError } from \"@anthropic-ai/sdk\";\n\n/**\n * Raw-error fields the wrapper reads off an Anthropic SDK error.\n *\n * `APIError` exposes `status`, `type` (the `error.type` from the\n * response body, e.g. `\"rate_limit_error\"`), `message`, `headers`, and\n * `requestID`. We duck-type because wrapped retries, proxied errors,\n * and custom subclasses sometimes lose the `instanceof` relationship.\n */\ntype AnthropicErrorShape = {\n status?: number;\n type?: string | null;\n message?: string;\n headers?: HeaderBag | undefined;\n name?: string;\n requestId?: string;\n};\n\n/** Either a fetch `Headers` instance or a plain record (duck-typed tests). */\ntype HeaderBag = Headers | Record<string, string>;\n\n/**\n * Wrap any thrown value caught inside the Anthropic adapter into the\n * appropriate `@warlock.js/ai` `AIError` subclass.\n *\n * **Dispatch strategy.** Anthropic has no per-error machine `code`; the\n * stable identifier is `error.type` on the response body (surfaced as\n * `APIError.type`). Dispatch prefers `type`, falls back to `status`\n * when the body was stripped (common with proxies). Name-based\n * detection catches transport-layer timeouts that never produced an\n * HTTP response. The `invalid_request_error` branch additionally\n * sniffs the message for Anthropic's \"prompt is too long\" phrasing,\n * which is the only signal that a 400 was a context-length overflow.\n *\n * `AIError` instances pass through unchanged so `catch/throw wrap(e)`\n * pipelines never double-wrap.\n *\n * @example\n * try {\n * return await this.client.messages.create(...);\n * } catch (thrown) {\n * throw wrapAnthropicError(thrown);\n * }\n */\nexport function wrapAnthropicError(thrown: unknown): AIError {\n if (thrown instanceof AIError) {\n return thrown;\n }\n\n const shape = toShape(thrown);\n const context = buildContext(shape);\n const message = shape.message ?? (thrown instanceof Error ? thrown.message : String(thrown));\n\n if (isTimeout(thrown, shape)) {\n return new ProviderTimeoutError(message, { cause: thrown, context });\n }\n\n if (shape.type === \"authentication_error\" || shape.type === \"permission_error\") {\n return new ProviderAuthError(message, { cause: thrown, context });\n }\n\n if (shape.status === 401 || shape.status === 403) {\n return new ProviderAuthError(message, { cause: thrown, context });\n }\n\n if (shape.type === \"billing_error\") {\n return new QuotaExceededError(message, { cause: thrown, context });\n }\n\n if (shape.type === \"rate_limit_error\" || shape.status === 429) {\n return new ProviderRateLimitError(message, {\n cause: thrown,\n context,\n retryAfter: parseRetryAfter(shape.headers),\n });\n }\n\n // HTTP 529 / `overloaded_error` — also delivered as a mid-stream SSE\n // `error` event, where no status exists.\n if (shape.type === \"overloaded_error\" || shape.status === 529) {\n return new ProviderOverloadedError(message, {\n cause: thrown,\n context,\n retryAfter: parseRetryAfter(shape.headers),\n });\n }\n\n if (shape.type === \"invalid_request_error\" || isClientStatus(shape.status)) {\n if (/prompt is too long/i.test(message)) {\n return new ContextLengthExceededError(message, { cause: thrown, context });\n }\n\n return new InvalidRequestError(message, { cause: thrown, context });\n }\n\n return new ProviderError(message, { cause: thrown, context });\n}\n\n/**\n * Read the raw error shape without depending on `instanceof APIError`\n * — proxies and re-wrappers strip the prototype chain. Duck-typing on\n * the visible fields is resilient to both.\n */\nfunction toShape(thrown: unknown): AnthropicErrorShape {\n if (thrown instanceof APIError) {\n return {\n status: typeof thrown.status === \"number\" ? thrown.status : undefined,\n type: thrown.type,\n message: thrown.message,\n headers: thrown.headers,\n name: thrown.name,\n requestId: thrown.requestID ?? undefined,\n };\n }\n\n if (typeof thrown === \"object\" && thrown !== null) {\n const raw = thrown as Record<string, unknown>;\n\n return {\n status: typeof raw.status === \"number\" ? raw.status : undefined,\n type: typeof raw.type === \"string\" ? raw.type : undefined,\n message: typeof raw.message === \"string\" ? raw.message : undefined,\n headers: isHeaderBag(raw.headers) ? raw.headers : undefined,\n name: typeof raw.name === \"string\" ? raw.name : undefined,\n requestId: readRequestId(raw),\n };\n }\n\n return {};\n}\n\n/**\n * Decide whether the thrown value represents a timeout. The Anthropic\n * SDK throws `APIConnectionTimeoutError` for transport-level timeouts;\n * Node surfaces `ETIMEDOUT` / `ECONNABORTED` on the socket layer.\n * Either signal counts.\n */\nfunction isTimeout(thrown: unknown, shape: AnthropicErrorShape): boolean {\n if (thrown instanceof APIConnectionTimeoutError) {\n return true;\n }\n\n if (shape.name === \"APIConnectionTimeoutError\") {\n return true;\n }\n\n if (typeof thrown === \"object\" && thrown !== null) {\n const code = (thrown as Record<string, unknown>).code;\n\n if (code === \"ETIMEDOUT\" || code === \"ECONNABORTED\") {\n return true;\n }\n }\n\n return false;\n}\n\n/** True for HTTP 4xx — a client-side request problem, not a server fault. */\nfunction isClientStatus(status: number | undefined): boolean {\n return typeof status === \"number\" && status >= 400 && status < 500;\n}\n\n/**\n * Attach the raw diagnostic fields to `error.context` so consumers\n * have everything the provider surfaced without each subclass having\n * to redeclare them. Never includes `cause` — that lives on\n * `error.cause`.\n */\nfunction buildContext(shape: AnthropicErrorShape): Record<string, unknown> {\n const context: Record<string, unknown> = {};\n\n if (shape.status !== undefined) {\n context.status = shape.status;\n }\n\n if (shape.type) {\n context.type = shape.type;\n }\n\n if (shape.requestId) {\n context.requestId = shape.requestId;\n }\n\n return context;\n}\n\n/** Anthropic exposes the request id as `requestID`; some proxies use `request_id`. */\nfunction readRequestId(raw: Record<string, unknown>): string | undefined {\n if (typeof raw.requestID === \"string\") {\n return raw.requestID;\n }\n\n if (typeof raw.request_id === \"string\") {\n return raw.request_id;\n }\n\n return undefined;\n}\n\nfunction isHeaderBag(value: unknown): value is HeaderBag {\n return typeof value === \"object\" && value !== null;\n}\n\n/** Read a header value from either a `Headers` instance or a plain record. */\nfunction readHeader(headers: HeaderBag, name: string): string | undefined {\n if (typeof (headers as Headers).get === \"function\") {\n return (headers as Headers).get(name) ?? undefined;\n }\n\n const record = headers as Record<string, string>;\n\n return record[name] ?? record[name.toLowerCase()];\n}\n\n/**\n * Parse the `Retry-After` response header (seconds per HTTP spec) into\n * milliseconds so consumers can feed it straight to `setTimeout`.\n * Returns `undefined` when missing or unparseable.\n */\nfunction parseRetryAfter(headers: HeaderBag | undefined): number | undefined {\n if (!headers) {\n return undefined;\n }\n\n const raw = readHeader(headers, \"retry-after\") ?? readHeader(headers, \"Retry-After\");\n\n if (!raw) {\n return undefined;\n }\n\n const seconds = Number(raw);\n\n if (!Number.isFinite(seconds) || seconds < 0) {\n return undefined;\n }\n\n return Math.round(seconds * 1000);\n}\n"],"mappings":"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"}
|
package/llms-full.txt
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
---
|
|
10
10
|
name: setup-anthropic
|
|
11
|
-
description: 'Wire @warlock.js/ai-anthropic — new AnthropicSDK({apiKey, baseURL?, provider?}) for Claude, .model({name, vision?, structuredOutput?, reasoning?, thinkingMode?, promptCaching?, maxTokens?}). System-prompt hoisting, max_tokens required (default
|
|
11
|
+
description: 'Wire @warlock.js/ai-anthropic — new AnthropicSDK({apiKey, baseURL?, provider?}) for Claude, .model({name, vision?, structuredOutput?, reasoning?, thinkingMode?, promptCaching?, maxTokens?, maxOutputTokens?}). System-prompt hoisting, max_tokens required (default: model max output when streaming, 16384 non-streaming; maxOutputTokens for gateway ids), extended thinking via options.reasoning → adaptive thinking + output_config.effort (current/unknown models) or budget_tokens (Haiku 4.5, 4.6 and older; override with thinkingMode), prompt caching via promptCaching + options.cacheControl (per-call ttl), provider blocks (thinking/compaction) replayed verbatim via ModelResponse.blocks / Message.blocks, providerOptions.anthropic (betas, body fields such as context_management / fallbacks, thinkingDisplay), model.countTokens(), distinct finish reasons (pause_turn, refusal, context_exceeded), built-in Claude list prices (ANTHROPIC_MODEL_PRICING, anthropicPricingFor, withAnthropicCacheWriteRates), cost-truth usage (inputIncludesCache: false, cachedTokens/cacheWriteTokens/cacheWrite1hTokens, usage.cost on complete()), ProviderOverloadedError for 529, no first-party embeddings. Triggers: `AnthropicSDK`, `anthropic.model`, `anthropic.count`, `maxTokens`, `maxOutputTokens`, `max_tokens`, `reasoning`, `thinking`, `budget_tokens`, `thinkingMode`, `adaptive`, `cacheControl`, `providerOptions`, `blocks`, `countTokens`, `pause_turn`, `refusal`, `context_management`, `contextManagement`, `serverCompaction`, `clear_tool_uses`, `clear_thinking`, `thinkingBlockBinding`, `block_binding`, `preservedThinking`, `ai.providerTool`, `web_search_20250305`, `bash_20250124`, `text_editor_20250728`, `streamChunks`, `thinking_delta`, `compaction`, `promptCaching`, `cachedTokens`, `cacheWriteTokens`, `cacheWrite1hTokens`, `inputIncludesCache`, `ANTHROPIC_MODEL_PRICING`, `ProviderOverloadedError`, `claude-sonnet-4-6`, `claude-haiku-4-5`, `claude-opus-4-7`; "wire claude into warlock agent", "configure anthropic provider", "use claude sonnet", "anthropic gateway baseURL", "claude extended thinking", "anthropic prompt caching cost"; typical import `import { AnthropicSDK } from "@warlock.js/ai-anthropic"`. Skip: embeddings — the `setup-openai` topic of the `warlock-js-ai-openai` skill; sibling adapters `@warlock.js/ai-openai`, `@warlock.js/ai-bedrock`, `@warlock.js/ai-google`, `@warlock.js/ai-ollama`; raw `@anthropic-ai/sdk`; Vercel `@ai-sdk/anthropic`.'
|
|
12
12
|
---
|
|
13
13
|
|
|
14
14
|
# `@warlock.js/ai-anthropic`
|
|
@@ -55,41 +55,95 @@ Explicit config always wins (`structuredOutput`, `vision`, `reasoning`, `thinkin
|
|
|
55
55
|
|
|
56
56
|
## Pricing & cost
|
|
57
57
|
|
|
58
|
-
|
|
58
|
+
Every model is priced out of the box from the built-in Claude list prices; supply your own rates to override them. Pricing reaches `Usage.cost` on every agent report **and** on the `usage` of a direct `model.complete()` / the streaming `done` chunk, so side calls outside an agent are costed too. Unknown ids stay unpriced (`cost` is `undefined` — honest absence, never a false zero).
|
|
59
|
+
|
|
60
|
+
Resolution at `model()` time: per-model `pricing` > SDK registry entry for that name > built-in `ANTHROPIC_MODEL_PRICING` (alias or dated snapshot id) > `undefined`.
|
|
59
61
|
|
|
60
62
|
```ts
|
|
61
|
-
|
|
63
|
+
import {
|
|
64
|
+
ANTHROPIC_MODEL_PRICING,
|
|
65
|
+
AnthropicSDK,
|
|
66
|
+
anthropicPricingFor,
|
|
67
|
+
withAnthropicCacheWriteRates,
|
|
68
|
+
} from "@warlock.js/ai-anthropic";
|
|
69
|
+
|
|
62
70
|
const anthropic = new AnthropicSDK({
|
|
63
|
-
apiKey,
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
"claude-sonnet-4-6": { input: 3, output: 15, cachedInput: 0.3 },
|
|
67
|
-
},
|
|
71
|
+
apiKey: process.env.ANTHROPIC_API_KEY ?? "",
|
|
72
|
+
// SDK-level registry — wins over the built-in table, keyed by model name.
|
|
73
|
+
pricing: { "claude-sonnet-4-6": { input: 3, output: 15, cachedInput: 0.3 } },
|
|
68
74
|
});
|
|
69
75
|
|
|
70
|
-
|
|
71
|
-
anthropic.model({ name: "claude-sonnet-4-6"
|
|
76
|
+
anthropic.model({ name: "claude-opus-5-5" }).pricing; // built-in: { input: 4, output: 20, cachedInput: 0.2, cacheWrite: 5, cacheWrite1h: 8 }
|
|
77
|
+
anthropic.model({ name: "claude-sonnet-4-6" }).pricing; // registry entry + write rates filled: cacheWrite 3.75, cacheWrite1h 6
|
|
78
|
+
anthropic.model({ name: "claude-haiku-4-5", pricing: { input: 1, output: 5 } }); // per-model override
|
|
79
|
+
|
|
80
|
+
anthropicPricingFor("claude-haiku-4-5-20251001"); // dated snapshot → the alias entry
|
|
81
|
+
withAnthropicCacheWriteRates({ input: 2, output: 10 }); // { input: 2, output: 10, cacheWrite: 2.5, cacheWrite1h: 4 }
|
|
82
|
+
Object.keys(ANTHROPIC_MODEL_PRICING); // the priced ids
|
|
72
83
|
```
|
|
73
84
|
|
|
74
|
-
|
|
85
|
+
- **Source.** `ANTHROPIC_MODEL_PRICING` holds the "Model pricing" table of https://platform.claude.com/docs/en/about-claude/pricing (fetched 2026-10-17): input, output, cache read (`cachedInput`), 5-minute write (`cacheWrite`) and 1-hour write (`cacheWrite1h`), USD per 1M tokens, standard global routing.
|
|
86
|
+
- **Write rates are filled for you.** Anthropic charges 1.25x input for a 5-minute cache write and 2x for a 1-hour write on every Claude model, so any entry without `cacheWrite` / `cacheWrite1h` (your own `{ input, output }` included) gets them from those multipliers (`withAnthropicCacheWriteRates`, exported with `ANTHROPIC_CACHE_WRITE_MULTIPLIER` / `ANTHROPIC_CACHE_WRITE_1H_MULTIPLIER`). The read rate differs per model (0.1x, 0.05x on Opus 5.5 / Sonnet 5.5, 0.025x on Fable 5.1), so it is never derived — set `cachedInput` yourself when you supply pricing, or cache reads bill at the full input rate.
|
|
87
|
+
- **Deliberately unpriced** (pass `pricing` yourself): Claude Haiku 5.5 (priced by prompt length — higher rates above 100,000 prompt tokens, which a flat rate cannot express), US-only inference (`inference_geo: "us"`, 1.1x), fast mode, the Batch API, limited-availability and retired models, and Claude on Bedrock / Vertex (partner-priced — see `@warlock.js/ai-bedrock`).
|
|
75
88
|
|
|
76
89
|
## Tokens & usage accounting
|
|
77
90
|
|
|
78
|
-
Every `ModelResponse.usage` (and the streaming terminal `done`) is normalized to the neutral `Usage` shape. Anthropic
|
|
91
|
+
Every `ModelResponse.usage` (and the streaming terminal `done`) is normalized to the neutral `Usage` shape. Anthropic's `input_tokens` is the **uncached remainder only** — cache reads and writes come on top of it — so the adapter marks the usage `inputIncludesCache: false` and `computeCost` bills each channel exactly once. `total` is computed (`input + output`); the full prompt size is `input + cachedTokens + cacheWriteTokens`.
|
|
92
|
+
|
|
93
|
+
| Neutral field | Anthropic source | Meaning / billing |
|
|
94
|
+
| -------------------------- | ------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
95
|
+
| `usage.input` | `input_tokens` | Uncached input. Bills at `input`. |
|
|
96
|
+
| `usage.inputIncludesCache` | — (always `false`) | Tells `computeCost` not to subtract cache tokens from `input`. |
|
|
97
|
+
| `usage.cachedTokens` | `cache_read_input_tokens` | Tokens read from the prompt cache. Bills at `cachedInput` (falls back to `input` when unset). |
|
|
98
|
+
| `usage.cacheWriteTokens` | `cache_creation_input_tokens` | Tokens **written** to the cache. Bills at `cacheWrite` (5-minute, 1.25x input). |
|
|
99
|
+
| `usage.cacheWrite1hTokens` | `cache_creation.ephemeral_1h_input_tokens` | The 1-hour share of the writes. Bills at `cacheWrite1h` (2x input). Without the breakdown, all writes count as 1-hour when every marker asked for `"1h"`. |
|
|
100
|
+
| `usage.reasoningTokens` | `output_tokens_details.thinking_tokens` | The thinking subset of `output_tokens`, informational; billed inside `output`. |
|
|
101
|
+
| `usage.cost` | computed | Per-channel USD (`input`, `output`, `cachedInput`, `cacheWrite`) when the model is priced. Sum with `totalCost(usage.cost)` from `@warlock.js/ai`. |
|
|
102
|
+
|
|
103
|
+
```ts
|
|
104
|
+
import { totalCost } from "@warlock.js/ai";
|
|
105
|
+
import { AnthropicSDK } from "@warlock.js/ai-anthropic";
|
|
106
|
+
|
|
107
|
+
const model = new AnthropicSDK({ apiKey: process.env.ANTHROPIC_API_KEY ?? "" }).model({
|
|
108
|
+
name: "claude-sonnet-4-6",
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
const { usage } = await model.complete([{ role: "user", content: "Summarise this thread." }]);
|
|
79
112
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
113
|
+
// 100 uncached + 50,000 read + 20,000 written + 500 output is billed as
|
|
114
|
+
// 100×3 + 50,000×0.3 + 20,000×3.75 + 500×15 (USD per 1M tokens).
|
|
115
|
+
console.log(
|
|
116
|
+
usage.inputIncludesCache,
|
|
117
|
+
usage.cachedTokens,
|
|
118
|
+
usage.cacheWriteTokens,
|
|
119
|
+
totalCost(usage.cost),
|
|
120
|
+
);
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
With server-side compaction (`serverCompaction`), the `compaction` entries of `usage.iterations` are added to `input` / `output` / the cache counts, since the top-level counts leave the compaction step out.
|
|
85
124
|
|
|
86
|
-
In streaming,
|
|
125
|
+
In streaming, the cache counters are seeded from `message_start` (including the 1-hour breakdown) and then **overwritten by the cumulative counts on `message_delta`** when present and non-zero, so the terminal `done` carries the final tally and its `cost`.
|
|
87
126
|
|
|
88
127
|
## `max_tokens` is required
|
|
89
128
|
|
|
90
|
-
Unlike OpenAI, Anthropic **requires** `max_tokens` on every request. Resolution: per-call `options.maxTokens`
|
|
129
|
+
Unlike OpenAI, Anthropic **requires** `max_tokens` on every request. Resolution: per-call `options.maxTokens` (or the agent's per-run / configured `modelOptions.maxTokens`) > `config.maxTokens` > a default sized for agent work:
|
|
130
|
+
|
|
131
|
+
| Request | Default `max_tokens` |
|
|
132
|
+
| ---------------------------- | -------------------------------------------------------------------------------------------------------------------- |
|
|
133
|
+
| Streaming (`stream()`) | the model's documented max output: 128K (Claude 5 family, Opus 4.6–4.8, Sonnet 4.6), 64K (Opus / Sonnet / Haiku 4.5) |
|
|
134
|
+
| Non-streaming (`complete()`) | `16384`, capped by the model's max output |
|
|
135
|
+
| Unknown id | `16384`; set `maxOutputTokens` on the model for gateway / proxy ids |
|
|
91
136
|
|
|
92
|
-
|
|
137
|
+
The non-streaming default stays at 16384 because `@anthropic-ai/sdk` refuses a non-streaming request whose `max_tokens` implies more than ten minutes (above ~21K tokens) unless the client sets a `timeout`. Limits come from Anthropic's model pages (checked 2026-10-17).
|
|
138
|
+
|
|
139
|
+
```ts
|
|
140
|
+
anthropic.model({ name: "claude-haiku-4-5" }); // stream 64000, complete 16384
|
|
141
|
+
anthropic.model({ name: "my-gateway/opus", maxOutputTokens: 128_000 });
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
With extended thinking enabled and no explicit cap, the default keeps room for the thinking budget plus 4096 answer tokens (never above the model's max output). In budget mode an explicit `maxTokens` must be greater than `budget_tokens` or the call throws before it reaches Anthropic.
|
|
145
|
+
|
|
146
|
+
A response that still hits the cap (`finishReason: "length"`) ends an agent run as incomplete (`AgentIncompleteError`) unless the agent sets `continueOnOutputLimit`.
|
|
93
147
|
|
|
94
148
|
**Tiny caps + adaptive thinking:** thinking tokens count inside `max_tokens`, so a very small cap can be spent entirely on thinking. Live check: Sonnet 5.5 with `maxTokens: 60` returned `finishReason: "length"` and empty content. For tiny outputs give thinking room (raise `maxTokens`) or turn reasoning off (`reasoning: false` on the model, or no `options.reasoning`).
|
|
95
149
|
|
|
@@ -101,7 +155,7 @@ Anthropic has no `"system"` role inside `messages`. The adapter hoists every neu
|
|
|
101
155
|
|
|
102
156
|
- Outgoing: vendor-neutral tools → Anthropic `tools` with `input_schema` (non-object schemas degrade to a parameterless object so registration never fails).
|
|
103
157
|
- Assistant tool calls in history → `assistant` message with an optional leading `text` block + one `tool_use` block per call.
|
|
104
|
-
- Tool results (`role: "tool"`) →
|
|
158
|
+
- Tool results (`role: "tool"`) → `tool_result` blocks keyed by `tool_use_id`. Consecutive tool messages (the results of one parallel tool-use turn) are grouped into **one** `user` turn, as Anthropic expects.
|
|
105
159
|
- Response `tool_use` blocks → neutral `toolCalls`; `stop_reason: "tool_use"` → `finishReason: "tool_calls"`.
|
|
106
160
|
|
|
107
161
|
## Structured output
|
|
@@ -121,7 +175,7 @@ Adaptive models reject `budget_tokens` with a 400, so the shape matters.
|
|
|
121
175
|
|
|
122
176
|
- **Adaptive:** `reasoning.effort` (`"low" | "medium" | "high"`) → `output_config.effort` of the same name. With only `reasoning.maxTokens` set, effort is `"medium"`; `maxTokens` then only sizes the reserved `max_tokens` room, it is not sent as a budget.
|
|
123
177
|
- **Budget:** `reasoning.maxTokens` → `budget_tokens` verbatim; `reasoning.effort` → a tiered budget (`1024` / `4096` / `12000`) when no `maxTokens` is given. Any resolved budget is floored at Anthropic's `1024` minimum.
|
|
124
|
-
- `reasoning` with neither `effort` nor `maxTokens
|
|
178
|
+
- `reasoning` with neither `effort` nor `maxTokens` emits nothing. `effort: "none"` emits nothing either, except on the Claude 5 models listed below (Sonnet 5.5, Sonnet 5, Haiku 5.5, Opus 5), which each get their own form.
|
|
125
179
|
|
|
126
180
|
### `thinkingMode` override
|
|
127
181
|
|
|
@@ -145,14 +199,111 @@ anthropic.model({ name: "claude-sonnet-4-6", thinkingMode: "adaptive" }); // opt
|
|
|
145
199
|
`temperature` is **not sent** to models after Opus 4.6 (adaptive mode) — they reject any non-default value with a 400. It is also dropped on any request that enables thinking, since Anthropic 400s on thinking plus an explicit temperature. So it is forwarded only in budget mode on requests without thinking; `thinkingMode` decides this too. Set `reasoning: false` on the model config to suppress the thinking param entirely for proxied/legacy targets.
|
|
146
200
|
|
|
147
201
|
```ts
|
|
148
|
-
await agent.execute("Prove it.", { reasoning: { effort: "high" } });
|
|
202
|
+
await agent.execute("Prove it.", { modelOptions: { reasoning: { effort: "high" } } });
|
|
149
203
|
// adaptive model: thinking { type: "adaptive" }, output_config.effort "high"
|
|
150
204
|
// budget model: thinking { type: "enabled", budget_tokens: 12000 }
|
|
151
205
|
await model.complete(messages, { reasoning: { maxTokens: 8000 } });
|
|
152
206
|
// adaptive model: effort "medium"; budget model: budget_tokens 8000
|
|
153
207
|
```
|
|
154
208
|
|
|
155
|
-
|
|
209
|
+
**Claude 5 family:** adaptive thinking runs by default and `budget_tokens` is a 400, so `reasoning.maxTokens` only sizes `max_tokens`. `effort: "none"` is mapped per model:
|
|
210
|
+
|
|
211
|
+
| Model | `effort: "none"` sends | Result |
|
|
212
|
+
| ----------------------- | -------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
|
|
213
|
+
| Sonnet 5.5 | `thinking: { type: "between_tools" }`, alone (no `output_config.effort`, no `display`) | Thinking off. `between_tools` takes no other field and needs effort `high` or below; the model default, `high`, applies. |
|
|
214
|
+
| Sonnet 5, Haiku 5.5 | `thinking: { type: "disabled" }`, alone (no `output_config.effort`, no `display`) | Thinking off. Haiku 5.5 accepts `disabled` only at effort `high` or below; its default, `medium`, applies. |
|
|
215
|
+
| Opus 5 | `thinking: { type: "adaptive" }` + `output_config.effort: "low"` | Thinking stays on at the lowest effort: with `disabled`, Opus 5 can emit a tool call as plain text (never run) and leak thinking tags. |
|
|
216
|
+
| Opus 5.5, Fable 5 / 5.1 | no `thinking` field | No thinking-off form exists, so the model still thinks at its default effort (Opus 5.5: `medium`). Pass `effort: "low"` to think less. |
|
|
217
|
+
|
|
218
|
+
`thinkingDisplay` is applied only to adaptive thinking, never beside `between_tools` or `disabled`.
|
|
219
|
+
|
|
220
|
+
```ts
|
|
221
|
+
import { AnthropicSDK } from "@warlock.js/ai-anthropic";
|
|
222
|
+
|
|
223
|
+
const anthropic = new AnthropicSDK({ apiKey: process.env.ANTHROPIC_API_KEY! });
|
|
224
|
+
const messages = [{ role: "user" as const, content: "Classify: great product!" }];
|
|
225
|
+
|
|
226
|
+
// Sonnet 5 / Haiku 5.5 → thinking: { type: "disabled" }
|
|
227
|
+
await anthropic.model({ name: "claude-haiku-5-5" }).complete(messages, {
|
|
228
|
+
reasoning: { effort: "none" },
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
// Opus 5 → thinking: { type: "adaptive" }, output_config: { effort: "low" }
|
|
232
|
+
await anthropic.model({ name: "claude-opus-5" }).complete(messages, {
|
|
233
|
+
reasoning: { effort: "none" },
|
|
234
|
+
});
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
`thinking.display` is set with `providerOptions.anthropic.thinkingDisplay` (`"summarized"` for readable summaries; the 5-family default is `"omitted"`, empty thinking text). It is applied whenever the adapter sends `thinking` to an adaptive model, so pair it with a `reasoning` option.
|
|
238
|
+
|
|
239
|
+
When a thinking-enabled response also makes tool calls, its signed `thinking` and `redacted_thinking` blocks are retained in each call's `providerMetadata.anthropic.thinkingBlocks` and replayed on the next assistant turn. The full turn is also returned as `ModelResponse.blocks` — see [Provider blocks](#provider-blocks-thinking-compaction-server-tools).
|
|
240
|
+
|
|
241
|
+
## Provider blocks (thinking, compaction, server tools)
|
|
242
|
+
|
|
243
|
+
When a response contains a block the neutral `content` / `toolCalls` cannot carry (thinking, redacted thinking, `compaction`, server-tool use/results, cited text), the adapter returns the whole ordered turn as `ModelResponse.blocks` (and on the streaming `done` chunk): `{ provider: "anthropic", type, data }` per block. Plain text / tool-use turns have no `blocks`.
|
|
244
|
+
|
|
245
|
+
The agent copies them onto the assistant `Message.blocks` (tool-call trips, `pause_turn` trips, repair turns) and onto `LLMTrip.blocks`; `AgentResult.blocks` is set only for a single-trip run. On the next request the adapter replays an assistant message **verbatim** from its `blocks` — required for preserved thinking and server-side compaction. It falls back to rebuilding from `content` + `toolCalls` when the blocks come from another provider, a block's `data.type` differs from its `type` or is not an assistant-turn type, or their `tool_use` ids no longer match `toolCalls`.
|
|
246
|
+
|
|
247
|
+
A replayed thinking block requires every earlier turn unchanged, including the run's tool-call turns and tool results. Never store just `{ content: result.text, blocks }` after a multi-trip run. Keep the run's turns:
|
|
248
|
+
|
|
249
|
+
```ts
|
|
250
|
+
// agent created with `captureMessages: true`
|
|
251
|
+
const result = await agent.execute(input, { history });
|
|
252
|
+
const finalTrip = result.report.trips.at(-1);
|
|
253
|
+
|
|
254
|
+
history = [
|
|
255
|
+
...(result.report.messages ?? []).filter((message) => message.role !== "system"),
|
|
256
|
+
{ role: "assistant", content: finalTrip?.output ?? "", blocks: finalTrip?.blocks },
|
|
257
|
+
];
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
Or let `ai.session({ id, store, agent })` store the turns for you (the `keep-agent-conversations` topic of the `warlock-js-ai` skill).
|
|
261
|
+
|
|
262
|
+
## Provider options (`providerOptions.anthropic`)
|
|
263
|
+
|
|
264
|
+
Anthropic-only request options, per call or in the agent's `modelOptions`. Other adapters ignore the key. Type: `AnthropicCallOptions`.
|
|
265
|
+
|
|
266
|
+
| Field | Effect |
|
|
267
|
+
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
268
|
+
| `betas` | Beta flags. When non-empty the request goes through `client.beta.messages` (needed for beta body fields and beta blocks such as `compaction`). |
|
|
269
|
+
| `body` | Extra body fields merged **last** (caller wins): `context_management`, `fallbacks`, `inference_geo`, `tool_choice`, … Not validated, except that `model`, `messages`, `system`, `tools`, `mcp_servers` and `stream` are refused (`InvalidRequestError`). |
|
|
270
|
+
| `thinkingDisplay` | `thinking.display` on adaptive models: `"summarized"`, `"omitted"`, `"updates"` (the last needs its beta). |
|
|
271
|
+
| `contextManagement` | Typed context editing: `clearToolUses` (`trigger: { inputTokens } \| { toolUses }`, `keep`, `clearAtLeast`, `excludeTools`, `clearToolInputs`) → `clear_tool_uses_20250919`; `clearThinking` (`keep: n \| "all"`) → `clear_thinking_20251015`, listed first. Adds beta `context-management-2025-06-27`. |
|
|
272
|
+
| `serverCompaction` | `true` or `{ triggerTokens (≥ 50,000; API default 150,000), instructions }` → `compact_20260112`, beta `compact-2026-01-12`. Can't be combined with `body.context_management` (`InvalidRequestError`). |
|
|
273
|
+
| `thinkingBlockBinding` | `"error"` \| `"drop_block"` → `thinking.block_binding.prefix_mismatch_behavior` + beta `thinking-binding-controls-2026-08-01`; adaptive or budget thinking only (skipped with a debug log on `between_tools`). |
|
|
274
|
+
|
|
275
|
+
```ts
|
|
276
|
+
const agent = ai.agent({
|
|
277
|
+
model: anthropic.model({ name: "claude-opus-5-5" }),
|
|
278
|
+
tools,
|
|
279
|
+
modelOptions: {
|
|
280
|
+
providerOptions: {
|
|
281
|
+
anthropic: {
|
|
282
|
+
contextManagement: { clearToolUses: { trigger: { inputTokens: 100_000 }, keep: 5 } },
|
|
283
|
+
serverCompaction: { triggerTokens: 200_000 },
|
|
284
|
+
},
|
|
285
|
+
},
|
|
286
|
+
},
|
|
287
|
+
});
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
The response then starts with a `compaction` block, kept on `blocks` and replayed (the API ignores everything before it). Compaction tokens are billed outside the top-level `input_tokens` / `output_tokens`; the adapter adds the `compaction` entries of `usage.iterations` into `usage`. Leave `pause_after_compaction` off inside an agent: a paused response reads as a final stop.
|
|
291
|
+
|
|
292
|
+
### Preserved thinking after client-side compaction
|
|
293
|
+
|
|
294
|
+
Claude Fable 5.1, Opus 5.5, Sonnet 5.5 and Haiku 5.5 accept a replayed thinking block only while everything before it is unchanged. The agent's own compaction marks turns it kept after a summary `compaction: "retained"`; on those models (inferred, or `anthropic.model({ name, preservedThinking: true })`) the adapter replays them **without** `thinking` / `redacted_thinking` blocks. Other models (Opus 5, Sonnet 5, Fable 5, Mythos 5.1, 4.x, budget mode) keep them. Setting `thinkingBlockBinding` disables the stripping and lets the API drop (`"drop_block"`) or reject (`"error"`) instead — also the way to recover a stored conversation someone edited:
|
|
295
|
+
|
|
296
|
+
```ts
|
|
297
|
+
const recovering = ai.agent({
|
|
298
|
+
model: anthropic.model({ name: "claude-opus-5-5" }),
|
|
299
|
+
modelOptions: { providerOptions: { anthropic: { thinkingBlockBinding: "drop_block" } } },
|
|
300
|
+
});
|
|
301
|
+
await recovering.execute(question, { history });
|
|
302
|
+
|
|
303
|
+
inferPreservedThinking("claude-opus-5-5"); // true (exported helper)
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
Cache TTL per call: `options.cacheControl.ttl` (`"5m"` | `"1h"`) overrides the model's `promptCacheTtl` for that call.
|
|
156
307
|
|
|
157
308
|
## Prompt caching (`cache_control`)
|
|
158
309
|
|
|
@@ -190,11 +341,38 @@ await agent.execute("…", { cacheControl: { breakpoints: 1 } }); // cache the s
|
|
|
190
341
|
|
|
191
342
|
- `content_block_delta` text → `{ type: "delta", content }`
|
|
192
343
|
- `tool_use` blocks accumulate `input_json_delta` fragments and emit one consolidated `{ type: "tool-call", ... }` at `content_block_stop` (no partial-arg `{}` artifact — input is parsed once, whole)
|
|
193
|
-
-
|
|
344
|
+
- every content block is also assembled by index (text, thinking + signature, server-tool input, beta `compaction_delta`) and returned as `done.blocks` when the turn has a non-neutral block
|
|
345
|
+
- terminal `{ type: "done", finishReason, usage, blocks? }` — `usage.input` from `message_start`, `usage.output` from `message_delta`, `total` computed; `cachedTokens` / `cacheWriteTokens` from `message_start` then the cumulative `message_delta` counts (see [Tokens & usage accounting](#tokens--usage-accounting))
|
|
346
|
+
- opt-in (`options.streamChunks`, set by `agent.stream()`): `{ type: "reasoning", delta }` per non-empty `thinking_delta`, `{ type: "tool-args", callId, name, delta }` per `input_json_delta` of a client `tool_use` block (never for `server_tool_use`), `{ type: "usage", usage }` after `message_start` and each `message_delta` (running totals). Claude 5 models stream thinking text only with `providerOptions.anthropic.thinkingDisplay: "summarized"`.
|
|
347
|
+
|
|
348
|
+
```ts
|
|
349
|
+
for await (const chunk of model.stream(messages, { streamChunks: true, reasoning: { effort: "high" } })) {
|
|
350
|
+
if (chunk.type === "reasoning") process.stderr.write(chunk.delta);
|
|
351
|
+
}
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
## Provider-defined tools
|
|
355
|
+
|
|
356
|
+
`ai.providerTool({ provider: "anthropic", definition })` entries are sent verbatim, before the function tools (the prompt-cache breakpoint stays on the last function tool). Server tools (`web_search_20250305`, `web_fetch_20250910`, `code_execution_20250825`) run inside the response and their `server_tool_use` / `*_tool_result` blocks round-trip via `blocks`. Client tools (`bash_20250124`, `text_editor_20250728` named `str_replace_based_edit_tool`, `memory_20250818`) come back as `tool_use` and dispatch to the provider tool's `execute`. Other providers' tools are skipped with a `providerTool.skipped` warning. `providerOptions.anthropic.body` still cannot set `tools`.
|
|
357
|
+
|
|
358
|
+
```ts
|
|
359
|
+
const webSearch = ai.providerTool({
|
|
360
|
+
provider: "anthropic",
|
|
361
|
+
definition: { type: "web_search_20250305", name: "web_search", max_uses: 5 },
|
|
362
|
+
});
|
|
363
|
+
const editor = ai.providerTool({
|
|
364
|
+
provider: "anthropic",
|
|
365
|
+
definition: { type: "text_editor_20250728", name: "str_replace_based_edit_tool" },
|
|
366
|
+
execute: async (input: { command: string; path: string }) => files.edit(input),
|
|
367
|
+
});
|
|
368
|
+
ai.agent({ model: anthropic.model({ name: "claude-sonnet-4-6" }), tools: [webSearch, editor] });
|
|
369
|
+
```
|
|
194
370
|
|
|
195
371
|
## Finish-reason mapping
|
|
196
372
|
|
|
197
|
-
`end_turn` / `stop_sequence` → `stop` · `max_tokens` → `length` · `
|
|
373
|
+
`end_turn` / `stop_sequence` / beta `compaction` → `stop` · `max_tokens` → `length` · `model_context_window_exceeded` → `context_exceeded` · `pause_turn` → `pause_turn` · `refusal` → `refusal` · `tool_use` → `tool_calls` · unknown / null → `error`.
|
|
374
|
+
|
|
375
|
+
The agent resumes `pause_turn` automatically (it replays the paused turn and calls again, within `maxTrips`). `refusal` and `context_exceeded` end the run like `stop`; check `report.trips.at(-1).finishReason` to fall back to another model or compact the history.
|
|
198
376
|
|
|
199
377
|
## Errors
|
|
200
378
|
|
|
@@ -204,15 +382,83 @@ Raw SDK errors are wrapped into the typed `@warlock.js/ai` `AIError` hierarchy.
|
|
|
204
382
|
- `rate_limit_error` / 429 → `ProviderRateLimitError` (+`retryAfter` from `retry-after`)
|
|
205
383
|
- `billing_error` → `QuotaExceededError`
|
|
206
384
|
- `invalid_request_error` with "prompt is too long" → `ContextLengthExceededError`, else `InvalidRequestError`
|
|
207
|
-
-
|
|
385
|
+
- `overloaded_error` / 529 → `ProviderOverloadedError` (`code: "PROVIDER_OVERLOADED"`, `retryable: true`, `retryAfter` from `retry-after`). Also raised for an `overloaded_error` delivered mid-stream as an SSE `error` event, which has no `status`.
|
|
386
|
+
- other 5xx → `ProviderError` (`retryable: true`)
|
|
208
387
|
- Connection timeouts → `ProviderTimeoutError`
|
|
209
388
|
|
|
389
|
+
Every wrapped error carries `status` (the HTTP status, when there was one), `retryable`, and `billed`: `false` for 401 / 402 / 403 (the request never reached a billable account), `"unknown"` otherwise — Anthropic publishes no rule for failed requests, so treat them as possibly billed when you settle a budget. `fallbackModel` fails over on `PROVIDER_OVERLOADED` by default.
|
|
390
|
+
|
|
391
|
+
```ts
|
|
392
|
+
import { ai, ProviderOverloadedError } from "@warlock.js/ai";
|
|
393
|
+
import { AnthropicSDK } from "@warlock.js/ai-anthropic";
|
|
394
|
+
|
|
395
|
+
const anthropic = new AnthropicSDK({ apiKey: process.env.ANTHROPIC_API_KEY ?? "" });
|
|
396
|
+
const agent = ai.agent({ model: anthropic.model({ name: "claude-sonnet-4-6" }) });
|
|
397
|
+
|
|
398
|
+
const result = await agent.execute("hi");
|
|
399
|
+
|
|
400
|
+
if (result.error instanceof ProviderOverloadedError) {
|
|
401
|
+
console.log(
|
|
402
|
+
result.error.status,
|
|
403
|
+
result.error.retryable,
|
|
404
|
+
result.error.billed,
|
|
405
|
+
result.error.retryAfter,
|
|
406
|
+
);
|
|
407
|
+
}
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
## Build and send an audited request
|
|
411
|
+
|
|
412
|
+
`model.buildRequest(messages, options?)` is synchronous and makes no network call.
|
|
413
|
+
It returns a detached `{ endpoint, body, betas }` snapshot, including thinking,
|
|
414
|
+
cache markers, provider body options and merged tool results. `body.stream` is
|
|
415
|
+
`false` by default; pass `{ ...options, stream: true }` to build a streaming request.
|
|
416
|
+
`betas` identifies the beta header flags; the SDK receives these separately from
|
|
417
|
+
its serialized Messages body.
|
|
418
|
+
|
|
419
|
+
```ts
|
|
420
|
+
const request = model.buildRequest(messages, options);
|
|
421
|
+
const bodyJSON = JSON.stringify(request.body);
|
|
422
|
+
// Hash or reserve spend against bodyJSON before sending.
|
|
423
|
+
const response = await model.send(request, { signal });
|
|
424
|
+
|
|
425
|
+
const streamingRequest = model.buildRequest(messages, { ...options, stream: true });
|
|
426
|
+
for await (const chunk of model.send(streamingRequest, { signal })) {
|
|
427
|
+
// Consume the same neutral chunks as model.stream().
|
|
428
|
+
}
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
`send()` uses the built endpoint, body and beta flags without rebuilding the
|
|
432
|
+
conversation or applying new defaults. It passes `betas` only when `endpoint` is
|
|
433
|
+
`"beta.messages"`: a request whose `endpoint` is `"messages"` is sent without
|
|
434
|
+
them, even if `betas` was edited by hand. Transport cancellation stays separate
|
|
435
|
+
from the audited body. `complete()`, `stream()` and `countTokens()` use this same
|
|
436
|
+
build path and always select their respective request modes. `buildRequest()`
|
|
437
|
+
throws build failures raw (an `InvalidRequestError` for a reserved `body` key, a
|
|
438
|
+
`DataCloneError` for a `body` value `structuredClone` cannot copy, such as a
|
|
439
|
+
function); `complete()`, `stream()` and `countTokens()` log them like send
|
|
440
|
+
failures and reject with an `AIError`, wrapping anything else in an
|
|
441
|
+
`InvalidRequestError`.
|
|
442
|
+
Treat the snapshot as read-only after hashing it; SDK JSON serialization and beta
|
|
443
|
+
header handling still apply.
|
|
444
|
+
|
|
445
|
+
Hosts with their own transport can import `toAnthropicMessages`,
|
|
446
|
+
`toAnthropicTools`, `toProviderBlocks`, `fromProviderBlocks`,
|
|
447
|
+
`ANTHROPIC_BLOCK_FORMAT` and the `AnthropicMessages` type from the package root.
|
|
448
|
+
`fromProviderBlocks(blocks, toolCalls)` retains the adapter's assistant-block
|
|
449
|
+
allowlist and tool-id validation.
|
|
450
|
+
|
|
210
451
|
## Token counting
|
|
211
452
|
|
|
212
453
|
```ts
|
|
213
454
|
await anthropic.count("some text"); // approximate heuristic, offline
|
|
455
|
+
|
|
456
|
+
const model = anthropic.model({ name: "claude-opus-5-5" }); // an AnthropicModel
|
|
457
|
+
await model.countTokens(messages, { tools }); // exact, via messages.countTokens (network)
|
|
214
458
|
```
|
|
215
459
|
|
|
460
|
+
`countTokens` sends the same system prompt, tools, thinking and `providerOptions.anthropic.betas` a real call would, keeping only the fields the endpoint accepts.
|
|
461
|
+
|
|
216
462
|
## No embeddings
|
|
217
463
|
|
|
218
464
|
Anthropic ships no first-party embeddings API, so `AnthropicSDK` intentionally does **not** implement `embedder()` (the `SDKAdapterContract.embedder` slot is optional). Use `@warlock.js/ai-openai` (or another embeddings-capable adapter; see the `setup-openai` topic of the `warlock-js-ai-openai` skill) for vectors.
|
package/llms.txt
CHANGED
|
@@ -6,4 +6,4 @@
|
|
|
6
6
|
|
|
7
7
|
## Skills
|
|
8
8
|
|
|
9
|
-
- [setup-anthropic](@warlock.js/ai-anthropic/setup-anthropic/SKILL.md): Wire @warlock.js/ai-anthropic — new AnthropicSDK({apiKey, baseURL?, provider?}) for Claude, .model({name, vision?, structuredOutput?, reasoning?, thinkingMode?, promptCaching?, maxTokens?}). System-prompt hoisting, max_tokens required (default
|
|
9
|
+
- [setup-anthropic](@warlock.js/ai-anthropic/setup-anthropic/SKILL.md): Wire @warlock.js/ai-anthropic — new AnthropicSDK({apiKey, baseURL?, provider?}) for Claude, .model({name, vision?, structuredOutput?, reasoning?, thinkingMode?, promptCaching?, maxTokens?, maxOutputTokens?}). System-prompt hoisting, max_tokens required (default: model max output when streaming, 16384 non-streaming; maxOutputTokens for gateway ids), extended thinking via options.reasoning → adaptive thinking + output_config.effort (current/unknown models) or budget_tokens (Haiku 4.5, 4.6 and older; override with thinkingMode), prompt caching via promptCaching + options.cacheControl (per-call ttl), provider blocks (thinking/compaction) replayed verbatim via ModelResponse.blocks / Message.blocks, providerOptions.anthropic (betas, body fields such as context_management / fallbacks, thinkingDisplay), model.countTokens(), distinct finish reasons (pause_turn, refusal, context_exceeded), built-in Claude list prices (ANTHROPIC_MODEL_PRICING, anthropicPricingFor, withAnthropicCacheWriteRates), cost-truth usage (inputIncludesCache: false, cachedTokens/cacheWriteTokens/cacheWrite1hTokens, usage.cost on complete()), ProviderOverloadedError for 529, no first-party embeddings. Triggers: `AnthropicSDK`, `anthropic.model`, `anthropic.count`, `maxTokens`, `maxOutputTokens`, `max_tokens`, `reasoning`, `thinking`, `budget_tokens`, `thinkingMode`, `adaptive`, `cacheControl`, `providerOptions`, `blocks`, `countTokens`, `pause_turn`, `refusal`, `context_management`, `contextManagement`, `serverCompaction`, `clear_tool_uses`, `clear_thinking`, `thinkingBlockBinding`, `block_binding`, `preservedThinking`, `ai.providerTool`, `web_search_20250305`, `bash_20250124`, `text_editor_20250728`, `streamChunks`, `thinking_delta`, `compaction`, `promptCaching`, `cachedTokens`, `cacheWriteTokens`, `cacheWrite1hTokens`, `inputIncludesCache`, `ANTHROPIC_MODEL_PRICING`, `ProviderOverloadedError`, `claude-sonnet-4-6`, `claude-haiku-4-5`, `claude-opus-4-7`; "wire claude into warlock agent", "configure anthropic provider", "use claude sonnet", "anthropic gateway baseURL", "claude extended thinking", "anthropic prompt caching cost"; typical import `import { AnthropicSDK } from "@warlock.js/ai-anthropic"`. Skip: embeddings — the `setup-openai` topic of the `warlock-js-ai-openai` skill; sibling adapters `@warlock.js/ai-openai`, `@warlock.js/ai-bedrock`, `@warlock.js/ai-google`, `@warlock.js/ai-ollama`; raw `@anthropic-ai/sdk`; Vercel `@ai-sdk/anthropic`.
|
package/package.json
CHANGED
|
@@ -11,16 +11,17 @@
|
|
|
11
11
|
"license": "MIT",
|
|
12
12
|
"repository": {
|
|
13
13
|
"type": "git",
|
|
14
|
-
"url": "https://github.com/warlockjs/
|
|
14
|
+
"url": "git+https://github.com/warlockjs/framework.git",
|
|
15
|
+
"directory": "packages/ai-anthropic"
|
|
15
16
|
},
|
|
16
17
|
"peerDependencies": {
|
|
17
|
-
"@warlock.js/ai": "5.
|
|
18
|
+
"@warlock.js/ai": "5.31.0"
|
|
18
19
|
},
|
|
19
20
|
"dependencies": {
|
|
20
21
|
"@anthropic-ai/sdk": "^0.129.0",
|
|
21
|
-
"@warlock.js/logger": "5.
|
|
22
|
+
"@warlock.js/logger": "5.31.0"
|
|
22
23
|
},
|
|
23
|
-
"version": "5.
|
|
24
|
+
"version": "5.31.0",
|
|
24
25
|
"main": "./cjs/index.cjs",
|
|
25
26
|
"module": "./esm/index.mjs",
|
|
26
27
|
"types": "./esm/index.d.mts",
|
package/skills/README.md
CHANGED
|
@@ -6,4 +6,4 @@ Per-task skills. Cross-references name the topic ("the `<topic>` topic"), and fo
|
|
|
6
6
|
|
|
7
7
|
### `setup-anthropic`
|
|
8
8
|
|
|
9
|
-
Wire @warlock.js/ai-anthropic — new AnthropicSDK({apiKey, baseURL?, provider?}) for Claude, .model({name, vision?, structuredOutput?, reasoning?, thinkingMode?, promptCaching?, maxTokens?}). System-prompt hoisting, max_tokens required (default
|
|
9
|
+
Wire @warlock.js/ai-anthropic — new AnthropicSDK({apiKey, baseURL?, provider?}) for Claude, .model({name, vision?, structuredOutput?, reasoning?, thinkingMode?, promptCaching?, maxTokens?, maxOutputTokens?}). System-prompt hoisting, max_tokens required (default: model max output when streaming, 16384 non-streaming), extended thinking via options.reasoning → adaptive thinking + output_config.effort (current/unknown models) or budget_tokens (Haiku 4.5, 4.6 and older; override with thinkingMode), prompt caching via promptCaching + options.cacheControl with cost-truth usage (cachedTokens/cacheWriteTokens), no first-party embeddings. Load when wiring a Claude-backed model into a @warlock.js agent.
|