dsh-livebench-panel 0.1.9 → 0.1.11

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/lib/index.js +40 -13
  2. package/package.json +1 -1
package/lib/index.js CHANGED
@@ -381,6 +381,14 @@ function writeGeneratedModelConfig(layout, YAML, { displayName, modelId, reasoni
381
381
  // note: reasoning_effort is an OpenAI-style knob and is intentionally
382
382
  // not forwarded on the anthropic protocol path.
383
383
  }
384
+ } else if (protocol === "openai_responses") {
385
+ // OpenAI Responses API proxy: provider name matches
386
+ // get_api_function('openai_responses') → chat_completion_openai_responses,
387
+ // which converts reasoning_effort to reasoning:{effort} itself.
388
+ lines.push(` openai_responses: ${modelId}`);
389
+ if (reasoningEffort) {
390
+ lines.push("api_kwargs:", " default:", ` reasoning_effort: ${reasoningEffort}`);
391
+ }
384
392
  } else {
385
393
  lines.push(` local: ${modelId}`);
386
394
  if (reasoningEffort) {
@@ -494,6 +502,22 @@ function asInt(value, min, max, fallback) {
494
502
  return Math.min(max, Math.max(min, Math.trunc(n)));
495
503
  }
496
504
 
505
+ /**
506
+ * Validate one bench path: "live_bench", "live_bench/<category>" or
507
+ * "live_bench/<category>/<task>". Task names are mixed-case in LiveBench
508
+ * (AMPS_Hard, LCB_generation, …), so segments allow A-Za-z0-9_.
509
+ * @returns {string|null} error description, or null when valid.
510
+ */
511
+ function validateBenchName(bn) {
512
+ const parts = bn.split("/").filter((s) => s.length > 0);
513
+ if (parts[0] !== "live_bench") return "must start with live_bench";
514
+ if (parts.length > 3) return "too deep";
515
+ for (const seg of parts) {
516
+ if (!/^[A-Za-z0-9_]{1,80}$/.test(seg)) return `bad segment "${seg}"`;
517
+ }
518
+ return null;
519
+ }
520
+
497
521
  function apply(ctx) {
498
522
  /** The single run slot. */
499
523
  let run = null;
@@ -537,14 +561,9 @@ function apply(ctx) {
537
561
  benchNames = [];
538
562
  for (const bn of body.benchNames) {
539
563
  if (typeof bn !== "string") return { status: 400, payload: { ok: false, error: "invalid bench name" } };
540
- const parts = bn.split("/").filter((s) => s.length > 0);
541
- if (parts[0] !== "live_bench" || parts.length > 3) {
542
- return { status: 400, payload: { ok: false, error: `invalid bench path: ${bn}` } };
543
- }
544
- for (const seg of parts) {
545
- if (!/^[a-z0-9_]+$/.test(seg)) return { status: 400, payload: { ok: false, error: `invalid bench path: ${bn}` } };
546
- }
547
- benchNames.push(parts.join("/"));
564
+ const error = validateBenchName(bn);
565
+ if (error) return { status: 400, payload: { ok: false, error: `invalid bench path: ${bn} (${error})` } };
566
+ benchNames.push(bn.split("/").filter((s) => s.length > 0).join("/"));
548
567
  }
549
568
  }
550
569
 
@@ -557,12 +576,19 @@ function apply(ctx) {
557
576
  // selects LiveBench's native anthropic client and the spawn env points
558
577
  // the SDK at the proxy (ANTHROPIC_BASE_URL / ANTHROPIC_API_KEY).
559
578
  const isAnthropicRoute = provider && provider.api === "anthropic-messages" && provider.baseURL;
560
- if (isAnthropicRoute || hasEffortSuffix) {
579
+ // OpenAI Responses-API proxies (api: openai-responses) select LiveBench's
580
+ // openai_responses client; --api-base + LIVEBENCH_API_KEY route them the
581
+ // usual way, and reasoning_effort converts to reasoning:{effort} inside.
582
+ const isOpenAIResponsesRoute = provider
583
+ && (provider.api === "openai-responses" || provider.api === "openai_responses")
584
+ && provider.baseURL;
585
+ const needConfig = isAnthropicRoute || isOpenAIResponsesRoute || hasEffortSuffix;
586
+ if (needConfig) {
561
587
  writeError = writeGeneratedModelConfig(layout, loadYaml(profileDir), {
562
588
  displayName,
563
589
  modelId,
564
590
  reasoningEffort: isAnthropicRoute ? null : reasoningEffort,
565
- protocol: isAnthropicRoute ? "anthropic" : "openai",
591
+ protocol: isAnthropicRoute ? "anthropic" : isOpenAIResponsesRoute ? "openai_responses" : "openai",
566
592
  });
567
593
  if (writeError) return { status: 500, payload: { ok: false, error: writeError } };
568
594
  cliModel = displayName;
@@ -693,7 +719,8 @@ function apply(ctx) {
693
719
  providers: providers.map(({ id, name: pname, models, api, baseURL }) => ({
694
720
  id,
695
721
  name: pname,
696
- routable: (api === "openai-completions" || api === "anthropic-messages") && typeof baseURL === "string" && baseURL.length > 0,
722
+ routable: ["openai-completions", "openai-responses", "openai_responses", "anthropic-messages"].includes(api)
723
+ && typeof baseURL === "string" && baseURL.length > 0,
697
724
  baseURL: baseURL ?? null,
698
725
  models,
699
726
  })),
@@ -870,7 +897,7 @@ function apply(ctx) {
870
897
  const task = typeof row.task === "string" ? row.task : "";
871
898
  // path-safety: membership in the scanned task list + charset guards
872
899
  if (!/^[A-Za-z0-9._@-]{1,160}$/.test(model)) continue;
873
- if (!/^[a-z0-9_]{1,60}$/.test(category) || !/^[a-z0-9_]{1,60}$/.test(task)) continue;
900
+ if (!/^[A-Za-z0-9_]{1,80}$/.test(category) || !/^[A-Za-z0-9_]{1,80}$/.test(task)) continue;
874
901
  if (!(tasks[category] && tasks[category][task])) continue;
875
902
  const taskDir = join(layout.dataDir, category, task);
876
903
  removed += filterJsonlByModel(join(taskDir, "model_answer", `${model}.jsonl`), "model_id", model);
@@ -886,4 +913,4 @@ function runsAlive() {
886
913
  return 1;
887
914
  }
888
915
 
889
- export { name, inject, apply, writeGeneratedModelConfig, readProviders };
916
+ export { name, inject, apply, writeGeneratedModelConfig, readProviders, validateBenchName };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-livebench-panel",
3
- "version": "0.1.9",
3
+ "version": "0.1.11",
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",