headroom-ai 0.39.1 → 0.40.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/dist/adapters/anthropic.cjs +4 -141
- package/dist/adapters/anthropic.cjs.map +1 -1
- package/dist/adapters/anthropic.js +1 -138
- package/dist/adapters/anthropic.js.map +1 -1
- package/dist/adapters/gemini.cjs +3 -3
- package/dist/adapters/gemini.js +1 -1
- package/dist/adapters/openai.cjs +2 -2
- package/dist/adapters/openai.js +1 -1
- package/dist/adapters/vercel-ai.cjs +7 -7
- package/dist/adapters/vercel-ai.js +1 -1
- package/dist/{chunk-24W6JPRV.js → chunk-FJQ65W3R.js} +56 -7
- package/dist/chunk-FJQ65W3R.js.map +1 -0
- package/dist/{chunk-26N6BVLT.cjs → chunk-N7HYJMEN.cjs} +57 -6
- package/dist/chunk-N7HYJMEN.cjs.map +1 -0
- package/dist/index.cjs +35 -35
- package/dist/index.js +2 -2
- package/package.json +2 -2
- package/dist/chunk-24W6JPRV.js.map +0 -1
- package/dist/chunk-26N6BVLT.cjs.map +0 -1
|
@@ -1,157 +1,20 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkN7HYJMEN_cjs = require('../chunk-N7HYJMEN.cjs');
|
|
4
4
|
|
|
5
5
|
// src/adapters/anthropic.ts
|
|
6
|
-
function anthropicImageUrl(source) {
|
|
7
|
-
if (!source || typeof source !== "object") return null;
|
|
8
|
-
if (source.type === "base64" && source.media_type && source.data) {
|
|
9
|
-
return `data:${source.media_type};base64,${source.data}`;
|
|
10
|
-
}
|
|
11
|
-
if (source.type === "url" && typeof source.url === "string") return source.url;
|
|
12
|
-
return null;
|
|
13
|
-
}
|
|
14
|
-
function openAIImageBlock(url) {
|
|
15
|
-
const m = /^data:([^;,]+);base64,(.*)$/s.exec(url);
|
|
16
|
-
if (m) return { type: "image", source: { type: "base64", media_type: m[1], data: m[2] } };
|
|
17
|
-
return { type: "image", source: { type: "url", url } };
|
|
18
|
-
}
|
|
19
|
-
function anthropicToOpenAI(messages) {
|
|
20
|
-
const result = [];
|
|
21
|
-
for (const msg of messages) {
|
|
22
|
-
if (msg.role === "user") {
|
|
23
|
-
if (typeof msg.content === "string") {
|
|
24
|
-
result.push({ role: "user", content: msg.content });
|
|
25
|
-
} else if (Array.isArray(msg.content)) {
|
|
26
|
-
const toolResults = msg.content.filter(
|
|
27
|
-
(b) => b.type === "tool_result"
|
|
28
|
-
);
|
|
29
|
-
const hasImages = msg.content.some((b) => b.type === "image");
|
|
30
|
-
if (hasImages) {
|
|
31
|
-
const parts = msg.content.filter((b) => b.type === "text" || b.type === "image").map((b) => {
|
|
32
|
-
if (b.type === "text") return { type: "text", text: b.text };
|
|
33
|
-
const url = anthropicImageUrl(b.source);
|
|
34
|
-
return url ? { type: "image_url", image_url: { url } } : null;
|
|
35
|
-
}).filter((p) => p !== null);
|
|
36
|
-
if (parts.length > 0) {
|
|
37
|
-
result.push({ role: "user", content: parts });
|
|
38
|
-
}
|
|
39
|
-
} else {
|
|
40
|
-
const textBlocks = msg.content.filter((b) => b.type === "text");
|
|
41
|
-
if (textBlocks.length > 0) {
|
|
42
|
-
result.push({
|
|
43
|
-
role: "user",
|
|
44
|
-
content: textBlocks.map((b) => b.text).join("\n")
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
for (const tr of toolResults) {
|
|
49
|
-
result.push({
|
|
50
|
-
role: "tool",
|
|
51
|
-
content: typeof tr.content === "string" ? tr.content : JSON.stringify(tr.content),
|
|
52
|
-
tool_call_id: tr.tool_use_id
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
continue;
|
|
57
|
-
}
|
|
58
|
-
if (msg.role === "assistant") {
|
|
59
|
-
if (typeof msg.content === "string") {
|
|
60
|
-
result.push({ role: "assistant", content: msg.content });
|
|
61
|
-
} else if (Array.isArray(msg.content)) {
|
|
62
|
-
const textBlocks = msg.content.filter((b) => b.type === "text");
|
|
63
|
-
const toolUseBlocks = msg.content.filter(
|
|
64
|
-
(b) => b.type === "tool_use"
|
|
65
|
-
);
|
|
66
|
-
const content = textBlocks.length > 0 ? textBlocks.map((b) => b.text).join("\n") : null;
|
|
67
|
-
const openaiMsg = { role: "assistant", content };
|
|
68
|
-
if (toolUseBlocks.length > 0) {
|
|
69
|
-
openaiMsg.tool_calls = toolUseBlocks.map(
|
|
70
|
-
(b) => ({
|
|
71
|
-
id: b.id,
|
|
72
|
-
type: "function",
|
|
73
|
-
function: {
|
|
74
|
-
name: b.name,
|
|
75
|
-
arguments: JSON.stringify(b.input)
|
|
76
|
-
}
|
|
77
|
-
})
|
|
78
|
-
);
|
|
79
|
-
}
|
|
80
|
-
result.push(openaiMsg);
|
|
81
|
-
}
|
|
82
|
-
continue;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
return result;
|
|
86
|
-
}
|
|
87
|
-
function openAIToAnthropic(messages) {
|
|
88
|
-
const result = [];
|
|
89
|
-
for (const msg of messages) {
|
|
90
|
-
if (msg.role === "user") {
|
|
91
|
-
if (typeof msg.content === "string") {
|
|
92
|
-
result.push({ role: "user", content: msg.content });
|
|
93
|
-
} else if (Array.isArray(msg.content)) {
|
|
94
|
-
result.push({
|
|
95
|
-
role: "user",
|
|
96
|
-
content: msg.content.map((p) => {
|
|
97
|
-
if (p.type === "text") return { type: "text", text: p.text };
|
|
98
|
-
if (p.type === "image_url") return openAIImageBlock(p.image_url.url);
|
|
99
|
-
return { type: "text", text: "" };
|
|
100
|
-
})
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
|
-
continue;
|
|
104
|
-
}
|
|
105
|
-
if (msg.role === "assistant") {
|
|
106
|
-
const blocks = [];
|
|
107
|
-
if (msg.content) blocks.push({ type: "text", text: msg.content });
|
|
108
|
-
if (msg.tool_calls) {
|
|
109
|
-
for (const tc of msg.tool_calls) {
|
|
110
|
-
blocks.push({
|
|
111
|
-
type: "tool_use",
|
|
112
|
-
id: tc.id,
|
|
113
|
-
name: tc.function.name,
|
|
114
|
-
input: JSON.parse(tc.function.arguments)
|
|
115
|
-
});
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
result.push({
|
|
119
|
-
role: "assistant",
|
|
120
|
-
content: blocks.length === 1 && blocks[0].type === "text" ? blocks[0].text : blocks
|
|
121
|
-
});
|
|
122
|
-
continue;
|
|
123
|
-
}
|
|
124
|
-
if (msg.role === "tool") {
|
|
125
|
-
result.push({
|
|
126
|
-
role: "user",
|
|
127
|
-
content: [
|
|
128
|
-
{
|
|
129
|
-
type: "tool_result",
|
|
130
|
-
tool_use_id: msg.tool_call_id,
|
|
131
|
-
content: msg.content
|
|
132
|
-
}
|
|
133
|
-
]
|
|
134
|
-
});
|
|
135
|
-
continue;
|
|
136
|
-
}
|
|
137
|
-
if (msg.role === "system") {
|
|
138
|
-
result.push({ role: "user", content: msg.content });
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
return result;
|
|
142
|
-
}
|
|
143
6
|
function withHeadroom(client, options = {}) {
|
|
144
7
|
const originalCreate = client.messages.create.bind(client.messages);
|
|
145
8
|
const compressedCreate = async (params) => {
|
|
146
9
|
const messages = params.messages;
|
|
147
10
|
const model = options.model ?? params.model ?? "claude-sonnet-4-5-20250929";
|
|
148
|
-
const openaiMessages = anthropicToOpenAI(messages);
|
|
149
|
-
const result = await
|
|
11
|
+
const openaiMessages = chunkN7HYJMEN_cjs.anthropicToOpenAI(messages);
|
|
12
|
+
const result = await chunkN7HYJMEN_cjs.compress(openaiMessages, {
|
|
150
13
|
stack: "adapter_ts_anthropic",
|
|
151
14
|
...options,
|
|
152
15
|
model
|
|
153
16
|
});
|
|
154
|
-
const anthropicMessages = result.compressed ? openAIToAnthropic(result.messages) : messages;
|
|
17
|
+
const anthropicMessages = result.compressed ? chunkN7HYJMEN_cjs.openAIToAnthropic(result.messages) : messages;
|
|
155
18
|
return originalCreate({
|
|
156
19
|
...params,
|
|
157
20
|
messages: anthropicMessages
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/adapters/anthropic.ts"],"names":["compress"],"mappings":"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","file":"anthropic.cjs","sourcesContent":["import { compress } from \"../compress.js\";\nimport type { CompressOptions, OpenAIMessage } from \"../types.js\";\nimport type { AssistantMessage, ToolCall } from \"../types.js\";\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\ninterface AnthropicLike {\n messages: {\n create: (params: any) => any;\n };\n [key: string]: any;\n}\n\n// Anthropic image block `source` -> OpenAI image_url url string, or null if unconvertible.\nfunction anthropicImageUrl(source: any): string | null {\n if (!source || typeof source !== \"object\") return null;\n if (source.type === \"base64\" && source.media_type && source.data) {\n return `data:${source.media_type};base64,${source.data}`;\n }\n if (source.type === \"url\" && typeof source.url === \"string\") return source.url;\n return null;\n}\n\n// OpenAI image_url url -> Anthropic image block. data: URIs become a base64 source; other urls a url source.\nfunction openAIImageBlock(url: string): any {\n const m = /^data:([^;,]+);base64,(.*)$/s.exec(url);\n if (m) return { type: \"image\", source: { type: \"base64\", media_type: m[1], data: m[2] } };\n return { type: \"image\", source: { type: \"url\", url } };\n}\n\n/**\n * Convert Anthropic messages to OpenAI format for compression.\n *\n * Anthropic format:\n * { role: 'user' | 'assistant', content: string | ContentBlock[] }\n * ContentBlock = { type: 'text', text } | { type: 'tool_use', ... } | { type: 'tool_result', ... }\n */\nfunction anthropicToOpenAI(messages: any[]): OpenAIMessage[] {\n const result: OpenAIMessage[] = [];\n\n for (const msg of messages) {\n if (msg.role === \"user\") {\n if (typeof msg.content === \"string\") {\n result.push({ role: \"user\", content: msg.content });\n } else if (Array.isArray(msg.content)) {\n const toolResults = msg.content.filter(\n (b: any) => b.type === \"tool_result\",\n );\n const hasImages = msg.content.some((b: any) => b.type === \"image\");\n\n if (hasImages) {\n const parts = msg.content\n .filter((b: any) => b.type === \"text\" || b.type === \"image\")\n .map((b: any) => {\n if (b.type === \"text\") return { type: \"text\" as const, text: b.text };\n const url = anthropicImageUrl(b.source);\n return url ? { type: \"image_url\" as const, image_url: { url } } : null;\n })\n .filter((p: any): p is NonNullable<typeof p> => p !== null);\n\n if (parts.length > 0) {\n result.push({ role: \"user\", content: parts });\n }\n } else {\n const textBlocks = msg.content.filter((b: any) => b.type === \"text\");\n if (textBlocks.length > 0) {\n result.push({\n role: \"user\",\n content: textBlocks.map((b: any) => b.text).join(\"\\n\"),\n });\n }\n }\n for (const tr of toolResults) {\n result.push({\n role: \"tool\",\n content:\n typeof tr.content === \"string\"\n ? tr.content\n : JSON.stringify(tr.content),\n tool_call_id: tr.tool_use_id,\n });\n }\n }\n continue;\n }\n\n if (msg.role === \"assistant\") {\n if (typeof msg.content === \"string\") {\n result.push({ role: \"assistant\", content: msg.content });\n } else if (Array.isArray(msg.content)) {\n const textBlocks = msg.content.filter((b: any) => b.type === \"text\");\n const toolUseBlocks = msg.content.filter(\n (b: any) => b.type === \"tool_use\",\n );\n\n const content =\n textBlocks.length > 0\n ? textBlocks.map((b: any) => b.text).join(\"\\n\")\n : null;\n\n const openaiMsg: AssistantMessage = { role: \"assistant\", content };\n if (toolUseBlocks.length > 0) {\n openaiMsg.tool_calls = toolUseBlocks.map(\n (b: any): ToolCall => ({\n id: b.id,\n type: \"function\",\n function: {\n name: b.name,\n arguments: JSON.stringify(b.input),\n },\n }),\n );\n }\n result.push(openaiMsg);\n }\n continue;\n }\n }\n\n return result;\n}\n\n/**\n * Convert compressed OpenAI messages back to Anthropic format.\n */\nfunction openAIToAnthropic(messages: OpenAIMessage[]): any[] {\n const result: any[] = [];\n\n for (const msg of messages) {\n if (msg.role === \"user\") {\n if (typeof msg.content === \"string\") {\n result.push({ role: \"user\", content: msg.content });\n } else if (Array.isArray(msg.content)) {\n result.push({\n role: \"user\",\n content: msg.content.map((p) => {\n if (p.type === \"text\") return { type: \"text\", text: p.text };\n if (p.type === \"image_url\") return openAIImageBlock(p.image_url.url);\n return { type: \"text\", text: \"\" };\n }),\n });\n }\n continue;\n }\n\n if (msg.role === \"assistant\") {\n const blocks: any[] = [];\n if (msg.content) blocks.push({ type: \"text\", text: msg.content });\n if (msg.tool_calls) {\n for (const tc of msg.tool_calls) {\n blocks.push({\n type: \"tool_use\",\n id: tc.id,\n name: tc.function.name,\n input: JSON.parse(tc.function.arguments),\n });\n }\n }\n result.push({\n role: \"assistant\",\n content:\n blocks.length === 1 && blocks[0].type === \"text\"\n ? blocks[0].text\n : blocks,\n });\n continue;\n }\n\n if (msg.role === \"tool\") {\n result.push({\n role: \"user\",\n content: [\n {\n type: \"tool_result\",\n tool_use_id: msg.tool_call_id,\n content: msg.content,\n },\n ],\n });\n continue;\n }\n\n if (msg.role === \"system\") {\n // System messages are handled separately in Anthropic (as `system` param)\n // Pass through as user message if it appears in the messages array\n result.push({ role: \"user\", content: msg.content });\n }\n }\n\n return result;\n}\n\n/**\n * Wrap an Anthropic client to auto-compress messages before each request.\n *\n * Intercepts `client.messages.create()` only. All other methods pass through.\n *\n * @example\n * ```typescript\n * import { withHeadroom } from 'headroom-ai/anthropic';\n * import Anthropic from '@anthropic-ai/sdk';\n *\n * const client = withHeadroom(new Anthropic());\n * const response = await client.messages.create({\n * model: 'claude-sonnet-4-5-20250929',\n * messages: longConversation,\n * max_tokens: 1024,\n * });\n * ```\n */\nexport function withHeadroom<T extends AnthropicLike>(\n client: T,\n options: CompressOptions = {},\n): T {\n const originalCreate = client.messages.create.bind(client.messages);\n\n const compressedCreate = async (params: any) => {\n const messages = params.messages;\n const model =\n options.model ?? params.model ?? \"claude-sonnet-4-5-20250929\";\n\n const openaiMessages = anthropicToOpenAI(messages);\n const result = await compress(openaiMessages, {\n stack: \"adapter_ts_anthropic\",\n ...options,\n model,\n });\n\n const anthropicMessages = result.compressed\n ? openAIToAnthropic(result.messages)\n : messages;\n\n return originalCreate({\n ...params,\n messages: anthropicMessages,\n });\n };\n\n const messagesProxy = new Proxy(client.messages, {\n get(target, prop) {\n if (prop === \"create\") return compressedCreate;\n return (target as any)[prop];\n },\n });\n\n return new Proxy(client, {\n get(target, prop) {\n if (prop === \"messages\") return messagesProxy;\n return (target as any)[prop];\n },\n }) as T;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/adapters/anthropic.ts"],"names":["anthropicToOpenAI","compress","openAIToAnthropic"],"mappings":";;;;;AA+BO,SAAS,YAAA,CACd,MAAA,EACA,OAAA,GAA2B,EAAC,EACzB;AACH,EAAA,MAAM,iBAAiB,MAAA,CAAO,QAAA,CAAS,MAAA,CAAO,IAAA,CAAK,OAAO,QAAQ,CAAA;AAElE,EAAA,MAAM,gBAAA,GAAmB,OAAO,MAAA,KAAgB;AAC9C,IAAA,MAAM,WAAW,MAAA,CAAO,QAAA;AACxB,IAAA,MAAM,KAAA,GACJ,OAAA,CAAQ,KAAA,IAAS,MAAA,CAAO,KAAA,IAAS,4BAAA;AAEnC,IAAA,MAAM,cAAA,GAAiBA,oCAAkB,QAAQ,CAAA;AACjD,IAAA,MAAM,MAAA,GAAS,MAAMC,0BAAA,CAAS,cAAA,EAAgB;AAAA,MAC5C,KAAA,EAAO,sBAAA;AAAA,MACP,GAAG,OAAA;AAAA,MACH;AAAA,KACD,CAAA;AAED,IAAA,MAAM,oBAAoB,MAAA,CAAO,UAAA,GAC7BC,mCAAA,CAAkB,MAAA,CAAO,QAAQ,CAAA,GACjC,QAAA;AAEJ,IAAA,OAAO,cAAA,CAAe;AAAA,MACpB,GAAG,MAAA;AAAA,MACH,QAAA,EAAU;AAAA,KACX,CAAA;AAAA,EACH,CAAA;AAEA,EAAA,MAAM,aAAA,GAAgB,IAAI,KAAA,CAAM,MAAA,CAAO,QAAA,EAAU;AAAA,IAC/C,GAAA,CAAI,QAAQ,IAAA,EAAM;AAChB,MAAA,IAAI,IAAA,KAAS,UAAU,OAAO,gBAAA;AAC9B,MAAA,OAAQ,OAAe,IAAI,CAAA;AAAA,IAC7B;AAAA,GACD,CAAA;AAED,EAAA,OAAO,IAAI,MAAM,MAAA,EAAQ;AAAA,IACvB,GAAA,CAAI,QAAQ,IAAA,EAAM;AAChB,MAAA,IAAI,IAAA,KAAS,YAAY,OAAO,aAAA;AAChC,MAAA,OAAQ,OAAe,IAAI,CAAA;AAAA,IAC7B;AAAA,GACD,CAAA;AACH","file":"anthropic.cjs","sourcesContent":["import { compress } from \"../compress.js\";\nimport type { CompressOptions } from \"../types.js\";\nimport { anthropicToOpenAI, openAIToAnthropic } from \"../utils/format.js\";\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\ninterface AnthropicLike {\n messages: {\n create: (params: any) => any;\n };\n [key: string]: any;\n}\n\n/**\n * Wrap an Anthropic client to auto-compress messages before each request.\n *\n * Intercepts `client.messages.create()` only. All other methods pass through.\n *\n * @example\n * ```typescript\n * import { withHeadroom } from 'headroom-ai/anthropic';\n * import Anthropic from '@anthropic-ai/sdk';\n *\n * const client = withHeadroom(new Anthropic());\n * const response = await client.messages.create({\n * model: 'claude-sonnet-4-5-20250929',\n * messages: longConversation,\n * max_tokens: 1024,\n * });\n * ```\n */\nexport function withHeadroom<T extends AnthropicLike>(\n client: T,\n options: CompressOptions = {},\n): T {\n const originalCreate = client.messages.create.bind(client.messages);\n\n const compressedCreate = async (params: any) => {\n const messages = params.messages;\n const model =\n options.model ?? params.model ?? \"claude-sonnet-4-5-20250929\";\n\n const openaiMessages = anthropicToOpenAI(messages);\n const result = await compress(openaiMessages, {\n stack: \"adapter_ts_anthropic\",\n ...options,\n model,\n });\n\n const anthropicMessages = result.compressed\n ? openAIToAnthropic(result.messages)\n : messages;\n\n return originalCreate({\n ...params,\n messages: anthropicMessages,\n });\n };\n\n const messagesProxy = new Proxy(client.messages, {\n get(target, prop) {\n if (prop === \"create\") return compressedCreate;\n return (target as any)[prop];\n },\n });\n\n return new Proxy(client, {\n get(target, prop) {\n if (prop === \"messages\") return messagesProxy;\n return (target as any)[prop];\n },\n }) as T;\n}\n"]}
|
|
@@ -1,143 +1,6 @@
|
|
|
1
|
-
import { compress } from '../chunk-
|
|
1
|
+
import { anthropicToOpenAI, compress, openAIToAnthropic } from '../chunk-FJQ65W3R.js';
|
|
2
2
|
|
|
3
3
|
// src/adapters/anthropic.ts
|
|
4
|
-
function anthropicImageUrl(source) {
|
|
5
|
-
if (!source || typeof source !== "object") return null;
|
|
6
|
-
if (source.type === "base64" && source.media_type && source.data) {
|
|
7
|
-
return `data:${source.media_type};base64,${source.data}`;
|
|
8
|
-
}
|
|
9
|
-
if (source.type === "url" && typeof source.url === "string") return source.url;
|
|
10
|
-
return null;
|
|
11
|
-
}
|
|
12
|
-
function openAIImageBlock(url) {
|
|
13
|
-
const m = /^data:([^;,]+);base64,(.*)$/s.exec(url);
|
|
14
|
-
if (m) return { type: "image", source: { type: "base64", media_type: m[1], data: m[2] } };
|
|
15
|
-
return { type: "image", source: { type: "url", url } };
|
|
16
|
-
}
|
|
17
|
-
function anthropicToOpenAI(messages) {
|
|
18
|
-
const result = [];
|
|
19
|
-
for (const msg of messages) {
|
|
20
|
-
if (msg.role === "user") {
|
|
21
|
-
if (typeof msg.content === "string") {
|
|
22
|
-
result.push({ role: "user", content: msg.content });
|
|
23
|
-
} else if (Array.isArray(msg.content)) {
|
|
24
|
-
const toolResults = msg.content.filter(
|
|
25
|
-
(b) => b.type === "tool_result"
|
|
26
|
-
);
|
|
27
|
-
const hasImages = msg.content.some((b) => b.type === "image");
|
|
28
|
-
if (hasImages) {
|
|
29
|
-
const parts = msg.content.filter((b) => b.type === "text" || b.type === "image").map((b) => {
|
|
30
|
-
if (b.type === "text") return { type: "text", text: b.text };
|
|
31
|
-
const url = anthropicImageUrl(b.source);
|
|
32
|
-
return url ? { type: "image_url", image_url: { url } } : null;
|
|
33
|
-
}).filter((p) => p !== null);
|
|
34
|
-
if (parts.length > 0) {
|
|
35
|
-
result.push({ role: "user", content: parts });
|
|
36
|
-
}
|
|
37
|
-
} else {
|
|
38
|
-
const textBlocks = msg.content.filter((b) => b.type === "text");
|
|
39
|
-
if (textBlocks.length > 0) {
|
|
40
|
-
result.push({
|
|
41
|
-
role: "user",
|
|
42
|
-
content: textBlocks.map((b) => b.text).join("\n")
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
for (const tr of toolResults) {
|
|
47
|
-
result.push({
|
|
48
|
-
role: "tool",
|
|
49
|
-
content: typeof tr.content === "string" ? tr.content : JSON.stringify(tr.content),
|
|
50
|
-
tool_call_id: tr.tool_use_id
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
continue;
|
|
55
|
-
}
|
|
56
|
-
if (msg.role === "assistant") {
|
|
57
|
-
if (typeof msg.content === "string") {
|
|
58
|
-
result.push({ role: "assistant", content: msg.content });
|
|
59
|
-
} else if (Array.isArray(msg.content)) {
|
|
60
|
-
const textBlocks = msg.content.filter((b) => b.type === "text");
|
|
61
|
-
const toolUseBlocks = msg.content.filter(
|
|
62
|
-
(b) => b.type === "tool_use"
|
|
63
|
-
);
|
|
64
|
-
const content = textBlocks.length > 0 ? textBlocks.map((b) => b.text).join("\n") : null;
|
|
65
|
-
const openaiMsg = { role: "assistant", content };
|
|
66
|
-
if (toolUseBlocks.length > 0) {
|
|
67
|
-
openaiMsg.tool_calls = toolUseBlocks.map(
|
|
68
|
-
(b) => ({
|
|
69
|
-
id: b.id,
|
|
70
|
-
type: "function",
|
|
71
|
-
function: {
|
|
72
|
-
name: b.name,
|
|
73
|
-
arguments: JSON.stringify(b.input)
|
|
74
|
-
}
|
|
75
|
-
})
|
|
76
|
-
);
|
|
77
|
-
}
|
|
78
|
-
result.push(openaiMsg);
|
|
79
|
-
}
|
|
80
|
-
continue;
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
return result;
|
|
84
|
-
}
|
|
85
|
-
function openAIToAnthropic(messages) {
|
|
86
|
-
const result = [];
|
|
87
|
-
for (const msg of messages) {
|
|
88
|
-
if (msg.role === "user") {
|
|
89
|
-
if (typeof msg.content === "string") {
|
|
90
|
-
result.push({ role: "user", content: msg.content });
|
|
91
|
-
} else if (Array.isArray(msg.content)) {
|
|
92
|
-
result.push({
|
|
93
|
-
role: "user",
|
|
94
|
-
content: msg.content.map((p) => {
|
|
95
|
-
if (p.type === "text") return { type: "text", text: p.text };
|
|
96
|
-
if (p.type === "image_url") return openAIImageBlock(p.image_url.url);
|
|
97
|
-
return { type: "text", text: "" };
|
|
98
|
-
})
|
|
99
|
-
});
|
|
100
|
-
}
|
|
101
|
-
continue;
|
|
102
|
-
}
|
|
103
|
-
if (msg.role === "assistant") {
|
|
104
|
-
const blocks = [];
|
|
105
|
-
if (msg.content) blocks.push({ type: "text", text: msg.content });
|
|
106
|
-
if (msg.tool_calls) {
|
|
107
|
-
for (const tc of msg.tool_calls) {
|
|
108
|
-
blocks.push({
|
|
109
|
-
type: "tool_use",
|
|
110
|
-
id: tc.id,
|
|
111
|
-
name: tc.function.name,
|
|
112
|
-
input: JSON.parse(tc.function.arguments)
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
result.push({
|
|
117
|
-
role: "assistant",
|
|
118
|
-
content: blocks.length === 1 && blocks[0].type === "text" ? blocks[0].text : blocks
|
|
119
|
-
});
|
|
120
|
-
continue;
|
|
121
|
-
}
|
|
122
|
-
if (msg.role === "tool") {
|
|
123
|
-
result.push({
|
|
124
|
-
role: "user",
|
|
125
|
-
content: [
|
|
126
|
-
{
|
|
127
|
-
type: "tool_result",
|
|
128
|
-
tool_use_id: msg.tool_call_id,
|
|
129
|
-
content: msg.content
|
|
130
|
-
}
|
|
131
|
-
]
|
|
132
|
-
});
|
|
133
|
-
continue;
|
|
134
|
-
}
|
|
135
|
-
if (msg.role === "system") {
|
|
136
|
-
result.push({ role: "user", content: msg.content });
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
return result;
|
|
140
|
-
}
|
|
141
4
|
function withHeadroom(client, options = {}) {
|
|
142
5
|
const originalCreate = client.messages.create.bind(client.messages);
|
|
143
6
|
const compressedCreate = async (params) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/adapters/anthropic.ts"],"names":[],"mappings":"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","file":"anthropic.js","sourcesContent":["import { compress } from \"../compress.js\";\nimport type { CompressOptions, OpenAIMessage } from \"../types.js\";\nimport type { AssistantMessage, ToolCall } from \"../types.js\";\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\ninterface AnthropicLike {\n messages: {\n create: (params: any) => any;\n };\n [key: string]: any;\n}\n\n// Anthropic image block `source` -> OpenAI image_url url string, or null if unconvertible.\nfunction anthropicImageUrl(source: any): string | null {\n if (!source || typeof source !== \"object\") return null;\n if (source.type === \"base64\" && source.media_type && source.data) {\n return `data:${source.media_type};base64,${source.data}`;\n }\n if (source.type === \"url\" && typeof source.url === \"string\") return source.url;\n return null;\n}\n\n// OpenAI image_url url -> Anthropic image block. data: URIs become a base64 source; other urls a url source.\nfunction openAIImageBlock(url: string): any {\n const m = /^data:([^;,]+);base64,(.*)$/s.exec(url);\n if (m) return { type: \"image\", source: { type: \"base64\", media_type: m[1], data: m[2] } };\n return { type: \"image\", source: { type: \"url\", url } };\n}\n\n/**\n * Convert Anthropic messages to OpenAI format for compression.\n *\n * Anthropic format:\n * { role: 'user' | 'assistant', content: string | ContentBlock[] }\n * ContentBlock = { type: 'text', text } | { type: 'tool_use', ... } | { type: 'tool_result', ... }\n */\nfunction anthropicToOpenAI(messages: any[]): OpenAIMessage[] {\n const result: OpenAIMessage[] = [];\n\n for (const msg of messages) {\n if (msg.role === \"user\") {\n if (typeof msg.content === \"string\") {\n result.push({ role: \"user\", content: msg.content });\n } else if (Array.isArray(msg.content)) {\n const toolResults = msg.content.filter(\n (b: any) => b.type === \"tool_result\",\n );\n const hasImages = msg.content.some((b: any) => b.type === \"image\");\n\n if (hasImages) {\n const parts = msg.content\n .filter((b: any) => b.type === \"text\" || b.type === \"image\")\n .map((b: any) => {\n if (b.type === \"text\") return { type: \"text\" as const, text: b.text };\n const url = anthropicImageUrl(b.source);\n return url ? { type: \"image_url\" as const, image_url: { url } } : null;\n })\n .filter((p: any): p is NonNullable<typeof p> => p !== null);\n\n if (parts.length > 0) {\n result.push({ role: \"user\", content: parts });\n }\n } else {\n const textBlocks = msg.content.filter((b: any) => b.type === \"text\");\n if (textBlocks.length > 0) {\n result.push({\n role: \"user\",\n content: textBlocks.map((b: any) => b.text).join(\"\\n\"),\n });\n }\n }\n for (const tr of toolResults) {\n result.push({\n role: \"tool\",\n content:\n typeof tr.content === \"string\"\n ? tr.content\n : JSON.stringify(tr.content),\n tool_call_id: tr.tool_use_id,\n });\n }\n }\n continue;\n }\n\n if (msg.role === \"assistant\") {\n if (typeof msg.content === \"string\") {\n result.push({ role: \"assistant\", content: msg.content });\n } else if (Array.isArray(msg.content)) {\n const textBlocks = msg.content.filter((b: any) => b.type === \"text\");\n const toolUseBlocks = msg.content.filter(\n (b: any) => b.type === \"tool_use\",\n );\n\n const content =\n textBlocks.length > 0\n ? textBlocks.map((b: any) => b.text).join(\"\\n\")\n : null;\n\n const openaiMsg: AssistantMessage = { role: \"assistant\", content };\n if (toolUseBlocks.length > 0) {\n openaiMsg.tool_calls = toolUseBlocks.map(\n (b: any): ToolCall => ({\n id: b.id,\n type: \"function\",\n function: {\n name: b.name,\n arguments: JSON.stringify(b.input),\n },\n }),\n );\n }\n result.push(openaiMsg);\n }\n continue;\n }\n }\n\n return result;\n}\n\n/**\n * Convert compressed OpenAI messages back to Anthropic format.\n */\nfunction openAIToAnthropic(messages: OpenAIMessage[]): any[] {\n const result: any[] = [];\n\n for (const msg of messages) {\n if (msg.role === \"user\") {\n if (typeof msg.content === \"string\") {\n result.push({ role: \"user\", content: msg.content });\n } else if (Array.isArray(msg.content)) {\n result.push({\n role: \"user\",\n content: msg.content.map((p) => {\n if (p.type === \"text\") return { type: \"text\", text: p.text };\n if (p.type === \"image_url\") return openAIImageBlock(p.image_url.url);\n return { type: \"text\", text: \"\" };\n }),\n });\n }\n continue;\n }\n\n if (msg.role === \"assistant\") {\n const blocks: any[] = [];\n if (msg.content) blocks.push({ type: \"text\", text: msg.content });\n if (msg.tool_calls) {\n for (const tc of msg.tool_calls) {\n blocks.push({\n type: \"tool_use\",\n id: tc.id,\n name: tc.function.name,\n input: JSON.parse(tc.function.arguments),\n });\n }\n }\n result.push({\n role: \"assistant\",\n content:\n blocks.length === 1 && blocks[0].type === \"text\"\n ? blocks[0].text\n : blocks,\n });\n continue;\n }\n\n if (msg.role === \"tool\") {\n result.push({\n role: \"user\",\n content: [\n {\n type: \"tool_result\",\n tool_use_id: msg.tool_call_id,\n content: msg.content,\n },\n ],\n });\n continue;\n }\n\n if (msg.role === \"system\") {\n // System messages are handled separately in Anthropic (as `system` param)\n // Pass through as user message if it appears in the messages array\n result.push({ role: \"user\", content: msg.content });\n }\n }\n\n return result;\n}\n\n/**\n * Wrap an Anthropic client to auto-compress messages before each request.\n *\n * Intercepts `client.messages.create()` only. All other methods pass through.\n *\n * @example\n * ```typescript\n * import { withHeadroom } from 'headroom-ai/anthropic';\n * import Anthropic from '@anthropic-ai/sdk';\n *\n * const client = withHeadroom(new Anthropic());\n * const response = await client.messages.create({\n * model: 'claude-sonnet-4-5-20250929',\n * messages: longConversation,\n * max_tokens: 1024,\n * });\n * ```\n */\nexport function withHeadroom<T extends AnthropicLike>(\n client: T,\n options: CompressOptions = {},\n): T {\n const originalCreate = client.messages.create.bind(client.messages);\n\n const compressedCreate = async (params: any) => {\n const messages = params.messages;\n const model =\n options.model ?? params.model ?? \"claude-sonnet-4-5-20250929\";\n\n const openaiMessages = anthropicToOpenAI(messages);\n const result = await compress(openaiMessages, {\n stack: \"adapter_ts_anthropic\",\n ...options,\n model,\n });\n\n const anthropicMessages = result.compressed\n ? openAIToAnthropic(result.messages)\n : messages;\n\n return originalCreate({\n ...params,\n messages: anthropicMessages,\n });\n };\n\n const messagesProxy = new Proxy(client.messages, {\n get(target, prop) {\n if (prop === \"create\") return compressedCreate;\n return (target as any)[prop];\n },\n });\n\n return new Proxy(client, {\n get(target, prop) {\n if (prop === \"messages\") return messagesProxy;\n return (target as any)[prop];\n },\n }) as T;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/adapters/anthropic.ts"],"names":[],"mappings":";;;AA+BO,SAAS,YAAA,CACd,MAAA,EACA,OAAA,GAA2B,EAAC,EACzB;AACH,EAAA,MAAM,iBAAiB,MAAA,CAAO,QAAA,CAAS,MAAA,CAAO,IAAA,CAAK,OAAO,QAAQ,CAAA;AAElE,EAAA,MAAM,gBAAA,GAAmB,OAAO,MAAA,KAAgB;AAC9C,IAAA,MAAM,WAAW,MAAA,CAAO,QAAA;AACxB,IAAA,MAAM,KAAA,GACJ,OAAA,CAAQ,KAAA,IAAS,MAAA,CAAO,KAAA,IAAS,4BAAA;AAEnC,IAAA,MAAM,cAAA,GAAiB,kBAAkB,QAAQ,CAAA;AACjD,IAAA,MAAM,MAAA,GAAS,MAAM,QAAA,CAAS,cAAA,EAAgB;AAAA,MAC5C,KAAA,EAAO,sBAAA;AAAA,MACP,GAAG,OAAA;AAAA,MACH;AAAA,KACD,CAAA;AAED,IAAA,MAAM,oBAAoB,MAAA,CAAO,UAAA,GAC7B,iBAAA,CAAkB,MAAA,CAAO,QAAQ,CAAA,GACjC,QAAA;AAEJ,IAAA,OAAO,cAAA,CAAe;AAAA,MACpB,GAAG,MAAA;AAAA,MACH,QAAA,EAAU;AAAA,KACX,CAAA;AAAA,EACH,CAAA;AAEA,EAAA,MAAM,aAAA,GAAgB,IAAI,KAAA,CAAM,MAAA,CAAO,QAAA,EAAU;AAAA,IAC/C,GAAA,CAAI,QAAQ,IAAA,EAAM;AAChB,MAAA,IAAI,IAAA,KAAS,UAAU,OAAO,gBAAA;AAC9B,MAAA,OAAQ,OAAe,IAAI,CAAA;AAAA,IAC7B;AAAA,GACD,CAAA;AAED,EAAA,OAAO,IAAI,MAAM,MAAA,EAAQ;AAAA,IACvB,GAAA,CAAI,QAAQ,IAAA,EAAM;AAChB,MAAA,IAAI,IAAA,KAAS,YAAY,OAAO,aAAA;AAChC,MAAA,OAAQ,OAAe,IAAI,CAAA;AAAA,IAC7B;AAAA,GACD,CAAA;AACH","file":"anthropic.js","sourcesContent":["import { compress } from \"../compress.js\";\nimport type { CompressOptions } from \"../types.js\";\nimport { anthropicToOpenAI, openAIToAnthropic } from \"../utils/format.js\";\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\ninterface AnthropicLike {\n messages: {\n create: (params: any) => any;\n };\n [key: string]: any;\n}\n\n/**\n * Wrap an Anthropic client to auto-compress messages before each request.\n *\n * Intercepts `client.messages.create()` only. All other methods pass through.\n *\n * @example\n * ```typescript\n * import { withHeadroom } from 'headroom-ai/anthropic';\n * import Anthropic from '@anthropic-ai/sdk';\n *\n * const client = withHeadroom(new Anthropic());\n * const response = await client.messages.create({\n * model: 'claude-sonnet-4-5-20250929',\n * messages: longConversation,\n * max_tokens: 1024,\n * });\n * ```\n */\nexport function withHeadroom<T extends AnthropicLike>(\n client: T,\n options: CompressOptions = {},\n): T {\n const originalCreate = client.messages.create.bind(client.messages);\n\n const compressedCreate = async (params: any) => {\n const messages = params.messages;\n const model =\n options.model ?? params.model ?? \"claude-sonnet-4-5-20250929\";\n\n const openaiMessages = anthropicToOpenAI(messages);\n const result = await compress(openaiMessages, {\n stack: \"adapter_ts_anthropic\",\n ...options,\n model,\n });\n\n const anthropicMessages = result.compressed\n ? openAIToAnthropic(result.messages)\n : messages;\n\n return originalCreate({\n ...params,\n messages: anthropicMessages,\n });\n };\n\n const messagesProxy = new Proxy(client.messages, {\n get(target, prop) {\n if (prop === \"create\") return compressedCreate;\n return (target as any)[prop];\n },\n });\n\n return new Proxy(client, {\n get(target, prop) {\n if (prop === \"messages\") return messagesProxy;\n return (target as any)[prop];\n },\n }) as T;\n}\n"]}
|
package/dist/adapters/gemini.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkN7HYJMEN_cjs = require('../chunk-N7HYJMEN.cjs');
|
|
4
4
|
|
|
5
5
|
// src/adapters/gemini.ts
|
|
6
6
|
function withHeadroom(model, options = {}) {
|
|
@@ -9,7 +9,7 @@ function withHeadroom(model, options = {}) {
|
|
|
9
9
|
const compressedGenerate = async (params) => {
|
|
10
10
|
const contents = params.contents ?? params;
|
|
11
11
|
const modelName = options.model ?? "gemini-2.0-flash";
|
|
12
|
-
const result = await
|
|
12
|
+
const result = await chunkN7HYJMEN_cjs.compress(
|
|
13
13
|
Array.isArray(contents) ? contents : [contents],
|
|
14
14
|
{ stack: "adapter_ts_gemini", ...options, model: modelName }
|
|
15
15
|
);
|
|
@@ -19,7 +19,7 @@ function withHeadroom(model, options = {}) {
|
|
|
19
19
|
const compressedStream = originalStream ? async (params) => {
|
|
20
20
|
const contents = params.contents ?? params;
|
|
21
21
|
const modelName = options.model ?? "gemini-2.0-flash";
|
|
22
|
-
const result = await
|
|
22
|
+
const result = await chunkN7HYJMEN_cjs.compress(
|
|
23
23
|
Array.isArray(contents) ? contents : [contents],
|
|
24
24
|
{ stack: "adapter_ts_gemini", ...options, model: modelName }
|
|
25
25
|
);
|
package/dist/adapters/gemini.js
CHANGED
package/dist/adapters/openai.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkN7HYJMEN_cjs = require('../chunk-N7HYJMEN.cjs');
|
|
4
4
|
|
|
5
5
|
// src/adapters/openai.ts
|
|
6
6
|
function withHeadroom(client, options = {}) {
|
|
@@ -10,7 +10,7 @@ function withHeadroom(client, options = {}) {
|
|
|
10
10
|
const compressedCreate = async (params) => {
|
|
11
11
|
const messages = params.messages;
|
|
12
12
|
const model = options.model ?? params.model ?? "gpt-4o";
|
|
13
|
-
const result = await
|
|
13
|
+
const result = await chunkN7HYJMEN_cjs.compress(messages, {
|
|
14
14
|
stack: "adapter_ts_openai",
|
|
15
15
|
...options,
|
|
16
16
|
model
|
package/dist/adapters/openai.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkN7HYJMEN_cjs = require('../chunk-N7HYJMEN.cjs');
|
|
4
4
|
var module$1 = require('module');
|
|
5
5
|
|
|
6
6
|
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
@@ -12,25 +12,25 @@ function headroomMiddleware(options = {}) {
|
|
|
12
12
|
const prompt = params.prompt;
|
|
13
13
|
if (!prompt || prompt.length === 0) return params;
|
|
14
14
|
const model = options.model ?? params.modelId ?? "gpt-4o";
|
|
15
|
-
const openaiMessages =
|
|
16
|
-
const result = await
|
|
15
|
+
const openaiMessages = chunkN7HYJMEN_cjs.vercelToOpenAI(prompt);
|
|
16
|
+
const result = await chunkN7HYJMEN_cjs.compress(openaiMessages, {
|
|
17
17
|
stack: "adapter_ts_vercel_ai",
|
|
18
18
|
...options,
|
|
19
19
|
model
|
|
20
20
|
});
|
|
21
21
|
if (!result.compressed) return params;
|
|
22
|
-
const compressedPrompt =
|
|
22
|
+
const compressedPrompt = chunkN7HYJMEN_cjs.openAIToVercel(result.messages);
|
|
23
23
|
return { ...params, prompt: compressedPrompt };
|
|
24
24
|
}
|
|
25
25
|
};
|
|
26
26
|
}
|
|
27
27
|
async function compressVercelMessages(messages, options = {}) {
|
|
28
|
-
const openaiMessages =
|
|
29
|
-
const result = await
|
|
28
|
+
const openaiMessages = chunkN7HYJMEN_cjs.vercelToOpenAI(messages);
|
|
29
|
+
const result = await chunkN7HYJMEN_cjs.compress(openaiMessages, {
|
|
30
30
|
stack: "adapter_ts_vercel_ai",
|
|
31
31
|
...options
|
|
32
32
|
});
|
|
33
|
-
const vercelMessages =
|
|
33
|
+
const vercelMessages = chunkN7HYJMEN_cjs.openAIToVercel(result.messages);
|
|
34
34
|
return {
|
|
35
35
|
...result,
|
|
36
36
|
messages: vercelMessages
|
|
@@ -822,6 +822,7 @@ function vercelToOpenAI(messages) {
|
|
|
822
822
|
}
|
|
823
823
|
function openAIToVercel(messages) {
|
|
824
824
|
const result = [];
|
|
825
|
+
const toolNames = /* @__PURE__ */ new Map();
|
|
825
826
|
for (const msg of messages) {
|
|
826
827
|
if (msg.role === "system") {
|
|
827
828
|
result.push({ role: "system", content: msg.content });
|
|
@@ -845,6 +846,7 @@ function openAIToVercel(messages) {
|
|
|
845
846
|
if (msg.content) parts.push({ type: "text", text: msg.content });
|
|
846
847
|
if (msg.tool_calls) {
|
|
847
848
|
for (const tc of msg.tool_calls) {
|
|
849
|
+
toolNames.set(tc.id, tc.function.name);
|
|
848
850
|
let input;
|
|
849
851
|
try {
|
|
850
852
|
input = JSON.parse(tc.function.arguments);
|
|
@@ -876,7 +878,7 @@ function openAIToVercel(messages) {
|
|
|
876
878
|
content: [{
|
|
877
879
|
type: "tool-result",
|
|
878
880
|
toolCallId: msg.tool_call_id,
|
|
879
|
-
toolName: "unknown",
|
|
881
|
+
toolName: toolNames.get(msg.tool_call_id) ?? "unknown",
|
|
880
882
|
output
|
|
881
883
|
}]
|
|
882
884
|
});
|
|
@@ -885,6 +887,32 @@ function openAIToVercel(messages) {
|
|
|
885
887
|
}
|
|
886
888
|
return result;
|
|
887
889
|
}
|
|
890
|
+
function geminiMediaImageUrl(part) {
|
|
891
|
+
const blob = part.inlineData;
|
|
892
|
+
if (blob && typeof blob === "object" && blob.mimeType && blob.data) {
|
|
893
|
+
return { url: `data:${blob.mimeType};base64,${blob.data}` };
|
|
894
|
+
}
|
|
895
|
+
const file = part.fileData;
|
|
896
|
+
if (file && typeof file === "object" && typeof file.fileUri === "string") {
|
|
897
|
+
return typeof file.mimeType === "string" ? { url: file.fileUri, mime_type: file.mimeType } : { url: file.fileUri };
|
|
898
|
+
}
|
|
899
|
+
return null;
|
|
900
|
+
}
|
|
901
|
+
var MIME_BY_EXTENSION = {
|
|
902
|
+
png: "image/png",
|
|
903
|
+
jpg: "image/jpeg",
|
|
904
|
+
jpeg: "image/jpeg",
|
|
905
|
+
gif: "image/gif",
|
|
906
|
+
webp: "image/webp",
|
|
907
|
+
pdf: "application/pdf"
|
|
908
|
+
};
|
|
909
|
+
function geminiMediaPart(imageUrl) {
|
|
910
|
+
const m = /^data:([^;,]+);base64,(.*)$/s.exec(imageUrl.url);
|
|
911
|
+
if (m) return { inlineData: { mimeType: m[1], data: m[2] } };
|
|
912
|
+
const ext = /\.([a-z0-9]+)(?:[?#]|$)/i.exec(imageUrl.url)?.[1]?.toLowerCase();
|
|
913
|
+
const mimeType = imageUrl.mime_type ?? (ext ? MIME_BY_EXTENSION[ext] : void 0);
|
|
914
|
+
return { fileData: mimeType ? { mimeType, fileUri: imageUrl.url } : { fileUri: imageUrl.url } };
|
|
915
|
+
}
|
|
888
916
|
function geminiToOpenAI(messages) {
|
|
889
917
|
const result = [];
|
|
890
918
|
for (const msg of messages) {
|
|
@@ -892,9 +920,21 @@ function geminiToOpenAI(messages) {
|
|
|
892
920
|
const parts = msg.parts ?? [];
|
|
893
921
|
if (role === "user") {
|
|
894
922
|
const funcResponses = parts.filter((p) => p.functionResponse);
|
|
895
|
-
const
|
|
896
|
-
if (
|
|
897
|
-
|
|
923
|
+
const hasMedia = parts.some((p) => p.inlineData || p.fileData);
|
|
924
|
+
if (hasMedia) {
|
|
925
|
+
const content = parts.filter((p) => p.text !== void 0 || p.inlineData || p.fileData).map((p) => {
|
|
926
|
+
if (p.text !== void 0) return { type: "text", text: p.text };
|
|
927
|
+
const imageUrl = geminiMediaImageUrl(p);
|
|
928
|
+
return imageUrl ? { type: "image_url", image_url: imageUrl } : null;
|
|
929
|
+
}).filter((p) => p !== null);
|
|
930
|
+
if (content.length > 0) {
|
|
931
|
+
result.push({ role: "user", content });
|
|
932
|
+
}
|
|
933
|
+
} else {
|
|
934
|
+
const textParts = parts.filter((p) => p.text !== void 0);
|
|
935
|
+
if (textParts.length > 0) {
|
|
936
|
+
result.push({ role: "user", content: textParts.map((p) => p.text).join("\n") });
|
|
937
|
+
}
|
|
898
938
|
}
|
|
899
939
|
for (const fr of funcResponses) {
|
|
900
940
|
result.push({
|
|
@@ -934,6 +974,15 @@ function openAIToGemini(messages) {
|
|
|
934
974
|
continue;
|
|
935
975
|
}
|
|
936
976
|
if (msg.role === "user") {
|
|
977
|
+
if (Array.isArray(msg.content) && msg.content.some((p) => p.type === "image_url")) {
|
|
978
|
+
const geminiParts = msg.content.map((p) => {
|
|
979
|
+
if (p.type === "text") return { text: p.text };
|
|
980
|
+
if (p.type === "image_url") return geminiMediaPart(p.image_url);
|
|
981
|
+
return null;
|
|
982
|
+
}).filter((p) => p !== null);
|
|
983
|
+
result.push({ role: "user", parts: geminiParts });
|
|
984
|
+
continue;
|
|
985
|
+
}
|
|
937
986
|
const text = typeof msg.content === "string" ? msg.content : (msg.content ?? []).filter((p) => p.type === "text").map((p) => p.text).join("\n");
|
|
938
987
|
result.push({ role: "user", parts: [{ text }] });
|
|
939
988
|
continue;
|
|
@@ -1100,6 +1149,6 @@ async function compress(messages, options = {}) {
|
|
|
1100
1149
|
return finalResult;
|
|
1101
1150
|
}
|
|
1102
1151
|
|
|
1103
|
-
export { CacheError, CompressionHooks, ConfigurationError, HeadroomAuthError, HeadroomClient, HeadroomCompressError, HeadroomConnectionError, HeadroomError, ProviderError, StorageError, TokenizationError, TransformError, ValidationError, __require, camelToSnake, collectStream, compress, countTurns, deepCamelCase, deepSnakeCase, detectFormat, extractToolCalls, extractUserQuery, fromOpenAI, mapProxyError, openAIToVercel, parseSSE, snakeToCamel, toOpenAI, vercelToOpenAI };
|
|
1104
|
-
//# sourceMappingURL=chunk-
|
|
1105
|
-
//# sourceMappingURL=chunk-
|
|
1152
|
+
export { CacheError, CompressionHooks, ConfigurationError, HeadroomAuthError, HeadroomClient, HeadroomCompressError, HeadroomConnectionError, HeadroomError, ProviderError, StorageError, TokenizationError, TransformError, ValidationError, __require, anthropicToOpenAI, camelToSnake, collectStream, compress, countTurns, deepCamelCase, deepSnakeCase, detectFormat, extractToolCalls, extractUserQuery, fromOpenAI, mapProxyError, openAIToAnthropic, openAIToVercel, parseSSE, snakeToCamel, toOpenAI, vercelToOpenAI };
|
|
1153
|
+
//# sourceMappingURL=chunk-FJQ65W3R.js.map
|
|
1154
|
+
//# sourceMappingURL=chunk-FJQ65W3R.js.map
|