@omnicross/core 0.1.0 → 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.
Files changed (139) hide show
  1. package/dist/ApiConverter.cjs +799 -0
  2. package/dist/ApiConverter.d.cts +82 -0
  3. package/dist/ApiConverter.d.ts +82 -0
  4. package/dist/ApiConverter.js +763 -0
  5. package/dist/BuiltinToolExecutor-BluWyeob.d.ts +81 -0
  6. package/dist/BuiltinToolExecutor-CS2WpXhM.d.cts +81 -0
  7. package/dist/CompletionService-7fCmKAP3.d.ts +212 -0
  8. package/dist/CompletionService-DtOF_War.d.cts +212 -0
  9. package/dist/{ProviderProxy-f_8ziIhW.d.cts → ProviderProxy-C-xqrkKi.d.ts} +7 -2
  10. package/dist/{ProviderProxy-vjt8sQQk.d.ts → ProviderProxy-CnMQYN59.d.cts} +7 -2
  11. package/dist/completion/BuiltinToolExecutor.cjs +327 -0
  12. package/dist/completion/BuiltinToolExecutor.d.cts +4 -0
  13. package/dist/completion/BuiltinToolExecutor.d.ts +4 -0
  14. package/dist/completion/BuiltinToolExecutor.js +296 -0
  15. package/dist/completion/CompletionService.cjs +3487 -0
  16. package/dist/completion/CompletionService.d.cts +21 -0
  17. package/dist/completion/CompletionService.d.ts +21 -0
  18. package/dist/completion/CompletionService.js +3461 -0
  19. package/dist/completion/NativeSearchInjector.cjs +196 -0
  20. package/dist/completion/NativeSearchInjector.d.cts +42 -0
  21. package/dist/completion/NativeSearchInjector.d.ts +42 -0
  22. package/dist/completion/NativeSearchInjector.js +167 -0
  23. package/dist/completion/ProviderSearchInjector.cjs +87 -0
  24. package/dist/completion/ProviderSearchInjector.d.cts +47 -0
  25. package/dist/completion/ProviderSearchInjector.d.ts +47 -0
  26. package/dist/completion/ProviderSearchInjector.js +60 -0
  27. package/dist/completion/native-search-types.cjs +67 -0
  28. package/dist/completion/native-search-types.d.cts +3 -0
  29. package/dist/completion/native-search-types.d.ts +3 -0
  30. package/dist/completion/native-search-types.js +38 -0
  31. package/dist/completion/openrouter-headers.cjs +72 -0
  32. package/dist/completion/openrouter-headers.d.cts +44 -0
  33. package/dist/completion/openrouter-headers.d.ts +44 -0
  34. package/dist/completion/openrouter-headers.js +42 -0
  35. package/dist/completion/openrouter-models.cjs +86 -0
  36. package/dist/completion/openrouter-models.d.cts +27 -0
  37. package/dist/completion/openrouter-models.d.ts +27 -0
  38. package/dist/completion/openrouter-models.js +59 -0
  39. package/dist/completion/types.cjs +18 -0
  40. package/dist/completion/types.d.cts +3 -0
  41. package/dist/completion/types.d.ts +3 -0
  42. package/dist/completion/types.js +0 -0
  43. package/dist/completion/url-builder.cjs +138 -0
  44. package/dist/completion/url-builder.d.cts +87 -0
  45. package/dist/completion/url-builder.d.ts +87 -0
  46. package/dist/completion/url-builder.js +104 -0
  47. package/dist/completion.d.cts +148 -7
  48. package/dist/completion.d.ts +148 -7
  49. package/dist/index.cjs +1 -0
  50. package/dist/index.d.cts +27 -90
  51. package/dist/index.d.ts +27 -90
  52. package/dist/index.js +1 -0
  53. package/dist/outbound-api/routeResolver.cjs +221 -0
  54. package/dist/outbound-api/routeResolver.d.cts +18 -0
  55. package/dist/outbound-api/routeResolver.d.ts +18 -0
  56. package/dist/outbound-api/routeResolver.js +192 -0
  57. package/dist/outbound-api/subscriptionRegistryPort.d.cts +5 -2
  58. package/dist/outbound-api/subscriptionRegistryPort.d.ts +5 -2
  59. package/dist/outbound-api/types.cjs +18 -0
  60. package/dist/{types-CbCN2NQP.d.ts → outbound-api/types.d.cts} +17 -3
  61. package/dist/{types-CGGrKqC_.d.cts → outbound-api/types.d.ts} +17 -3
  62. package/dist/outbound-api/types.js +0 -0
  63. package/dist/outbound-api.cjs +1 -0
  64. package/dist/outbound-api.d.cts +14 -87
  65. package/dist/outbound-api.d.ts +14 -87
  66. package/dist/outbound-api.js +1 -0
  67. package/dist/pipeline/AuthSource.cjs +18 -0
  68. package/dist/pipeline/AuthSource.d.cts +101 -0
  69. package/dist/pipeline/AuthSource.d.ts +101 -0
  70. package/dist/pipeline/AuthSource.js +0 -0
  71. package/dist/pipeline/LlmConfigProviderAuth.cjs +169 -0
  72. package/dist/pipeline/LlmConfigProviderAuth.d.cts +86 -0
  73. package/dist/pipeline/LlmConfigProviderAuth.d.ts +86 -0
  74. package/dist/pipeline/LlmConfigProviderAuth.js +142 -0
  75. package/dist/pipeline/SubscriptionAuthSource.d.cts +165 -3
  76. package/dist/pipeline/SubscriptionAuthSource.d.ts +165 -3
  77. package/dist/pipeline/executeProviderCall.cjs +70 -0
  78. package/dist/pipeline/executeProviderCall.d.cts +149 -0
  79. package/dist/pipeline/executeProviderCall.d.ts +149 -0
  80. package/dist/pipeline/executeProviderCall.js +45 -0
  81. package/dist/pipeline/resolveProviderChain.cjs +47 -0
  82. package/dist/pipeline/resolveProviderChain.d.cts +58 -0
  83. package/dist/pipeline/resolveProviderChain.d.ts +58 -0
  84. package/dist/pipeline/resolveProviderChain.js +22 -0
  85. package/dist/pipeline/resolveSubscriptionChain.cjs +68 -0
  86. package/dist/pipeline/resolveSubscriptionChain.d.cts +68 -0
  87. package/dist/pipeline/resolveSubscriptionChain.d.ts +68 -0
  88. package/dist/pipeline/resolveSubscriptionChain.js +43 -0
  89. package/dist/ports/provider-config-source.cjs +18 -0
  90. package/dist/ports/provider-config-source.d.cts +51 -0
  91. package/dist/ports/provider-config-source.d.ts +51 -0
  92. package/dist/ports/provider-config-source.js +0 -0
  93. package/dist/ports/web-search-backend.cjs +18 -0
  94. package/dist/ports/web-search-backend.d.cts +29 -0
  95. package/dist/ports/web-search-backend.d.ts +29 -0
  96. package/dist/ports/web-search-backend.js +0 -0
  97. package/dist/ports.d.cts +10 -7
  98. package/dist/ports.d.ts +10 -7
  99. package/dist/provider-proxy/ProviderProxy.cjs +4643 -0
  100. package/dist/provider-proxy/ProviderProxy.d.cts +16 -0
  101. package/dist/provider-proxy/ProviderProxy.d.ts +16 -0
  102. package/dist/provider-proxy/ProviderProxy.js +4618 -0
  103. package/dist/provider-proxy/ingress/providerProxyShared.d.cts +5 -2
  104. package/dist/provider-proxy/ingress/providerProxyShared.d.ts +5 -2
  105. package/dist/provider-proxy/types.d.cts +406 -8
  106. package/dist/provider-proxy/types.d.ts +406 -8
  107. package/dist/provider-proxy.cjs +1 -0
  108. package/dist/provider-proxy.d.cts +8 -5
  109. package/dist/provider-proxy.d.ts +8 -5
  110. package/dist/provider-proxy.js +1 -0
  111. package/dist/routeResolver-BrbK6ja9.d.cts +88 -0
  112. package/dist/routeResolver-HE-ZO0fO.d.ts +88 -0
  113. package/dist/transformer/anthropicBetaInject.cjs +51 -0
  114. package/dist/transformer/anthropicBetaInject.d.cts +20 -0
  115. package/dist/transformer/anthropicBetaInject.d.ts +20 -0
  116. package/dist/transformer/anthropicBetaInject.js +25 -0
  117. package/dist/transformer/transformers/AnthropicTransformer.cjs +1017 -0
  118. package/dist/transformer/transformers/AnthropicTransformer.d.cts +148 -0
  119. package/dist/transformer/transformers/AnthropicTransformer.d.ts +148 -0
  120. package/dist/transformer/transformers/AnthropicTransformer.js +990 -0
  121. package/dist/transformer/transformers/ReasoningTransformer.cjs +273 -0
  122. package/dist/transformer/transformers/ReasoningTransformer.d.cts +47 -0
  123. package/dist/transformer/transformers/ReasoningTransformer.d.ts +47 -0
  124. package/dist/transformer/transformers/ReasoningTransformer.js +253 -0
  125. package/dist/transformer/transformers.cjs +3206 -0
  126. package/dist/transformer/transformers.d.cts +100 -0
  127. package/dist/transformer/transformers.d.ts +100 -0
  128. package/dist/transformer/transformers.js +3174 -0
  129. package/dist/transformer.d.cts +8 -31
  130. package/dist/transformer.d.ts +8 -31
  131. package/dist/types-BScIHmPr.d.cts +153 -0
  132. package/dist/types-BScIHmPr.d.ts +153 -0
  133. package/package.json +3 -3
  134. package/dist/SubscriptionAuthSource-Cr4fVEYY.d.cts +0 -264
  135. package/dist/SubscriptionAuthSource-D89zmiSS.d.ts +0 -264
  136. package/dist/index-BTSmc9Sm.d.ts +0 -645
  137. package/dist/index-DXazdTzZ.d.cts +0 -645
  138. package/dist/types-DCzHkhJt.d.ts +0 -467
  139. package/dist/types-DZIQbgp0.d.cts +0 -467
@@ -0,0 +1,990 @@
1
+ // src/transformer/transformers/AnthropicToolHandling.ts
2
+ function isServerSideTool(tool) {
3
+ const type = String(tool.type || "");
4
+ return type.startsWith("web_search_") || type.startsWith("code_execution_") || type.startsWith("text_editor_") || type.startsWith("memory_") || type.startsWith("web_fetch_") || type.startsWith("search_tool_");
5
+ }
6
+ function convertAnthropicToolsToOpenAI(tools) {
7
+ return tools.filter((tool) => !isServerSideTool(tool)).map((tool) => ({
8
+ type: "function",
9
+ function: {
10
+ name: String(tool.name),
11
+ description: String(tool.description || ""),
12
+ parameters: tool.input_schema
13
+ }
14
+ }));
15
+ }
16
+
17
+ // src/transformer/transformers/AnthropicTypes.ts
18
+ function getThinkLevel(budgetTokens) {
19
+ if (!budgetTokens || budgetTokens <= 0) return "none";
20
+ if (budgetTokens < 4096) return "low";
21
+ if (budgetTokens < 16384) return "medium";
22
+ return "high";
23
+ }
24
+ function formatBase64(data, mediaType) {
25
+ if (data.startsWith("data:")) return data;
26
+ return `data:${mediaType || "image/png"};base64,${data}`;
27
+ }
28
+
29
+ // src/transformer/transformers/AnthropicRequestBuilder.ts
30
+ function buildAnthropicRequestBody(request) {
31
+ let systemContent;
32
+ const anthropicMessages = [];
33
+ for (let i = 0; i < request.messages.length; i++) {
34
+ const msg = request.messages[i];
35
+ if (msg.role === "system") {
36
+ if (typeof msg.content === "string") {
37
+ systemContent = msg.content;
38
+ } else if (Array.isArray(msg.content)) {
39
+ systemContent = msg.content.filter((c) => c.type === "text").map((c) => ({
40
+ type: "text",
41
+ text: c.text,
42
+ ...c.cache_control ? { cache_control: c.cache_control } : {}
43
+ }));
44
+ }
45
+ continue;
46
+ }
47
+ if (msg.role === "assistant") {
48
+ const content = [];
49
+ if (msg.thinking?.content) {
50
+ const block = {
51
+ type: "thinking",
52
+ thinking: msg.thinking.content
53
+ };
54
+ if (msg.thinking.signature) {
55
+ block.signature = msg.thinking.signature;
56
+ }
57
+ content.push(block);
58
+ }
59
+ if (msg.content) {
60
+ const text = typeof msg.content === "string" ? msg.content : msg.content.filter((c) => c.type === "text").map((c) => c.text).join("\n");
61
+ if (text) {
62
+ content.push({ type: "text", text });
63
+ }
64
+ }
65
+ if (msg.tool_calls?.length) {
66
+ for (const tc of msg.tool_calls) {
67
+ let input;
68
+ try {
69
+ input = typeof tc.function.arguments === "string" ? JSON.parse(tc.function.arguments) : tc.function.arguments;
70
+ } catch {
71
+ input = { text: tc.function.arguments || "" };
72
+ }
73
+ content.push({
74
+ type: "tool_use",
75
+ id: tc.id,
76
+ name: tc.function.name,
77
+ input
78
+ });
79
+ }
80
+ }
81
+ anthropicMessages.push({
82
+ role: "assistant",
83
+ content: content.length > 0 ? content : ""
84
+ });
85
+ continue;
86
+ }
87
+ if (msg.role === "tool") {
88
+ const toolResults = [];
89
+ let j = i;
90
+ while (j < request.messages.length && request.messages[j].role === "tool") {
91
+ const t = request.messages[j];
92
+ toolResults.push({
93
+ type: "tool_result",
94
+ tool_use_id: t.tool_call_id || "",
95
+ content: typeof t.content === "string" ? t.content : JSON.stringify(t.content),
96
+ ...t.cache_control ? { cache_control: t.cache_control } : {}
97
+ });
98
+ j++;
99
+ }
100
+ anthropicMessages.push({ role: "user", content: toolResults });
101
+ i = j - 1;
102
+ continue;
103
+ }
104
+ if (typeof msg.content === "string") {
105
+ anthropicMessages.push({ role: "user", content: msg.content });
106
+ } else if (Array.isArray(msg.content)) {
107
+ const content = msg.content.map((part) => {
108
+ if (part.type === "image_url") {
109
+ const url = part.image_url.url;
110
+ if (url.startsWith("data:")) {
111
+ const match = url.match(/^data:([^;]+);base64,(.+)$/);
112
+ if (match) {
113
+ return {
114
+ type: "image",
115
+ source: { type: "base64", media_type: match[1], data: match[2] }
116
+ };
117
+ }
118
+ }
119
+ return {
120
+ type: "image",
121
+ source: { type: "url", url }
122
+ };
123
+ }
124
+ return { type: "text", text: part.text };
125
+ });
126
+ anthropicMessages.push({ role: "user", content });
127
+ }
128
+ }
129
+ const body = {
130
+ model: request.model,
131
+ messages: anthropicMessages,
132
+ max_tokens: request.max_tokens || 4096,
133
+ stream: request.stream ?? false
134
+ };
135
+ if (request.temperature !== void 0) {
136
+ body.temperature = request.temperature;
137
+ }
138
+ if (systemContent !== void 0) {
139
+ body.system = systemContent;
140
+ }
141
+ if (request.tools?.length) {
142
+ body.tools = request.tools.map((tool) => ({
143
+ name: tool.function.name,
144
+ description: tool.function.description || "",
145
+ input_schema: tool.function.parameters
146
+ }));
147
+ }
148
+ const serverSideTools = request._serverSideTools;
149
+ if (serverSideTools?.length) {
150
+ body.tools = [...body.tools || [], ...serverSideTools];
151
+ }
152
+ if (request.tool_choice) {
153
+ if (typeof request.tool_choice === "string") {
154
+ if (request.tool_choice === "required") {
155
+ body.tool_choice = { type: "any" };
156
+ } else if (request.tool_choice !== "none") {
157
+ body.tool_choice = { type: request.tool_choice };
158
+ }
159
+ } else if (typeof request.tool_choice === "object" && "function" in request.tool_choice) {
160
+ body.tool_choice = { type: "tool", name: request.tool_choice.function.name };
161
+ }
162
+ }
163
+ if (request.reasoning?.enabled) {
164
+ const budgetMap = { low: 2048, medium: 8192, high: 32768 };
165
+ const budget = request.reasoning.max_tokens || budgetMap[request.reasoning.effort || "medium"] || 8192;
166
+ body.thinking = { type: "enabled", budget_tokens: budget };
167
+ body.temperature = 1;
168
+ }
169
+ return body;
170
+ }
171
+
172
+ // src/transformer/transformers/AnthropicResponseConversion.ts
173
+ function convertAnthropicResponseToOpenAI(anthropicResponse) {
174
+ const content = anthropicResponse.content || [];
175
+ const textParts = content.filter((c) => c.type === "text").map((c) => c.text);
176
+ const toolUses = content.filter((c) => c.type === "tool_use" || c.type === "server_tool_use");
177
+ const thinkingBlock = content.find((c) => c.type === "thinking");
178
+ const searchResults = content.filter((c) => c.type === "web_search_tool_result");
179
+ for (const sr of searchResults) {
180
+ const searches = sr.content;
181
+ if (searches?.length) {
182
+ const formatted = searches.map((s) => `[${s.title}](${s.url}): ${s.page_content || s.snippet || ""}`).join("\n");
183
+ textParts.push(`
184
+
185
+ **Search Results:**
186
+ ${formatted}`);
187
+ }
188
+ }
189
+ const message = {
190
+ role: "assistant",
191
+ content: textParts.join("") || null
192
+ };
193
+ if (toolUses.length > 0) {
194
+ message.tool_calls = toolUses.map((tc) => ({
195
+ id: tc.id,
196
+ type: "function",
197
+ function: {
198
+ name: tc.name,
199
+ arguments: JSON.stringify(tc.input || {})
200
+ }
201
+ }));
202
+ }
203
+ if (thinkingBlock) {
204
+ message.thinking = {
205
+ content: thinkingBlock.thinking,
206
+ signature: thinkingBlock.signature
207
+ };
208
+ }
209
+ const stopReasonMapping = {
210
+ end_turn: "stop",
211
+ max_tokens: "length",
212
+ tool_use: "tool_calls",
213
+ stop_sequence: "stop"
214
+ };
215
+ const usage = anthropicResponse.usage;
216
+ return {
217
+ id: anthropicResponse.id || `chatcmpl-${Date.now()}`,
218
+ object: "chat.completion",
219
+ created: Math.floor(Date.now() / 1e3),
220
+ model: anthropicResponse.model || "unknown",
221
+ choices: [{
222
+ index: 0,
223
+ message,
224
+ finish_reason: stopReasonMapping[anthropicResponse.stop_reason] || "stop"
225
+ }],
226
+ usage: usage ? {
227
+ prompt_tokens: usage.input_tokens || 0,
228
+ completion_tokens: usage.output_tokens || 0,
229
+ total_tokens: (usage.input_tokens || 0) + (usage.output_tokens || 0)
230
+ } : void 0
231
+ };
232
+ }
233
+ function convertOpenAIResponseToAnthropic(openaiResponse) {
234
+ const choice = openaiResponse.choices?.[0];
235
+ if (!choice) {
236
+ throw new Error("No choices found in OpenAI response");
237
+ }
238
+ const message = choice.message;
239
+ const content = [];
240
+ if (message.content) {
241
+ content.push({
242
+ type: "text",
243
+ text: message.content
244
+ });
245
+ }
246
+ const toolCalls = message.tool_calls;
247
+ if (toolCalls?.length) {
248
+ for (const toolCall of toolCalls) {
249
+ const func = toolCall.function;
250
+ let parsedInput = {};
251
+ try {
252
+ const args = func.arguments;
253
+ parsedInput = typeof args === "string" ? JSON.parse(args) : args;
254
+ } catch {
255
+ parsedInput = { text: func.arguments || "" };
256
+ }
257
+ content.push({
258
+ type: "tool_use",
259
+ id: toolCall.id,
260
+ name: func.name,
261
+ input: parsedInput
262
+ });
263
+ }
264
+ }
265
+ const thinking = message.thinking;
266
+ if (thinking?.content) {
267
+ content.push({
268
+ type: "thinking",
269
+ thinking: thinking.content,
270
+ signature: thinking.signature
271
+ });
272
+ }
273
+ const finishReason = choice.finish_reason;
274
+ const stopReasonMapping = {
275
+ stop: "end_turn",
276
+ length: "max_tokens",
277
+ tool_calls: "tool_use",
278
+ content_filter: "stop_sequence"
279
+ };
280
+ const usage = openaiResponse.usage;
281
+ const usageDetails = usage?.prompt_tokens_details;
282
+ return {
283
+ id: openaiResponse.id,
284
+ type: "message",
285
+ role: "assistant",
286
+ model: openaiResponse.model,
287
+ content,
288
+ stop_reason: stopReasonMapping[finishReason] || "end_turn",
289
+ stop_sequence: null,
290
+ usage: {
291
+ input_tokens: (usage?.prompt_tokens || 0) - (usageDetails?.cached_tokens || 0),
292
+ output_tokens: usage?.completion_tokens || 0,
293
+ cache_read_input_tokens: usageDetails?.cached_tokens || 0
294
+ }
295
+ };
296
+ }
297
+
298
+ // src/transformer/transformers/AnthropicConversion.ts
299
+ function transformAnthropicRequestToUnified(request) {
300
+ const anthropicRequest = request;
301
+ const messages = [];
302
+ if (anthropicRequest.system) {
303
+ if (typeof anthropicRequest.system === "string") {
304
+ messages.push({
305
+ role: "system",
306
+ content: anthropicRequest.system
307
+ });
308
+ } else if (Array.isArray(anthropicRequest.system)) {
309
+ const textParts = anthropicRequest.system.filter((item) => item.type === "text" && item.text).map((item) => ({
310
+ type: "text",
311
+ text: item.text,
312
+ cache_control: item.cache_control
313
+ }));
314
+ if (textParts.length > 0) {
315
+ messages.push({
316
+ role: "system",
317
+ content: textParts
318
+ });
319
+ }
320
+ }
321
+ }
322
+ const requestMessages = JSON.parse(JSON.stringify(anthropicRequest.messages || []));
323
+ for (const msg of requestMessages) {
324
+ if (msg.role !== "user" && msg.role !== "assistant") continue;
325
+ if (typeof msg.content === "string") {
326
+ messages.push({
327
+ role: msg.role,
328
+ content: msg.content
329
+ });
330
+ continue;
331
+ }
332
+ if (Array.isArray(msg.content)) {
333
+ if (msg.role === "user") {
334
+ const toolParts = msg.content.filter(
335
+ (c) => c.type === "tool_result" && c.tool_use_id
336
+ );
337
+ for (const tool of toolParts) {
338
+ messages.push({
339
+ role: "tool",
340
+ content: typeof tool.content === "string" ? tool.content : JSON.stringify(tool.content),
341
+ tool_call_id: tool.tool_use_id,
342
+ cache_control: tool.cache_control
343
+ });
344
+ }
345
+ const textAndMediaParts = msg.content.filter(
346
+ (c) => c.type === "text" && c.text || c.type === "image" && c.source
347
+ );
348
+ if (textAndMediaParts.length > 0) {
349
+ messages.push({
350
+ role: "user",
351
+ content: textAndMediaParts.map((part) => {
352
+ if (part.type === "image") {
353
+ const imagePart = part;
354
+ return {
355
+ type: "image_url",
356
+ image_url: {
357
+ url: imagePart.source.type === "base64" ? formatBase64(imagePart.source.data || "", imagePart.source.media_type) : imagePart.source.url || ""
358
+ },
359
+ media_type: imagePart.source.media_type
360
+ };
361
+ }
362
+ return {
363
+ type: "text",
364
+ text: part.text
365
+ };
366
+ })
367
+ });
368
+ }
369
+ } else if (msg.role === "assistant") {
370
+ const assistantMessage = {
371
+ role: "assistant",
372
+ content: ""
373
+ };
374
+ const textParts = msg.content.filter(
375
+ (c) => c.type === "text" && c.text
376
+ );
377
+ if (textParts.length > 0) {
378
+ assistantMessage.content = textParts.map((t) => t.text).join("\n");
379
+ }
380
+ const toolCallParts = msg.content.filter(
381
+ (c) => c.type === "tool_use" && c.id
382
+ );
383
+ if (toolCallParts.length > 0) {
384
+ assistantMessage.tool_calls = toolCallParts.map((tool) => ({
385
+ id: tool.id,
386
+ type: "function",
387
+ function: {
388
+ name: tool.name,
389
+ arguments: JSON.stringify(tool.input || {})
390
+ }
391
+ }));
392
+ }
393
+ const thinkingPart = msg.content.find(
394
+ (c) => c.type === "thinking"
395
+ );
396
+ if (thinkingPart?.thinking) {
397
+ assistantMessage.thinking = {
398
+ content: thinkingPart.thinking,
399
+ signature: thinkingPart.signature
400
+ };
401
+ }
402
+ messages.push(assistantMessage);
403
+ }
404
+ }
405
+ }
406
+ const rawTools = anthropicRequest.tools || [];
407
+ const serverSideTools = rawTools.filter((t) => isServerSideTool(t));
408
+ const functionTools = rawTools.length > 0 ? convertAnthropicToolsToOpenAI(rawTools) : void 0;
409
+ const result = {
410
+ messages,
411
+ model: anthropicRequest.model,
412
+ max_tokens: anthropicRequest.max_tokens,
413
+ temperature: anthropicRequest.temperature,
414
+ stream: anthropicRequest.stream,
415
+ tools: functionTools?.length ? functionTools : void 0
416
+ };
417
+ if (serverSideTools.length > 0) {
418
+ result._serverSideTools = serverSideTools;
419
+ }
420
+ if (anthropicRequest.thinking) {
421
+ result.reasoning = {
422
+ effort: getThinkLevel(anthropicRequest.thinking.budget_tokens),
423
+ enabled: anthropicRequest.thinking.type === "enabled"
424
+ };
425
+ }
426
+ if (anthropicRequest.tool_choice) {
427
+ if (anthropicRequest.tool_choice.type === "tool" && anthropicRequest.tool_choice.name) {
428
+ result.tool_choice = {
429
+ type: "function",
430
+ function: { name: anthropicRequest.tool_choice.name }
431
+ };
432
+ } else {
433
+ result.tool_choice = anthropicRequest.tool_choice.type;
434
+ }
435
+ }
436
+ return result;
437
+ }
438
+
439
+ // src/transformer/transformers/AnthropicAnthropicToOpenAIStream.ts
440
+ function convertAnthropicStreamToOpenAI(anthropicStream, logger) {
441
+ const decoder = new TextDecoder();
442
+ const encoder = new TextEncoder();
443
+ const activeToolCalls = /* @__PURE__ */ new Map();
444
+ let toolCallCounter = 0;
445
+ let model = "unknown";
446
+ let messageId = `chatcmpl-${Date.now()}`;
447
+ return new ReadableStream({
448
+ start: async (controller) => {
449
+ const reader = anthropicStream.getReader();
450
+ let buffer = "";
451
+ let isClosed = false;
452
+ const safeEnqueue = (data) => {
453
+ if (!isClosed) {
454
+ try {
455
+ controller.enqueue(encoder.encode(data));
456
+ } catch {
457
+ isClosed = true;
458
+ }
459
+ }
460
+ };
461
+ try {
462
+ while (true) {
463
+ const { done, value } = await reader.read();
464
+ if (done) break;
465
+ buffer += decoder.decode(value, { stream: true });
466
+ const lines = buffer.split("\n");
467
+ buffer = lines.pop() || "";
468
+ for (const line of lines) {
469
+ if (isClosed) break;
470
+ if (!line.startsWith("data:")) continue;
471
+ const data = line.slice(5).trim();
472
+ if (!data || data === "[DONE]") continue;
473
+ try {
474
+ const event = JSON.parse(data);
475
+ if (event.type === "message_start" && event.message) {
476
+ model = event.message.model || model;
477
+ messageId = event.message.id || messageId;
478
+ }
479
+ if (event.type === "content_block_delta" && event.delta) {
480
+ const chunk = {
481
+ id: messageId,
482
+ object: "chat.completion.chunk",
483
+ created: Math.floor(Date.now() / 1e3),
484
+ model,
485
+ choices: [{ index: 0, delta: {}, finish_reason: null }]
486
+ };
487
+ const delta = chunk.choices[0].delta;
488
+ if (event.delta.type === "text_delta") {
489
+ delta.content = event.delta.text;
490
+ } else if (event.delta.type === "input_json_delta") {
491
+ const toolInfo = activeToolCalls.get(event.index);
492
+ if (toolInfo) {
493
+ delta.tool_calls = [{
494
+ index: toolInfo.index,
495
+ function: { arguments: event.delta.partial_json }
496
+ }];
497
+ }
498
+ } else if (event.delta.type === "thinking_delta") {
499
+ delta.thinking = { content: event.delta.thinking };
500
+ } else if (event.delta.type === "signature_delta") {
501
+ delta.thinking = { signature: event.delta.signature };
502
+ } else {
503
+ continue;
504
+ }
505
+ safeEnqueue(`data: ${JSON.stringify(chunk)}
506
+
507
+ `);
508
+ }
509
+ if (event.type === "content_block_start" && event.content_block) {
510
+ if (event.content_block.type === "tool_use" || event.content_block.type === "server_tool_use") {
511
+ const tcIndex = toolCallCounter++;
512
+ activeToolCalls.set(event.index, {
513
+ id: event.content_block.id,
514
+ name: event.content_block.name,
515
+ index: tcIndex
516
+ });
517
+ const chunk = {
518
+ id: messageId,
519
+ object: "chat.completion.chunk",
520
+ created: Math.floor(Date.now() / 1e3),
521
+ model,
522
+ choices: [{
523
+ index: 0,
524
+ delta: {
525
+ tool_calls: [{
526
+ index: tcIndex,
527
+ id: event.content_block.id,
528
+ type: "function",
529
+ function: { name: event.content_block.name, arguments: "" }
530
+ }]
531
+ },
532
+ finish_reason: null
533
+ }]
534
+ };
535
+ safeEnqueue(`data: ${JSON.stringify(chunk)}
536
+
537
+ `);
538
+ } else if (event.content_block.type === "web_search_tool_result") {
539
+ const searches = event.content_block.content;
540
+ if (searches?.length) {
541
+ const formatted = searches.map((s) => `[${s.title}](${s.url}): ${s.page_content || s.snippet || ""}`).join("\n");
542
+ const chunk = {
543
+ id: messageId,
544
+ object: "chat.completion.chunk",
545
+ created: Math.floor(Date.now() / 1e3),
546
+ model,
547
+ choices: [{
548
+ index: 0,
549
+ delta: { content: `
550
+
551
+ **Search Results:**
552
+ ${formatted}` },
553
+ finish_reason: null
554
+ }]
555
+ };
556
+ safeEnqueue(`data: ${JSON.stringify(chunk)}
557
+
558
+ `);
559
+ }
560
+ }
561
+ }
562
+ if (event.type === "message_delta" && event.delta) {
563
+ const stopReasonMapping = {
564
+ end_turn: "stop",
565
+ max_tokens: "length",
566
+ tool_use: "tool_calls",
567
+ stop_sequence: "stop"
568
+ };
569
+ const chunk = {
570
+ id: messageId,
571
+ object: "chat.completion.chunk",
572
+ created: Math.floor(Date.now() / 1e3),
573
+ model,
574
+ choices: [{
575
+ index: 0,
576
+ delta: {},
577
+ finish_reason: stopReasonMapping[event.delta.stop_reason] || "stop"
578
+ }]
579
+ };
580
+ if (event.usage) {
581
+ chunk.usage = {
582
+ prompt_tokens: event.usage.input_tokens || 0,
583
+ completion_tokens: event.usage.output_tokens || 0,
584
+ total_tokens: (event.usage.input_tokens || 0) + (event.usage.output_tokens || 0)
585
+ };
586
+ }
587
+ safeEnqueue(`data: ${JSON.stringify(chunk)}
588
+
589
+ `);
590
+ }
591
+ } catch (e) {
592
+ logger?.error("Error parsing Anthropic stream event:", e);
593
+ }
594
+ }
595
+ }
596
+ } catch (e) {
597
+ if (!isClosed) {
598
+ controller.error(e);
599
+ }
600
+ } finally {
601
+ safeEnqueue("data: [DONE]\n\n");
602
+ if (!isClosed) {
603
+ try {
604
+ controller.close();
605
+ } catch {
606
+ }
607
+ }
608
+ reader.releaseLock();
609
+ }
610
+ }
611
+ });
612
+ }
613
+
614
+ // src/transformer/transformers/AnthropicOpenAIToAnthropicStream.ts
615
+ function convertOpenAIStreamToAnthropic(openaiStream, _context, logger) {
616
+ const decoder = new TextDecoder();
617
+ const encoder = new TextEncoder();
618
+ let hasStarted = false;
619
+ let hasTextContentStarted = false;
620
+ let isThinkingStarted = false;
621
+ let contentIndex = 0;
622
+ let currentContentBlockIndex = -1;
623
+ const toolCallIndexToContentBlockIndex = /* @__PURE__ */ new Map();
624
+ return new ReadableStream({
625
+ start: async (controller) => {
626
+ const reader = openaiStream.getReader();
627
+ let buffer = "";
628
+ const messageId = `msg_${Date.now()}`;
629
+ let model = "unknown";
630
+ let isClosed = false;
631
+ let stopReasonDelta = null;
632
+ const safeEnqueue = (data) => {
633
+ if (!isClosed) {
634
+ try {
635
+ controller.enqueue(encoder.encode(data));
636
+ } catch (_e) {
637
+ isClosed = true;
638
+ }
639
+ }
640
+ };
641
+ const assignContentBlockIndex = () => {
642
+ return contentIndex++;
643
+ };
644
+ const safeClose = () => {
645
+ if (isClosed) return;
646
+ if (currentContentBlockIndex >= 0) {
647
+ safeEnqueue(`event: content_block_stop
648
+ data: ${JSON.stringify({
649
+ type: "content_block_stop",
650
+ index: currentContentBlockIndex
651
+ })}
652
+
653
+ `);
654
+ }
655
+ if (stopReasonDelta) {
656
+ safeEnqueue(`event: message_delta
657
+ data: ${JSON.stringify(stopReasonDelta)}
658
+
659
+ `);
660
+ } else {
661
+ safeEnqueue(`event: message_delta
662
+ data: ${JSON.stringify({
663
+ type: "message_delta",
664
+ delta: { stop_reason: "end_turn", stop_sequence: null },
665
+ usage: { input_tokens: 0, output_tokens: 0 }
666
+ })}
667
+
668
+ `);
669
+ }
670
+ safeEnqueue(`event: message_stop
671
+ data: ${JSON.stringify({ type: "message_stop" })}
672
+
673
+ `);
674
+ try {
675
+ controller.close();
676
+ } catch (_e) {
677
+ }
678
+ isClosed = true;
679
+ };
680
+ try {
681
+ while (true) {
682
+ const { done, value } = await reader.read();
683
+ if (done) break;
684
+ buffer += decoder.decode(value, { stream: true });
685
+ const lines = buffer.split("\n");
686
+ buffer = lines.pop() || "";
687
+ for (const line of lines) {
688
+ if (isClosed) break;
689
+ if (!line.startsWith("data:")) continue;
690
+ const data = line.slice(5).trim();
691
+ if (data === "[DONE]") continue;
692
+ try {
693
+ const chunk = JSON.parse(data);
694
+ if (chunk.error) {
695
+ safeEnqueue(`event: error
696
+ data: ${JSON.stringify({
697
+ type: "error",
698
+ message: { type: "api_error", message: JSON.stringify(chunk.error) }
699
+ })}
700
+
701
+ `);
702
+ continue;
703
+ }
704
+ model = chunk.model || model;
705
+ if (!hasStarted) {
706
+ hasStarted = true;
707
+ safeEnqueue(`event: message_start
708
+ data: ${JSON.stringify({
709
+ type: "message_start",
710
+ message: {
711
+ id: messageId,
712
+ type: "message",
713
+ role: "assistant",
714
+ content: [],
715
+ model,
716
+ stop_reason: null,
717
+ stop_sequence: null,
718
+ usage: { input_tokens: 0, output_tokens: 0 }
719
+ }
720
+ })}
721
+
722
+ `);
723
+ }
724
+ const choice = chunk.choices?.[0];
725
+ if (!choice) continue;
726
+ if (chunk.usage) {
727
+ stopReasonDelta = {
728
+ type: "message_delta",
729
+ delta: { stop_reason: "end_turn", stop_sequence: null },
730
+ usage: {
731
+ input_tokens: (chunk.usage.prompt_tokens || 0) - (chunk.usage.prompt_tokens_details?.cached_tokens || 0),
732
+ output_tokens: chunk.usage.completion_tokens || 0,
733
+ cache_read_input_tokens: chunk.usage.prompt_tokens_details?.cached_tokens || 0
734
+ }
735
+ };
736
+ }
737
+ if (choice.delta?.thinking) {
738
+ if (!isThinkingStarted) {
739
+ const thinkingBlockIndex = assignContentBlockIndex();
740
+ safeEnqueue(`event: content_block_start
741
+ data: ${JSON.stringify({
742
+ type: "content_block_start",
743
+ index: thinkingBlockIndex,
744
+ content_block: { type: "thinking", thinking: "" }
745
+ })}
746
+
747
+ `);
748
+ currentContentBlockIndex = thinkingBlockIndex;
749
+ isThinkingStarted = true;
750
+ }
751
+ if (choice.delta.thinking.signature) {
752
+ safeEnqueue(`event: content_block_delta
753
+ data: ${JSON.stringify({
754
+ type: "content_block_delta",
755
+ index: currentContentBlockIndex,
756
+ delta: { type: "signature_delta", signature: choice.delta.thinking.signature }
757
+ })}
758
+
759
+ `);
760
+ safeEnqueue(`event: content_block_stop
761
+ data: ${JSON.stringify({
762
+ type: "content_block_stop",
763
+ index: currentContentBlockIndex
764
+ })}
765
+
766
+ `);
767
+ currentContentBlockIndex = -1;
768
+ } else if (choice.delta.thinking.content) {
769
+ safeEnqueue(`event: content_block_delta
770
+ data: ${JSON.stringify({
771
+ type: "content_block_delta",
772
+ index: currentContentBlockIndex,
773
+ delta: { type: "thinking_delta", thinking: choice.delta.thinking.content }
774
+ })}
775
+
776
+ `);
777
+ }
778
+ }
779
+ if (choice.delta?.content) {
780
+ if (!hasTextContentStarted) {
781
+ if (currentContentBlockIndex >= 0 && isThinkingStarted) {
782
+ safeEnqueue(`event: content_block_stop
783
+ data: ${JSON.stringify({
784
+ type: "content_block_stop",
785
+ index: currentContentBlockIndex
786
+ })}
787
+
788
+ `);
789
+ }
790
+ hasTextContentStarted = true;
791
+ const textBlockIndex = assignContentBlockIndex();
792
+ safeEnqueue(`event: content_block_start
793
+ data: ${JSON.stringify({
794
+ type: "content_block_start",
795
+ index: textBlockIndex,
796
+ content_block: { type: "text", text: "" }
797
+ })}
798
+
799
+ `);
800
+ currentContentBlockIndex = textBlockIndex;
801
+ }
802
+ safeEnqueue(`event: content_block_delta
803
+ data: ${JSON.stringify({
804
+ type: "content_block_delta",
805
+ index: currentContentBlockIndex,
806
+ delta: { type: "text_delta", text: choice.delta.content }
807
+ })}
808
+
809
+ `);
810
+ }
811
+ if (choice.delta?.tool_calls) {
812
+ for (const toolCall of choice.delta.tool_calls) {
813
+ const toolCallIndex = toolCall.index ?? 0;
814
+ if (!toolCallIndexToContentBlockIndex.has(toolCallIndex)) {
815
+ if (currentContentBlockIndex >= 0) {
816
+ safeEnqueue(`event: content_block_stop
817
+ data: ${JSON.stringify({
818
+ type: "content_block_stop",
819
+ index: currentContentBlockIndex
820
+ })}
821
+
822
+ `);
823
+ hasTextContentStarted = false;
824
+ }
825
+ const newBlockIndex = assignContentBlockIndex();
826
+ toolCallIndexToContentBlockIndex.set(toolCallIndex, newBlockIndex);
827
+ safeEnqueue(`event: content_block_start
828
+ data: ${JSON.stringify({
829
+ type: "content_block_start",
830
+ index: newBlockIndex,
831
+ content_block: {
832
+ type: "tool_use",
833
+ id: toolCall.id || `call_${Date.now()}_${toolCallIndex}`,
834
+ name: toolCall.function?.name || `tool_${toolCallIndex}`,
835
+ input: {}
836
+ }
837
+ })}
838
+
839
+ `);
840
+ currentContentBlockIndex = newBlockIndex;
841
+ }
842
+ if (toolCall.function?.arguments) {
843
+ const blockIndex = toolCallIndexToContentBlockIndex.get(toolCallIndex);
844
+ if (blockIndex !== void 0) {
845
+ safeEnqueue(`event: content_block_delta
846
+ data: ${JSON.stringify({
847
+ type: "content_block_delta",
848
+ index: blockIndex,
849
+ delta: { type: "input_json_delta", partial_json: toolCall.function.arguments }
850
+ })}
851
+
852
+ `);
853
+ }
854
+ }
855
+ }
856
+ }
857
+ if (choice.finish_reason) {
858
+ const stopReasonMapping = {
859
+ stop: "end_turn",
860
+ length: "max_tokens",
861
+ tool_calls: "tool_use",
862
+ content_filter: "stop_sequence"
863
+ };
864
+ stopReasonDelta = {
865
+ type: "message_delta",
866
+ delta: {
867
+ stop_reason: stopReasonMapping[choice.finish_reason] || "end_turn",
868
+ stop_sequence: null
869
+ },
870
+ usage: {
871
+ input_tokens: (chunk.usage?.prompt_tokens || 0) - (chunk.usage?.prompt_tokens_details?.cached_tokens || 0),
872
+ output_tokens: chunk.usage?.completion_tokens || 0,
873
+ cache_read_input_tokens: chunk.usage?.prompt_tokens_details?.cached_tokens || 0
874
+ }
875
+ };
876
+ }
877
+ } catch (e) {
878
+ logger?.error("Error parsing stream chunk:", e);
879
+ }
880
+ }
881
+ }
882
+ } catch (e) {
883
+ if (!isClosed) {
884
+ controller.error(e);
885
+ }
886
+ } finally {
887
+ safeClose();
888
+ reader.releaseLock();
889
+ }
890
+ }
891
+ });
892
+ }
893
+
894
+ // src/transformer/transformers/AnthropicTransformer.ts
895
+ var AnthropicTransformer = class {
896
+ static TransformerName = "anthropic";
897
+ name = "anthropic";
898
+ logger;
899
+ endPoint = "/v1/messages";
900
+ useBearer;
901
+ constructor(options) {
902
+ this.useBearer = options?.UseBearer ?? false;
903
+ }
904
+ /**
905
+ * Handle authentication - Anthropic uses x-api-key header
906
+ */
907
+ async auth(request, provider, _context) {
908
+ const headers = {};
909
+ if (this.useBearer) {
910
+ headers["authorization"] = `Bearer ${provider.apiKey}`;
911
+ headers["x-api-key"] = void 0;
912
+ } else {
913
+ headers["x-api-key"] = provider.apiKey;
914
+ headers["authorization"] = void 0;
915
+ }
916
+ return {
917
+ body: request,
918
+ config: { headers }
919
+ };
920
+ }
921
+ /**
922
+ * Transform Anthropic request to unified format.
923
+ */
924
+ async transformRequestOut(request, _context) {
925
+ return transformAnthropicRequestToUnified(request);
926
+ }
927
+ /**
928
+ * Transform OpenAI/unified response back to Anthropic format
929
+ * (auto-detects stream vs JSON via Content-Type).
930
+ */
931
+ async transformResponseIn(response, context) {
932
+ const contentType = response.headers.get("Content-Type") ?? "";
933
+ if (contentType.includes("text/event-stream")) {
934
+ if (!response.body) {
935
+ throw new Error("Stream response body is null");
936
+ }
937
+ const convertedStream = convertOpenAIStreamToAnthropic(response.body, context, this.logger);
938
+ return new Response(convertedStream, {
939
+ headers: {
940
+ "Content-Type": "text/event-stream",
941
+ "Cache-Control": "no-cache",
942
+ Connection: "keep-alive"
943
+ }
944
+ });
945
+ } else {
946
+ const data = await response.json();
947
+ const anthropicResponse = convertOpenAIResponseToAnthropic(data);
948
+ return new Response(JSON.stringify(anthropicResponse), {
949
+ headers: { "Content-Type": "application/json" }
950
+ });
951
+ }
952
+ }
953
+ /**
954
+ * Transform unified request to Anthropic Messages API format.
955
+ * This is the reverse of transformRequestOut — converts OpenAI/unified format
956
+ * to Anthropic's expected request body structure.
957
+ */
958
+ async transformRequestIn(request, _provider, _context) {
959
+ return buildAnthropicRequestBody(request);
960
+ }
961
+ /**
962
+ * Transform Anthropic response to OpenAI/unified format
963
+ * (auto-detects stream vs JSON via Content-Type).
964
+ */
965
+ async transformResponseOut(response, _context) {
966
+ const contentType = response.headers.get("Content-Type") ?? "";
967
+ if (contentType.includes("text/event-stream")) {
968
+ if (!response.body) {
969
+ throw new Error("Stream response body is null");
970
+ }
971
+ const convertedStream = convertAnthropicStreamToOpenAI(response.body, this.logger);
972
+ return new Response(convertedStream, {
973
+ headers: {
974
+ "Content-Type": "text/event-stream",
975
+ "Cache-Control": "no-cache",
976
+ Connection: "keep-alive"
977
+ }
978
+ });
979
+ } else {
980
+ const data = await response.json();
981
+ const openaiResponse = convertAnthropicResponseToOpenAI(data);
982
+ return new Response(JSON.stringify(openaiResponse), {
983
+ headers: { "Content-Type": "application/json" }
984
+ });
985
+ }
986
+ }
987
+ };
988
+ export {
989
+ AnthropicTransformer
990
+ };