@alvin0/ai-agent-sdk-protocol-anthropic-messages 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +18 -0
- package/dist/index.d.ts +365 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +638 -0
- package/dist/index.js.map +1 -0
- package/package.json +70 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 alvin0 (chaulamdinhai) <chaulamdinhai@gmail.com>
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# @alvin0/ai-agent-sdk-protocol-anthropic-messages
|
|
2
|
+
|
|
3
|
+
Runtime: **Universal** (Edge/Worker, browser, Deno, Bun, and Node).
|
|
4
|
+
|
|
5
|
+
```sh
|
|
6
|
+
pnpm add @alvin0/ai-agent-sdk-core @alvin0/ai-agent-sdk-protocol-anthropic-messages
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
Universal Anthropic Messages wire schema, request serializer, stream translator, and dialect. It owns no endpoint, credentials, fetch implementation, filesystem access, or Node.js APIs.
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
import { anthropicMessagesProtocol } from '@alvin0/ai-agent-sdk-protocol-anthropic-messages'
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Composition: `provider-author.protocol`. Lifecycle: `inert-value`; select it in
|
|
16
|
+
`createRuntimeHttpProvider()` without any startup or cleanup obligation.
|
|
17
|
+
|
|
18
|
+
The only runtime dependency is `@alvin0/ai-agent-sdk-core`.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
import { GenerateOptions, StreamChunk, UsageCounters } from "@alvin0/ai-agent-sdk-core";
|
|
2
|
+
import { ModelTarget, ResolvedModelInfo } from "@alvin0/ai-agent-sdk-core/provider";
|
|
3
|
+
//#region src/contract.d.ts
|
|
4
|
+
/** The request fields a pure wire protocol is allowed to inspect. */
|
|
5
|
+
interface ProtocolRequest {
|
|
6
|
+
readonly options: GenerateOptions;
|
|
7
|
+
readonly maxTokens: number;
|
|
8
|
+
}
|
|
9
|
+
/** One decoded SSE event, expressed without depending on an HTTP transport. */
|
|
10
|
+
interface ProtocolSseEvent {
|
|
11
|
+
readonly event: string | undefined;
|
|
12
|
+
readonly data: string;
|
|
13
|
+
}
|
|
14
|
+
/** Protocol-internal chunks may carry a partial untrusted usage report. */
|
|
15
|
+
type ProtocolStreamChunk = Exclude<StreamChunk, {
|
|
16
|
+
readonly type: 'usage';
|
|
17
|
+
}> | {
|
|
18
|
+
readonly type: 'usage';
|
|
19
|
+
readonly usage: UsageCounters;
|
|
20
|
+
};
|
|
21
|
+
/** Structural protocol contract implemented without importing provider-http. */
|
|
22
|
+
interface ProtocolDefinition<Dialect> {
|
|
23
|
+
readonly id: string;
|
|
24
|
+
readonly defaultDialect: Dialect;
|
|
25
|
+
endpointPath(request: ProtocolRequest, dialect: Dialect): string;
|
|
26
|
+
protocolHeaders?(dialect: Dialect): Record<string, string>;
|
|
27
|
+
serialize(request: ProtocolRequest, dialect: Dialect): unknown | Promise<unknown>;
|
|
28
|
+
translate(events: AsyncIterable<ProtocolSseEvent>, request: ProtocolRequest, displayName: string): AsyncGenerator<ProtocolStreamChunk>;
|
|
29
|
+
}
|
|
30
|
+
//#endregion
|
|
31
|
+
//#region src/wire.d.ts
|
|
32
|
+
/**
|
|
33
|
+
* The Anthropic Messages API wire shapes.
|
|
34
|
+
*
|
|
35
|
+
* These types never leave this folder. Keeping the vendor vocabulary quarantined
|
|
36
|
+
* here is what lets `serialize`/`translate` be the only two places that need
|
|
37
|
+
* updating when the API changes, and it stops provider-specific field names from
|
|
38
|
+
* leaking into the core.
|
|
39
|
+
*
|
|
40
|
+
* @module ai-agent-sdk/providers/anthropic/wire
|
|
41
|
+
*/
|
|
42
|
+
/** Image bytes as the Messages API accepts them. */
|
|
43
|
+
type WireImageSource = {
|
|
44
|
+
type: 'base64';
|
|
45
|
+
media_type: string;
|
|
46
|
+
data: string;
|
|
47
|
+
} | {
|
|
48
|
+
type: 'url';
|
|
49
|
+
url: string;
|
|
50
|
+
};
|
|
51
|
+
/** A request-side content block. */
|
|
52
|
+
type WireRequestBlock = {
|
|
53
|
+
type: 'text';
|
|
54
|
+
text: string;
|
|
55
|
+
citations?: WireCitation[];
|
|
56
|
+
} | {
|
|
57
|
+
type: 'image';
|
|
58
|
+
source: WireImageSource;
|
|
59
|
+
} | {
|
|
60
|
+
type: 'tool_use';
|
|
61
|
+
id: string;
|
|
62
|
+
name: string;
|
|
63
|
+
input: unknown;
|
|
64
|
+
} | {
|
|
65
|
+
type: 'tool_result';
|
|
66
|
+
tool_use_id: string;
|
|
67
|
+
content: WireToolResultContent[] | string;
|
|
68
|
+
is_error?: boolean;
|
|
69
|
+
} |
|
|
70
|
+
/**
|
|
71
|
+
* An echoed thinking block. `signature` is mandatory on the way back: the API
|
|
72
|
+
* verifies it to confirm the block is genuinely Claude's own reasoning.
|
|
73
|
+
*/
|
|
74
|
+
{
|
|
75
|
+
type: 'thinking';
|
|
76
|
+
thinking: string;
|
|
77
|
+
signature: string;
|
|
78
|
+
} | {
|
|
79
|
+
type: 'redacted_thinking';
|
|
80
|
+
data: string;
|
|
81
|
+
} | WireServerToolUseBlock | WireWebSearchToolResultBlock;
|
|
82
|
+
interface WireServerToolUseBlock {
|
|
83
|
+
type: 'server_tool_use';
|
|
84
|
+
id: string;
|
|
85
|
+
name: string;
|
|
86
|
+
input: unknown;
|
|
87
|
+
}
|
|
88
|
+
interface WireWebSearchToolResultBlock {
|
|
89
|
+
type: 'web_search_tool_result';
|
|
90
|
+
tool_use_id: string;
|
|
91
|
+
content: unknown;
|
|
92
|
+
caller?: unknown;
|
|
93
|
+
}
|
|
94
|
+
interface WireCitation {
|
|
95
|
+
type: string;
|
|
96
|
+
[key: string]: unknown;
|
|
97
|
+
}
|
|
98
|
+
/** What a `tool_result` block may carry back to the model. */
|
|
99
|
+
type WireToolResultContent = {
|
|
100
|
+
type: 'text';
|
|
101
|
+
text: string;
|
|
102
|
+
} | {
|
|
103
|
+
type: 'image';
|
|
104
|
+
source: WireImageSource;
|
|
105
|
+
};
|
|
106
|
+
/** One request message. Only `user` and `assistant` exist; system text is a top-level field. */
|
|
107
|
+
interface WireMessage {
|
|
108
|
+
role: 'user' | 'assistant';
|
|
109
|
+
content: WireRequestBlock[];
|
|
110
|
+
}
|
|
111
|
+
/** A host function offered to the model. */
|
|
112
|
+
interface WireFunctionTool {
|
|
113
|
+
name: string;
|
|
114
|
+
description: string;
|
|
115
|
+
input_schema: Record<string, unknown>;
|
|
116
|
+
}
|
|
117
|
+
/** Anthropic-hosted web search. */
|
|
118
|
+
interface WireWebSearchTool {
|
|
119
|
+
type: 'web_search_20250305';
|
|
120
|
+
name: 'web_search';
|
|
121
|
+
max_uses?: number;
|
|
122
|
+
allowed_domains?: string[];
|
|
123
|
+
blocked_domains?: string[];
|
|
124
|
+
user_location?: {
|
|
125
|
+
type: 'approximate';
|
|
126
|
+
city?: string;
|
|
127
|
+
region?: string;
|
|
128
|
+
country?: string;
|
|
129
|
+
timezone?: string;
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
type WireTool = WireFunctionTool | WireWebSearchTool;
|
|
133
|
+
/** How the model must choose among the offered tools. */
|
|
134
|
+
type WireToolChoice = {
|
|
135
|
+
type: 'auto';
|
|
136
|
+
} | {
|
|
137
|
+
type: 'any';
|
|
138
|
+
} | {
|
|
139
|
+
type: 'none';
|
|
140
|
+
} | {
|
|
141
|
+
type: 'tool';
|
|
142
|
+
name: string;
|
|
143
|
+
};
|
|
144
|
+
/** Extended-thinking configuration. */
|
|
145
|
+
type WireThinking = {
|
|
146
|
+
type: 'enabled';
|
|
147
|
+
budget_tokens: number;
|
|
148
|
+
} | {
|
|
149
|
+
type: 'disabled';
|
|
150
|
+
};
|
|
151
|
+
interface WireOutputConfig {
|
|
152
|
+
format: {
|
|
153
|
+
type: 'json_schema';
|
|
154
|
+
schema: Readonly<Record<string, unknown>>;
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
/** The request body. */
|
|
158
|
+
interface WireRequest {
|
|
159
|
+
model: string;
|
|
160
|
+
/** REQUIRED by this API, unlike most others — the adapter always resolves one. */
|
|
161
|
+
max_tokens: number;
|
|
162
|
+
messages: WireMessage[];
|
|
163
|
+
system?: string;
|
|
164
|
+
tools?: WireTool[];
|
|
165
|
+
tool_choice?: WireToolChoice;
|
|
166
|
+
temperature?: number;
|
|
167
|
+
top_p?: number;
|
|
168
|
+
stop_sequences?: string[];
|
|
169
|
+
thinking?: WireThinking;
|
|
170
|
+
output_config?: WireOutputConfig;
|
|
171
|
+
stream?: boolean;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Token accounting.
|
|
175
|
+
*
|
|
176
|
+
* `input_tokens` already EXCLUDES cached tokens, which is why this adapter passes
|
|
177
|
+
* the counts through unchanged — providers that fold cache hits into one prompt
|
|
178
|
+
* total have to subtract them back out to honour the SDK's disjoint convention.
|
|
179
|
+
*/
|
|
180
|
+
interface WireUsage {
|
|
181
|
+
input_tokens?: number;
|
|
182
|
+
output_tokens?: number;
|
|
183
|
+
cache_creation_input_tokens?: number | null;
|
|
184
|
+
cache_read_input_tokens?: number | null;
|
|
185
|
+
}
|
|
186
|
+
/** Why generation stopped. */
|
|
187
|
+
type WireStopReason = 'end_turn' | 'max_tokens' | 'stop_sequence' | 'tool_use' | 'pause_turn' | 'refusal';
|
|
188
|
+
/** A response-side content block, as `content_block_start` announces it. */
|
|
189
|
+
type WireResponseBlock = {
|
|
190
|
+
type: 'text';
|
|
191
|
+
text: string;
|
|
192
|
+
} | {
|
|
193
|
+
type: 'thinking';
|
|
194
|
+
thinking: string;
|
|
195
|
+
signature?: string;
|
|
196
|
+
} | {
|
|
197
|
+
type: 'redacted_thinking';
|
|
198
|
+
data: string;
|
|
199
|
+
} | {
|
|
200
|
+
type: 'tool_use';
|
|
201
|
+
id: string;
|
|
202
|
+
name: string;
|
|
203
|
+
input: unknown;
|
|
204
|
+
} | WireServerToolUseBlock | WireWebSearchToolResultBlock;
|
|
205
|
+
/** Incremental updates to an open content block. */
|
|
206
|
+
type WireDelta = {
|
|
207
|
+
type: 'text_delta';
|
|
208
|
+
text: string;
|
|
209
|
+
} | {
|
|
210
|
+
type: 'input_json_delta';
|
|
211
|
+
partial_json: string;
|
|
212
|
+
} | {
|
|
213
|
+
type: 'thinking_delta';
|
|
214
|
+
thinking: string;
|
|
215
|
+
} |
|
|
216
|
+
/** Arrives once, immediately before `content_block_stop`, for a thinking block. */
|
|
217
|
+
{
|
|
218
|
+
type: 'signature_delta';
|
|
219
|
+
signature: string;
|
|
220
|
+
} | {
|
|
221
|
+
type: 'citations_delta';
|
|
222
|
+
citation: WireCitation;
|
|
223
|
+
};
|
|
224
|
+
/** The streaming event union. */
|
|
225
|
+
type WireStreamEvent = {
|
|
226
|
+
type: 'message_start';
|
|
227
|
+
message: {
|
|
228
|
+
id?: string;
|
|
229
|
+
model?: string;
|
|
230
|
+
usage?: WireUsage;
|
|
231
|
+
};
|
|
232
|
+
} | {
|
|
233
|
+
type: 'content_block_start';
|
|
234
|
+
index: number;
|
|
235
|
+
content_block: WireResponseBlock;
|
|
236
|
+
} | {
|
|
237
|
+
type: 'content_block_delta';
|
|
238
|
+
index: number;
|
|
239
|
+
delta: WireDelta;
|
|
240
|
+
} | {
|
|
241
|
+
type: 'content_block_stop';
|
|
242
|
+
index: number;
|
|
243
|
+
} | {
|
|
244
|
+
type: 'message_delta';
|
|
245
|
+
delta: {
|
|
246
|
+
stop_reason?: WireStopReason | null;
|
|
247
|
+
stop_sequence?: string | null;
|
|
248
|
+
};
|
|
249
|
+
usage?: WireUsage;
|
|
250
|
+
} | {
|
|
251
|
+
type: 'message_stop';
|
|
252
|
+
} | {
|
|
253
|
+
type: 'ping';
|
|
254
|
+
} | {
|
|
255
|
+
type: 'error';
|
|
256
|
+
error: WireErrorBody;
|
|
257
|
+
};
|
|
258
|
+
/** The error payload, in both HTTP error bodies and mid-stream `error` events. */
|
|
259
|
+
interface WireErrorBody {
|
|
260
|
+
type?: string;
|
|
261
|
+
message?: string;
|
|
262
|
+
}
|
|
263
|
+
/** An HTTP error response body. */
|
|
264
|
+
interface WireErrorResponse {
|
|
265
|
+
type?: 'error';
|
|
266
|
+
error?: WireErrorBody;
|
|
267
|
+
}
|
|
268
|
+
//#endregion
|
|
269
|
+
//#region src/serialize.d.ts
|
|
270
|
+
/**
|
|
271
|
+
* Adapter-private state kept on a {@link ReasoningBlock} so a thinking block can
|
|
272
|
+
* be echoed back exactly.
|
|
273
|
+
*
|
|
274
|
+
* The signature is the load-bearing part: this API verifies it to confirm the
|
|
275
|
+
* block is genuinely the model's own reasoning, and a thinking block sent back
|
|
276
|
+
* without it is rejected.
|
|
277
|
+
*/
|
|
278
|
+
interface AnthropicReasoningState {
|
|
279
|
+
/** `thinking` for an ordinary block, `redacted_thinking` for an opaque one. */
|
|
280
|
+
kind: 'thinking' | 'redacted_thinking';
|
|
281
|
+
/** Cryptographic signature over the thinking content. */
|
|
282
|
+
signature?: string;
|
|
283
|
+
/** Opaque payload of a redacted block. */
|
|
284
|
+
data?: string;
|
|
285
|
+
}
|
|
286
|
+
/** How a reasoning effort becomes a thinking token budget. */
|
|
287
|
+
type ThinkingBudgets = Readonly<Record<string, number>>;
|
|
288
|
+
/** Options controlling how the request is built. */
|
|
289
|
+
interface AnthropicSerializeOptions {
|
|
290
|
+
/** Effort id to thinking-token budget. An absent or zero budget disables thinking. */
|
|
291
|
+
budgets: ThinkingBudgets;
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Build the Messages request body.
|
|
295
|
+
* @param request - the resolved request, model, and connection.
|
|
296
|
+
* @param options - thinking-budget mapping.
|
|
297
|
+
* @returns the wire body, ready to serialize.
|
|
298
|
+
*/
|
|
299
|
+
declare function serializeAnthropicRequest(request: ProtocolRequest, options: AnthropicSerializeOptions): WireRequest;
|
|
300
|
+
//#endregion
|
|
301
|
+
//#region src/protocol.d.ts
|
|
302
|
+
/** Protocol id, usable as a stable string in configuration. */
|
|
303
|
+
declare const ANTHROPIC_MESSAGES_PROTOCOL_ID = "anthropic-messages";
|
|
304
|
+
/**
|
|
305
|
+
* The API version header value.
|
|
306
|
+
*
|
|
307
|
+
* Mandatory on every request. Stable across the entire lifetime of this API — new
|
|
308
|
+
* capabilities arrive as opt-in beta headers rather than a version bump — which is
|
|
309
|
+
* why it lives on the protocol instead of being restated by each endpoint.
|
|
310
|
+
*/
|
|
311
|
+
declare const ANTHROPIC_VERSION = "2023-06-01";
|
|
312
|
+
/**
|
|
313
|
+
* Default reasoning efforts, expressed as thinking-token budgets.
|
|
314
|
+
*
|
|
315
|
+
* Budgets rather than an opaque level because that is what this API takes. The
|
|
316
|
+
* SDK's effort ids are a neutral surface over a provider-specific knob, and
|
|
317
|
+
* mapping them here is the whole reason `ReasoningEffortId` is opaque.
|
|
318
|
+
*/
|
|
319
|
+
declare const DEFAULT_THINKING_BUDGETS: ThinkingBudgets;
|
|
320
|
+
/** Per-endpoint knobs of the Messages protocol. */
|
|
321
|
+
interface AnthropicDialect {
|
|
322
|
+
/** Effort id to thinking-token budget. */
|
|
323
|
+
readonly budgets: ThinkingBudgets;
|
|
324
|
+
/** `anthropic-version` header value. */
|
|
325
|
+
readonly version: string;
|
|
326
|
+
/** Opt-in beta features, sent as `anthropic-beta`. */
|
|
327
|
+
readonly beta: readonly string[];
|
|
328
|
+
}
|
|
329
|
+
interface RuntimeProtocolRequest extends ProtocolRequest {
|
|
330
|
+
readonly model: ResolvedModelInfo;
|
|
331
|
+
readonly connection: {
|
|
332
|
+
readonly baseUrl: string;
|
|
333
|
+
readonly headers: Readonly<Record<string, string>>;
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
/** Marker-based runtime view, kept structurally independent from provider-http. */
|
|
337
|
+
interface AnthropicMessagesProtocolDefinition {
|
|
338
|
+
readonly kind: 'http-wire-protocol';
|
|
339
|
+
readonly apiVersion: 1;
|
|
340
|
+
readonly id: string;
|
|
341
|
+
readonly defaultDialect: AnthropicDialect;
|
|
342
|
+
readonly exampleModel?: ModelTarget;
|
|
343
|
+
readonly endpointPath: (request: RuntimeProtocolRequest, dialect: AnthropicDialect) => string;
|
|
344
|
+
readonly protocolHeaders?: (dialect: AnthropicDialect) => Readonly<Record<string, string>>;
|
|
345
|
+
readonly serialize: (request: RuntimeProtocolRequest, dialect: AnthropicDialect) => Readonly<Record<string, unknown>>;
|
|
346
|
+
readonly translate: (events: AsyncIterable<ProtocolSseEvent>, request: RuntimeProtocolRequest, displayName: string) => AsyncGenerator<ProtocolStreamChunk>;
|
|
347
|
+
}
|
|
348
|
+
/** The Anthropic Messages wire protocol. */
|
|
349
|
+
declare const anthropicMessagesProtocol: ProtocolDefinition<AnthropicDialect> & AnthropicMessagesProtocolDefinition;
|
|
350
|
+
//#endregion
|
|
351
|
+
//#region src/translate.d.ts
|
|
352
|
+
/**
|
|
353
|
+
* Translate one Messages SSE stream.
|
|
354
|
+
*
|
|
355
|
+
* Owns termination. There is no `[DONE]` sentinel: the stream ends on
|
|
356
|
+
* `message_stop`, and a body that ends before that was truncated — a failure
|
|
357
|
+
* rather than a short answer.
|
|
358
|
+
* @param events - decoded SSE events.
|
|
359
|
+
* @param displayName - provider name, used in diagnostics.
|
|
360
|
+
* @returns the chunk stream.
|
|
361
|
+
*/
|
|
362
|
+
declare function translateAnthropicStream(events: AsyncIterable<ProtocolSseEvent>, displayName: string): AsyncGenerator<ProtocolStreamChunk>;
|
|
363
|
+
//#endregion
|
|
364
|
+
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 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 };
|
|
365
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +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;WACT;;;UAIM;WACN;WACA;;;KAIC,sBACR,QAAQ;WAAwB;;WACrB;WAAwB,OAAO;;;UAG7B,mBAAmB;WACzB;WACA,gBAAgB;EACzB,aAAa,SAAS,iBAAiB,SAAS;EAChD,iBAAiB,SAAS,UAAU;EACpC,UAAU,SAAS,iBAAiB,SAAS,oBAAoB;EACjE,UACE,QAAQ,cAAc,mBACtB,SAAS,iBACT,sBACC,eAAe;;;;;;;;;;;;;;;KClBR;EACN;EAAgB;EAAoB;;EACpC;EAAa;;;KAGP;EACN;EAAc;EAAc,YAAY;;EACxC;EAAe,QAAQ;;EACvB;EAAkB;EAAY;EAAc;;EAE9C;EACA;EACA,SAAS;EACT;;;;;;;EAME;EAAkB;EAAkB;;EACpC;EAA2B;IAC7B,yBACA;UAEa;EACf;EACA;EACA;EACA;;UAGe;EACf;EACA;EACA;EACA;;UAGe;EACf;GACC;;;KAIS;EACN;EAAc;;EACd;EAAe,QAAQ;;;UAGZ;EACf;EACA,SAAS;;;UAIM;EACf;EACA;EACA,cAAc;;;UAIC;EACf;EACA;EACA;EACA;EACA;EACA;IACE;IACA;IACA;IACA;IACA;;;KAIQ,WAAW,mBAAmB;;KAG9B;EACN;;EACA;;EACA;;EACA;EAAc;;;KAGR;EACN;EAAiB;;EACjB;;UAEW;EACf;IACE;IACA,QAAQ,SAAS;;;;UAKJ;EACf;;EAEA;EACA,UAAU;EACV;EACA,QAAQ;EACR,cAAc;EACd;EACA;EACA;EACA,WAAW;EACX,gBAAgB;EAChB;;;;;;;;;UAUe;EACf;EACA;EACA;EACA;;;KAIU;;KASA;EACN;EAAc;;EACd;EAAkB;EAAkB;;EACpC;EAA2B;;EAC3B;EAAkB;EAAY;EAAc;IAC9C,yBACA;;KAGQ;EACN;EAAoB;;EACpB;EAA0B;;EAC1B;EAAwB;;;;EAExB;EAAyB;;EACzB;EAAyB,UAAU;;;KAG7B;EACN;EAAuB;IAAW;IAAa;IAAgB,QAAQ;;;EACvE;EAA6B;EAAe,eAAe;;EAC3D;EAA6B;EAAe,OAAO;;EACnD;EAA4B;;EAE9B;EACA;IAAS,cAAc;IAAuB;;EAC9C,QAAQ;;EAEN;;EACA;;EACA;EAAe,OAAO;;;UAGX;EACf;EACA;;;UAIe;EACf;EACA,QAAQ;;;;;;;;;;;;UChJO;;EAEf;;EAEA;;EAEA;;;KAiOU,kBAAkB,SAAS;;UAGtB;;EAEf,SAAS;;;;;;;;iBAmCK,0BACd,SAAS,iBACT,SAAS,4BACR;;;;cCjTU;;;;;;;;cASA;;;;;;;;cASA,0BAA0B;;UAQtB;;WAEN,SAAS;;WAET;;WAEA;;UASD,+BAA+B;WAC9B,OAAO;WACP;aACE;aACA,SAAS,SAAS;;;;UAKd;WACN;WACA;WACA;WACA,gBAAgB;WAChB,eAAe;WACf,eAAe,SAAS,wBAAwB,SAAS;WACzD,mBAAmB,SAAS,qBAAqB,SAAS;WAC1D,YACP,SAAS,wBACT,SAAS,qBACN,SAAS;WACL,YACP,QAAQ,cAAc,mBACtB,SAAS,wBACT,wBACG,eAAe;;;cAIT,2BAA2B,mBAAmB,oBACvD;;;;;;;;;;;;;iBC6HmB,yBACrB,QAAQ,cAAc,mBACtB,sBACC,eAAe"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,638 @@
|
|
|
1
|
+
import { CONTEXT_WINDOW_EXCEEDED_CODE, MODEL_ERROR_CODES, ModelError, QUOTA_EXCEEDED_CODE, ToolCallId, isContextWindowExceededError, isJsonValue, isNativeToolSchema, isQuotaExceededError } from "@alvin0/ai-agent-sdk-core";
|
|
2
|
+
|
|
3
|
+
//#region src/serialize.ts
|
|
4
|
+
/**
|
|
5
|
+
* Normalized request to Anthropic Messages API wire JSON.
|
|
6
|
+
*
|
|
7
|
+
* Two things here differ sharply from the Responses API and are easy to get wrong:
|
|
8
|
+
*
|
|
9
|
+
* 1. `tool_use.input` is a parsed OBJECT, not a JSON string. Our normalized block
|
|
10
|
+
* keeps the raw string the model produced, so it is parsed on the way out.
|
|
11
|
+
* 2. Consecutive same-role messages are MERGED. This is not cosmetic tidying —
|
|
12
|
+
* when a model makes three parallel tool calls, we produce three separate
|
|
13
|
+
* tool-result messages, and this API expects all three `tool_result` blocks in
|
|
14
|
+
* ONE user message. Without merging, parallel tool use breaks.
|
|
15
|
+
*
|
|
16
|
+
* @module ai-agent-sdk/providers/anthropic/serialize
|
|
17
|
+
*/
|
|
18
|
+
/** Read reasoning state back off a block, tolerating anything unexpected. */
|
|
19
|
+
function reasoningStateOf(value) {
|
|
20
|
+
if (typeof value !== "object" || value === null) return void 0;
|
|
21
|
+
const state = value;
|
|
22
|
+
if (state.kind !== "thinking" && state.kind !== "redacted_thinking") return void 0;
|
|
23
|
+
return {
|
|
24
|
+
kind: state.kind,
|
|
25
|
+
...typeof state.signature === "string" ? { signature: state.signature } : {},
|
|
26
|
+
...typeof state.data === "string" ? { data: state.data } : {}
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/** Map an image source onto this API's tagged source object. */
|
|
30
|
+
function imageSource(source) {
|
|
31
|
+
if (source.kind === "url") return {
|
|
32
|
+
type: "url",
|
|
33
|
+
url: source.url
|
|
34
|
+
};
|
|
35
|
+
if (source.kind === "base64") return {
|
|
36
|
+
type: "base64",
|
|
37
|
+
media_type: source.mediaType,
|
|
38
|
+
data: source.data
|
|
39
|
+
};
|
|
40
|
+
throw new ModelError("Anthropic image inputs support URL or base64 sources, not file ids", MODEL_ERROR_CODES.INVALID_REQUEST);
|
|
41
|
+
}
|
|
42
|
+
/** Restrict tool-result content to the block types this API accepts there. */
|
|
43
|
+
function toolResultContent(blocks) {
|
|
44
|
+
const parts = [];
|
|
45
|
+
let textOnly = true;
|
|
46
|
+
for (const block of blocks) if (block.type === "text") parts.push({
|
|
47
|
+
type: "text",
|
|
48
|
+
text: block.text
|
|
49
|
+
});
|
|
50
|
+
else if (block.type === "image") {
|
|
51
|
+
textOnly = false;
|
|
52
|
+
parts.push({
|
|
53
|
+
type: "image",
|
|
54
|
+
source: imageSource(block.source)
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
if (textOnly) return parts.map((part) => part.type === "text" ? part.text : "").join("\n");
|
|
58
|
+
return parts;
|
|
59
|
+
}
|
|
60
|
+
/** Parse tool-call arguments into the object this API expects. */
|
|
61
|
+
function toolInput(raw) {
|
|
62
|
+
if (raw.trim().length === 0) return {};
|
|
63
|
+
try {
|
|
64
|
+
return JSON.parse(raw);
|
|
65
|
+
} catch {
|
|
66
|
+
return {};
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
function citationOf(value) {
|
|
70
|
+
if (typeof value !== "object" || value === null) return void 0;
|
|
71
|
+
const citation = value;
|
|
72
|
+
return typeof citation.type === "string" ? structuredClone(citation) : void 0;
|
|
73
|
+
}
|
|
74
|
+
function nativeReplayBlocks(value) {
|
|
75
|
+
if (typeof value !== "object" || value === null) return [];
|
|
76
|
+
const state = value;
|
|
77
|
+
return [state.call, state.result].flatMap((candidate) => {
|
|
78
|
+
if (typeof candidate !== "object" || candidate === null) return [];
|
|
79
|
+
const block = candidate;
|
|
80
|
+
if (block.type === "server_tool_use" && typeof block.id === "string" && typeof block.name === "string") return [{
|
|
81
|
+
type: "server_tool_use",
|
|
82
|
+
id: block.id,
|
|
83
|
+
name: block.name,
|
|
84
|
+
input: structuredClone(block.input ?? {})
|
|
85
|
+
}];
|
|
86
|
+
if (block.type === "web_search_tool_result" && typeof block.tool_use_id === "string") return [{
|
|
87
|
+
type: "web_search_tool_result",
|
|
88
|
+
tool_use_id: block.tool_use_id,
|
|
89
|
+
content: structuredClone(block.content),
|
|
90
|
+
...block.caller === void 0 ? {} : { caller: structuredClone(block.caller) }
|
|
91
|
+
}];
|
|
92
|
+
return [];
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
/** Convert one normalized block to zero or more wire blocks. */
|
|
96
|
+
function requestBlocks(block) {
|
|
97
|
+
switch (block.type) {
|
|
98
|
+
case "text": {
|
|
99
|
+
if (block.text.trim().length === 0) return [];
|
|
100
|
+
const citations = block.annotations?.flatMap((annotation) => {
|
|
101
|
+
if (annotation.type !== "url-citation") return [];
|
|
102
|
+
const citation = citationOf(annotation.providerState);
|
|
103
|
+
return citation === void 0 ? [] : [citation];
|
|
104
|
+
});
|
|
105
|
+
return [{
|
|
106
|
+
type: "text",
|
|
107
|
+
text: block.text,
|
|
108
|
+
...citations === void 0 || citations.length === 0 ? {} : { citations }
|
|
109
|
+
}];
|
|
110
|
+
}
|
|
111
|
+
case "image": return [{
|
|
112
|
+
type: "image",
|
|
113
|
+
source: imageSource(block.source)
|
|
114
|
+
}];
|
|
115
|
+
case "tool-call": return [{
|
|
116
|
+
type: "tool_use",
|
|
117
|
+
id: block.id,
|
|
118
|
+
name: block.name,
|
|
119
|
+
input: toolInput(block.arguments)
|
|
120
|
+
}];
|
|
121
|
+
case "tool-result": return [{
|
|
122
|
+
type: "tool_result",
|
|
123
|
+
tool_use_id: block.toolCallId,
|
|
124
|
+
content: toolResultContent(block.content),
|
|
125
|
+
...block.isError === true ? { is_error: true } : {}
|
|
126
|
+
}];
|
|
127
|
+
case "native-tool-call": return nativeReplayBlocks(block.providerState);
|
|
128
|
+
case "reasoning": {
|
|
129
|
+
const state = reasoningStateOf(block.providerState);
|
|
130
|
+
if (state === void 0) return [];
|
|
131
|
+
if (state.kind === "redacted_thinking") return state.data === void 0 ? [] : [{
|
|
132
|
+
type: "redacted_thinking",
|
|
133
|
+
data: state.data
|
|
134
|
+
}];
|
|
135
|
+
return state.signature === void 0 ? [] : [{
|
|
136
|
+
type: "thinking",
|
|
137
|
+
thinking: block.text,
|
|
138
|
+
signature: state.signature
|
|
139
|
+
}];
|
|
140
|
+
}
|
|
141
|
+
default: return [];
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Build the message list, merging consecutive same-role messages.
|
|
146
|
+
*
|
|
147
|
+
* See the module note for why merging matters.
|
|
148
|
+
*/
|
|
149
|
+
function messagesOf(messages) {
|
|
150
|
+
const result = [];
|
|
151
|
+
for (const message of messages) {
|
|
152
|
+
if (message.role === "system") continue;
|
|
153
|
+
const role = message.role === "assistant" ? "assistant" : "user";
|
|
154
|
+
const blocks = message.content.flatMap(requestBlocks);
|
|
155
|
+
if (blocks.length === 0) continue;
|
|
156
|
+
const previous = result.at(-1);
|
|
157
|
+
if (previous !== void 0 && previous.role === role) previous.content.push(...blocks);
|
|
158
|
+
else result.push({
|
|
159
|
+
role,
|
|
160
|
+
content: blocks
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
return result;
|
|
164
|
+
}
|
|
165
|
+
/** Collect the system prompt from the request plus any system-role messages. */
|
|
166
|
+
function systemOf(request) {
|
|
167
|
+
const fromMessages = request.options.messages.filter((message) => message.role === "system").flatMap((message) => message.content).filter((block) => block.type === "text").map((block) => block.text);
|
|
168
|
+
const joined = (request.options.system === void 0 ? fromMessages : [request.options.system, ...fromMessages]).join("\n\n");
|
|
169
|
+
return joined.length === 0 ? void 0 : joined;
|
|
170
|
+
}
|
|
171
|
+
/** Map the neutral tool-choice vocabulary onto this API's. */
|
|
172
|
+
function toolChoiceOf(choice) {
|
|
173
|
+
if (choice === "auto") return { type: "auto" };
|
|
174
|
+
if (choice === "none") return { type: "none" };
|
|
175
|
+
if (choice === "required") return { type: "any" };
|
|
176
|
+
return {
|
|
177
|
+
type: "tool",
|
|
178
|
+
name: choice.type === "native" ? nativeToolName(choice.name) : choice.name
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
function functionTool(tool) {
|
|
182
|
+
return {
|
|
183
|
+
name: tool.name,
|
|
184
|
+
description: tool.description,
|
|
185
|
+
input_schema: tool.parameters
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
function nativeToolName(name) {
|
|
189
|
+
if (name === "web-search") return "web_search";
|
|
190
|
+
return name.replaceAll("-", "_");
|
|
191
|
+
}
|
|
192
|
+
function webSearchTool(tool) {
|
|
193
|
+
if (tool.allowedDomains !== void 0 && tool.blockedDomains !== void 0) throw new ModelError("Anthropic web search accepts allowedDomains or blockedDomains, not both", MODEL_ERROR_CODES.INVALID_REQUEST);
|
|
194
|
+
return {
|
|
195
|
+
type: "web_search_20250305",
|
|
196
|
+
name: "web_search",
|
|
197
|
+
...tool.maxUses === void 0 ? {} : { max_uses: tool.maxUses },
|
|
198
|
+
...tool.allowedDomains === void 0 ? {} : { allowed_domains: [...tool.allowedDomains] },
|
|
199
|
+
...tool.blockedDomains === void 0 ? {} : { blocked_domains: [...tool.blockedDomains] },
|
|
200
|
+
...tool.userLocation === void 0 ? {} : { user_location: {
|
|
201
|
+
type: "approximate",
|
|
202
|
+
...tool.userLocation
|
|
203
|
+
} }
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
function toolOf(tool) {
|
|
207
|
+
if (!isNativeToolSchema(tool)) return functionTool(tool);
|
|
208
|
+
if (tool.name === "web-search") return webSearchTool(tool);
|
|
209
|
+
throw new ModelError(`Anthropic does not support the provider-native tool '${tool.name}'`, MODEL_ERROR_CODES.INVALID_REQUEST);
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Resolve the `thinking` field for this request.
|
|
213
|
+
*
|
|
214
|
+
* The budget must leave room for a real answer, so it is capped below
|
|
215
|
+
* `max_tokens` — this API requires `budget_tokens < max_tokens` and rejects the
|
|
216
|
+
* request otherwise.
|
|
217
|
+
*/
|
|
218
|
+
function thinkingOf(effort, maxTokens, budgets) {
|
|
219
|
+
if (effort === void 0) return void 0;
|
|
220
|
+
const requested = budgets[effort];
|
|
221
|
+
if (requested === void 0 || requested <= 0) return { type: "disabled" };
|
|
222
|
+
const capped = Math.min(requested, Math.floor(maxTokens * .75));
|
|
223
|
+
return capped < 1024 ? { type: "disabled" } : {
|
|
224
|
+
type: "enabled",
|
|
225
|
+
budget_tokens: capped
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
function outputConfig(format) {
|
|
229
|
+
if (format === void 0 || format.type === "text") return void 0;
|
|
230
|
+
return { format: {
|
|
231
|
+
type: "json_schema",
|
|
232
|
+
schema: format.schema
|
|
233
|
+
} };
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Build the Messages request body.
|
|
237
|
+
* @param request - the resolved request, model, and connection.
|
|
238
|
+
* @param options - thinking-budget mapping.
|
|
239
|
+
* @returns the wire body, ready to serialize.
|
|
240
|
+
*/
|
|
241
|
+
function serializeAnthropicRequest(request, options) {
|
|
242
|
+
const { options: call } = request;
|
|
243
|
+
const system = systemOf(request);
|
|
244
|
+
const tools = call.tools === void 0 || call.tools.length === 0 ? void 0 : call.tools.map(toolOf);
|
|
245
|
+
const thinking = thinkingOf(call.reasoningEffort === void 0 ? void 0 : String(call.reasoningEffort), request.maxTokens, options.budgets);
|
|
246
|
+
const thinkingEnabled = thinking?.type === "enabled";
|
|
247
|
+
const output = outputConfig(call.outputFormat);
|
|
248
|
+
return {
|
|
249
|
+
model: call.model,
|
|
250
|
+
max_tokens: request.maxTokens,
|
|
251
|
+
messages: messagesOf(call.messages),
|
|
252
|
+
...system === void 0 ? {} : { system },
|
|
253
|
+
...tools === void 0 ? {} : { tools },
|
|
254
|
+
...call.toolChoice === void 0 ? {} : { tool_choice: toolChoiceOf(call.toolChoice) },
|
|
255
|
+
...!thinkingEnabled && call.temperature !== void 0 ? { temperature: call.temperature } : {},
|
|
256
|
+
...!thinkingEnabled && call.topP !== void 0 ? { top_p: call.topP } : {},
|
|
257
|
+
...call.stop === void 0 || call.stop.length === 0 ? {} : { stop_sequences: [...call.stop] },
|
|
258
|
+
...thinking === void 0 ? {} : { thinking },
|
|
259
|
+
...output === void 0 ? {} : { output_config: output },
|
|
260
|
+
stream: true
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
//#endregion
|
|
265
|
+
//#region src/translate.ts
|
|
266
|
+
/**
|
|
267
|
+
* Anthropic Messages API SSE events to the SDK's chunk protocol.
|
|
268
|
+
*
|
|
269
|
+
* Notable differences from the Responses translation:
|
|
270
|
+
*
|
|
271
|
+
* - Block indices come straight from the provider. This API numbers content
|
|
272
|
+
* blocks contiguously from zero in emission order, which is already exactly
|
|
273
|
+
* what our protocol wants, so no remapping is needed.
|
|
274
|
+
* - Usage arrives in TWO places: input counts on `message_start`, output counts on
|
|
275
|
+
* `message_delta`. They are accumulated and emitted once, before the finish.
|
|
276
|
+
* - `input_tokens` here already EXCLUDES cached tokens, so unlike the Responses
|
|
277
|
+
* translation nothing is subtracted. Getting this backwards would under-report
|
|
278
|
+
* input on every cached call.
|
|
279
|
+
*
|
|
280
|
+
* @module ai-agent-sdk/providers/anthropic/translate
|
|
281
|
+
*/
|
|
282
|
+
function blockKind(type) {
|
|
283
|
+
switch (type) {
|
|
284
|
+
case "text": return "text";
|
|
285
|
+
case "thinking":
|
|
286
|
+
case "redacted_thinking": return "reasoning";
|
|
287
|
+
case "tool_use": return "tool-call";
|
|
288
|
+
case "server_tool_use": return "native-tool-call";
|
|
289
|
+
default: return;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
function absorbUsage(target, usage) {
|
|
293
|
+
if (typeof usage !== "object" || usage === null) return;
|
|
294
|
+
if ("input_tokens" in usage) target.input = usage.input_tokens;
|
|
295
|
+
if ("output_tokens" in usage) target.output = usage.output_tokens;
|
|
296
|
+
if ("cache_read_input_tokens" in usage && usage.cache_read_input_tokens !== null) target.cacheRead = usage.cache_read_input_tokens;
|
|
297
|
+
if ("cache_creation_input_tokens" in usage && usage.cache_creation_input_tokens !== null) target.cacheWrite = usage.cache_creation_input_tokens;
|
|
298
|
+
target.seen = true;
|
|
299
|
+
}
|
|
300
|
+
function finalUsage(accumulated) {
|
|
301
|
+
if (!accumulated.seen) return void 0;
|
|
302
|
+
const output = {
|
|
303
|
+
...accumulated.input === void 0 ? {} : { inputTokens: accumulated.input },
|
|
304
|
+
...accumulated.output === void 0 ? {} : { outputTokens: accumulated.output },
|
|
305
|
+
...accumulated.cacheRead === void 0 || accumulated.cacheRead === 0 ? {} : { cacheReadTokens: accumulated.cacheRead },
|
|
306
|
+
...accumulated.cacheWrite === void 0 || accumulated.cacheWrite === 0 ? {} : { cacheWriteTokens: accumulated.cacheWrite }
|
|
307
|
+
};
|
|
308
|
+
const counters = [
|
|
309
|
+
accumulated.input,
|
|
310
|
+
accumulated.cacheRead ?? 0,
|
|
311
|
+
accumulated.cacheWrite ?? 0,
|
|
312
|
+
accumulated.output
|
|
313
|
+
];
|
|
314
|
+
if (counters.every(validUsageCounter)) output.totalTokens = counters.reduce((total, value) => total + value, 0);
|
|
315
|
+
return output;
|
|
316
|
+
}
|
|
317
|
+
function validUsageCounter(value) {
|
|
318
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
|
|
319
|
+
}
|
|
320
|
+
/** Map this API's stop reason onto ours. */
|
|
321
|
+
function finishReason(stop) {
|
|
322
|
+
switch (stop) {
|
|
323
|
+
case "tool_use": return { kind: "tool-calls" };
|
|
324
|
+
case "max_tokens": return { kind: "max-tokens" };
|
|
325
|
+
case "refusal": return {
|
|
326
|
+
kind: "error",
|
|
327
|
+
failure: {
|
|
328
|
+
message: "the model refused to answer",
|
|
329
|
+
code: MODEL_ERROR_CODES.INVALID_REQUEST
|
|
330
|
+
}
|
|
331
|
+
};
|
|
332
|
+
default: return { kind: "stop" };
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
/** Build the authoritative block for a completed content block. */
|
|
336
|
+
function closedBlock(open) {
|
|
337
|
+
switch (open.kind) {
|
|
338
|
+
case "text": return {
|
|
339
|
+
type: "text",
|
|
340
|
+
text: open.text,
|
|
341
|
+
...open.annotations.length === 0 ? {} : { annotations: open.annotations }
|
|
342
|
+
};
|
|
343
|
+
case "reasoning": {
|
|
344
|
+
const state = open.redactedData !== void 0 ? {
|
|
345
|
+
kind: "redacted_thinking",
|
|
346
|
+
data: open.redactedData
|
|
347
|
+
} : {
|
|
348
|
+
kind: "thinking",
|
|
349
|
+
...open.signature === void 0 ? {} : { signature: open.signature }
|
|
350
|
+
};
|
|
351
|
+
return {
|
|
352
|
+
type: "reasoning",
|
|
353
|
+
text: open.text,
|
|
354
|
+
providerState: state
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
case "tool-call": return {
|
|
358
|
+
type: "tool-call",
|
|
359
|
+
id: ToolCallId(open.callId),
|
|
360
|
+
name: open.name,
|
|
361
|
+
arguments: open.args.length > 0 ? open.args : "{}"
|
|
362
|
+
};
|
|
363
|
+
case "native-tool-call": {
|
|
364
|
+
const parsed = parsedArguments(open.args, open.nativeCall?.input);
|
|
365
|
+
const call = open.nativeCall ?? {
|
|
366
|
+
type: "server_tool_use",
|
|
367
|
+
id: open.callId,
|
|
368
|
+
name: "web_search",
|
|
369
|
+
input: parsed
|
|
370
|
+
};
|
|
371
|
+
return {
|
|
372
|
+
type: "native-tool-call",
|
|
373
|
+
id: open.callId,
|
|
374
|
+
name: open.name === "web_search" ? "web-search" : open.name.replaceAll("_", "-"),
|
|
375
|
+
arguments: parsed,
|
|
376
|
+
content: [],
|
|
377
|
+
providerState: {
|
|
378
|
+
call: {
|
|
379
|
+
...call,
|
|
380
|
+
input: parsed
|
|
381
|
+
},
|
|
382
|
+
...open.nativeResult === void 0 ? {} : { result: open.nativeResult }
|
|
383
|
+
}
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
default: return;
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
function parsedArguments(raw, fallback) {
|
|
390
|
+
if (raw.length === 0) return isJsonValue(fallback) ? fallback : {};
|
|
391
|
+
try {
|
|
392
|
+
const value = JSON.parse(raw);
|
|
393
|
+
return isJsonValue(value) ? value : {};
|
|
394
|
+
} catch {
|
|
395
|
+
return {};
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
function citationAnnotation(citation) {
|
|
399
|
+
if (citation.type !== "web_search_result_location" || typeof citation.url !== "string") return;
|
|
400
|
+
return {
|
|
401
|
+
type: "url-citation",
|
|
402
|
+
url: citation.url,
|
|
403
|
+
...typeof citation.title === "string" ? { title: citation.title } : {},
|
|
404
|
+
providerState: structuredClone(citation)
|
|
405
|
+
};
|
|
406
|
+
}
|
|
407
|
+
/**
|
|
408
|
+
* Translate one Messages SSE stream.
|
|
409
|
+
*
|
|
410
|
+
* Owns termination. There is no `[DONE]` sentinel: the stream ends on
|
|
411
|
+
* `message_stop`, and a body that ends before that was truncated — a failure
|
|
412
|
+
* rather than a short answer.
|
|
413
|
+
* @param events - decoded SSE events.
|
|
414
|
+
* @param displayName - provider name, used in diagnostics.
|
|
415
|
+
* @returns the chunk stream.
|
|
416
|
+
*/
|
|
417
|
+
async function* translateAnthropicStream(events, displayName) {
|
|
418
|
+
const open = /* @__PURE__ */ new Map();
|
|
419
|
+
const usage = {
|
|
420
|
+
input: void 0,
|
|
421
|
+
output: void 0,
|
|
422
|
+
cacheRead: void 0,
|
|
423
|
+
cacheWrite: void 0,
|
|
424
|
+
seen: false
|
|
425
|
+
};
|
|
426
|
+
let stop;
|
|
427
|
+
let terminated = false;
|
|
428
|
+
let emittedBlocks = 0;
|
|
429
|
+
for await (const raw of events) {
|
|
430
|
+
let event;
|
|
431
|
+
try {
|
|
432
|
+
event = JSON.parse(raw.data);
|
|
433
|
+
} catch (error) {
|
|
434
|
+
throw new ModelError(`${displayName} sent a malformed stream event`, MODEL_ERROR_CODES.MALFORMED_RESPONSE, { cause: error });
|
|
435
|
+
}
|
|
436
|
+
switch (event.type) {
|
|
437
|
+
case "message_start":
|
|
438
|
+
absorbUsage(usage, event.message.usage);
|
|
439
|
+
break;
|
|
440
|
+
case "content_block_start": {
|
|
441
|
+
if (event.content_block.type === "web_search_tool_result") {
|
|
442
|
+
const result = event.content_block;
|
|
443
|
+
const owner = [...open.values()].find((entry) => entry.kind === "native-tool-call" && entry.callId === result.tool_use_id);
|
|
444
|
+
if (owner !== void 0) {
|
|
445
|
+
owner.nativeResult = result;
|
|
446
|
+
const block = closedBlock(owner);
|
|
447
|
+
if (block !== void 0 && !owner.closed) {
|
|
448
|
+
owner.closed = true;
|
|
449
|
+
yield {
|
|
450
|
+
type: "block-end",
|
|
451
|
+
index: [...open.entries()].find(([, entry]) => entry === owner)?.[0] ?? event.index,
|
|
452
|
+
block
|
|
453
|
+
};
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
break;
|
|
457
|
+
}
|
|
458
|
+
const kind = blockKind(event.content_block.type);
|
|
459
|
+
if (kind === void 0) break;
|
|
460
|
+
const block = event.content_block;
|
|
461
|
+
const entry = {
|
|
462
|
+
kind,
|
|
463
|
+
text: block.type === "text" ? block.text : block.type === "thinking" ? block.thinking : "",
|
|
464
|
+
args: "",
|
|
465
|
+
callId: block.type === "tool_use" ? block.id : `block-${event.index}`,
|
|
466
|
+
name: block.type === "tool_use" || block.type === "server_tool_use" ? block.name : "",
|
|
467
|
+
signature: block.type === "thinking" ? block.signature : void 0,
|
|
468
|
+
redactedData: block.type === "redacted_thinking" ? block.data : void 0,
|
|
469
|
+
annotations: [],
|
|
470
|
+
nativeCall: block.type === "server_tool_use" ? block : void 0,
|
|
471
|
+
nativeResult: void 0,
|
|
472
|
+
closed: false
|
|
473
|
+
};
|
|
474
|
+
if (block.type === "server_tool_use") {
|
|
475
|
+
entry.callId = block.id;
|
|
476
|
+
entry.args = "";
|
|
477
|
+
}
|
|
478
|
+
open.set(event.index, entry);
|
|
479
|
+
emittedBlocks += 1;
|
|
480
|
+
yield {
|
|
481
|
+
type: "block-start",
|
|
482
|
+
index: event.index,
|
|
483
|
+
blockType: kind
|
|
484
|
+
};
|
|
485
|
+
break;
|
|
486
|
+
}
|
|
487
|
+
case "content_block_delta": {
|
|
488
|
+
const entry = open.get(event.index);
|
|
489
|
+
if (entry === void 0) break;
|
|
490
|
+
const delta = event.delta;
|
|
491
|
+
switch (delta.type) {
|
|
492
|
+
case "text_delta":
|
|
493
|
+
entry.text += delta.text;
|
|
494
|
+
yield {
|
|
495
|
+
type: "text-delta",
|
|
496
|
+
index: event.index,
|
|
497
|
+
text: delta.text
|
|
498
|
+
};
|
|
499
|
+
break;
|
|
500
|
+
case "thinking_delta":
|
|
501
|
+
entry.text += delta.thinking;
|
|
502
|
+
yield {
|
|
503
|
+
type: "reasoning-delta",
|
|
504
|
+
index: event.index,
|
|
505
|
+
text: delta.thinking
|
|
506
|
+
};
|
|
507
|
+
break;
|
|
508
|
+
case "signature_delta":
|
|
509
|
+
entry.signature = delta.signature;
|
|
510
|
+
break;
|
|
511
|
+
case "input_json_delta":
|
|
512
|
+
entry.args += delta.partial_json;
|
|
513
|
+
if (entry.kind === "tool-call") yield {
|
|
514
|
+
type: "tool-call-delta",
|
|
515
|
+
index: event.index,
|
|
516
|
+
id: ToolCallId(entry.callId),
|
|
517
|
+
...entry.name.length > 0 ? { name: entry.name } : {},
|
|
518
|
+
argumentsDelta: delta.partial_json
|
|
519
|
+
};
|
|
520
|
+
break;
|
|
521
|
+
case "citations_delta": {
|
|
522
|
+
const annotation = citationAnnotation(delta.citation);
|
|
523
|
+
if (annotation !== void 0) entry.annotations.push(annotation);
|
|
524
|
+
break;
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
break;
|
|
528
|
+
}
|
|
529
|
+
case "content_block_stop": {
|
|
530
|
+
const entry = open.get(event.index);
|
|
531
|
+
if (entry === void 0) break;
|
|
532
|
+
if (entry.kind === "native-tool-call") break;
|
|
533
|
+
const block = closedBlock(entry);
|
|
534
|
+
if (block !== void 0 && !entry.closed) {
|
|
535
|
+
entry.closed = true;
|
|
536
|
+
yield {
|
|
537
|
+
type: "block-end",
|
|
538
|
+
index: event.index,
|
|
539
|
+
block
|
|
540
|
+
};
|
|
541
|
+
}
|
|
542
|
+
break;
|
|
543
|
+
}
|
|
544
|
+
case "message_delta":
|
|
545
|
+
stop = event.delta.stop_reason;
|
|
546
|
+
absorbUsage(usage, event.usage);
|
|
547
|
+
break;
|
|
548
|
+
case "message_stop": {
|
|
549
|
+
for (const [index, entry] of open) {
|
|
550
|
+
if (entry.kind !== "native-tool-call" || entry.closed) continue;
|
|
551
|
+
const block = closedBlock(entry);
|
|
552
|
+
if (block !== void 0) yield {
|
|
553
|
+
type: "block-end",
|
|
554
|
+
index,
|
|
555
|
+
block
|
|
556
|
+
};
|
|
557
|
+
entry.closed = true;
|
|
558
|
+
}
|
|
559
|
+
const mapped = finalUsage(usage);
|
|
560
|
+
if (mapped !== void 0) yield {
|
|
561
|
+
type: "usage",
|
|
562
|
+
usage: mapped
|
|
563
|
+
};
|
|
564
|
+
if (emittedBlocks === 0) throw new ModelError(`${displayName} returned a response with no content`, "EMPTY_RESPONSE");
|
|
565
|
+
yield {
|
|
566
|
+
type: "finish",
|
|
567
|
+
reason: finishReason(stop)
|
|
568
|
+
};
|
|
569
|
+
terminated = true;
|
|
570
|
+
return;
|
|
571
|
+
}
|
|
572
|
+
case "error": {
|
|
573
|
+
const detail = [event.error.type, event.error.message].filter((part) => part !== void 0).join(" ");
|
|
574
|
+
throw new ModelError(event.error.message ?? `${displayName} reported a stream error`, event.error.type === "overloaded_error" ? MODEL_ERROR_CODES.SERVER : anthropicStreamErrorCode(event.error.type, detail));
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
if (!terminated) throw new ModelError(`${displayName} stream ended before message_stop`, MODEL_ERROR_CODES.STREAM_CLOSED);
|
|
579
|
+
}
|
|
580
|
+
function anthropicStreamErrorCode(type, detail) {
|
|
581
|
+
if (type === "authentication_error" || type === "permission_error") return MODEL_ERROR_CODES.AUTH;
|
|
582
|
+
if (isQuotaExceededError(detail)) return QUOTA_EXCEEDED_CODE;
|
|
583
|
+
if (type === "rate_limit_error") return MODEL_ERROR_CODES.RATE_LIMIT;
|
|
584
|
+
if (type === "api_error") return MODEL_ERROR_CODES.SERVER;
|
|
585
|
+
if (isContextWindowExceededError(detail)) return CONTEXT_WINDOW_EXCEEDED_CODE;
|
|
586
|
+
return MODEL_ERROR_CODES.INVALID_REQUEST;
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
//#endregion
|
|
590
|
+
//#region src/protocol.ts
|
|
591
|
+
/** Protocol id, usable as a stable string in configuration. */
|
|
592
|
+
const ANTHROPIC_MESSAGES_PROTOCOL_ID = "anthropic-messages";
|
|
593
|
+
/**
|
|
594
|
+
* The API version header value.
|
|
595
|
+
*
|
|
596
|
+
* Mandatory on every request. Stable across the entire lifetime of this API — new
|
|
597
|
+
* capabilities arrive as opt-in beta headers rather than a version bump — which is
|
|
598
|
+
* why it lives on the protocol instead of being restated by each endpoint.
|
|
599
|
+
*/
|
|
600
|
+
const ANTHROPIC_VERSION = "2023-06-01";
|
|
601
|
+
/**
|
|
602
|
+
* Default reasoning efforts, expressed as thinking-token budgets.
|
|
603
|
+
*
|
|
604
|
+
* Budgets rather than an opaque level because that is what this API takes. The
|
|
605
|
+
* SDK's effort ids are a neutral surface over a provider-specific knob, and
|
|
606
|
+
* mapping them here is the whole reason `ReasoningEffortId` is opaque.
|
|
607
|
+
*/
|
|
608
|
+
const DEFAULT_THINKING_BUDGETS = Object.freeze({
|
|
609
|
+
off: 0,
|
|
610
|
+
low: 2048,
|
|
611
|
+
medium: 8192,
|
|
612
|
+
high: 24576
|
|
613
|
+
});
|
|
614
|
+
const DEFAULT_DIALECT = Object.freeze({
|
|
615
|
+
budgets: DEFAULT_THINKING_BUDGETS,
|
|
616
|
+
version: ANTHROPIC_VERSION,
|
|
617
|
+
beta: Object.freeze([])
|
|
618
|
+
});
|
|
619
|
+
/** The Anthropic Messages wire protocol. */
|
|
620
|
+
const anthropicMessagesProtocol = Object.freeze({
|
|
621
|
+
kind: "http-wire-protocol",
|
|
622
|
+
apiVersion: 1,
|
|
623
|
+
id: ANTHROPIC_MESSAGES_PROTOCOL_ID,
|
|
624
|
+
defaultDialect: DEFAULT_DIALECT,
|
|
625
|
+
endpointPath: () => "/v1/messages",
|
|
626
|
+
protocolHeaders: (dialect) => ({
|
|
627
|
+
"anthropic-version": dialect.version,
|
|
628
|
+
...dialect.beta.length === 0 ? {} : { "anthropic-beta": dialect.beta.join(",") }
|
|
629
|
+
}),
|
|
630
|
+
serialize(request, dialect) {
|
|
631
|
+
return serializeAnthropicRequest(request, { budgets: dialect.budgets });
|
|
632
|
+
},
|
|
633
|
+
translate: (events, _request, displayName) => translateAnthropicStream(events, displayName)
|
|
634
|
+
});
|
|
635
|
+
|
|
636
|
+
//#endregion
|
|
637
|
+
export { ANTHROPIC_MESSAGES_PROTOCOL_ID, ANTHROPIC_VERSION, DEFAULT_THINKING_BUDGETS, anthropicMessagesProtocol, serializeAnthropicRequest, translateAnthropicStream };
|
|
638
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +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, 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 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/** 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 '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`. They are accumulated and emitted once, 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 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 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":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@alvin0/ai-agent-sdk-protocol-anthropic-messages",
|
|
3
|
+
"author": {
|
|
4
|
+
"name": "alvin0 - chaulamdinhai",
|
|
5
|
+
"email": "chaulamdinhai@gmail.com"
|
|
6
|
+
},
|
|
7
|
+
"version": "0.1.0",
|
|
8
|
+
"description": "Universal Anthropic Messages wire schema, serializer, translator, and dialect for ai-agent-sdk",
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "git+https://github.com/alvin0/ai-agent-sdk.git",
|
|
13
|
+
"directory": "packages/protocol-anthropic-messages"
|
|
14
|
+
},
|
|
15
|
+
"homepage": "https://github.com/alvin0/ai-agent-sdk/tree/main/packages/protocol-anthropic-messages#readme",
|
|
16
|
+
"bugs": {
|
|
17
|
+
"url": "https://github.com/alvin0/ai-agent-sdk/issues"
|
|
18
|
+
},
|
|
19
|
+
"type": "module",
|
|
20
|
+
"sideEffects": false,
|
|
21
|
+
"files": [
|
|
22
|
+
"dist",
|
|
23
|
+
"README.md",
|
|
24
|
+
"LICENSE"
|
|
25
|
+
],
|
|
26
|
+
"main": "./dist/index.js",
|
|
27
|
+
"types": "./dist/index.d.ts",
|
|
28
|
+
"exports": {
|
|
29
|
+
".": {
|
|
30
|
+
"types": "./dist/index.d.ts",
|
|
31
|
+
"import": "./dist/index.js",
|
|
32
|
+
"default": "./dist/index.js"
|
|
33
|
+
},
|
|
34
|
+
"./package.json": "./package.json"
|
|
35
|
+
},
|
|
36
|
+
"publishConfig": {
|
|
37
|
+
"access": "public",
|
|
38
|
+
"provenance": true
|
|
39
|
+
},
|
|
40
|
+
"peerDependencies": {
|
|
41
|
+
"@alvin0/ai-agent-sdk-core": "^0.1.0"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@alvin0/ai-agent-sdk-core": "^0.1.0",
|
|
45
|
+
"@arethetypeswrong/cli": "0.18.5",
|
|
46
|
+
"playwright": "1.62.1",
|
|
47
|
+
"publint": "0.3.24",
|
|
48
|
+
"tsdown": "0.22.14",
|
|
49
|
+
"typescript": "7.0.2",
|
|
50
|
+
"vitest": "4.1.11",
|
|
51
|
+
"wrangler": "4.127.1"
|
|
52
|
+
},
|
|
53
|
+
"aiAgentSdk": {
|
|
54
|
+
"runtime": "universal",
|
|
55
|
+
"coreApi": 1,
|
|
56
|
+
"roles": [
|
|
57
|
+
"wire-protocol"
|
|
58
|
+
]
|
|
59
|
+
},
|
|
60
|
+
"scripts": {
|
|
61
|
+
"build": "tsdown",
|
|
62
|
+
"clean": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true});require('node:fs').rmSync('artifacts',{recursive:true,force:true})\"",
|
|
63
|
+
"typecheck": "tsc --noEmit",
|
|
64
|
+
"test": "vitest run --config vitest.config.ts",
|
|
65
|
+
"pack": "pnpm pack --pack-destination artifacts",
|
|
66
|
+
"test:pack": "node ../../scripts/test-packed-protocol.mts protocol-anthropic-messages",
|
|
67
|
+
"check:publint": "publint",
|
|
68
|
+
"check:types": "attw --profile esm-only --pack ."
|
|
69
|
+
}
|
|
70
|
+
}
|