dsh-livebench-panel 0.1.1 → 0.1.3

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/lib/client.js CHANGED
@@ -78,7 +78,7 @@ window.__ModuleLoader__.load({
78
78
  function LiveBenchView() {
79
79
  const [config, setConfig] = useState(null);
80
80
  const [configError, setConfigError] = useState(null);
81
- const [sel, setSel] = useState({ provider: "", model: "", category: "", task: "", release: "2024-11-25", begin: "", end: "", maxTokens: "4096" });
81
+ const [sel, setSel] = useState({ provider: "", model: "", reasoning: "default", category: "", task: "", release: "2024-11-25", begin: "", end: "", maxTokens: "32000" });
82
82
  const [busy, setBusy] = useState(false);
83
83
  const [running, setRunning] = useState(false);
84
84
  const [log, setLog] = useState("");
@@ -273,7 +273,7 @@ window.__ModuleLoader__.load({
273
273
  ),
274
274
  ),
275
275
  h("div", { className: c("field") },
276
- h("label", { className: c("label") }, "max-tokens"),
276
+ h("label", { className: c("label") }, "max-tokens(默认 32000)"),
277
277
  h("input", { className: c("input"), type: "number", min: 256, max: 32768, value: sel.maxTokens, onChange: setField("maxTokens") }),
278
278
  ),
279
279
  ),
package/lib/index.js CHANGED
@@ -27,8 +27,8 @@
27
27
  import { spawn } from "node:child_process";
28
28
  import { readdirSync, readFileSync, existsSync, statSync, writeFileSync } from "node:fs";
29
29
  import { createRequire } from "node:module";
30
+ import { delimiter, dirname, join } from "node:path";
30
31
  import { homedir } from "node:os";
31
- import { join } from "node:path";
32
32
  import { fileURLToPath } from "node:url";
33
33
 
34
34
  /** Stable Cordis plugin name. */
@@ -115,9 +115,70 @@ function readProviders(profileDir) {
115
115
  keyEnv: typeof dsCfg.apiKeyEnv === "string" && dsCfg.apiKeyEnv.length > 0 ? dsCfg.apiKeyEnv : "DEEPSEEK_API_KEY",
116
116
  models: dsModels,
117
117
  });
118
+
119
+ // Providers without an explicit baseURL may still be OpenAI-compatible with
120
+ // a well-known endpoint: resolve it from the pi-ai provider registry
121
+ // (@earendil-works/pi-ai, the same source the harness serves from).
122
+ const piAiData = resolvePiAiDataDir(profileDir);
123
+ if (piAiData !== null) {
124
+ for (const provider of providers) {
125
+ if (provider.baseURL === null) {
126
+ const base = builtinBaseUrl(piAiData, provider.id);
127
+ if (base !== null) {
128
+ provider.baseURL = base;
129
+ provider.api = provider.api ?? "openai-completions";
130
+ }
131
+ }
132
+ }
133
+ }
118
134
  return providers;
119
135
  }
120
136
 
137
+ /**
138
+ * Locate the pi-ai provider data directory (providers/data/*.json).
139
+ * @returns {string|null} directory path, or null when pi-ai cannot be found.
140
+ */
141
+ function resolvePiAiDataDir(profileDir) {
142
+ const candidates = [];
143
+ // 1) resolvable from the profile's own dependency tree
144
+ try {
145
+ const requireFromProfile = createRequire(join(profileDir, "package.json"));
146
+ candidates.push(join(dirname(requireFromProfile.resolve("@earendil-works/pi-ai/package.json")), "dist", "providers", "data"));
147
+ } catch { /* not in the profile tree */ }
148
+ // 2) the dsh installation the web process booted from (process.argv[1] = .../dsh/lib/bin.js)
149
+ const bin = process.argv[1];
150
+ if (typeof bin === "string" && bin.includes("@deepseek-ai")) {
151
+ const dshRoot = dirname(dirname(bin));
152
+ candidates.push(join(dshRoot, "node_modules", "@earendil-works", "pi-ai", "dist", "providers", "data"));
153
+ }
154
+ // 3) the default global npm layout on Windows
155
+ const appdata = process.env.APPDATA;
156
+ if (appdata) {
157
+ candidates.push(join(appdata, "npm", "node_modules", "@deepseek-ai", "dsh", "node_modules", "@earendil-works", "pi-ai", "dist", "providers", "data"));
158
+ }
159
+ for (const candidate of candidates) {
160
+ if (existsSync(candidate)) return candidate;
161
+ }
162
+ return null;
163
+ }
164
+
165
+ /** Read one provider's built-in OpenAI-compatible baseUrl from pi-ai data. */
166
+ function builtinBaseUrl(piAiDataDir, providerId) {
167
+ if (!/^[a-z0-9-]+$/.test(providerId)) return null;
168
+ const file = join(piAiDataDir, `${providerId}.json`);
169
+ if (!existsSync(file)) return null;
170
+ try {
171
+ const data = JSON.parse(readFileSync(file, "utf8"));
172
+ const openai = data?.["openai-completions"];
173
+ if (openai && typeof openai === "object") {
174
+ for (const entry of Object.values(openai)) {
175
+ if (entry && typeof entry.baseUrl === "string" && entry.baseUrl.length > 0) return entry.baseUrl;
176
+ }
177
+ }
178
+ } catch { /* unreadable data file — treat as unknown */ }
179
+ return null;
180
+ }
181
+
121
182
  /** Reasoning efforts offered by the built-in DeepSeek route. */
122
183
  const DEEPSEEK_EFFORTS = ["off", "low", "high", "max"];
123
184
  /** Fallback catalog when settings.yaml has no llm-deepseek.models section. */
@@ -342,7 +403,7 @@ function apply(ctx) {
342
403
  /** The single run slot. */
343
404
  let run = null;
344
405
 
345
- const startRun = (body) => {
406
+ const startRun = async (body) => {
346
407
  const layout = livebenchLayout();
347
408
  if (!layout.available) {
348
409
  return { status: 409, payload: { ok: false, error: `LiveBench venv not found under ${layout.root}` } };
@@ -390,7 +451,7 @@ function apply(ctx) {
390
451
  "--model-display-name", displayName,
391
452
  "--bench-name", benchParts.join("/"),
392
453
  "--livebench-release-option", release,
393
- "--max-tokens", String(asInt(body.maxTokens, 256, 32768, 4096)),
454
+ "--max-tokens", String(asInt(body.maxTokens, 256, 32768, 32000)),
394
455
  "--parallel-requests", String(asInt(body.parallel, 1, 8, 2)),
395
456
  "--mode", "single",
396
457
  ];
@@ -406,13 +467,29 @@ function apply(ctx) {
406
467
  ...process.env,
407
468
  HF_HOME: join(layout.root, ".hf_cache"),
408
469
  HF_HUB_DISABLE_SYMLINKS_WARNING: "1",
470
+ // run_livebench.py shells out to bare `python`; without the venv on
471
+ // PATH that resolves to the system interpreter and dies on the first
472
+ // livebench import (shortuuid etc.).
473
+ PATH: `${join(layout.root, ".venv", "Scripts")}${delimiter}${process.env.PATH ?? ""}`,
409
474
  };
410
475
  // Only OpenAI-compatible providers can be routed with --api-base; for
411
- // those, hand the key over via env (never the command line).
476
+ // those, hand the key over via env (never the command line). The key is
477
+ // resolved through the harness credential seam when available (values may
478
+ // live encrypted in .credentials.yaml rather than in the process env),
479
+ // falling back to the plain environment variable.
412
480
  if (provider && provider.api === "openai-completions" && provider.baseURL) {
413
481
  args.push("--api-base", provider.baseURL);
414
- if (provider.keyEnv && process.env[provider.keyEnv]) {
415
- env.LIVEBENCH_API_KEY = process.env[provider.keyEnv];
482
+ if (provider.keyEnv) {
483
+ let key;
484
+ try {
485
+ const credentials = ctx.get ? ctx.get("credentials") : undefined;
486
+ if (credentials && typeof credentials.resolve === "function") {
487
+ const resolved = await credentials.resolve(provider.keyEnv);
488
+ if (resolved && typeof resolved.value === "string" && resolved.value.length > 0) key = resolved.value;
489
+ }
490
+ } catch { /* credential seam unavailable — fall through to env */ }
491
+ if (!key && process.env[provider.keyEnv]) key = process.env[provider.keyEnv];
492
+ if (key) env.LIVEBENCH_API_KEY = key;
416
493
  }
417
494
  }
418
495
 
@@ -486,6 +563,7 @@ function apply(ctx) {
486
563
  id,
487
564
  name: pname,
488
565
  routable: api === "openai-completions" && typeof baseURL === "string" && baseURL.length > 0,
566
+ baseURL: baseURL ?? null,
489
567
  models,
490
568
  })),
491
569
  });
@@ -515,7 +593,7 @@ function apply(ctx) {
515
593
  sendJson(res, 409, { ok: false, error: "another evaluation is already running" });
516
594
  return;
517
595
  }
518
- const result = startRun(body);
596
+ const result = await startRun(body);
519
597
  sendJson(res, result.status, result.payload);
520
598
  },
521
599
  }), `${name}: start route`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-livebench-panel",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "DSH web plugin: a LiveBench tab in the Trajectory view (right of 对话/轨迹). Run LiveBench evaluations against every model configured in the DeepSeek Harness — pick provider/model, category, task, release and question range from dropdowns, watch progress, and read scores in place.",
5
5
  "license": "MIT",
6
6
  "type": "module",