@alvin0/ai-agent-sdk-protocol-anthropic-messages 0.1.3 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +104 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +74 -22
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -4,7 +4,8 @@ import { ModelTarget, ResolvedModelInfo } from "@alvin0/ai-agent-sdk-core/provid
|
|
|
4
4
|
/** The request fields a pure wire protocol is allowed to inspect. */
|
|
5
5
|
interface ProtocolRequest {
|
|
6
6
|
readonly options: GenerateOptions;
|
|
7
|
-
|
|
7
|
+
/** Absent when neither the caller, the model, nor the route names an output cap. */
|
|
8
|
+
readonly maxTokens?: number;
|
|
8
9
|
}
|
|
9
10
|
/** One decoded SSE event, expressed without depending on an HTTP transport. */
|
|
10
11
|
interface ProtocolSseEvent {
|
|
@@ -65,8 +66,19 @@ type WireDocumentSource = {
|
|
|
65
66
|
type: 'file';
|
|
66
67
|
file_id: string;
|
|
67
68
|
};
|
|
69
|
+
/**
|
|
70
|
+
* A cache breakpoint. Marks "everything up through this block" as worth
|
|
71
|
+
* keeping warm — this API charges a premium to WRITE the cache once and a
|
|
72
|
+
* steep discount to READ it on every later request that repeats the same
|
|
73
|
+
* prefix verbatim, which is exactly what a multi-turn conversation does.
|
|
74
|
+
*/
|
|
75
|
+
interface WireCacheControl {
|
|
76
|
+
type: 'ephemeral';
|
|
77
|
+
/** Defaults to this API's own default (5 minutes) when omitted. */
|
|
78
|
+
ttl?: '5m' | '1h';
|
|
79
|
+
}
|
|
68
80
|
/** A request-side content block. */
|
|
69
|
-
type WireRequestBlock = {
|
|
81
|
+
type WireRequestBlock = ({
|
|
70
82
|
type: 'text';
|
|
71
83
|
text: string;
|
|
72
84
|
citations?: WireCitation[];
|
|
@@ -103,7 +115,9 @@ type WireRequestBlock = {
|
|
|
103
115
|
} | {
|
|
104
116
|
type: 'redacted_thinking';
|
|
105
117
|
data: string;
|
|
106
|
-
} | WireServerToolUseBlock | WireWebSearchToolResultBlock
|
|
118
|
+
} | WireServerToolUseBlock | WireWebSearchToolResultBlock) & {
|
|
119
|
+
cache_control?: WireCacheControl;
|
|
120
|
+
};
|
|
107
121
|
interface WireServerToolUseBlock {
|
|
108
122
|
type: 'server_tool_use';
|
|
109
123
|
id: string;
|
|
@@ -154,7 +168,15 @@ interface WireWebSearchTool {
|
|
|
154
168
|
timezone?: string;
|
|
155
169
|
};
|
|
156
170
|
}
|
|
157
|
-
type WireTool = WireFunctionTool | WireWebSearchTool
|
|
171
|
+
type WireTool = (WireFunctionTool | WireWebSearchTool) & {
|
|
172
|
+
cache_control?: WireCacheControl;
|
|
173
|
+
};
|
|
174
|
+
/** A `system` block, when caching needs one to attach a breakpoint to. */
|
|
175
|
+
interface WireSystemBlock {
|
|
176
|
+
type: 'text';
|
|
177
|
+
text: string;
|
|
178
|
+
cache_control?: WireCacheControl;
|
|
179
|
+
}
|
|
158
180
|
/** How the model must choose among the offered tools. */
|
|
159
181
|
type WireToolChoice = {
|
|
160
182
|
type: 'auto';
|
|
@@ -168,16 +190,20 @@ type WireToolChoice = {
|
|
|
168
190
|
};
|
|
169
191
|
/** Extended-thinking configuration. */
|
|
170
192
|
type WireThinking = {
|
|
193
|
+
type: 'adaptive';
|
|
194
|
+
} | {
|
|
171
195
|
type: 'enabled';
|
|
172
196
|
budget_tokens: number;
|
|
173
197
|
} | {
|
|
174
198
|
type: 'disabled';
|
|
175
199
|
};
|
|
176
200
|
interface WireOutputConfig {
|
|
177
|
-
format
|
|
201
|
+
format?: {
|
|
178
202
|
type: 'json_schema';
|
|
179
203
|
schema: Readonly<Record<string, unknown>>;
|
|
180
204
|
};
|
|
205
|
+
/** The GA reasoning-effort field: `"low" | "medium" | "high" | "xhigh" | "max"`, sent verbatim. */
|
|
206
|
+
effort?: string;
|
|
181
207
|
}
|
|
182
208
|
/** The request body. */
|
|
183
209
|
interface WireRequest {
|
|
@@ -185,7 +211,8 @@ interface WireRequest {
|
|
|
185
211
|
/** REQUIRED by this API, unlike most others — the adapter always resolves one. */
|
|
186
212
|
max_tokens: number;
|
|
187
213
|
messages: WireMessage[];
|
|
188
|
-
|
|
214
|
+
/** A plain string, or blocks when a cache breakpoint needs to attach to one. */
|
|
215
|
+
system?: string | WireSystemBlock[];
|
|
189
216
|
tools?: WireTool[];
|
|
190
217
|
tool_choice?: WireToolChoice;
|
|
191
218
|
temperature?: number;
|
|
@@ -308,17 +335,60 @@ interface AnthropicReasoningState {
|
|
|
308
335
|
/** Opaque payload of a redacted block. */
|
|
309
336
|
data?: string;
|
|
310
337
|
}
|
|
311
|
-
/** How a reasoning effort becomes a thinking token budget
|
|
338
|
+
/** How a reasoning effort becomes a thinking token budget, for `reasoningFormat: 'thinking-budget'`. */
|
|
312
339
|
type ThinkingBudgets = Readonly<Record<string, number>>;
|
|
340
|
+
/** Which field carries reasoning effort on the wire. */
|
|
341
|
+
type AnthropicReasoningFormat = 'output-config' | 'thinking-budget';
|
|
313
342
|
/** Options controlling how the request is built. */
|
|
314
343
|
interface AnthropicSerializeOptions {
|
|
315
|
-
/**
|
|
344
|
+
/**
|
|
345
|
+
* `'output-config'` (default, current models): effort is pass-through —
|
|
346
|
+
* sent verbatim as `output_config.effort`, exactly what the caller gave.
|
|
347
|
+
* `'thinking-budget'` (older models, or a gateway that only understands a
|
|
348
|
+
* token budget): effort is looked up in `budgets` and converted to
|
|
349
|
+
* `thinking.budget_tokens` instead — the SDK does the conversion because the
|
|
350
|
+
* endpoint has no `effort` field to receive the raw string at all.
|
|
351
|
+
*/
|
|
352
|
+
reasoningFormat?: AnthropicReasoningFormat;
|
|
353
|
+
/** Effort id to thinking-token budget; only consulted under `'thinking-budget'`. */
|
|
316
354
|
budgets: ThinkingBudgets;
|
|
355
|
+
/**
|
|
356
|
+
* Extended-thinking mode, sent only when set — omission means "say nothing",
|
|
357
|
+
* which is this API's own way of leaving the model's default behavior alone.
|
|
358
|
+
* Ignored under `'thinking-budget'`, which derives `thinking` from the effort instead.
|
|
359
|
+
*/
|
|
360
|
+
thinking?: 'adaptive' | 'disabled';
|
|
361
|
+
/**
|
|
362
|
+
* Mark the stable prefix of one request as a cache breakpoint: the system
|
|
363
|
+
* prompt, the last tool definition (if any), and every message but the
|
|
364
|
+
* newest — up to 3 of this API's 4-breakpoint ceiling, leaving one spare.
|
|
365
|
+
* A conversation resending its whole history on every turn (this API is
|
|
366
|
+
* stateless) pays full price for that history without this; with it, a
|
|
367
|
+
* later turn reads the unchanged prefix at a steep discount instead of
|
|
368
|
+
* paying to reprocess it.
|
|
369
|
+
*
|
|
370
|
+
* Off by default: not every account or Anthropic-COMPATIBLE gateway
|
|
371
|
+
* behind this same adapter understands `cache_control`, and a route that
|
|
372
|
+
* doesn't should not silently be asked to. See `dialectOf()` in
|
|
373
|
+
* `provider-anthropic/src/adapter.ts` for the live-discovered fallback
|
|
374
|
+
* that turns this off automatically, permanently, the first time a
|
|
375
|
+
* gateway rejects it.
|
|
376
|
+
*/
|
|
377
|
+
promptCaching?: boolean;
|
|
378
|
+
/** Cache breakpoint lifetime. Defaults to this API's own default (5 minutes). */
|
|
379
|
+
promptCachingTtl?: '5m' | '1h';
|
|
317
380
|
}
|
|
381
|
+
/**
|
|
382
|
+
* Last-resort `max_tokens`, used only when neither the caller, the model, nor
|
|
383
|
+
* the route names one. This API rejects a request that omits the field
|
|
384
|
+
* entirely, unlike most others — see {@link serializeAnthropicRequest}.
|
|
385
|
+
*/
|
|
386
|
+
declare const DEFAULT_MAX_TOKENS = 8192;
|
|
318
387
|
/**
|
|
319
388
|
* Build the Messages request body.
|
|
320
389
|
* @param request - the resolved request, model, and connection.
|
|
321
|
-
* @param options -
|
|
390
|
+
* @param options - which field carries effort, its budget table, and the
|
|
391
|
+
* explicit-thinking switch.
|
|
322
392
|
* @returns the wire body, ready to serialize.
|
|
323
393
|
*/
|
|
324
394
|
declare function serializeAnthropicRequest(request: ProtocolRequest, options: AnthropicSerializeOptions): WireRequest;
|
|
@@ -344,12 +414,35 @@ declare const ANTHROPIC_VERSION = "2023-06-01";
|
|
|
344
414
|
declare const DEFAULT_THINKING_BUDGETS: ThinkingBudgets;
|
|
345
415
|
/** Per-endpoint knobs of the Messages protocol. */
|
|
346
416
|
interface AnthropicDialect {
|
|
347
|
-
/**
|
|
417
|
+
/**
|
|
418
|
+
* Which field carries reasoning effort. `'output-config'` (default) is pure
|
|
419
|
+
* pass-through — the caller's effort string reaches `output_config.effort`
|
|
420
|
+
* unchanged, current GA behavior. `'thinking-budget'` is for an older model
|
|
421
|
+
* or a gateway that only understands a token budget: the SDK converts effort
|
|
422
|
+
* to `thinking.budget_tokens` using `budgets` instead of sending it raw.
|
|
423
|
+
*/
|
|
424
|
+
readonly reasoningFormat: AnthropicReasoningFormat;
|
|
425
|
+
/** Effort id to thinking-token budget; only consulted under `'thinking-budget'`. */
|
|
348
426
|
readonly budgets: ThinkingBudgets;
|
|
427
|
+
/**
|
|
428
|
+
* Extended-thinking mode, sent only when set. Independent of effort under
|
|
429
|
+
* `'output-config'` — omission leaves the model's own default thinking
|
|
430
|
+
* behavior alone rather than the SDK guessing one.
|
|
431
|
+
*/
|
|
432
|
+
readonly thinking?: 'adaptive' | 'disabled';
|
|
349
433
|
/** `anthropic-version` header value. */
|
|
350
434
|
readonly version: string;
|
|
351
435
|
/** Opt-in beta features, sent as `anthropic-beta`. */
|
|
352
436
|
readonly beta: readonly string[];
|
|
437
|
+
/**
|
|
438
|
+
* Marks the stable prefix (system, tools, everything but the newest
|
|
439
|
+
* message) as a cache breakpoint. See `AnthropicSerializeOptions`'s doc
|
|
440
|
+
* comment in `serialize.ts` for why, and off by default for the same
|
|
441
|
+
* "not every gateway understands this" reason `reasoningFormat` is opt-in.
|
|
442
|
+
*/
|
|
443
|
+
readonly promptCaching: boolean;
|
|
444
|
+
/** Cache breakpoint lifetime; unset defers to this API's own default. */
|
|
445
|
+
readonly promptCachingTtl?: '5m' | '1h';
|
|
353
446
|
}
|
|
354
447
|
interface RuntimeProtocolRequest extends ProtocolRequest {
|
|
355
448
|
readonly model: ResolvedModelInfo;
|
|
@@ -386,5 +479,5 @@ declare const anthropicMessagesProtocol: ProtocolDefinition<AnthropicDialect> &
|
|
|
386
479
|
*/
|
|
387
480
|
declare function translateAnthropicStream(events: AsyncIterable<ProtocolSseEvent>, displayName: string): AsyncGenerator<ProtocolStreamChunk>;
|
|
388
481
|
//#endregion
|
|
389
|
-
export { ANTHROPIC_MESSAGES_PROTOCOL_ID, ANTHROPIC_VERSION, type AnthropicDialect, type AnthropicMessagesProtocolDefinition, type AnthropicReasoningState, type AnthropicSerializeOptions, DEFAULT_THINKING_BUDGETS, type ProtocolDefinition, type ProtocolRequest, type ProtocolSseEvent, type ProtocolStreamChunk, type ThinkingBudgets, type WireCitation, type WireDelta, type WireDocumentSource, type WireErrorBody, type WireErrorResponse, type WireFunctionTool, type WireImageSource, type WireMessage, type WireOutputConfig, type WireRequest, type WireRequestBlock, type WireResponseBlock, type WireServerToolUseBlock, type WireStopReason, type WireStreamEvent, type WireThinking, type WireTool, type WireToolChoice, type WireToolResultContent, type WireUsage, type WireWebSearchTool, type WireWebSearchToolResultBlock, anthropicMessagesProtocol, serializeAnthropicRequest, translateAnthropicStream };
|
|
482
|
+
export { ANTHROPIC_MESSAGES_PROTOCOL_ID, ANTHROPIC_VERSION, type AnthropicDialect, type AnthropicMessagesProtocolDefinition, type AnthropicReasoningFormat, type AnthropicReasoningState, type AnthropicSerializeOptions, DEFAULT_MAX_TOKENS, DEFAULT_THINKING_BUDGETS, type ProtocolDefinition, type ProtocolRequest, type ProtocolSseEvent, type ProtocolStreamChunk, type ThinkingBudgets, type WireCacheControl, type WireCitation, type WireDelta, type WireDocumentSource, type WireErrorBody, type WireErrorResponse, type WireFunctionTool, type WireImageSource, type WireMessage, type WireOutputConfig, type WireRequest, type WireRequestBlock, type WireResponseBlock, type WireServerToolUseBlock, type WireStopReason, type WireStreamEvent, type WireSystemBlock, type WireThinking, type WireTool, type WireToolChoice, type WireToolResultContent, type WireUsage, type WireWebSearchTool, type WireWebSearchToolResultBlock, anthropicMessagesProtocol, serializeAnthropicRequest, translateAnthropicStream };
|
|
390
483
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/contract.ts","../src/wire.ts","../src/serialize.ts","../src/protocol.ts","../src/translate.ts"],"mappings":";;;;UAGiB;WACN,SAAS
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/contract.ts","../src/wire.ts","../src/serialize.ts","../src/protocol.ts","../src/translate.ts"],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -176,8 +176,13 @@ function requestBlocks(block) {
|
|
|
176
176
|
* Build the message list, merging consecutive same-role messages.
|
|
177
177
|
*
|
|
178
178
|
* See the module note for why merging matters.
|
|
179
|
+
* @param messages - the normalized conversation.
|
|
180
|
+
* @param cacheControl - when set, attached to the LAST block of the
|
|
181
|
+
* SECOND-TO-LAST wire message — everything but the newest turn, which is
|
|
182
|
+
* the only part of the history that changed since the previous request.
|
|
183
|
+
* A history of fewer than two wire messages has nothing stable to mark yet.
|
|
179
184
|
*/
|
|
180
|
-
function messagesOf(messages) {
|
|
185
|
+
function messagesOf(messages, cacheControl) {
|
|
181
186
|
const result = [];
|
|
182
187
|
for (const message of messages) {
|
|
183
188
|
if (message.role === "system") continue;
|
|
@@ -191,13 +196,30 @@ function messagesOf(messages) {
|
|
|
191
196
|
content: blocks
|
|
192
197
|
});
|
|
193
198
|
}
|
|
199
|
+
if (cacheControl !== void 0 && result.length >= 2) {
|
|
200
|
+
const lastBlock = result[result.length - 2]?.content.at(-1);
|
|
201
|
+
if (lastBlock !== void 0) lastBlock.cache_control = cacheControl;
|
|
202
|
+
}
|
|
194
203
|
return result;
|
|
195
204
|
}
|
|
196
|
-
/**
|
|
197
|
-
|
|
205
|
+
/**
|
|
206
|
+
* Collect the system prompt from the request plus any system-role messages.
|
|
207
|
+
* @param request - the resolved request.
|
|
208
|
+
* @param cacheControl - when set, the joined text comes back as ONE block
|
|
209
|
+
* carrying this breakpoint instead of a plain string — the system prompt is
|
|
210
|
+
* as stable a prefix as a conversation has, so it is always the first thing
|
|
211
|
+
* marked when caching is on.
|
|
212
|
+
*/
|
|
213
|
+
function systemOf(request, cacheControl) {
|
|
198
214
|
const fromMessages = request.options.messages.filter((message) => message.role === "system").flatMap((message) => message.content).filter((block) => block.type === "text").map((block) => block.text);
|
|
199
215
|
const joined = (request.options.system === void 0 ? fromMessages : [request.options.system, ...fromMessages]).join("\n\n");
|
|
200
|
-
|
|
216
|
+
if (joined.length === 0) return void 0;
|
|
217
|
+
if (cacheControl === void 0) return joined;
|
|
218
|
+
return [{
|
|
219
|
+
type: "text",
|
|
220
|
+
text: joined,
|
|
221
|
+
cache_control: cacheControl
|
|
222
|
+
}];
|
|
201
223
|
}
|
|
202
224
|
/** Map the neutral tool-choice vocabulary onto this API's. */
|
|
203
225
|
function toolChoiceOf(choice) {
|
|
@@ -240,13 +262,19 @@ function toolOf(tool) {
|
|
|
240
262
|
throw new ModelError(`Anthropic does not support the provider-native tool '${tool.name}'`, MODEL_ERROR_CODES.INVALID_REQUEST);
|
|
241
263
|
}
|
|
242
264
|
/**
|
|
243
|
-
*
|
|
265
|
+
* Last-resort `max_tokens`, used only when neither the caller, the model, nor
|
|
266
|
+
* the route names one. This API rejects a request that omits the field
|
|
267
|
+
* entirely, unlike most others — see {@link serializeAnthropicRequest}.
|
|
268
|
+
*/
|
|
269
|
+
const DEFAULT_MAX_TOKENS = 8192;
|
|
270
|
+
/**
|
|
271
|
+
* Resolve the `thinking` field under `reasoningFormat: 'thinking-budget'`.
|
|
244
272
|
*
|
|
245
273
|
* The budget must leave room for a real answer, so it is capped below
|
|
246
274
|
* `max_tokens` — this API requires `budget_tokens < max_tokens` and rejects the
|
|
247
275
|
* request otherwise.
|
|
248
276
|
*/
|
|
249
|
-
function
|
|
277
|
+
function thinkingFromBudget(effort, maxTokens, budgets) {
|
|
250
278
|
if (effort === void 0) return void 0;
|
|
251
279
|
const requested = budgets[effort];
|
|
252
280
|
if (requested === void 0 || requested <= 0) return { type: "disabled" };
|
|
@@ -256,35 +284,51 @@ function thinkingOf(effort, maxTokens, budgets) {
|
|
|
256
284
|
budget_tokens: capped
|
|
257
285
|
};
|
|
258
286
|
}
|
|
259
|
-
function outputConfig(format) {
|
|
260
|
-
|
|
261
|
-
return { format: {
|
|
287
|
+
function outputConfig(format, effort) {
|
|
288
|
+
const formatPart = format === void 0 || format.type === "text" ? void 0 : {
|
|
262
289
|
type: "json_schema",
|
|
263
290
|
schema: format.schema
|
|
264
|
-
}
|
|
291
|
+
};
|
|
292
|
+
if (formatPart === void 0 && effort === void 0) return void 0;
|
|
293
|
+
return {
|
|
294
|
+
...formatPart === void 0 ? {} : { format: formatPart },
|
|
295
|
+
...effort === void 0 ? {} : { effort }
|
|
296
|
+
};
|
|
265
297
|
}
|
|
266
298
|
/**
|
|
267
299
|
* Build the Messages request body.
|
|
268
300
|
* @param request - the resolved request, model, and connection.
|
|
269
|
-
* @param options -
|
|
301
|
+
* @param options - which field carries effort, its budget table, and the
|
|
302
|
+
* explicit-thinking switch.
|
|
270
303
|
* @returns the wire body, ready to serialize.
|
|
271
304
|
*/
|
|
272
305
|
function serializeAnthropicRequest(request, options) {
|
|
273
306
|
const { options: call } = request;
|
|
274
|
-
const
|
|
307
|
+
const cacheControl = options.promptCaching === true ? {
|
|
308
|
+
type: "ephemeral",
|
|
309
|
+
...options.promptCachingTtl === void 0 ? {} : { ttl: options.promptCachingTtl }
|
|
310
|
+
} : void 0;
|
|
311
|
+
const system = systemOf(request, cacheControl);
|
|
275
312
|
const tools = call.tools === void 0 || call.tools.length === 0 ? void 0 : call.tools.map(toolOf);
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
313
|
+
if (cacheControl !== void 0 && tools !== void 0) {
|
|
314
|
+
const lastTool = tools[tools.length - 1];
|
|
315
|
+
if (lastTool !== void 0) lastTool.cache_control = cacheControl;
|
|
316
|
+
}
|
|
317
|
+
const maxTokens = request.maxTokens ?? 8192;
|
|
318
|
+
const reasoningFormat = options.reasoningFormat ?? "output-config";
|
|
319
|
+
const effort = call.reasoningEffort === void 0 ? void 0 : String(call.reasoningEffort);
|
|
320
|
+
const budgetThinking = reasoningFormat === "thinking-budget" ? thinkingFromBudget(effort, maxTokens, options.budgets) : void 0;
|
|
321
|
+
const thinking = reasoningFormat === "thinking-budget" ? budgetThinking : options.thinking === void 0 ? void 0 : options.thinking === "adaptive" ? { type: "adaptive" } : { type: "disabled" };
|
|
322
|
+
const output = outputConfig(call.outputFormat, reasoningFormat === "output-config" ? effort : void 0);
|
|
279
323
|
return {
|
|
280
324
|
model: call.model,
|
|
281
|
-
max_tokens:
|
|
282
|
-
messages: messagesOf(call.messages),
|
|
325
|
+
max_tokens: maxTokens,
|
|
326
|
+
messages: messagesOf(call.messages, cacheControl),
|
|
283
327
|
...system === void 0 ? {} : { system },
|
|
284
328
|
...tools === void 0 ? {} : { tools },
|
|
285
329
|
...call.toolChoice === void 0 ? {} : { tool_choice: toolChoiceOf(call.toolChoice) },
|
|
286
|
-
|
|
287
|
-
|
|
330
|
+
...call.temperature === void 0 ? {} : { temperature: call.temperature },
|
|
331
|
+
...call.topP === void 0 ? {} : { top_p: call.topP },
|
|
288
332
|
...call.stop === void 0 || call.stop.length === 0 ? {} : { stop_sequences: [...call.stop] },
|
|
289
333
|
...thinking === void 0 ? {} : { thinking },
|
|
290
334
|
...output === void 0 ? {} : { output_config: output },
|
|
@@ -656,9 +700,11 @@ const DEFAULT_THINKING_BUDGETS = Object.freeze({
|
|
|
656
700
|
high: 24576
|
|
657
701
|
});
|
|
658
702
|
const DEFAULT_DIALECT = Object.freeze({
|
|
703
|
+
reasoningFormat: "output-config",
|
|
659
704
|
budgets: DEFAULT_THINKING_BUDGETS,
|
|
660
705
|
version: ANTHROPIC_VERSION,
|
|
661
|
-
beta: Object.freeze([])
|
|
706
|
+
beta: Object.freeze([]),
|
|
707
|
+
promptCaching: false
|
|
662
708
|
});
|
|
663
709
|
/** The Anthropic Messages wire protocol. */
|
|
664
710
|
const anthropicMessagesProtocol = Object.freeze({
|
|
@@ -672,11 +718,17 @@ const anthropicMessagesProtocol = Object.freeze({
|
|
|
672
718
|
...dialect.beta.length === 0 ? {} : { "anthropic-beta": dialect.beta.join(",") }
|
|
673
719
|
}),
|
|
674
720
|
serialize(request, dialect) {
|
|
675
|
-
return serializeAnthropicRequest(request, {
|
|
721
|
+
return serializeAnthropicRequest(request, {
|
|
722
|
+
reasoningFormat: dialect.reasoningFormat,
|
|
723
|
+
budgets: dialect.budgets,
|
|
724
|
+
...dialect.thinking === void 0 ? {} : { thinking: dialect.thinking },
|
|
725
|
+
promptCaching: dialect.promptCaching,
|
|
726
|
+
...dialect.promptCachingTtl === void 0 ? {} : { promptCachingTtl: dialect.promptCachingTtl }
|
|
727
|
+
});
|
|
676
728
|
},
|
|
677
729
|
translate: (events, _request, displayName) => translateAnthropicStream(events, displayName)
|
|
678
730
|
});
|
|
679
731
|
|
|
680
732
|
//#endregion
|
|
681
|
-
export { ANTHROPIC_MESSAGES_PROTOCOL_ID, ANTHROPIC_VERSION, DEFAULT_THINKING_BUDGETS, anthropicMessagesProtocol, serializeAnthropicRequest, translateAnthropicStream };
|
|
733
|
+
export { ANTHROPIC_MESSAGES_PROTOCOL_ID, ANTHROPIC_VERSION, DEFAULT_MAX_TOKENS, DEFAULT_THINKING_BUDGETS, anthropicMessagesProtocol, serializeAnthropicRequest, translateAnthropicStream };
|
|
682
734
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/serialize.ts","../src/translate.ts","../src/protocol.ts"],"sourcesContent":["/**\n * Normalized request to Anthropic Messages API wire JSON.\n *\n * Two things here differ sharply from the Responses API and are easy to get wrong:\n *\n * 1. `tool_use.input` is a parsed OBJECT, not a JSON string. Our normalized block\n * keeps the raw string the model produced, so it is parsed on the way out.\n * 2. Consecutive same-role messages are MERGED. This is not cosmetic tidying —\n * when a model makes three parallel tool calls, we produce three separate\n * tool-result messages, and this API expects all three `tool_result` blocks in\n * ONE user message. Without merging, parallel tool use breaks.\n *\n * @module ai-agent-sdk/providers/anthropic/serialize\n */\n\nimport {\n isNativeToolSchema,\n type ModelOutputFormat,\n type ModelToolSchema,\n type NativeWebSearchTool,\n type ToolChoice,\n type ToolSchema,\n} from '@alvin0/ai-agent-sdk-core'\nimport { MODEL_ERROR_CODES, ModelError } from '@alvin0/ai-agent-sdk-core'\nimport type { ContentBlock, DocumentSource, ImageSource } from '@alvin0/ai-agent-sdk-core'\nimport type { Message } from '@alvin0/ai-agent-sdk-core'\nimport type { ProtocolRequest } from './contract.ts'\nimport type {\n WireDocumentSource,\n WireImageSource,\n WireCitation,\n WireMessage,\n WireOutputConfig,\n WireRequest,\n WireRequestBlock,\n WireThinking,\n WireTool,\n WireToolChoice,\n WireToolResultContent,\n} from './wire.ts'\n\n/**\n * Adapter-private state kept on a {@link ReasoningBlock} so a thinking block can\n * be echoed back exactly.\n *\n * The signature is the load-bearing part: this API verifies it to confirm the\n * block is genuinely the model's own reasoning, and a thinking block sent back\n * without it is rejected.\n */\nexport interface AnthropicReasoningState {\n /** `thinking` for an ordinary block, `redacted_thinking` for an opaque one. */\n kind: 'thinking' | 'redacted_thinking'\n /** Cryptographic signature over the thinking content. */\n signature?: string\n /** Opaque payload of a redacted block. */\n data?: string\n}\n\n/** Read reasoning state back off a block, tolerating anything unexpected. */\nfunction reasoningStateOf(value: unknown): AnthropicReasoningState | undefined {\n if (typeof value !== 'object' || value === null) return undefined\n const state = value as AnthropicReasoningState\n if (state.kind !== 'thinking' && state.kind !== 'redacted_thinking') return undefined\n return {\n kind: state.kind,\n ...typeof state.signature === 'string' ? { signature: state.signature } : {},\n ...typeof state.data === 'string' ? { data: state.data } : {},\n }\n}\n\n/** Map an image source onto this API's tagged source object. */\nfunction imageSource(source: ImageSource): WireImageSource {\n if (source.kind === 'url') return { type: 'url', url: source.url }\n if (source.kind === 'base64') {\n return { type: 'base64', media_type: source.mediaType, data: source.data }\n }\n throw new ModelError(\n 'Anthropic image inputs support URL or base64 sources, not file ids',\n MODEL_ERROR_CODES.INVALID_REQUEST,\n )\n}\n\n/**\n * Map a document source onto this API's tagged source object.\n *\n * All three variants are supported here, including the file id that\n * {@link imageSource} has to reject.\n */\nfunction documentSource(source: DocumentSource): WireDocumentSource {\n if (source.kind === 'url') return { type: 'url', url: source.url }\n if (source.kind === 'file') return { type: 'file', file_id: source.fileId }\n return { type: 'base64', media_type: source.mediaType, data: source.data }\n}\n\n/** Restrict tool-result content to the block types this API accepts there. */\nfunction toolResultContent(blocks: readonly ContentBlock[]): WireToolResultContent[] | string {\n const parts: WireToolResultContent[] = []\n let textOnly = true\n for (const block of blocks) {\n if (block.type === 'text') parts.push({ type: 'text', text: block.text })\n else if (block.type === 'image') {\n textOnly = false\n parts.push({ type: 'image', source: imageSource(block.source) })\n }\n // Anything else (a nested tool result, an extension block) has no\n // representation inside a tool result and is dropped rather than guessed at.\n }\n if (textOnly) {\n return parts.map(part => (part.type === 'text' ? part.text : '')).join('\\n')\n }\n return parts\n}\n\n/** Parse tool-call arguments into the object this API expects. */\nfunction toolInput(raw: string): unknown {\n if (raw.trim().length === 0) return {}\n try {\n return JSON.parse(raw) as unknown\n } catch {\n // The model emitted invalid JSON. Sending `{}` keeps the conversation\n // well-formed so the tool layer can report the problem back to the model,\n // which is recoverable; failing the request here is not.\n return {}\n }\n}\n\nfunction citationOf(value: unknown): WireCitation | undefined {\n if (typeof value !== 'object' || value === null) return undefined\n const citation = value as Record<string, unknown>\n return typeof citation.type === 'string' ? structuredClone(citation) as WireCitation : undefined\n}\n\nfunction nativeReplayBlocks(value: unknown): WireRequestBlock[] {\n if (typeof value !== 'object' || value === null) return []\n const state = value as Record<string, unknown>\n const values = [state.call, state.result]\n return values.flatMap((candidate): WireRequestBlock[] => {\n if (typeof candidate !== 'object' || candidate === null) return []\n const block = candidate as Record<string, unknown>\n if (block.type === 'server_tool_use'\n && typeof block.id === 'string'\n && typeof block.name === 'string') {\n return [{\n type: 'server_tool_use', id: block.id, name: block.name,\n input: structuredClone(block.input ?? {}),\n }]\n }\n if (block.type === 'web_search_tool_result' && typeof block.tool_use_id === 'string') {\n return [{\n type: 'web_search_tool_result', tool_use_id: block.tool_use_id,\n content: structuredClone(block.content),\n ...block.caller === undefined ? {} : { caller: structuredClone(block.caller) },\n }]\n }\n return []\n })\n}\n\n/** Convert one normalized block to zero or more wire blocks. */\nfunction requestBlocks(block: ContentBlock): WireRequestBlock[] {\n switch (block.type) {\n case 'text': {\n // Whitespace-only text is rejected by this API, so it is dropped.\n if (block.text.trim().length === 0) return []\n const citations = block.annotations?.flatMap((annotation): WireCitation[] => {\n if (annotation.type !== 'url-citation') return []\n const citation = citationOf(annotation.providerState)\n return citation === undefined ? [] : [citation]\n })\n return [{\n type: 'text', text: block.text,\n ...citations === undefined || citations.length === 0 ? {} : { citations },\n }]\n }\n case 'image':\n return [{ type: 'image', source: imageSource(block.source) }]\n case 'document': {\n // `title` is what a citation is attributed to, so the file name is a much\n // better fallback than leaving it unset.\n const title = block.title ?? block.filename\n return [{\n type: 'document',\n source: documentSource(block.source),\n ...title === undefined ? {} : { title },\n ...block.context === undefined ? {} : { context: block.context },\n ...block.citations === undefined ? {} : { citations: { enabled: block.citations } },\n }]\n }\n case 'tool-call':\n return [{\n type: 'tool_use',\n id: block.id,\n name: block.name,\n input: toolInput(block.arguments),\n }]\n case 'tool-result':\n return [{\n type: 'tool_result',\n tool_use_id: block.toolCallId,\n content: toolResultContent(block.content),\n ...block.isError === true ? { is_error: true } : {},\n }]\n case 'native-tool-call':\n return nativeReplayBlocks(block.providerState)\n case 'reasoning': {\n const state = reasoningStateOf(block.providerState)\n if (state === undefined) {\n // No signature means this cannot be replayed as a thinking block. Dropping\n // it is correct: sending unsigned thinking is rejected outright.\n return []\n }\n if (state.kind === 'redacted_thinking') {\n return state.data === undefined ? [] : [{ type: 'redacted_thinking', data: state.data }]\n }\n return state.signature === undefined\n ? []\n : [{ type: 'thinking', thinking: block.text, signature: state.signature }]\n }\n default:\n return []\n }\n}\n\n/**\n * Build the message list, merging consecutive same-role messages.\n *\n * See the module note for why merging matters.\n */\nfunction messagesOf(messages: readonly Message[]): WireMessage[] {\n const result: WireMessage[] = []\n for (const message of messages) {\n if (message.role === 'system') continue // hoisted to the `system` field\n const role = message.role === 'assistant' ? 'assistant' : 'user'\n const blocks = message.content.flatMap(requestBlocks)\n if (blocks.length === 0) continue\n\n const previous = result.at(-1)\n if (previous !== undefined && previous.role === role) previous.content.push(...blocks)\n else result.push({ role, content: blocks })\n }\n return result\n}\n\n/** Collect the system prompt from the request plus any system-role messages. */\nfunction systemOf(request: ProtocolRequest): string | undefined {\n const fromMessages = request.options.messages\n .filter(message => message.role === 'system')\n .flatMap(message => message.content)\n .filter((block): block is Extract<ContentBlock, { type: 'text' }> => block.type === 'text')\n .map(block => block.text)\n const all = request.options.system === undefined\n ? fromMessages\n : [request.options.system, ...fromMessages]\n const joined = all.join('\\n\\n')\n return joined.length === 0 ? undefined : joined\n}\n\n/** Map the neutral tool-choice vocabulary onto this API's. */\nfunction toolChoiceOf(choice: ToolChoice): WireToolChoice {\n if (choice === 'auto') return { type: 'auto' }\n if (choice === 'none') return { type: 'none' }\n // \"call some tool\" is spelled `any` here, not `required`.\n if (choice === 'required') return { type: 'any' }\n return { type: 'tool', name: choice.type === 'native' ? nativeToolName(choice.name) : choice.name }\n}\n\nfunction functionTool(tool: ToolSchema): WireTool {\n return { name: tool.name, description: tool.description, input_schema: tool.parameters }\n}\n\nfunction nativeToolName(name: string): string {\n if (name === 'web-search') return 'web_search'\n return name.replaceAll('-', '_')\n}\n\nfunction webSearchTool(tool: NativeWebSearchTool): WireTool {\n if (tool.allowedDomains !== undefined && tool.blockedDomains !== undefined) {\n throw new ModelError(\n 'Anthropic web search accepts allowedDomains or blockedDomains, not both',\n MODEL_ERROR_CODES.INVALID_REQUEST,\n )\n }\n return {\n type: 'web_search_20250305',\n name: 'web_search',\n ...tool.maxUses === undefined ? {} : { max_uses: tool.maxUses },\n ...tool.allowedDomains === undefined ? {} : { allowed_domains: [...tool.allowedDomains] },\n ...tool.blockedDomains === undefined ? {} : { blocked_domains: [...tool.blockedDomains] },\n ...tool.userLocation === undefined ? {} : {\n user_location: { type: 'approximate', ...tool.userLocation },\n },\n }\n}\n\nfunction toolOf(tool: ModelToolSchema): WireTool {\n if (!isNativeToolSchema(tool)) return functionTool(tool)\n if (tool.name === 'web-search') return webSearchTool(tool)\n throw new ModelError(\n `Anthropic does not support the provider-native tool '${tool.name}'`,\n MODEL_ERROR_CODES.INVALID_REQUEST,\n )\n}\n\n/** How a reasoning effort becomes a thinking token budget. */\nexport type ThinkingBudgets = Readonly<Record<string, number>>\n\n/** Options controlling how the request is built. */\nexport interface AnthropicSerializeOptions {\n /** Effort id to thinking-token budget. An absent or zero budget disables thinking. */\n budgets: ThinkingBudgets\n}\n\n/**\n * Resolve the `thinking` field for this request.\n *\n * The budget must leave room for a real answer, so it is capped below\n * `max_tokens` — this API requires `budget_tokens < max_tokens` and rejects the\n * request otherwise.\n */\nfunction thinkingOf(\n effort: string | undefined,\n maxTokens: number,\n budgets: ThinkingBudgets,\n): WireThinking | undefined {\n if (effort === undefined) return undefined\n const requested = budgets[effort]\n if (requested === undefined || requested <= 0) return { type: 'disabled' }\n // Leave at least a quarter of the budget for the visible answer.\n const capped = Math.min(requested, Math.floor(maxTokens * 0.75))\n // This API's own floor for extended thinking.\n return capped < 1_024 ? { type: 'disabled' } : { type: 'enabled', budget_tokens: capped }\n}\n\nfunction outputConfig(format: ModelOutputFormat | undefined): WireOutputConfig | undefined {\n if (format === undefined || format.type === 'text') return undefined\n return { format: { type: 'json_schema', schema: format.schema } }\n}\n\n/**\n * Build the Messages request body.\n * @param request - the resolved request, model, and connection.\n * @param options - thinking-budget mapping.\n * @returns the wire body, ready to serialize.\n */\nexport function serializeAnthropicRequest(\n request: ProtocolRequest,\n options: AnthropicSerializeOptions,\n): WireRequest {\n const { options: call } = request\n const system = systemOf(request)\n const tools = call.tools === undefined || call.tools.length === 0\n ? undefined\n : call.tools.map(toolOf)\n const thinking = thinkingOf(\n call.reasoningEffort === undefined ? undefined : String(call.reasoningEffort),\n request.maxTokens,\n options.budgets,\n )\n const thinkingEnabled = thinking?.type === 'enabled'\n const output = outputConfig(call.outputFormat)\n\n return {\n model: call.model,\n // Required by this API — unlike most others, omitting it is an error.\n max_tokens: request.maxTokens,\n messages: messagesOf(call.messages),\n ...system === undefined ? {} : { system },\n ...tools === undefined ? {} : { tools },\n ...call.toolChoice === undefined ? {} : { tool_choice: toolChoiceOf(call.toolChoice) },\n // Extended thinking is incompatible with sampling adjustments; sending both\n // is rejected, so the sampling knobs are dropped when thinking is on.\n ...!thinkingEnabled && call.temperature !== undefined\n ? { temperature: call.temperature }\n : {},\n ...!thinkingEnabled && call.topP !== undefined ? { top_p: call.topP } : {},\n ...call.stop === undefined || call.stop.length === 0\n ? {}\n : { stop_sequences: [...call.stop] },\n ...thinking === undefined ? {} : { thinking },\n ...output === undefined ? {} : { output_config: output },\n stream: true,\n }\n}\n","/**\n * Anthropic Messages API SSE events to the SDK's chunk protocol.\n *\n * Notable differences from the Responses translation:\n *\n * - Block indices come straight from the provider. This API numbers content\n * blocks contiguously from zero in emission order, which is already exactly\n * what our protocol wants, so no remapping is needed.\n * - Usage arrives in TWO places: input counts on `message_start`, output counts on\n * `message_delta`. Cumulative snapshots are emitted as usage-progress; the\n * final usage is emitted once at message_stop, before the finish.\n * - `input_tokens` here already EXCLUDES cached tokens, so unlike the Responses\n * translation nothing is subtracted. Getting this backwards would under-report\n * input on every cached call.\n *\n * @module ai-agent-sdk/providers/anthropic/translate\n */\n\nimport {\n CONTEXT_WINDOW_EXCEEDED_CODE,\n MODEL_ERROR_CODES,\n ModelError,\n QUOTA_EXCEEDED_CODE,\n isContextWindowExceededError,\n isQuotaExceededError,\n} from '@alvin0/ai-agent-sdk-core'\nimport { ToolCallId } from '@alvin0/ai-agent-sdk-core'\nimport { isJsonValue, type JsonValue } from '@alvin0/ai-agent-sdk-core'\nimport type { ContentBlock, TextAnnotation } from '@alvin0/ai-agent-sdk-core'\nimport type { FinishReason, UsageCounters } from '@alvin0/ai-agent-sdk-core'\nimport type { ProtocolSseEvent, ProtocolStreamChunk } from './contract.ts'\nimport type { AnthropicReasoningState } from './serialize.ts'\nimport type {\n WireCitation,\n WireServerToolUseBlock,\n WireStopReason,\n WireStreamEvent,\n WireUsage,\n WireWebSearchToolResultBlock,\n} from './wire.ts'\n\n/** Which of our block types one wire block maps to. */\ntype BlockKind = 'text' | 'reasoning' | 'tool-call' | 'native-tool-call'\n\ninterface OpenBlock {\n readonly kind: BlockKind\n text: string\n args: string\n callId: string\n name: string\n signature: string | undefined\n redactedData: string | undefined\n annotations: TextAnnotation[]\n nativeCall: WireServerToolUseBlock | undefined\n nativeResult: WireWebSearchToolResultBlock | undefined\n closed: boolean\n}\n\nfunction blockKind(type: string | undefined): BlockKind | undefined {\n switch (type) {\n case 'text': return 'text'\n case 'thinking':\n case 'redacted_thinking': return 'reasoning'\n case 'tool_use': return 'tool-call'\n case 'server_tool_use': return 'native-tool-call'\n default: return undefined\n }\n}\n\n/** Accumulated token counts, filled from two different events. */\ninterface UsageAccumulator {\n input: unknown\n output: unknown\n cacheRead: unknown\n cacheWrite: unknown\n seen: boolean\n}\n\nfunction absorbUsage(target: UsageAccumulator, usage: WireUsage | undefined): void {\n if (typeof usage !== 'object' || usage === null) return\n if ('input_tokens' in usage) target.input = usage.input_tokens\n if ('output_tokens' in usage) target.output = usage.output_tokens\n if ('cache_read_input_tokens' in usage && usage.cache_read_input_tokens !== null) {\n target.cacheRead = usage.cache_read_input_tokens\n }\n if ('cache_creation_input_tokens' in usage && usage.cache_creation_input_tokens !== null) {\n target.cacheWrite = usage.cache_creation_input_tokens\n }\n target.seen = true\n}\n\nfunction finalUsage(accumulated: UsageAccumulator): UsageCounters | undefined {\n if (!accumulated.seen) return undefined\n const output: Record<string, unknown> = {\n ...accumulated.input === undefined ? {} : { inputTokens: accumulated.input },\n ...accumulated.output === undefined ? {} : { outputTokens: accumulated.output },\n // Cache omission/null is authoritative zero for this protocol. Invalid\n // present values are retained so the accounting boundary can record them.\n ...accumulated.cacheRead === undefined || accumulated.cacheRead === 0\n ? {} : { cacheReadTokens: accumulated.cacheRead },\n ...accumulated.cacheWrite === undefined || accumulated.cacheWrite === 0\n ? {} : { cacheWriteTokens: accumulated.cacheWrite },\n }\n const counters = [\n accumulated.input,\n accumulated.cacheRead ?? 0,\n accumulated.cacheWrite ?? 0,\n accumulated.output,\n ]\n if (counters.every(validUsageCounter)) {\n output.totalTokens = counters.reduce<number>((total, value) => total + value, 0)\n }\n return output as UsageCounters\n}\n\nfunction validUsageCounter(value: unknown): value is number {\n return typeof value === 'number' && Number.isSafeInteger(value) && value >= 0\n}\n\n/** Map this API's stop reason onto ours. */\nfunction finishReason(stop: WireStopReason | null | undefined): FinishReason {\n switch (stop) {\n case 'tool_use': return { kind: 'tool-calls' }\n case 'max_tokens': return { kind: 'max-tokens' }\n case 'refusal':\n return {\n kind: 'error',\n failure: {\n message: 'the model refused to answer',\n code: MODEL_ERROR_CODES.INVALID_REQUEST,\n },\n }\n // `end_turn`, `stop_sequence`, and `pause_turn` all mean the turn produced a\n // complete answer as far as a caller is concerned.\n default: return { kind: 'stop' }\n }\n}\n\n/** Build the authoritative block for a completed content block. */\nfunction closedBlock(open: OpenBlock): ContentBlock | undefined {\n switch (open.kind) {\n case 'text':\n return {\n type: 'text', text: open.text,\n ...open.annotations.length === 0 ? {} : { annotations: open.annotations },\n }\n case 'reasoning': {\n const state: AnthropicReasoningState = open.redactedData !== undefined\n ? { kind: 'redacted_thinking', data: open.redactedData }\n : {\n kind: 'thinking',\n ...open.signature === undefined ? {} : { signature: open.signature },\n }\n return { type: 'reasoning', text: open.text, providerState: state }\n }\n case 'tool-call':\n return {\n type: 'tool-call',\n id: ToolCallId(open.callId),\n name: open.name,\n arguments: open.args.length > 0 ? open.args : '{}',\n }\n case 'native-tool-call': {\n const parsed = parsedArguments(open.args, open.nativeCall?.input)\n const call: WireServerToolUseBlock = open.nativeCall ?? {\n type: 'server_tool_use', id: open.callId, name: 'web_search', input: parsed,\n }\n return {\n type: 'native-tool-call', id: open.callId,\n name: open.name === 'web_search' ? 'web-search' : open.name.replaceAll('_', '-'),\n arguments: parsed,\n content: [],\n providerState: {\n call: { ...call, input: parsed },\n ...open.nativeResult === undefined ? {} : { result: open.nativeResult },\n },\n }\n }\n default:\n return undefined\n }\n}\n\nfunction parsedArguments(raw: string, fallback?: unknown): JsonValue {\n if (raw.length === 0) return isJsonValue(fallback) ? fallback : {}\n try {\n const value: unknown = JSON.parse(raw)\n return isJsonValue(value) ? value : {}\n } catch {\n return {}\n }\n}\n\nfunction citationAnnotation(citation: WireCitation): TextAnnotation | undefined {\n if (citation.type !== 'web_search_result_location' || typeof citation.url !== 'string') {\n return undefined\n }\n return {\n type: 'url-citation', url: citation.url,\n ...typeof citation.title === 'string' ? { title: citation.title } : {},\n providerState: structuredClone(citation),\n }\n}\n\n/**\n * Translate one Messages SSE stream.\n *\n * Owns termination. There is no `[DONE]` sentinel: the stream ends on\n * `message_stop`, and a body that ends before that was truncated — a failure\n * rather than a short answer.\n * @param events - decoded SSE events.\n * @param displayName - provider name, used in diagnostics.\n * @returns the chunk stream.\n */\nexport async function* translateAnthropicStream(\n events: AsyncIterable<ProtocolSseEvent>,\n displayName: string,\n): AsyncGenerator<ProtocolStreamChunk> {\n const open = new Map<number, OpenBlock>()\n const usage: UsageAccumulator = {\n input: undefined, output: undefined, cacheRead: undefined, cacheWrite: undefined, seen: false,\n }\n let stop: WireStopReason | null | undefined\n let terminated = false\n let emittedBlocks = 0\n\n for await (const raw of events) {\n let event: WireStreamEvent\n try {\n event = JSON.parse(raw.data) as WireStreamEvent\n } catch (error: unknown) {\n throw new ModelError(\n `${displayName} sent a malformed stream event`,\n MODEL_ERROR_CODES.MALFORMED_RESPONSE,\n { cause: error },\n )\n }\n\n switch (event.type) {\n case 'message_start': {\n absorbUsage(usage, event.message.usage)\n const progress = finalUsage(usage)\n if (progress !== undefined) yield { type: 'usage-progress', usage: progress }\n break\n }\n\n case 'content_block_start': {\n if (event.content_block.type === 'web_search_tool_result') {\n const result = event.content_block\n const owner = [...open.values()].find(entry => entry.kind === 'native-tool-call'\n && entry.callId === result.tool_use_id)\n if (owner !== undefined) {\n owner.nativeResult = result\n const block = closedBlock(owner)\n if (block !== undefined && !owner.closed) {\n owner.closed = true\n yield {\n type: 'block-end',\n index: [...open.entries()].find(([, entry]) => entry === owner)?.[0] ?? event.index,\n block,\n }\n }\n }\n break\n }\n const kind = blockKind(event.content_block.type)\n if (kind === undefined) break\n const block = event.content_block\n const entry: OpenBlock = {\n kind,\n text: block.type === 'text'\n ? block.text\n : block.type === 'thinking' ? block.thinking : '',\n args: '',\n callId: block.type === 'tool_use' ? block.id : `block-${event.index}`,\n name: block.type === 'tool_use' || block.type === 'server_tool_use' ? block.name : '',\n signature: block.type === 'thinking' ? block.signature : undefined,\n redactedData: block.type === 'redacted_thinking' ? block.data : undefined,\n annotations: [],\n nativeCall: block.type === 'server_tool_use' ? block : undefined,\n nativeResult: undefined,\n closed: false,\n }\n if (block.type === 'server_tool_use') {\n entry.callId = block.id\n entry.args = ''\n }\n open.set(event.index, entry)\n emittedBlocks += 1\n yield { type: 'block-start', index: event.index, blockType: kind }\n break\n }\n\n case 'content_block_delta': {\n const entry = open.get(event.index)\n if (entry === undefined) break\n const delta = event.delta\n switch (delta.type) {\n case 'text_delta':\n entry.text += delta.text\n yield { type: 'text-delta', index: event.index, text: delta.text }\n break\n case 'thinking_delta':\n entry.text += delta.thinking\n yield { type: 'reasoning-delta', index: event.index, text: delta.thinking }\n break\n case 'signature_delta':\n // Arrives once, just before the block closes. It carries no visible\n // content, so it produces no chunk — only the state needed to replay\n // this thinking block on a later request.\n entry.signature = delta.signature\n break\n case 'input_json_delta':\n entry.args += delta.partial_json\n if (entry.kind === 'tool-call') {\n yield {\n type: 'tool-call-delta',\n index: event.index,\n id: ToolCallId(entry.callId),\n ...entry.name.length > 0 ? { name: entry.name } : {},\n argumentsDelta: delta.partial_json,\n }\n }\n break\n case 'citations_delta': {\n const annotation = citationAnnotation(delta.citation)\n if (annotation !== undefined) entry.annotations.push(annotation)\n break\n }\n default:\n break\n }\n break\n }\n\n case 'content_block_stop': {\n const entry = open.get(event.index)\n if (entry === undefined) break\n if (entry.kind === 'native-tool-call') break\n const block = closedBlock(entry)\n if (block !== undefined && !entry.closed) {\n entry.closed = true\n yield { type: 'block-end', index: event.index, block }\n }\n break\n }\n\n case 'message_delta': {\n stop = event.delta.stop_reason\n absorbUsage(usage, event.usage)\n const progress = finalUsage(usage)\n if (progress !== undefined) yield { type: 'usage-progress', usage: progress }\n break\n }\n\n case 'message_stop': {\n for (const [index, entry] of open) {\n if (entry.kind !== 'native-tool-call' || entry.closed) continue\n const block = closedBlock(entry)\n if (block !== undefined) yield { type: 'block-end', index, block }\n entry.closed = true\n }\n const mapped = finalUsage(usage)\n if (mapped !== undefined) yield { type: 'usage', usage: mapped }\n if (emittedBlocks === 0) {\n // A clean stop with no content at all. Reported as a failure rather\n // than an empty message, because an empty message ends the turn with\n // nothing for the caller to act on — and it is safe to retry.\n throw new ModelError(\n `${displayName} returned a response with no content`,\n 'EMPTY_RESPONSE',\n )\n }\n yield { type: 'finish', reason: finishReason(stop) }\n terminated = true\n return\n }\n\n case 'error': {\n const detail = [event.error.type, event.error.message]\n .filter((part): part is string => part !== undefined)\n .join(' ')\n throw new ModelError(\n event.error.message ?? `${displayName} reported a stream error`,\n // `overloaded_error` mid-stream is the common case and must stay\n // retryable, which the shared 5xx mapping gives us.\n event.error.type === 'overloaded_error'\n ? MODEL_ERROR_CODES.SERVER\n : anthropicStreamErrorCode(event.error.type, detail),\n )\n }\n\n // `ping` and any future event carry nothing this protocol needs.\n default:\n break\n }\n }\n\n if (!terminated) {\n throw new ModelError(\n `${displayName} stream ended before message_stop`,\n MODEL_ERROR_CODES.STREAM_CLOSED,\n )\n }\n}\n\nfunction anthropicStreamErrorCode(type: string | undefined, detail: string): string {\n if (type === 'authentication_error' || type === 'permission_error') {\n return MODEL_ERROR_CODES.AUTH\n }\n if (isQuotaExceededError(detail)) return QUOTA_EXCEEDED_CODE\n if (type === 'rate_limit_error') return MODEL_ERROR_CODES.RATE_LIMIT\n if (type === 'api_error') return MODEL_ERROR_CODES.SERVER\n if (isContextWindowExceededError(detail)) return CONTEXT_WINDOW_EXCEEDED_CODE\n return MODEL_ERROR_CODES.INVALID_REQUEST\n}\n","/**\n * The Anthropic Messages protocol, as a reusable {@link WireProtocol}.\n *\n * @module ai-agent-sdk/providers/protocols/anthropic-messages\n */\n\nimport type {\n ProtocolDefinition,\n ProtocolRequest,\n ProtocolSseEvent,\n ProtocolStreamChunk,\n} from './contract.ts'\nimport type { ModelTarget, ResolvedModelInfo } from '@alvin0/ai-agent-sdk-core/provider'\nimport { serializeAnthropicRequest, type ThinkingBudgets } from './serialize.ts'\nimport { translateAnthropicStream } from './translate.ts'\n\n/** Protocol id, usable as a stable string in configuration. */\nexport const ANTHROPIC_MESSAGES_PROTOCOL_ID = 'anthropic-messages'\n\n/**\n * The API version header value.\n *\n * Mandatory on every request. Stable across the entire lifetime of this API — new\n * capabilities arrive as opt-in beta headers rather than a version bump — which is\n * why it lives on the protocol instead of being restated by each endpoint.\n */\nexport const ANTHROPIC_VERSION = '2023-06-01'\n\n/**\n * Default reasoning efforts, expressed as thinking-token budgets.\n *\n * Budgets rather than an opaque level because that is what this API takes. The\n * SDK's effort ids are a neutral surface over a provider-specific knob, and\n * mapping them here is the whole reason `ReasoningEffortId` is opaque.\n */\nexport const DEFAULT_THINKING_BUDGETS: ThinkingBudgets = Object.freeze({\n off: 0,\n low: 2_048,\n medium: 8_192,\n high: 24_576,\n})\n\n/** Per-endpoint knobs of the Messages protocol. */\nexport interface AnthropicDialect {\n /** Effort id to thinking-token budget. */\n readonly budgets: ThinkingBudgets\n /** `anthropic-version` header value. */\n readonly version: string\n /** Opt-in beta features, sent as `anthropic-beta`. */\n readonly beta: readonly string[]\n}\n\nconst DEFAULT_DIALECT: AnthropicDialect = Object.freeze({\n budgets: DEFAULT_THINKING_BUDGETS,\n version: ANTHROPIC_VERSION,\n beta: Object.freeze([]),\n})\n\ninterface RuntimeProtocolRequest extends ProtocolRequest {\n readonly model: ResolvedModelInfo\n readonly connection: {\n readonly baseUrl: string\n readonly headers: Readonly<Record<string, string>>\n }\n}\n\n/** Marker-based runtime view, kept structurally independent from provider-http. */\nexport interface AnthropicMessagesProtocolDefinition {\n readonly kind: 'http-wire-protocol'\n readonly apiVersion: 1\n readonly id: string\n readonly defaultDialect: AnthropicDialect\n readonly exampleModel?: ModelTarget\n readonly endpointPath: (request: RuntimeProtocolRequest, dialect: AnthropicDialect) => string\n readonly protocolHeaders?: (dialect: AnthropicDialect) => Readonly<Record<string, string>>\n readonly serialize: (\n request: RuntimeProtocolRequest,\n dialect: AnthropicDialect,\n ) => Readonly<Record<string, unknown>>\n readonly translate: (\n events: AsyncIterable<ProtocolSseEvent>,\n request: RuntimeProtocolRequest,\n displayName: string,\n ) => AsyncGenerator<ProtocolStreamChunk>\n}\n\n/** The Anthropic Messages wire protocol. */\nexport const anthropicMessagesProtocol: ProtocolDefinition<AnthropicDialect>\n & AnthropicMessagesProtocolDefinition = Object.freeze({\n kind: 'http-wire-protocol' as const,\n apiVersion: 1 as const,\n id: ANTHROPIC_MESSAGES_PROTOCOL_ID,\n defaultDialect: DEFAULT_DIALECT,\n endpointPath: () => '/v1/messages',\n protocolHeaders: (dialect: AnthropicDialect) => ({\n 'anthropic-version': dialect.version,\n ...dialect.beta.length === 0 ? {} : { 'anthropic-beta': dialect.beta.join(',') },\n }),\n serialize(request: ProtocolRequest, dialect: AnthropicDialect): Readonly<Record<string, unknown>> {\n const body: unknown = serializeAnthropicRequest(request, { budgets: dialect.budgets })\n return body as Readonly<Record<string, unknown>>\n },\n // Params are annotated because `Object.freeze` erases the contextual typing the\n // `WireProtocol` annotation would otherwise supply.\n translate: (\n events: AsyncIterable<ProtocolSseEvent>,\n _request: ProtocolRequest,\n displayName: string,\n ): AsyncGenerator<ProtocolStreamChunk> => translateAnthropicStream(events, displayName),\n})\n\nexport type { ThinkingBudgets }\n"],"mappings":";;;;;;;;;;;;;;;;;;AA2DA,SAAS,iBAAiB,OAAqD;CAC7E,IAAI,OAAO,UAAU,YAAY,UAAU,MAAM,OAAO;CACxD,MAAM,QAAQ;CACd,IAAI,MAAM,SAAS,cAAc,MAAM,SAAS,qBAAqB,OAAO;CAC5E,OAAO;EACL,MAAM,MAAM;EACZ,GAAG,OAAO,MAAM,cAAc,WAAW,EAAE,WAAW,MAAM,UAAU,IAAI,CAAC;EAC3E,GAAG,OAAO,MAAM,SAAS,WAAW,EAAE,MAAM,MAAM,KAAK,IAAI,CAAC;CAC9D;AACF;;AAGA,SAAS,YAAY,QAAsC;CACzD,IAAI,OAAO,SAAS,OAAO,OAAO;EAAE,MAAM;EAAO,KAAK,OAAO;CAAI;CACjE,IAAI,OAAO,SAAS,UAClB,OAAO;EAAE,MAAM;EAAU,YAAY,OAAO;EAAW,MAAM,OAAO;CAAK;CAE3E,MAAM,IAAI,WACR,sEACA,kBAAkB,eACpB;AACF;;;;;;;AAQA,SAAS,eAAe,QAA4C;CAClE,IAAI,OAAO,SAAS,OAAO,OAAO;EAAE,MAAM;EAAO,KAAK,OAAO;CAAI;CACjE,IAAI,OAAO,SAAS,QAAQ,OAAO;EAAE,MAAM;EAAQ,SAAS,OAAO;CAAO;CAC1E,OAAO;EAAE,MAAM;EAAU,YAAY,OAAO;EAAW,MAAM,OAAO;CAAK;AAC3E;;AAGA,SAAS,kBAAkB,QAAmE;CAC5F,MAAM,QAAiC,CAAC;CACxC,IAAI,WAAW;CACf,KAAK,MAAM,SAAS,QAClB,IAAI,MAAM,SAAS,QAAQ,MAAM,KAAK;EAAE,MAAM;EAAQ,MAAM,MAAM;CAAK,CAAC;MACnE,IAAI,MAAM,SAAS,SAAS;EAC/B,WAAW;EACX,MAAM,KAAK;GAAE,MAAM;GAAS,QAAQ,YAAY,MAAM,MAAM;EAAE,CAAC;CACjE;CAIF,IAAI,UACF,OAAO,MAAM,KAAI,SAAS,KAAK,SAAS,SAAS,KAAK,OAAO,EAAG,CAAC,CAAC,KAAK,IAAI;CAE7E,OAAO;AACT;;AAGA,SAAS,UAAU,KAAsB;CACvC,IAAI,IAAI,KAAK,CAAC,CAAC,WAAW,GAAG,OAAO,CAAC;CACrC,IAAI;EACF,OAAO,KAAK,MAAM,GAAG;CACvB,QAAQ;EAIN,OAAO,CAAC;CACV;AACF;AAEA,SAAS,WAAW,OAA0C;CAC5D,IAAI,OAAO,UAAU,YAAY,UAAU,MAAM,OAAO;CACxD,MAAM,WAAW;CACjB,OAAO,OAAO,SAAS,SAAS,WAAW,gBAAgB,QAAQ,IAAoB;AACzF;AAEA,SAAS,mBAAmB,OAAoC;CAC9D,IAAI,OAAO,UAAU,YAAY,UAAU,MAAM,OAAO,CAAC;CACzD,MAAM,QAAQ;CAEd,OAAO,CADS,MAAM,MAAM,MAAM,MACtB,CAAC,CAAC,SAAS,cAAkC;EACvD,IAAI,OAAO,cAAc,YAAY,cAAc,MAAM,OAAO,CAAC;EACjE,MAAM,QAAQ;EACd,IAAI,MAAM,SAAS,qBACd,OAAO,MAAM,OAAO,YACpB,OAAO,MAAM,SAAS,UACzB,OAAO,CAAC;GACN,MAAM;GAAmB,IAAI,MAAM;GAAI,MAAM,MAAM;GACnD,OAAO,gBAAgB,MAAM,SAAS,CAAC,CAAC;EAC1C,CAAC;EAEH,IAAI,MAAM,SAAS,4BAA4B,OAAO,MAAM,gBAAgB,UAC1E,OAAO,CAAC;GACN,MAAM;GAA0B,aAAa,MAAM;GACnD,SAAS,gBAAgB,MAAM,OAAO;GACtC,GAAG,MAAM,WAAW,SAAY,CAAC,IAAI,EAAE,QAAQ,gBAAgB,MAAM,MAAM,EAAE;EAC/E,CAAC;EAEH,OAAO,CAAC;CACV,CAAC;AACH;;AAGA,SAAS,cAAc,OAAyC;CAC9D,QAAQ,MAAM,MAAd;EACE,KAAK,QAAQ;GAEX,IAAI,MAAM,KAAK,KAAK,CAAC,CAAC,WAAW,GAAG,OAAO,CAAC;GAC5C,MAAM,YAAY,MAAM,aAAa,SAAS,eAA+B;IAC3E,IAAI,WAAW,SAAS,gBAAgB,OAAO,CAAC;IAChD,MAAM,WAAW,WAAW,WAAW,aAAa;IACpD,OAAO,aAAa,SAAY,CAAC,IAAI,CAAC,QAAQ;GAChD,CAAC;GACD,OAAO,CAAC;IACN,MAAM;IAAQ,MAAM,MAAM;IAC1B,GAAG,cAAc,UAAa,UAAU,WAAW,IAAI,CAAC,IAAI,EAAE,UAAU;GAC1E,CAAC;EACH;EACA,KAAK,SACH,OAAO,CAAC;GAAE,MAAM;GAAS,QAAQ,YAAY,MAAM,MAAM;EAAE,CAAC;EAC9D,KAAK,YAAY;GAGf,MAAM,QAAQ,MAAM,SAAS,MAAM;GACnC,OAAO,CAAC;IACN,MAAM;IACN,QAAQ,eAAe,MAAM,MAAM;IACnC,GAAG,UAAU,SAAY,CAAC,IAAI,EAAE,MAAM;IACtC,GAAG,MAAM,YAAY,SAAY,CAAC,IAAI,EAAE,SAAS,MAAM,QAAQ;IAC/D,GAAG,MAAM,cAAc,SAAY,CAAC,IAAI,EAAE,WAAW,EAAE,SAAS,MAAM,UAAU,EAAE;GACpF,CAAC;EACH;EACA,KAAK,aACH,OAAO,CAAC;GACN,MAAM;GACN,IAAI,MAAM;GACV,MAAM,MAAM;GACZ,OAAO,UAAU,MAAM,SAAS;EAClC,CAAC;EACH,KAAK,eACH,OAAO,CAAC;GACN,MAAM;GACN,aAAa,MAAM;GACnB,SAAS,kBAAkB,MAAM,OAAO;GACxC,GAAG,MAAM,YAAY,OAAO,EAAE,UAAU,KAAK,IAAI,CAAC;EACpD,CAAC;EACH,KAAK,oBACH,OAAO,mBAAmB,MAAM,aAAa;EAC/C,KAAK,aAAa;GAChB,MAAM,QAAQ,iBAAiB,MAAM,aAAa;GAClD,IAAI,UAAU,QAGZ,OAAO,CAAC;GAEV,IAAI,MAAM,SAAS,qBACjB,OAAO,MAAM,SAAS,SAAY,CAAC,IAAI,CAAC;IAAE,MAAM;IAAqB,MAAM,MAAM;GAAK,CAAC;GAEzF,OAAO,MAAM,cAAc,SACvB,CAAC,IACD,CAAC;IAAE,MAAM;IAAY,UAAU,MAAM;IAAM,WAAW,MAAM;GAAU,CAAC;EAC7E;EACA,SACE,OAAO,CAAC;CACZ;AACF;;;;;;AAOA,SAAS,WAAW,UAA6C;CAC/D,MAAM,SAAwB,CAAC;CAC/B,KAAK,MAAM,WAAW,UAAU;EAC9B,IAAI,QAAQ,SAAS,UAAU;EAC/B,MAAM,OAAO,QAAQ,SAAS,cAAc,cAAc;EAC1D,MAAM,SAAS,QAAQ,QAAQ,QAAQ,aAAa;EACpD,IAAI,OAAO,WAAW,GAAG;EAEzB,MAAM,WAAW,OAAO,GAAG,EAAE;EAC7B,IAAI,aAAa,UAAa,SAAS,SAAS,MAAM,SAAS,QAAQ,KAAK,GAAG,MAAM;OAChF,OAAO,KAAK;GAAE;GAAM,SAAS;EAAO,CAAC;CAC5C;CACA,OAAO;AACT;;AAGA,SAAS,SAAS,SAA8C;CAC9D,MAAM,eAAe,QAAQ,QAAQ,SAClC,QAAO,YAAW,QAAQ,SAAS,QAAQ,CAAC,CAC5C,SAAQ,YAAW,QAAQ,OAAO,CAAC,CACnC,QAAQ,UAA4D,MAAM,SAAS,MAAM,CAAC,CAC1F,KAAI,UAAS,MAAM,IAAI;CAI1B,MAAM,UAHM,QAAQ,QAAQ,WAAW,SACnC,eACA,CAAC,QAAQ,QAAQ,QAAQ,GAAG,YAAY,EAC1B,CAAC,KAAK,MAAM;CAC9B,OAAO,OAAO,WAAW,IAAI,SAAY;AAC3C;;AAGA,SAAS,aAAa,QAAoC;CACxD,IAAI,WAAW,QAAQ,OAAO,EAAE,MAAM,OAAO;CAC7C,IAAI,WAAW,QAAQ,OAAO,EAAE,MAAM,OAAO;CAE7C,IAAI,WAAW,YAAY,OAAO,EAAE,MAAM,MAAM;CAChD,OAAO;EAAE,MAAM;EAAQ,MAAM,OAAO,SAAS,WAAW,eAAe,OAAO,IAAI,IAAI,OAAO;CAAK;AACpG;AAEA,SAAS,aAAa,MAA4B;CAChD,OAAO;EAAE,MAAM,KAAK;EAAM,aAAa,KAAK;EAAa,cAAc,KAAK;CAAW;AACzF;AAEA,SAAS,eAAe,MAAsB;CAC5C,IAAI,SAAS,cAAc,OAAO;CAClC,OAAO,KAAK,WAAW,KAAK,GAAG;AACjC;AAEA,SAAS,cAAc,MAAqC;CAC1D,IAAI,KAAK,mBAAmB,UAAa,KAAK,mBAAmB,QAC/D,MAAM,IAAI,WACR,2EACA,kBAAkB,eACpB;CAEF,OAAO;EACL,MAAM;EACN,MAAM;EACN,GAAG,KAAK,YAAY,SAAY,CAAC,IAAI,EAAE,UAAU,KAAK,QAAQ;EAC9D,GAAG,KAAK,mBAAmB,SAAY,CAAC,IAAI,EAAE,iBAAiB,CAAC,GAAG,KAAK,cAAc,EAAE;EACxF,GAAG,KAAK,mBAAmB,SAAY,CAAC,IAAI,EAAE,iBAAiB,CAAC,GAAG,KAAK,cAAc,EAAE;EACxF,GAAG,KAAK,iBAAiB,SAAY,CAAC,IAAI,EACxC,eAAe;GAAE,MAAM;GAAe,GAAG,KAAK;EAAa,EAC7D;CACF;AACF;AAEA,SAAS,OAAO,MAAiC;CAC/C,IAAI,CAAC,mBAAmB,IAAI,GAAG,OAAO,aAAa,IAAI;CACvD,IAAI,KAAK,SAAS,cAAc,OAAO,cAAc,IAAI;CACzD,MAAM,IAAI,WACR,wDAAwD,KAAK,KAAK,IAClE,kBAAkB,eACpB;AACF;;;;;;;;AAkBA,SAAS,WACP,QACA,WACA,SAC0B;CAC1B,IAAI,WAAW,QAAW,OAAO;CACjC,MAAM,YAAY,QAAQ;CAC1B,IAAI,cAAc,UAAa,aAAa,GAAG,OAAO,EAAE,MAAM,WAAW;CAEzE,MAAM,SAAS,KAAK,IAAI,WAAW,KAAK,MAAM,YAAY,GAAI,CAAC;CAE/D,OAAO,SAAS,OAAQ,EAAE,MAAM,WAAW,IAAI;EAAE,MAAM;EAAW,eAAe;CAAO;AAC1F;AAEA,SAAS,aAAa,QAAqE;CACzF,IAAI,WAAW,UAAa,OAAO,SAAS,QAAQ,OAAO;CAC3D,OAAO,EAAE,QAAQ;EAAE,MAAM;EAAe,QAAQ,OAAO;CAAO,EAAE;AAClE;;;;;;;AAQA,SAAgB,0BACd,SACA,SACa;CACb,MAAM,EAAE,SAAS,SAAS;CAC1B,MAAM,SAAS,SAAS,OAAO;CAC/B,MAAM,QAAQ,KAAK,UAAU,UAAa,KAAK,MAAM,WAAW,IAC5D,SACA,KAAK,MAAM,IAAI,MAAM;CACzB,MAAM,WAAW,WACf,KAAK,oBAAoB,SAAY,SAAY,OAAO,KAAK,eAAe,GAC5E,QAAQ,WACR,QAAQ,OACV;CACA,MAAM,kBAAkB,UAAU,SAAS;CAC3C,MAAM,SAAS,aAAa,KAAK,YAAY;CAE7C,OAAO;EACL,OAAO,KAAK;EAEZ,YAAY,QAAQ;EACpB,UAAU,WAAW,KAAK,QAAQ;EAClC,GAAG,WAAW,SAAY,CAAC,IAAI,EAAE,OAAO;EACxC,GAAG,UAAU,SAAY,CAAC,IAAI,EAAE,MAAM;EACtC,GAAG,KAAK,eAAe,SAAY,CAAC,IAAI,EAAE,aAAa,aAAa,KAAK,UAAU,EAAE;EAGrF,GAAG,CAAC,mBAAmB,KAAK,gBAAgB,SACxC,EAAE,aAAa,KAAK,YAAY,IAChC,CAAC;EACL,GAAG,CAAC,mBAAmB,KAAK,SAAS,SAAY,EAAE,OAAO,KAAK,KAAK,IAAI,CAAC;EACzE,GAAG,KAAK,SAAS,UAAa,KAAK,KAAK,WAAW,IAC/C,CAAC,IACD,EAAE,gBAAgB,CAAC,GAAG,KAAK,IAAI,EAAE;EACrC,GAAG,aAAa,SAAY,CAAC,IAAI,EAAE,SAAS;EAC5C,GAAG,WAAW,SAAY,CAAC,IAAI,EAAE,eAAe,OAAO;EACvD,QAAQ;CACV;AACF;;;;;;;;;;;;;;;;;;;;;ACpUA,SAAS,UAAU,MAAiD;CAClE,QAAQ,MAAR;EACE,KAAK,QAAQ,OAAO;EACpB,KAAK;EACL,KAAK,qBAAqB,OAAO;EACjC,KAAK,YAAY,OAAO;EACxB,KAAK,mBAAmB,OAAO;EAC/B,SAAS;CACX;AACF;AAWA,SAAS,YAAY,QAA0B,OAAoC;CACjF,IAAI,OAAO,UAAU,YAAY,UAAU,MAAM;CACjD,IAAI,kBAAkB,OAAO,OAAO,QAAQ,MAAM;CAClD,IAAI,mBAAmB,OAAO,OAAO,SAAS,MAAM;CACpD,IAAI,6BAA6B,SAAS,MAAM,4BAA4B,MAC1E,OAAO,YAAY,MAAM;CAE3B,IAAI,iCAAiC,SAAS,MAAM,gCAAgC,MAClF,OAAO,aAAa,MAAM;CAE5B,OAAO,OAAO;AAChB;AAEA,SAAS,WAAW,aAA0D;CAC5E,IAAI,CAAC,YAAY,MAAM,OAAO;CAC9B,MAAM,SAAkC;EACtC,GAAG,YAAY,UAAU,SAAY,CAAC,IAAI,EAAE,aAAa,YAAY,MAAM;EAC3E,GAAG,YAAY,WAAW,SAAY,CAAC,IAAI,EAAE,cAAc,YAAY,OAAO;EAG9E,GAAG,YAAY,cAAc,UAAa,YAAY,cAAc,IAChE,CAAC,IAAI,EAAE,iBAAiB,YAAY,UAAU;EAClD,GAAG,YAAY,eAAe,UAAa,YAAY,eAAe,IAClE,CAAC,IAAI,EAAE,kBAAkB,YAAY,WAAW;CACtD;CACA,MAAM,WAAW;EACf,YAAY;EACZ,YAAY,aAAa;EACzB,YAAY,cAAc;EAC1B,YAAY;CACd;CACA,IAAI,SAAS,MAAM,iBAAiB,GAClC,OAAO,cAAc,SAAS,QAAgB,OAAO,UAAU,QAAQ,OAAO,CAAC;CAEjF,OAAO;AACT;AAEA,SAAS,kBAAkB,OAAiC;CAC1D,OAAO,OAAO,UAAU,YAAY,OAAO,cAAc,KAAK,KAAK,SAAS;AAC9E;;AAGA,SAAS,aAAa,MAAuD;CAC3E,QAAQ,MAAR;EACE,KAAK,YAAY,OAAO,EAAE,MAAM,aAAa;EAC7C,KAAK,cAAc,OAAO,EAAE,MAAM,aAAa;EAC/C,KAAK,WACH,OAAO;GACL,MAAM;GACN,SAAS;IACP,SAAS;IACT,MAAM,kBAAkB;GAC1B;EACF;EAGF,SAAS,OAAO,EAAE,MAAM,OAAO;CACjC;AACF;;AAGA,SAAS,YAAY,MAA2C;CAC9D,QAAQ,KAAK,MAAb;EACE,KAAK,QACH,OAAO;GACL,MAAM;GAAQ,MAAM,KAAK;GACzB,GAAG,KAAK,YAAY,WAAW,IAAI,CAAC,IAAI,EAAE,aAAa,KAAK,YAAY;EAC1E;EACF,KAAK,aAAa;GAChB,MAAM,QAAiC,KAAK,iBAAiB,SACzD;IAAE,MAAM;IAAqB,MAAM,KAAK;GAAa,IACrD;IACA,MAAM;IACN,GAAG,KAAK,cAAc,SAAY,CAAC,IAAI,EAAE,WAAW,KAAK,UAAU;GACrE;GACF,OAAO;IAAE,MAAM;IAAa,MAAM,KAAK;IAAM,eAAe;GAAM;EACpE;EACA,KAAK,aACH,OAAO;GACL,MAAM;GACN,IAAI,WAAW,KAAK,MAAM;GAC1B,MAAM,KAAK;GACX,WAAW,KAAK,KAAK,SAAS,IAAI,KAAK,OAAO;EAChD;EACF,KAAK,oBAAoB;GACvB,MAAM,SAAS,gBAAgB,KAAK,MAAM,KAAK,YAAY,KAAK;GAChE,MAAM,OAA+B,KAAK,cAAc;IACtD,MAAM;IAAmB,IAAI,KAAK;IAAQ,MAAM;IAAc,OAAO;GACvE;GACA,OAAO;IACL,MAAM;IAAoB,IAAI,KAAK;IACnC,MAAM,KAAK,SAAS,eAAe,eAAe,KAAK,KAAK,WAAW,KAAK,GAAG;IAC/E,WAAW;IACX,SAAS,CAAC;IACV,eAAe;KACb,MAAM;MAAE,GAAG;MAAM,OAAO;KAAO;KAC/B,GAAG,KAAK,iBAAiB,SAAY,CAAC,IAAI,EAAE,QAAQ,KAAK,aAAa;IACxE;GACF;EACF;EACA,SACE;CACJ;AACF;AAEA,SAAS,gBAAgB,KAAa,UAA+B;CACnE,IAAI,IAAI,WAAW,GAAG,OAAO,YAAY,QAAQ,IAAI,WAAW,CAAC;CACjE,IAAI;EACF,MAAM,QAAiB,KAAK,MAAM,GAAG;EACrC,OAAO,YAAY,KAAK,IAAI,QAAQ,CAAC;CACvC,QAAQ;EACN,OAAO,CAAC;CACV;AACF;AAEA,SAAS,mBAAmB,UAAoD;CAC9E,IAAI,SAAS,SAAS,gCAAgC,OAAO,SAAS,QAAQ,UAC5E;CAEF,OAAO;EACL,MAAM;EAAgB,KAAK,SAAS;EACpC,GAAG,OAAO,SAAS,UAAU,WAAW,EAAE,OAAO,SAAS,MAAM,IAAI,CAAC;EACrE,eAAe,gBAAgB,QAAQ;CACzC;AACF;;;;;;;;;;;AAYA,gBAAuB,yBACrB,QACA,aACqC;CACrC,MAAM,uBAAO,IAAI,IAAuB;CACxC,MAAM,QAA0B;EAC9B,OAAO;EAAW,QAAQ;EAAW,WAAW;EAAW,YAAY;EAAW,MAAM;CAC1F;CACA,IAAI;CACJ,IAAI,aAAa;CACjB,IAAI,gBAAgB;CAEpB,WAAW,MAAM,OAAO,QAAQ;EAC9B,IAAI;EACJ,IAAI;GACF,QAAQ,KAAK,MAAM,IAAI,IAAI;EAC7B,SAAS,OAAgB;GACvB,MAAM,IAAI,WACR,GAAG,YAAY,iCACf,kBAAkB,oBAClB,EAAE,OAAO,MAAM,CACjB;EACF;EAEA,QAAQ,MAAM,MAAd;GACE,KAAK,iBAAiB;IACpB,YAAY,OAAO,MAAM,QAAQ,KAAK;IACtC,MAAM,WAAW,WAAW,KAAK;IACjC,IAAI,aAAa,QAAW,MAAM;KAAE,MAAM;KAAkB,OAAO;IAAS;IAC5E;GACF;GAEA,KAAK,uBAAuB;IAC1B,IAAI,MAAM,cAAc,SAAS,0BAA0B;KACzD,MAAM,SAAS,MAAM;KACrB,MAAM,QAAQ,CAAC,GAAG,KAAK,OAAO,CAAC,CAAC,CAAC,MAAK,UAAS,MAAM,SAAS,sBACzD,MAAM,WAAW,OAAO,WAAW;KACxC,IAAI,UAAU,QAAW;MACvB,MAAM,eAAe;MACrB,MAAM,QAAQ,YAAY,KAAK;MAC/B,IAAI,UAAU,UAAa,CAAC,MAAM,QAAQ;OACxC,MAAM,SAAS;OACf,MAAM;QACJ,MAAM;QACN,OAAO,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,GAAG,WAAW,UAAU,KAAK,CAAC,GAAG,MAAM,MAAM;QAC9E;OACF;MACF;KACF;KACA;IACF;IACA,MAAM,OAAO,UAAU,MAAM,cAAc,IAAI;IAC/C,IAAI,SAAS,QAAW;IACxB,MAAM,QAAQ,MAAM;IACpB,MAAM,QAAmB;KACvB;KACA,MAAM,MAAM,SAAS,SACjB,MAAM,OACN,MAAM,SAAS,aAAa,MAAM,WAAW;KACjD,MAAM;KACN,QAAQ,MAAM,SAAS,aAAa,MAAM,KAAK,SAAS,MAAM;KAC9D,MAAM,MAAM,SAAS,cAAc,MAAM,SAAS,oBAAoB,MAAM,OAAO;KACnF,WAAW,MAAM,SAAS,aAAa,MAAM,YAAY;KACzD,cAAc,MAAM,SAAS,sBAAsB,MAAM,OAAO;KAChE,aAAa,CAAC;KACd,YAAY,MAAM,SAAS,oBAAoB,QAAQ;KACvD,cAAc;KACd,QAAQ;IACV;IACA,IAAI,MAAM,SAAS,mBAAmB;KACpC,MAAM,SAAS,MAAM;KACrB,MAAM,OAAO;IACf;IACA,KAAK,IAAI,MAAM,OAAO,KAAK;IAC3B,iBAAiB;IACjB,MAAM;KAAE,MAAM;KAAe,OAAO,MAAM;KAAO,WAAW;IAAK;IACjE;GACF;GAEA,KAAK,uBAAuB;IAC1B,MAAM,QAAQ,KAAK,IAAI,MAAM,KAAK;IAClC,IAAI,UAAU,QAAW;IACzB,MAAM,QAAQ,MAAM;IACpB,QAAQ,MAAM,MAAd;KACE,KAAK;MACH,MAAM,QAAQ,MAAM;MACpB,MAAM;OAAE,MAAM;OAAc,OAAO,MAAM;OAAO,MAAM,MAAM;MAAK;MACjE;KACF,KAAK;MACH,MAAM,QAAQ,MAAM;MACpB,MAAM;OAAE,MAAM;OAAmB,OAAO,MAAM;OAAO,MAAM,MAAM;MAAS;MAC1E;KACF,KAAK;MAIH,MAAM,YAAY,MAAM;MACxB;KACF,KAAK;MACH,MAAM,QAAQ,MAAM;MACpB,IAAI,MAAM,SAAS,aACjB,MAAM;OACJ,MAAM;OACN,OAAO,MAAM;OACb,IAAI,WAAW,MAAM,MAAM;OAC3B,GAAG,MAAM,KAAK,SAAS,IAAI,EAAE,MAAM,MAAM,KAAK,IAAI,CAAC;OACnD,gBAAgB,MAAM;MACxB;MAEF;KACF,KAAK,mBAAmB;MACtB,MAAM,aAAa,mBAAmB,MAAM,QAAQ;MACpD,IAAI,eAAe,QAAW,MAAM,YAAY,KAAK,UAAU;MAC/D;KACF;IAGF;IACA;GACF;GAEA,KAAK,sBAAsB;IACzB,MAAM,QAAQ,KAAK,IAAI,MAAM,KAAK;IAClC,IAAI,UAAU,QAAW;IACzB,IAAI,MAAM,SAAS,oBAAoB;IACvC,MAAM,QAAQ,YAAY,KAAK;IAC/B,IAAI,UAAU,UAAa,CAAC,MAAM,QAAQ;KACxC,MAAM,SAAS;KACf,MAAM;MAAE,MAAM;MAAa,OAAO,MAAM;MAAO;KAAM;IACvD;IACA;GACF;GAEA,KAAK,iBAAiB;IACpB,OAAO,MAAM,MAAM;IACnB,YAAY,OAAO,MAAM,KAAK;IAC9B,MAAM,WAAW,WAAW,KAAK;IACjC,IAAI,aAAa,QAAW,MAAM;KAAE,MAAM;KAAkB,OAAO;IAAS;IAC5E;GACF;GAEA,KAAK,gBAAgB;IACnB,KAAK,MAAM,CAAC,OAAO,UAAU,MAAM;KACjC,IAAI,MAAM,SAAS,sBAAsB,MAAM,QAAQ;KACvD,MAAM,QAAQ,YAAY,KAAK;KAC/B,IAAI,UAAU,QAAW,MAAM;MAAE,MAAM;MAAa;MAAO;KAAM;KACjE,MAAM,SAAS;IACjB;IACA,MAAM,SAAS,WAAW,KAAK;IAC/B,IAAI,WAAW,QAAW,MAAM;KAAE,MAAM;KAAS,OAAO;IAAO;IAC/D,IAAI,kBAAkB,GAIpB,MAAM,IAAI,WACR,GAAG,YAAY,uCACf,gBACF;IAEF,MAAM;KAAE,MAAM;KAAU,QAAQ,aAAa,IAAI;IAAE;IACnD,aAAa;IACb;GACF;GAEA,KAAK,SAAS;IACZ,MAAM,SAAS,CAAC,MAAM,MAAM,MAAM,MAAM,MAAM,OAAO,CAAC,CACnD,QAAQ,SAAyB,SAAS,MAAS,CAAC,CACpD,KAAK,GAAG;IACX,MAAM,IAAI,WACR,MAAM,MAAM,WAAW,GAAG,YAAY,2BAGtC,MAAM,MAAM,SAAS,qBACjB,kBAAkB,SAClB,yBAAyB,MAAM,MAAM,MAAM,MAAM,CACvD;GACF;EAKF;CACF;CAEA,IAAI,CAAC,YACH,MAAM,IAAI,WACR,GAAG,YAAY,oCACf,kBAAkB,aACpB;AAEJ;AAEA,SAAS,yBAAyB,MAA0B,QAAwB;CAClF,IAAI,SAAS,0BAA0B,SAAS,oBAC9C,OAAO,kBAAkB;CAE3B,IAAI,qBAAqB,MAAM,GAAG,OAAO;CACzC,IAAI,SAAS,oBAAoB,OAAO,kBAAkB;CAC1D,IAAI,SAAS,aAAa,OAAO,kBAAkB;CACnD,IAAI,6BAA6B,MAAM,GAAG,OAAO;CACjD,OAAO,kBAAkB;AAC3B;;;;;AC9YA,MAAa,iCAAiC;;;;;;;;AAS9C,MAAa,oBAAoB;;;;;;;;AASjC,MAAa,2BAA4C,OAAO,OAAO;CACrE,KAAK;CACL,KAAK;CACL,QAAQ;CACR,MAAM;AACR,CAAC;AAYD,MAAM,kBAAoC,OAAO,OAAO;CACtD,SAAS;CACT,SAAS;CACT,MAAM,OAAO,OAAO,CAAC,CAAC;AACxB,CAAC;;AA+BD,MAAa,4BAC6B,OAAO,OAAO;CACtD,MAAM;CACN,YAAY;CACZ,IAAI;CACJ,gBAAgB;CAChB,oBAAoB;CACpB,kBAAkB,aAA+B;EAC/C,qBAAqB,QAAQ;EAC7B,GAAG,QAAQ,KAAK,WAAW,IAAI,CAAC,IAAI,EAAE,kBAAkB,QAAQ,KAAK,KAAK,GAAG,EAAE;CACjF;CACA,UAAU,SAA0B,SAA8D;EAEhG,OADsB,0BAA0B,SAAS,EAAE,SAAS,QAAQ,QAAQ,CAC1E;CACZ;CAGA,YACE,QACA,UACA,gBACwC,yBAAyB,QAAQ,WAAW;AACxF,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/serialize.ts","../src/translate.ts","../src/protocol.ts"],"sourcesContent":["/**\n * Normalized request to Anthropic Messages API wire JSON.\n *\n * Two things here differ sharply from the Responses API and are easy to get wrong:\n *\n * 1. `tool_use.input` is a parsed OBJECT, not a JSON string. Our normalized block\n * keeps the raw string the model produced, so it is parsed on the way out.\n * 2. Consecutive same-role messages are MERGED. This is not cosmetic tidying —\n * when a model makes three parallel tool calls, we produce three separate\n * tool-result messages, and this API expects all three `tool_result` blocks in\n * ONE user message. Without merging, parallel tool use breaks.\n *\n * @module ai-agent-sdk/providers/anthropic/serialize\n */\n\nimport {\n isNativeToolSchema,\n type ModelOutputFormat,\n type ModelToolSchema,\n type NativeWebSearchTool,\n type ToolChoice,\n type ToolSchema,\n} from '@alvin0/ai-agent-sdk-core'\nimport { MODEL_ERROR_CODES, ModelError } from '@alvin0/ai-agent-sdk-core'\nimport type { ContentBlock, DocumentSource, ImageSource } from '@alvin0/ai-agent-sdk-core'\nimport type { Message } from '@alvin0/ai-agent-sdk-core'\nimport type { ProtocolRequest } from './contract.ts'\nimport type {\n WireCacheControl,\n WireDocumentSource,\n WireImageSource,\n WireCitation,\n WireMessage,\n WireOutputConfig,\n WireRequest,\n WireRequestBlock,\n WireSystemBlock,\n WireThinking,\n WireTool,\n WireToolChoice,\n WireToolResultContent,\n} from './wire.ts'\n\n/**\n * Adapter-private state kept on a {@link ReasoningBlock} so a thinking block can\n * be echoed back exactly.\n *\n * The signature is the load-bearing part: this API verifies it to confirm the\n * block is genuinely the model's own reasoning, and a thinking block sent back\n * without it is rejected.\n */\nexport interface AnthropicReasoningState {\n /** `thinking` for an ordinary block, `redacted_thinking` for an opaque one. */\n kind: 'thinking' | 'redacted_thinking'\n /** Cryptographic signature over the thinking content. */\n signature?: string\n /** Opaque payload of a redacted block. */\n data?: string\n}\n\n/** Read reasoning state back off a block, tolerating anything unexpected. */\nfunction reasoningStateOf(value: unknown): AnthropicReasoningState | undefined {\n if (typeof value !== 'object' || value === null) return undefined\n const state = value as AnthropicReasoningState\n if (state.kind !== 'thinking' && state.kind !== 'redacted_thinking') return undefined\n return {\n kind: state.kind,\n ...typeof state.signature === 'string' ? { signature: state.signature } : {},\n ...typeof state.data === 'string' ? { data: state.data } : {},\n }\n}\n\n/** Map an image source onto this API's tagged source object. */\nfunction imageSource(source: ImageSource): WireImageSource {\n if (source.kind === 'url') return { type: 'url', url: source.url }\n if (source.kind === 'base64') {\n return { type: 'base64', media_type: source.mediaType, data: source.data }\n }\n throw new ModelError(\n 'Anthropic image inputs support URL or base64 sources, not file ids',\n MODEL_ERROR_CODES.INVALID_REQUEST,\n )\n}\n\n/**\n * Map a document source onto this API's tagged source object.\n *\n * All three variants are supported here, including the file id that\n * {@link imageSource} has to reject.\n */\nfunction documentSource(source: DocumentSource): WireDocumentSource {\n if (source.kind === 'url') return { type: 'url', url: source.url }\n if (source.kind === 'file') return { type: 'file', file_id: source.fileId }\n return { type: 'base64', media_type: source.mediaType, data: source.data }\n}\n\n/** Restrict tool-result content to the block types this API accepts there. */\nfunction toolResultContent(blocks: readonly ContentBlock[]): WireToolResultContent[] | string {\n const parts: WireToolResultContent[] = []\n let textOnly = true\n for (const block of blocks) {\n if (block.type === 'text') parts.push({ type: 'text', text: block.text })\n else if (block.type === 'image') {\n textOnly = false\n parts.push({ type: 'image', source: imageSource(block.source) })\n }\n // Anything else (a nested tool result, an extension block) has no\n // representation inside a tool result and is dropped rather than guessed at.\n }\n if (textOnly) {\n return parts.map(part => (part.type === 'text' ? part.text : '')).join('\\n')\n }\n return parts\n}\n\n/** Parse tool-call arguments into the object this API expects. */\nfunction toolInput(raw: string): unknown {\n if (raw.trim().length === 0) return {}\n try {\n return JSON.parse(raw) as unknown\n } catch {\n // The model emitted invalid JSON. Sending `{}` keeps the conversation\n // well-formed so the tool layer can report the problem back to the model,\n // which is recoverable; failing the request here is not.\n return {}\n }\n}\n\nfunction citationOf(value: unknown): WireCitation | undefined {\n if (typeof value !== 'object' || value === null) return undefined\n const citation = value as Record<string, unknown>\n return typeof citation.type === 'string' ? structuredClone(citation) as WireCitation : undefined\n}\n\nfunction nativeReplayBlocks(value: unknown): WireRequestBlock[] {\n if (typeof value !== 'object' || value === null) return []\n const state = value as Record<string, unknown>\n const values = [state.call, state.result]\n return values.flatMap((candidate): WireRequestBlock[] => {\n if (typeof candidate !== 'object' || candidate === null) return []\n const block = candidate as Record<string, unknown>\n if (block.type === 'server_tool_use'\n && typeof block.id === 'string'\n && typeof block.name === 'string') {\n return [{\n type: 'server_tool_use', id: block.id, name: block.name,\n input: structuredClone(block.input ?? {}),\n }]\n }\n if (block.type === 'web_search_tool_result' && typeof block.tool_use_id === 'string') {\n return [{\n type: 'web_search_tool_result', tool_use_id: block.tool_use_id,\n content: structuredClone(block.content),\n ...block.caller === undefined ? {} : { caller: structuredClone(block.caller) },\n }]\n }\n return []\n })\n}\n\n/** Convert one normalized block to zero or more wire blocks. */\nfunction requestBlocks(block: ContentBlock): WireRequestBlock[] {\n switch (block.type) {\n case 'text': {\n // Whitespace-only text is rejected by this API, so it is dropped.\n if (block.text.trim().length === 0) return []\n const citations = block.annotations?.flatMap((annotation): WireCitation[] => {\n if (annotation.type !== 'url-citation') return []\n const citation = citationOf(annotation.providerState)\n return citation === undefined ? [] : [citation]\n })\n return [{\n type: 'text', text: block.text,\n ...citations === undefined || citations.length === 0 ? {} : { citations },\n }]\n }\n case 'image':\n return [{ type: 'image', source: imageSource(block.source) }]\n case 'document': {\n // `title` is what a citation is attributed to, so the file name is a much\n // better fallback than leaving it unset.\n const title = block.title ?? block.filename\n return [{\n type: 'document',\n source: documentSource(block.source),\n ...title === undefined ? {} : { title },\n ...block.context === undefined ? {} : { context: block.context },\n ...block.citations === undefined ? {} : { citations: { enabled: block.citations } },\n }]\n }\n case 'tool-call':\n return [{\n type: 'tool_use',\n id: block.id,\n name: block.name,\n input: toolInput(block.arguments),\n }]\n case 'tool-result':\n return [{\n type: 'tool_result',\n tool_use_id: block.toolCallId,\n content: toolResultContent(block.content),\n ...block.isError === true ? { is_error: true } : {},\n }]\n case 'native-tool-call':\n return nativeReplayBlocks(block.providerState)\n case 'reasoning': {\n const state = reasoningStateOf(block.providerState)\n if (state === undefined) {\n // No signature means this cannot be replayed as a thinking block. Dropping\n // it is correct: sending unsigned thinking is rejected outright.\n return []\n }\n if (state.kind === 'redacted_thinking') {\n return state.data === undefined ? [] : [{ type: 'redacted_thinking', data: state.data }]\n }\n return state.signature === undefined\n ? []\n : [{ type: 'thinking', thinking: block.text, signature: state.signature }]\n }\n default:\n return []\n }\n}\n\n/**\n * Build the message list, merging consecutive same-role messages.\n *\n * See the module note for why merging matters.\n * @param messages - the normalized conversation.\n * @param cacheControl - when set, attached to the LAST block of the\n * SECOND-TO-LAST wire message — everything but the newest turn, which is\n * the only part of the history that changed since the previous request.\n * A history of fewer than two wire messages has nothing stable to mark yet.\n */\nfunction messagesOf(\n messages: readonly Message[],\n cacheControl: WireCacheControl | undefined,\n): WireMessage[] {\n const result: WireMessage[] = []\n for (const message of messages) {\n if (message.role === 'system') continue // hoisted to the `system` field\n const role = message.role === 'assistant' ? 'assistant' : 'user'\n const blocks = message.content.flatMap(requestBlocks)\n if (blocks.length === 0) continue\n\n const previous = result.at(-1)\n if (previous !== undefined && previous.role === role) previous.content.push(...blocks)\n else result.push({ role, content: blocks })\n }\n if (cacheControl !== undefined && result.length >= 2) {\n const boundary = result[result.length - 2]\n const lastBlock = boundary?.content.at(-1)\n if (lastBlock !== undefined) lastBlock.cache_control = cacheControl\n }\n return result\n}\n\n/**\n * Collect the system prompt from the request plus any system-role messages.\n * @param request - the resolved request.\n * @param cacheControl - when set, the joined text comes back as ONE block\n * carrying this breakpoint instead of a plain string — the system prompt is\n * as stable a prefix as a conversation has, so it is always the first thing\n * marked when caching is on.\n */\nfunction systemOf(\n request: ProtocolRequest,\n cacheControl: WireCacheControl | undefined,\n): string | WireSystemBlock[] | undefined {\n const fromMessages = request.options.messages\n .filter(message => message.role === 'system')\n .flatMap(message => message.content)\n .filter((block): block is Extract<ContentBlock, { type: 'text' }> => block.type === 'text')\n .map(block => block.text)\n const all = request.options.system === undefined\n ? fromMessages\n : [request.options.system, ...fromMessages]\n const joined = all.join('\\n\\n')\n if (joined.length === 0) return undefined\n if (cacheControl === undefined) return joined\n return [{ type: 'text', text: joined, cache_control: cacheControl }]\n}\n\n/** Map the neutral tool-choice vocabulary onto this API's. */\nfunction toolChoiceOf(choice: ToolChoice): WireToolChoice {\n if (choice === 'auto') return { type: 'auto' }\n if (choice === 'none') return { type: 'none' }\n // \"call some tool\" is spelled `any` here, not `required`.\n if (choice === 'required') return { type: 'any' }\n return { type: 'tool', name: choice.type === 'native' ? nativeToolName(choice.name) : choice.name }\n}\n\nfunction functionTool(tool: ToolSchema): WireTool {\n return { name: tool.name, description: tool.description, input_schema: tool.parameters }\n}\n\nfunction nativeToolName(name: string): string {\n if (name === 'web-search') return 'web_search'\n return name.replaceAll('-', '_')\n}\n\nfunction webSearchTool(tool: NativeWebSearchTool): WireTool {\n if (tool.allowedDomains !== undefined && tool.blockedDomains !== undefined) {\n throw new ModelError(\n 'Anthropic web search accepts allowedDomains or blockedDomains, not both',\n MODEL_ERROR_CODES.INVALID_REQUEST,\n )\n }\n return {\n type: 'web_search_20250305',\n name: 'web_search',\n ...tool.maxUses === undefined ? {} : { max_uses: tool.maxUses },\n ...tool.allowedDomains === undefined ? {} : { allowed_domains: [...tool.allowedDomains] },\n ...tool.blockedDomains === undefined ? {} : { blocked_domains: [...tool.blockedDomains] },\n ...tool.userLocation === undefined ? {} : {\n user_location: { type: 'approximate', ...tool.userLocation },\n },\n }\n}\n\nfunction toolOf(tool: ModelToolSchema): WireTool {\n if (!isNativeToolSchema(tool)) return functionTool(tool)\n if (tool.name === 'web-search') return webSearchTool(tool)\n throw new ModelError(\n `Anthropic does not support the provider-native tool '${tool.name}'`,\n MODEL_ERROR_CODES.INVALID_REQUEST,\n )\n}\n\n/** How a reasoning effort becomes a thinking token budget, for `reasoningFormat: 'thinking-budget'`. */\nexport type ThinkingBudgets = Readonly<Record<string, number>>\n\n/** Which field carries reasoning effort on the wire. */\nexport type AnthropicReasoningFormat = 'output-config' | 'thinking-budget'\n\n/** Options controlling how the request is built. */\nexport interface AnthropicSerializeOptions {\n /**\n * `'output-config'` (default, current models): effort is pass-through —\n * sent verbatim as `output_config.effort`, exactly what the caller gave.\n * `'thinking-budget'` (older models, or a gateway that only understands a\n * token budget): effort is looked up in `budgets` and converted to\n * `thinking.budget_tokens` instead — the SDK does the conversion because the\n * endpoint has no `effort` field to receive the raw string at all.\n */\n reasoningFormat?: AnthropicReasoningFormat\n /** Effort id to thinking-token budget; only consulted under `'thinking-budget'`. */\n budgets: ThinkingBudgets\n /**\n * Extended-thinking mode, sent only when set — omission means \"say nothing\",\n * which is this API's own way of leaving the model's default behavior alone.\n * Ignored under `'thinking-budget'`, which derives `thinking` from the effort instead.\n */\n thinking?: 'adaptive' | 'disabled'\n /**\n * Mark the stable prefix of one request as a cache breakpoint: the system\n * prompt, the last tool definition (if any), and every message but the\n * newest — up to 3 of this API's 4-breakpoint ceiling, leaving one spare.\n * A conversation resending its whole history on every turn (this API is\n * stateless) pays full price for that history without this; with it, a\n * later turn reads the unchanged prefix at a steep discount instead of\n * paying to reprocess it.\n *\n * Off by default: not every account or Anthropic-COMPATIBLE gateway\n * behind this same adapter understands `cache_control`, and a route that\n * doesn't should not silently be asked to. See `dialectOf()` in\n * `provider-anthropic/src/adapter.ts` for the live-discovered fallback\n * that turns this off automatically, permanently, the first time a\n * gateway rejects it.\n */\n promptCaching?: boolean\n /** Cache breakpoint lifetime. Defaults to this API's own default (5 minutes). */\n promptCachingTtl?: '5m' | '1h'\n}\n\n/**\n * Last-resort `max_tokens`, used only when neither the caller, the model, nor\n * the route names one. This API rejects a request that omits the field\n * entirely, unlike most others — see {@link serializeAnthropicRequest}.\n */\nexport const DEFAULT_MAX_TOKENS = 8_192\n\n/**\n * Resolve the `thinking` field under `reasoningFormat: 'thinking-budget'`.\n *\n * The budget must leave room for a real answer, so it is capped below\n * `max_tokens` — this API requires `budget_tokens < max_tokens` and rejects the\n * request otherwise.\n */\nfunction thinkingFromBudget(\n effort: string | undefined,\n maxTokens: number,\n budgets: ThinkingBudgets,\n): WireThinking | undefined {\n if (effort === undefined) return undefined\n const requested = budgets[effort]\n if (requested === undefined || requested <= 0) return { type: 'disabled' }\n // Leave at least a quarter of the budget for the visible answer.\n const capped = Math.min(requested, Math.floor(maxTokens * 0.75))\n // This API's own floor for extended thinking.\n return capped < 1_024 ? { type: 'disabled' } : { type: 'enabled', budget_tokens: capped }\n}\n\nfunction outputConfig(\n format: ModelOutputFormat | undefined,\n effort: string | undefined,\n): WireOutputConfig | undefined {\n const formatPart = format === undefined || format.type === 'text'\n ? undefined\n : { type: 'json_schema' as const, schema: format.schema }\n if (formatPart === undefined && effort === undefined) return undefined\n return {\n ...(formatPart === undefined ? {} : { format: formatPart }),\n ...(effort === undefined ? {} : { effort }),\n }\n}\n\n/**\n * Build the Messages request body.\n * @param request - the resolved request, model, and connection.\n * @param options - which field carries effort, its budget table, and the\n * explicit-thinking switch.\n * @returns the wire body, ready to serialize.\n */\nexport function serializeAnthropicRequest(\n request: ProtocolRequest,\n options: AnthropicSerializeOptions,\n): WireRequest {\n const { options: call } = request\n const cacheControl: WireCacheControl | undefined = options.promptCaching === true\n ? { type: 'ephemeral', ...(options.promptCachingTtl === undefined ? {} : { ttl: options.promptCachingTtl }) }\n : undefined\n const system = systemOf(request, cacheControl)\n const tools = call.tools === undefined || call.tools.length === 0\n ? undefined\n : call.tools.map(toolOf)\n // The LAST tool carries the breakpoint: tool definitions are serialized in\n // one fixed block ahead of every message, so marking the final one caches\n // the whole list — same reasoning as the system prompt.\n if (cacheControl !== undefined && tools !== undefined) {\n const lastTool = tools[tools.length - 1]\n if (lastTool !== undefined) lastTool.cache_control = cacheControl\n }\n // Required by this API — unlike most others, omitting it is an error — so\n // this is the one field the SDK still defaults on the caller's behalf when\n // nothing upstream (caller, model, or route) named a value.\n const maxTokens = request.maxTokens ?? DEFAULT_MAX_TOKENS\n const reasoningFormat = options.reasoningFormat ?? 'output-config'\n const effort = call.reasoningEffort === undefined ? undefined : String(call.reasoningEffort)\n const budgetThinking = reasoningFormat === 'thinking-budget'\n ? thinkingFromBudget(effort, maxTokens, options.budgets)\n : undefined\n // Under 'output-config', `thinking` is an independent, explicit switch — not\n // derived from effort — so it is sent only when the caller configured one.\n const thinking = reasoningFormat === 'thinking-budget'\n ? budgetThinking\n : options.thinking === undefined\n ? undefined\n : options.thinking === 'adaptive' ? { type: 'adaptive' as const } : { type: 'disabled' as const }\n const output = outputConfig(call.outputFormat, reasoningFormat === 'output-config' ? effort : undefined)\n\n return {\n model: call.model,\n max_tokens: maxTokens,\n messages: messagesOf(call.messages, cacheControl),\n ...system === undefined ? {} : { system },\n ...tools === undefined ? {} : { tools },\n ...call.toolChoice === undefined ? {} : { tool_choice: toolChoiceOf(call.toolChoice) },\n // Pass-through: the caller's own sampling choices are forwarded as given.\n // An endpoint that rejects temperature/top_p alongside thinking says so in\n // its own error — the SDK no longer guesses and drops them first.\n ...call.temperature === undefined ? {} : { temperature: call.temperature },\n ...call.topP === undefined ? {} : { top_p: call.topP },\n ...call.stop === undefined || call.stop.length === 0\n ? {}\n : { stop_sequences: [...call.stop] },\n ...thinking === undefined ? {} : { thinking },\n ...output === undefined ? {} : { output_config: output },\n stream: true,\n }\n}\n","/**\n * Anthropic Messages API SSE events to the SDK's chunk protocol.\n *\n * Notable differences from the Responses translation:\n *\n * - Block indices come straight from the provider. This API numbers content\n * blocks contiguously from zero in emission order, which is already exactly\n * what our protocol wants, so no remapping is needed.\n * - Usage arrives in TWO places: input counts on `message_start`, output counts on\n * `message_delta`. Cumulative snapshots are emitted as usage-progress; the\n * final usage is emitted once at message_stop, before the finish.\n * - `input_tokens` here already EXCLUDES cached tokens, so unlike the Responses\n * translation nothing is subtracted. Getting this backwards would under-report\n * input on every cached call.\n *\n * @module ai-agent-sdk/providers/anthropic/translate\n */\n\nimport {\n CONTEXT_WINDOW_EXCEEDED_CODE,\n MODEL_ERROR_CODES,\n ModelError,\n QUOTA_EXCEEDED_CODE,\n isContextWindowExceededError,\n isQuotaExceededError,\n} from '@alvin0/ai-agent-sdk-core'\nimport { ToolCallId } from '@alvin0/ai-agent-sdk-core'\nimport { isJsonValue, type JsonValue } from '@alvin0/ai-agent-sdk-core'\nimport type { ContentBlock, TextAnnotation } from '@alvin0/ai-agent-sdk-core'\nimport type { FinishReason, UsageCounters } from '@alvin0/ai-agent-sdk-core'\nimport type { ProtocolSseEvent, ProtocolStreamChunk } from './contract.ts'\nimport type { AnthropicReasoningState } from './serialize.ts'\nimport type {\n WireCitation,\n WireServerToolUseBlock,\n WireStopReason,\n WireStreamEvent,\n WireUsage,\n WireWebSearchToolResultBlock,\n} from './wire.ts'\n\n/** Which of our block types one wire block maps to. */\ntype BlockKind = 'text' | 'reasoning' | 'tool-call' | 'native-tool-call'\n\ninterface OpenBlock {\n readonly kind: BlockKind\n text: string\n args: string\n callId: string\n name: string\n signature: string | undefined\n redactedData: string | undefined\n annotations: TextAnnotation[]\n nativeCall: WireServerToolUseBlock | undefined\n nativeResult: WireWebSearchToolResultBlock | undefined\n closed: boolean\n}\n\nfunction blockKind(type: string | undefined): BlockKind | undefined {\n switch (type) {\n case 'text': return 'text'\n case 'thinking':\n case 'redacted_thinking': return 'reasoning'\n case 'tool_use': return 'tool-call'\n case 'server_tool_use': return 'native-tool-call'\n default: return undefined\n }\n}\n\n/** Accumulated token counts, filled from two different events. */\ninterface UsageAccumulator {\n input: unknown\n output: unknown\n cacheRead: unknown\n cacheWrite: unknown\n seen: boolean\n}\n\nfunction absorbUsage(target: UsageAccumulator, usage: WireUsage | undefined): void {\n if (typeof usage !== 'object' || usage === null) return\n if ('input_tokens' in usage) target.input = usage.input_tokens\n if ('output_tokens' in usage) target.output = usage.output_tokens\n if ('cache_read_input_tokens' in usage && usage.cache_read_input_tokens !== null) {\n target.cacheRead = usage.cache_read_input_tokens\n }\n if ('cache_creation_input_tokens' in usage && usage.cache_creation_input_tokens !== null) {\n target.cacheWrite = usage.cache_creation_input_tokens\n }\n target.seen = true\n}\n\nfunction finalUsage(accumulated: UsageAccumulator): UsageCounters | undefined {\n if (!accumulated.seen) return undefined\n const output: Record<string, unknown> = {\n ...accumulated.input === undefined ? {} : { inputTokens: accumulated.input },\n ...accumulated.output === undefined ? {} : { outputTokens: accumulated.output },\n // Cache omission/null is authoritative zero for this protocol. Invalid\n // present values are retained so the accounting boundary can record them.\n ...accumulated.cacheRead === undefined || accumulated.cacheRead === 0\n ? {} : { cacheReadTokens: accumulated.cacheRead },\n ...accumulated.cacheWrite === undefined || accumulated.cacheWrite === 0\n ? {} : { cacheWriteTokens: accumulated.cacheWrite },\n }\n const counters = [\n accumulated.input,\n accumulated.cacheRead ?? 0,\n accumulated.cacheWrite ?? 0,\n accumulated.output,\n ]\n if (counters.every(validUsageCounter)) {\n output.totalTokens = counters.reduce<number>((total, value) => total + value, 0)\n }\n return output as UsageCounters\n}\n\nfunction validUsageCounter(value: unknown): value is number {\n return typeof value === 'number' && Number.isSafeInteger(value) && value >= 0\n}\n\n/** Map this API's stop reason onto ours. */\nfunction finishReason(stop: WireStopReason | null | undefined): FinishReason {\n switch (stop) {\n case 'tool_use': return { kind: 'tool-calls' }\n case 'max_tokens': return { kind: 'max-tokens' }\n case 'refusal':\n return {\n kind: 'error',\n failure: {\n message: 'the model refused to answer',\n code: MODEL_ERROR_CODES.INVALID_REQUEST,\n },\n }\n // `end_turn`, `stop_sequence`, and `pause_turn` all mean the turn produced a\n // complete answer as far as a caller is concerned.\n default: return { kind: 'stop' }\n }\n}\n\n/** Build the authoritative block for a completed content block. */\nfunction closedBlock(open: OpenBlock): ContentBlock | undefined {\n switch (open.kind) {\n case 'text':\n return {\n type: 'text', text: open.text,\n ...open.annotations.length === 0 ? {} : { annotations: open.annotations },\n }\n case 'reasoning': {\n const state: AnthropicReasoningState = open.redactedData !== undefined\n ? { kind: 'redacted_thinking', data: open.redactedData }\n : {\n kind: 'thinking',\n ...open.signature === undefined ? {} : { signature: open.signature },\n }\n return { type: 'reasoning', text: open.text, providerState: state }\n }\n case 'tool-call':\n return {\n type: 'tool-call',\n id: ToolCallId(open.callId),\n name: open.name,\n arguments: open.args.length > 0 ? open.args : '{}',\n }\n case 'native-tool-call': {\n const parsed = parsedArguments(open.args, open.nativeCall?.input)\n const call: WireServerToolUseBlock = open.nativeCall ?? {\n type: 'server_tool_use', id: open.callId, name: 'web_search', input: parsed,\n }\n return {\n type: 'native-tool-call', id: open.callId,\n name: open.name === 'web_search' ? 'web-search' : open.name.replaceAll('_', '-'),\n arguments: parsed,\n content: [],\n providerState: {\n call: { ...call, input: parsed },\n ...open.nativeResult === undefined ? {} : { result: open.nativeResult },\n },\n }\n }\n default:\n return undefined\n }\n}\n\nfunction parsedArguments(raw: string, fallback?: unknown): JsonValue {\n if (raw.length === 0) return isJsonValue(fallback) ? fallback : {}\n try {\n const value: unknown = JSON.parse(raw)\n return isJsonValue(value) ? value : {}\n } catch {\n return {}\n }\n}\n\nfunction citationAnnotation(citation: WireCitation): TextAnnotation | undefined {\n if (citation.type !== 'web_search_result_location' || typeof citation.url !== 'string') {\n return undefined\n }\n return {\n type: 'url-citation', url: citation.url,\n ...typeof citation.title === 'string' ? { title: citation.title } : {},\n providerState: structuredClone(citation),\n }\n}\n\n/**\n * Translate one Messages SSE stream.\n *\n * Owns termination. There is no `[DONE]` sentinel: the stream ends on\n * `message_stop`, and a body that ends before that was truncated — a failure\n * rather than a short answer.\n * @param events - decoded SSE events.\n * @param displayName - provider name, used in diagnostics.\n * @returns the chunk stream.\n */\nexport async function* translateAnthropicStream(\n events: AsyncIterable<ProtocolSseEvent>,\n displayName: string,\n): AsyncGenerator<ProtocolStreamChunk> {\n const open = new Map<number, OpenBlock>()\n const usage: UsageAccumulator = {\n input: undefined, output: undefined, cacheRead: undefined, cacheWrite: undefined, seen: false,\n }\n let stop: WireStopReason | null | undefined\n let terminated = false\n let emittedBlocks = 0\n\n for await (const raw of events) {\n let event: WireStreamEvent\n try {\n event = JSON.parse(raw.data) as WireStreamEvent\n } catch (error: unknown) {\n throw new ModelError(\n `${displayName} sent a malformed stream event`,\n MODEL_ERROR_CODES.MALFORMED_RESPONSE,\n { cause: error },\n )\n }\n\n switch (event.type) {\n case 'message_start': {\n absorbUsage(usage, event.message.usage)\n const progress = finalUsage(usage)\n if (progress !== undefined) yield { type: 'usage-progress', usage: progress }\n break\n }\n\n case 'content_block_start': {\n if (event.content_block.type === 'web_search_tool_result') {\n const result = event.content_block\n const owner = [...open.values()].find(entry => entry.kind === 'native-tool-call'\n && entry.callId === result.tool_use_id)\n if (owner !== undefined) {\n owner.nativeResult = result\n const block = closedBlock(owner)\n if (block !== undefined && !owner.closed) {\n owner.closed = true\n yield {\n type: 'block-end',\n index: [...open.entries()].find(([, entry]) => entry === owner)?.[0] ?? event.index,\n block,\n }\n }\n }\n break\n }\n const kind = blockKind(event.content_block.type)\n if (kind === undefined) break\n const block = event.content_block\n const entry: OpenBlock = {\n kind,\n text: block.type === 'text'\n ? block.text\n : block.type === 'thinking' ? block.thinking : '',\n args: '',\n callId: block.type === 'tool_use' ? block.id : `block-${event.index}`,\n name: block.type === 'tool_use' || block.type === 'server_tool_use' ? block.name : '',\n signature: block.type === 'thinking' ? block.signature : undefined,\n redactedData: block.type === 'redacted_thinking' ? block.data : undefined,\n annotations: [],\n nativeCall: block.type === 'server_tool_use' ? block : undefined,\n nativeResult: undefined,\n closed: false,\n }\n if (block.type === 'server_tool_use') {\n entry.callId = block.id\n entry.args = ''\n }\n open.set(event.index, entry)\n emittedBlocks += 1\n yield { type: 'block-start', index: event.index, blockType: kind }\n break\n }\n\n case 'content_block_delta': {\n const entry = open.get(event.index)\n if (entry === undefined) break\n const delta = event.delta\n switch (delta.type) {\n case 'text_delta':\n entry.text += delta.text\n yield { type: 'text-delta', index: event.index, text: delta.text }\n break\n case 'thinking_delta':\n entry.text += delta.thinking\n yield { type: 'reasoning-delta', index: event.index, text: delta.thinking }\n break\n case 'signature_delta':\n // Arrives once, just before the block closes. It carries no visible\n // content, so it produces no chunk — only the state needed to replay\n // this thinking block on a later request.\n entry.signature = delta.signature\n break\n case 'input_json_delta':\n entry.args += delta.partial_json\n if (entry.kind === 'tool-call') {\n yield {\n type: 'tool-call-delta',\n index: event.index,\n id: ToolCallId(entry.callId),\n ...entry.name.length > 0 ? { name: entry.name } : {},\n argumentsDelta: delta.partial_json,\n }\n }\n break\n case 'citations_delta': {\n const annotation = citationAnnotation(delta.citation)\n if (annotation !== undefined) entry.annotations.push(annotation)\n break\n }\n default:\n break\n }\n break\n }\n\n case 'content_block_stop': {\n const entry = open.get(event.index)\n if (entry === undefined) break\n if (entry.kind === 'native-tool-call') break\n const block = closedBlock(entry)\n if (block !== undefined && !entry.closed) {\n entry.closed = true\n yield { type: 'block-end', index: event.index, block }\n }\n break\n }\n\n case 'message_delta': {\n stop = event.delta.stop_reason\n absorbUsage(usage, event.usage)\n const progress = finalUsage(usage)\n if (progress !== undefined) yield { type: 'usage-progress', usage: progress }\n break\n }\n\n case 'message_stop': {\n for (const [index, entry] of open) {\n if (entry.kind !== 'native-tool-call' || entry.closed) continue\n const block = closedBlock(entry)\n if (block !== undefined) yield { type: 'block-end', index, block }\n entry.closed = true\n }\n const mapped = finalUsage(usage)\n if (mapped !== undefined) yield { type: 'usage', usage: mapped }\n if (emittedBlocks === 0) {\n // A clean stop with no content at all. Reported as a failure rather\n // than an empty message, because an empty message ends the turn with\n // nothing for the caller to act on — and it is safe to retry.\n throw new ModelError(\n `${displayName} returned a response with no content`,\n 'EMPTY_RESPONSE',\n )\n }\n yield { type: 'finish', reason: finishReason(stop) }\n terminated = true\n return\n }\n\n case 'error': {\n const detail = [event.error.type, event.error.message]\n .filter((part): part is string => part !== undefined)\n .join(' ')\n throw new ModelError(\n event.error.message ?? `${displayName} reported a stream error`,\n // `overloaded_error` mid-stream is the common case and must stay\n // retryable, which the shared 5xx mapping gives us.\n event.error.type === 'overloaded_error'\n ? MODEL_ERROR_CODES.SERVER\n : anthropicStreamErrorCode(event.error.type, detail),\n )\n }\n\n // `ping` and any future event carry nothing this protocol needs.\n default:\n break\n }\n }\n\n if (!terminated) {\n throw new ModelError(\n `${displayName} stream ended before message_stop`,\n MODEL_ERROR_CODES.STREAM_CLOSED,\n )\n }\n}\n\nfunction anthropicStreamErrorCode(type: string | undefined, detail: string): string {\n if (type === 'authentication_error' || type === 'permission_error') {\n return MODEL_ERROR_CODES.AUTH\n }\n if (isQuotaExceededError(detail)) return QUOTA_EXCEEDED_CODE\n if (type === 'rate_limit_error') return MODEL_ERROR_CODES.RATE_LIMIT\n if (type === 'api_error') return MODEL_ERROR_CODES.SERVER\n if (isContextWindowExceededError(detail)) return CONTEXT_WINDOW_EXCEEDED_CODE\n return MODEL_ERROR_CODES.INVALID_REQUEST\n}\n","/**\n * The Anthropic Messages protocol, as a reusable {@link WireProtocol}.\n *\n * @module ai-agent-sdk/providers/protocols/anthropic-messages\n */\n\nimport type {\n ProtocolDefinition,\n ProtocolRequest,\n ProtocolSseEvent,\n ProtocolStreamChunk,\n} from './contract.ts'\nimport type { ModelTarget, ResolvedModelInfo } from '@alvin0/ai-agent-sdk-core/provider'\nimport { serializeAnthropicRequest, type AnthropicReasoningFormat, type ThinkingBudgets } from './serialize.ts'\nimport { translateAnthropicStream } from './translate.ts'\n\n/** Protocol id, usable as a stable string in configuration. */\nexport const ANTHROPIC_MESSAGES_PROTOCOL_ID = 'anthropic-messages'\n\n/**\n * The API version header value.\n *\n * Mandatory on every request. Stable across the entire lifetime of this API — new\n * capabilities arrive as opt-in beta headers rather than a version bump — which is\n * why it lives on the protocol instead of being restated by each endpoint.\n */\nexport const ANTHROPIC_VERSION = '2023-06-01'\n\n/**\n * Default reasoning efforts, expressed as thinking-token budgets.\n *\n * Budgets rather than an opaque level because that is what this API takes. The\n * SDK's effort ids are a neutral surface over a provider-specific knob, and\n * mapping them here is the whole reason `ReasoningEffortId` is opaque.\n */\nexport const DEFAULT_THINKING_BUDGETS: ThinkingBudgets = Object.freeze({\n off: 0,\n low: 2_048,\n medium: 8_192,\n high: 24_576,\n})\n\n/** Per-endpoint knobs of the Messages protocol. */\nexport interface AnthropicDialect {\n /**\n * Which field carries reasoning effort. `'output-config'` (default) is pure\n * pass-through — the caller's effort string reaches `output_config.effort`\n * unchanged, current GA behavior. `'thinking-budget'` is for an older model\n * or a gateway that only understands a token budget: the SDK converts effort\n * to `thinking.budget_tokens` using `budgets` instead of sending it raw.\n */\n readonly reasoningFormat: AnthropicReasoningFormat\n /** Effort id to thinking-token budget; only consulted under `'thinking-budget'`. */\n readonly budgets: ThinkingBudgets\n /**\n * Extended-thinking mode, sent only when set. Independent of effort under\n * `'output-config'` — omission leaves the model's own default thinking\n * behavior alone rather than the SDK guessing one.\n */\n readonly thinking?: 'adaptive' | 'disabled'\n /** `anthropic-version` header value. */\n readonly version: string\n /** Opt-in beta features, sent as `anthropic-beta`. */\n readonly beta: readonly string[]\n /**\n * Marks the stable prefix (system, tools, everything but the newest\n * message) as a cache breakpoint. See `AnthropicSerializeOptions`'s doc\n * comment in `serialize.ts` for why, and off by default for the same\n * \"not every gateway understands this\" reason `reasoningFormat` is opt-in.\n */\n readonly promptCaching: boolean\n /** Cache breakpoint lifetime; unset defers to this API's own default. */\n readonly promptCachingTtl?: '5m' | '1h'\n}\n\nconst DEFAULT_DIALECT: AnthropicDialect = Object.freeze({\n reasoningFormat: 'output-config' as const,\n budgets: DEFAULT_THINKING_BUDGETS,\n version: ANTHROPIC_VERSION,\n beta: Object.freeze([]),\n promptCaching: false,\n})\n\ninterface RuntimeProtocolRequest extends ProtocolRequest {\n readonly model: ResolvedModelInfo\n readonly connection: {\n readonly baseUrl: string\n readonly headers: Readonly<Record<string, string>>\n }\n}\n\n/** Marker-based runtime view, kept structurally independent from provider-http. */\nexport interface AnthropicMessagesProtocolDefinition {\n readonly kind: 'http-wire-protocol'\n readonly apiVersion: 1\n readonly id: string\n readonly defaultDialect: AnthropicDialect\n readonly exampleModel?: ModelTarget\n readonly endpointPath: (request: RuntimeProtocolRequest, dialect: AnthropicDialect) => string\n readonly protocolHeaders?: (dialect: AnthropicDialect) => Readonly<Record<string, string>>\n readonly serialize: (\n request: RuntimeProtocolRequest,\n dialect: AnthropicDialect,\n ) => Readonly<Record<string, unknown>>\n readonly translate: (\n events: AsyncIterable<ProtocolSseEvent>,\n request: RuntimeProtocolRequest,\n displayName: string,\n ) => AsyncGenerator<ProtocolStreamChunk>\n}\n\n/** The Anthropic Messages wire protocol. */\nexport const anthropicMessagesProtocol: ProtocolDefinition<AnthropicDialect>\n & AnthropicMessagesProtocolDefinition = Object.freeze({\n kind: 'http-wire-protocol' as const,\n apiVersion: 1 as const,\n id: ANTHROPIC_MESSAGES_PROTOCOL_ID,\n defaultDialect: DEFAULT_DIALECT,\n endpointPath: () => '/v1/messages',\n protocolHeaders: (dialect: AnthropicDialect) => ({\n 'anthropic-version': dialect.version,\n ...dialect.beta.length === 0 ? {} : { 'anthropic-beta': dialect.beta.join(',') },\n }),\n serialize(request: ProtocolRequest, dialect: AnthropicDialect): Readonly<Record<string, unknown>> {\n const body: unknown = serializeAnthropicRequest(request, {\n reasoningFormat: dialect.reasoningFormat,\n budgets: dialect.budgets,\n ...(dialect.thinking === undefined ? {} : { thinking: dialect.thinking }),\n promptCaching: dialect.promptCaching,\n ...(dialect.promptCachingTtl === undefined ? {} : { promptCachingTtl: dialect.promptCachingTtl }),\n })\n return body as Readonly<Record<string, unknown>>\n },\n // Params are annotated because `Object.freeze` erases the contextual typing the\n // `WireProtocol` annotation would otherwise supply.\n translate: (\n events: AsyncIterable<ProtocolSseEvent>,\n _request: ProtocolRequest,\n displayName: string,\n ): AsyncGenerator<ProtocolStreamChunk> => translateAnthropicStream(events, displayName),\n})\n\nexport type { ThinkingBudgets }\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"name": "alvin0 - chaulamdinhai",
|
|
5
5
|
"email": "chaulamdinhai@gmail.com"
|
|
6
6
|
},
|
|
7
|
-
"version": "0.1.
|
|
7
|
+
"version": "0.1.5",
|
|
8
8
|
"description": "Universal Anthropic Messages wire schema, serializer, translator, and dialect for ai-agent-sdk",
|
|
9
9
|
"license": "MIT",
|
|
10
10
|
"repository": {
|
|
@@ -38,10 +38,10 @@
|
|
|
38
38
|
"provenance": true
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
|
41
|
-
"@alvin0/ai-agent-sdk-core": "^0.1.
|
|
41
|
+
"@alvin0/ai-agent-sdk-core": "^0.1.5"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
|
-
"@alvin0/ai-agent-sdk-core": "^0.1.
|
|
44
|
+
"@alvin0/ai-agent-sdk-core": "^0.1.5",
|
|
45
45
|
"@arethetypeswrong/cli": "0.18.5",
|
|
46
46
|
"playwright": "1.62.1",
|
|
47
47
|
"publint": "0.3.24",
|