headroom-ai 0.1.0 → 0.22.4
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/README.md +300 -14
- package/dist/adapters/anthropic.cjs +6 -2
- package/dist/adapters/anthropic.cjs.map +1 -1
- package/dist/adapters/anthropic.d.cts +1 -1
- package/dist/adapters/anthropic.d.ts +1 -1
- package/dist/adapters/anthropic.js +6 -2
- package/dist/adapters/anthropic.js.map +1 -1
- package/dist/adapters/gemini.cjs +41 -0
- package/dist/adapters/gemini.cjs.map +1 -0
- package/dist/adapters/gemini.d.cts +31 -0
- package/dist/adapters/gemini.d.ts +31 -0
- package/dist/adapters/gemini.js +39 -0
- package/dist/adapters/gemini.js.map +1 -0
- package/dist/adapters/openai.cjs +6 -2
- package/dist/adapters/openai.cjs.map +1 -1
- package/dist/adapters/openai.d.cts +1 -1
- package/dist/adapters/openai.d.ts +1 -1
- package/dist/adapters/openai.js +6 -2
- package/dist/adapters/openai.js.map +1 -1
- package/dist/adapters/vercel-ai.cjs +33 -8
- package/dist/adapters/vercel-ai.cjs.map +1 -1
- package/dist/adapters/vercel-ai.d.cts +30 -2
- package/dist/adapters/vercel-ai.d.ts +30 -2
- package/dist/adapters/vercel-ai.js +28 -5
- package/dist/adapters/vercel-ai.js.map +1 -1
- package/dist/chunk-7AJIWIPP.js +1108 -0
- package/dist/chunk-7AJIWIPP.js.map +1 -0
- package/dist/chunk-R6FB52AD.cjs +1139 -0
- package/dist/chunk-R6FB52AD.cjs.map +1 -0
- package/dist/index.cjs +430 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +797 -18
- package/dist/index.d.ts +797 -18
- package/dist/index.js +326 -1
- package/dist/index.js.map +1 -1
- package/dist/types-BTrX7__W.d.cts +149 -0
- package/dist/types-BTrX7__W.d.ts +149 -0
- package/package.json +12 -2
- package/dist/chunk-3N25JEWK.cjs +0 -538
- package/dist/chunk-3N25JEWK.cjs.map +0 -1
- package/dist/chunk-YTTW7S2Q.js +0 -526
- package/dist/chunk-YTTW7S2Q.js.map +0 -1
- package/dist/types-DQtcLXq3.d.cts +0 -87
- package/dist/types-DQtcLXq3.d.ts +0 -87
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { compress } from '../chunk-7AJIWIPP.js';
|
|
2
|
+
|
|
3
|
+
// src/adapters/gemini.ts
|
|
4
|
+
function withHeadroom(model, options = {}) {
|
|
5
|
+
const originalGenerate = model.generateContent.bind(model);
|
|
6
|
+
const originalStream = model.generateContentStream?.bind(model);
|
|
7
|
+
const compressedGenerate = async (params) => {
|
|
8
|
+
const contents = params.contents ?? params;
|
|
9
|
+
const modelName = options.model ?? "gemini-2.0-flash";
|
|
10
|
+
const result = await compress(
|
|
11
|
+
Array.isArray(contents) ? contents : [contents],
|
|
12
|
+
{ stack: "adapter_ts_gemini", ...options, model: modelName }
|
|
13
|
+
);
|
|
14
|
+
const newParams = Array.isArray(params) ? result.messages : { ...params, contents: result.messages };
|
|
15
|
+
return originalGenerate(newParams);
|
|
16
|
+
};
|
|
17
|
+
const compressedStream = originalStream ? async (params) => {
|
|
18
|
+
const contents = params.contents ?? params;
|
|
19
|
+
const modelName = options.model ?? "gemini-2.0-flash";
|
|
20
|
+
const result = await compress(
|
|
21
|
+
Array.isArray(contents) ? contents : [contents],
|
|
22
|
+
{ stack: "adapter_ts_gemini", ...options, model: modelName }
|
|
23
|
+
);
|
|
24
|
+
const newParams = Array.isArray(params) ? result.messages : { ...params, contents: result.messages };
|
|
25
|
+
return originalStream(newParams);
|
|
26
|
+
} : void 0;
|
|
27
|
+
return new Proxy(model, {
|
|
28
|
+
get(target, prop) {
|
|
29
|
+
if (prop === "generateContent") return compressedGenerate;
|
|
30
|
+
if (prop === "generateContentStream" && compressedStream)
|
|
31
|
+
return compressedStream;
|
|
32
|
+
return target[prop];
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export { withHeadroom };
|
|
38
|
+
//# sourceMappingURL=gemini.js.map
|
|
39
|
+
//# sourceMappingURL=gemini.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/adapters/gemini.ts"],"names":[],"mappings":";;;AAgCO,SAAS,YAAA,CACd,KAAA,EACA,OAAA,GAA2B,EAAC,EACzB;AACH,EAAA,MAAM,gBAAA,GAAmB,KAAA,CAAM,eAAA,CAAgB,IAAA,CAAK,KAAK,CAAA;AACzD,EAAA,MAAM,cAAA,GAAiB,KAAA,CAAM,qBAAA,EAAuB,IAAA,CAAK,KAAK,CAAA;AAE9D,EAAA,MAAM,kBAAA,GAAqB,OAAO,MAAA,KAAgB;AAChD,IAAA,MAAM,QAAA,GAAW,OAAO,QAAA,IAAY,MAAA;AACpC,IAAA,MAAM,SAAA,GAAY,QAAQ,KAAA,IAAS,kBAAA;AAGnC,IAAA,MAAM,SAAS,MAAM,QAAA;AAAA,MACnB,MAAM,OAAA,CAAQ,QAAQ,CAAA,GAAI,QAAA,GAAW,CAAC,QAAQ,CAAA;AAAA,MAC9C,EAAE,KAAA,EAAO,mBAAA,EAAqB,GAAG,OAAA,EAAS,OAAO,SAAA;AAAU,KAC7D;AAEA,IAAA,MAAM,SAAA,GAAY,KAAA,CAAM,OAAA,CAAQ,MAAM,CAAA,GAClC,MAAA,CAAO,QAAA,GACP,EAAE,GAAG,MAAA,EAAQ,QAAA,EAAU,MAAA,CAAO,QAAA,EAAS;AAE3C,IAAA,OAAO,iBAAiB,SAAS,CAAA;AAAA,EACnC,CAAA;AAEA,EAAA,MAAM,gBAAA,GAAmB,cAAA,GACrB,OAAO,MAAA,KAAgB;AACrB,IAAA,MAAM,QAAA,GAAW,OAAO,QAAA,IAAY,MAAA;AACpC,IAAA,MAAM,SAAA,GAAY,QAAQ,KAAA,IAAS,kBAAA;AAEnC,IAAA,MAAM,SAAS,MAAM,QAAA;AAAA,MACnB,MAAM,OAAA,CAAQ,QAAQ,CAAA,GAAI,QAAA,GAAW,CAAC,QAAQ,CAAA;AAAA,MAC9C,EAAE,KAAA,EAAO,mBAAA,EAAqB,GAAG,OAAA,EAAS,OAAO,SAAA;AAAU,KAC7D;AAEA,IAAA,MAAM,SAAA,GAAY,KAAA,CAAM,OAAA,CAAQ,MAAM,CAAA,GAClC,MAAA,CAAO,QAAA,GACP,EAAE,GAAG,MAAA,EAAQ,QAAA,EAAU,MAAA,CAAO,QAAA,EAAS;AAE3C,IAAA,OAAO,eAAe,SAAS,CAAA;AAAA,EACjC,CAAA,GACA,MAAA;AAEJ,EAAA,OAAO,IAAI,MAAM,KAAA,EAAO;AAAA,IACtB,GAAA,CAAI,QAAQ,IAAA,EAAM;AAChB,MAAA,IAAI,IAAA,KAAS,mBAAmB,OAAO,kBAAA;AACvC,MAAA,IAAI,SAAS,uBAAA,IAA2B,gBAAA;AACtC,QAAA,OAAO,gBAAA;AACT,MAAA,OAAQ,OAAe,IAAI,CAAA;AAAA,IAC7B;AAAA,GACD,CAAA;AACH","file":"gemini.js","sourcesContent":["/**\n * Gemini adapter — wraps Google Generative AI model with auto-compression.\n * Matches the pattern of openai.ts and anthropic.ts adapters.\n */\n\nimport { compress } from \"../compress.js\";\nimport type { CompressOptions } from \"../types.js\";\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\ninterface GeminiModelLike {\n generateContent: (params: any) => any;\n generateContentStream?: (params: any) => any;\n [key: string]: any;\n}\n\n/**\n * Wrap a Google Generative AI model to auto-compress before each request.\n *\n * Intercepts `model.generateContent()` and `model.generateContentStream()`.\n *\n * @example\n * ```typescript\n * import { withHeadroom } from 'headroom-ai/gemini';\n * import { GoogleGenerativeAI } from '@google/generative-ai';\n *\n * const genAI = new GoogleGenerativeAI(process.env.GEMINI_API_KEY!);\n * const model = withHeadroom(genAI.getGenerativeModel({ model: 'gemini-2.0-flash' }));\n *\n * const result = await model.generateContent({ contents: longConversation });\n * ```\n */\nexport function withHeadroom<T extends GeminiModelLike>(\n model: T,\n options: CompressOptions = {},\n): T {\n const originalGenerate = model.generateContent.bind(model);\n const originalStream = model.generateContentStream?.bind(model);\n\n const compressedGenerate = async (params: any) => {\n const contents = params.contents ?? params;\n const modelName = options.model ?? \"gemini-2.0-flash\";\n\n // compress() auto-detects Gemini format\n const result = await compress(\n Array.isArray(contents) ? contents : [contents],\n { stack: \"adapter_ts_gemini\", ...options, model: modelName },\n );\n\n const newParams = Array.isArray(params)\n ? result.messages\n : { ...params, contents: result.messages };\n\n return originalGenerate(newParams);\n };\n\n const compressedStream = originalStream\n ? async (params: any) => {\n const contents = params.contents ?? params;\n const modelName = options.model ?? \"gemini-2.0-flash\";\n\n const result = await compress(\n Array.isArray(contents) ? contents : [contents],\n { stack: \"adapter_ts_gemini\", ...options, model: modelName },\n );\n\n const newParams = Array.isArray(params)\n ? result.messages\n : { ...params, contents: result.messages };\n\n return originalStream(newParams);\n }\n : undefined;\n\n return new Proxy(model, {\n get(target, prop) {\n if (prop === \"generateContent\") return compressedGenerate;\n if (prop === \"generateContentStream\" && compressedStream)\n return compressedStream;\n return (target as any)[prop];\n },\n }) as T;\n}\n"]}
|
package/dist/adapters/openai.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkR6FB52AD_cjs = require('../chunk-R6FB52AD.cjs');
|
|
4
4
|
|
|
5
5
|
// src/adapters/openai.ts
|
|
6
6
|
function withHeadroom(client, options = {}) {
|
|
@@ -10,7 +10,11 @@ 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 chunkR6FB52AD_cjs.compress(messages, {
|
|
14
|
+
stack: "adapter_ts_openai",
|
|
15
|
+
...options,
|
|
16
|
+
model
|
|
17
|
+
});
|
|
14
18
|
return originalCreate({
|
|
15
19
|
...params,
|
|
16
20
|
messages: result.messages
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/adapters/openai.ts"],"names":["compress"],"mappings":";;;;;AAgCO,SAAS,YAAA,CACd,MAAA,EACA,OAAA,GAA2B,EAAC,EACzB;AACH,EAAA,MAAM,cAAA,GAAiB,MAAA,CAAO,IAAA,CAAK,WAAA,CAAY,MAAA,CAAO,IAAA;AAAA,IACpD,OAAO,IAAA,CAAK;AAAA,GACd;AAEA,EAAA,MAAM,gBAAA,GAAmB,OAAO,MAAA,KAAgB;AAC9C,IAAA,MAAM,WAA4B,MAAA,CAAO,QAAA;AACzC,IAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,KAAA,IAAS,MAAA,CAAO,KAAA,IAAS,QAAA;AAE/C,IAAA,MAAM,MAAA,GAAS,MAAMA,0BAAA,CAAS,QAAA,EAAU,
|
|
1
|
+
{"version":3,"sources":["../../src/adapters/openai.ts"],"names":["compress"],"mappings":";;;;;AAgCO,SAAS,YAAA,CACd,MAAA,EACA,OAAA,GAA2B,EAAC,EACzB;AACH,EAAA,MAAM,cAAA,GAAiB,MAAA,CAAO,IAAA,CAAK,WAAA,CAAY,MAAA,CAAO,IAAA;AAAA,IACpD,OAAO,IAAA,CAAK;AAAA,GACd;AAEA,EAAA,MAAM,gBAAA,GAAmB,OAAO,MAAA,KAAgB;AAC9C,IAAA,MAAM,WAA4B,MAAA,CAAO,QAAA;AACzC,IAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,KAAA,IAAS,MAAA,CAAO,KAAA,IAAS,QAAA;AAE/C,IAAA,MAAM,MAAA,GAAS,MAAMA,0BAAA,CAAS,QAAA,EAAU;AAAA,MACtC,KAAA,EAAO,mBAAA;AAAA,MACP,GAAG,OAAA;AAAA,MACH;AAAA,KACD,CAAA;AAED,IAAA,OAAO,cAAA,CAAe;AAAA,MACpB,GAAG,MAAA;AAAA,MACH,UAAU,MAAA,CAAO;AAAA,KAClB,CAAA;AAAA,EACH,CAAA;AAEA,EAAA,MAAM,gBAAA,GAAmB,IAAI,KAAA,CAAM,MAAA,CAAO,KAAK,WAAA,EAAa;AAAA,IAC1D,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,MAAM,SAAA,GAAY,IAAI,KAAA,CAAM,MAAA,CAAO,IAAA,EAAM;AAAA,IACvC,GAAA,CAAI,QAAQ,IAAA,EAAM;AAChB,MAAA,IAAI,IAAA,KAAS,eAAe,OAAO,gBAAA;AACnC,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,QAAQ,OAAO,SAAA;AAC5B,MAAA,OAAQ,OAAe,IAAI,CAAA;AAAA,IAC7B;AAAA,GACD,CAAA;AACH","file":"openai.cjs","sourcesContent":["import { compress } from \"../compress.js\";\nimport type { CompressOptions, OpenAIMessage } from \"../types.js\";\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\ninterface OpenAILike {\n chat: {\n completions: {\n create: (params: any) => any;\n };\n };\n [key: string]: any;\n}\n\n/**\n * Wrap an OpenAI client to auto-compress messages before each request.\n *\n * Intercepts `client.chat.completions.create()` only. All other methods\n * (embeddings, images, audio, etc.) pass through unchanged.\n *\n * @example\n * ```typescript\n * import { withHeadroom } from 'headroom-ai/openai';\n * import OpenAI from 'openai';\n *\n * const client = withHeadroom(new OpenAI());\n * const response = await client.chat.completions.create({\n * model: 'gpt-4o',\n * messages: longConversation,\n * });\n * ```\n */\nexport function withHeadroom<T extends OpenAILike>(\n client: T,\n options: CompressOptions = {},\n): T {\n const originalCreate = client.chat.completions.create.bind(\n client.chat.completions,\n );\n\n const compressedCreate = async (params: any) => {\n const messages: OpenAIMessage[] = params.messages;\n const model = options.model ?? params.model ?? \"gpt-4o\";\n\n const result = await compress(messages, {\n stack: \"adapter_ts_openai\",\n ...options,\n model,\n });\n\n return originalCreate({\n ...params,\n messages: result.messages,\n });\n };\n\n const completionsProxy = new Proxy(client.chat.completions, {\n get(target, prop) {\n if (prop === \"create\") return compressedCreate;\n return (target as any)[prop];\n },\n });\n\n const chatProxy = new Proxy(client.chat, {\n get(target, prop) {\n if (prop === \"completions\") return completionsProxy;\n return (target as any)[prop];\n },\n });\n\n return new Proxy(client, {\n get(target, prop) {\n if (prop === \"chat\") return chatProxy;\n return (target as any)[prop];\n },\n }) as T;\n}\n"]}
|
package/dist/adapters/openai.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { compress } from '../chunk-
|
|
1
|
+
import { compress } from '../chunk-7AJIWIPP.js';
|
|
2
2
|
|
|
3
3
|
// src/adapters/openai.ts
|
|
4
4
|
function withHeadroom(client, options = {}) {
|
|
@@ -8,7 +8,11 @@ function withHeadroom(client, options = {}) {
|
|
|
8
8
|
const compressedCreate = async (params) => {
|
|
9
9
|
const messages = params.messages;
|
|
10
10
|
const model = options.model ?? params.model ?? "gpt-4o";
|
|
11
|
-
const result = await compress(messages, {
|
|
11
|
+
const result = await compress(messages, {
|
|
12
|
+
stack: "adapter_ts_openai",
|
|
13
|
+
...options,
|
|
14
|
+
model
|
|
15
|
+
});
|
|
12
16
|
return originalCreate({
|
|
13
17
|
...params,
|
|
14
18
|
messages: result.messages
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/adapters/openai.ts"],"names":[],"mappings":";;;AAgCO,SAAS,YAAA,CACd,MAAA,EACA,OAAA,GAA2B,EAAC,EACzB;AACH,EAAA,MAAM,cAAA,GAAiB,MAAA,CAAO,IAAA,CAAK,WAAA,CAAY,MAAA,CAAO,IAAA;AAAA,IACpD,OAAO,IAAA,CAAK;AAAA,GACd;AAEA,EAAA,MAAM,gBAAA,GAAmB,OAAO,MAAA,KAAgB;AAC9C,IAAA,MAAM,WAA4B,MAAA,CAAO,QAAA;AACzC,IAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,KAAA,IAAS,MAAA,CAAO,KAAA,IAAS,QAAA;AAE/C,IAAA,MAAM,MAAA,GAAS,MAAM,QAAA,CAAS,QAAA,EAAU,
|
|
1
|
+
{"version":3,"sources":["../../src/adapters/openai.ts"],"names":[],"mappings":";;;AAgCO,SAAS,YAAA,CACd,MAAA,EACA,OAAA,GAA2B,EAAC,EACzB;AACH,EAAA,MAAM,cAAA,GAAiB,MAAA,CAAO,IAAA,CAAK,WAAA,CAAY,MAAA,CAAO,IAAA;AAAA,IACpD,OAAO,IAAA,CAAK;AAAA,GACd;AAEA,EAAA,MAAM,gBAAA,GAAmB,OAAO,MAAA,KAAgB;AAC9C,IAAA,MAAM,WAA4B,MAAA,CAAO,QAAA;AACzC,IAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,KAAA,IAAS,MAAA,CAAO,KAAA,IAAS,QAAA;AAE/C,IAAA,MAAM,MAAA,GAAS,MAAM,QAAA,CAAS,QAAA,EAAU;AAAA,MACtC,KAAA,EAAO,mBAAA;AAAA,MACP,GAAG,OAAA;AAAA,MACH;AAAA,KACD,CAAA;AAED,IAAA,OAAO,cAAA,CAAe;AAAA,MACpB,GAAG,MAAA;AAAA,MACH,UAAU,MAAA,CAAO;AAAA,KAClB,CAAA;AAAA,EACH,CAAA;AAEA,EAAA,MAAM,gBAAA,GAAmB,IAAI,KAAA,CAAM,MAAA,CAAO,KAAK,WAAA,EAAa;AAAA,IAC1D,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,MAAM,SAAA,GAAY,IAAI,KAAA,CAAM,MAAA,CAAO,IAAA,EAAM;AAAA,IACvC,GAAA,CAAI,QAAQ,IAAA,EAAM;AAChB,MAAA,IAAI,IAAA,KAAS,eAAe,OAAO,gBAAA;AACnC,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,QAAQ,OAAO,SAAA;AAC5B,MAAA,OAAQ,OAAe,IAAI,CAAA;AAAA,IAC7B;AAAA,GACD,CAAA;AACH","file":"openai.js","sourcesContent":["import { compress } from \"../compress.js\";\nimport type { CompressOptions, OpenAIMessage } from \"../types.js\";\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\ninterface OpenAILike {\n chat: {\n completions: {\n create: (params: any) => any;\n };\n };\n [key: string]: any;\n}\n\n/**\n * Wrap an OpenAI client to auto-compress messages before each request.\n *\n * Intercepts `client.chat.completions.create()` only. All other methods\n * (embeddings, images, audio, etc.) pass through unchanged.\n *\n * @example\n * ```typescript\n * import { withHeadroom } from 'headroom-ai/openai';\n * import OpenAI from 'openai';\n *\n * const client = withHeadroom(new OpenAI());\n * const response = await client.chat.completions.create({\n * model: 'gpt-4o',\n * messages: longConversation,\n * });\n * ```\n */\nexport function withHeadroom<T extends OpenAILike>(\n client: T,\n options: CompressOptions = {},\n): T {\n const originalCreate = client.chat.completions.create.bind(\n client.chat.completions,\n );\n\n const compressedCreate = async (params: any) => {\n const messages: OpenAIMessage[] = params.messages;\n const model = options.model ?? params.model ?? \"gpt-4o\";\n\n const result = await compress(messages, {\n stack: \"adapter_ts_openai\",\n ...options,\n model,\n });\n\n return originalCreate({\n ...params,\n messages: result.messages,\n });\n };\n\n const completionsProxy = new Proxy(client.chat.completions, {\n get(target, prop) {\n if (prop === \"create\") return compressedCreate;\n return (target as any)[prop];\n },\n });\n\n const chatProxy = new Proxy(client.chat, {\n get(target, prop) {\n if (prop === \"completions\") return completionsProxy;\n return (target as any)[prop];\n },\n });\n\n return new Proxy(client, {\n get(target, prop) {\n if (prop === \"chat\") return chatProxy;\n return (target as any)[prop];\n },\n }) as T;\n}\n"]}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkR6FB52AD_cjs = require('../chunk-R6FB52AD.cjs');
|
|
4
|
+
var module$1 = require('module');
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
6
7
|
function headroomMiddleware(options = {}) {
|
|
7
8
|
return {
|
|
8
9
|
transformParams: async ({
|
|
@@ -11,25 +12,49 @@ function headroomMiddleware(options = {}) {
|
|
|
11
12
|
const prompt = params.prompt;
|
|
12
13
|
if (!prompt || prompt.length === 0) return params;
|
|
13
14
|
const model = options.model ?? params.modelId ?? "gpt-4o";
|
|
14
|
-
const openaiMessages =
|
|
15
|
-
const result = await
|
|
15
|
+
const openaiMessages = chunkR6FB52AD_cjs.vercelToOpenAI(prompt);
|
|
16
|
+
const result = await chunkR6FB52AD_cjs.compress(openaiMessages, {
|
|
17
|
+
stack: "adapter_ts_vercel_ai",
|
|
18
|
+
...options,
|
|
19
|
+
model
|
|
20
|
+
});
|
|
16
21
|
if (!result.compressed) return params;
|
|
17
|
-
const compressedPrompt =
|
|
22
|
+
const compressedPrompt = chunkR6FB52AD_cjs.openAIToVercel(result.messages);
|
|
18
23
|
return { ...params, prompt: compressedPrompt };
|
|
19
24
|
}
|
|
20
25
|
};
|
|
21
26
|
}
|
|
22
27
|
async function compressVercelMessages(messages, options = {}) {
|
|
23
|
-
const openaiMessages =
|
|
24
|
-
const result = await
|
|
25
|
-
|
|
28
|
+
const openaiMessages = chunkR6FB52AD_cjs.vercelToOpenAI(messages);
|
|
29
|
+
const result = await chunkR6FB52AD_cjs.compress(openaiMessages, {
|
|
30
|
+
stack: "adapter_ts_vercel_ai",
|
|
31
|
+
...options
|
|
32
|
+
});
|
|
33
|
+
const vercelMessages = chunkR6FB52AD_cjs.openAIToVercel(result.messages);
|
|
26
34
|
return {
|
|
27
35
|
...result,
|
|
28
36
|
messages: vercelMessages
|
|
29
37
|
};
|
|
30
38
|
}
|
|
39
|
+
function withHeadroom(model, options = {}) {
|
|
40
|
+
let wrapLanguageModel;
|
|
41
|
+
try {
|
|
42
|
+
const require2 = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('vercel-ai.cjs', document.baseURI).href)));
|
|
43
|
+
const ai = require2("ai");
|
|
44
|
+
wrapLanguageModel = ai.wrapLanguageModel;
|
|
45
|
+
} catch {
|
|
46
|
+
throw new Error(
|
|
47
|
+
'withHeadroom() requires the "ai" package. Install it with: npm install ai'
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
return wrapLanguageModel({
|
|
51
|
+
model,
|
|
52
|
+
middleware: headroomMiddleware(options)
|
|
53
|
+
});
|
|
54
|
+
}
|
|
31
55
|
|
|
32
56
|
exports.compressVercelMessages = compressVercelMessages;
|
|
33
57
|
exports.headroomMiddleware = headroomMiddleware;
|
|
58
|
+
exports.withHeadroom = withHeadroom;
|
|
34
59
|
//# sourceMappingURL=vercel-ai.cjs.map
|
|
35
60
|
//# sourceMappingURL=vercel-ai.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/adapters/vercel-ai.ts"],"names":["vercelToOpenAI","compress","openAIToVercel"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../src/adapters/vercel-ai.ts"],"names":["vercelToOpenAI","compress","openAIToVercel","require","createRequire"],"mappings":";;;;;;AAsCO,SAAS,kBAAA,CAAmB,OAAA,GAA2B,EAAC,EAAG;AAChE,EAAA,OAAO;AAAA,IACL,iBAAiB,OAAO;AAAA,MACtB;AAAA,KACF,KAIM;AACJ,MAAA,MAAM,SAA0B,MAAA,CAAO,MAAA;AACvC,MAAA,IAAI,CAAC,MAAA,IAAU,MAAA,CAAO,MAAA,KAAW,GAAG,OAAO,MAAA;AAE3C,MAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,KAAA,IAAS,MAAA,CAAO,OAAA,IAAW,QAAA;AAGjD,MAAA,MAAM,cAAA,GAAiBA,iCAAe,MAAM,CAAA;AAG5C,MAAA,MAAM,MAAA,GAAS,MAAMC,0BAAA,CAAS,cAAA,EAAgB;AAAA,QAC5C,KAAA,EAAO,sBAAA;AAAA,QACP,GAAG,OAAA;AAAA,QACH;AAAA,OACD,CAAA;AAED,MAAA,IAAI,CAAC,MAAA,CAAO,UAAA,EAAY,OAAO,MAAA;AAG/B,MAAA,MAAM,gBAAA,GAAmBC,gCAAA,CAAe,MAAA,CAAO,QAAQ,CAAA;AAEvD,MAAA,OAAO,EAAE,GAAG,MAAA,EAAQ,MAAA,EAAQ,gBAAA,EAAiB;AAAA,IAC/C;AAAA,GACF;AACF;AAMA,eAAsB,sBAAA,CACpB,QAAA,EACA,OAAA,GAA2B,EAAC,EAC6B;AACzD,EAAA,MAAM,cAAA,GAAiBF,iCAAe,QAAQ,CAAA;AAC9C,EAAA,MAAM,MAAA,GAAS,MAAMC,0BAAA,CAAS,cAAA,EAAgB;AAAA,IAC5C,KAAA,EAAO,sBAAA;AAAA,IACP,GAAG;AAAA,GACJ,CAAA;AACD,EAAA,MAAM,cAAA,GAAiBC,gCAAA,CAAe,MAAA,CAAO,QAAQ,CAAA;AAErD,EAAA,OAAO;AAAA,IACL,GAAG,MAAA;AAAA,IACH,QAAA,EAAU;AAAA,GACZ;AACF;AAgBO,SAAS,YAAA,CACd,KAAA,EACA,OAAA,GAA2B,EAAC,EACzB;AACH,EAAA,IAAI,iBAAA;AAKJ,EAAA,IAAI;AACF,IAAA,MAAMC,QAAAA,GAAUC,sBAAA,CAAc,+PAAe,CAAA;AAC7C,IAAA,MAAM,EAAA,GAAKD,SAAQ,IAAI,CAAA;AACvB,IAAA,iBAAA,GAAoB,EAAA,CAAG,iBAAA;AAAA,EACzB,CAAA,CAAA,MAAQ;AACN,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KACF;AAAA,EACF;AAEA,EAAA,OAAO,iBAAA,CAAkB;AAAA,IACvB,KAAA;AAAA,IACA,UAAA,EAAY,mBAAmB,OAAO;AAAA,GACvC,CAAA;AACH","file":"vercel-ai.cjs","sourcesContent":["import { createRequire } from \"node:module\";\nimport { compress } from \"../compress.js\";\nimport type { CompressOptions, CompressResult } from \"../types.js\";\nimport { vercelToOpenAI, openAIToVercel } from \"../utils/format.js\";\n\n/**\n * Minimal structural type for Vercel AI SDK language models.\n * Compatible with both LanguageModelV1 (@ai-sdk/provider <=1.x)\n * and LanguageModelV3 (@ai-sdk/provider >=2.x).\n */\ninterface LanguageModel {\n readonly specificationVersion: string;\n readonly provider: string;\n readonly modelId: string;\n doGenerate: (...args: any[]) => any;\n doStream: (...args: any[]) => any;\n [key: string]: any;\n}\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\ntype VercelMessage = any;\n\n/**\n * Vercel AI SDK LanguageModelV3Middleware that compresses messages\n * before they reach the LLM.\n *\n * @example\n * ```typescript\n * import { headroomMiddleware } from 'headroom-ai/vercel-ai';\n * import { wrapLanguageModel } from 'ai';\n * import { openai } from '@ai-sdk/openai';\n *\n * const model = wrapLanguageModel({\n * model: openai('gpt-4o'),\n * middleware: headroomMiddleware(),\n * });\n * ```\n */\nexport function headroomMiddleware(options: CompressOptions = {}) {\n return {\n transformParams: async ({\n params,\n }: {\n params: any;\n model: any;\n type: string;\n }) => {\n const prompt: VercelMessage[] = params.prompt;\n if (!prompt || prompt.length === 0) return params;\n\n const model = options.model ?? params.modelId ?? \"gpt-4o\";\n\n // Convert Vercel format → OpenAI format\n const openaiMessages = vercelToOpenAI(prompt);\n\n // Compress via Headroom\n const result = await compress(openaiMessages, {\n stack: \"adapter_ts_vercel_ai\",\n ...options,\n model,\n });\n\n if (!result.compressed) return params;\n\n // Convert back to Vercel format\n const compressedPrompt = openAIToVercel(result.messages);\n\n return { ...params, prompt: compressedPrompt };\n },\n };\n}\n\n/**\n * Standalone: compress Vercel AI SDK ModelMessage[] directly.\n * Returns compressed messages in Vercel format + compression stats.\n */\nexport async function compressVercelMessages(\n messages: VercelMessage[],\n options: CompressOptions = {},\n): Promise<CompressResult & { messages: VercelMessage[] }> {\n const openaiMessages = vercelToOpenAI(messages);\n const result = await compress(openaiMessages, {\n stack: \"adapter_ts_vercel_ai\",\n ...options,\n });\n const vercelMessages = openAIToVercel(result.messages);\n\n return {\n ...result,\n messages: vercelMessages,\n };\n}\n\n/**\n * Wrap a Vercel AI SDK language model with Headroom compression.\n * Convenience wrapper around `wrapLanguageModel` + `headroomMiddleware`.\n *\n * @example\n * ```typescript\n * import { withHeadroom } from 'headroom-ai/vercel-ai';\n * import { openai } from '@ai-sdk/openai';\n * import { generateText } from 'ai';\n *\n * const model = withHeadroom(openai('gpt-4o'));\n * const { text } = await generateText({ model, messages });\n * ```\n */\nexport function withHeadroom<T extends LanguageModel>(\n model: T,\n options: CompressOptions = {},\n): T {\n let wrapLanguageModel: (opts: {\n model: T;\n middleware: any;\n }) => T;\n\n try {\n const require = createRequire(import.meta.url);\n const ai = require(\"ai\");\n wrapLanguageModel = ai.wrapLanguageModel;\n } catch {\n throw new Error(\n 'withHeadroom() requires the \"ai\" package. Install it with: npm install ai',\n );\n }\n\n return wrapLanguageModel({\n model,\n middleware: headroomMiddleware(options),\n });\n}\n"]}
|
|
@@ -1,5 +1,18 @@
|
|
|
1
|
-
import { C as CompressOptions, a as CompressResult } from '../types-
|
|
1
|
+
import { C as CompressOptions, a as CompressResult } from '../types-BTrX7__W.cjs';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Minimal structural type for Vercel AI SDK language models.
|
|
5
|
+
* Compatible with both LanguageModelV1 (@ai-sdk/provider <=1.x)
|
|
6
|
+
* and LanguageModelV3 (@ai-sdk/provider >=2.x).
|
|
7
|
+
*/
|
|
8
|
+
interface LanguageModel {
|
|
9
|
+
readonly specificationVersion: string;
|
|
10
|
+
readonly provider: string;
|
|
11
|
+
readonly modelId: string;
|
|
12
|
+
doGenerate: (...args: any[]) => any;
|
|
13
|
+
doStream: (...args: any[]) => any;
|
|
14
|
+
[key: string]: any;
|
|
15
|
+
}
|
|
3
16
|
type VercelMessage = any;
|
|
4
17
|
/**
|
|
5
18
|
* Vercel AI SDK LanguageModelV3Middleware that compresses messages
|
|
@@ -31,5 +44,20 @@ declare function headroomMiddleware(options?: CompressOptions): {
|
|
|
31
44
|
declare function compressVercelMessages(messages: VercelMessage[], options?: CompressOptions): Promise<CompressResult & {
|
|
32
45
|
messages: VercelMessage[];
|
|
33
46
|
}>;
|
|
47
|
+
/**
|
|
48
|
+
* Wrap a Vercel AI SDK language model with Headroom compression.
|
|
49
|
+
* Convenience wrapper around `wrapLanguageModel` + `headroomMiddleware`.
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```typescript
|
|
53
|
+
* import { withHeadroom } from 'headroom-ai/vercel-ai';
|
|
54
|
+
* import { openai } from '@ai-sdk/openai';
|
|
55
|
+
* import { generateText } from 'ai';
|
|
56
|
+
*
|
|
57
|
+
* const model = withHeadroom(openai('gpt-4o'));
|
|
58
|
+
* const { text } = await generateText({ model, messages });
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
declare function withHeadroom<T extends LanguageModel>(model: T, options?: CompressOptions): T;
|
|
34
62
|
|
|
35
|
-
export { compressVercelMessages, headroomMiddleware };
|
|
63
|
+
export { compressVercelMessages, headroomMiddleware, withHeadroom };
|
|
@@ -1,5 +1,18 @@
|
|
|
1
|
-
import { C as CompressOptions, a as CompressResult } from '../types-
|
|
1
|
+
import { C as CompressOptions, a as CompressResult } from '../types-BTrX7__W.js';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Minimal structural type for Vercel AI SDK language models.
|
|
5
|
+
* Compatible with both LanguageModelV1 (@ai-sdk/provider <=1.x)
|
|
6
|
+
* and LanguageModelV3 (@ai-sdk/provider >=2.x).
|
|
7
|
+
*/
|
|
8
|
+
interface LanguageModel {
|
|
9
|
+
readonly specificationVersion: string;
|
|
10
|
+
readonly provider: string;
|
|
11
|
+
readonly modelId: string;
|
|
12
|
+
doGenerate: (...args: any[]) => any;
|
|
13
|
+
doStream: (...args: any[]) => any;
|
|
14
|
+
[key: string]: any;
|
|
15
|
+
}
|
|
3
16
|
type VercelMessage = any;
|
|
4
17
|
/**
|
|
5
18
|
* Vercel AI SDK LanguageModelV3Middleware that compresses messages
|
|
@@ -31,5 +44,20 @@ declare function headroomMiddleware(options?: CompressOptions): {
|
|
|
31
44
|
declare function compressVercelMessages(messages: VercelMessage[], options?: CompressOptions): Promise<CompressResult & {
|
|
32
45
|
messages: VercelMessage[];
|
|
33
46
|
}>;
|
|
47
|
+
/**
|
|
48
|
+
* Wrap a Vercel AI SDK language model with Headroom compression.
|
|
49
|
+
* Convenience wrapper around `wrapLanguageModel` + `headroomMiddleware`.
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```typescript
|
|
53
|
+
* import { withHeadroom } from 'headroom-ai/vercel-ai';
|
|
54
|
+
* import { openai } from '@ai-sdk/openai';
|
|
55
|
+
* import { generateText } from 'ai';
|
|
56
|
+
*
|
|
57
|
+
* const model = withHeadroom(openai('gpt-4o'));
|
|
58
|
+
* const { text } = await generateText({ model, messages });
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
declare function withHeadroom<T extends LanguageModel>(model: T, options?: CompressOptions): T;
|
|
34
62
|
|
|
35
|
-
export { compressVercelMessages, headroomMiddleware };
|
|
63
|
+
export { compressVercelMessages, headroomMiddleware, withHeadroom };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { vercelToOpenAI, compress, openAIToVercel } from '../chunk-
|
|
1
|
+
import { vercelToOpenAI, compress, openAIToVercel } from '../chunk-7AJIWIPP.js';
|
|
2
|
+
import { createRequire } from 'module';
|
|
2
3
|
|
|
3
|
-
// src/adapters/vercel-ai.ts
|
|
4
4
|
function headroomMiddleware(options = {}) {
|
|
5
5
|
return {
|
|
6
6
|
transformParams: async ({
|
|
@@ -10,7 +10,11 @@ function headroomMiddleware(options = {}) {
|
|
|
10
10
|
if (!prompt || prompt.length === 0) return params;
|
|
11
11
|
const model = options.model ?? params.modelId ?? "gpt-4o";
|
|
12
12
|
const openaiMessages = vercelToOpenAI(prompt);
|
|
13
|
-
const result = await compress(openaiMessages, {
|
|
13
|
+
const result = await compress(openaiMessages, {
|
|
14
|
+
stack: "adapter_ts_vercel_ai",
|
|
15
|
+
...options,
|
|
16
|
+
model
|
|
17
|
+
});
|
|
14
18
|
if (!result.compressed) return params;
|
|
15
19
|
const compressedPrompt = openAIToVercel(result.messages);
|
|
16
20
|
return { ...params, prompt: compressedPrompt };
|
|
@@ -19,14 +23,33 @@ function headroomMiddleware(options = {}) {
|
|
|
19
23
|
}
|
|
20
24
|
async function compressVercelMessages(messages, options = {}) {
|
|
21
25
|
const openaiMessages = vercelToOpenAI(messages);
|
|
22
|
-
const result = await compress(openaiMessages,
|
|
26
|
+
const result = await compress(openaiMessages, {
|
|
27
|
+
stack: "adapter_ts_vercel_ai",
|
|
28
|
+
...options
|
|
29
|
+
});
|
|
23
30
|
const vercelMessages = openAIToVercel(result.messages);
|
|
24
31
|
return {
|
|
25
32
|
...result,
|
|
26
33
|
messages: vercelMessages
|
|
27
34
|
};
|
|
28
35
|
}
|
|
36
|
+
function withHeadroom(model, options = {}) {
|
|
37
|
+
let wrapLanguageModel;
|
|
38
|
+
try {
|
|
39
|
+
const require2 = createRequire(import.meta.url);
|
|
40
|
+
const ai = require2("ai");
|
|
41
|
+
wrapLanguageModel = ai.wrapLanguageModel;
|
|
42
|
+
} catch {
|
|
43
|
+
throw new Error(
|
|
44
|
+
'withHeadroom() requires the "ai" package. Install it with: npm install ai'
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
return wrapLanguageModel({
|
|
48
|
+
model,
|
|
49
|
+
middleware: headroomMiddleware(options)
|
|
50
|
+
});
|
|
51
|
+
}
|
|
29
52
|
|
|
30
|
-
export { compressVercelMessages, headroomMiddleware };
|
|
53
|
+
export { compressVercelMessages, headroomMiddleware, withHeadroom };
|
|
31
54
|
//# sourceMappingURL=vercel-ai.js.map
|
|
32
55
|
//# sourceMappingURL=vercel-ai.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/adapters/vercel-ai.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"sources":["../../src/adapters/vercel-ai.ts"],"names":["require"],"mappings":";;;AAsCO,SAAS,kBAAA,CAAmB,OAAA,GAA2B,EAAC,EAAG;AAChE,EAAA,OAAO;AAAA,IACL,iBAAiB,OAAO;AAAA,MACtB;AAAA,KACF,KAIM;AACJ,MAAA,MAAM,SAA0B,MAAA,CAAO,MAAA;AACvC,MAAA,IAAI,CAAC,MAAA,IAAU,MAAA,CAAO,MAAA,KAAW,GAAG,OAAO,MAAA;AAE3C,MAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,KAAA,IAAS,MAAA,CAAO,OAAA,IAAW,QAAA;AAGjD,MAAA,MAAM,cAAA,GAAiB,eAAe,MAAM,CAAA;AAG5C,MAAA,MAAM,MAAA,GAAS,MAAM,QAAA,CAAS,cAAA,EAAgB;AAAA,QAC5C,KAAA,EAAO,sBAAA;AAAA,QACP,GAAG,OAAA;AAAA,QACH;AAAA,OACD,CAAA;AAED,MAAA,IAAI,CAAC,MAAA,CAAO,UAAA,EAAY,OAAO,MAAA;AAG/B,MAAA,MAAM,gBAAA,GAAmB,cAAA,CAAe,MAAA,CAAO,QAAQ,CAAA;AAEvD,MAAA,OAAO,EAAE,GAAG,MAAA,EAAQ,MAAA,EAAQ,gBAAA,EAAiB;AAAA,IAC/C;AAAA,GACF;AACF;AAMA,eAAsB,sBAAA,CACpB,QAAA,EACA,OAAA,GAA2B,EAAC,EAC6B;AACzD,EAAA,MAAM,cAAA,GAAiB,eAAe,QAAQ,CAAA;AAC9C,EAAA,MAAM,MAAA,GAAS,MAAM,QAAA,CAAS,cAAA,EAAgB;AAAA,IAC5C,KAAA,EAAO,sBAAA;AAAA,IACP,GAAG;AAAA,GACJ,CAAA;AACD,EAAA,MAAM,cAAA,GAAiB,cAAA,CAAe,MAAA,CAAO,QAAQ,CAAA;AAErD,EAAA,OAAO;AAAA,IACL,GAAG,MAAA;AAAA,IACH,QAAA,EAAU;AAAA,GACZ;AACF;AAgBO,SAAS,YAAA,CACd,KAAA,EACA,OAAA,GAA2B,EAAC,EACzB;AACH,EAAA,IAAI,iBAAA;AAKJ,EAAA,IAAI;AACF,IAAA,MAAMA,QAAAA,GAAU,aAAA,CAAc,MAAA,CAAA,IAAA,CAAY,GAAG,CAAA;AAC7C,IAAA,MAAM,EAAA,GAAKA,SAAQ,IAAI,CAAA;AACvB,IAAA,iBAAA,GAAoB,EAAA,CAAG,iBAAA;AAAA,EACzB,CAAA,CAAA,MAAQ;AACN,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KACF;AAAA,EACF;AAEA,EAAA,OAAO,iBAAA,CAAkB;AAAA,IACvB,KAAA;AAAA,IACA,UAAA,EAAY,mBAAmB,OAAO;AAAA,GACvC,CAAA;AACH","file":"vercel-ai.js","sourcesContent":["import { createRequire } from \"node:module\";\nimport { compress } from \"../compress.js\";\nimport type { CompressOptions, CompressResult } from \"../types.js\";\nimport { vercelToOpenAI, openAIToVercel } from \"../utils/format.js\";\n\n/**\n * Minimal structural type for Vercel AI SDK language models.\n * Compatible with both LanguageModelV1 (@ai-sdk/provider <=1.x)\n * and LanguageModelV3 (@ai-sdk/provider >=2.x).\n */\ninterface LanguageModel {\n readonly specificationVersion: string;\n readonly provider: string;\n readonly modelId: string;\n doGenerate: (...args: any[]) => any;\n doStream: (...args: any[]) => any;\n [key: string]: any;\n}\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\ntype VercelMessage = any;\n\n/**\n * Vercel AI SDK LanguageModelV3Middleware that compresses messages\n * before they reach the LLM.\n *\n * @example\n * ```typescript\n * import { headroomMiddleware } from 'headroom-ai/vercel-ai';\n * import { wrapLanguageModel } from 'ai';\n * import { openai } from '@ai-sdk/openai';\n *\n * const model = wrapLanguageModel({\n * model: openai('gpt-4o'),\n * middleware: headroomMiddleware(),\n * });\n * ```\n */\nexport function headroomMiddleware(options: CompressOptions = {}) {\n return {\n transformParams: async ({\n params,\n }: {\n params: any;\n model: any;\n type: string;\n }) => {\n const prompt: VercelMessage[] = params.prompt;\n if (!prompt || prompt.length === 0) return params;\n\n const model = options.model ?? params.modelId ?? \"gpt-4o\";\n\n // Convert Vercel format → OpenAI format\n const openaiMessages = vercelToOpenAI(prompt);\n\n // Compress via Headroom\n const result = await compress(openaiMessages, {\n stack: \"adapter_ts_vercel_ai\",\n ...options,\n model,\n });\n\n if (!result.compressed) return params;\n\n // Convert back to Vercel format\n const compressedPrompt = openAIToVercel(result.messages);\n\n return { ...params, prompt: compressedPrompt };\n },\n };\n}\n\n/**\n * Standalone: compress Vercel AI SDK ModelMessage[] directly.\n * Returns compressed messages in Vercel format + compression stats.\n */\nexport async function compressVercelMessages(\n messages: VercelMessage[],\n options: CompressOptions = {},\n): Promise<CompressResult & { messages: VercelMessage[] }> {\n const openaiMessages = vercelToOpenAI(messages);\n const result = await compress(openaiMessages, {\n stack: \"adapter_ts_vercel_ai\",\n ...options,\n });\n const vercelMessages = openAIToVercel(result.messages);\n\n return {\n ...result,\n messages: vercelMessages,\n };\n}\n\n/**\n * Wrap a Vercel AI SDK language model with Headroom compression.\n * Convenience wrapper around `wrapLanguageModel` + `headroomMiddleware`.\n *\n * @example\n * ```typescript\n * import { withHeadroom } from 'headroom-ai/vercel-ai';\n * import { openai } from '@ai-sdk/openai';\n * import { generateText } from 'ai';\n *\n * const model = withHeadroom(openai('gpt-4o'));\n * const { text } = await generateText({ model, messages });\n * ```\n */\nexport function withHeadroom<T extends LanguageModel>(\n model: T,\n options: CompressOptions = {},\n): T {\n let wrapLanguageModel: (opts: {\n model: T;\n middleware: any;\n }) => T;\n\n try {\n const require = createRequire(import.meta.url);\n const ai = require(\"ai\");\n wrapLanguageModel = ai.wrapLanguageModel;\n } catch {\n throw new Error(\n 'withHeadroom() requires the \"ai\" package. Install it with: npm install ai',\n );\n }\n\n return wrapLanguageModel({\n model,\n middleware: headroomMiddleware(options),\n });\n}\n"]}
|