easyrouter-config 1.0.7 → 1.0.8
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 +58 -9
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -20,7 +20,7 @@ import { parseArgs } from "util";
|
|
|
20
20
|
import pc from "picocolors";
|
|
21
21
|
|
|
22
22
|
// src/config/constants.ts
|
|
23
|
-
var VERSION = true ? "1.0.
|
|
23
|
+
var VERSION = true ? "1.0.8" : "0.0.0-dev";
|
|
24
24
|
var PRIMARY_HOST = "https://easyrouter.io";
|
|
25
25
|
var FALLBACK_HOSTS = ["https://ezr.sh"];
|
|
26
26
|
var HOST_PROBE_TIMEOUT_MS = 5e3;
|
|
@@ -362,7 +362,46 @@ var claudeClient = {
|
|
|
362
362
|
// src/config/models.ts
|
|
363
363
|
import { log as log2, select, isCancel } from "@clack/prompts";
|
|
364
364
|
import pc4 from "picocolors";
|
|
365
|
-
function
|
|
365
|
+
async function fetchOpenRouterContextMap(verbose) {
|
|
366
|
+
const map = /* @__PURE__ */ new Map();
|
|
367
|
+
try {
|
|
368
|
+
const ctrl = new AbortController();
|
|
369
|
+
const timer = setTimeout(() => ctrl.abort(), FETCH_MODELS_TIMEOUT_MS);
|
|
370
|
+
const res = await fetch("https://openrouter.ai/api/v1/models", {
|
|
371
|
+
signal: ctrl.signal,
|
|
372
|
+
headers: { "User-Agent": "easyrouter-config/1.0" }
|
|
373
|
+
});
|
|
374
|
+
clearTimeout(timer);
|
|
375
|
+
if (!res.ok) return map;
|
|
376
|
+
const json = await res.json();
|
|
377
|
+
const models = Array.isArray(json?.data) ? json.data : [];
|
|
378
|
+
for (const m of models) {
|
|
379
|
+
const short = m.id.split("/").pop() ?? m.id;
|
|
380
|
+
const ctx = m.context_length ?? 0;
|
|
381
|
+
const maxOut = m.max_completion_tokens ?? Math.min(32768, Math.max(4096, Math.floor(ctx / 4)));
|
|
382
|
+
const entry = { contextLength: ctx, maxTokens: maxOut };
|
|
383
|
+
map.set(short.toLowerCase(), entry);
|
|
384
|
+
map.set(normalizeModelId(short), entry);
|
|
385
|
+
}
|
|
386
|
+
if (verbose) log2.info(`\u2713 OpenRouter: \u62C9\u53D6\u5230 ${models.length} \u4E2A\u6A21\u578B\u4E0A\u4E0B\u6587\u4FE1\u606F`);
|
|
387
|
+
} catch (err) {
|
|
388
|
+
if (verbose) log2.warn(`OpenRouter \u62C9\u53D6\u5931\u8D25\uFF1A${err?.message}\uFF08\u5C06\u7528\u515C\u5E95 contextWindow\uFF09`);
|
|
389
|
+
}
|
|
390
|
+
return map;
|
|
391
|
+
}
|
|
392
|
+
function normalizeModelId(s) {
|
|
393
|
+
s = s.replace(/-\d{6}$/, "");
|
|
394
|
+
s = s.replace(/(?<=[a-zA-Z])-(\d+)-(\d+)(?=-|$)/g, "-$1.$2");
|
|
395
|
+
return s.toLowerCase();
|
|
396
|
+
}
|
|
397
|
+
var _orContextMapPromise = null;
|
|
398
|
+
function getOpenRouterContextMap(verbose) {
|
|
399
|
+
if (!_orContextMapPromise) {
|
|
400
|
+
_orContextMapPromise = fetchOpenRouterContextMap(verbose);
|
|
401
|
+
}
|
|
402
|
+
return _orContextMapPromise;
|
|
403
|
+
}
|
|
404
|
+
function toOpenClawCost(m, orContextMap) {
|
|
366
405
|
const ratio = m.model_ratio ?? 0;
|
|
367
406
|
const compRatio = m.completion_ratio ?? 1;
|
|
368
407
|
const cacheRatio = m.cache_ratio ?? 0;
|
|
@@ -370,9 +409,16 @@ function toOpenClawCost(m) {
|
|
|
370
409
|
const output = round6(ratio * compRatio * 2e-3);
|
|
371
410
|
const cacheRead = round6(ratio * cacheRatio * 2e-3);
|
|
372
411
|
const cacheWrite = round6(input * 1.25);
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
412
|
+
let contextWindow = 131072;
|
|
413
|
+
let maxTokens = 32768;
|
|
414
|
+
if (orContextMap) {
|
|
415
|
+
const name = m.model_name;
|
|
416
|
+
const hit = orContextMap.get(name.toLowerCase()) ?? orContextMap.get(normalizeModelId(name));
|
|
417
|
+
if (hit && hit.contextLength > 0) {
|
|
418
|
+
contextWindow = hit.contextLength;
|
|
419
|
+
maxTokens = hit.maxTokens;
|
|
420
|
+
}
|
|
421
|
+
}
|
|
376
422
|
return {
|
|
377
423
|
cost: { input, output, cacheRead, cacheWrite },
|
|
378
424
|
contextWindow,
|
|
@@ -577,7 +623,8 @@ var openClawClient = {
|
|
|
577
623
|
await runOpenClawSubprocess(args, ctx);
|
|
578
624
|
let registered = 0;
|
|
579
625
|
if (llms.length > 1) {
|
|
580
|
-
|
|
626
|
+
const orContextMap = await getOpenRouterContextMap(ctx.verbose);
|
|
627
|
+
registered = await patchOpenClawJson(llms, defaultModel, ctx, orContextMap);
|
|
581
628
|
}
|
|
582
629
|
return {
|
|
583
630
|
configPaths: ["~/.openclaw/openclaw.json"],
|
|
@@ -585,7 +632,7 @@ var openClawClient = {
|
|
|
585
632
|
};
|
|
586
633
|
}
|
|
587
634
|
};
|
|
588
|
-
async function patchOpenClawJson(llms, defaultModel, ctx) {
|
|
635
|
+
async function patchOpenClawJson(llms, defaultModel, ctx, orContextMap) {
|
|
589
636
|
const configPath = join(homedir(), ".openclaw", "openclaw.json");
|
|
590
637
|
let json;
|
|
591
638
|
try {
|
|
@@ -623,11 +670,13 @@ async function patchOpenClawJson(llms, defaultModel, ctx) {
|
|
|
623
670
|
let updated = 0;
|
|
624
671
|
const agentsModels = json?.agents?.defaults?.models ?? null;
|
|
625
672
|
for (const m of llms) {
|
|
626
|
-
const { cost, contextWindow, maxTokens } = toOpenClawCost(m);
|
|
673
|
+
const { cost, contextWindow, maxTokens } = toOpenClawCost(m, orContextMap);
|
|
627
674
|
const idx = existingById.get(m.model_name);
|
|
628
675
|
if (idx !== void 0) {
|
|
629
676
|
const existing = provider.models[idx];
|
|
630
|
-
|
|
677
|
+
const costChanged = existing.cost?.input !== cost.input || existing.cost?.output !== cost.output;
|
|
678
|
+
const ctxChanged = existing.contextWindow !== contextWindow;
|
|
679
|
+
if (costChanged || ctxChanged) {
|
|
631
680
|
existing.cost = cost;
|
|
632
681
|
existing.contextWindow = contextWindow;
|
|
633
682
|
existing.maxTokens = maxTokens;
|