@amux.ai/adapter-anthropic 0.1.1

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.cjs ADDED
@@ -0,0 +1,724 @@
1
+ 'use strict';
2
+
3
+ // src/inbound/request-parser.ts
4
+ function parseRequest(request) {
5
+ const req = request;
6
+ const messages = [];
7
+ for (const msg of req.messages) {
8
+ const parsed = parseMessage(msg);
9
+ messages.push(...parsed);
10
+ }
11
+ return {
12
+ messages,
13
+ model: req.model,
14
+ // Set system directly in IR instead of adding to messages
15
+ system: req.system,
16
+ tools: req.tools?.map((tool) => ({
17
+ type: "function",
18
+ function: {
19
+ name: tool.name,
20
+ description: tool.description,
21
+ parameters: tool.input_schema
22
+ }
23
+ })),
24
+ toolChoice: req.tool_choice ? req.tool_choice.type === "any" ? "required" : req.tool_choice.type === "auto" ? "auto" : req.tool_choice.name ? { type: "function", function: { name: req.tool_choice.name } } : void 0 : void 0,
25
+ stream: req.stream,
26
+ generation: {
27
+ maxTokens: req.max_tokens,
28
+ temperature: req.temperature,
29
+ topP: req.top_p,
30
+ topK: req.top_k,
31
+ stopSequences: req.stop_sequences
32
+ },
33
+ metadata: {
34
+ userId: req.metadata?.user_id
35
+ },
36
+ raw: request
37
+ };
38
+ }
39
+ function parseMessage(msg) {
40
+ if (typeof msg.content === "string") {
41
+ return [{
42
+ role: msg.role,
43
+ content: msg.content
44
+ }];
45
+ }
46
+ const contentParts = [];
47
+ const toolCalls = [];
48
+ const toolResults = [];
49
+ for (const part of msg.content) {
50
+ if (part.type === "tool_use") {
51
+ toolCalls.push({
52
+ id: part.id,
53
+ type: "function",
54
+ function: {
55
+ name: part.name,
56
+ arguments: JSON.stringify(part.input)
57
+ }
58
+ });
59
+ } else if (part.type === "tool_result") {
60
+ toolResults.push({
61
+ role: "tool",
62
+ content: typeof part.content === "string" ? part.content : JSON.stringify(part.content),
63
+ toolCallId: part.tool_use_id
64
+ });
65
+ } else {
66
+ contentParts.push(parseContentPart(part));
67
+ }
68
+ }
69
+ const messages = [];
70
+ if (contentParts.length > 0 || toolCalls.length > 0) {
71
+ const message = {
72
+ role: msg.role,
73
+ content: contentParts.length === 1 && contentParts[0]?.type === "text" ? contentParts[0].text : contentParts.length > 0 ? contentParts : ""
74
+ };
75
+ if (toolCalls.length > 0) {
76
+ message.toolCalls = toolCalls;
77
+ }
78
+ messages.push(message);
79
+ }
80
+ messages.push(...toolResults);
81
+ return messages;
82
+ }
83
+ function parseContentPart(part) {
84
+ switch (part.type) {
85
+ case "text":
86
+ return {
87
+ type: "text",
88
+ text: part.text
89
+ };
90
+ case "image":
91
+ return {
92
+ type: "image",
93
+ source: part.source.data ? {
94
+ type: "base64",
95
+ mediaType: part.source.media_type ?? "image/jpeg",
96
+ data: part.source.data
97
+ } : {
98
+ type: "url",
99
+ url: part.source.url ?? ""
100
+ }
101
+ };
102
+ default:
103
+ return {
104
+ type: "text",
105
+ text: JSON.stringify(part)
106
+ };
107
+ }
108
+ }
109
+
110
+ // src/inbound/response-parser.ts
111
+ function parseResponse(response) {
112
+ const res = response;
113
+ const contentParts = [];
114
+ const toolCalls = [];
115
+ for (const part of res.content) {
116
+ if (part.type === "tool_use") {
117
+ toolCalls.push({
118
+ id: part.id,
119
+ type: "function",
120
+ function: {
121
+ name: part.name,
122
+ arguments: JSON.stringify(part.input)
123
+ }
124
+ });
125
+ } else {
126
+ contentParts.push(parseContentPart2(part));
127
+ }
128
+ }
129
+ const message = {
130
+ role: "assistant",
131
+ content: contentParts.length === 1 && contentParts[0]?.type === "text" ? contentParts[0].text : contentParts.length > 0 ? contentParts : ""
132
+ };
133
+ if (toolCalls.length > 0) {
134
+ message.toolCalls = toolCalls;
135
+ }
136
+ const choice = {
137
+ index: 0,
138
+ message,
139
+ finishReason: mapStopReason(res.stop_reason)
140
+ };
141
+ return {
142
+ id: res.id,
143
+ model: res.model,
144
+ choices: [choice],
145
+ usage: {
146
+ promptTokens: res.usage.input_tokens,
147
+ completionTokens: res.usage.output_tokens,
148
+ totalTokens: res.usage.input_tokens + res.usage.output_tokens
149
+ },
150
+ raw: response
151
+ };
152
+ }
153
+ function parseContentPart2(part) {
154
+ switch (part.type) {
155
+ case "text":
156
+ return {
157
+ type: "text",
158
+ text: part.text
159
+ };
160
+ default:
161
+ return {
162
+ type: "text",
163
+ text: JSON.stringify(part)
164
+ };
165
+ }
166
+ }
167
+ function mapStopReason(reason) {
168
+ if (!reason) return "stop";
169
+ const reasonMap = {
170
+ "end_turn": "stop",
171
+ "max_tokens": "length",
172
+ "stop_sequence": "stop",
173
+ "tool_use": "tool_calls"
174
+ };
175
+ return reasonMap[reason] ?? "stop";
176
+ }
177
+
178
+ // src/inbound/stream-parser.ts
179
+ function parseStream(chunk) {
180
+ const event = chunk;
181
+ switch (event.type) {
182
+ case "message_start":
183
+ return {
184
+ type: "start",
185
+ id: event.message?.id,
186
+ model: event.message?.model,
187
+ raw: chunk
188
+ };
189
+ case "content_block_start":
190
+ if (event.content_block?.type === "text") {
191
+ return {
192
+ type: "content",
193
+ content: {
194
+ type: "content",
195
+ delta: "",
196
+ index: event.index
197
+ },
198
+ raw: chunk
199
+ };
200
+ }
201
+ if (event.content_block?.type === "tool_use") {
202
+ return {
203
+ type: "tool_call",
204
+ toolCall: {
205
+ type: "tool_call",
206
+ id: event.content_block.id,
207
+ name: event.content_block.name,
208
+ index: event.index
209
+ },
210
+ raw: chunk
211
+ };
212
+ }
213
+ return null;
214
+ case "content_block_delta":
215
+ if (event.delta?.type === "text_delta" && event.delta.text !== void 0) {
216
+ return {
217
+ type: "content",
218
+ content: {
219
+ type: "content",
220
+ delta: event.delta.text,
221
+ index: event.index
222
+ },
223
+ raw: chunk
224
+ };
225
+ }
226
+ if (event.delta?.type === "input_json_delta" && event.delta.partial_json !== void 0) {
227
+ return {
228
+ type: "tool_call",
229
+ toolCall: {
230
+ type: "tool_call",
231
+ arguments: event.delta.partial_json,
232
+ index: event.index
233
+ },
234
+ raw: chunk
235
+ };
236
+ }
237
+ return null;
238
+ case "content_block_stop":
239
+ return null;
240
+ case "message_delta":
241
+ if (event.delta?.stop_reason) {
242
+ return {
243
+ type: "end",
244
+ finishReason: mapStopReason2(event.delta.stop_reason),
245
+ raw: chunk
246
+ };
247
+ }
248
+ return null;
249
+ case "message_stop":
250
+ return {
251
+ type: "end",
252
+ raw: chunk
253
+ };
254
+ default:
255
+ return null;
256
+ }
257
+ }
258
+ function mapStopReason2(reason) {
259
+ const reasonMap = {
260
+ "end_turn": "stop",
261
+ "max_tokens": "length",
262
+ "stop_sequence": "stop",
263
+ "tool_use": "tool_calls"
264
+ };
265
+ return reasonMap[reason] ?? "stop";
266
+ }
267
+
268
+ // src/inbound/error-parser.ts
269
+ function parseError(error) {
270
+ if (error && typeof error === "object") {
271
+ if ("type" in error && error.type === "error" && "error" in error) {
272
+ const err = error.error;
273
+ return {
274
+ type: mapErrorType(err.type),
275
+ message: err.message,
276
+ code: err.type,
277
+ raw: error
278
+ };
279
+ }
280
+ if ("error" in error) {
281
+ const err = error.error;
282
+ return {
283
+ type: mapErrorType(err.type),
284
+ message: err.message,
285
+ code: err.type,
286
+ raw: error
287
+ };
288
+ }
289
+ }
290
+ return {
291
+ type: "unknown",
292
+ message: String(error),
293
+ raw: error
294
+ };
295
+ }
296
+ function mapErrorType(type) {
297
+ if (!type) return "unknown";
298
+ const typeMap = {
299
+ invalid_request_error: "validation",
300
+ authentication_error: "authentication",
301
+ permission_error: "permission",
302
+ not_found_error: "not_found",
303
+ rate_limit_error: "rate_limit",
304
+ api_error: "api",
305
+ overloaded_error: "server"
306
+ };
307
+ return typeMap[type] ?? "unknown";
308
+ }
309
+
310
+ // src/outbound/request-builder.ts
311
+ function buildRequest(ir) {
312
+ let system = ir.system;
313
+ const messages = [];
314
+ for (const msg of ir.messages) {
315
+ if (msg.role === "system") {
316
+ if (!system) {
317
+ system = typeof msg.content === "string" ? msg.content : JSON.stringify(msg.content);
318
+ }
319
+ } else {
320
+ messages.push(msg);
321
+ }
322
+ }
323
+ return {
324
+ model: ir.model ?? "claude-3-5-sonnet-20241022",
325
+ messages: messages.map((msg) => buildMessage(msg)),
326
+ system,
327
+ tools: ir.tools?.map((tool) => ({
328
+ name: tool.function.name,
329
+ description: tool.function.description,
330
+ input_schema: tool.function.parameters ?? { type: "object", properties: {} }
331
+ })),
332
+ tool_choice: ir.toolChoice ? typeof ir.toolChoice === "string" ? ir.toolChoice === "required" ? { type: "any" } : { type: ir.toolChoice } : { type: "tool", name: ir.toolChoice.function.name } : void 0,
333
+ max_tokens: ir.generation?.maxTokens ?? 4096,
334
+ temperature: ir.generation?.temperature,
335
+ top_p: ir.generation?.topP,
336
+ top_k: ir.generation?.topK,
337
+ stop_sequences: ir.generation?.stopSequences,
338
+ stream: ir.stream,
339
+ metadata: ir.metadata?.userId ? {
340
+ user_id: ir.metadata.userId
341
+ } : void 0
342
+ };
343
+ }
344
+ function buildMessage(msg) {
345
+ const content = [];
346
+ if (typeof msg.content === "string") {
347
+ if (msg.content) {
348
+ content.push({ type: "text", text: msg.content });
349
+ }
350
+ } else if (Array.isArray(msg.content)) {
351
+ for (const part of msg.content) {
352
+ content.push(buildContentPart(part));
353
+ }
354
+ }
355
+ if (msg.role === "tool" && msg.toolCallId) {
356
+ const resultContent = typeof msg.content === "string" ? msg.content : JSON.stringify(msg.content);
357
+ return {
358
+ role: "user",
359
+ content: [{
360
+ type: "tool_result",
361
+ tool_use_id: msg.toolCallId,
362
+ content: resultContent
363
+ }]
364
+ };
365
+ }
366
+ if (msg.toolCalls && msg.toolCalls.length > 0) {
367
+ for (const toolCall of msg.toolCalls) {
368
+ content.push({
369
+ type: "tool_use",
370
+ id: toolCall.id,
371
+ name: toolCall.function.name,
372
+ input: JSON.parse(toolCall.function.arguments)
373
+ });
374
+ }
375
+ }
376
+ if (content.length === 0) {
377
+ content.push({ type: "text", text: "" });
378
+ }
379
+ const firstContent = content[0];
380
+ const simplifiedContent = content.length === 1 && firstContent?.type === "text" ? firstContent.text : content;
381
+ return {
382
+ role: msg.role === "user" ? "user" : "assistant",
383
+ content: simplifiedContent
384
+ };
385
+ }
386
+ function buildContentPart(part) {
387
+ switch (part.type) {
388
+ case "text":
389
+ return {
390
+ type: "text",
391
+ text: part.text
392
+ };
393
+ case "image":
394
+ return {
395
+ type: "image",
396
+ source: part.source.type === "base64" ? {
397
+ type: "base64",
398
+ media_type: part.source.mediaType,
399
+ data: part.source.data
400
+ } : {
401
+ type: "url",
402
+ url: part.source.url
403
+ }
404
+ };
405
+ default:
406
+ return {
407
+ type: "text",
408
+ text: JSON.stringify(part)
409
+ };
410
+ }
411
+ }
412
+
413
+ // src/outbound/response-builder.ts
414
+ function buildResponse(ir) {
415
+ const choice = ir.choices[0];
416
+ if (!choice) {
417
+ throw new Error("No choices in response");
418
+ }
419
+ const content = buildContent(choice.message);
420
+ return {
421
+ id: ir.id,
422
+ type: "message",
423
+ role: "assistant",
424
+ content,
425
+ model: ir.model,
426
+ stop_reason: mapFinishReason(choice.finishReason),
427
+ stop_sequence: null,
428
+ usage: {
429
+ input_tokens: ir.usage?.promptTokens ?? 0,
430
+ output_tokens: ir.usage?.completionTokens ?? 0
431
+ }
432
+ };
433
+ }
434
+ function buildContent(message) {
435
+ const content = [];
436
+ if (typeof message.content === "string") {
437
+ if (message.content) {
438
+ content.push({ type: "text", text: message.content });
439
+ }
440
+ } else if (Array.isArray(message.content)) {
441
+ for (const part of message.content) {
442
+ content.push(buildContentPart2(part));
443
+ }
444
+ }
445
+ if (message.toolCalls && message.toolCalls.length > 0) {
446
+ for (const toolCall of message.toolCalls) {
447
+ content.push({
448
+ type: "tool_use",
449
+ id: toolCall.id,
450
+ name: toolCall.function.name,
451
+ input: JSON.parse(toolCall.function.arguments)
452
+ });
453
+ }
454
+ }
455
+ if (content.length === 0) {
456
+ content.push({ type: "text", text: "" });
457
+ }
458
+ return content;
459
+ }
460
+ function buildContentPart2(part) {
461
+ switch (part.type) {
462
+ case "text":
463
+ return {
464
+ type: "text",
465
+ text: part.text
466
+ };
467
+ default:
468
+ return {
469
+ type: "text",
470
+ text: JSON.stringify(part)
471
+ };
472
+ }
473
+ }
474
+ function mapFinishReason(reason) {
475
+ if (!reason) return "end_turn";
476
+ const reasonMap = {
477
+ "stop": "end_turn",
478
+ "length": "max_tokens",
479
+ "tool_calls": "tool_use"
480
+ };
481
+ return reasonMap[reason] ?? "end_turn";
482
+ }
483
+
484
+ // src/outbound/stream-builder.ts
485
+ function createStreamBuilder() {
486
+ let hasStarted = false;
487
+ let messageId = `msg_${Date.now()}`;
488
+ let model = "";
489
+ let contentIndex = 0;
490
+ let currentBlockType = null;
491
+ let outputTokens = 0;
492
+ return {
493
+ process(event) {
494
+ const events = [];
495
+ const ensureStarted = () => {
496
+ if (!hasStarted) {
497
+ hasStarted = true;
498
+ if (event.id) messageId = event.id;
499
+ if (event.model) model = event.model;
500
+ events.push({
501
+ event: "message_start",
502
+ data: {
503
+ type: "message_start",
504
+ message: {
505
+ id: messageId,
506
+ type: "message",
507
+ role: "assistant",
508
+ content: [],
509
+ model,
510
+ stop_reason: null,
511
+ stop_sequence: null,
512
+ usage: { input_tokens: 0, output_tokens: 0 }
513
+ }
514
+ }
515
+ });
516
+ }
517
+ };
518
+ if (event.type === "start") {
519
+ ensureStarted();
520
+ }
521
+ if (event.type === "reasoning" && event.reasoning?.delta) {
522
+ ensureStarted();
523
+ if (currentBlockType !== "thinking") {
524
+ if (currentBlockType !== null) {
525
+ events.push({
526
+ event: "content_block_stop",
527
+ data: { type: "content_block_stop", index: contentIndex }
528
+ });
529
+ contentIndex++;
530
+ }
531
+ events.push({
532
+ event: "content_block_start",
533
+ data: {
534
+ type: "content_block_start",
535
+ index: contentIndex,
536
+ content_block: { type: "thinking", thinking: "" }
537
+ }
538
+ });
539
+ currentBlockType = "thinking";
540
+ }
541
+ events.push({
542
+ event: "content_block_delta",
543
+ data: {
544
+ type: "content_block_delta",
545
+ index: contentIndex,
546
+ delta: { type: "thinking_delta", thinking: event.reasoning.delta }
547
+ }
548
+ });
549
+ }
550
+ if (event.type === "content" && event.content?.delta) {
551
+ ensureStarted();
552
+ if (currentBlockType !== "text") {
553
+ if (currentBlockType !== null) {
554
+ events.push({
555
+ event: "content_block_stop",
556
+ data: { type: "content_block_stop", index: contentIndex }
557
+ });
558
+ contentIndex++;
559
+ }
560
+ events.push({
561
+ event: "content_block_start",
562
+ data: {
563
+ type: "content_block_start",
564
+ index: contentIndex,
565
+ content_block: { type: "text", text: "" }
566
+ }
567
+ });
568
+ currentBlockType = "text";
569
+ }
570
+ events.push({
571
+ event: "content_block_delta",
572
+ data: {
573
+ type: "content_block_delta",
574
+ index: contentIndex,
575
+ delta: { type: "text_delta", text: event.content.delta }
576
+ }
577
+ });
578
+ }
579
+ if (event.type === "tool_call" && event.toolCall) {
580
+ ensureStarted();
581
+ if (event.toolCall.name) {
582
+ if (currentBlockType !== null) {
583
+ events.push({
584
+ event: "content_block_stop",
585
+ data: { type: "content_block_stop", index: contentIndex }
586
+ });
587
+ contentIndex++;
588
+ }
589
+ events.push({
590
+ event: "content_block_start",
591
+ data: {
592
+ type: "content_block_start",
593
+ index: contentIndex,
594
+ content_block: {
595
+ type: "tool_use",
596
+ id: event.toolCall.id || `toolu_${Date.now()}`,
597
+ name: event.toolCall.name,
598
+ input: {}
599
+ }
600
+ }
601
+ });
602
+ currentBlockType = "tool_use";
603
+ }
604
+ if (event.toolCall.arguments) {
605
+ events.push({
606
+ event: "content_block_delta",
607
+ data: {
608
+ type: "content_block_delta",
609
+ index: contentIndex,
610
+ delta: { type: "input_json_delta", partial_json: event.toolCall.arguments }
611
+ }
612
+ });
613
+ }
614
+ }
615
+ if (event.type === "end") {
616
+ if (event.usage) {
617
+ if (event.usage.completionTokens) outputTokens = event.usage.completionTokens;
618
+ }
619
+ if (currentBlockType !== null) {
620
+ events.push({
621
+ event: "content_block_stop",
622
+ data: { type: "content_block_stop", index: contentIndex }
623
+ });
624
+ }
625
+ const stopReason = mapFinishReason2(event.finishReason);
626
+ events.push({
627
+ event: "message_delta",
628
+ data: {
629
+ type: "message_delta",
630
+ delta: { stop_reason: stopReason, stop_sequence: null },
631
+ usage: { output_tokens: outputTokens }
632
+ }
633
+ });
634
+ events.push({
635
+ event: "message_stop",
636
+ data: { type: "message_stop" }
637
+ });
638
+ }
639
+ if (event.type === "error" && event.error) {
640
+ events.push({
641
+ event: "error",
642
+ data: {
643
+ type: "error",
644
+ error: {
645
+ type: "api_error",
646
+ message: event.error.message
647
+ }
648
+ }
649
+ });
650
+ }
651
+ return events;
652
+ }
653
+ };
654
+ }
655
+ function mapFinishReason2(reason) {
656
+ if (!reason) return "end_turn";
657
+ const reasonMap = {
658
+ stop: "end_turn",
659
+ length: "max_tokens",
660
+ tool_calls: "tool_use",
661
+ content_filter: "end_turn"
662
+ };
663
+ return reasonMap[reason] ?? "end_turn";
664
+ }
665
+
666
+ // src/adapter.ts
667
+ var anthropicAdapter = {
668
+ name: "anthropic",
669
+ version: "1.0.0",
670
+ capabilities: {
671
+ streaming: true,
672
+ tools: true,
673
+ vision: true,
674
+ multimodal: true,
675
+ systemPrompt: true,
676
+ toolChoice: true,
677
+ reasoning: true,
678
+ // Extended thinking
679
+ webSearch: false,
680
+ jsonMode: false,
681
+ // Anthropic doesn't have native JSON mode
682
+ logprobs: false,
683
+ seed: false
684
+ },
685
+ inbound: {
686
+ parseRequest: (request) => {
687
+ return parseRequest(request);
688
+ },
689
+ parseResponse: (response) => {
690
+ return parseResponse(response);
691
+ },
692
+ parseStream: (chunk) => {
693
+ return parseStream(chunk);
694
+ },
695
+ parseError: (error) => {
696
+ return parseError(error);
697
+ }
698
+ },
699
+ outbound: {
700
+ buildRequest: (ir) => {
701
+ return buildRequest(ir);
702
+ },
703
+ buildResponse: (ir) => {
704
+ return buildResponse(ir);
705
+ },
706
+ createStreamBuilder
707
+ },
708
+ getInfo() {
709
+ return {
710
+ name: this.name,
711
+ version: this.version,
712
+ capabilities: this.capabilities,
713
+ endpoint: {
714
+ baseUrl: "https://api.anthropic.com",
715
+ chatPath: "/v1/messages",
716
+ modelsPath: "/v1/models"
717
+ }
718
+ };
719
+ }
720
+ };
721
+
722
+ exports.anthropicAdapter = anthropicAdapter;
723
+ //# sourceMappingURL=index.cjs.map
724
+ //# sourceMappingURL=index.cjs.map