@happyvertical/ai 0.102.8 → 0.103.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/AGENT.md +3 -2
- package/README.md +123 -4
- package/dist/chunks/{anthropic-CxOrttgj.js → anthropic-CdbK9Jl-.js} +3 -3
- package/dist/chunks/{anthropic-CxOrttgj.js.map → anthropic-CdbK9Jl-.js.map} +1 -1
- package/dist/chunks/{bedrock-B0cNEXFa.js → bedrock-DNkxz3ow.js} +3 -3
- package/dist/chunks/{bedrock-B0cNEXFa.js.map → bedrock-DNkxz3ow.js.map} +1 -1
- package/dist/chunks/{bifrost-BXiXdyb8.js → bifrost-DmbaXObX.js} +4 -4
- package/dist/chunks/{bifrost-BXiXdyb8.js.map → bifrost-DmbaXObX.js.map} +1 -1
- package/dist/chunks/{byteplus-modelark-DZ0YL2vl.js → byteplus-modelark-BAi0y9SK.js} +3 -3
- package/dist/chunks/{byteplus-modelark-DZ0YL2vl.js.map → byteplus-modelark-BAi0y9SK.js.map} +1 -1
- package/dist/chunks/{claude-cli-CtBp-Uk-.js → claude-cli-C40pIzrp.js} +3 -3
- package/dist/chunks/{claude-cli-CtBp-Uk-.js.map → claude-cli-C40pIzrp.js.map} +1 -1
- package/dist/chunks/{continuation-7o7400bp.js → continuation-L5KnnE9R.js} +2 -2
- package/dist/chunks/{continuation-7o7400bp.js.map → continuation-L5KnnE9R.js.map} +1 -1
- package/dist/chunks/{gateway-audio-models-BSZGgjd8.js → gateway-audio-models-B1tGNv1H.js} +2 -2
- package/dist/chunks/{gateway-audio-models-BSZGgjd8.js.map → gateway-audio-models-B1tGNv1H.js.map} +1 -1
- package/dist/chunks/{gemini-DUk4ssth.js → gemini-C-r6c4N9.js} +3 -3
- package/dist/chunks/{gemini-DUk4ssth.js.map → gemini-C-r6c4N9.js.map} +1 -1
- package/dist/chunks/{huggingface-C41BZOoI.js → huggingface-DtuYF1vb.js} +3 -3
- package/dist/chunks/{huggingface-C41BZOoI.js.map → huggingface-DtuYF1vb.js.map} +1 -1
- package/dist/chunks/laya-D-P82D0h.js +471 -0
- package/dist/chunks/laya-D-P82D0h.js.map +1 -0
- package/dist/chunks/{litellm-rMCXClTb.js → litellm-BaGgWzHR.js} +4 -4
- package/dist/chunks/{litellm-rMCXClTb.js.map → litellm-BaGgWzHR.js.map} +1 -1
- package/dist/chunks/{ollama--y88p8Bz.js → ollama-C3T3mn68.js} +4 -4
- package/dist/chunks/{ollama--y88p8Bz.js.map → ollama-C3T3mn68.js.map} +1 -1
- package/dist/chunks/{openai-compat-video-erarPEz-.js → openai-compat-video-CwFsKAxR.js} +3 -3
- package/dist/chunks/{openai-compat-video-erarPEz-.js.map → openai-compat-video-CwFsKAxR.js.map} +1 -1
- package/dist/chunks/{qwen-tts-C9w7teY6.js → qwen-tts-DqMxfA54.js} +2 -2
- package/dist/chunks/{qwen-tts-C9w7teY6.js.map → qwen-tts-DqMxfA54.js.map} +1 -1
- package/dist/chunks/{rate-limit-Bln_w0rH.js → rate-limit-BkK4-hXY.js} +2 -2
- package/dist/chunks/{rate-limit-Bln_w0rH.js.map → rate-limit-BkK4-hXY.js.map} +1 -1
- package/dist/chunks/{seevio-CosohVa0.js → seevio-EzC6eKz-.js} +3 -3
- package/dist/chunks/{seevio-CosohVa0.js.map → seevio-EzC6eKz-.js.map} +1 -1
- package/dist/chunks/{src-nB7u5Xl0.js → src-Cc5yFnnQ.js} +25 -18
- package/dist/chunks/{src-nB7u5Xl0.js.map → src-Cc5yFnnQ.js.map} +1 -1
- package/dist/chunks/{typesafe-BNM-QAJ2.js → typesafe-D7ZmI9-n.js} +3 -3
- package/dist/chunks/{typesafe-BNM-QAJ2.js.map → typesafe-D7ZmI9-n.js.map} +1 -1
- package/dist/chunks/{usage-BaQKo8bc.js → usage-B9gPCWSa.js} +2 -1
- package/dist/chunks/usage-B9gPCWSa.js.map +1 -0
- package/dist/chunks/{webllm-CWgY5nnP.js → webllm-DT31sqUY.js} +2 -2
- package/dist/chunks/{webllm-CWgY5nnP.js.map → webllm-DT31sqUY.js.map} +1 -1
- package/dist/index.js +2 -2
- package/dist/local.js +2 -2
- package/dist/node/factory.d.ts.map +1 -1
- package/dist/node.js +16 -3
- package/dist/node.js.map +1 -1
- package/dist/shared/factory.d.ts.map +1 -1
- package/dist/shared/providers/laya.d.ts +46 -0
- package/dist/shared/providers/laya.d.ts.map +1 -0
- package/dist/shared/types.d.ts +37 -3
- package/dist/shared/types.d.ts.map +1 -1
- package/metadata.json +2 -2
- package/package.json +4 -3
- package/dist/chunks/usage-BaQKo8bc.js.map +0 -1
package/AGENT.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
<!-- BEGIN AGENT:GENERATED -->
|
|
4
4
|
## Purpose
|
|
5
|
-
Standardized AI interface supporting chat, embeddings, media, and TypeSafe/Jev typed decisions
|
|
5
|
+
Standardized AI interface supporting chat, embeddings, media, and TypeSafe/Jev and Laya typed decisions
|
|
6
6
|
|
|
7
7
|
## Package Map
|
|
8
8
|
- Package: `@happyvertical/ai`
|
|
@@ -16,6 +16,7 @@ Standardized AI interface supporting chat, embeddings, media, and TypeSafe/Jev t
|
|
|
16
16
|
```bash
|
|
17
17
|
pnpm --filter @happyvertical/ai build
|
|
18
18
|
pnpm --filter @happyvertical/ai test
|
|
19
|
+
pnpm --filter @happyvertical/ai typecheck
|
|
19
20
|
pnpm --filter @happyvertical/ai clean
|
|
20
21
|
```
|
|
21
22
|
|
|
@@ -25,7 +26,7 @@ pnpm --filter @happyvertical/ai clean
|
|
|
25
26
|
- If failures span multiple packages or Turborepo ordering looks wrong, run `pnpm build` and `pnpm typecheck` from the repo root before retrying package-scoped commands.
|
|
26
27
|
|
|
27
28
|
## Ecosystem Relationships
|
|
28
|
-
- Provides: Standardized AI interface supporting chat, embeddings, media, and TypeSafe/Jev typed decisions
|
|
29
|
+
- Provides: Standardized AI interface supporting chat, embeddings, media, and TypeSafe/Jev and Laya typed decisions
|
|
29
30
|
- Implements: none
|
|
30
31
|
- Requires: @happyvertical/utils, @anthropic-ai/sdk, @aws-sdk/client-bedrock-runtime, @google/genai, @mlc-ai/web-llm, openai
|
|
31
32
|
- Stability: stable (Primary package surface is described as implemented and production-oriented.)
|
package/README.md
CHANGED
|
@@ -137,6 +137,14 @@ const typesafe = await getAI({
|
|
|
137
137
|
defaultModel: 'jev-latest',
|
|
138
138
|
});
|
|
139
139
|
|
|
140
|
+
// Laya (self-hosted typed decisions only; baseUrl is the laya-serve root)
|
|
141
|
+
const laya = await getAI({
|
|
142
|
+
type: 'laya',
|
|
143
|
+
baseUrl: process.env.LAYA_BASE_URL!, // e.g. http://localhost:8000
|
|
144
|
+
apiKey: process.env.LAYA_API_KEY, // only if the server sets LAYA_API_KEY
|
|
145
|
+
defaultModel: 'typed-decisions', // checkpoint; omit to let the server route
|
|
146
|
+
});
|
|
147
|
+
|
|
140
148
|
// WebLLM (in-browser, WebGPU, no server or API key; see "In-Browser Chat")
|
|
141
149
|
const local = await getAI({ type: 'webllm', model: 'Llama-3.2-1B-Instruct-q4f16_1-MLC' });
|
|
142
150
|
```
|
|
@@ -261,9 +269,11 @@ excluded; a browser-safe root entry is tracked separately.
|
|
|
261
269
|
|
|
262
270
|
## Typed Decisions
|
|
263
271
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
272
|
+
The optional decision providers (`typesafe`, for TypeSafe's hosted Jev, and
|
|
273
|
+
`laya`, for a self-hosted Laya server; see [Laya](#laya-self-hosted)) evaluate a
|
|
274
|
+
shared state against a batch of typed predicates, choices, and ordered scores.
|
|
275
|
+
They do not provide chat or text generation. Check both optional contracts before
|
|
276
|
+
routing a request:
|
|
267
277
|
|
|
268
278
|
```typescript
|
|
269
279
|
const ai = await getAI({ type: 'typesafe', apiKey: process.env.TYPESAFE_API_KEY! });
|
|
@@ -284,7 +294,7 @@ if (capabilities.decisions === true && ai.decide) {
|
|
|
284
294
|
`defaultModel` and request `model` select a Jev model. Results preserve the
|
|
285
295
|
actual provider model, token usage, complete distributions, and provenance.
|
|
286
296
|
Probabilities are provider output and are not calibrated for comparison with
|
|
287
|
-
another provider. The optional capability and method preserve compatibility
|
|
297
|
+
another provider (Laya and Jev in particular are not interchangeable). The optional capability and method preserve compatibility
|
|
288
298
|
with existing provider implementations.
|
|
289
299
|
|
|
290
300
|
TypeSafe documents normalized choice and score distributions. For measured
|
|
@@ -293,6 +303,114 @@ accepts a positive distribution within one percentage point of unit mass and
|
|
|
293
303
|
normalizes it by its actual sum. It continues to reject non-finite,
|
|
294
304
|
out-of-range, missing, extra, all-zero, and non-hundredth distributions.
|
|
295
305
|
|
|
306
|
+
### Laya (self-hosted)
|
|
307
|
+
|
|
308
|
+
`type: 'laya'` is a second decision provider, for a [Laya](https://github.com/NandhaKishorM/laya)
|
|
309
|
+
server (`pip install "laya[serve]"`, then `laya-serve`; Apache-2.0 code and
|
|
310
|
+
weights at [convaiinnovations/laya](https://huggingface.co/convaiinnovations/laya)).
|
|
311
|
+
State and questions are sent to the configured server, which you can host inside
|
|
312
|
+
your network; there is no hosted dependency. HTTP redirects are rejected to
|
|
313
|
+
prevent forwarding state or credentials to another endpoint. Configure the final
|
|
314
|
+
server URL directly. It implements the
|
|
315
|
+
same `decide()` contract and, like TypeSafe, is decision-only: `chat()`,
|
|
316
|
+
`complete()`, `embed()`, streaming and every other operation throw an `AIError`
|
|
317
|
+
with code `NOT_IMPLEMENTED`.
|
|
318
|
+
|
|
319
|
+
`laya-serve` answers the Jev `POST /v1/systemone` wire shape, but the TypeSafe
|
|
320
|
+
adapter is not a drop-in client for it: Laya rounds each probability to four
|
|
321
|
+
decimals independently, picks its checkpoint with its own router, takes a
|
|
322
|
+
`max_len` token window, and reports truncation. The Laya adapter handles those
|
|
323
|
+
directly.
|
|
324
|
+
|
|
325
|
+
```typescript
|
|
326
|
+
const ai = await getAI({
|
|
327
|
+
type: 'laya',
|
|
328
|
+
baseUrl: 'http://localhost:8000',
|
|
329
|
+
defaultModel: 'typed-decisions',
|
|
330
|
+
maxLen: 1024,
|
|
331
|
+
timeout: 10_000,
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
const result = await ai.decide!({
|
|
335
|
+
state: { message: 'Please refund my duplicate charge.' },
|
|
336
|
+
questions: {
|
|
337
|
+
route: { type: 'choice', instructions: 'Which team?', criteria: { billing: 'Payments', support: 'General help' } },
|
|
338
|
+
},
|
|
339
|
+
});
|
|
340
|
+
result.model; // the checkpoint that answered, e.g. 'typed-decisions'
|
|
341
|
+
result.provenance.details; // requested model, repo, token and truncation facts, raw values
|
|
342
|
+
|
|
343
|
+
// Per-request checkpoint and token window. maxLen is Laya-only, so type the
|
|
344
|
+
// options as LayaDecisionOptions (a subtype of DecisionOptions).
|
|
345
|
+
const options: LayaDecisionOptions = { model: 'english', maxLen: 512 }; // import type from '@happyvertical/ai'
|
|
346
|
+
await ai.decide!(request, options);
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
| Option | Meaning |
|
|
350
|
+
| --- | --- |
|
|
351
|
+
| `baseUrl` | Required. The server root, e.g. `http://localhost:8000`. A trailing `/v1` or `/v1/systemone` is accepted, so a Jev-style base URL works. A path prefix behind a reverse proxy is kept. Env (Node): `LAYA_BASE_URL`. |
|
|
352
|
+
| `apiKey` | Optional. Sent as `Authorization: Bearer ...`; needed only when the server sets `LAYA_API_KEY`. A 401 becomes an `AuthenticationError`. Env (Node): `LAYA_API_KEY`. |
|
|
353
|
+
| `defaultModel` | A checkpoint: `typed-decisions`, `english`, `multilingual`, an alias, or a name the server registered. Omit it and nothing is sent, so the server routes by language and question IDs. A request `model` overrides it. |
|
|
354
|
+
| `maxLen` | The total token window (`max_len`) sent with each request. Omit it for the checkpoint's own window (512 for `english`, 1024 for `typed-decisions` and `multilingual`). The server rejects values above its `LAYA_MAX_TOKEN_BUDGET` (8192 by default). A request `maxLen` overrides it. |
|
|
355
|
+
| `timeout`, `rateLimit`, `onUsage`, `onRequest`, `headers` | The shared conventions, as for every provider. The adapter does not retry by itself; configure `rateLimit` to retry a busy server. |
|
|
356
|
+
|
|
357
|
+
**How requests map.** One `decide()` call is one `POST {baseUrl}/v1/systemone`
|
|
358
|
+
carrying every question, so Laya answers them in one pass over the shared state.
|
|
359
|
+
`predicate` is sent as Laya's `noul`; `choice` and `score` keep their shape. Only
|
|
360
|
+
`state`, `questions`, `model` and `max_len` are sent: generation controls
|
|
361
|
+
(`maxTokens`, `temperature`, `reasoning`) and unknown properties on a question are
|
|
362
|
+
never forwarded. Laya limits a request to 64 questions, 100 options per choice,
|
|
363
|
+
32 levels per score, 512 options in total and 50,000 characters of state; the
|
|
364
|
+
server answers anything larger with an HTTP 413 and the adapter reports it as a
|
|
365
|
+
non-retryable `API_ERROR` (it never splits a request, because Laya's routing and
|
|
366
|
+
usage depend on the whole question set). `/v1/systemone/batch`, which answers
|
|
367
|
+
one question set over many states, is not used: `decide()` takes one state.
|
|
368
|
+
|
|
369
|
+
**Results and provenance.** `result.model` and `provenance.model` are the
|
|
370
|
+
checkpoint that answered, read from the response's `routing.model`. The
|
|
371
|
+
response's own `model` field is the constant `laya-rl-agent` (Laya's decision
|
|
372
|
+
head), kept as `provenance.details.serverModel`. A server running with
|
|
373
|
+
`LAYA_JEV_STRICT=1` omits `routing`; the adapter then reports `laya-rl-agent` and
|
|
374
|
+
leaves `details.checkpoint` unset rather than guess. `provenance.details` is a
|
|
375
|
+
JSON map with `serverModel`, and where known `requestedModel`, `checkpoint`,
|
|
376
|
+
`checkpointRepo`, `routeReason`, `maxLen`, `stateTokens`, `stateTokensDropped`,
|
|
377
|
+
`truncated` and `truncatedQuestions`. **Check `truncated`**: a state longer than
|
|
378
|
+
the window is cut, Laya still answers, and nothing else in the result says so.
|
|
379
|
+
`usage` is the input token count (`completionTokens` is always 0).
|
|
380
|
+
|
|
381
|
+
**Rounded distributions.** `laya-serve` rounds each probability to four decimals
|
|
382
|
+
on its own, so a choice or score distribution routinely sums to 1.0001 or 0.9999
|
|
383
|
+
(about half the responses in our tests). The adapter accepts a distribution whose
|
|
384
|
+
mass is within `n * 0.00005` of 1 (n values, capped at 0.01), divides it by its
|
|
385
|
+
actual sum, and records the values as received in
|
|
386
|
+
`provenance.details.rawProbabilities` (keyed by question ID, with the IDs in
|
|
387
|
+
`details.renormalized`). Ranking and the chosen option are unchanged. Anything
|
|
388
|
+
else is rejected as `INVALID_RESPONSE`: values that are missing, extra, not
|
|
389
|
+
finite, outside [0, 1], summing to zero, or off by more than the rounding bound;
|
|
390
|
+
a `choice` that is not a requested option; a `score` outside the rubric or whose
|
|
391
|
+
`legend` does not match the requested levels (a non-string level may come back as
|
|
392
|
+
Python-style JSON text and is compared as parsed JSON); answers whose IDs or
|
|
393
|
+
types differ from the request; and a malformed `usage` or `routing`.
|
|
394
|
+
|
|
395
|
+
**Errors.** 401 is `AUTH_ERROR`. 503 (Laya's `LAYA_MAX_CONCURRENT` admission
|
|
396
|
+
limit, with `Retry-After`) and 429 are `RateLimitError`s, which the shared
|
|
397
|
+
`rateLimit` option retries. Other HTTP failures are `API_ERROR` carrying the
|
|
398
|
+
server's detail, retryable only for 5xx. A timeout is `REQUEST_TIMEOUT`, a caller
|
|
399
|
+
abort `REQUEST_ABORTED`, and a connection failure `NETWORK_ERROR`. The first
|
|
400
|
+
request for a checkpoint the server has not preloaded can take a minute while it
|
|
401
|
+
loads (Laya preloads only `LAYA_MODELS`), so size `timeout` for a cold start or
|
|
402
|
+
preload what you use. Run the stock `laya-serve`; no wrapper is needed.
|
|
403
|
+
|
|
404
|
+
**Not interchangeable with Jev.** Laya's probabilities and its `confidence` are
|
|
405
|
+
not Jev's. The `confidence` on a choice or score answer is normalized entropy
|
|
406
|
+
(`1 - H(p)/log k`), not Jev's `(n*p_max - 1)/(n - 1)`, so a threshold tuned for
|
|
407
|
+
one gates differently on the other. Laya's `typed-decisions` checkpoint was found
|
|
408
|
+
under-confident in a small shop evaluation (59 hand-written items, so wide
|
|
409
|
+
error bars): its numbers rank answers usefully but are not literal
|
|
410
|
+
probabilities. Measure a cut-off on your own data and do not swap providers
|
|
411
|
+
behind one threshold. Laya's abstention gate (`min_confidence`) and its `task`
|
|
412
|
+
and `lang` routing hints are not exposed.
|
|
413
|
+
|
|
296
414
|
## Video Generation
|
|
297
415
|
|
|
298
416
|
Video generation is asynchronous: `submitVideoGenerationJob` returns a JSON-serializable
|
|
@@ -682,6 +800,7 @@ for (const site of sites) {
|
|
|
682
800
|
- `MODELARK_API_KEY` / `ARK_API_KEY`, `MODELARK_BASE_URL`
|
|
683
801
|
- `OPENAI_COMPAT_VIDEO_BASE_URL`, `OPENAI_COMPAT_VIDEO_API_KEY`
|
|
684
802
|
- `TYPESAFE_API_KEY`, `TYPESAFE_BASE_URL` (last-resort decision-only auto-detection)
|
|
803
|
+
- `LAYA_BASE_URL`, `LAYA_API_KEY` (decision-only; `LAYA_BASE_URL` alone selects Laya as the last resort, after TypeSafe)
|
|
685
804
|
|
|
686
805
|
## API Overview
|
|
687
806
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { b as extractTextContent, f as AuthenticationError, g as ModelNotFoundError, l as prepareRequestControls, m as ContextLengthError, o as normalizeBaseAIOptions, s as normalizeChatOptions, t as emitUsage, u as AIError } from "./usage-
|
|
2
|
-
import { n as rateLimitErrorFrom } from "./rate-limit-
|
|
1
|
+
import { b as extractTextContent, f as AuthenticationError, g as ModelNotFoundError, l as prepareRequestControls, m as ContextLengthError, o as normalizeBaseAIOptions, s as normalizeChatOptions, t as emitUsage, u as AIError } from "./usage-B9gPCWSa.js";
|
|
2
|
+
import { n as rateLimitErrorFrom } from "./rate-limit-BkK4-hXY.js";
|
|
3
3
|
import { r as parseToolArguments } from "./tool-messages-0ND35mYX.js";
|
|
4
4
|
//#region src/shared/providers/anthropic.ts
|
|
5
5
|
/**
|
|
@@ -604,4 +604,4 @@ function extractThinkingBlocks(content) {
|
|
|
604
604
|
//#endregion
|
|
605
605
|
export { AnthropicProvider };
|
|
606
606
|
|
|
607
|
-
//# sourceMappingURL=anthropic-
|
|
607
|
+
//# sourceMappingURL=anthropic-CdbK9Jl-.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"anthropic-CxOrttgj.js","names":[],"sources":["../../src/shared/providers/anthropic.ts"],"sourcesContent":["/**\n * Anthropic Claude provider implementation\n *\n * Provides a standardized interface for interacting with Anthropic's Claude models,\n * including chat completions, streaming responses, and vision capabilities.\n * Note: Claude models do not support embeddings - use OpenAI or another provider for that.\n */\n\nimport { rateLimitErrorFrom } from '../rate-limit';\nimport {\n normalizeBaseAIOptions,\n normalizeChatOptions,\n type PreparedRequestControls,\n prepareRequestControls,\n} from '../safety';\nimport { parseToolArguments } from '../tool-messages';\nimport type {\n AICapabilities,\n AIInterface,\n AIMessage,\n AIModel,\n AIResponse,\n AIThinkingBlock,\n AIToolCall,\n AnthropicOptions,\n ChatOptions,\n CompletionOptions,\n EmbeddingOptions,\n EmbeddingResponse,\n ImageDescriptionOptions,\n ImageEmbeddingOptions,\n ImageGenerationOptions,\n ImageGenerationResponse,\n MessageOptions,\n TokenUsage,\n TTSOptions,\n TTSResponse,\n VideoGenerationJob,\n VideoGenerationOptions,\n VideoGenerationResult,\n VideoGenerationStatusResult,\n Voice,\n VoiceCloneOptions,\n VoiceDesignOptions,\n VoiceListOptions,\n} from '../types';\nimport {\n AIError,\n AuthenticationError,\n ContextLengthError,\n extractTextContent,\n ModelNotFoundError,\n} from '../types';\nimport { emitUsage } from './usage';\n\ntype AnthropicContentBlock =\n | AIThinkingBlock\n | { type: 'text'; text: string }\n | {\n type: 'tool_use';\n id: string;\n name: string;\n input: Record<string, unknown>;\n }\n | { type: 'tool_result'; tool_use_id: string; content: string };\n\ninterface AnthropicMessage {\n role: 'user' | 'assistant';\n content: string | AnthropicContentBlock[];\n}\n\n// Note: This implementation will require @anthropic-ai/sdk package\n// For now, this is a placeholder that defines the interface\n\n/**\n * Anthropic Claude provider implementation that handles all interactions with Anthropic's API.\n * Supports Claude models, streaming, vision capabilities, and function calling.\n * Does not support embeddings (use OpenAI or another provider for embeddings).\n */\nexport class AnthropicProvider implements AIInterface {\n private options: AnthropicOptions;\n private client: any; // Will be Anthropic instance from @anthropic-ai/sdk\n\n /**\n * Creates a new Anthropic provider instance\n * @param options - Configuration options for the Anthropic provider\n */\n constructor(options: AnthropicOptions) {\n this.options = normalizeBaseAIOptions({\n defaultModel: 'claude-3-5-sonnet-20241022',\n anthropicVersion: '2023-06-01',\n ...options,\n });\n\n // Initialize Anthropic client\n this.initializeClientSync();\n }\n\n private initializeClientSync() {\n try {\n // Dynamic import in constructor - this will work if the package is installed\n import('@anthropic-ai/sdk')\n .then(({ Anthropic }) => {\n this.client = new Anthropic({\n apiKey: this.options.apiKey,\n baseURL: this.options.baseUrl,\n timeout: this.options.timeout,\n maxRetries: this.options.maxRetries,\n defaultHeaders: {\n 'anthropic-version': this.options.anthropicVersion,\n ...this.options.headers,\n },\n });\n })\n .catch(() => {\n // Client will be null and we'll handle it in methods\n });\n } catch (_error) {\n // Client will be null and we'll handle it in methods\n }\n }\n\n /**\n * Ensures the Anthropic client is initialized by dynamically importing the SDK\n * @throws {AIError} When the Anthropic SDK cannot be loaded\n * @private\n */\n private async ensureClient() {\n if (!this.client) {\n try {\n const { Anthropic } = await import('@anthropic-ai/sdk');\n this.client = new Anthropic({\n apiKey: this.options.apiKey,\n baseURL: this.options.baseUrl,\n timeout: this.options.timeout,\n maxRetries: this.options.maxRetries,\n defaultHeaders: {\n 'anthropic-version': this.options.anthropicVersion,\n ...this.options.headers,\n },\n });\n } catch (_error) {\n throw new AIError(\n 'Failed to initialize Anthropic client. Make sure @anthropic-ai/sdk is installed.',\n 'INITIALIZATION_ERROR',\n 'anthropic',\n );\n }\n }\n }\n\n /**\n * Generate a chat completion using Claude models\n * @param messages - Array of conversation messages\n * @param options - Optional configuration for the chat completion\n * @returns Promise resolving to the AI response with content and metadata\n * @throws {AIError} When the API request fails or SDK is not available\n *\n * @example\n * ```typescript\n * const response = await provider.chat([\n * { role: 'system', content: 'You are a helpful assistant.' },\n * { role: 'user', content: 'Explain quantum computing' }\n * ], {\n * model: 'claude-3-5-sonnet-20241022',\n * maxTokens: 1000\n * });\n * ```\n */\n async chat(\n messages: AIMessage[],\n options: ChatOptions = {},\n ): Promise<AIResponse> {\n const startTime = Date.now();\n let controls: PreparedRequestControls | undefined;\n try {\n await this.ensureClient();\n\n const { system, anthropicMessages } =\n this.mapMessagesToAnthropic(messages);\n\n const model = options.model || this.options.defaultModel;\n options = normalizeChatOptions(this.options, options, 'anthropic', model);\n controls = prepareRequestControls(this.options, options);\n\n // Build request parameters\n const requestParams: Record<string, any> = {\n model,\n messages: anthropicMessages,\n max_tokens: options.maxTokens,\n temperature: options.temperature,\n top_p: options.topP,\n stop_sequences: Array.isArray(options.stop)\n ? options.stop\n : options.stop\n ? [options.stop]\n : undefined,\n system: system || undefined,\n ...this.mapToolParams(options, anthropicMessages),\n stream: false,\n };\n const thinking = this.mapThinking(options, anthropicMessages);\n if (thinking) {\n requestParams.thinking = thinking;\n }\n\n // Add response format if specified\n if (options.responseFormat?.type === 'json_object') {\n const jsonInstruction =\n '\\n\\nIMPORTANT: You must respond with valid JSON only. Do not include any explanatory text outside the JSON object.';\n requestParams.system = requestParams.system\n ? requestParams.system + jsonInstruction\n : jsonInstruction.trim();\n }\n\n const response = await this.client.messages.create(requestParams, {\n signal: controls.signal,\n timeout: controls.timeout,\n });\n\n // Extract text content and tool calls from response\n const textContent = response.content\n .filter((block: any) => block.type === 'text')\n .map((block: any) => block.text)\n .join('');\n\n const toolCalls: AIToolCall[] = response.content\n .filter((block: any) => block.type === 'tool_use')\n .map((block: any) => ({\n id: block.id,\n type: 'function' as const,\n function: {\n name: block.name,\n arguments: JSON.stringify(block.input),\n },\n }));\n\n // Extended thinking: the replayed tool_use turn must start with these\n // blocks (signatures intact), so they ride on the first tool call.\n const thinkingBlocks = extractThinkingBlocks(response.content);\n if (toolCalls.length > 0 && thinkingBlocks.length > 0) {\n toolCalls[0].thinkingBlocks = thinkingBlocks;\n }\n\n const usage: TokenUsage = {\n promptTokens: response.usage.input_tokens,\n completionTokens: response.usage.output_tokens,\n totalTokens: response.usage.input_tokens + response.usage.output_tokens,\n };\n emitUsage(\n this.options,\n 'anthropic',\n 'chat',\n response.model || model,\n usage,\n startTime,\n options.usageTags,\n );\n\n return {\n content: textContent,\n model: response.model,\n finishReason: this.mapFinishReason(response.stop_reason),\n usage,\n toolCalls: toolCalls.length > 0 ? toolCalls : undefined,\n };\n } catch (error) {\n if (controls?.didTimeout()) {\n throw new AIError(\n `AI request timed out after ${controls.timeout}ms`,\n 'AI_TIMEOUT',\n 'anthropic',\n options.model,\n );\n }\n if (options.signal?.aborted) {\n throw new AIError(\n 'AI request aborted by caller',\n 'AI_ABORTED',\n 'anthropic',\n options.model,\n );\n }\n throw this.mapError(error);\n } finally {\n controls?.cleanup();\n }\n }\n\n async complete(\n prompt: string,\n options: CompletionOptions = {},\n ): Promise<AIResponse> {\n return this.chat([{ role: 'user', content: prompt }], {\n model: options.model,\n maxTokens: options.maxTokens,\n temperature: options.temperature,\n topP: options.topP,\n n: options.n,\n stop: options.stop,\n stream: options.stream,\n onProgress: options.onProgress,\n signal: options.signal,\n timeout: options.timeout,\n reasoning: options.reasoning,\n usageTags: options.usageTags,\n continueOnLength: options.continueOnLength,\n });\n }\n\n /**\n * Simple message interface for single-turn interactions with optional history\n *\n * @param text - The message text to send\n * @param options - Configuration options including history, model, etc.\n * @returns Promise resolving to the response content string\n *\n * @example\n * ```typescript\n * // Simple usage\n * const response = await provider.message('Hello!');\n *\n * // With history\n * const response = await provider.message('What was my question?', {\n * history: [\n * { role: 'user', content: 'What is 2+2?' },\n * { role: 'assistant', content: '4' }\n * ]\n * });\n * ```\n */\n async message(text: string, options: MessageOptions = {}): Promise<string> {\n // Build messages array from history + current message\n const messages: AIMessage[] = [\n ...(options.history || []),\n { role: options.role || 'user', content: text },\n ];\n\n const response = await this.chat(messages, {\n model: options.model,\n maxTokens: options.maxTokens,\n temperature: options.temperature,\n topP: options.topP,\n stop: options.stop,\n stream: options.stream,\n frequencyPenalty: options.frequencyPenalty,\n presencePenalty: options.presencePenalty,\n responseFormat: options.responseFormat,\n seed: options.seed,\n tools: options.tools,\n toolChoice: options.toolChoice,\n onProgress: options.onProgress,\n signal: options.signal,\n timeout: options.timeout,\n reasoning: options.reasoning,\n usageTags: options.usageTags,\n continueOnLength: options.continueOnLength,\n });\n\n return response.content;\n }\n\n async embed(\n _text: string | string[],\n _options: EmbeddingOptions = {},\n ): Promise<EmbeddingResponse> {\n // Anthropic Claude doesn't provide embeddings API\n throw new AIError(\n 'Anthropic Claude does not support embeddings. Use OpenAI or another provider for embeddings.',\n 'NOT_SUPPORTED',\n 'anthropic',\n );\n }\n\n async embedImage(\n _image: string | Buffer,\n _options: ImageEmbeddingOptions = {},\n ): Promise<EmbeddingResponse> {\n throw new AIError(\n 'Anthropic Claude does not support image embeddings. Use OpenAI or Gemini.',\n 'NOT_SUPPORTED',\n 'anthropic',\n );\n }\n\n async describeImage(\n _image: string | Buffer,\n _prompt?: string,\n _options: ImageDescriptionOptions = {},\n ): Promise<string> {\n // Note: Claude does support vision, but we're keeping this as a stub for now\n // A full implementation could use the chat API with image content\n throw new AIError(\n 'Image description is not yet implemented for Anthropic. Use OpenAI or Gemini.',\n 'NOT_IMPLEMENTED',\n 'anthropic',\n );\n }\n\n async generateImage(\n _prompt: string,\n _options: ImageGenerationOptions = {},\n ): Promise<ImageGenerationResponse> {\n throw new AIError(\n 'Anthropic Claude does not support image generation. Use OpenAI or Gemini.',\n 'NOT_SUPPORTED',\n 'anthropic',\n );\n }\n\n /**\n * Streams a chat completion as text chunks.\n *\n * Streams yield text only and never surface tool calls, so `options.tools`\n * and `options.toolChoice` are ignored: tools are declared only when the\n * replayed history contains `tool_use` blocks (Anthropic requires it), with\n * `tool_choice: { type: 'none' }`. Use `chat()` for rounds that may call\n * tools.\n */\n async *stream(\n messages: AIMessage[],\n options: ChatOptions = {},\n ): AsyncIterable<string> {\n const startTime = Date.now();\n let controls: PreparedRequestControls | undefined;\n try {\n await this.ensureClient();\n\n const { system, anthropicMessages } =\n this.mapMessagesToAnthropic(messages);\n\n const model = options.model || this.options.defaultModel;\n options = normalizeChatOptions(this.options, options, 'anthropic', model);\n controls = prepareRequestControls(this.options, options);\n\n const requestParams: Record<string, any> = {\n model,\n messages: anthropicMessages,\n max_tokens: options.maxTokens,\n temperature: options.temperature,\n top_p: options.topP,\n stop_sequences: Array.isArray(options.stop)\n ? options.stop\n : options.stop\n ? [options.stop]\n : undefined,\n system: system || undefined,\n // stream() yields text only, so a tool call would be lost: declare\n // tools only when the replayed history requires it, with\n // tool_choice none.\n ...this.mapHistoryToolParams(anthropicMessages),\n stream: true,\n };\n const thinking = this.mapThinking(options, anthropicMessages);\n if (thinking) {\n requestParams.thinking = thinking;\n }\n const stream = await this.client.messages.create(requestParams, {\n signal: controls.signal,\n timeout: controls.timeout,\n });\n\n let streamStopReason: string | null = null;\n for await (const chunk of stream) {\n if (chunk.type === 'message_delta' && chunk.delta?.stop_reason) {\n streamStopReason = chunk.delta.stop_reason;\n }\n if (\n chunk.type === 'content_block_delta' &&\n chunk.delta.type === 'text_delta'\n ) {\n if (options.onProgress) {\n options.onProgress(chunk.delta.text);\n }\n yield chunk.delta.text;\n }\n }\n options.onFinishReason?.(\n this.mapFinishReason(streamStopReason) ?? 'stop',\n );\n\n emitUsage(\n this.options,\n 'anthropic',\n 'stream',\n model!,\n undefined,\n startTime,\n options.usageTags,\n );\n } catch (error) {\n if (controls?.didTimeout()) {\n throw new AIError(\n `AI request timed out after ${controls.timeout}ms`,\n 'AI_TIMEOUT',\n 'anthropic',\n options.model,\n );\n }\n if (options.signal?.aborted) {\n throw new AIError(\n 'AI request aborted by caller',\n 'AI_ABORTED',\n 'anthropic',\n options.model,\n );\n }\n throw this.mapError(error);\n } finally {\n controls?.cleanup();\n }\n }\n\n async countTokens(text: string): Promise<number> {\n // Anthropic doesn't provide a direct token counting API\n // This is an approximation - Claude uses a different tokenizer than OpenAI\n return Math.ceil(text.length / 3.5); // Slightly different ratio for Claude\n }\n\n async getModels(): Promise<AIModel[]> {\n // Return static list of known Claude models\n return [\n {\n id: 'claude-3-5-sonnet-20241022',\n name: 'Claude 3.5 Sonnet',\n description: 'Most intelligent Claude model with balanced performance',\n contextLength: 200000,\n capabilities: ['text', 'chat', 'vision', 'functions'],\n supportsFunctions: true,\n supportsVision: true,\n },\n {\n id: 'claude-3-5-haiku-20241022',\n name: 'Claude 3.5 Haiku',\n description: 'Fastest Claude model for simple tasks',\n contextLength: 200000,\n capabilities: ['text', 'chat', 'vision'],\n supportsFunctions: true,\n supportsVision: true,\n },\n {\n id: 'claude-3-opus-20240229',\n name: 'Claude 3 Opus',\n description: 'Most powerful Claude model for complex tasks',\n contextLength: 200000,\n capabilities: ['text', 'chat', 'vision', 'functions'],\n supportsFunctions: true,\n supportsVision: true,\n },\n {\n id: 'claude-3-sonnet-20240229',\n name: 'Claude 3 Sonnet',\n description: 'Balanced Claude model for most tasks',\n contextLength: 200000,\n capabilities: ['text', 'chat', 'vision'],\n supportsFunctions: true,\n supportsVision: true,\n },\n {\n id: 'claude-3-haiku-20240307',\n name: 'Claude 3 Haiku',\n description: 'Fast Claude model for simple tasks',\n contextLength: 200000,\n capabilities: ['text', 'chat', 'vision'],\n supportsFunctions: false,\n supportsVision: true,\n },\n ];\n }\n\n async getCapabilities(): Promise<AICapabilities> {\n return {\n chat: true,\n completion: true,\n embeddings: false, // Claude doesn't support embeddings\n streaming: true,\n functions: true,\n vision: true,\n fineTuning: false,\n imageEmbeddings: false,\n imageGeneration: false,\n videoGeneration: false,\n tts: false,\n voiceCloning: false,\n voiceDesign: false,\n maxContextLength: 200000,\n supportedOperations: [\n 'chat',\n 'completion',\n 'streaming',\n 'functions',\n 'vision',\n ],\n };\n }\n\n // ============================================================================\n // Video Generation Methods (Not supported - use gemini, byteplus-modelark,\n // or openai-compat-video provider)\n // ============================================================================\n\n async submitVideoGenerationJob(\n _options: VideoGenerationOptions,\n ): Promise<VideoGenerationJob> {\n throw new AIError(\n 'Video generation is not supported by Anthropic provider. Use gemini, byteplus-modelark, or openai-compat-video provider.',\n 'NOT_IMPLEMENTED',\n 'anthropic',\n );\n }\n\n async getVideoGenerationJob(\n _handle: VideoGenerationJob,\n ): Promise<VideoGenerationStatusResult> {\n throw new AIError(\n 'Video generation is not supported by Anthropic provider. Use gemini, byteplus-modelark, or openai-compat-video provider.',\n 'NOT_IMPLEMENTED',\n 'anthropic',\n );\n }\n\n async fetchVideoGenerationResult(\n _handle: VideoGenerationJob,\n ): Promise<VideoGenerationResult> {\n throw new AIError(\n 'Video generation is not supported by Anthropic provider. Use gemini, byteplus-modelark, or openai-compat-video provider.',\n 'NOT_IMPLEMENTED',\n 'anthropic',\n );\n }\n\n async cancelVideoGenerationJob(_handle: VideoGenerationJob): Promise<void> {\n throw new AIError(\n 'Video generation is not supported by Anthropic provider. Use gemini, byteplus-modelark, or openai-compat-video provider.',\n 'NOT_IMPLEMENTED',\n 'anthropic',\n );\n }\n\n async validateVideoGenerationAccess(): Promise<boolean> {\n throw new AIError(\n 'Video generation is not supported by Anthropic provider. Use gemini, byteplus-modelark, or openai-compat-video provider.',\n 'NOT_IMPLEMENTED',\n 'anthropic',\n );\n }\n\n // ============================================================================\n // TTS Methods (Not supported - use Qwen3-TTS provider)\n // ============================================================================\n\n async synthesizeSpeech(\n _text: string,\n _options?: TTSOptions,\n ): Promise<TTSResponse> {\n throw new AIError(\n 'TTS is not supported by Anthropic provider. Use Qwen3-TTS provider.',\n 'NOT_IMPLEMENTED',\n 'anthropic',\n );\n }\n\n streamSpeech(_text: string, _options?: TTSOptions): AsyncIterable<Buffer> {\n const error = new AIError(\n 'TTS streaming is not supported by Anthropic provider. Use Qwen3-TTS provider.',\n 'NOT_IMPLEMENTED',\n 'anthropic',\n );\n return {\n [Symbol.asyncIterator]: () => ({\n next: () => Promise.reject(error),\n }),\n };\n }\n\n async cloneVoice(_options: VoiceCloneOptions): Promise<Voice> {\n throw new AIError(\n 'Voice cloning is not supported by Anthropic provider. Use Qwen3-TTS provider.',\n 'NOT_IMPLEMENTED',\n 'anthropic',\n );\n }\n\n async designVoice(_options: VoiceDesignOptions): Promise<Voice> {\n throw new AIError(\n 'Voice design is not supported by Anthropic provider. Use Qwen3-TTS provider.',\n 'NOT_IMPLEMENTED',\n 'anthropic',\n );\n }\n\n async getVoices(_options?: VoiceListOptions): Promise<Voice[]> {\n throw new AIError(\n 'Voice listing is not supported by Anthropic provider. Use Qwen3-TTS provider.',\n 'NOT_IMPLEMENTED',\n 'anthropic',\n );\n }\n\n /**\n * Maps internal messages to Anthropic Messages API turns.\n *\n * Assistant `tool_calls` become `tool_use` blocks and `role: 'tool'`\n * results become `tool_result` blocks paired by `tool_call_id`\n * (`tool_use_id`). Consecutive tool results are grouped into one user turn,\n * as Anthropic requires every result for a turn to follow it directly.\n * Only answered calls are replayed as `tool_use`, and only results whose\n * `tool_call_id` matches a replayed call become `tool_result`. A result\n * without `tool_call_id`, or one answering no replayed call, falls back to\n * plain text (and a call left unanswered keeps only its text).\n */\n private mapMessagesToAnthropic(messages: AIMessage[]): {\n system?: string;\n anthropicMessages: AnthropicMessage[];\n } {\n // Anthropic handles system messages separately\n let system: string | undefined;\n const anthropicMessages: AnthropicMessage[] = [];\n const answeredToolCallIds = new Set(\n messages\n .filter((message) => message.role === 'tool' && message.tool_call_id)\n .map((message) => message.tool_call_id as string),\n );\n // Calls replayed as tool_use: those with an answer. Only results for\n // these ids become tool_result blocks; any other result is an orphan\n // Anthropic would reject, so it falls back to plain text.\n const replayedToolUseIds = new Set<string>();\n for (const message of messages) {\n if (message.role !== 'assistant') continue;\n for (const toolCall of message.tool_calls || []) {\n if (answeredToolCallIds.has(toolCall.id)) {\n replayedToolUseIds.add(toolCall.id);\n }\n }\n }\n\n for (const message of messages) {\n const textContent = extractTextContent(message.content);\n if (message.role === 'system') {\n // Combine multiple system messages\n system = system ? `${system}\\n\\n${textContent}` : textContent;\n continue;\n }\n\n if (\n message.role === 'tool' &&\n message.tool_call_id &&\n replayedToolUseIds.has(message.tool_call_id)\n ) {\n const block: AnthropicContentBlock = {\n type: 'tool_result',\n tool_use_id: message.tool_call_id,\n content: textContent,\n };\n const previous = anthropicMessages[anthropicMessages.length - 1];\n if (\n previous?.role === 'user' &&\n Array.isArray(previous.content) &&\n previous.content.every((part) => part.type === 'tool_result')\n ) {\n previous.content.push(block);\n } else {\n anthropicMessages.push({ role: 'user', content: [block] });\n }\n continue;\n }\n\n const toolCalls =\n message.role === 'assistant'\n ? (message.tool_calls || []).filter((toolCall) =>\n answeredToolCallIds.has(toolCall.id),\n )\n : [];\n if (toolCalls.length > 0) {\n const content: AnthropicContentBlock[] = [];\n for (const toolCall of toolCalls) {\n for (const block of toolCall.thinkingBlocks || []) {\n content.push({ ...block });\n }\n }\n if (textContent) {\n content.push({ type: 'text', text: textContent });\n }\n for (const toolCall of toolCalls) {\n content.push({\n type: 'tool_use',\n id: toolCall.id,\n name: toolCall.function.name,\n input: parseToolArguments(toolCall.function.arguments),\n });\n }\n anthropicMessages.push({ role: 'assistant', content });\n continue;\n }\n\n anthropicMessages.push({\n role: message.role === 'assistant' ? 'assistant' : 'user',\n content: textContent,\n });\n }\n\n return { system, anthropicMessages };\n }\n\n /**\n * Builds the `tools` / `tool_choice` request fields.\n *\n * Anthropic rejects a request whose history contains `tool_use` or\n * `tool_result` blocks unless `tools` is declared. A tool loop's final,\n * tool-less round (no `tools`, typically `toolChoice: 'none'`) still\n * replays that history, so when the caller declares no tools but the\n * history uses some, this declares a minimal definition for each tool the\n * history references and sets `tool_choice: { type: 'none' }` so the model\n * answers in text instead of calling them.\n */\n private mapToolParams(\n options: ChatOptions,\n anthropicMessages: AnthropicMessage[],\n ): { tools?: Record<string, any>[]; tool_choice?: Record<string, any> } {\n const tools = this.mapTools(options);\n if (tools) {\n return { tools, tool_choice: this.mapToolChoice(options.toolChoice) };\n }\n return this.mapHistoryToolParams(anthropicMessages);\n }\n\n /**\n * Declares a minimal definition for each tool the replayed history\n * references, with `tool_choice: { type: 'none' }`, or nothing when the\n * history has no `tool_use` blocks. Used for tool-less rounds and for\n * every stream (streams never yield tool calls).\n */\n private mapHistoryToolParams(anthropicMessages: AnthropicMessage[]): {\n tools?: Record<string, any>[];\n tool_choice?: Record<string, any>;\n } {\n // mapMessagesToAnthropic emits tool_result only for ids it replayed as\n // tool_use (orphan results become text), so tool_use names cover every\n // tool the history references.\n const historyToolNames = new Set<string>();\n for (const message of anthropicMessages) {\n if (!Array.isArray(message.content)) continue;\n for (const block of message.content) {\n if (block.type === 'tool_use') historyToolNames.add(block.name);\n }\n }\n if (historyToolNames.size === 0) {\n return {};\n }\n\n return {\n tools: [...historyToolNames].map((name) => ({\n name,\n description:\n 'Used earlier in this conversation; not available for this turn.',\n input_schema: { type: 'object' },\n })),\n tool_choice: { type: 'none' },\n };\n }\n\n /**\n * Builds the `thinking` request field for `options.reasoning.maxTokens`.\n *\n * While thinking is enabled, Anthropic requires the assistant turn of an\n * in-progress tool loop (the last assistant turn, when it holds `tool_use`)\n * to start with its thinking blocks. They are replayed from\n * `AIToolCall.thinkingBlocks`; when that turn has none (the history came\n * from another provider, a store that dropped the field, or a call made\n * without thinking), thinking is left off for this request rather than\n * sending a request Anthropic would reject.\n */\n private mapThinking(\n options: ChatOptions,\n anthropicMessages: AnthropicMessage[],\n ): { type: 'enabled'; budget_tokens: number } | undefined {\n const budget = options.reasoning?.maxTokens || 0;\n if (budget <= 0) return undefined;\n\n const lastAssistant = [...anthropicMessages]\n .reverse()\n .find((message) => message.role === 'assistant');\n if (\n lastAssistant &&\n Array.isArray(lastAssistant.content) &&\n lastAssistant.content.some((block) => block.type === 'tool_use')\n ) {\n const firstType = lastAssistant.content[0]?.type;\n if (firstType !== 'thinking' && firstType !== 'redacted_thinking') {\n return undefined;\n }\n }\n\n return { type: 'enabled', budget_tokens: budget };\n }\n\n private mapTools(options: ChatOptions): Record<string, any>[] | undefined {\n return options.tools && options.tools.length > 0\n ? options.tools.map((tool) => ({\n name: tool.function.name,\n description: tool.function.description || '',\n input_schema: tool.function.parameters || { type: 'object' },\n }))\n : undefined;\n }\n\n private mapToolChoice(\n toolChoice?:\n | 'auto'\n | 'none'\n | { type: 'function'; function: { name: string } },\n ): any {\n if (!toolChoice || toolChoice === 'auto') {\n return { type: 'auto' };\n }\n\n if (toolChoice === 'none') {\n return { type: 'none' };\n }\n\n if (typeof toolChoice === 'object' && toolChoice.type === 'function') {\n return {\n type: 'tool',\n name: toolChoice.function.name,\n };\n }\n\n return { type: 'auto' };\n }\n\n private mapFinishReason(reason: string | null): AIResponse['finishReason'] {\n switch (reason) {\n case 'end_turn':\n return 'stop';\n case 'max_tokens':\n return 'length';\n case 'stop_sequence':\n return 'stop';\n case 'tool_use':\n return 'tool_calls';\n default:\n return 'stop';\n }\n }\n\n private mapError(error: unknown): AIError {\n if (error instanceof AIError) {\n return error;\n }\n\n // Map common HTTP status codes from Anthropic API\n if (typeof error === 'object' && error !== null && 'status' in error) {\n const apiError = error as { status: number; message?: string };\n switch (apiError.status) {\n case 401:\n return new AuthenticationError('anthropic');\n case 429:\n return rateLimitErrorFrom('anthropic', error);\n case 404:\n return new ModelNotFoundError(\n apiError.message || 'Model not found',\n 'anthropic',\n );\n case 413:\n return new ContextLengthError('anthropic');\n }\n }\n\n const errorMessage =\n error instanceof Error\n ? error.message\n : 'Unknown Anthropic error occurred';\n return new AIError(errorMessage, 'UNKNOWN_ERROR', 'anthropic');\n }\n}\n\n/**\n * Thinking and redacted-thinking blocks from an Anthropic response, copied\n * with only the fields the API accepts back.\n */\nfunction extractThinkingBlocks(content: any[]): AIThinkingBlock[] {\n const blocks: AIThinkingBlock[] = [];\n for (const block of content || []) {\n if (block?.type === 'thinking') {\n blocks.push({\n type: 'thinking',\n thinking: block.thinking,\n signature: block.signature,\n });\n } else if (block?.type === 'redacted_thinking') {\n blocks.push({ type: 'redacted_thinking', data: block.data });\n }\n }\n return blocks;\n}\n"],"mappings":";;;;;;;;;;;;;;;;AA+EA,IAAa,oBAAb,MAAsD;CACpD;CACA;;;;;CAMA,YAAY,SAA2B;EACrC,KAAK,UAAU,uBAAuB;GACpC,cAAc;GACd,kBAAkB;GAClB,GAAG;EACL,CAAC;EAGD,KAAK,qBAAqB;CAC5B;CAEA,uBAA+B;EAC7B,IAAI;GAEF,OAAO,oBAAoB,CACxB,MAAM,EAAE,gBAAgB;IACvB,KAAK,SAAS,IAAI,UAAU;KAC1B,QAAQ,KAAK,QAAQ;KACrB,SAAS,KAAK,QAAQ;KACtB,SAAS,KAAK,QAAQ;KACtB,YAAY,KAAK,QAAQ;KACzB,gBAAgB;MACd,qBAAqB,KAAK,QAAQ;MAClC,GAAG,KAAK,QAAQ;KAClB;IACF,CAAC;GACH,CAAC,CAAC,CACD,YAAY,CAEb,CAAC;EACL,SAAS,QAAQ,CAEjB;CACF;;;;;;CAOA,MAAc,eAAe;EAC3B,IAAI,CAAC,KAAK,QACR,IAAI;GACF,MAAM,EAAE,cAAc,MAAM,OAAO;GACnC,KAAK,SAAS,IAAI,UAAU;IAC1B,QAAQ,KAAK,QAAQ;IACrB,SAAS,KAAK,QAAQ;IACtB,SAAS,KAAK,QAAQ;IACtB,YAAY,KAAK,QAAQ;IACzB,gBAAgB;KACd,qBAAqB,KAAK,QAAQ;KAClC,GAAG,KAAK,QAAQ;IAClB;GACF,CAAC;EACH,SAAS,QAAQ;GACf,MAAM,IAAI,QACR,oFACA,wBACA,WACF;EACF;CAEJ;;;;;;;;;;;;;;;;;;;CAoBA,MAAM,KACJ,UACA,UAAuB,CAAC,GACH;EACrB,MAAM,YAAY,KAAK,IAAI;EAC3B,IAAI;EACJ,IAAI;GACF,MAAM,KAAK,aAAa;GAExB,MAAM,EAAE,QAAQ,sBACd,KAAK,uBAAuB,QAAQ;GAEtC,MAAM,QAAQ,QAAQ,SAAS,KAAK,QAAQ;GAC5C,UAAU,qBAAqB,KAAK,SAAS,SAAS,aAAa,KAAK;GACxE,WAAW,uBAAuB,KAAK,SAAS,OAAO;GAGvD,MAAM,gBAAqC;IACzC;IACA,UAAU;IACV,YAAY,QAAQ;IACpB,aAAa,QAAQ;IACrB,OAAO,QAAQ;IACf,gBAAgB,MAAM,QAAQ,QAAQ,IAAI,IACtC,QAAQ,OACR,QAAQ,OACN,CAAC,QAAQ,IAAI,IACb,KAAA;IACN,QAAQ,UAAU,KAAA;IAClB,GAAG,KAAK,cAAc,SAAS,iBAAiB;IAChD,QAAQ;GACV;GACA,MAAM,WAAW,KAAK,YAAY,SAAS,iBAAiB;GAC5D,IAAI,UACF,cAAc,WAAW;GAI3B,IAAI,QAAQ,gBAAgB,SAAS,eAAe;IAClD,MAAM,kBACJ;IACF,cAAc,SAAS,cAAc,SACjC,cAAc,SAAS,kBACvB,gBAAgB,KAAK;GAC3B;GAEA,MAAM,WAAW,MAAM,KAAK,OAAO,SAAS,OAAO,eAAe;IAChE,QAAQ,SAAS;IACjB,SAAS,SAAS;GACpB,CAAC;GAGD,MAAM,cAAc,SAAS,QAC1B,QAAQ,UAAe,MAAM,SAAS,MAAM,CAAC,CAC7C,KAAK,UAAe,MAAM,IAAI,CAAC,CAC/B,KAAK,EAAE;GAEV,MAAM,YAA0B,SAAS,QACtC,QAAQ,UAAe,MAAM,SAAS,UAAU,CAAC,CACjD,KAAK,WAAgB;IACpB,IAAI,MAAM;IACV,MAAM;IACN,UAAU;KACR,MAAM,MAAM;KACZ,WAAW,KAAK,UAAU,MAAM,KAAK;IACvC;GACF,EAAE;GAIJ,MAAM,iBAAiB,sBAAsB,SAAS,OAAO;GAC7D,IAAI,UAAU,SAAS,KAAK,eAAe,SAAS,GAClD,UAAU,EAAE,CAAC,iBAAiB;GAGhC,MAAM,QAAoB;IACxB,cAAc,SAAS,MAAM;IAC7B,kBAAkB,SAAS,MAAM;IACjC,aAAa,SAAS,MAAM,eAAe,SAAS,MAAM;GAC5D;GACA,UACE,KAAK,SACL,aACA,QACA,SAAS,SAAS,OAClB,OACA,WACA,QAAQ,SACV;GAEA,OAAO;IACL,SAAS;IACT,OAAO,SAAS;IAChB,cAAc,KAAK,gBAAgB,SAAS,WAAW;IACvD;IACA,WAAW,UAAU,SAAS,IAAI,YAAY,KAAA;GAChD;EACF,SAAS,OAAO;GACd,IAAI,UAAU,WAAW,GACvB,MAAM,IAAI,QACR,8BAA8B,SAAS,QAAQ,KAC/C,cACA,aACA,QAAQ,KACV;GAEF,IAAI,QAAQ,QAAQ,SAClB,MAAM,IAAI,QACR,gCACA,cACA,aACA,QAAQ,KACV;GAEF,MAAM,KAAK,SAAS,KAAK;EAC3B,UAAU;GACR,UAAU,QAAQ;EACpB;CACF;CAEA,MAAM,SACJ,QACA,UAA6B,CAAC,GACT;EACrB,OAAO,KAAK,KAAK,CAAC;GAAE,MAAM;GAAQ,SAAS;EAAO,CAAC,GAAG;GACpD,OAAO,QAAQ;GACf,WAAW,QAAQ;GACnB,aAAa,QAAQ;GACrB,MAAM,QAAQ;GACd,GAAG,QAAQ;GACX,MAAM,QAAQ;GACd,QAAQ,QAAQ;GAChB,YAAY,QAAQ;GACpB,QAAQ,QAAQ;GAChB,SAAS,QAAQ;GACjB,WAAW,QAAQ;GACnB,WAAW,QAAQ;GACnB,kBAAkB,QAAQ;EAC5B,CAAC;CACH;;;;;;;;;;;;;;;;;;;;;;CAuBA,MAAM,QAAQ,MAAc,UAA0B,CAAC,GAAoB;EAEzE,MAAM,WAAwB,CAC5B,GAAI,QAAQ,WAAW,CAAC,GACxB;GAAE,MAAM,QAAQ,QAAQ;GAAQ,SAAS;EAAK,CAChD;EAuBA,QAAO,MArBgB,KAAK,KAAK,UAAU;GACzC,OAAO,QAAQ;GACf,WAAW,QAAQ;GACnB,aAAa,QAAQ;GACrB,MAAM,QAAQ;GACd,MAAM,QAAQ;GACd,QAAQ,QAAQ;GAChB,kBAAkB,QAAQ;GAC1B,iBAAiB,QAAQ;GACzB,gBAAgB,QAAQ;GACxB,MAAM,QAAQ;GACd,OAAO,QAAQ;GACf,YAAY,QAAQ;GACpB,YAAY,QAAQ;GACpB,QAAQ,QAAQ;GAChB,SAAS,QAAQ;GACjB,WAAW,QAAQ;GACnB,WAAW,QAAQ;GACnB,kBAAkB,QAAQ;EAC5B,CAAC,EAAA,CAEe;CAClB;CAEA,MAAM,MACJ,OACA,WAA6B,CAAC,GACF;EAE5B,MAAM,IAAI,QACR,gGACA,iBACA,WACF;CACF;CAEA,MAAM,WACJ,QACA,WAAkC,CAAC,GACP;EAC5B,MAAM,IAAI,QACR,6EACA,iBACA,WACF;CACF;CAEA,MAAM,cACJ,QACA,SACA,WAAoC,CAAC,GACpB;EAGjB,MAAM,IAAI,QACR,iFACA,mBACA,WACF;CACF;CAEA,MAAM,cACJ,SACA,WAAmC,CAAC,GACF;EAClC,MAAM,IAAI,QACR,6EACA,iBACA,WACF;CACF;;;;;;;;;;CAWA,OAAO,OACL,UACA,UAAuB,CAAC,GACD;EACvB,MAAM,YAAY,KAAK,IAAI;EAC3B,IAAI;EACJ,IAAI;GACF,MAAM,KAAK,aAAa;GAExB,MAAM,EAAE,QAAQ,sBACd,KAAK,uBAAuB,QAAQ;GAEtC,MAAM,QAAQ,QAAQ,SAAS,KAAK,QAAQ;GAC5C,UAAU,qBAAqB,KAAK,SAAS,SAAS,aAAa,KAAK;GACxE,WAAW,uBAAuB,KAAK,SAAS,OAAO;GAEvD,MAAM,gBAAqC;IACzC;IACA,UAAU;IACV,YAAY,QAAQ;IACpB,aAAa,QAAQ;IACrB,OAAO,QAAQ;IACf,gBAAgB,MAAM,QAAQ,QAAQ,IAAI,IACtC,QAAQ,OACR,QAAQ,OACN,CAAC,QAAQ,IAAI,IACb,KAAA;IACN,QAAQ,UAAU,KAAA;IAIlB,GAAG,KAAK,qBAAqB,iBAAiB;IAC9C,QAAQ;GACV;GACA,MAAM,WAAW,KAAK,YAAY,SAAS,iBAAiB;GAC5D,IAAI,UACF,cAAc,WAAW;GAE3B,MAAM,SAAS,MAAM,KAAK,OAAO,SAAS,OAAO,eAAe;IAC9D,QAAQ,SAAS;IACjB,SAAS,SAAS;GACpB,CAAC;GAED,IAAI,mBAAkC;GACtC,WAAW,MAAM,SAAS,QAAQ;IAChC,IAAI,MAAM,SAAS,mBAAmB,MAAM,OAAO,aACjD,mBAAmB,MAAM,MAAM;IAEjC,IACE,MAAM,SAAS,yBACf,MAAM,MAAM,SAAS,cACrB;KACA,IAAI,QAAQ,YACV,QAAQ,WAAW,MAAM,MAAM,IAAI;KAErC,MAAM,MAAM,MAAM;IACpB;GACF;GACA,QAAQ,iBACN,KAAK,gBAAgB,gBAAgB,KAAK,MAC5C;GAEA,UACE,KAAK,SACL,aACA,UACA,OACA,KAAA,GACA,WACA,QAAQ,SACV;EACF,SAAS,OAAO;GACd,IAAI,UAAU,WAAW,GACvB,MAAM,IAAI,QACR,8BAA8B,SAAS,QAAQ,KAC/C,cACA,aACA,QAAQ,KACV;GAEF,IAAI,QAAQ,QAAQ,SAClB,MAAM,IAAI,QACR,gCACA,cACA,aACA,QAAQ,KACV;GAEF,MAAM,KAAK,SAAS,KAAK;EAC3B,UAAU;GACR,UAAU,QAAQ;EACpB;CACF;CAEA,MAAM,YAAY,MAA+B;EAG/C,OAAO,KAAK,KAAK,KAAK,SAAS,GAAG;CACpC;CAEA,MAAM,YAAgC;EAEpC,OAAO;GACL;IACE,IAAI;IACJ,MAAM;IACN,aAAa;IACb,eAAe;IACf,cAAc;KAAC;KAAQ;KAAQ;KAAU;IAAW;IACpD,mBAAmB;IACnB,gBAAgB;GAClB;GACA;IACE,IAAI;IACJ,MAAM;IACN,aAAa;IACb,eAAe;IACf,cAAc;KAAC;KAAQ;KAAQ;IAAQ;IACvC,mBAAmB;IACnB,gBAAgB;GAClB;GACA;IACE,IAAI;IACJ,MAAM;IACN,aAAa;IACb,eAAe;IACf,cAAc;KAAC;KAAQ;KAAQ;KAAU;IAAW;IACpD,mBAAmB;IACnB,gBAAgB;GAClB;GACA;IACE,IAAI;IACJ,MAAM;IACN,aAAa;IACb,eAAe;IACf,cAAc;KAAC;KAAQ;KAAQ;IAAQ;IACvC,mBAAmB;IACnB,gBAAgB;GAClB;GACA;IACE,IAAI;IACJ,MAAM;IACN,aAAa;IACb,eAAe;IACf,cAAc;KAAC;KAAQ;KAAQ;IAAQ;IACvC,mBAAmB;IACnB,gBAAgB;GAClB;EACF;CACF;CAEA,MAAM,kBAA2C;EAC/C,OAAO;GACL,MAAM;GACN,YAAY;GACZ,YAAY;GACZ,WAAW;GACX,WAAW;GACX,QAAQ;GACR,YAAY;GACZ,iBAAiB;GACjB,iBAAiB;GACjB,iBAAiB;GACjB,KAAK;GACL,cAAc;GACd,aAAa;GACb,kBAAkB;GAClB,qBAAqB;IACnB;IACA;IACA;IACA;IACA;GACF;EACF;CACF;CAOA,MAAM,yBACJ,UAC6B;EAC7B,MAAM,IAAI,QACR,4HACA,mBACA,WACF;CACF;CAEA,MAAM,sBACJ,SACsC;EACtC,MAAM,IAAI,QACR,4HACA,mBACA,WACF;CACF;CAEA,MAAM,2BACJ,SACgC;EAChC,MAAM,IAAI,QACR,4HACA,mBACA,WACF;CACF;CAEA,MAAM,yBAAyB,SAA4C;EACzE,MAAM,IAAI,QACR,4HACA,mBACA,WACF;CACF;CAEA,MAAM,gCAAkD;EACtD,MAAM,IAAI,QACR,4HACA,mBACA,WACF;CACF;CAMA,MAAM,iBACJ,OACA,UACsB;EACtB,MAAM,IAAI,QACR,uEACA,mBACA,WACF;CACF;CAEA,aAAa,OAAe,UAA8C;EACxE,MAAM,QAAQ,IAAI,QAChB,iFACA,mBACA,WACF;EACA,OAAO,GACJ,OAAO,uBAAuB,EAC7B,YAAY,QAAQ,OAAO,KAAK,EAClC,GACF;CACF;CAEA,MAAM,WAAW,UAA6C;EAC5D,MAAM,IAAI,QACR,iFACA,mBACA,WACF;CACF;CAEA,MAAM,YAAY,UAA8C;EAC9D,MAAM,IAAI,QACR,gFACA,mBACA,WACF;CACF;CAEA,MAAM,UAAU,UAA+C;EAC7D,MAAM,IAAI,QACR,iFACA,mBACA,WACF;CACF;;;;;;;;;;;;;CAcA,uBAA+B,UAG7B;EAEA,IAAI;EACJ,MAAM,oBAAwC,CAAC;EAC/C,MAAM,sBAAsB,IAAI,IAC9B,SACG,QAAQ,YAAY,QAAQ,SAAS,UAAU,QAAQ,YAAY,CAAC,CACpE,KAAK,YAAY,QAAQ,YAAsB,CACpD;EAIA,MAAM,qCAAqB,IAAI,IAAY;EAC3C,KAAK,MAAM,WAAW,UAAU;GAC9B,IAAI,QAAQ,SAAS,aAAa;GAClC,KAAK,MAAM,YAAY,QAAQ,cAAc,CAAC,GAC5C,IAAI,oBAAoB,IAAI,SAAS,EAAE,GACrC,mBAAmB,IAAI,SAAS,EAAE;EAGxC;EAEA,KAAK,MAAM,WAAW,UAAU;GAC9B,MAAM,cAAc,mBAAmB,QAAQ,OAAO;GACtD,IAAI,QAAQ,SAAS,UAAU;IAE7B,SAAS,SAAS,GAAG,OAAO,MAAM,gBAAgB;IAClD;GACF;GAEA,IACE,QAAQ,SAAS,UACjB,QAAQ,gBACR,mBAAmB,IAAI,QAAQ,YAAY,GAC3C;IACA,MAAM,QAA+B;KACnC,MAAM;KACN,aAAa,QAAQ;KACrB,SAAS;IACX;IACA,MAAM,WAAW,kBAAkB,kBAAkB,SAAS;IAC9D,IACE,UAAU,SAAS,UACnB,MAAM,QAAQ,SAAS,OAAO,KAC9B,SAAS,QAAQ,OAAO,SAAS,KAAK,SAAS,aAAa,GAE5D,SAAS,QAAQ,KAAK,KAAK;SAE3B,kBAAkB,KAAK;KAAE,MAAM;KAAQ,SAAS,CAAC,KAAK;IAAE,CAAC;IAE3D;GACF;GAEA,MAAM,YACJ,QAAQ,SAAS,eACZ,QAAQ,cAAc,CAAC,EAAA,CAAG,QAAQ,aACjC,oBAAoB,IAAI,SAAS,EAAE,CACrC,IACA,CAAC;GACP,IAAI,UAAU,SAAS,GAAG;IACxB,MAAM,UAAmC,CAAC;IAC1C,KAAK,MAAM,YAAY,WACrB,KAAK,MAAM,SAAS,SAAS,kBAAkB,CAAC,GAC9C,QAAQ,KAAK,EAAE,GAAG,MAAM,CAAC;IAG7B,IAAI,aACF,QAAQ,KAAK;KAAE,MAAM;KAAQ,MAAM;IAAY,CAAC;IAElD,KAAK,MAAM,YAAY,WACrB,QAAQ,KAAK;KACX,MAAM;KACN,IAAI,SAAS;KACb,MAAM,SAAS,SAAS;KACxB,OAAO,mBAAmB,SAAS,SAAS,SAAS;IACvD,CAAC;IAEH,kBAAkB,KAAK;KAAE,MAAM;KAAa;IAAQ,CAAC;IACrD;GACF;GAEA,kBAAkB,KAAK;IACrB,MAAM,QAAQ,SAAS,cAAc,cAAc;IACnD,SAAS;GACX,CAAC;EACH;EAEA,OAAO;GAAE;GAAQ;EAAkB;CACrC;;;;;;;;;;;;CAaA,cACE,SACA,mBACsE;EACtE,MAAM,QAAQ,KAAK,SAAS,OAAO;EACnC,IAAI,OACF,OAAO;GAAE;GAAO,aAAa,KAAK,cAAc,QAAQ,UAAU;EAAE;EAEtE,OAAO,KAAK,qBAAqB,iBAAiB;CACpD;;;;;;;CAQA,qBAA6B,mBAG3B;EAIA,MAAM,mCAAmB,IAAI,IAAY;EACzC,KAAK,MAAM,WAAW,mBAAmB;GACvC,IAAI,CAAC,MAAM,QAAQ,QAAQ,OAAO,GAAG;GACrC,KAAK,MAAM,SAAS,QAAQ,SAC1B,IAAI,MAAM,SAAS,YAAY,iBAAiB,IAAI,MAAM,IAAI;EAElE;EACA,IAAI,iBAAiB,SAAS,GAC5B,OAAO,CAAC;EAGV,OAAO;GACL,OAAO,CAAC,GAAG,gBAAgB,CAAC,CAAC,KAAK,UAAU;IAC1C;IACA,aACE;IACF,cAAc,EAAE,MAAM,SAAS;GACjC,EAAE;GACF,aAAa,EAAE,MAAM,OAAO;EAC9B;CACF;;;;;;;;;;;;CAaA,YACE,SACA,mBACwD;EACxD,MAAM,SAAS,QAAQ,WAAW,aAAa;EAC/C,IAAI,UAAU,GAAG,OAAO,KAAA;EAExB,MAAM,gBAAgB,CAAC,GAAG,iBAAiB,CAAC,CACzC,QAAQ,CAAC,CACT,MAAM,YAAY,QAAQ,SAAS,WAAW;EACjD,IACE,iBACA,MAAM,QAAQ,cAAc,OAAO,KACnC,cAAc,QAAQ,MAAM,UAAU,MAAM,SAAS,UAAU,GAC/D;GACA,MAAM,YAAY,cAAc,QAAQ,EAAE,EAAE;GAC5C,IAAI,cAAc,cAAc,cAAc,qBAC5C;EAEJ;EAEA,OAAO;GAAE,MAAM;GAAW,eAAe;EAAO;CAClD;CAEA,SAAiB,SAAyD;EACxE,OAAO,QAAQ,SAAS,QAAQ,MAAM,SAAS,IAC3C,QAAQ,MAAM,KAAK,UAAU;GAC3B,MAAM,KAAK,SAAS;GACpB,aAAa,KAAK,SAAS,eAAe;GAC1C,cAAc,KAAK,SAAS,cAAc,EAAE,MAAM,SAAS;EAC7D,EAAE,IACF,KAAA;CACN;CAEA,cACE,YAIK;EACL,IAAI,CAAC,cAAc,eAAe,QAChC,OAAO,EAAE,MAAM,OAAO;EAGxB,IAAI,eAAe,QACjB,OAAO,EAAE,MAAM,OAAO;EAGxB,IAAI,OAAO,eAAe,YAAY,WAAW,SAAS,YACxD,OAAO;GACL,MAAM;GACN,MAAM,WAAW,SAAS;EAC5B;EAGF,OAAO,EAAE,MAAM,OAAO;CACxB;CAEA,gBAAwB,QAAmD;EACzE,QAAQ,QAAR;GACE,KAAK,YACH,OAAO;GACT,KAAK,cACH,OAAO;GACT,KAAK,iBACH,OAAO;GACT,KAAK,YACH,OAAO;GACT,SACE,OAAO;EACX;CACF;CAEA,SAAiB,OAAyB;EACxC,IAAI,iBAAiB,SACnB,OAAO;EAIT,IAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,YAAY,OAAO;GACpE,MAAM,WAAW;GACjB,QAAQ,SAAS,QAAjB;IACE,KAAK,KACH,OAAO,IAAI,oBAAoB,WAAW;IAC5C,KAAK,KACH,OAAO,mBAAmB,aAAa,KAAK;IAC9C,KAAK,KACH,OAAO,IAAI,mBACT,SAAS,WAAW,mBACpB,WACF;IACF,KAAK,KACH,OAAO,IAAI,mBAAmB,WAAW;GAC7C;EACF;EAMA,OAAO,IAAI,QAHT,iBAAiB,QACb,MAAM,UACN,oCAC2B,iBAAiB,WAAW;CAC/D;AACF;;;;;AAMA,SAAS,sBAAsB,SAAmC;CAChE,MAAM,SAA4B,CAAC;CACnC,KAAK,MAAM,SAAS,WAAW,CAAC,GAC9B,IAAI,OAAO,SAAS,YAClB,OAAO,KAAK;EACV,MAAM;EACN,UAAU,MAAM;EAChB,WAAW,MAAM;CACnB,CAAC;MACI,IAAI,OAAO,SAAS,qBACzB,OAAO,KAAK;EAAE,MAAM;EAAqB,MAAM,MAAM;CAAK,CAAC;CAG/D,OAAO;AACT"}
|
|
1
|
+
{"version":3,"file":"anthropic-CdbK9Jl-.js","names":[],"sources":["../../src/shared/providers/anthropic.ts"],"sourcesContent":["/**\n * Anthropic Claude provider implementation\n *\n * Provides a standardized interface for interacting with Anthropic's Claude models,\n * including chat completions, streaming responses, and vision capabilities.\n * Note: Claude models do not support embeddings - use OpenAI or another provider for that.\n */\n\nimport { rateLimitErrorFrom } from '../rate-limit';\nimport {\n normalizeBaseAIOptions,\n normalizeChatOptions,\n type PreparedRequestControls,\n prepareRequestControls,\n} from '../safety';\nimport { parseToolArguments } from '../tool-messages';\nimport type {\n AICapabilities,\n AIInterface,\n AIMessage,\n AIModel,\n AIResponse,\n AIThinkingBlock,\n AIToolCall,\n AnthropicOptions,\n ChatOptions,\n CompletionOptions,\n EmbeddingOptions,\n EmbeddingResponse,\n ImageDescriptionOptions,\n ImageEmbeddingOptions,\n ImageGenerationOptions,\n ImageGenerationResponse,\n MessageOptions,\n TokenUsage,\n TTSOptions,\n TTSResponse,\n VideoGenerationJob,\n VideoGenerationOptions,\n VideoGenerationResult,\n VideoGenerationStatusResult,\n Voice,\n VoiceCloneOptions,\n VoiceDesignOptions,\n VoiceListOptions,\n} from '../types';\nimport {\n AIError,\n AuthenticationError,\n ContextLengthError,\n extractTextContent,\n ModelNotFoundError,\n} from '../types';\nimport { emitUsage } from './usage';\n\ntype AnthropicContentBlock =\n | AIThinkingBlock\n | { type: 'text'; text: string }\n | {\n type: 'tool_use';\n id: string;\n name: string;\n input: Record<string, unknown>;\n }\n | { type: 'tool_result'; tool_use_id: string; content: string };\n\ninterface AnthropicMessage {\n role: 'user' | 'assistant';\n content: string | AnthropicContentBlock[];\n}\n\n// Note: This implementation will require @anthropic-ai/sdk package\n// For now, this is a placeholder that defines the interface\n\n/**\n * Anthropic Claude provider implementation that handles all interactions with Anthropic's API.\n * Supports Claude models, streaming, vision capabilities, and function calling.\n * Does not support embeddings (use OpenAI or another provider for embeddings).\n */\nexport class AnthropicProvider implements AIInterface {\n private options: AnthropicOptions;\n private client: any; // Will be Anthropic instance from @anthropic-ai/sdk\n\n /**\n * Creates a new Anthropic provider instance\n * @param options - Configuration options for the Anthropic provider\n */\n constructor(options: AnthropicOptions) {\n this.options = normalizeBaseAIOptions({\n defaultModel: 'claude-3-5-sonnet-20241022',\n anthropicVersion: '2023-06-01',\n ...options,\n });\n\n // Initialize Anthropic client\n this.initializeClientSync();\n }\n\n private initializeClientSync() {\n try {\n // Dynamic import in constructor - this will work if the package is installed\n import('@anthropic-ai/sdk')\n .then(({ Anthropic }) => {\n this.client = new Anthropic({\n apiKey: this.options.apiKey,\n baseURL: this.options.baseUrl,\n timeout: this.options.timeout,\n maxRetries: this.options.maxRetries,\n defaultHeaders: {\n 'anthropic-version': this.options.anthropicVersion,\n ...this.options.headers,\n },\n });\n })\n .catch(() => {\n // Client will be null and we'll handle it in methods\n });\n } catch (_error) {\n // Client will be null and we'll handle it in methods\n }\n }\n\n /**\n * Ensures the Anthropic client is initialized by dynamically importing the SDK\n * @throws {AIError} When the Anthropic SDK cannot be loaded\n * @private\n */\n private async ensureClient() {\n if (!this.client) {\n try {\n const { Anthropic } = await import('@anthropic-ai/sdk');\n this.client = new Anthropic({\n apiKey: this.options.apiKey,\n baseURL: this.options.baseUrl,\n timeout: this.options.timeout,\n maxRetries: this.options.maxRetries,\n defaultHeaders: {\n 'anthropic-version': this.options.anthropicVersion,\n ...this.options.headers,\n },\n });\n } catch (_error) {\n throw new AIError(\n 'Failed to initialize Anthropic client. Make sure @anthropic-ai/sdk is installed.',\n 'INITIALIZATION_ERROR',\n 'anthropic',\n );\n }\n }\n }\n\n /**\n * Generate a chat completion using Claude models\n * @param messages - Array of conversation messages\n * @param options - Optional configuration for the chat completion\n * @returns Promise resolving to the AI response with content and metadata\n * @throws {AIError} When the API request fails or SDK is not available\n *\n * @example\n * ```typescript\n * const response = await provider.chat([\n * { role: 'system', content: 'You are a helpful assistant.' },\n * { role: 'user', content: 'Explain quantum computing' }\n * ], {\n * model: 'claude-3-5-sonnet-20241022',\n * maxTokens: 1000\n * });\n * ```\n */\n async chat(\n messages: AIMessage[],\n options: ChatOptions = {},\n ): Promise<AIResponse> {\n const startTime = Date.now();\n let controls: PreparedRequestControls | undefined;\n try {\n await this.ensureClient();\n\n const { system, anthropicMessages } =\n this.mapMessagesToAnthropic(messages);\n\n const model = options.model || this.options.defaultModel;\n options = normalizeChatOptions(this.options, options, 'anthropic', model);\n controls = prepareRequestControls(this.options, options);\n\n // Build request parameters\n const requestParams: Record<string, any> = {\n model,\n messages: anthropicMessages,\n max_tokens: options.maxTokens,\n temperature: options.temperature,\n top_p: options.topP,\n stop_sequences: Array.isArray(options.stop)\n ? options.stop\n : options.stop\n ? [options.stop]\n : undefined,\n system: system || undefined,\n ...this.mapToolParams(options, anthropicMessages),\n stream: false,\n };\n const thinking = this.mapThinking(options, anthropicMessages);\n if (thinking) {\n requestParams.thinking = thinking;\n }\n\n // Add response format if specified\n if (options.responseFormat?.type === 'json_object') {\n const jsonInstruction =\n '\\n\\nIMPORTANT: You must respond with valid JSON only. Do not include any explanatory text outside the JSON object.';\n requestParams.system = requestParams.system\n ? requestParams.system + jsonInstruction\n : jsonInstruction.trim();\n }\n\n const response = await this.client.messages.create(requestParams, {\n signal: controls.signal,\n timeout: controls.timeout,\n });\n\n // Extract text content and tool calls from response\n const textContent = response.content\n .filter((block: any) => block.type === 'text')\n .map((block: any) => block.text)\n .join('');\n\n const toolCalls: AIToolCall[] = response.content\n .filter((block: any) => block.type === 'tool_use')\n .map((block: any) => ({\n id: block.id,\n type: 'function' as const,\n function: {\n name: block.name,\n arguments: JSON.stringify(block.input),\n },\n }));\n\n // Extended thinking: the replayed tool_use turn must start with these\n // blocks (signatures intact), so they ride on the first tool call.\n const thinkingBlocks = extractThinkingBlocks(response.content);\n if (toolCalls.length > 0 && thinkingBlocks.length > 0) {\n toolCalls[0].thinkingBlocks = thinkingBlocks;\n }\n\n const usage: TokenUsage = {\n promptTokens: response.usage.input_tokens,\n completionTokens: response.usage.output_tokens,\n totalTokens: response.usage.input_tokens + response.usage.output_tokens,\n };\n emitUsage(\n this.options,\n 'anthropic',\n 'chat',\n response.model || model,\n usage,\n startTime,\n options.usageTags,\n );\n\n return {\n content: textContent,\n model: response.model,\n finishReason: this.mapFinishReason(response.stop_reason),\n usage,\n toolCalls: toolCalls.length > 0 ? toolCalls : undefined,\n };\n } catch (error) {\n if (controls?.didTimeout()) {\n throw new AIError(\n `AI request timed out after ${controls.timeout}ms`,\n 'AI_TIMEOUT',\n 'anthropic',\n options.model,\n );\n }\n if (options.signal?.aborted) {\n throw new AIError(\n 'AI request aborted by caller',\n 'AI_ABORTED',\n 'anthropic',\n options.model,\n );\n }\n throw this.mapError(error);\n } finally {\n controls?.cleanup();\n }\n }\n\n async complete(\n prompt: string,\n options: CompletionOptions = {},\n ): Promise<AIResponse> {\n return this.chat([{ role: 'user', content: prompt }], {\n model: options.model,\n maxTokens: options.maxTokens,\n temperature: options.temperature,\n topP: options.topP,\n n: options.n,\n stop: options.stop,\n stream: options.stream,\n onProgress: options.onProgress,\n signal: options.signal,\n timeout: options.timeout,\n reasoning: options.reasoning,\n usageTags: options.usageTags,\n continueOnLength: options.continueOnLength,\n });\n }\n\n /**\n * Simple message interface for single-turn interactions with optional history\n *\n * @param text - The message text to send\n * @param options - Configuration options including history, model, etc.\n * @returns Promise resolving to the response content string\n *\n * @example\n * ```typescript\n * // Simple usage\n * const response = await provider.message('Hello!');\n *\n * // With history\n * const response = await provider.message('What was my question?', {\n * history: [\n * { role: 'user', content: 'What is 2+2?' },\n * { role: 'assistant', content: '4' }\n * ]\n * });\n * ```\n */\n async message(text: string, options: MessageOptions = {}): Promise<string> {\n // Build messages array from history + current message\n const messages: AIMessage[] = [\n ...(options.history || []),\n { role: options.role || 'user', content: text },\n ];\n\n const response = await this.chat(messages, {\n model: options.model,\n maxTokens: options.maxTokens,\n temperature: options.temperature,\n topP: options.topP,\n stop: options.stop,\n stream: options.stream,\n frequencyPenalty: options.frequencyPenalty,\n presencePenalty: options.presencePenalty,\n responseFormat: options.responseFormat,\n seed: options.seed,\n tools: options.tools,\n toolChoice: options.toolChoice,\n onProgress: options.onProgress,\n signal: options.signal,\n timeout: options.timeout,\n reasoning: options.reasoning,\n usageTags: options.usageTags,\n continueOnLength: options.continueOnLength,\n });\n\n return response.content;\n }\n\n async embed(\n _text: string | string[],\n _options: EmbeddingOptions = {},\n ): Promise<EmbeddingResponse> {\n // Anthropic Claude doesn't provide embeddings API\n throw new AIError(\n 'Anthropic Claude does not support embeddings. Use OpenAI or another provider for embeddings.',\n 'NOT_SUPPORTED',\n 'anthropic',\n );\n }\n\n async embedImage(\n _image: string | Buffer,\n _options: ImageEmbeddingOptions = {},\n ): Promise<EmbeddingResponse> {\n throw new AIError(\n 'Anthropic Claude does not support image embeddings. Use OpenAI or Gemini.',\n 'NOT_SUPPORTED',\n 'anthropic',\n );\n }\n\n async describeImage(\n _image: string | Buffer,\n _prompt?: string,\n _options: ImageDescriptionOptions = {},\n ): Promise<string> {\n // Note: Claude does support vision, but we're keeping this as a stub for now\n // A full implementation could use the chat API with image content\n throw new AIError(\n 'Image description is not yet implemented for Anthropic. Use OpenAI or Gemini.',\n 'NOT_IMPLEMENTED',\n 'anthropic',\n );\n }\n\n async generateImage(\n _prompt: string,\n _options: ImageGenerationOptions = {},\n ): Promise<ImageGenerationResponse> {\n throw new AIError(\n 'Anthropic Claude does not support image generation. Use OpenAI or Gemini.',\n 'NOT_SUPPORTED',\n 'anthropic',\n );\n }\n\n /**\n * Streams a chat completion as text chunks.\n *\n * Streams yield text only and never surface tool calls, so `options.tools`\n * and `options.toolChoice` are ignored: tools are declared only when the\n * replayed history contains `tool_use` blocks (Anthropic requires it), with\n * `tool_choice: { type: 'none' }`. Use `chat()` for rounds that may call\n * tools.\n */\n async *stream(\n messages: AIMessage[],\n options: ChatOptions = {},\n ): AsyncIterable<string> {\n const startTime = Date.now();\n let controls: PreparedRequestControls | undefined;\n try {\n await this.ensureClient();\n\n const { system, anthropicMessages } =\n this.mapMessagesToAnthropic(messages);\n\n const model = options.model || this.options.defaultModel;\n options = normalizeChatOptions(this.options, options, 'anthropic', model);\n controls = prepareRequestControls(this.options, options);\n\n const requestParams: Record<string, any> = {\n model,\n messages: anthropicMessages,\n max_tokens: options.maxTokens,\n temperature: options.temperature,\n top_p: options.topP,\n stop_sequences: Array.isArray(options.stop)\n ? options.stop\n : options.stop\n ? [options.stop]\n : undefined,\n system: system || undefined,\n // stream() yields text only, so a tool call would be lost: declare\n // tools only when the replayed history requires it, with\n // tool_choice none.\n ...this.mapHistoryToolParams(anthropicMessages),\n stream: true,\n };\n const thinking = this.mapThinking(options, anthropicMessages);\n if (thinking) {\n requestParams.thinking = thinking;\n }\n const stream = await this.client.messages.create(requestParams, {\n signal: controls.signal,\n timeout: controls.timeout,\n });\n\n let streamStopReason: string | null = null;\n for await (const chunk of stream) {\n if (chunk.type === 'message_delta' && chunk.delta?.stop_reason) {\n streamStopReason = chunk.delta.stop_reason;\n }\n if (\n chunk.type === 'content_block_delta' &&\n chunk.delta.type === 'text_delta'\n ) {\n if (options.onProgress) {\n options.onProgress(chunk.delta.text);\n }\n yield chunk.delta.text;\n }\n }\n options.onFinishReason?.(\n this.mapFinishReason(streamStopReason) ?? 'stop',\n );\n\n emitUsage(\n this.options,\n 'anthropic',\n 'stream',\n model!,\n undefined,\n startTime,\n options.usageTags,\n );\n } catch (error) {\n if (controls?.didTimeout()) {\n throw new AIError(\n `AI request timed out after ${controls.timeout}ms`,\n 'AI_TIMEOUT',\n 'anthropic',\n options.model,\n );\n }\n if (options.signal?.aborted) {\n throw new AIError(\n 'AI request aborted by caller',\n 'AI_ABORTED',\n 'anthropic',\n options.model,\n );\n }\n throw this.mapError(error);\n } finally {\n controls?.cleanup();\n }\n }\n\n async countTokens(text: string): Promise<number> {\n // Anthropic doesn't provide a direct token counting API\n // This is an approximation - Claude uses a different tokenizer than OpenAI\n return Math.ceil(text.length / 3.5); // Slightly different ratio for Claude\n }\n\n async getModels(): Promise<AIModel[]> {\n // Return static list of known Claude models\n return [\n {\n id: 'claude-3-5-sonnet-20241022',\n name: 'Claude 3.5 Sonnet',\n description: 'Most intelligent Claude model with balanced performance',\n contextLength: 200000,\n capabilities: ['text', 'chat', 'vision', 'functions'],\n supportsFunctions: true,\n supportsVision: true,\n },\n {\n id: 'claude-3-5-haiku-20241022',\n name: 'Claude 3.5 Haiku',\n description: 'Fastest Claude model for simple tasks',\n contextLength: 200000,\n capabilities: ['text', 'chat', 'vision'],\n supportsFunctions: true,\n supportsVision: true,\n },\n {\n id: 'claude-3-opus-20240229',\n name: 'Claude 3 Opus',\n description: 'Most powerful Claude model for complex tasks',\n contextLength: 200000,\n capabilities: ['text', 'chat', 'vision', 'functions'],\n supportsFunctions: true,\n supportsVision: true,\n },\n {\n id: 'claude-3-sonnet-20240229',\n name: 'Claude 3 Sonnet',\n description: 'Balanced Claude model for most tasks',\n contextLength: 200000,\n capabilities: ['text', 'chat', 'vision'],\n supportsFunctions: true,\n supportsVision: true,\n },\n {\n id: 'claude-3-haiku-20240307',\n name: 'Claude 3 Haiku',\n description: 'Fast Claude model for simple tasks',\n contextLength: 200000,\n capabilities: ['text', 'chat', 'vision'],\n supportsFunctions: false,\n supportsVision: true,\n },\n ];\n }\n\n async getCapabilities(): Promise<AICapabilities> {\n return {\n chat: true,\n completion: true,\n embeddings: false, // Claude doesn't support embeddings\n streaming: true,\n functions: true,\n vision: true,\n fineTuning: false,\n imageEmbeddings: false,\n imageGeneration: false,\n videoGeneration: false,\n tts: false,\n voiceCloning: false,\n voiceDesign: false,\n maxContextLength: 200000,\n supportedOperations: [\n 'chat',\n 'completion',\n 'streaming',\n 'functions',\n 'vision',\n ],\n };\n }\n\n // ============================================================================\n // Video Generation Methods (Not supported - use gemini, byteplus-modelark,\n // or openai-compat-video provider)\n // ============================================================================\n\n async submitVideoGenerationJob(\n _options: VideoGenerationOptions,\n ): Promise<VideoGenerationJob> {\n throw new AIError(\n 'Video generation is not supported by Anthropic provider. Use gemini, byteplus-modelark, or openai-compat-video provider.',\n 'NOT_IMPLEMENTED',\n 'anthropic',\n );\n }\n\n async getVideoGenerationJob(\n _handle: VideoGenerationJob,\n ): Promise<VideoGenerationStatusResult> {\n throw new AIError(\n 'Video generation is not supported by Anthropic provider. Use gemini, byteplus-modelark, or openai-compat-video provider.',\n 'NOT_IMPLEMENTED',\n 'anthropic',\n );\n }\n\n async fetchVideoGenerationResult(\n _handle: VideoGenerationJob,\n ): Promise<VideoGenerationResult> {\n throw new AIError(\n 'Video generation is not supported by Anthropic provider. Use gemini, byteplus-modelark, or openai-compat-video provider.',\n 'NOT_IMPLEMENTED',\n 'anthropic',\n );\n }\n\n async cancelVideoGenerationJob(_handle: VideoGenerationJob): Promise<void> {\n throw new AIError(\n 'Video generation is not supported by Anthropic provider. Use gemini, byteplus-modelark, or openai-compat-video provider.',\n 'NOT_IMPLEMENTED',\n 'anthropic',\n );\n }\n\n async validateVideoGenerationAccess(): Promise<boolean> {\n throw new AIError(\n 'Video generation is not supported by Anthropic provider. Use gemini, byteplus-modelark, or openai-compat-video provider.',\n 'NOT_IMPLEMENTED',\n 'anthropic',\n );\n }\n\n // ============================================================================\n // TTS Methods (Not supported - use Qwen3-TTS provider)\n // ============================================================================\n\n async synthesizeSpeech(\n _text: string,\n _options?: TTSOptions,\n ): Promise<TTSResponse> {\n throw new AIError(\n 'TTS is not supported by Anthropic provider. Use Qwen3-TTS provider.',\n 'NOT_IMPLEMENTED',\n 'anthropic',\n );\n }\n\n streamSpeech(_text: string, _options?: TTSOptions): AsyncIterable<Buffer> {\n const error = new AIError(\n 'TTS streaming is not supported by Anthropic provider. Use Qwen3-TTS provider.',\n 'NOT_IMPLEMENTED',\n 'anthropic',\n );\n return {\n [Symbol.asyncIterator]: () => ({\n next: () => Promise.reject(error),\n }),\n };\n }\n\n async cloneVoice(_options: VoiceCloneOptions): Promise<Voice> {\n throw new AIError(\n 'Voice cloning is not supported by Anthropic provider. Use Qwen3-TTS provider.',\n 'NOT_IMPLEMENTED',\n 'anthropic',\n );\n }\n\n async designVoice(_options: VoiceDesignOptions): Promise<Voice> {\n throw new AIError(\n 'Voice design is not supported by Anthropic provider. Use Qwen3-TTS provider.',\n 'NOT_IMPLEMENTED',\n 'anthropic',\n );\n }\n\n async getVoices(_options?: VoiceListOptions): Promise<Voice[]> {\n throw new AIError(\n 'Voice listing is not supported by Anthropic provider. Use Qwen3-TTS provider.',\n 'NOT_IMPLEMENTED',\n 'anthropic',\n );\n }\n\n /**\n * Maps internal messages to Anthropic Messages API turns.\n *\n * Assistant `tool_calls` become `tool_use` blocks and `role: 'tool'`\n * results become `tool_result` blocks paired by `tool_call_id`\n * (`tool_use_id`). Consecutive tool results are grouped into one user turn,\n * as Anthropic requires every result for a turn to follow it directly.\n * Only answered calls are replayed as `tool_use`, and only results whose\n * `tool_call_id` matches a replayed call become `tool_result`. A result\n * without `tool_call_id`, or one answering no replayed call, falls back to\n * plain text (and a call left unanswered keeps only its text).\n */\n private mapMessagesToAnthropic(messages: AIMessage[]): {\n system?: string;\n anthropicMessages: AnthropicMessage[];\n } {\n // Anthropic handles system messages separately\n let system: string | undefined;\n const anthropicMessages: AnthropicMessage[] = [];\n const answeredToolCallIds = new Set(\n messages\n .filter((message) => message.role === 'tool' && message.tool_call_id)\n .map((message) => message.tool_call_id as string),\n );\n // Calls replayed as tool_use: those with an answer. Only results for\n // these ids become tool_result blocks; any other result is an orphan\n // Anthropic would reject, so it falls back to plain text.\n const replayedToolUseIds = new Set<string>();\n for (const message of messages) {\n if (message.role !== 'assistant') continue;\n for (const toolCall of message.tool_calls || []) {\n if (answeredToolCallIds.has(toolCall.id)) {\n replayedToolUseIds.add(toolCall.id);\n }\n }\n }\n\n for (const message of messages) {\n const textContent = extractTextContent(message.content);\n if (message.role === 'system') {\n // Combine multiple system messages\n system = system ? `${system}\\n\\n${textContent}` : textContent;\n continue;\n }\n\n if (\n message.role === 'tool' &&\n message.tool_call_id &&\n replayedToolUseIds.has(message.tool_call_id)\n ) {\n const block: AnthropicContentBlock = {\n type: 'tool_result',\n tool_use_id: message.tool_call_id,\n content: textContent,\n };\n const previous = anthropicMessages[anthropicMessages.length - 1];\n if (\n previous?.role === 'user' &&\n Array.isArray(previous.content) &&\n previous.content.every((part) => part.type === 'tool_result')\n ) {\n previous.content.push(block);\n } else {\n anthropicMessages.push({ role: 'user', content: [block] });\n }\n continue;\n }\n\n const toolCalls =\n message.role === 'assistant'\n ? (message.tool_calls || []).filter((toolCall) =>\n answeredToolCallIds.has(toolCall.id),\n )\n : [];\n if (toolCalls.length > 0) {\n const content: AnthropicContentBlock[] = [];\n for (const toolCall of toolCalls) {\n for (const block of toolCall.thinkingBlocks || []) {\n content.push({ ...block });\n }\n }\n if (textContent) {\n content.push({ type: 'text', text: textContent });\n }\n for (const toolCall of toolCalls) {\n content.push({\n type: 'tool_use',\n id: toolCall.id,\n name: toolCall.function.name,\n input: parseToolArguments(toolCall.function.arguments),\n });\n }\n anthropicMessages.push({ role: 'assistant', content });\n continue;\n }\n\n anthropicMessages.push({\n role: message.role === 'assistant' ? 'assistant' : 'user',\n content: textContent,\n });\n }\n\n return { system, anthropicMessages };\n }\n\n /**\n * Builds the `tools` / `tool_choice` request fields.\n *\n * Anthropic rejects a request whose history contains `tool_use` or\n * `tool_result` blocks unless `tools` is declared. A tool loop's final,\n * tool-less round (no `tools`, typically `toolChoice: 'none'`) still\n * replays that history, so when the caller declares no tools but the\n * history uses some, this declares a minimal definition for each tool the\n * history references and sets `tool_choice: { type: 'none' }` so the model\n * answers in text instead of calling them.\n */\n private mapToolParams(\n options: ChatOptions,\n anthropicMessages: AnthropicMessage[],\n ): { tools?: Record<string, any>[]; tool_choice?: Record<string, any> } {\n const tools = this.mapTools(options);\n if (tools) {\n return { tools, tool_choice: this.mapToolChoice(options.toolChoice) };\n }\n return this.mapHistoryToolParams(anthropicMessages);\n }\n\n /**\n * Declares a minimal definition for each tool the replayed history\n * references, with `tool_choice: { type: 'none' }`, or nothing when the\n * history has no `tool_use` blocks. Used for tool-less rounds and for\n * every stream (streams never yield tool calls).\n */\n private mapHistoryToolParams(anthropicMessages: AnthropicMessage[]): {\n tools?: Record<string, any>[];\n tool_choice?: Record<string, any>;\n } {\n // mapMessagesToAnthropic emits tool_result only for ids it replayed as\n // tool_use (orphan results become text), so tool_use names cover every\n // tool the history references.\n const historyToolNames = new Set<string>();\n for (const message of anthropicMessages) {\n if (!Array.isArray(message.content)) continue;\n for (const block of message.content) {\n if (block.type === 'tool_use') historyToolNames.add(block.name);\n }\n }\n if (historyToolNames.size === 0) {\n return {};\n }\n\n return {\n tools: [...historyToolNames].map((name) => ({\n name,\n description:\n 'Used earlier in this conversation; not available for this turn.',\n input_schema: { type: 'object' },\n })),\n tool_choice: { type: 'none' },\n };\n }\n\n /**\n * Builds the `thinking` request field for `options.reasoning.maxTokens`.\n *\n * While thinking is enabled, Anthropic requires the assistant turn of an\n * in-progress tool loop (the last assistant turn, when it holds `tool_use`)\n * to start with its thinking blocks. They are replayed from\n * `AIToolCall.thinkingBlocks`; when that turn has none (the history came\n * from another provider, a store that dropped the field, or a call made\n * without thinking), thinking is left off for this request rather than\n * sending a request Anthropic would reject.\n */\n private mapThinking(\n options: ChatOptions,\n anthropicMessages: AnthropicMessage[],\n ): { type: 'enabled'; budget_tokens: number } | undefined {\n const budget = options.reasoning?.maxTokens || 0;\n if (budget <= 0) return undefined;\n\n const lastAssistant = [...anthropicMessages]\n .reverse()\n .find((message) => message.role === 'assistant');\n if (\n lastAssistant &&\n Array.isArray(lastAssistant.content) &&\n lastAssistant.content.some((block) => block.type === 'tool_use')\n ) {\n const firstType = lastAssistant.content[0]?.type;\n if (firstType !== 'thinking' && firstType !== 'redacted_thinking') {\n return undefined;\n }\n }\n\n return { type: 'enabled', budget_tokens: budget };\n }\n\n private mapTools(options: ChatOptions): Record<string, any>[] | undefined {\n return options.tools && options.tools.length > 0\n ? options.tools.map((tool) => ({\n name: tool.function.name,\n description: tool.function.description || '',\n input_schema: tool.function.parameters || { type: 'object' },\n }))\n : undefined;\n }\n\n private mapToolChoice(\n toolChoice?:\n | 'auto'\n | 'none'\n | { type: 'function'; function: { name: string } },\n ): any {\n if (!toolChoice || toolChoice === 'auto') {\n return { type: 'auto' };\n }\n\n if (toolChoice === 'none') {\n return { type: 'none' };\n }\n\n if (typeof toolChoice === 'object' && toolChoice.type === 'function') {\n return {\n type: 'tool',\n name: toolChoice.function.name,\n };\n }\n\n return { type: 'auto' };\n }\n\n private mapFinishReason(reason: string | null): AIResponse['finishReason'] {\n switch (reason) {\n case 'end_turn':\n return 'stop';\n case 'max_tokens':\n return 'length';\n case 'stop_sequence':\n return 'stop';\n case 'tool_use':\n return 'tool_calls';\n default:\n return 'stop';\n }\n }\n\n private mapError(error: unknown): AIError {\n if (error instanceof AIError) {\n return error;\n }\n\n // Map common HTTP status codes from Anthropic API\n if (typeof error === 'object' && error !== null && 'status' in error) {\n const apiError = error as { status: number; message?: string };\n switch (apiError.status) {\n case 401:\n return new AuthenticationError('anthropic');\n case 429:\n return rateLimitErrorFrom('anthropic', error);\n case 404:\n return new ModelNotFoundError(\n apiError.message || 'Model not found',\n 'anthropic',\n );\n case 413:\n return new ContextLengthError('anthropic');\n }\n }\n\n const errorMessage =\n error instanceof Error\n ? error.message\n : 'Unknown Anthropic error occurred';\n return new AIError(errorMessage, 'UNKNOWN_ERROR', 'anthropic');\n }\n}\n\n/**\n * Thinking and redacted-thinking blocks from an Anthropic response, copied\n * with only the fields the API accepts back.\n */\nfunction extractThinkingBlocks(content: any[]): AIThinkingBlock[] {\n const blocks: AIThinkingBlock[] = [];\n for (const block of content || []) {\n if (block?.type === 'thinking') {\n blocks.push({\n type: 'thinking',\n thinking: block.thinking,\n signature: block.signature,\n });\n } else if (block?.type === 'redacted_thinking') {\n blocks.push({ type: 'redacted_thinking', data: block.data });\n }\n }\n return blocks;\n}\n"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { b as extractTextContent, c as normalizeImageGenerationOptions, f as AuthenticationError, g as ModelNotFoundError, l as prepareRequestControls, m as ContextLengthError, o as normalizeBaseAIOptions, s as normalizeChatOptions, t as emitUsage, u as AIError } from "./usage-
|
|
2
|
-
import { n as rateLimitErrorFrom } from "./rate-limit-
|
|
1
|
+
import { b as extractTextContent, c as normalizeImageGenerationOptions, f as AuthenticationError, g as ModelNotFoundError, l as prepareRequestControls, m as ContextLengthError, o as normalizeBaseAIOptions, s as normalizeChatOptions, t as emitUsage, u as AIError } from "./usage-B9gPCWSa.js";
|
|
2
|
+
import { n as rateLimitErrorFrom } from "./rate-limit-BkK4-hXY.js";
|
|
3
3
|
//#region src/shared/providers/bedrock.ts
|
|
4
4
|
/**
|
|
5
5
|
* AWS Bedrock provider implementation
|
|
@@ -761,4 +761,4 @@ var BedrockProvider = class {
|
|
|
761
761
|
//#endregion
|
|
762
762
|
export { BedrockProvider };
|
|
763
763
|
|
|
764
|
-
//# sourceMappingURL=bedrock-
|
|
764
|
+
//# sourceMappingURL=bedrock-DNkxz3ow.js.map
|