@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.
Files changed (2) hide show
  1. package/dist/index.js +114 -55
  2. 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 upstreamToModels(data) {
21
- return data.map((m) => {
22
- const promptPrice = m.pricing?.prompt ? parseFloat(m.pricing.prompt) * 1e6 : 0;
23
- const completionPrice = m.pricing?.completion ? parseFloat(m.pricing.completion) * 1e6 : 0;
24
- const isReasoning = /\bo[34]\b|reasoner|thinking|deepthink/i.test(m.id);
25
- const inputMods = ["text"];
26
- const archInputs = m.architecture?.input_modalities || [];
27
- if (archInputs.includes("image") || /vision|4o|gemini|claude-.*[34]/i.test(m.id)) {
28
- inputMods.push("image");
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 upstreamModels = await fetchUpstreamModels(DEFAULT_BASE_URL, data.apiKey, llmKey, upstreamBaseUrl);
145
- const modelCount = upstreamModels ? upstreamModels.length : FALLBACK_MODELS.length;
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: buildProviderModels(DEFAULT_BASE_URL, llmKey, upstreamBaseUrl, upstreamModels || void 0)
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 apiKey = getApiKey(api);
186
- let dynamicModels = null;
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
- const modelCount = dynamicModels ? dynamicModels.length : FALLBACK_MODELS.length;
201
- const source = dynamicModels ? "upstream" : "fallback";
202
- api.logger.info(`OpenCompress provider registered (${modelCount} ${source} models, 5-layer compression)`);
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 upstreamModels = await fetchUpstreamModels(baseUrl, apiKey2, upstreamKey, upstreamBaseUrl);
319
- const updatedModels = buildProviderModels(baseUrl, upstreamKey, upstreamBaseUrl, upstreamModels || void 0);
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 = upstreamModels ? upstreamModels.length : FALLBACK_MODELS.length;
393
+ const modelCount2 = existingModels2 ? existingModels2.length : FALLBACK_MODELS.length;
335
394
  return {
336
395
  text: [
337
396
  `Switched to **BYOK mode** (${provider}).`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opencompress/opencompress",
3
- "version": "1.4.0",
3
+ "version": "1.5.1",
4
4
  "description": "OpenCompress plugin for OpenClaw — automatic 5-layer prompt compression for any LLM",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",