@yourgpt/llm-sdk 0.1.0 → 1.0.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.
Files changed (56) hide show
  1. package/README.md +61 -40
  2. package/dist/adapters/index.d.mts +4 -258
  3. package/dist/adapters/index.d.ts +4 -258
  4. package/dist/adapters/index.js +0 -113
  5. package/dist/adapters/index.js.map +1 -1
  6. package/dist/adapters/index.mjs +1 -112
  7. package/dist/adapters/index.mjs.map +1 -1
  8. package/dist/base-D_FyHFKj.d.mts +235 -0
  9. package/dist/base-D_FyHFKj.d.ts +235 -0
  10. package/dist/index.d.mts +209 -451
  11. package/dist/index.d.ts +209 -451
  12. package/dist/index.js +1905 -311
  13. package/dist/index.js.map +1 -1
  14. package/dist/index.mjs +1895 -309
  15. package/dist/index.mjs.map +1 -1
  16. package/dist/providers/anthropic/index.d.mts +61 -0
  17. package/dist/providers/anthropic/index.d.ts +61 -0
  18. package/dist/providers/anthropic/index.js +939 -0
  19. package/dist/providers/anthropic/index.js.map +1 -0
  20. package/dist/providers/anthropic/index.mjs +934 -0
  21. package/dist/providers/anthropic/index.mjs.map +1 -0
  22. package/dist/providers/azure/index.d.mts +38 -0
  23. package/dist/providers/azure/index.d.ts +38 -0
  24. package/dist/providers/azure/index.js +380 -0
  25. package/dist/providers/azure/index.js.map +1 -0
  26. package/dist/providers/azure/index.mjs +377 -0
  27. package/dist/providers/azure/index.mjs.map +1 -0
  28. package/dist/providers/google/index.d.mts +72 -0
  29. package/dist/providers/google/index.d.ts +72 -0
  30. package/dist/providers/google/index.js +790 -0
  31. package/dist/providers/google/index.js.map +1 -0
  32. package/dist/providers/google/index.mjs +785 -0
  33. package/dist/providers/google/index.mjs.map +1 -0
  34. package/dist/providers/ollama/index.d.mts +24 -0
  35. package/dist/providers/ollama/index.d.ts +24 -0
  36. package/dist/providers/ollama/index.js +235 -0
  37. package/dist/providers/ollama/index.js.map +1 -0
  38. package/dist/providers/ollama/index.mjs +232 -0
  39. package/dist/providers/ollama/index.mjs.map +1 -0
  40. package/dist/providers/openai/index.d.mts +82 -0
  41. package/dist/providers/openai/index.d.ts +82 -0
  42. package/dist/providers/openai/index.js +679 -0
  43. package/dist/providers/openai/index.js.map +1 -0
  44. package/dist/providers/openai/index.mjs +674 -0
  45. package/dist/providers/openai/index.mjs.map +1 -0
  46. package/dist/providers/xai/index.d.mts +78 -0
  47. package/dist/providers/xai/index.d.ts +78 -0
  48. package/dist/providers/xai/index.js +671 -0
  49. package/dist/providers/xai/index.js.map +1 -0
  50. package/dist/providers/xai/index.mjs +666 -0
  51. package/dist/providers/xai/index.mjs.map +1 -0
  52. package/dist/types-BBCZ3Fxy.d.mts +308 -0
  53. package/dist/types-CdORv1Yu.d.mts +338 -0
  54. package/dist/types-CdORv1Yu.d.ts +338 -0
  55. package/dist/types-DcoCaVVC.d.ts +308 -0
  56. package/package.json +34 -3
@@ -0,0 +1,939 @@
1
+ 'use strict';
2
+
3
+ var core = require('@yourgpt/copilot-sdk/core');
4
+
5
+ // src/providers/anthropic/provider.ts
6
+ var ANTHROPIC_MODELS = {
7
+ // Claude 4 series
8
+ "claude-sonnet-4-20250514": {
9
+ vision: true,
10
+ tools: true,
11
+ thinking: true,
12
+ pdf: true,
13
+ maxTokens: 2e5
14
+ },
15
+ "claude-opus-4-20250514": {
16
+ vision: true,
17
+ tools: true,
18
+ thinking: true,
19
+ pdf: true,
20
+ maxTokens: 2e5
21
+ },
22
+ // Claude 3.7 series
23
+ "claude-3-7-sonnet-20250219": {
24
+ vision: true,
25
+ tools: true,
26
+ thinking: true,
27
+ pdf: true,
28
+ maxTokens: 2e5
29
+ },
30
+ "claude-3-7-sonnet-latest": {
31
+ vision: true,
32
+ tools: true,
33
+ thinking: true,
34
+ pdf: true,
35
+ maxTokens: 2e5
36
+ },
37
+ // Claude 3.5 series
38
+ "claude-3-5-sonnet-20241022": {
39
+ vision: true,
40
+ tools: true,
41
+ thinking: false,
42
+ pdf: true,
43
+ maxTokens: 2e5
44
+ },
45
+ "claude-3-5-sonnet-latest": {
46
+ vision: true,
47
+ tools: true,
48
+ thinking: false,
49
+ pdf: true,
50
+ maxTokens: 2e5
51
+ },
52
+ "claude-3-5-haiku-20241022": {
53
+ vision: true,
54
+ tools: true,
55
+ thinking: false,
56
+ pdf: false,
57
+ maxTokens: 2e5
58
+ },
59
+ "claude-3-5-haiku-latest": {
60
+ vision: true,
61
+ tools: true,
62
+ thinking: false,
63
+ pdf: false,
64
+ maxTokens: 2e5
65
+ },
66
+ // Claude 3 series
67
+ "claude-3-opus-20240229": {
68
+ vision: true,
69
+ tools: true,
70
+ thinking: false,
71
+ pdf: false,
72
+ maxTokens: 2e5
73
+ },
74
+ "claude-3-sonnet-20240229": {
75
+ vision: true,
76
+ tools: true,
77
+ thinking: false,
78
+ pdf: false,
79
+ maxTokens: 2e5
80
+ },
81
+ "claude-3-haiku-20240307": {
82
+ vision: true,
83
+ tools: true,
84
+ thinking: false,
85
+ pdf: false,
86
+ maxTokens: 2e5
87
+ }
88
+ };
89
+ function anthropic(modelId, options = {}) {
90
+ const apiKey = options.apiKey ?? process.env.ANTHROPIC_API_KEY;
91
+ let client = null;
92
+ async function getClient() {
93
+ if (!client) {
94
+ const { default: Anthropic } = await import('@anthropic-ai/sdk');
95
+ client = new Anthropic({
96
+ apiKey,
97
+ baseURL: options.baseURL
98
+ });
99
+ }
100
+ return client;
101
+ }
102
+ const modelConfig = ANTHROPIC_MODELS[modelId] ?? ANTHROPIC_MODELS["claude-3-5-sonnet-latest"];
103
+ return {
104
+ provider: "anthropic",
105
+ modelId,
106
+ capabilities: {
107
+ supportsVision: modelConfig.vision,
108
+ supportsTools: modelConfig.tools,
109
+ supportsStreaming: true,
110
+ supportsJsonMode: false,
111
+ supportsThinking: modelConfig.thinking,
112
+ supportsPDF: modelConfig.pdf,
113
+ maxTokens: modelConfig.maxTokens,
114
+ supportedImageTypes: modelConfig.vision ? ["image/png", "image/jpeg", "image/gif", "image/webp"] : []
115
+ },
116
+ async doGenerate(params) {
117
+ const client2 = await getClient();
118
+ const { system, messages } = formatMessagesForAnthropic(params.messages);
119
+ const requestOptions = {
120
+ model: modelId,
121
+ max_tokens: params.maxTokens ?? 4096,
122
+ system: system || void 0,
123
+ messages,
124
+ tools: params.tools
125
+ };
126
+ if (params.temperature !== void 0) {
127
+ requestOptions.temperature = params.temperature;
128
+ }
129
+ if (options.thinking?.enabled && modelConfig.thinking) {
130
+ requestOptions.thinking = {
131
+ type: "enabled",
132
+ budget_tokens: options.thinking.budgetTokens ?? 1e4
133
+ };
134
+ }
135
+ const response = await client2.messages.create(requestOptions);
136
+ let text = "";
137
+ const toolCalls = [];
138
+ for (const block of response.content) {
139
+ if (block.type === "text") {
140
+ text += block.text;
141
+ } else if (block.type === "tool_use") {
142
+ toolCalls.push({
143
+ id: block.id,
144
+ name: block.name,
145
+ args: block.input
146
+ });
147
+ }
148
+ }
149
+ return {
150
+ text,
151
+ toolCalls,
152
+ finishReason: mapFinishReason(response.stop_reason),
153
+ usage: {
154
+ promptTokens: response.usage?.input_tokens ?? 0,
155
+ completionTokens: response.usage?.output_tokens ?? 0,
156
+ totalTokens: (response.usage?.input_tokens ?? 0) + (response.usage?.output_tokens ?? 0)
157
+ },
158
+ rawResponse: response
159
+ };
160
+ },
161
+ async *doStream(params) {
162
+ const client2 = await getClient();
163
+ const { system, messages } = formatMessagesForAnthropic(params.messages);
164
+ const requestOptions = {
165
+ model: modelId,
166
+ max_tokens: params.maxTokens ?? 4096,
167
+ system: system || void 0,
168
+ messages,
169
+ tools: params.tools
170
+ };
171
+ if (params.temperature !== void 0) {
172
+ requestOptions.temperature = params.temperature;
173
+ }
174
+ if (options.thinking?.enabled && modelConfig.thinking) {
175
+ requestOptions.thinking = {
176
+ type: "enabled",
177
+ budget_tokens: options.thinking.budgetTokens ?? 1e4
178
+ };
179
+ }
180
+ const stream = await client2.messages.stream(requestOptions);
181
+ let currentToolUse = null;
182
+ let inputTokens = 0;
183
+ let outputTokens = 0;
184
+ for await (const event of stream) {
185
+ if (params.signal?.aborted) {
186
+ yield { type: "error", error: new Error("Aborted") };
187
+ return;
188
+ }
189
+ switch (event.type) {
190
+ case "message_start":
191
+ if (event.message?.usage) {
192
+ inputTokens = event.message.usage.input_tokens ?? 0;
193
+ }
194
+ break;
195
+ case "content_block_start":
196
+ if (event.content_block?.type === "tool_use") {
197
+ currentToolUse = {
198
+ id: event.content_block.id,
199
+ name: event.content_block.name,
200
+ input: ""
201
+ };
202
+ }
203
+ break;
204
+ case "content_block_delta":
205
+ if (event.delta?.type === "text_delta") {
206
+ yield { type: "text-delta", text: event.delta.text };
207
+ } else if (event.delta?.type === "input_json_delta" && currentToolUse) {
208
+ currentToolUse.input += event.delta.partial_json;
209
+ }
210
+ break;
211
+ case "content_block_stop":
212
+ if (currentToolUse) {
213
+ yield {
214
+ type: "tool-call",
215
+ toolCall: {
216
+ id: currentToolUse.id,
217
+ name: currentToolUse.name,
218
+ args: JSON.parse(currentToolUse.input || "{}")
219
+ }
220
+ };
221
+ currentToolUse = null;
222
+ }
223
+ break;
224
+ case "message_delta":
225
+ if (event.usage) {
226
+ outputTokens = event.usage.output_tokens ?? 0;
227
+ }
228
+ if (event.delta?.stop_reason) {
229
+ yield {
230
+ type: "finish",
231
+ finishReason: mapFinishReason(event.delta.stop_reason),
232
+ usage: {
233
+ promptTokens: inputTokens,
234
+ completionTokens: outputTokens,
235
+ totalTokens: inputTokens + outputTokens
236
+ }
237
+ };
238
+ }
239
+ break;
240
+ }
241
+ }
242
+ }
243
+ };
244
+ }
245
+ function mapFinishReason(reason) {
246
+ switch (reason) {
247
+ case "end_turn":
248
+ case "stop_sequence":
249
+ return "stop";
250
+ case "max_tokens":
251
+ return "length";
252
+ case "tool_use":
253
+ return "tool-calls";
254
+ default:
255
+ return "unknown";
256
+ }
257
+ }
258
+ function formatMessagesForAnthropic(messages) {
259
+ let system = "";
260
+ const formatted = [];
261
+ const pendingToolResults = [];
262
+ for (const msg of messages) {
263
+ if (msg.role === "system") {
264
+ system += (system ? "\n" : "") + msg.content;
265
+ continue;
266
+ }
267
+ if (msg.role === "assistant" && pendingToolResults.length > 0) {
268
+ formatted.push({
269
+ role: "user",
270
+ content: pendingToolResults.map((tr) => ({
271
+ type: "tool_result",
272
+ tool_use_id: tr.toolCallId,
273
+ content: tr.content
274
+ }))
275
+ });
276
+ pendingToolResults.length = 0;
277
+ }
278
+ if (msg.role === "user") {
279
+ if (pendingToolResults.length > 0) {
280
+ formatted.push({
281
+ role: "user",
282
+ content: pendingToolResults.map((tr) => ({
283
+ type: "tool_result",
284
+ tool_use_id: tr.toolCallId,
285
+ content: tr.content
286
+ }))
287
+ });
288
+ pendingToolResults.length = 0;
289
+ }
290
+ if (typeof msg.content === "string") {
291
+ formatted.push({ role: "user", content: msg.content });
292
+ } else {
293
+ const content = [];
294
+ for (const part of msg.content) {
295
+ if (part.type === "text") {
296
+ content.push({ type: "text", text: part.text });
297
+ } else if (part.type === "image") {
298
+ const imageData = typeof part.image === "string" ? part.image : Buffer.from(part.image).toString("base64");
299
+ if (imageData.startsWith("http")) {
300
+ content.push({
301
+ type: "image",
302
+ source: { type: "url", url: imageData }
303
+ });
304
+ } else {
305
+ const base64 = imageData.startsWith("data:") ? imageData.split(",")[1] : imageData;
306
+ content.push({
307
+ type: "image",
308
+ source: {
309
+ type: "base64",
310
+ media_type: part.mimeType ?? "image/png",
311
+ data: base64
312
+ }
313
+ });
314
+ }
315
+ }
316
+ }
317
+ formatted.push({ role: "user", content });
318
+ }
319
+ } else if (msg.role === "assistant") {
320
+ const content = [];
321
+ if (msg.content) {
322
+ content.push({ type: "text", text: msg.content });
323
+ }
324
+ if (msg.toolCalls && msg.toolCalls.length > 0) {
325
+ for (const tc of msg.toolCalls) {
326
+ content.push({
327
+ type: "tool_use",
328
+ id: tc.id,
329
+ name: tc.name,
330
+ input: tc.args
331
+ });
332
+ }
333
+ }
334
+ if (content.length > 0) {
335
+ formatted.push({ role: "assistant", content });
336
+ }
337
+ } else if (msg.role === "tool") {
338
+ pendingToolResults.push({
339
+ toolCallId: msg.toolCallId,
340
+ content: msg.content
341
+ });
342
+ }
343
+ }
344
+ if (pendingToolResults.length > 0) {
345
+ formatted.push({
346
+ role: "user",
347
+ content: pendingToolResults.map((tr) => ({
348
+ type: "tool_result",
349
+ tool_use_id: tr.toolCallId,
350
+ content: tr.content
351
+ }))
352
+ });
353
+ }
354
+ return { system, messages: formatted };
355
+ }
356
+
357
+ // src/adapters/base.ts
358
+ function hasMediaAttachments(message) {
359
+ const attachments = message.metadata?.attachments;
360
+ return attachments?.some(
361
+ (a) => a.type === "image" || a.type === "file" && a.mimeType === "application/pdf"
362
+ ) ?? false;
363
+ }
364
+ function attachmentToAnthropicImage(attachment) {
365
+ if (attachment.type !== "image") return null;
366
+ if (attachment.url) {
367
+ return {
368
+ type: "image",
369
+ source: {
370
+ type: "url",
371
+ url: attachment.url
372
+ }
373
+ };
374
+ }
375
+ if (!attachment.data) return null;
376
+ let base64Data = attachment.data;
377
+ if (base64Data.startsWith("data:")) {
378
+ const commaIndex = base64Data.indexOf(",");
379
+ if (commaIndex !== -1) {
380
+ base64Data = base64Data.slice(commaIndex + 1);
381
+ }
382
+ }
383
+ return {
384
+ type: "image",
385
+ source: {
386
+ type: "base64",
387
+ media_type: attachment.mimeType || "image/png",
388
+ data: base64Data
389
+ }
390
+ };
391
+ }
392
+ function attachmentToAnthropicDocument(attachment) {
393
+ if (attachment.type !== "file" || attachment.mimeType !== "application/pdf") {
394
+ return null;
395
+ }
396
+ if (attachment.url) {
397
+ return {
398
+ type: "document",
399
+ source: {
400
+ type: "url",
401
+ url: attachment.url
402
+ }
403
+ };
404
+ }
405
+ if (!attachment.data) return null;
406
+ let base64Data = attachment.data;
407
+ if (base64Data.startsWith("data:")) {
408
+ const commaIndex = base64Data.indexOf(",");
409
+ if (commaIndex !== -1) {
410
+ base64Data = base64Data.slice(commaIndex + 1);
411
+ }
412
+ }
413
+ return {
414
+ type: "document",
415
+ source: {
416
+ type: "base64",
417
+ media_type: "application/pdf",
418
+ data: base64Data
419
+ }
420
+ };
421
+ }
422
+ function messageToAnthropicContent(message) {
423
+ const attachments = message.metadata?.attachments;
424
+ const content = message.content ?? "";
425
+ if (!hasMediaAttachments(message)) {
426
+ return content;
427
+ }
428
+ const blocks = [];
429
+ if (attachments) {
430
+ for (const attachment of attachments) {
431
+ const imageBlock = attachmentToAnthropicImage(attachment);
432
+ if (imageBlock) {
433
+ blocks.push(imageBlock);
434
+ continue;
435
+ }
436
+ const docBlock = attachmentToAnthropicDocument(attachment);
437
+ if (docBlock) {
438
+ blocks.push(docBlock);
439
+ }
440
+ }
441
+ }
442
+ if (content) {
443
+ blocks.push({ type: "text", text: content });
444
+ }
445
+ return blocks;
446
+ }
447
+ function formatMessagesForAnthropic2(messages, systemPrompt) {
448
+ const formatted = [];
449
+ for (let i = 0; i < messages.length; i++) {
450
+ const msg = messages[i];
451
+ if (msg.role === "system") continue;
452
+ if (msg.role === "assistant") {
453
+ const content = [];
454
+ if (msg.content) {
455
+ content.push({ type: "text", text: msg.content });
456
+ }
457
+ if (msg.tool_calls && msg.tool_calls.length > 0) {
458
+ for (const tc of msg.tool_calls) {
459
+ content.push({
460
+ type: "tool_use",
461
+ id: tc.id,
462
+ name: tc.function.name,
463
+ input: JSON.parse(tc.function.arguments)
464
+ });
465
+ }
466
+ }
467
+ formatted.push({
468
+ role: "assistant",
469
+ content: content.length === 1 && content[0].type === "text" ? content[0].text : content
470
+ });
471
+ } else if (msg.role === "tool" && msg.tool_call_id) {
472
+ const toolResults = [
473
+ {
474
+ type: "tool_result",
475
+ tool_use_id: msg.tool_call_id,
476
+ content: msg.content ?? ""
477
+ }
478
+ ];
479
+ while (i + 1 < messages.length && messages[i + 1].role === "tool") {
480
+ i++;
481
+ const nextTool = messages[i];
482
+ if (nextTool.tool_call_id) {
483
+ toolResults.push({
484
+ type: "tool_result",
485
+ tool_use_id: nextTool.tool_call_id,
486
+ content: nextTool.content ?? ""
487
+ });
488
+ }
489
+ }
490
+ formatted.push({
491
+ role: "user",
492
+ content: toolResults
493
+ });
494
+ } else if (msg.role === "user") {
495
+ formatted.push({
496
+ role: "user",
497
+ content: messageToAnthropicContent(msg)
498
+ });
499
+ }
500
+ }
501
+ return {
502
+ system: "",
503
+ messages: formatted
504
+ };
505
+ }
506
+
507
+ // src/adapters/anthropic.ts
508
+ var AnthropicAdapter = class {
509
+ constructor(config) {
510
+ this.provider = "anthropic";
511
+ this.config = config;
512
+ this.model = config.model || "claude-3-5-sonnet-latest";
513
+ }
514
+ async getClient() {
515
+ if (!this.client) {
516
+ const { default: Anthropic } = await import('@anthropic-ai/sdk');
517
+ this.client = new Anthropic({
518
+ apiKey: this.config.apiKey
519
+ });
520
+ }
521
+ return this.client;
522
+ }
523
+ /**
524
+ * Convert OpenAI-style messages to Anthropic format
525
+ *
526
+ * OpenAI format:
527
+ * - { role: "assistant", content: "...", tool_calls: [...] }
528
+ * - { role: "tool", tool_call_id: "...", content: "..." }
529
+ *
530
+ * Anthropic format:
531
+ * - { role: "assistant", content: [{ type: "text", text: "..." }, { type: "tool_use", id: "...", name: "...", input: {...} }] }
532
+ * - { role: "user", content: [{ type: "tool_result", tool_use_id: "...", content: "..." }] }
533
+ */
534
+ convertToAnthropicMessages(rawMessages) {
535
+ const messages = [];
536
+ const pendingToolResults = [];
537
+ for (const msg of rawMessages) {
538
+ if (msg.role === "system") continue;
539
+ if (msg.role === "assistant") {
540
+ if (pendingToolResults.length > 0) {
541
+ messages.push({
542
+ role: "user",
543
+ content: pendingToolResults.map((tr) => ({
544
+ type: "tool_result",
545
+ tool_use_id: tr.tool_use_id,
546
+ content: tr.content
547
+ }))
548
+ });
549
+ pendingToolResults.length = 0;
550
+ }
551
+ const content = [];
552
+ if (msg.content && typeof msg.content === "string" && msg.content.trim()) {
553
+ content.push({ type: "text", text: msg.content });
554
+ }
555
+ const toolCalls = msg.tool_calls;
556
+ if (toolCalls && toolCalls.length > 0) {
557
+ for (const tc of toolCalls) {
558
+ let input = {};
559
+ try {
560
+ input = JSON.parse(tc.function.arguments);
561
+ } catch {
562
+ }
563
+ content.push({
564
+ type: "tool_use",
565
+ id: tc.id,
566
+ name: tc.function.name,
567
+ input
568
+ });
569
+ }
570
+ }
571
+ if (content.length > 0) {
572
+ messages.push({ role: "assistant", content });
573
+ }
574
+ } else if (msg.role === "tool") {
575
+ pendingToolResults.push({
576
+ tool_use_id: msg.tool_call_id,
577
+ content: typeof msg.content === "string" ? msg.content : JSON.stringify(msg.content)
578
+ });
579
+ } else if (msg.role === "user") {
580
+ if (pendingToolResults.length > 0) {
581
+ messages.push({
582
+ role: "user",
583
+ content: pendingToolResults.map((tr) => ({
584
+ type: "tool_result",
585
+ tool_use_id: tr.tool_use_id,
586
+ content: tr.content
587
+ }))
588
+ });
589
+ pendingToolResults.length = 0;
590
+ }
591
+ if (msg.attachments && Array.isArray(msg.attachments) && msg.attachments.length > 0) {
592
+ const content = [];
593
+ if (msg.content && typeof msg.content === "string") {
594
+ content.push({ type: "text", text: msg.content });
595
+ }
596
+ for (const attachment of msg.attachments) {
597
+ if (attachment.type === "image") {
598
+ if (attachment.url) {
599
+ content.push({
600
+ type: "image",
601
+ source: {
602
+ type: "url",
603
+ url: attachment.url
604
+ }
605
+ });
606
+ } else if (attachment.data) {
607
+ let base64Data = attachment.data;
608
+ if (base64Data.startsWith("data:")) {
609
+ const commaIndex = base64Data.indexOf(",");
610
+ if (commaIndex !== -1) {
611
+ base64Data = base64Data.slice(commaIndex + 1);
612
+ }
613
+ }
614
+ content.push({
615
+ type: "image",
616
+ source: {
617
+ type: "base64",
618
+ media_type: attachment.mimeType || "image/png",
619
+ data: base64Data
620
+ }
621
+ });
622
+ }
623
+ } else if (attachment.type === "file" && attachment.mimeType === "application/pdf") {
624
+ if (attachment.url) {
625
+ content.push({
626
+ type: "document",
627
+ source: {
628
+ type: "url",
629
+ url: attachment.url
630
+ }
631
+ });
632
+ } else if (attachment.data) {
633
+ let base64Data = attachment.data;
634
+ if (base64Data.startsWith("data:")) {
635
+ const commaIndex = base64Data.indexOf(",");
636
+ if (commaIndex !== -1) {
637
+ base64Data = base64Data.slice(commaIndex + 1);
638
+ }
639
+ }
640
+ content.push({
641
+ type: "document",
642
+ source: {
643
+ type: "base64",
644
+ media_type: "application/pdf",
645
+ data: base64Data
646
+ }
647
+ });
648
+ }
649
+ }
650
+ }
651
+ messages.push({ role: "user", content });
652
+ } else {
653
+ messages.push({
654
+ role: "user",
655
+ content: typeof msg.content === "string" ? msg.content : JSON.stringify(msg.content)
656
+ });
657
+ }
658
+ }
659
+ }
660
+ if (pendingToolResults.length > 0) {
661
+ messages.push({
662
+ role: "user",
663
+ content: pendingToolResults.map((tr) => ({
664
+ type: "tool_result",
665
+ tool_use_id: tr.tool_use_id,
666
+ content: tr.content
667
+ }))
668
+ });
669
+ }
670
+ return messages;
671
+ }
672
+ /**
673
+ * Build common request options for both streaming and non-streaming
674
+ */
675
+ buildRequestOptions(request) {
676
+ const systemMessage = request.systemPrompt || "";
677
+ let messages;
678
+ if (request.rawMessages && request.rawMessages.length > 0) {
679
+ messages = this.convertToAnthropicMessages(request.rawMessages);
680
+ } else {
681
+ const formatted = formatMessagesForAnthropic2(request.messages);
682
+ messages = formatted.messages;
683
+ }
684
+ const tools = request.actions?.map((action) => ({
685
+ name: action.name,
686
+ description: action.description,
687
+ input_schema: {
688
+ type: "object",
689
+ properties: action.parameters ? Object.fromEntries(
690
+ Object.entries(action.parameters).map(([key, param]) => [
691
+ key,
692
+ {
693
+ type: param.type,
694
+ description: param.description,
695
+ enum: param.enum
696
+ }
697
+ ])
698
+ ) : {},
699
+ required: action.parameters ? Object.entries(action.parameters).filter(([, param]) => param.required).map(([key]) => key) : []
700
+ }
701
+ }));
702
+ const options = {
703
+ model: request.config?.model || this.model,
704
+ max_tokens: request.config?.maxTokens || this.config.maxTokens || 4096,
705
+ system: systemMessage,
706
+ messages,
707
+ tools: tools?.length ? tools : void 0
708
+ };
709
+ if (this.config.thinking?.type === "enabled") {
710
+ options.thinking = {
711
+ type: "enabled",
712
+ budget_tokens: this.config.thinking.budgetTokens || 1e4
713
+ };
714
+ }
715
+ return { options, messages };
716
+ }
717
+ /**
718
+ * Non-streaming completion (for debugging/comparison with original studio-ai)
719
+ */
720
+ async complete(request) {
721
+ const client = await this.getClient();
722
+ const { options } = this.buildRequestOptions(request);
723
+ const nonStreamingOptions = {
724
+ ...options,
725
+ stream: false
726
+ };
727
+ try {
728
+ const response = await client.messages.create(nonStreamingOptions);
729
+ let content = "";
730
+ let thinking = "";
731
+ const toolCalls = [];
732
+ for (const block of response.content) {
733
+ if (block.type === "text") {
734
+ content += block.text;
735
+ } else if (block.type === "thinking") {
736
+ thinking += block.thinking;
737
+ } else if (block.type === "tool_use") {
738
+ toolCalls.push({
739
+ id: block.id,
740
+ name: block.name,
741
+ args: block.input
742
+ });
743
+ }
744
+ }
745
+ return {
746
+ content,
747
+ toolCalls,
748
+ thinking: thinking || void 0,
749
+ rawResponse: response
750
+ };
751
+ } catch (error) {
752
+ throw error;
753
+ }
754
+ }
755
+ async *stream(request) {
756
+ const client = await this.getClient();
757
+ const { options } = this.buildRequestOptions(request);
758
+ const messageId = core.generateMessageId();
759
+ yield { type: "message:start", id: messageId };
760
+ try {
761
+ const stream = await client.messages.stream(options);
762
+ let currentToolUse = null;
763
+ let isInThinkingBlock = false;
764
+ for await (const event of stream) {
765
+ if (request.signal?.aborted) {
766
+ break;
767
+ }
768
+ switch (event.type) {
769
+ case "content_block_start":
770
+ if (event.content_block.type === "tool_use") {
771
+ currentToolUse = {
772
+ id: event.content_block.id,
773
+ name: event.content_block.name,
774
+ input: ""
775
+ };
776
+ yield {
777
+ type: "action:start",
778
+ id: currentToolUse.id,
779
+ name: currentToolUse.name
780
+ };
781
+ } else if (event.content_block.type === "thinking") {
782
+ isInThinkingBlock = true;
783
+ yield { type: "thinking:start" };
784
+ }
785
+ break;
786
+ case "content_block_delta":
787
+ if (event.delta.type === "text_delta") {
788
+ yield { type: "message:delta", content: event.delta.text };
789
+ } else if (event.delta.type === "thinking_delta") {
790
+ yield { type: "thinking:delta", content: event.delta.thinking };
791
+ } else if (event.delta.type === "input_json_delta" && currentToolUse) {
792
+ currentToolUse.input += event.delta.partial_json;
793
+ }
794
+ break;
795
+ case "content_block_stop":
796
+ if (currentToolUse) {
797
+ yield {
798
+ type: "action:args",
799
+ id: currentToolUse.id,
800
+ args: currentToolUse.input
801
+ };
802
+ currentToolUse = null;
803
+ }
804
+ if (isInThinkingBlock) {
805
+ yield { type: "thinking:end" };
806
+ isInThinkingBlock = false;
807
+ }
808
+ break;
809
+ case "message_stop":
810
+ break;
811
+ }
812
+ }
813
+ yield { type: "message:end" };
814
+ yield { type: "done" };
815
+ } catch (error) {
816
+ yield {
817
+ type: "error",
818
+ message: error instanceof Error ? error.message : "Unknown error",
819
+ code: "ANTHROPIC_ERROR"
820
+ };
821
+ }
822
+ }
823
+ };
824
+ function createAnthropicAdapter(config) {
825
+ return new AnthropicAdapter(config);
826
+ }
827
+
828
+ // src/providers/anthropic/index.ts
829
+ var ANTHROPIC_MODELS2 = {
830
+ // Claude 4 series (latest)
831
+ "claude-sonnet-4-20250514": {
832
+ vision: true,
833
+ tools: true,
834
+ thinking: true,
835
+ maxTokens: 64e3
836
+ },
837
+ "claude-opus-4-20250514": {
838
+ vision: true,
839
+ tools: true,
840
+ thinking: true,
841
+ maxTokens: 32e3
842
+ },
843
+ // Claude 3.5 series
844
+ "claude-3-5-sonnet-latest": {
845
+ vision: true,
846
+ tools: true,
847
+ thinking: true,
848
+ maxTokens: 2e5
849
+ },
850
+ "claude-3-5-sonnet-20241022": {
851
+ vision: true,
852
+ tools: true,
853
+ thinking: true,
854
+ maxTokens: 2e5
855
+ },
856
+ "claude-3-5-haiku-latest": {
857
+ vision: true,
858
+ tools: true,
859
+ thinking: false,
860
+ maxTokens: 2e5
861
+ },
862
+ "claude-3-5-haiku-20241022": {
863
+ vision: true,
864
+ tools: true,
865
+ thinking: false,
866
+ maxTokens: 2e5
867
+ },
868
+ // Claude 3 series
869
+ "claude-3-opus-latest": {
870
+ vision: true,
871
+ tools: true,
872
+ thinking: true,
873
+ maxTokens: 2e5
874
+ },
875
+ "claude-3-opus-20240229": {
876
+ vision: true,
877
+ tools: true,
878
+ thinking: true,
879
+ maxTokens: 2e5
880
+ },
881
+ "claude-3-sonnet-20240229": {
882
+ vision: true,
883
+ tools: true,
884
+ thinking: false,
885
+ maxTokens: 2e5
886
+ },
887
+ "claude-3-haiku-20240307": {
888
+ vision: true,
889
+ tools: true,
890
+ thinking: false,
891
+ maxTokens: 2e5
892
+ }
893
+ };
894
+ function createAnthropic(config = {}) {
895
+ const apiKey = config.apiKey ?? process.env.ANTHROPIC_API_KEY ?? "";
896
+ return {
897
+ name: "anthropic",
898
+ supportedModels: Object.keys(ANTHROPIC_MODELS2),
899
+ languageModel(modelId) {
900
+ return createAnthropicAdapter({
901
+ apiKey,
902
+ model: modelId,
903
+ baseUrl: config.baseUrl,
904
+ thinking: config.thinkingBudget ? { type: "enabled", budgetTokens: config.thinkingBudget } : void 0
905
+ });
906
+ },
907
+ getCapabilities(modelId) {
908
+ const model = ANTHROPIC_MODELS2[modelId] ?? ANTHROPIC_MODELS2["claude-3-5-sonnet-latest"];
909
+ return {
910
+ supportsVision: model.vision,
911
+ supportsTools: model.tools,
912
+ supportsThinking: model.thinking,
913
+ supportsStreaming: true,
914
+ supportsPDF: true,
915
+ // Claude supports PDFs
916
+ supportsAudio: false,
917
+ supportsVideo: false,
918
+ maxTokens: model.maxTokens,
919
+ supportedImageTypes: [
920
+ "image/png",
921
+ "image/jpeg",
922
+ "image/gif",
923
+ "image/webp"
924
+ ],
925
+ supportsJsonMode: false,
926
+ // Anthropic doesn't have JSON mode
927
+ supportsSystemMessages: true
928
+ };
929
+ }
930
+ };
931
+ }
932
+ var createAnthropicProvider = createAnthropic;
933
+
934
+ exports.anthropic = anthropic;
935
+ exports.createAnthropic = createAnthropic;
936
+ exports.createAnthropicModel = anthropic;
937
+ exports.createAnthropicProvider = createAnthropicProvider;
938
+ //# sourceMappingURL=index.js.map
939
+ //# sourceMappingURL=index.js.map