dsh-livebench-panel 0.1.3 → 0.1.4

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
@@ -151,8 +151,21 @@ window.__ModuleLoader__.load({
151
151
  const categories = useMemo(() => (config ? Object.keys(config.tasks) : []), [config]);
152
152
  const taskList = useMemo(() => {
153
153
  if (!config || sel.category.length === 0) return [];
154
- return config.tasks[sel.category] ?? [];
154
+ return Object.keys(config.tasks[sel.category] ?? {});
155
155
  }, [config, sel.category]);
156
+ // 有效题数:LiveBench 会丢弃「发布晚于所选 release」和「在所选 release
157
+ // 前已退役」的题目,这里按题目桶 (发布日, 移除日) 精确复算。
158
+ const countFor = useCallback((category, task) => {
159
+ if (!config || category.length === 0) return null;
160
+ const meta = (config.tasks[category] ?? {})[task];
161
+ if (!meta || !Array.isArray(meta.buckets)) return null;
162
+ const option = sel.release;
163
+ return meta.buckets.reduce((sum, b) => {
164
+ const releasedOk = b.r !== "" && b.r <= option;
165
+ const notRemoved = b.rm === "" || b.rm > option;
166
+ return sum + (releasedOk && notRemoved ? b.n : 0);
167
+ }, 0);
168
+ }, [config, sel.release]);
156
169
  const selectedProvider = useMemo(
157
170
  () => (config ? config.providers.find((p) => p.id === sel.provider) ?? null : null),
158
171
  [config, sel.provider],
@@ -168,6 +181,10 @@ window.__ModuleLoader__.load({
168
181
 
169
182
  const onStart = async () => {
170
183
  setStartError(null);
184
+ if (sel.category !== "" && sel.task !== "" && countFor(sel.category, sel.task) === 0) {
185
+ setStartError(`任务 ${sel.task} 在 release ${sel.release} 下没有可用题目(该批题目已退役)。请换一个 release 或任务。`);
186
+ return;
187
+ }
171
188
  setBusy(true);
172
189
  try {
173
190
  const payload = await api("/start", {
@@ -263,7 +280,11 @@ window.__ModuleLoader__.load({
263
280
  h("label", { className: c("label") }, "任务"),
264
281
  h("select", { className: c("select"), value: sel.task, onChange: setField("task") },
265
282
  h("option", { value: "" }, sel.category === "" ? "(先选分类)" : "全部任务"),
266
- taskList.map((task) => h("option", { key: task, value: task }, task))),
283
+ taskList.map((task) => {
284
+ const n = countFor(sel.category, task);
285
+ const label = n === null ? task : `${task}(${n} 题)`;
286
+ return h("option", { key: task, value: task, disabled: n === 0 }, n === 0 ? `${task}(此release无题)` : label);
287
+ })),
267
288
  ),
268
289
  h("div", { className: c("field") },
269
290
  h("label", { className: c("label") }, "题目序号范围(可选)"),
package/lib/index.js CHANGED
@@ -227,18 +227,25 @@ function livebenchLayout() {
227
227
  function scanCategoryTasks(dataDir) {
228
228
  const tasks = {};
229
229
  if (!existsSync(dataDir)) return tasks;
230
- let categoryDirs;
231
- try {
232
- categoryDirs = readDirSafe(dataDir);
233
- } catch {
234
- return tasks;
235
- }
230
+ const categoryDirs = readDirSafe(dataDir);
236
231
  for (const category of categoryDirs) {
237
232
  const catDir = join(dataDir, category);
238
233
  for (const task of readDirSafe(catDir)) {
239
- if (existsSync(join(catDir, task, "question.jsonl"))) {
240
- (tasks[category] ??= []).push(task);
234
+ const questionFile = join(catDir, task, "question.jsonl");
235
+ if (!existsSync(questionFile)) continue;
236
+ // Bucket questions by (release date, removal date) so the UI can
237
+ // compute how many questions survive a chosen release option:
238
+ // LiveBench drops questions released after the option and questions
239
+ // removed at or before the option.
240
+ const buckets = [];
241
+ for (const q of readJsonl(questionFile)) {
242
+ const r = typeof q.livebench_release_date === "string" ? q.livebench_release_date : "";
243
+ const rm = typeof q.livebench_removal_date === "string" ? q.livebench_removal_date : "";
244
+ const bucket = buckets.find((b) => b.r === r && b.rm === rm);
245
+ if (bucket) bucket.n += 1;
246
+ else buckets.push({ r, rm, n: 1 });
241
247
  }
248
+ ((tasks[category] ??= {})[task] = { buckets, total: buckets.reduce((sum, b) => sum + b.n, 0) });
242
249
  }
243
250
  }
244
251
  return tasks;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-livebench-panel",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
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",