llm-relay 0.0.11 → 0.0.13

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 (57) hide show
  1. package/README.md +78 -5
  2. package/dist/benchmarks.d.ts +13 -0
  3. package/dist/benchmarks.js +79 -0
  4. package/dist/benchmarks.js.map +1 -0
  5. package/dist/circuit-breaker.d.ts +32 -0
  6. package/dist/circuit-breaker.js +98 -0
  7. package/dist/circuit-breaker.js.map +1 -0
  8. package/dist/cli.d.ts +4 -0
  9. package/dist/cli.js +134 -21
  10. package/dist/cli.js.map +1 -1
  11. package/dist/config.d.ts +14 -7
  12. package/dist/config.js +64 -25
  13. package/dist/config.js.map +1 -1
  14. package/dist/key-checker.d.ts +13 -0
  15. package/dist/key-checker.js +101 -0
  16. package/dist/key-checker.js.map +1 -0
  17. package/dist/metadata.d.ts +10 -0
  18. package/dist/metadata.js +74 -0
  19. package/dist/metadata.js.map +1 -0
  20. package/dist/onboarding.d.ts +14 -0
  21. package/dist/onboarding.js +100 -0
  22. package/dist/onboarding.js.map +1 -0
  23. package/dist/ping/cadence.d.ts +52 -0
  24. package/dist/ping/cadence.js +165 -0
  25. package/dist/ping/cadence.js.map +1 -0
  26. package/dist/ping/metrics.d.ts +23 -0
  27. package/dist/ping/metrics.js +88 -0
  28. package/dist/ping/metrics.js.map +1 -0
  29. package/dist/ping/ping.d.ts +40 -0
  30. package/dist/ping/ping.js +231 -0
  31. package/dist/ping/ping.js.map +1 -0
  32. package/dist/ping/probe-cache.d.ts +40 -0
  33. package/dist/ping/probe-cache.js +96 -0
  34. package/dist/ping/probe-cache.js.map +1 -0
  35. package/dist/ping/quota.d.ts +15 -0
  36. package/dist/ping/quota.js +42 -0
  37. package/dist/ping/quota.js.map +1 -0
  38. package/dist/ping/runtime-telemetry.d.ts +42 -0
  39. package/dist/ping/runtime-telemetry.js +86 -0
  40. package/dist/ping/runtime-telemetry.js.map +1 -0
  41. package/dist/presets.d.ts +23 -0
  42. package/dist/presets.js +167 -0
  43. package/dist/presets.js.map +1 -0
  44. package/dist/registry.d.ts +6 -2
  45. package/dist/registry.js +7 -1
  46. package/dist/registry.js.map +1 -1
  47. package/dist/server.d.ts +2 -0
  48. package/dist/server.js +113 -45
  49. package/dist/server.js.map +1 -1
  50. package/dist/setup-claude.d.ts +16 -0
  51. package/dist/setup-claude.js +78 -0
  52. package/dist/setup-claude.js.map +1 -0
  53. package/dist/telemetry.d.ts +26 -0
  54. package/dist/telemetry.js +43 -0
  55. package/dist/telemetry.js.map +1 -0
  56. package/docs/tier-data.json +2137 -2060
  57. package/package.json +1 -1
@@ -0,0 +1,96 @@
1
+ import { readFileSync, writeFileSync, renameSync, mkdirSync } from "node:fs";
2
+ import { join, dirname } from "node:path";
3
+ import { homedir } from "node:os";
4
+ export const DEFAULT_PROBE_TTL_MS = 24 * 60 * 60 * 1000; // 24 hours
5
+ export const CURRENT_PROBE_VERSION = 1;
6
+ export function getProbeCachePath() {
7
+ const xdg = process.env.XDG_CACHE_HOME;
8
+ const baseDir = xdg && xdg.trim() ? join(xdg, "llm-relay") : join(homedir(), ".llm-relay");
9
+ return join(baseDir, "probe-cache.json");
10
+ }
11
+ function emptyCache() {
12
+ return { version: CURRENT_PROBE_VERSION, providers: {} };
13
+ }
14
+ let _cache = null;
15
+ let _cachePath = null;
16
+ export function loadProbeCache(opts = {}) {
17
+ const target = opts.path ?? getProbeCachePath();
18
+ _cachePath = target;
19
+ try {
20
+ const raw = readFileSync(target, "utf8");
21
+ const parsed = JSON.parse(raw);
22
+ if (parsed && typeof parsed === "object" && parsed.providers) {
23
+ _cache = parsed;
24
+ return parsed;
25
+ }
26
+ }
27
+ catch {
28
+ /* No cache or parse error */
29
+ }
30
+ _cache = emptyCache();
31
+ return _cache;
32
+ }
33
+ export function flushProbeCache(opts = {}) {
34
+ const target = opts.path ?? _cachePath ?? getProbeCachePath();
35
+ const cacheData = opts.cache ?? _cache ?? emptyCache();
36
+ try {
37
+ mkdirSync(dirname(target), { recursive: true });
38
+ const tmpPath = `${target}.${Date.now()}.${Math.random().toString(36).slice(2, 8)}.tmp`;
39
+ writeFileSync(tmpPath, JSON.stringify(cacheData, null, 2) + "\n", "utf8");
40
+ renameSync(tmpPath, target);
41
+ }
42
+ catch {
43
+ /* best-effort persistence */
44
+ }
45
+ }
46
+ export function getModelsDueForProbe(providerKey, modelIds, opts = {}) {
47
+ const ttlMs = opts.ttlMs ?? DEFAULT_PROBE_TTL_MS;
48
+ const now = opts.now ?? Date.now();
49
+ const probeVersion = opts.probeVersion ?? CURRENT_PROBE_VERSION;
50
+ const cache = opts.path ? loadProbeCache({ path: opts.path }) : (_cache ?? loadProbeCache());
51
+ const providerBucket = cache.providers[providerKey];
52
+ const models = providerBucket?.models ?? {};
53
+ const due = [];
54
+ for (const id of modelIds) {
55
+ const entry = models[id];
56
+ if (!entry) {
57
+ due.push(id);
58
+ continue;
59
+ }
60
+ if (entry.probeVersion !== probeVersion) {
61
+ due.push(id);
62
+ continue;
63
+ }
64
+ if (entry.status === "broken") {
65
+ due.push(id);
66
+ continue;
67
+ }
68
+ if (now - entry.lastProbedAt >= ttlMs) {
69
+ due.push(id);
70
+ continue;
71
+ }
72
+ }
73
+ return due;
74
+ }
75
+ export function recordProbeResult(providerKey, modelId, result, opts = {}) {
76
+ const now = opts.now ?? Date.now();
77
+ const probeVersion = opts.probeVersion ?? CURRENT_PROBE_VERSION;
78
+ const cache = opts.path ? loadProbeCache({ path: opts.path }) : (_cache ?? loadProbeCache());
79
+ if (!cache.providers[providerKey]) {
80
+ cache.providers[providerKey] = { models: {} };
81
+ }
82
+ const isOk = result.code === "200" || result.code === "401";
83
+ const entry = {
84
+ modelId,
85
+ status: isOk ? "ok" : "broken",
86
+ lastProbedAt: now,
87
+ probeVersion,
88
+ ms: result.ms,
89
+ code: result.code,
90
+ quotaPercent: result.quotaPercent,
91
+ };
92
+ cache.providers[providerKey].models[modelId] = entry;
93
+ flushProbeCache({ ...(opts.path ? { path: opts.path } : {}), cache });
94
+ return entry;
95
+ }
96
+ //# sourceMappingURL=probe-cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"probe-cache.js","sourceRoot":"","sources":["../../src/ping/probe-cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,EAAc,MAAM,SAAS,CAAC;AACzF,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAElC,MAAM,CAAC,MAAM,oBAAoB,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,WAAW;AACpE,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC;AAiBvC,MAAM,UAAU,iBAAiB;IAC/B,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;IACvC,MAAM,OAAO,GAAG,GAAG,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,YAAY,CAAC,CAAC;IAC3F,OAAO,IAAI,CAAC,OAAO,EAAE,kBAAkB,CAAC,CAAC;AAC3C,CAAC;AAED,SAAS,UAAU;IACjB,OAAO,EAAE,OAAO,EAAE,qBAAqB,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC;AAC3D,CAAC;AAED,IAAI,MAAM,GAA0B,IAAI,CAAC;AACzC,IAAI,UAAU,GAAkB,IAAI,CAAC;AAErC,MAAM,UAAU,cAAc,CAAC,OAA0B,EAAE;IACzD,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,IAAI,iBAAiB,EAAE,CAAC;IAChD,UAAU,GAAG,MAAM,CAAC;IAEpB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACzC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAmB,CAAC;QACjD,IAAI,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;YAC7D,MAAM,GAAG,MAAM,CAAC;YAChB,OAAO,MAAM,CAAC;QAChB,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,6BAA6B;IAC/B,CAAC;IAED,MAAM,GAAG,UAAU,EAAE,CAAC;IACtB,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,OAAkD,EAAE;IAClF,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,IAAI,UAAU,IAAI,iBAAiB,EAAE,CAAC;IAC9D,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,IAAI,MAAM,IAAI,UAAU,EAAE,CAAC;IAEvD,IAAI,CAAC;QACH,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAChD,MAAM,OAAO,GAAG,GAAG,MAAM,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC;QACxF,aAAa,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC;QAC1E,UAAU,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC9B,CAAC;IAAC,MAAM,CAAC;QACP,6BAA6B;IAC/B,CAAC;AACH,CAAC;AAED,MAAM,UAAU,oBAAoB,CAClC,WAAmB,EACnB,QAAkB,EAClB,OAA+E,EAAE;IAEjF,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,oBAAoB,CAAC;IACjD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;IACnC,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,IAAI,qBAAqB,CAAC;IAChE,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,cAAc,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,IAAI,cAAc,EAAE,CAAC,CAAC;IAE7F,MAAM,cAAc,GAAG,KAAK,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IACpD,MAAM,MAAM,GAAG,cAAc,EAAE,MAAM,IAAI,EAAE,CAAC;IAE5C,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,MAAM,EAAE,IAAI,QAAQ,EAAE,CAAC;QAC1B,MAAM,KAAK,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC;QACzB,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACb,SAAS;QACX,CAAC;QACD,IAAI,KAAK,CAAC,YAAY,KAAK,YAAY,EAAE,CAAC;YACxC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACb,SAAS;QACX,CAAC;QACD,IAAI,KAAK,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;YAC9B,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACb,SAAS;QACX,CAAC;QACD,IAAI,GAAG,GAAG,KAAK,CAAC,YAAY,IAAI,KAAK,EAAE,CAAC;YACtC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACb,SAAS;QACX,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,WAAmB,EACnB,OAAe,EACf,MAAiE,EACjE,OAA+D,EAAE;IAEjE,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;IACnC,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,IAAI,qBAAqB,CAAC;IAChE,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,cAAc,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,IAAI,cAAc,EAAE,CAAC,CAAC;IAE7F,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,WAAW,CAAC,EAAE,CAAC;QAClC,KAAK,CAAC,SAAS,CAAC,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IAChD,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,KAAK,KAAK,IAAI,MAAM,CAAC,IAAI,KAAK,KAAK,CAAC;IAC5D,MAAM,KAAK,GAAe;QACxB,OAAO;QACP,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ;QAC9B,YAAY,EAAE,GAAG;QACjB,YAAY;QACZ,EAAE,EAAE,MAAM,CAAC,EAAE;QACb,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,YAAY,EAAE,MAAM,CAAC,YAAY;KAClC,CAAC;IAEF,KAAK,CAAC,SAAS,CAAC,WAAW,CAAE,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,KAAK,CAAC;IACtD,eAAe,CAAC,EAAE,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IACtE,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type { ProviderConfig } from "../config.js";
2
+ export interface QuotaInfo {
3
+ provider: string;
4
+ ok: boolean;
5
+ quotaPercent?: number | null;
6
+ creditBalanceUsd?: number | null;
7
+ limitUsd?: number | null;
8
+ usageUsd?: number | null;
9
+ statusText?: string;
10
+ }
11
+ /**
12
+ * Explicit quota/balance fetcher for key providers.
13
+ * OpenRouter: GET https://openrouter.ai/api/v1/auth/key
14
+ */
15
+ export declare function fetchProviderQuota(providerName: string, cfg: ProviderConfig, apiKey?: string, fetchFn?: typeof fetch): Promise<QuotaInfo>;
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Explicit quota/balance fetcher for key providers.
3
+ * OpenRouter: GET https://openrouter.ai/api/v1/auth/key
4
+ */
5
+ export async function fetchProviderQuota(providerName, cfg, apiKey, fetchFn = fetch) {
6
+ if (!apiKey) {
7
+ return { provider: providerName, ok: false, statusText: "No API key configured" };
8
+ }
9
+ // OpenRouter key management API
10
+ if (providerName.toLowerCase().includes("openrouter") || cfg.base.includes("openrouter.ai")) {
11
+ try {
12
+ const resp = await fetchFn("https://openrouter.ai/api/v1/auth/key", {
13
+ headers: { Authorization: apiKey.startsWith("Bearer ") ? apiKey : `Bearer ${apiKey}` },
14
+ });
15
+ if (!resp.ok) {
16
+ return { provider: providerName, ok: false, statusText: `HTTP ${resp.status}` };
17
+ }
18
+ const data = (await resp.json());
19
+ const limit = data.data?.limit;
20
+ const usage = data.data?.usage;
21
+ let pct = null;
22
+ if (typeof limit === "number" && typeof usage === "number" && limit > 0) {
23
+ const rem = Math.max(0, limit - usage);
24
+ pct = Math.round((rem / limit) * 100);
25
+ }
26
+ return {
27
+ provider: providerName,
28
+ ok: true,
29
+ quotaPercent: pct,
30
+ limitUsd: limit ?? null,
31
+ usageUsd: usage ?? null,
32
+ creditBalanceUsd: limit && usage !== undefined ? limit - usage : null,
33
+ };
34
+ }
35
+ catch (e) {
36
+ return { provider: providerName, ok: false, statusText: e.message };
37
+ }
38
+ }
39
+ // Generic fallback: returns true if provider is reachable
40
+ return { provider: providerName, ok: true };
41
+ }
42
+ //# sourceMappingURL=quota.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quota.js","sourceRoot":"","sources":["../../src/ping/quota.ts"],"names":[],"mappings":"AAYA;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,YAAoB,EACpB,GAAmB,EACnB,MAAe,EACf,UAAwB,KAAK;IAE7B,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,uBAAuB,EAAE,CAAC;IACpF,CAAC;IAED,gCAAgC;IAChC,IAAI,YAAY,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC;QAC5F,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,uCAAuC,EAAE;gBAClE,OAAO,EAAE,EAAE,aAAa,EAAE,MAAM,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,MAAM,EAAE,EAAE;aACvF,CAAC,CAAC;YACH,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;gBACb,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,QAAQ,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;YAClF,CAAC;YACD,MAAM,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,CAA0E,CAAC;YAC1G,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC;YAC/B,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC;YAE/B,IAAI,GAAG,GAAkB,IAAI,CAAC;YAC9B,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;gBACxE,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC,CAAC;gBACvC,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,GAAG,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC;YACxC,CAAC;YAED,OAAO;gBACL,QAAQ,EAAE,YAAY;gBACtB,EAAE,EAAE,IAAI;gBACR,YAAY,EAAE,GAAG;gBACjB,QAAQ,EAAE,KAAK,IAAI,IAAI;gBACvB,QAAQ,EAAE,KAAK,IAAI,IAAI;gBACvB,gBAAgB,EAAE,KAAK,IAAI,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI;aACtE,CAAC;QACJ,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,EAAE,EAAE,KAAK,EAAE,UAAU,EAAG,CAAW,CAAC,OAAO,EAAE,CAAC;QACjF,CAAC;IACH,CAAC;IAED,0DAA0D;IAC1D,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;AAC9C,CAAC"}
@@ -0,0 +1,42 @@
1
+ export declare const MAX_RECENT_CALLS = 50;
2
+ export declare const DEFAULT_MIN_CALLS_FOR_SCORE = 5;
3
+ export interface RecentCall {
4
+ timestamp: number;
5
+ ok: boolean;
6
+ latencyMs: number;
7
+ tokens?: number;
8
+ }
9
+ export interface ModelTelemetry {
10
+ providerKey: string;
11
+ modelId: string;
12
+ totalCalls: number;
13
+ successCalls: number;
14
+ totalLatencyMs: number;
15
+ totalCompletionTokens: number;
16
+ lastCalledAt: number;
17
+ recentCalls: RecentCall[];
18
+ }
19
+ export interface TelemetryData {
20
+ version: number;
21
+ models: Record<string, ModelTelemetry>;
22
+ }
23
+ export declare function getRuntimeTelemetryPath(): string;
24
+ export declare function loadRuntimeTelemetry(opts?: {
25
+ path?: string;
26
+ }): TelemetryData;
27
+ export declare function flushRuntimeTelemetry(opts?: {
28
+ path?: string;
29
+ telemetry?: TelemetryData;
30
+ }): void;
31
+ export declare function recordModelCall(providerKey: string, modelId: string, callResult: {
32
+ ok: boolean;
33
+ latencyMs: number;
34
+ completionTokens?: number;
35
+ }, opts?: {
36
+ now?: number;
37
+ path?: string;
38
+ }): void;
39
+ export declare function getRealWorldScore(providerKey: string, modelId: string, opts?: {
40
+ minCalls?: number;
41
+ path?: string;
42
+ }): number | null;
@@ -0,0 +1,86 @@
1
+ import { readFileSync, writeFileSync, renameSync, mkdirSync } from "node:fs";
2
+ import { join, dirname } from "node:path";
3
+ import { homedir } from "node:os";
4
+ export const MAX_RECENT_CALLS = 50;
5
+ export const DEFAULT_MIN_CALLS_FOR_SCORE = 5;
6
+ export function getRuntimeTelemetryPath() {
7
+ const xdg = process.env.XDG_CACHE_HOME;
8
+ const baseDir = xdg && xdg.trim() ? join(xdg, "llm-relay") : join(homedir(), ".llm-relay");
9
+ return join(baseDir, "runtime-telemetry.json");
10
+ }
11
+ let _telemetry = null;
12
+ export function loadRuntimeTelemetry(opts = {}) {
13
+ const target = opts.path ?? getRuntimeTelemetryPath();
14
+ try {
15
+ const raw = readFileSync(target, "utf8");
16
+ const parsed = JSON.parse(raw);
17
+ if (parsed && typeof parsed === "object" && parsed.models) {
18
+ _telemetry = parsed;
19
+ return parsed;
20
+ }
21
+ }
22
+ catch { }
23
+ _telemetry = { version: 1, models: {} };
24
+ return _telemetry;
25
+ }
26
+ export function flushRuntimeTelemetry(opts = {}) {
27
+ const target = opts.path ?? getRuntimeTelemetryPath();
28
+ const data = opts.telemetry ?? _telemetry ?? { version: 1, models: {} };
29
+ try {
30
+ mkdirSync(dirname(target), { recursive: true });
31
+ const tmpPath = `${target}.${Date.now()}.${Math.random().toString(36).slice(2, 8)}.tmp`;
32
+ writeFileSync(tmpPath, JSON.stringify(data, null, 2) + "\n", "utf8");
33
+ renameSync(tmpPath, target);
34
+ }
35
+ catch { }
36
+ }
37
+ export function recordModelCall(providerKey, modelId, callResult, opts = {}) {
38
+ const now = opts.now ?? Date.now();
39
+ const data = opts.path ? loadRuntimeTelemetry({ path: opts.path }) : (_telemetry ?? loadRuntimeTelemetry());
40
+ const key = `${providerKey}/${modelId}`;
41
+ if (!data.models[key]) {
42
+ data.models[key] = {
43
+ providerKey,
44
+ modelId,
45
+ totalCalls: 0,
46
+ successCalls: 0,
47
+ totalLatencyMs: 0,
48
+ totalCompletionTokens: 0,
49
+ lastCalledAt: now,
50
+ recentCalls: [],
51
+ };
52
+ }
53
+ const m = data.models[key];
54
+ m.totalCalls += 1;
55
+ if (callResult.ok)
56
+ m.successCalls += 1;
57
+ m.totalLatencyMs += callResult.latencyMs;
58
+ m.totalCompletionTokens += callResult.completionTokens ?? 0;
59
+ m.lastCalledAt = now;
60
+ m.recentCalls.push({
61
+ timestamp: now,
62
+ ok: callResult.ok,
63
+ latencyMs: callResult.latencyMs,
64
+ ...(callResult.completionTokens !== undefined ? { tokens: callResult.completionTokens } : {}),
65
+ });
66
+ if (m.recentCalls.length > MAX_RECENT_CALLS) {
67
+ m.recentCalls.shift();
68
+ }
69
+ flushRuntimeTelemetry({ ...(opts.path ? { path: opts.path } : {}), telemetry: data });
70
+ }
71
+ export function getRealWorldScore(providerKey, modelId, opts = {}) {
72
+ const minCalls = opts.minCalls ?? DEFAULT_MIN_CALLS_FOR_SCORE;
73
+ const data = opts.path ? loadRuntimeTelemetry({ path: opts.path }) : (_telemetry ?? loadRuntimeTelemetry());
74
+ const key = `${providerKey}/${modelId}`;
75
+ const m = data.models[key];
76
+ if (!m || m.totalCalls < minCalls)
77
+ return null;
78
+ const successRate = m.successCalls / m.totalCalls;
79
+ const avgLatency = m.totalLatencyMs / m.totalCalls;
80
+ const speedScore = Math.max(0, Math.min(100, 100 * (1 - avgLatency / 5000)));
81
+ const recencyHours = (Date.now() - m.lastCalledAt) / (1000 * 60 * 60);
82
+ const recencyScore = Math.max(0, Math.min(100, 100 * (1 - recencyHours / 24)));
83
+ const score = 0.6 * (successRate * 100) + 0.25 * speedScore + 0.15 * recencyScore;
84
+ return Math.round(score);
85
+ }
86
+ //# sourceMappingURL=runtime-telemetry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-telemetry.js","sourceRoot":"","sources":["../../src/ping/runtime-telemetry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import type { ProviderConfig } from "./config.js";
2
+ export interface PresetProvider extends ProviderConfig {
3
+ name: string;
4
+ displayName: string;
5
+ signupUrl?: string;
6
+ tierType: "free" | "subscription";
7
+ recommendedModels: string[];
8
+ }
9
+ /** 100%-Free provider presets with direct signup URLs and recommended models. */
10
+ export declare const FREE_PROVIDER_PRESETS: Record<string, PresetProvider>;
11
+ /** User subscription templates for pooling subscription quotas. */
12
+ export declare const SUBSCRIPTION_PROVIDER_PRESETS: Record<string, PresetProvider>;
13
+ /** All available provider presets (free + subscription). */
14
+ export declare const ALL_PROVIDER_PRESETS: Record<string, PresetProvider>;
15
+ /** Default multi-tier routing mapping across free & subscription endpoints. */
16
+ export declare const DEFAULT_PRESET_ROUTING: {
17
+ default: string[];
18
+ tiers: {
19
+ opus: string[];
20
+ sonnet: string[];
21
+ haiku: string[];
22
+ };
23
+ };
@@ -0,0 +1,167 @@
1
+ /** 100%-Free provider presets with direct signup URLs and recommended models. */
2
+ export const FREE_PROVIDER_PRESETS = {
3
+ nim: {
4
+ name: "nim",
5
+ displayName: "NVIDIA NIM (Free Credits)",
6
+ base: "https://integrate.api.nvidia.com/v1",
7
+ kind: "openai",
8
+ authEnv: "NVIDIA_API_KEY",
9
+ authHeader: "authorization",
10
+ timeoutMs: 120000,
11
+ tierType: "free",
12
+ signupUrl: "https://build.nvidia.com",
13
+ recommendedModels: [
14
+ "z-ai/glm-5.2",
15
+ "nvidia/nemotron-3-super-120b-a12b",
16
+ "meta/llama-3.1-70b-instruct",
17
+ "meta/llama-3.1-8b-instruct",
18
+ ],
19
+ },
20
+ groq: {
21
+ name: "groq",
22
+ displayName: "Groq (Free Tier)",
23
+ base: "https://api.groq.com/openai/v1",
24
+ kind: "openai",
25
+ authEnv: "GROQ_API_KEY",
26
+ authHeader: "authorization",
27
+ timeoutMs: 60000,
28
+ tierType: "free",
29
+ signupUrl: "https://console.groq.com/keys",
30
+ recommendedModels: [
31
+ "llama-3.3-70b-versatile",
32
+ "llama-3.1-8b-instant",
33
+ "mixtral-8x7b-32768",
34
+ ],
35
+ },
36
+ gemini: {
37
+ name: "gemini",
38
+ displayName: "Google Gemini AI Studio (Free Tier)",
39
+ base: "https://generativelanguage.googleapis.com/v1beta/openai",
40
+ kind: "openai",
41
+ authEnv: "GEMINI_API_KEY",
42
+ authHeader: "authorization",
43
+ timeoutMs: 120000,
44
+ tierType: "free",
45
+ signupUrl: "https://aistudio.google.com/app/apikey",
46
+ recommendedModels: [
47
+ "gemini-2.5-flash",
48
+ "gemini-2.5-pro",
49
+ "gemini-1.5-flash",
50
+ ],
51
+ },
52
+ openrouter: {
53
+ name: "openrouter",
54
+ displayName: "OpenRouter (Free Models)",
55
+ base: "https://openrouter.ai/api/v1",
56
+ kind: "openai",
57
+ authEnv: "OPENROUTER_API_KEY",
58
+ authHeader: "authorization",
59
+ timeoutMs: 120000,
60
+ tierType: "free",
61
+ signupUrl: "https://openrouter.ai/keys",
62
+ recommendedModels: [
63
+ "meta-llama/llama-3.3-70b-instruct:free",
64
+ "qwen/qwen-2.5-coder-32b-instruct:free",
65
+ "google/gemma-2-9b-it:free",
66
+ ],
67
+ },
68
+ cerebras: {
69
+ name: "cerebras",
70
+ displayName: "Cerebras Inference (Free Tier)",
71
+ base: "https://api.cerebras.ai/v1",
72
+ kind: "openai",
73
+ authEnv: "CEREBRAS_API_KEY",
74
+ authHeader: "authorization",
75
+ timeoutMs: 30000,
76
+ tierType: "free",
77
+ signupUrl: "https://cloud.cerebras.ai",
78
+ recommendedModels: [
79
+ "llama3.1-70b",
80
+ "llama3.1-8b",
81
+ ],
82
+ },
83
+ sambanova: {
84
+ name: "sambanova",
85
+ displayName: "SambaNova Cloud (Free Tier)",
86
+ base: "https://api.sambanova.ai/v1",
87
+ kind: "openai",
88
+ authEnv: "SAMBANOVA_API_KEY",
89
+ authHeader: "authorization",
90
+ timeoutMs: 60000,
91
+ tierType: "free",
92
+ signupUrl: "https://cloud.sambanova.ai",
93
+ recommendedModels: [
94
+ "Meta-Llama-3.3-70B-Instruct",
95
+ "Qwen2.5-Coder-32B-Instruct",
96
+ ],
97
+ },
98
+ };
99
+ /** User subscription templates for pooling subscription quotas. */
100
+ export const SUBSCRIPTION_PROVIDER_PRESETS = {
101
+ openai: {
102
+ name: "openai",
103
+ displayName: "OpenAI ChatGPT / API Subscription",
104
+ base: "https://api.openai.com/v1",
105
+ kind: "openai",
106
+ authEnv: "OPENAI_API_KEY",
107
+ authHeader: "authorization",
108
+ timeoutMs: 120000,
109
+ tierType: "subscription",
110
+ signupUrl: "https://platform.openai.com/api-keys",
111
+ recommendedModels: [
112
+ "gpt-4o",
113
+ "gpt-4o-mini",
114
+ "o3-mini",
115
+ ],
116
+ },
117
+ anthropic: {
118
+ name: "anthropic",
119
+ displayName: "Anthropic Direct Subscription",
120
+ base: "https://api.anthropic.com",
121
+ kind: "anthropic",
122
+ authEnv: "ANTHROPIC_API_KEY",
123
+ authHeader: "x-api-key",
124
+ timeoutMs: 120000,
125
+ tierType: "subscription",
126
+ signupUrl: "https://console.anthropic.com",
127
+ recommendedModels: [
128
+ "claude-3-5-sonnet-20241022",
129
+ "claude-3-5-haiku-20241022",
130
+ ],
131
+ },
132
+ };
133
+ /** All available provider presets (free + subscription). */
134
+ export const ALL_PROVIDER_PRESETS = {
135
+ ...FREE_PROVIDER_PRESETS,
136
+ ...SUBSCRIPTION_PROVIDER_PRESETS,
137
+ };
138
+ /** Default multi-tier routing mapping across free & subscription endpoints. */
139
+ export const DEFAULT_PRESET_ROUTING = {
140
+ default: [
141
+ "groq/llama-3.3-70b-versatile",
142
+ "nim/z-ai/glm-5.2",
143
+ "gemini/gemini-2.5-flash",
144
+ "openrouter/meta-llama/llama-3.3-70b-instruct:free",
145
+ ],
146
+ tiers: {
147
+ opus: [
148
+ "openai/gpt-4o",
149
+ "nim/nvidia/nemotron-3-super-120b-a12b",
150
+ "gemini/gemini-2.5-pro",
151
+ ],
152
+ sonnet: [
153
+ "openai/gpt-4o-mini",
154
+ "groq/llama-3.3-70b-versatile",
155
+ "nim/z-ai/glm-5.2",
156
+ "gemini/gemini-2.5-flash",
157
+ "sambanova/Meta-Llama-3.3-70B-Instruct",
158
+ ],
159
+ haiku: [
160
+ "groq/llama-3.1-8b-instant",
161
+ "cerebras/llama3.1-8b",
162
+ "nim/meta/llama-3.1-8b-instruct",
163
+ "openrouter/google/gemma-2-9b-it:free",
164
+ ],
165
+ },
166
+ };
167
+ //# sourceMappingURL=presets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"presets.js","sourceRoot":"","sources":["../src/presets.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  import type { Config } from "./config.js";
2
2
  import type { ModelCatalog } from "./catalog.js";
3
+ import type { PingLoop, ModelHealthSummary } from "./ping/cadence.js";
3
4
  interface CapabilityScore {
4
5
  bfcl_overall: number | null;
5
6
  bfcl_multi_turn: number | null;
@@ -12,6 +13,7 @@ interface RegistryModel {
12
13
  id: string;
13
14
  /** Best-effort leaderboard match (null when no confident match — matching is fuzzy). */
14
15
  capability: CapabilityScore | null;
16
+ health?: ModelHealthSummary;
15
17
  }
16
18
  interface RegistryProvider {
17
19
  base: string;
@@ -21,6 +23,7 @@ interface RegistryProvider {
21
23
  has_key: boolean;
22
24
  /** openai providers only: did the live /models catalog return anything (reachable + authorized)? */
23
25
  reachable: boolean | null;
26
+ quota_percent?: number | null;
24
27
  models: RegistryModel[];
25
28
  }
26
29
  export interface RegistryView {
@@ -28,8 +31,8 @@ export interface RegistryView {
28
31
  /** How to address a backend: namespace a request model "provider/model" (audit-tools names the
29
32
  * exact model), or let routing map by Claude tier / default (dumb-client convenience). */
30
33
  routing: {
31
- default: string;
32
- tiers: Record<string, string>;
34
+ default: string | string[];
35
+ tiers: Record<string, string | string[]>;
33
36
  };
34
37
  providers: Record<string, RegistryProvider>;
35
38
  capability_source: {
@@ -43,5 +46,6 @@ export interface RegistryView {
43
46
  /** Build the discovery view: providers × live models (best-effort capability) + routing + raw scores. */
44
47
  export declare function buildRegistry(cfg: Config, catalog: ModelCatalog, opts?: {
45
48
  now?: string;
49
+ pingLoop?: PingLoop;
46
50
  }): Promise<RegistryView>;
47
51
  export {};
package/dist/registry.js CHANGED
@@ -52,14 +52,20 @@ export async function buildRegistry(cfg, catalog, opts = {}) {
52
52
  if (p.kind === "openai") {
53
53
  const ids = await catalog.list(name, p);
54
54
  reachable = ids.length > 0;
55
- models = ids.map((id) => ({ id, capability: joinCapability(id, byNorm) }));
55
+ models = ids.map((id) => {
56
+ const capability = joinCapability(id, byNorm);
57
+ const health = opts.pingLoop ? opts.pingLoop.getModelSummary(name, id) : undefined;
58
+ return { id, capability, ...(health ? { health } : {}) };
59
+ });
56
60
  }
61
+ const quota_percent = opts.pingLoop ? opts.pingLoop.getProviderQuota(name) : undefined;
57
62
  providers[name] = {
58
63
  base: p.base,
59
64
  kind: p.kind,
60
65
  ...(p.authEnv ? { authEnv: p.authEnv } : {}),
61
66
  has_key,
62
67
  reachable,
68
+ ...(quota_percent !== undefined ? { quota_percent } : {}),
63
69
  models,
64
70
  };
65
71
  }
@@ -1 +1 @@
1
- {"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"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"}
package/dist/server.d.ts CHANGED
@@ -2,8 +2,10 @@ import { type IncomingMessage, type ServerResponse } from "node:http";
2
2
  import { type Config } from "./config.js";
3
3
  import { type Reshaper } from "./reshaper.js";
4
4
  import { ModelCatalog } from "./catalog.js";
5
+ import { PingLoop } from "./ping/cadence.js";
5
6
  export interface ProxyDeps {
6
7
  reshaper?: Reshaper;
7
8
  catalog?: ModelCatalog;
9
+ pingLoop?: PingLoop;
8
10
  }
9
11
  export declare function createProxy(cfg: Config, deps?: ProxyDeps): import("http").Server<typeof IncomingMessage, typeof ServerResponse>;