@opencompress/opencompress 1.4.0 → 1.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +114 -55
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
2
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
3
|
+
}) : x)(function(x) {
|
|
4
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
5
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
6
|
+
});
|
|
7
|
+
|
|
1
8
|
// src/index.ts
|
|
2
9
|
var VERSION = "1.0.0";
|
|
3
10
|
var DEFAULT_BASE_URL = "https://www.opencompress.ai/api";
|
|
@@ -17,48 +24,26 @@ var FALLBACK_MODELS = [
|
|
|
17
24
|
{ id: "deepseek/deepseek-chat-v3-0324", name: "DeepSeek V3", reasoning: false, input: ["text"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 8192 },
|
|
18
25
|
{ id: "deepseek/deepseek-reasoner", name: "DeepSeek Reasoner", reasoning: true, input: ["text"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 8192 }
|
|
19
26
|
];
|
|
20
|
-
function
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
function readExistingModels(api) {
|
|
28
|
+
const providers = api.config.models?.providers;
|
|
29
|
+
if (!providers) return null;
|
|
30
|
+
const seen = /* @__PURE__ */ new Set();
|
|
31
|
+
const models = [];
|
|
32
|
+
for (const [providerId, providerConfig] of Object.entries(providers)) {
|
|
33
|
+
if (providerId === "opencompress") continue;
|
|
34
|
+
const providerModels = providerConfig.models || [];
|
|
35
|
+
for (const m of providerModels) {
|
|
36
|
+
if (m.name?.includes("\u2192")) continue;
|
|
37
|
+
if (seen.has(m.id)) continue;
|
|
38
|
+
seen.add(m.id);
|
|
39
|
+
models.push({
|
|
40
|
+
...m,
|
|
41
|
+
// Zero out cost — billing handled by OpenCompress proxy
|
|
42
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }
|
|
43
|
+
});
|
|
29
44
|
}
|
|
30
|
-
return {
|
|
31
|
-
id: m.id,
|
|
32
|
-
name: m.id,
|
|
33
|
-
reasoning: isReasoning,
|
|
34
|
-
input: inputMods,
|
|
35
|
-
cost: {
|
|
36
|
-
input: promptPrice,
|
|
37
|
-
output: completionPrice,
|
|
38
|
-
cacheRead: 0,
|
|
39
|
-
cacheWrite: 0
|
|
40
|
-
},
|
|
41
|
-
contextWindow: m.context_length || 128e3,
|
|
42
|
-
maxTokens: Math.min(m.context_length || 128e3, 65536)
|
|
43
|
-
};
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
async function fetchUpstreamModels(baseUrl, apiKey, upstreamKey, upstreamBaseUrl) {
|
|
47
|
-
try {
|
|
48
|
-
const headers = {
|
|
49
|
-
Authorization: `Bearer ${apiKey}`
|
|
50
|
-
};
|
|
51
|
-
if (upstreamKey) headers["X-Upstream-Key"] = upstreamKey;
|
|
52
|
-
if (upstreamBaseUrl) headers["X-Upstream-Base-Url"] = upstreamBaseUrl;
|
|
53
|
-
const res = await fetch(`${baseUrl}/v1/models`, { headers });
|
|
54
|
-
if (!res.ok) return null;
|
|
55
|
-
const data = await res.json();
|
|
56
|
-
const models = data.data || [];
|
|
57
|
-
if (models.length === 0) return null;
|
|
58
|
-
return upstreamToModels(models);
|
|
59
|
-
} catch {
|
|
60
|
-
return null;
|
|
61
45
|
}
|
|
46
|
+
return models.length > 0 ? models : null;
|
|
62
47
|
}
|
|
63
48
|
function buildProviderModels(baseUrl, upstreamKey, upstreamBaseUrl, models) {
|
|
64
49
|
const config = {
|
|
@@ -73,6 +58,75 @@ function buildProviderModels(baseUrl, upstreamKey, upstreamBaseUrl, models) {
|
|
|
73
58
|
}
|
|
74
59
|
return config;
|
|
75
60
|
}
|
|
61
|
+
function persistModelsConfig(providerModels) {
|
|
62
|
+
try {
|
|
63
|
+
const os = __require("os");
|
|
64
|
+
const fs = __require("fs");
|
|
65
|
+
const path = __require("path");
|
|
66
|
+
const configPath = path.join(os.homedir(), ".openclaw", "openclaw.json");
|
|
67
|
+
if (!fs.existsSync(configPath)) return;
|
|
68
|
+
const raw = fs.readFileSync(configPath, "utf-8");
|
|
69
|
+
let config;
|
|
70
|
+
try {
|
|
71
|
+
config = JSON.parse(raw);
|
|
72
|
+
} catch {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
if (!config.models) config.models = {};
|
|
76
|
+
const models = config.models;
|
|
77
|
+
if (!models.providers) models.providers = {};
|
|
78
|
+
const providers = models.providers;
|
|
79
|
+
const configSafeModels = providerModels.models.map((m) => ({
|
|
80
|
+
id: m.id,
|
|
81
|
+
name: m.name
|
|
82
|
+
}));
|
|
83
|
+
const configEntry = {
|
|
84
|
+
baseUrl: providerModels.baseUrl,
|
|
85
|
+
api: providerModels.api || "openai-completions",
|
|
86
|
+
models: configSafeModels
|
|
87
|
+
};
|
|
88
|
+
if (providerModels.headers) {
|
|
89
|
+
configEntry.headers = providerModels.headers;
|
|
90
|
+
}
|
|
91
|
+
providers.opencompress = configEntry;
|
|
92
|
+
fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n");
|
|
93
|
+
} catch {
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
function persistAuthProfile(apiKey) {
|
|
97
|
+
try {
|
|
98
|
+
const os = __require("os");
|
|
99
|
+
const fs = __require("fs");
|
|
100
|
+
const path = __require("path");
|
|
101
|
+
const agentsDir = path.join(os.homedir(), ".openclaw", "agents");
|
|
102
|
+
if (!fs.existsSync(agentsDir)) return;
|
|
103
|
+
const agentDirs = fs.readdirSync(agentsDir);
|
|
104
|
+
for (const agent of agentDirs) {
|
|
105
|
+
const authPath = path.join(agentsDir, agent, "agent", "auth-profiles.json");
|
|
106
|
+
const authDir = path.dirname(authPath);
|
|
107
|
+
if (!fs.existsSync(authDir)) {
|
|
108
|
+
fs.mkdirSync(authDir, { recursive: true });
|
|
109
|
+
}
|
|
110
|
+
let profiles = {
|
|
111
|
+
version: 1,
|
|
112
|
+
profiles: {}
|
|
113
|
+
};
|
|
114
|
+
if (fs.existsSync(authPath)) {
|
|
115
|
+
try {
|
|
116
|
+
profiles = JSON.parse(fs.readFileSync(authPath, "utf-8"));
|
|
117
|
+
} catch {
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
profiles.profiles["opencompress:default"] = {
|
|
121
|
+
type: "api_key",
|
|
122
|
+
provider: "opencompress",
|
|
123
|
+
key: apiKey
|
|
124
|
+
};
|
|
125
|
+
fs.writeFileSync(authPath, JSON.stringify(profiles, null, 2) + "\n");
|
|
126
|
+
}
|
|
127
|
+
} catch {
|
|
128
|
+
}
|
|
129
|
+
}
|
|
76
130
|
var opencompressProvider = {
|
|
77
131
|
id: "opencompress",
|
|
78
132
|
label: "OpenCompress",
|
|
@@ -141,8 +195,10 @@ var opencompressProvider = {
|
|
|
141
195
|
});
|
|
142
196
|
} catch {
|
|
143
197
|
}
|
|
144
|
-
const
|
|
145
|
-
const modelCount =
|
|
198
|
+
const onboardModels = buildProviderModels(DEFAULT_BASE_URL, llmKey, upstreamBaseUrl);
|
|
199
|
+
const modelCount = FALLBACK_MODELS.length;
|
|
200
|
+
persistModelsConfig(onboardModels);
|
|
201
|
+
persistAuthProfile(data.apiKey);
|
|
146
202
|
return {
|
|
147
203
|
profiles: [
|
|
148
204
|
{
|
|
@@ -153,7 +209,7 @@ var opencompressProvider = {
|
|
|
153
209
|
configPatch: {
|
|
154
210
|
models: {
|
|
155
211
|
providers: {
|
|
156
|
-
opencompress:
|
|
212
|
+
opencompress: onboardModels
|
|
157
213
|
}
|
|
158
214
|
}
|
|
159
215
|
},
|
|
@@ -182,12 +238,8 @@ var plugin = {
|
|
|
182
238
|
const existingHeaders = api.config.models?.providers?.opencompress?.headers;
|
|
183
239
|
const existingUpstreamKey = existingHeaders?.["X-Upstream-Key"];
|
|
184
240
|
const existingUpstreamBaseUrl = existingHeaders?.["X-Upstream-Base-Url"];
|
|
185
|
-
const
|
|
186
|
-
|
|
187
|
-
if (apiKey && existingUpstreamKey) {
|
|
188
|
-
dynamicModels = await fetchUpstreamModels(baseUrl, apiKey, existingUpstreamKey, existingUpstreamBaseUrl);
|
|
189
|
-
}
|
|
190
|
-
const providerModels = buildProviderModels(baseUrl, existingUpstreamKey, existingUpstreamBaseUrl, dynamicModels || void 0);
|
|
241
|
+
const existingModels = readExistingModels(api);
|
|
242
|
+
const providerModels = buildProviderModels(baseUrl, existingUpstreamKey, existingUpstreamBaseUrl, existingModels || void 0);
|
|
191
243
|
opencompressProvider.models = providerModels;
|
|
192
244
|
api.registerProvider(opencompressProvider);
|
|
193
245
|
if (!api.config.models) {
|
|
@@ -197,9 +249,14 @@ var plugin = {
|
|
|
197
249
|
api.config.models.providers = {};
|
|
198
250
|
}
|
|
199
251
|
api.config.models.providers.opencompress = providerModels;
|
|
200
|
-
|
|
201
|
-
const
|
|
202
|
-
|
|
252
|
+
persistModelsConfig(providerModels);
|
|
253
|
+
const apiKey = getApiKey(api);
|
|
254
|
+
if (apiKey) {
|
|
255
|
+
persistAuthProfile(apiKey);
|
|
256
|
+
}
|
|
257
|
+
const modelCount = existingModels ? existingModels.length : FALLBACK_MODELS.length;
|
|
258
|
+
const source = existingModels ? "from existing providers" : "fallback";
|
|
259
|
+
api.logger.info(`OpenCompress provider registered (${modelCount} models ${source}, 5-layer compression)`);
|
|
203
260
|
api.registerCommand({
|
|
204
261
|
name: "compress-stats",
|
|
205
262
|
description: "Show OpenCompress usage statistics and savings",
|
|
@@ -285,6 +342,7 @@ var plugin = {
|
|
|
285
342
|
if (api.config.models?.providers) {
|
|
286
343
|
api.config.models.providers.opencompress = cleanModels;
|
|
287
344
|
}
|
|
345
|
+
persistModelsConfig(cleanModels);
|
|
288
346
|
try {
|
|
289
347
|
await fetch(`${baseUrl}/v1/byok`, {
|
|
290
348
|
method: "DELETE",
|
|
@@ -315,11 +373,12 @@ var plugin = {
|
|
|
315
373
|
provider = "google";
|
|
316
374
|
upstreamBaseUrl = "https://generativelanguage.googleapis.com/v1beta/openai";
|
|
317
375
|
}
|
|
318
|
-
const
|
|
319
|
-
const updatedModels = buildProviderModels(baseUrl, upstreamKey, upstreamBaseUrl,
|
|
376
|
+
const existingModels2 = readExistingModels(api);
|
|
377
|
+
const updatedModels = buildProviderModels(baseUrl, upstreamKey, upstreamBaseUrl, existingModels2 || void 0);
|
|
320
378
|
if (api.config.models?.providers) {
|
|
321
379
|
api.config.models.providers.opencompress = updatedModels;
|
|
322
380
|
}
|
|
381
|
+
persistModelsConfig(updatedModels);
|
|
323
382
|
try {
|
|
324
383
|
await fetch(`${baseUrl}/v1/byok`, {
|
|
325
384
|
method: "POST",
|
|
@@ -331,7 +390,7 @@ var plugin = {
|
|
|
331
390
|
});
|
|
332
391
|
} catch {
|
|
333
392
|
}
|
|
334
|
-
const modelCount2 =
|
|
393
|
+
const modelCount2 = existingModels2 ? existingModels2.length : FALLBACK_MODELS.length;
|
|
335
394
|
return {
|
|
336
395
|
text: [
|
|
337
396
|
`Switched to **BYOK mode** (${provider}).`,
|