dsh-eval-guard 0.5.0 → 0.6.0

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/README.md CHANGED
@@ -26,14 +26,15 @@
26
26
  | FeatureBench 单 feature | 1440 分钟,默认关闭 |
27
27
  | Neural-CPP 纯 C++ 张量后端 | 1440 分钟,默认关闭 |
28
28
  | Neural-FP32 纯 C++ 运算与性能 | 1440 分钟,默认关闭 |
29
+ | Neural-CIFAR 从零训练图像分类 | 1440 分钟,默认关闭 |
29
30
 
30
31
  ## 任务与安装
31
32
 
32
- 设置页可安装十个任务包:
33
+ 设置页可安装十一个任务包:
33
34
 
34
35
  - 原 5 个比赛任务:坦克大战、仓储调度、圈地、炸弹人、夺旗。
35
36
  - 3 个长时单任务:Commit0 单库实现、SWE-Bench Pro 单任务、FeatureBench 单 feature。
36
- - 2 个纯 C++ 项目:Neural-CPP 张量后端、Neural-FP32 运算与性能。
37
+ - 3 个纯 C++ 项目:Neural-CPP 张量后端、Neural-FP32 运算与性能、Neural-CIFAR 图像分类训练。
37
38
 
38
39
  Neural-CPP 安装时自动把 workspace.zip 解压到工作区根目录,并在完成后移除 setup.sh;agent 从根目录的 CMakeLists.txt 开始。工作区只包含 TASK.md、CMakeLists.txt 和 include/nn/nn.hpp;实现在 src/ 中从零完成,纯 C++17,无 Python/OpenCL/第三方库。
39
40
 
@@ -41,6 +42,10 @@ Neural-CPP 安装时自动把 workspace.zip 解压到工作区根目录,并在
41
42
 
42
43
  Neural-FP32 是独立的新任务:固定 fp32,不做完整训练;agent 从零实现 `build/nn_task` CLI,覆盖逐元素、matmul、linear、relu、softmax、layernorm、mse、conv2d、对应反向传播、AdamW 和 SGD momentum。评测侧用 PyTorch 在相同数据和参数上计算参考值,逐操作输出可执行性、是否通过误差阈值、加权平均相对误差、速度,并在最前面给出是否所有操作可执行、最大加权平均相对误差和速度几何平均;不提供统一 score,速度不受误差门控影响。
43
44
 
45
+ Neural-CIFAR 在 Neural-FP32 的基础上要求 agent 用同一套 C++ 训练框架构造并训练 CIFAR-10 图像分类网络。任务不限时,agent 定位为神经网络全栈设计与优化大师,提交前应尽可能优化;速度和未知验证集准确率都是重要指标,会参与世界顶尖水平比拼。安装时下载并准备 50k train split;隐藏 10k test split 由独立评测目录 `dsh-eval-guard/neural-cifar-eval/fetch_cifar.py` 获取并放在该目录的 `hidden/`,不作为工作区文件。评测保留全部原算子指标,并额外用 4 线程和全部逻辑 CPU 分别跑推理,输出验证准确率、FPS、平均单图耗时;4 线程 0.02s/image 只报告,不门控。
46
+
47
+ CIFAR-10 下载缓存固定在用户 home 下:`~/.dsh/eval-guard/cache/cifar10/`,保存 train/val 的 images/labels。下载使用 `~/.dsh/eval-guard/cache/cifar10/.download.lock` 独占锁,并实时打印进度;锁存在时认为其他 DSH 实例正在下载,任务安装/评测会提示等待或手动删除锁文件。缓存完整且无锁时直接复用。设置页新增「CIFAR download proxy」输入框,只用于 CIFAR 下载;按任务安装和评测时分别传给 setup/fetch 脚本。
48
+
44
49
  评测时在临时目录独立构建,然后从 assets/neural-cpp/hidden/ 注入 C++ 测试源码;测试数据由固定种子在进程内生成,不依赖或复制外部数据文件。
45
50
 
46
51
  结果返回 coreAccuracy(核心 C++ 测试通过率)、matrixAccuracy、逐类型 metrics(f32/int128/MXFP4 的矩阵与反向准确率、平均绝对误差、fwd/bwd 毫秒、fwd/bwd GFLOP/s)、speedGflops,以及按矩阵吞吐计算的 speedGeomeanGflops 和 matrixSizes(f32/i128/MXFP4 均为 256×256×256)。确定性项目使用 4 组独立输入取平均;MXFP4 RNE 和随机舍入分开统计,随机舍入使用 2 组输入×每组 1024 次采样,逐元素比较参考均值/标准差和候选均值/标准差,按 3σ 和 0.1–10× 标准差规则统计正确率。参考值由测试侧独立标量实现先算完,再调用候选实现,参考计算不计入候选耗时。隐藏测试不在工作区,agent 无法读取。开发要求线程数最多 4,评测阶段使用全部逻辑 CPU。
@@ -79,12 +84,13 @@ Gitee/GitCode 都使用 git fetch --depth 1 origin <任务 commit> 验证。GitL
79
84
 
80
85
  设置页安装/评测共用一组任务和工作区选择;「评测当前工作区」只评测一个结果,不生成排行。
81
86
 
82
- 插件 eval/ 目录内置全部 10 个任务的单结果评测脚本:
87
+ 插件 eval/ 目录内置全部 11 个任务的单结果评测脚本:
83
88
 
84
89
  - Commit0:单元测试通过率。
85
90
  - SWE-Bench Pro / FeatureBench:隐藏 F2P/P2P 测试;全部通过才 resolved,同时返回 passRate。
86
91
  - Neural-CPP:独立编译隐藏 C++ 测试,返回 accuracy 与 matmul speedGflops;数据在测试进程内按固定种子生成。
87
92
  - Neural-FP32:调用候选 build/nn_task,用 PyTorch 参考值统计每个操作的 MRE 和速度;汇总项在最前面,不输出统一 score。
93
+ - Neural-CIFAR:保留 Neural-FP32 的算子评测,加载训练好的模型,在隐藏验证集上分别用 4 线程和全部线程测准确率/FPS;独立脚本在 `dsh-eval-guard/neural-cifar-eval/`。
88
94
  - Tank / Warehouse / Land / Bomberman / CTF:运行官方引擎/裁判,只返回当前工作区候选者结果,不生成排名。
89
95
 
90
96
  评测也是后台任务,日志和结果实时显示,持久化在 jobs 目录。
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env python3
2
+ """Plugin wrapper for the standalone Neural-CIFAR evaluator."""
3
+ from __future__ import annotations
4
+ import os
5
+ import sys
6
+ from pathlib import Path
7
+
8
+ HERE = Path(__file__).resolve().parent
9
+ STANDALONE = HERE.parent / 'neural-cifar-eval' / 'run_eval.py'
10
+
11
+ if not STANDALONE.is_file():
12
+ print('neural-cifar-eval/run_eval.py missing; copy the standalone evaluator folder first', file=sys.stderr)
13
+ raise SystemExit(1)
14
+
15
+ os.execv(sys.executable, [sys.executable, '-X', 'utf8', str(STANDALONE), *sys.argv[1:]])
@@ -82,7 +82,8 @@ window.__ModuleLoader__.load({
82
82
  pipIndex: "pypi",
83
83
  customPipUrl: "",
84
84
  gitProxyUrl: "",
85
- pipProxyUrl: ""
85
+ pipProxyUrl: "",
86
+ cifarProxyUrl: ""
86
87
  };
87
88
  const box = {
88
89
  border: "1px solid var(--vscode-panel-border, #3c3c3c)",
@@ -144,7 +145,8 @@ window.__ModuleLoader__.load({
144
145
  pipIndex: typeof value?.pipIndex === "string" && value.pipIndex !== "" ? value.pipIndex : "pypi",
145
146
  customPipUrl: typeof value?.customPipUrl === "string" ? value.customPipUrl : "",
146
147
  gitProxyUrl: typeof value?.gitProxyUrl === "string" ? value.gitProxyUrl : "",
147
- pipProxyUrl: typeof value?.pipProxyUrl === "string" ? value.pipProxyUrl : ""
148
+ pipProxyUrl: typeof value?.pipProxyUrl === "string" ? value.pipProxyUrl : "",
149
+ cifarProxyUrl: typeof value?.cifarProxyUrl === "string" ? value.cifarProxyUrl : ""
148
150
  };
149
151
  }
150
152
  /** The settings card. */
@@ -337,7 +339,8 @@ window.__ModuleLoader__.load({
337
339
  pipIndex: draft.pipIndex,
338
340
  customPipUrl: draft.customPipUrl,
339
341
  gitProxyUrl: draft.gitProxyUrl,
340
- pipProxyUrl: draft.pipProxyUrl
342
+ pipProxyUrl: draft.pipProxyUrl,
343
+ cifarProxyUrl: draft.cifarProxyUrl
341
344
  })
342
345
  }).then(readJson);
343
346
  if (!result.ok || result.jobId === void 0) {
@@ -613,6 +616,17 @@ window.__ModuleLoader__.load({
613
616
  onBlur: () => void save({ pipProxyUrl: draft.pipProxyUrl }),
614
617
  placeholder: "127.0.0.1:7897"
615
618
  })]
619
+ }),
620
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
621
+ style: row,
622
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [t("settings.cifarProxy"), ":"] }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
623
+ style: { width: 260 },
624
+ disabled: !ready,
625
+ value: draft.cifarProxyUrl,
626
+ onChange: (event) => edit({ cifarProxyUrl: event.target.value }),
627
+ onBlur: () => void save({ cifarProxyUrl: draft.cifarProxyUrl }),
628
+ placeholder: "127.0.0.1:7897"
629
+ })]
616
630
  })
617
631
  ] });
618
632
  })(),
@@ -1037,6 +1051,7 @@ window.__ModuleLoader__.load({
1037
1051
  "settings.startSession": "Open in new conversation",
1038
1052
  "settings.gitProxy": "Git proxy",
1039
1053
  "settings.pipProxy": "pip proxy",
1054
+ "settings.cifarProxy": "CIFAR download proxy",
1040
1055
  "settings.loading": "Loading…",
1041
1056
  "settings.recent": "Recent events",
1042
1057
  "settings.none": "None.",
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["useSyncExternalStore","useState","useRef","useState"],"sources":["../../src/shared.ts","../../src/client/bridge.ts","../../src/client/Settings.tsx","../../src/client/Toast.tsx","../../src/client/locales.ts","../../src/client/index.ts"],"sourcesContent":["/**\n * Wire types shared by the host and browser halves. Keep this module import-free:\n * the client bundle includes it without pulling host code.\n * @module dsh-eval-guard/shared\n */\n\n/** Settings namespace; also the Loader row id in cordis.patch.yml. */\nexport const SETTINGS_NS = 'eval-guard'\n\n/** Route paths owned by this plugin. */\nexport const STATE_ROUTE = '/api/eval-guard/state'\nexport const CHECK_ROUTE = '/api/eval-guard/check'\nexport const INSTALL_ROUTE = '/api/eval-guard/install'\nexport const PROMPT_ROUTE = '/api/eval-guard/prompt'\nexport const EVENTS_ROUTE = '/api/eval-guard/events'\nexport const REVEAL_ROUTE = '/api/eval-guard/reveal'\nexport const MANUAL_ROUTE = '/api/eval-guard/manual'\nexport const JOBS_ROUTE = '/api/eval-guard/jobs'\nexport const JOB_ROUTE = '/api/eval-guard/job'\nexport const JOB_CANCEL_ROUTE = '/api/eval-guard/job/cancel'\nexport const EVAL_ROUTE = '/api/eval-guard/evaluate'\n\n/** Supported task ids. */\nexport const TANK_TASK = 'tank'\nexport const TANK_TASK_LABEL = '第 6 集 · 坦克大战'\nexport const WAREHOUSE_TASK = 'warehouse'\nexport const WAREHOUSE_TASK_LABEL = '第 5 集 · 仓储调度'\nexport const LAND_TASK = 'land'\nexport const LAND_TASK_LABEL = '第 1 集 · 圈地'\nexport const BOMBERMAN_TASK = 'bomberman'\nexport const BOMBERMAN_TASK_LABEL = '第 2 集 · 炸弹人'\nexport const CTF_TASK = 'ctf'\nexport const CTF_TASK_LABEL = '第 3 集 · 夺旗'\nexport const COMMIT0_TASK = 'commit0'\nexport const COMMIT0_TASK_LABEL = 'Commit0 · 单库实现'\nexport const SWE_BENCH_PRO_TASK = 'swe-bench-pro'\nexport const SWE_BENCH_PRO_TASK_LABEL = 'SWE-Bench Pro · 单任务'\nexport const FEATUREBENCH_TASK = 'featurebench'\nexport const FEATUREBENCH_TASK_LABEL = 'FeatureBench · 单 feature'\nexport const NEURAL_CPP_TASK = 'neural-cpp'\nexport const NEURAL_CPP_TASK_LABEL = 'Neural-CPP · 纯 C++ 张量后端'\nexport const NEURAL_FP32_TASK = 'neural-fp32'\nexport const NEURAL_FP32_TASK_LABEL = 'Neural-FP32 · 运算与性能'\n\n/** One validated clone remote for a task. */\nexport interface TaskRemote {\n id: string\n label: string\n url: string\n}\n\n/** Common pip indexes offered by the settings page. */\nexport const PIP_MIRRORS: readonly { id: string; label: string; url: string }[] = [\n { id: 'pypi', label: 'PyPI', url: 'https://pypi.org/simple' },\n { id: 'tsinghua', label: '清华 TUNA', url: 'https://pypi.tuna.tsinghua.edu.cn/simple' },\n { id: 'aliyun', label: '阿里云', url: 'https://mirrors.aliyun.com/pypi/simple' },\n { id: 'tencent', label: '腾讯云', url: 'https://mirrors.cloud.tencent.com/pypi/simple' },\n { id: 'bfsu', label: '北外', url: 'https://mirrors.bfsu.edu.cn/pypi/web/simple' },\n { id: 'sjtu', label: '上海交大', url: 'https://mirror.sjtu.edu.cn/pypi/web/simple' },\n]\n\n/** One task offered by the installer. */\nexport interface TaskInfo {\n id: string\n label: string\n description: string\n /** Default wall-clock limit applied when the user selects this task. */\n timeLimitMinutes: number\n /** Default time-limit switch applied when the user selects this task. */\n timeLimitEnabled: boolean\n /** Whether installation needs a host-side clone / venv setup. */\n needsSetup: boolean\n /** Canonical upstream repository; used to build mirror URLs. */\n repoUrl?: string\n /** Clone remotes verified to contain the exact pinned commit. */\n remotes?: TaskRemote[]\n}\n\nexport type JobKind = 'install' | 'eval'\nexport type JobStatus = 'queued' | 'running' | 'succeeded' | 'failed' | 'cancelled' | 'interrupted'\n\n/** Summary of one background setup or evaluation job. */\nexport interface JobInfo {\n id: string\n kind: JobKind\n task: string\n workspaceId: string\n status: JobStatus\n createdAt: number\n startedAt: number | null\n endedAt: number | null\n updatedAt: number\n error?: string\n}\n\n/** Full job state, including a bounded log and optional result. */\nexport interface JobDetail extends JobInfo {\n log: string\n prompt?: string\n runId?: string\n result?: unknown\n}\n\n/** A live conversation the enable-time warning has to mention. */\nexport interface RunningSession {\n sessionId: string\n title: string\n cwd: string\n running: boolean\n jobs: number\n}\n\n/** One warning surfaced to the browser. */\nexport interface GuardEvent {\n seq: number\n at: number\n sessionId?: string\n runId?: string\n kind: 'tool-blocked' | 'path-denied' | 'process-denied' | 'wait-blocked' | 'timeout' | 'notice'\n tool?: string\n detail: string\n}\n\n/** Host answer for the enable pre-check. */\nexport interface GuardState {\n enabled: boolean\n running: RunningSession[]\n tasks: TaskInfo[]\n defaultBlacklist: string\n generatedDefault: boolean\n workspaceRoot: string\n runsRoot: string\n pipMirrors?: { id: string; label: string; url: string }[]\n}\n\n/** Result of checking one workspace before install. */\nexport interface CheckResult {\n ok: boolean\n workspaceId: string\n path: string\n empty: boolean\n entries: string[]\n error?: string\n}\n\n/** Result of installing the task pack. */\nexport interface InstallResult {\n ok: boolean\n error?: string\n runId?: string\n workspaceId?: string\n workspacePath?: string\n prompt?: string\n}\n\n/** Manual-channel material locations. */\nexport interface ManualPaths {\n source: string\n prompt: string\n}\n\n/** Usage record written next to one run. */\nexport interface RunUsage {\n inputTokens: number\n outputTokens: number\n cacheReadTokens: number\n cacheWriteTokens: number\n reasoningTokens: number\n toolCalls: number\n turns: number\n steps: number\n wallTimeMs: number\n startedAt: number | null\n updatedAt: number\n}\n\n/** Metadata for one guarded task run. */\nexport interface RunRecord {\n runId: string\n task: string\n workspaceId: string\n workspacePath: string\n sessionId: string | null\n createdAt: number\n startedAt: number | null\n endedAt: number | null\n status: 'prepared' | 'active' | 'timeout' | 'ended'\n prompt: string\n timeLimitMinutes: number\n provider?: string\n model?: string\n title?: string\n}\n","/** Shell capabilities published to the Settings panel. */\nexport interface EvalWorkspace { id: string; label: string }\nexport interface EvalBridge {\n startSession(workspaceId: string, prompt: string): void\n workspaces(): readonly EvalWorkspace[]\n}\nlet current: EvalBridge | undefined\nexport function configureEvalBridge(next: EvalBridge | undefined): void { current = next }\nexport function evalBridge(): EvalBridge | undefined { return current }\n","/**\n * Settings panel for the evaluation guard.\n * @module dsh-eval-guard/client/Settings\n */\nimport { useEffect, useRef, useState, useSyncExternalStore, type CSSProperties, type ReactElement } from 'react'\nimport {\n CHECK_ROUTE, EVENTS_ROUTE, INSTALL_ROUTE, MANUAL_ROUTE, REVEAL_ROUTE, STATE_ROUTE,\n JOBS_ROUTE, JOB_ROUTE, JOB_CANCEL_ROUTE, EVAL_ROUTE,\n type CheckResult, type GuardEvent, type GuardState, type InstallResult, type ManualPaths, type JobDetail, type JobInfo,\n PIP_MIRRORS,\n} from '../shared.ts'\nimport { evalBridge } from './bridge.ts'\n\ntype Snapshot = {\n status: 'loading' | 'ready' | 'unavailable'\n value?: Record<string, unknown>\n revision?: number\n writable: boolean\n}\ntype Form = {\n getSnapshot: () => Snapshot\n subscribe: (listener: () => void) => () => void\n mutate: (ops: readonly { op: 'set'; path: string[]; value: unknown }[], revision?: number) => Promise<boolean>\n}\ntype Props = { form: Form; t: (key: string) => string }\n\ninterface Draft {\n enabled: boolean\n timeLimitEnabled: boolean\n timeLimitMinutes: number\n forbiddenPaths: string\n toolBlacklistUseDefault: boolean\n toolBlacklist: string\n cloneSource: string\n customCloneUrl: string\n pipIndex: string\n customPipUrl: string\n gitProxyUrl: string\n pipProxyUrl: string\n}\n\nconst EMPTY: Draft = {\n enabled: false,\n timeLimitEnabled: true,\n timeLimitMinutes: 90,\n forbiddenPaths: '',\n toolBlacklistUseDefault: true,\n toolBlacklist: '',\n cloneSource: 'github',\n customCloneUrl: '',\n pipIndex: 'pypi',\n customPipUrl: '',\n gitProxyUrl: '',\n pipProxyUrl: '',\n}\n\nconst box: CSSProperties = { border: '1px solid var(--vscode-panel-border, #3c3c3c)', borderRadius: 8, padding: 14, marginBottom: 14 }\nconst row: CSSProperties = { display: 'flex', gap: 10, alignItems: 'center', flexWrap: 'wrap', marginBottom: 8 }\nconst note: CSSProperties = { opacity: 0.72, fontSize: 12, lineHeight: 1.5, margin: '6px 0' }\nconst textarea: CSSProperties = { width: '100%', minHeight: 110, fontFamily: 'monospace', fontSize: 12, padding: 8, boxSizing: 'border-box' }\nconst button: CSSProperties = { padding: '5px 12px', borderRadius: 6, cursor: 'pointer' }\nconst primary: CSSProperties = { ...button, background: '#2f6fd0', color: '#fff', border: 'none' }\nconst danger: CSSProperties = { ...button, background: '#a33', color: '#fff', border: 'none' }\n\nasync function readJson<T>(response: Response): Promise<T> { return await response.json() as T }\n\nfunction normalize(value: Record<string, unknown> | undefined): Draft {\n return {\n enabled: value?.enabled === true,\n timeLimitEnabled: value?.timeLimitEnabled !== false,\n timeLimitMinutes: typeof value?.timeLimitMinutes === 'number' ? value.timeLimitMinutes : 90,\n forbiddenPaths: typeof value?.forbiddenPaths === 'string' ? value.forbiddenPaths : '',\n toolBlacklistUseDefault: value?.toolBlacklistUseDefault !== false,\n toolBlacklist: typeof value?.toolBlacklist === 'string' ? value.toolBlacklist : '',\n cloneSource: typeof value?.cloneSource === 'string' && value.cloneSource !== '' ? value.cloneSource : 'github',\n customCloneUrl: typeof value?.customCloneUrl === 'string' ? value.customCloneUrl : '',\n pipIndex: typeof value?.pipIndex === 'string' && value.pipIndex !== '' ? value.pipIndex : 'pypi',\n customPipUrl: typeof value?.customPipUrl === 'string' ? value.customPipUrl : '',\n gitProxyUrl: typeof value?.gitProxyUrl === 'string' ? value.gitProxyUrl : '',\n pipProxyUrl: typeof value?.pipProxyUrl === 'string' ? value.pipProxyUrl : '',\n }\n}\n\n/** The settings card. */\nexport function EvalGuardSettings({ form, t }: Props): ReactElement {\n const snapshot = useSyncExternalStore(form.subscribe, form.getSnapshot, form.getSnapshot)\n const [draft, setDraft] = useState<Draft>(EMPTY)\n const [dirty, setDirty] = useState(false)\n const [state, setState] = useState<GuardState | null>(null)\n const [events, setEvents] = useState<GuardEvent[]>([])\n const [pendingEnable, setPendingEnable] = useState(false)\n const [notice, setNotice] = useState('')\n const [error, setError] = useState('')\n const [workspaceId, setWorkspaceId] = useState(() => typeof localStorage === 'undefined' ? '' : localStorage.getItem('evalGuard.workspaceId') ?? '')\n const [taskId, setTaskId] = useState(() => typeof localStorage === 'undefined' ? '' : localStorage.getItem('evalGuard.taskId') ?? '')\n const [check, setCheck] = useState<CheckResult | null>(null)\n const [manual, setManual] = useState<ManualPaths | null>(null)\n const [prompt, setPrompt] = useState('')\n const [copied, setCopied] = useState('')\n const workspaces = evalBridge()?.workspaces() ?? []\n const [job, setJob] = useState<JobDetail | null>(null)\n const [jobNotice, setJobNotice] = useState('')\n const autoOpenJob = useRef('')\n\n const pollJob = (id: string): void => {\n fetch(JOB_ROUTE + '?id=' + encodeURIComponent(id)).then(readJson<JobDetail>).then(setJob).catch(() => undefined)\n }\n const loadLatestJob = (workspace: string, task: string): void => {\n if (workspace === '' || task === '') { setJob(null); return }\n fetch(JOBS_ROUTE + '?workspaceId=' + encodeURIComponent(workspace) + '&task=' + encodeURIComponent(task))\n .then(readJson<JobInfo[]>).then(items => {\n const latest = items[0]\n if (latest !== undefined) pollJob(latest.id)\n else setJob(null)\n }).catch(() => undefined)\n }\n useEffect(() => {\n if (job === null || (job.status !== 'running' && job.status !== 'queued')) return\n const timer = setInterval(() => { pollJob(job.id) }, 800)\n return () => clearInterval(timer)\n }, [job])\n useEffect(() => { if (job?.status === 'succeeded' && job.kind === 'install' && job.prompt !== undefined) {\n setPrompt(job.prompt); setJobNotice(t('settings.installOk')); loadState()\n if (autoOpenJob.current === job.id) {\n autoOpenJob.current = ''\n evalBridge()?.startSession(job.workspaceId, job.prompt)\n }\n } }, [job])\n useEffect(() => { loadLatestJob(workspaceId, taskId) }, [workspaceId, taskId])\n\n useEffect(() => {\n if (snapshot.status !== 'ready' || snapshot.value === undefined || dirty) return\n setDraft(normalize(snapshot.value))\n }, [snapshot, dirty])\n\n const loadState = (): void => {\n fetch(STATE_ROUTE).then(readJson<GuardState>).then(setState).catch(() => setState(null))\n }\n useEffect(() => {\n loadState()\n let since = 0\n const timer = setInterval(() => {\n fetch(EVENTS_ROUTE + '?since=' + String(since)).then(readJson<{ events: GuardEvent[] }>).then(data => {\n if (data.events.length === 0) return\n since = data.events[data.events.length - 1]!.seq\n setEvents(current => [...data.events, ...current].slice(0, 12))\n }).catch(() => undefined)\n }, 2000)\n return () => clearInterval(timer)\n }, [])\n\n useEffect(() => {\n if (state !== null && state.tasks.length > 0 && (taskId === '' || !state.tasks.some(task => task.id === taskId))) setTaskId(state.tasks[0]!.id)\n }, [state, taskId])\n\n const ready = snapshot.status === 'ready' && snapshot.writable\n const save = async (patch: Partial<Draft>): Promise<void> => {\n if (!ready || snapshot.revision === undefined) return\n const next = { ...draft, ...patch }\n const ops: { op: 'set'; path: string[]; value: unknown }[] = []\n for (const key of Object.keys(patch) as (keyof Draft)[]) ops.push({ op: 'set', path: [key], value: next[key] })\n try {\n const accepted = await form.mutate(ops, snapshot.revision)\n if (!accepted) { setError('保存冲突,请刷新后重试。'); return }\n setDraft(next)\n setDirty(false)\n setError('')\n loadState()\n } catch (reason: unknown) {\n setError(reason instanceof Error ? reason.message : String(reason))\n }\n }\n const edit = (patch: Partial<Draft>): void => {\n setDraft(current => ({ ...current, ...patch }))\n setDirty(true)\n }\n\n const selectTask = (next: string): void => {\n setTaskId(next)\n try { localStorage.setItem('evalGuard.taskId', next) } catch { /* storage is optional */ }\n setCheck(null); setManual(null); setPrompt(''); setJob(null); setJobNotice('')\n if (workspaceId !== '') loadManual(workspaceId, next)\n const task = state?.tasks.find(item => item.id === next)\n if (task === undefined) return\n const remotes = task.remotes ?? []\n const cloneSource = draft.cloneSource === 'custom' || remotes.some(remote => remote.id === draft.cloneSource)\n ? draft.cloneSource : (remotes[0]?.id ?? 'github')\n setDraft(current => ({ ...current, timeLimitMinutes: task.timeLimitMinutes, timeLimitEnabled: task.timeLimitEnabled, cloneSource }))\n setNotice(t('settings.taskDefaults').replace('{minutes}', String(task.timeLimitMinutes)).replace('{state}', task.timeLimitEnabled ? t('settings.on') : t('settings.off')))\n void save({ timeLimitMinutes: task.timeLimitMinutes, timeLimitEnabled: task.timeLimitEnabled, cloneSource })\n }\n\n const toggleEnabled = (next: boolean): void => {\n if (!next) { void save({ enabled: false }); return }\n fetch(STATE_ROUTE).then(readJson<GuardState>).then(latest => {\n setState(latest)\n if (latest.running.length > 0) setPendingEnable(true)\n else void save({ enabled: true })\n }).catch(() => void save({ enabled: true }))\n }\n\n const forceEnable = (): void => {\n setPendingEnable(false)\n void save({ enabled: true })\n }\n\n const loadManual = (id: string, task: string): void => {\n if (id === '') { setCheck(null); setManual(null); setPrompt(''); return }\n fetch(CHECK_ROUTE + '?workspaceId=' + encodeURIComponent(id)).then(readJson<CheckResult>).then(result => {\n setCheck(result)\n if (result.ok) {\n fetch(MANUAL_ROUTE + '?workspaceId=' + encodeURIComponent(id) + '&task=' + encodeURIComponent(task)).then(readJson<ManualPaths>).then(paths => {\n setManual(paths)\n setPrompt(paths.prompt)\n }).catch(() => undefined)\n }\n }).catch((reason: unknown) => setError(reason instanceof Error ? reason.message : String(reason)))\n }\n\n const install = async (): Promise<void> => {\n if (workspaceId === '' || taskId === '') return\n setError(''); setNotice(''); setJobNotice('')\n const checked = await fetch(CHECK_ROUTE + '?workspaceId=' + encodeURIComponent(workspaceId)).then(readJson<CheckResult>)\n setCheck(checked)\n if (!checked.ok || !checked.empty) { setError(checked.error ?? t('settings.nonEmpty')); return }\n const result = await fetch(INSTALL_ROUTE, {\n method: 'POST', headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ workspaceId, task: taskId, cloneSource: draft.cloneSource, customCloneUrl: draft.customCloneUrl,\n pipIndex: draft.pipIndex, customPipUrl: draft.customPipUrl, gitProxyUrl: draft.gitProxyUrl, pipProxyUrl: draft.pipProxyUrl }),\n }).then(readJson<{ ok: boolean; jobId?: string; error?: string }>)\n if (!result.ok || result.jobId === undefined) { autoOpenJob.current = ''; setError(result.error ?? '安装失败'); return }\n autoOpenJob.current = result.jobId\n pollJob(result.jobId)\n }\n\n const evaluate = async (): Promise<void> => {\n if (workspaceId === '' || taskId === '') return\n setError(''); setNotice(''); setJobNotice('')\n const result = await fetch(EVAL_ROUTE, {\n method: 'POST', headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ workspaceId, task: taskId }),\n }).then(readJson<{ ok: boolean; jobId?: string; error?: string }>)\n if (!result.ok || result.jobId === undefined) { setError(result.error ?? '评测启动失败'); return }\n pollJob(result.jobId)\n }\n\n const cancelJob = async (): Promise<void> => {\n if (job === null) return\n await fetch(JOB_CANCEL_ROUTE, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ id: job.id }) })\n pollJob(job.id)\n }\n\n const copy = async (label: string, text: string): Promise<void> => {\n try {\n await navigator.clipboard.writeText(text)\n setCopied(label)\n setTimeout(() => setCopied(''), 1500)\n } catch { setError('复制失败') }\n }\n const reveal = (target: string): void => {\n void fetch(REVEAL_ROUTE, {\n method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ path: target }),\n })\n }\n const blacklistText = draft.toolBlacklistUseDefault ? state?.defaultBlacklist ?? '' : draft.toolBlacklist\n\n if (snapshot.status === 'loading') return <div style={box}>{t('settings.loading')}</div>\n return <div>\n {pendingEnable && <div style={{ ...box, borderColor: '#caa23a' }}>\n <strong>{t('settings.warningTitle')}</strong>\n <p style={note}>{t('settings.runningWarning')}</p>\n <ul style={{ ...note, paddingLeft: 18 }}>{(state?.running ?? []).map(item =>\n <li key={item.sessionId}>{item.title} · {item.cwd}{item.jobs > 0 ? ' · jobs: ' + String(item.jobs) : ''}</li>)}</ul>\n <div style={row}>\n <button style={button} onClick={() => { setPendingEnable(false); loadState() }}>{t('settings.runningCancel')}</button>\n <button style={danger} onClick={forceEnable}>{t('settings.runningForce')}</button>\n </div>\n </div>}\n\n <section style={box}>\n <div style={row}>\n <label><input type=\"checkbox\" checked={draft.enabled} disabled={!ready} onChange={event => toggleEnabled(event.target.checked)} /> {t('settings.enabled')}</label>\n </div>\n <p style={note}>{t('settings.enabledHint')}</p>\n </section>\n\n <section style={box}>\n <strong>{t('settings.forbidden')}</strong>\n <p style={note}>{t('settings.forbiddenHint')}</p>\n <textarea style={textarea} value={draft.forbiddenPaths} disabled={!ready}\n onChange={event => edit({ forbiddenPaths: event.target.value })}\n onBlur={() => void save({ forbiddenPaths: draft.forbiddenPaths })} />\n </section>\n\n <section style={box}>\n <div style={row}>\n <strong>{t('settings.blacklist')}</strong>\n <button style={button} disabled={!ready} onClick={() => void save({ toolBlacklistUseDefault: true, toolBlacklist: '' })}>{t('settings.reset')}</button>\n </div>\n <p style={note}>{t('settings.blacklistHint')}</p>\n <textarea style={textarea} value={blacklistText} disabled={!ready}\n onChange={event => edit({ toolBlacklistUseDefault: false, toolBlacklist: event.target.value })}\n onBlur={() => void save({ toolBlacklistUseDefault: draft.toolBlacklistUseDefault, toolBlacklist: draft.toolBlacklist })} />\n {draft.toolBlacklistUseDefault && <p style={note}>{t('settings.editingDefault')}</p>}\n </section>\n\n <section style={box}>\n <strong>{t('settings.task')}</strong>\n <p style={note}>{t('settings.taskHint')}</p>\n <div style={row}>\n <span>{t('settings.taskLabel')}:</span>\n <select value={taskId} disabled={state === null || state.tasks.length === 0}\n onChange={event => selectTask(event.target.value)}>\n {(state?.tasks ?? []).map(task => <option key={task.id} value={task.id}>{task.label}</option>)}\n </select>\n </div>\n {state !== null && <p style={note}>{state.tasks.find(task => task.id === taskId)?.description ?? ''}</p>}\n {(() => {\n const selected = state?.tasks.find(item => item.id === taskId)\n if (selected?.needsSetup !== true) return null\n return <div>\n <div style={row}>\n <span>{t('settings.cloneSource')}:</span>\n <select value={draft.cloneSource} disabled={!ready} onChange={event => void save({ cloneSource: event.target.value })}>\n {(selected.remotes ?? []).map(remote => <option key={remote.id} value={remote.id}>{remote.label}</option>)}\n <option value=\"custom\">{t('settings.custom')}</option>\n </select>\n {draft.cloneSource === 'custom' && <input style={{ width: 260 }} disabled={!ready} value={draft.customCloneUrl}\n onChange={event => edit({ customCloneUrl: event.target.value })} onBlur={() => void save({ customCloneUrl: draft.customCloneUrl })} placeholder=\"https://git.example.com\" />}\n </div>\n <div style={row}>\n <span>{t('settings.pipIndex')}:</span>\n <select value={draft.pipIndex} disabled={!ready} onChange={event => void save({ pipIndex: event.target.value })}>\n {PIP_MIRRORS.map(mirror => <option key={mirror.id} value={mirror.id}>{mirror.label}</option>)}\n <option value=\"custom\">{t('settings.custom')}</option>\n </select>\n {draft.pipIndex === 'custom' && <input style={{ width: 260 }} disabled={!ready} value={draft.customPipUrl}\n onChange={event => edit({ customPipUrl: event.target.value })} onBlur={() => void save({ customPipUrl: draft.customPipUrl })} placeholder=\"https://pypi.example.com/simple\" />}\n </div>\n <div style={row}>\n <span>{t('settings.gitProxy')}:</span>\n <input style={{ width: 260 }} disabled={!ready} value={draft.gitProxyUrl}\n onChange={event => edit({ gitProxyUrl: event.target.value })} onBlur={() => void save({ gitProxyUrl: draft.gitProxyUrl })} placeholder=\"127.0.0.1:7897\" />\n </div>\n <div style={row}>\n <span>{t('settings.pipProxy')}:</span>\n <input style={{ width: 260 }} disabled={!ready} value={draft.pipProxyUrl}\n onChange={event => edit({ pipProxyUrl: event.target.value })} onBlur={() => void save({ pipProxyUrl: draft.pipProxyUrl })} placeholder=\"127.0.0.1:7897\" />\n </div>\n </div>\n })()}\n <div style={row}>\n <span>{t('settings.workspace')}:</span>\n <select value={workspaceId} onChange={event => { const next = event.target.value; setWorkspaceId(next); try { localStorage.setItem('evalGuard.workspaceId', next) } catch { /* storage is optional */ } loadManual(next, taskId); loadLatestJob(next, taskId) }}>\n <option value=\"\">{t('settings.pickWorkspace')}</option>\n {workspaces.map(workspace => <option key={workspace.id} value={workspace.id}>{workspace.label}</option>)}\n </select>\n <button style={primary} disabled={workspaceId === '' || taskId === '' || job?.status === 'running'} onClick={() => void install()}>{t('settings.check')}</button>\n <button style={button} disabled={workspaceId === '' || taskId === '' || job?.status === 'running'} onClick={() => void evaluate()}>{t('settings.evaluate')}</button>\n </div>\n <p style={note}>{t('settings.evalHint')}</p>\n {workspaces.length === 0 && <p style={note}>{t('settings.noWorkspaces')}</p>}\n {check !== null && !check.empty && <p style={{ ...note, color: '#d99' }}>{t('settings.nonEmpty')} ({check.entries.slice(0, 6).join(', ')})</p>}\n {notice !== '' && <p style={{ ...note, color: '#7c7' }}>{notice}</p>}\n {error !== '' && <p style={{ ...note, color: '#d77' }}>{error}</p>}\n {jobNotice !== '' && <p style={{ ...note, color: '#7c7' }}>{jobNotice}</p>}\n {job !== null && <div style={{ ...box, borderColor: job.status === 'failed' ? '#a55' : job.status === 'succeeded' ? '#4a7' : '#3a6' }}>\n <div style={row}><strong>{job.kind === 'install' ? t('settings.installJob') : t('settings.evalJob')}</strong><span>{job.status}</span>\n {job.status === 'running' && <button style={danger} onClick={() => void cancelJob()}>{t('settings.cancel')}</button>}\n {job.kind === 'install' && job.status === 'succeeded' && job.prompt !== undefined && workspaceId !== '' && <button style={primary} onClick={() => evalBridge()?.startSession(workspaceId, job.prompt!)}>{t('settings.startSession')}</button>}</div>\n {job.error !== undefined && <p style={{ ...note, color: '#d77' }}>{job.error}</p>}\n <pre style={{ ...textarea, maxHeight: 260, overflow: 'auto' }}>{job.log || t('settings.waiting')}</pre>\n {job.result !== undefined && <pre style={{ ...textarea, maxHeight: 260, overflow: 'auto' }}>{JSON.stringify(job.result, undefined, 2)}</pre>}\n </div>}\n </section>\n\n <section style={box}>\n <div style={row}>\n <label><input type=\"checkbox\" checked={draft.timeLimitEnabled} disabled={!ready} onChange={event => void save({ timeLimitEnabled: event.target.checked })} /> {t('settings.timeLimit')}</label>\n <input type=\"number\" min={1} max={1440} value={draft.timeLimitMinutes} disabled={!ready}\n style={{ width: 90 }} onChange={event => edit({ timeLimitMinutes: Number(event.target.value) })}\n onBlur={() => void save({ timeLimitMinutes: draft.timeLimitMinutes })} />\n <span style={note}>{t('settings.minutes')}</span>\n </div>\n <p style={note}>{t('settings.timeLimitHint')}</p>\n </section>\n\n <section style={box}>\n <strong>{t('settings.manual')}</strong>\n <p style={note}>{t('settings.manualHint')}</p>\n <div style={row}><span>{t('settings.source')}:</span><code style={{ wordBreak: 'break-all' }}>{manual?.source ?? '—'}</code>\n {manual !== null && <button style={button} onClick={() => reveal(manual.source)}>{t('settings.reveal')}</button>}</div>\n <div style={row}><span>{t('settings.target')}:</span><code style={{ wordBreak: 'break-all' }}>{check?.path ?? '—'}</code>\n {check?.path !== undefined && check.path !== '' && <button style={button} onClick={() => reveal(check.path)}>{t('settings.reveal')}</button>}</div>\n <div style={row}><button style={button} disabled={prompt === ''} onClick={() => void copy('prompt', prompt)}>{copied === 'prompt' ? t('settings.copied') : t('settings.copy')}</button></div>\n <textarea style={{ ...textarea, minHeight: 160 }} readOnly value={prompt} placeholder={t('settings.prompt')} />\n </section>\n\n <section style={box}>\n <strong>{t('settings.recent')}</strong>\n {events.length === 0 && <p style={note}>{t('settings.none')}</p>}\n {events.map(event => <div key={event.seq} style={{ ...note, borderTop: '1px solid #333', paddingTop: 4 }}>\n <strong>[{event.kind}]</strong> {event.tool !== undefined ? event.tool + ' · ' : ''}{event.detail}\n </div>)}\n </section>\n </div>\n}\n","/**\n * Frame-wide warning toasts fed by the host event route.\n * @module dsh-eval-guard/client/Toast\n */\nimport { useEffect, useState, type ReactElement } from 'react'\nimport { EVENTS_ROUTE, type GuardEvent } from '../shared.ts'\n\n/** One toast with a dismiss deadline. */\ninterface Shown { event: GuardEvent; until: number }\n\n/** Poll the host event feed and show new warnings. */\nexport function GuardToast({ t }: { t: (key: string) => string }): ReactElement | null {\n const [shown, setShown] = useState<Shown[]>([])\n useEffect(() => {\n let since = 0\n let alive = true\n const poll = (): void => {\n fetch(EVENTS_ROUTE + '?since=' + String(since)).then(async response => await response.json() as { events: GuardEvent[] }).then(data => {\n if (!alive || data.events.length === 0) return\n since = data.events[data.events.length - 1]!.seq\n const warnings = data.events.filter(event => event.kind !== 'notice')\n if (warnings.length === 0) return\n const now = Date.now()\n setShown(current => [...warnings.map(event => ({ event, until: now + 8000 })), ...current].slice(0, 5))\n }).catch(() => undefined)\n }\n const timer = setInterval(() => {\n poll()\n const now = Date.now()\n setShown(current => current.filter(item => item.until > now))\n }, 1500)\n poll()\n return () => { alive = false; clearInterval(timer) }\n }, [])\n if (shown.length === 0) return null\n return <div style={{ position: 'fixed', right: 18, bottom: 18, zIndex: 9999, display: 'flex', flexDirection: 'column', gap: 8, maxWidth: 420 }}>\n {shown.map(item => <div key={item.event.seq} style={{\n background: '#3a2a12', color: '#ffdca8', border: '1px solid #8a6a2a', borderRadius: 8,\n padding: '10px 12px', fontSize: 12, lineHeight: 1.5, boxShadow: '0 6px 24px rgba(0,0,0,.45)',\n }}>\n <strong>{t('settings.warningTitle')}</strong>\n <div>{item.event.detail}</div>\n </div>)}\n </div>\n}\n","/** Locale namespace and dictionaries for the browser half. */\nexport const NS = 'evalGuard'\n\nexport const zh = {\n 'settings.nav': '评测守护',\n 'settings.title': '评测守护',\n 'settings.enabled': '启用评测守护',\n 'settings.enabledHint': '启用后,所有用户主对话只能读写自己的工作区,禁止联网、子代理与跨 agent 通信,并按任务时限强制终止。默认关闭。',\n 'settings.runningWarning': '当前有正在运行的对话。启用评测守护会立即约束它们,是否强行开启?',\n 'settings.runningCancel': '放弃',\n 'settings.runningForce': '强行开启',\n 'settings.timeLimit': '开启最长时长',\n 'settings.timeLimitHint': '从每条用户消息发送时开始计时;到点只终止当前轮次,并递归清理子代理与后台任务。',\n 'settings.minutes': '分钟',\n 'settings.forbidden': '额外禁止路径',\n 'settings.forbiddenHint': '每行一个绝对路径;# 开头为注释;! 开头表示在禁止范围内放开该子路径;按行顺序生效。默认空。',\n 'settings.blacklist': '工具黑名单',\n 'settings.blacklistHint': '每行一个工具名;默认内容按当前已安装工具生成,不存在的工具会被忽略。',\n 'settings.reset': '恢复默认黑名单',\n 'settings.editingDefault': '编辑后将以自定义黑名单保存。',\n 'settings.task': '安装 / 评测任务',\n 'settings.taskHint': '选择任务和工作区;安装与评测共用这组选择。安装会写入素材并准备环境,评测只对当前工作区运行一次。',\n 'settings.taskLabel': '任务',\n 'settings.workspace': '工作区',\n 'settings.pickWorkspace': '请选择工作区',\n 'settings.check': '安装任务',\n 'settings.nonEmpty': '工作区不是空的;未执行任何操作。',\n 'settings.manual': '手动通道',\n 'settings.manualHint': '手动复制素材:自己把素材目录内容复制到工作区根目录;手动填充提示词:复制下面的提示词。',\n 'settings.source': '素材路径',\n 'settings.target': '工作区路径',\n 'settings.copy': '复制',\n 'settings.copied': '已复制',\n 'settings.prompt': '初始提示词',\n 'settings.reveal': '在文件管理器中打开',\n 'settings.noWorkspaces': '没有可选的工作区。',\n 'settings.installOk': '任务素材已安装,提示词已填入新会话,请自行发送。',\n 'settings.taskDefaults': '已按任务默认值设置限时:{minutes} 分钟,限时开关 {state}。你可以随后手动修改。',\n 'settings.on': '打开',\n 'settings.off': '关闭',\n 'settings.evaluate': '评测当前工作区',\n 'settings.evalJob': '评测任务',\n 'settings.installJob': '安装任务',\n 'settings.cloneSource': '仓库来源',\n 'settings.pipIndex': 'pip 镜像',\n 'settings.custom': '自定义',\n 'settings.cancel': '取消',\n 'settings.waiting': '正在准备…',\n 'settings.evalHint': '只评测单个工作区,不做排名。评测任务与安装共用上面的工作区和任务选择。',\n 'settings.startSession': '填入新会话',\n 'settings.gitProxy': 'Git 代理',\n 'settings.pipProxy': 'pip 代理',\n 'settings.loading': '加载中…',\n 'settings.recent': '最近事件',\n 'settings.none': '暂无。',\n 'settings.warningTitle': '评测守护警告',\n 'settings.close': '关闭',\n} as const\n\nexport type Key = keyof typeof zh\n\nexport const en: Record<Key, string> = {\n 'settings.nav': 'Eval Guard',\n 'settings.title': 'Eval Guard',\n 'settings.enabled': 'Enable evaluation guard',\n 'settings.enabledHint': 'When on, every user main conversation may only read/write its own workspace, with network, subagents and cross-agent channels blocked, and a wall-clock limit. Off by default.',\n 'settings.runningWarning': 'Conversations are running right now. Enabling the guard will constrain them immediately. Force enable?',\n 'settings.runningCancel': 'Cancel',\n 'settings.runningForce': 'Force enable',\n 'settings.timeLimit': 'Enable time limit',\n 'settings.timeLimitHint': 'The clock starts at each user message; at the deadline only the current turn is cancelled, and subagents/jobs are cleaned up recursively.',\n 'settings.minutes': 'minutes',\n 'settings.forbidden': 'Extra forbidden paths',\n 'settings.forbiddenHint': 'One absolute path per line; # comments; ! re-allows a subpath; later lines win. Empty by default.',\n 'settings.blacklist': 'Tool blacklist',\n 'settings.blacklistHint': 'One tool name per line; the default is generated from the tools installed now and missing tools are ignored.',\n 'settings.reset': 'Reset default blacklist',\n 'settings.editingDefault': 'Editing switches this to a custom blacklist.',\n 'settings.task': 'Install / evaluate task',\n 'settings.taskHint': 'Pick a task and workspace; install and evaluation share this selection. Install writes the task and prepares the environment; evaluation runs once on the current workspace.',\n 'settings.taskLabel': 'Task',\n 'settings.workspace': 'Workspace',\n 'settings.pickWorkspace': 'Pick a workspace',\n 'settings.check': 'Install task',\n 'settings.nonEmpty': 'The workspace is not empty; nothing was changed.',\n 'settings.manual': 'Manual channel',\n 'settings.manualHint': 'Manual material copy: copy the source folder contents into the workspace root yourself. Manual prompt: copy the text below.',\n 'settings.source': 'Material path',\n 'settings.target': 'Workspace path',\n 'settings.copy': 'Copy',\n 'settings.copied': 'Copied',\n 'settings.prompt': 'Initial prompt',\n 'settings.reveal': 'Open in file manager',\n 'settings.noWorkspaces': 'No workspace is available.',\n 'settings.installOk': 'Task installed and the prompt was seeded into a new conversation; send it yourself.',\n 'settings.taskDefaults': 'Applied task defaults: {minutes} minutes, time limit {state}. You can change them afterwards.',\n 'settings.on': 'on',\n 'settings.off': 'off',\n 'settings.evaluate': 'Evaluate current workspace',\n 'settings.evalJob': 'Evaluation job',\n 'settings.installJob': 'Install job',\n 'settings.cloneSource': 'Clone source',\n 'settings.pipIndex': 'pip index',\n 'settings.custom': 'Custom',\n 'settings.cancel': 'Cancel',\n 'settings.waiting': 'Preparing…',\n 'settings.evalHint': 'Evaluates one workspace only; no ranking. Uses the same workspace/task selection as install.',\n 'settings.startSession': 'Open in new conversation',\n 'settings.gitProxy': 'Git proxy',\n 'settings.pipProxy': 'pip proxy',\n 'settings.loading': 'Loading…',\n 'settings.recent': 'Recent events',\n 'settings.none': 'None.',\n 'settings.warningTitle': 'Eval Guard warning',\n 'settings.close': 'Close',\n}\n","/**\n * Evaluation guard, browser half: the Settings section, the warning toast, and\n * the shell bridge used to seed a new conversation with the task prompt.\n * @module dsh-eval-guard/client\n */\nimport type { Context } from '@deepseek-ai/cordis'\nimport { SETTINGS_NS } from '../shared.ts'\nimport { EvalGuardSettings } from './Settings.tsx'\nimport { GuardToast } from './Toast.tsx'\nimport { configureEvalBridge } from './bridge.ts'\nimport { en, NS, zh, type Key } from './locales.ts'\n\ndeclare module '@deepseek-ai/dsh-client-ui-slots' {\n interface LocaleNamespaceMap {\n evalGuard: Key\n }\n}\n\nexport const inject = ['slots', 'locale', 'configForms', 'uiWorkspace']\n\nexport function apply(ctx: Context): void {\n ctx.effect(() => ctx.locale.register(NS, { zh, en }))\n configureEvalBridge({\n startSession: (workspaceId, prompt) => {\n ctx.uiWorkspace.startSession(workspaceId as Parameters<typeof ctx.uiWorkspace.startSession>[0], { prompt })\n },\n workspaces: () => {\n const service = (ctx as unknown as { get(key: string): unknown }).get('workspaces') as\n { list?: { getSnapshot(): { items?: readonly Record<string, unknown>[] } } } | undefined\n const items = service?.list?.getSnapshot().items ?? []\n return items.map((item, index) => ({\n id: typeof item['workspaceId'] === 'string' ? item['workspaceId'] : String(item['id'] ?? index),\n label: typeof item['title'] === 'string' && item['title'] !== ''\n ? item['title']\n : String(item['path'] ?? item['workspaceId'] ?? ('workspace ' + String(index + 1))),\n }))\n },\n })\n ctx.effect(() => () => { configureEvalBridge(undefined) })\n const t = ctx.locale.bind(NS)\n const form = ctx.configForms.get(SETTINGS_NS) as {\n getSnapshot(): unknown\n subscribe(listener: () => void): () => void\n mutate(ops: never, revision?: number): unknown\n }\n const formFace = {\n getSnapshot: () => form.getSnapshot(),\n subscribe: (listener: () => void) => form.subscribe(listener),\n mutate: (ops: never, revision?: number) => form.mutate(ops, revision),\n }\n ctx.slots.inject('settings.section', () => ctx.slots.register({\n name: 'settings.section', id: SETTINGS_NS, order: 41,\n label: () => t('settings.nav'), locale: NS,\n inject: () => ({ form: formFace }),\n }, EvalGuardSettings))\n ctx.slots.inject('shell.overlay', () => ctx.slots.register({\n name: 'shell.overlay', id: SETTINGS_NS + '.toast', locale: NS,\n inject: () => ({ t }),\n }, GuardToast))\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["useSyncExternalStore","useState","useRef","useState"],"sources":["../../src/shared.ts","../../src/client/bridge.ts","../../src/client/Settings.tsx","../../src/client/Toast.tsx","../../src/client/locales.ts","../../src/client/index.ts"],"sourcesContent":["/**\n * Wire types shared by the host and browser halves. Keep this module import-free:\n * the client bundle includes it without pulling host code.\n * @module dsh-eval-guard/shared\n */\n\n/** Settings namespace; also the Loader row id in cordis.patch.yml. */\nexport const SETTINGS_NS = 'eval-guard'\n\n/** Route paths owned by this plugin. */\nexport const STATE_ROUTE = '/api/eval-guard/state'\nexport const CHECK_ROUTE = '/api/eval-guard/check'\nexport const INSTALL_ROUTE = '/api/eval-guard/install'\nexport const PROMPT_ROUTE = '/api/eval-guard/prompt'\nexport const EVENTS_ROUTE = '/api/eval-guard/events'\nexport const REVEAL_ROUTE = '/api/eval-guard/reveal'\nexport const MANUAL_ROUTE = '/api/eval-guard/manual'\nexport const JOBS_ROUTE = '/api/eval-guard/jobs'\nexport const JOB_ROUTE = '/api/eval-guard/job'\nexport const JOB_CANCEL_ROUTE = '/api/eval-guard/job/cancel'\nexport const EVAL_ROUTE = '/api/eval-guard/evaluate'\n\n/** Supported task ids. */\nexport const TANK_TASK = 'tank'\nexport const TANK_TASK_LABEL = '第 6 集 · 坦克大战'\nexport const WAREHOUSE_TASK = 'warehouse'\nexport const WAREHOUSE_TASK_LABEL = '第 5 集 · 仓储调度'\nexport const LAND_TASK = 'land'\nexport const LAND_TASK_LABEL = '第 1 集 · 圈地'\nexport const BOMBERMAN_TASK = 'bomberman'\nexport const BOMBERMAN_TASK_LABEL = '第 2 集 · 炸弹人'\nexport const CTF_TASK = 'ctf'\nexport const CTF_TASK_LABEL = '第 3 集 · 夺旗'\nexport const COMMIT0_TASK = 'commit0'\nexport const COMMIT0_TASK_LABEL = 'Commit0 · 单库实现'\nexport const SWE_BENCH_PRO_TASK = 'swe-bench-pro'\nexport const SWE_BENCH_PRO_TASK_LABEL = 'SWE-Bench Pro · 单任务'\nexport const FEATUREBENCH_TASK = 'featurebench'\nexport const FEATUREBENCH_TASK_LABEL = 'FeatureBench · 单 feature'\nexport const NEURAL_CPP_TASK = 'neural-cpp'\nexport const NEURAL_CPP_TASK_LABEL = 'Neural-CPP · 纯 C++ 张量后端'\nexport const NEURAL_FP32_TASK = 'neural-fp32'\nexport const NEURAL_FP32_TASK_LABEL = 'Neural-FP32 · 运算与性能'\nexport const NEURAL_CIFAR_TASK = 'neural-cifar'\nexport const NEURAL_CIFAR_TASK_LABEL = 'Neural-CIFAR · 从零训练图像分类'\n\n/** One validated clone remote for a task. */\nexport interface TaskRemote {\n id: string\n label: string\n url: string\n}\n\n/** Common pip indexes offered by the settings page. */\nexport const PIP_MIRRORS: readonly { id: string; label: string; url: string }[] = [\n { id: 'pypi', label: 'PyPI', url: 'https://pypi.org/simple' },\n { id: 'tsinghua', label: '清华 TUNA', url: 'https://pypi.tuna.tsinghua.edu.cn/simple' },\n { id: 'aliyun', label: '阿里云', url: 'https://mirrors.aliyun.com/pypi/simple' },\n { id: 'tencent', label: '腾讯云', url: 'https://mirrors.cloud.tencent.com/pypi/simple' },\n { id: 'bfsu', label: '北外', url: 'https://mirrors.bfsu.edu.cn/pypi/web/simple' },\n { id: 'sjtu', label: '上海交大', url: 'https://mirror.sjtu.edu.cn/pypi/web/simple' },\n]\n\n/** One task offered by the installer. */\nexport interface TaskInfo {\n id: string\n label: string\n description: string\n /** Default wall-clock limit applied when the user selects this task. */\n timeLimitMinutes: number\n /** Default time-limit switch applied when the user selects this task. */\n timeLimitEnabled: boolean\n /** Whether installation needs a host-side clone / venv setup. */\n needsSetup: boolean\n /** Canonical upstream repository; used to build mirror URLs. */\n repoUrl?: string\n /** Clone remotes verified to contain the exact pinned commit. */\n remotes?: TaskRemote[]\n}\n\nexport type JobKind = 'install' | 'eval'\nexport type JobStatus = 'queued' | 'running' | 'succeeded' | 'failed' | 'cancelled' | 'interrupted'\n\n/** Summary of one background setup or evaluation job. */\nexport interface JobInfo {\n id: string\n kind: JobKind\n task: string\n workspaceId: string\n status: JobStatus\n createdAt: number\n startedAt: number | null\n endedAt: number | null\n updatedAt: number\n error?: string\n}\n\n/** Full job state, including a bounded log and optional result. */\nexport interface JobDetail extends JobInfo {\n log: string\n prompt?: string\n runId?: string\n result?: unknown\n}\n\n/** A live conversation the enable-time warning has to mention. */\nexport interface RunningSession {\n sessionId: string\n title: string\n cwd: string\n running: boolean\n jobs: number\n}\n\n/** One warning surfaced to the browser. */\nexport interface GuardEvent {\n seq: number\n at: number\n sessionId?: string\n runId?: string\n kind: 'tool-blocked' | 'path-denied' | 'process-denied' | 'wait-blocked' | 'timeout' | 'notice'\n tool?: string\n detail: string\n}\n\n/** Host answer for the enable pre-check. */\nexport interface GuardState {\n enabled: boolean\n running: RunningSession[]\n tasks: TaskInfo[]\n defaultBlacklist: string\n generatedDefault: boolean\n workspaceRoot: string\n runsRoot: string\n pipMirrors?: { id: string; label: string; url: string }[]\n}\n\n/** Result of checking one workspace before install. */\nexport interface CheckResult {\n ok: boolean\n workspaceId: string\n path: string\n empty: boolean\n entries: string[]\n error?: string\n}\n\n/** Result of installing the task pack. */\nexport interface InstallResult {\n ok: boolean\n error?: string\n runId?: string\n workspaceId?: string\n workspacePath?: string\n prompt?: string\n}\n\n/** Manual-channel material locations. */\nexport interface ManualPaths {\n source: string\n prompt: string\n}\n\n/** Usage record written next to one run. */\nexport interface RunUsage {\n inputTokens: number\n outputTokens: number\n cacheReadTokens: number\n cacheWriteTokens: number\n reasoningTokens: number\n toolCalls: number\n turns: number\n steps: number\n wallTimeMs: number\n startedAt: number | null\n updatedAt: number\n}\n\n/** Metadata for one guarded task run. */\nexport interface RunRecord {\n runId: string\n task: string\n workspaceId: string\n workspacePath: string\n sessionId: string | null\n createdAt: number\n startedAt: number | null\n endedAt: number | null\n status: 'prepared' | 'active' | 'timeout' | 'ended'\n prompt: string\n timeLimitMinutes: number\n provider?: string\n model?: string\n title?: string\n}\n","/** Shell capabilities published to the Settings panel. */\nexport interface EvalWorkspace { id: string; label: string }\nexport interface EvalBridge {\n startSession(workspaceId: string, prompt: string): void\n workspaces(): readonly EvalWorkspace[]\n}\nlet current: EvalBridge | undefined\nexport function configureEvalBridge(next: EvalBridge | undefined): void { current = next }\nexport function evalBridge(): EvalBridge | undefined { return current }\n","/**\n * Settings panel for the evaluation guard.\n * @module dsh-eval-guard/client/Settings\n */\nimport { useEffect, useRef, useState, useSyncExternalStore, type CSSProperties, type ReactElement } from 'react'\nimport {\n CHECK_ROUTE, EVENTS_ROUTE, INSTALL_ROUTE, MANUAL_ROUTE, REVEAL_ROUTE, STATE_ROUTE,\n JOBS_ROUTE, JOB_ROUTE, JOB_CANCEL_ROUTE, EVAL_ROUTE,\n type CheckResult, type GuardEvent, type GuardState, type InstallResult, type ManualPaths, type JobDetail, type JobInfo,\n PIP_MIRRORS,\n} from '../shared.ts'\nimport { evalBridge } from './bridge.ts'\n\ntype Snapshot = {\n status: 'loading' | 'ready' | 'unavailable'\n value?: Record<string, unknown>\n revision?: number\n writable: boolean\n}\ntype Form = {\n getSnapshot: () => Snapshot\n subscribe: (listener: () => void) => () => void\n mutate: (ops: readonly { op: 'set'; path: string[]; value: unknown }[], revision?: number) => Promise<boolean>\n}\ntype Props = { form: Form; t: (key: string) => string }\n\ninterface Draft {\n enabled: boolean\n timeLimitEnabled: boolean\n timeLimitMinutes: number\n forbiddenPaths: string\n toolBlacklistUseDefault: boolean\n toolBlacklist: string\n cloneSource: string\n customCloneUrl: string\n pipIndex: string\n customPipUrl: string\n gitProxyUrl: string\n pipProxyUrl: string\n cifarProxyUrl: string\n}\n\nconst EMPTY: Draft = {\n enabled: false,\n timeLimitEnabled: true,\n timeLimitMinutes: 90,\n forbiddenPaths: '',\n toolBlacklistUseDefault: true,\n toolBlacklist: '',\n cloneSource: 'github',\n customCloneUrl: '',\n pipIndex: 'pypi',\n customPipUrl: '',\n gitProxyUrl: '',\n pipProxyUrl: '',\n cifarProxyUrl: '',\n}\n\nconst box: CSSProperties = { border: '1px solid var(--vscode-panel-border, #3c3c3c)', borderRadius: 8, padding: 14, marginBottom: 14 }\nconst row: CSSProperties = { display: 'flex', gap: 10, alignItems: 'center', flexWrap: 'wrap', marginBottom: 8 }\nconst note: CSSProperties = { opacity: 0.72, fontSize: 12, lineHeight: 1.5, margin: '6px 0' }\nconst textarea: CSSProperties = { width: '100%', minHeight: 110, fontFamily: 'monospace', fontSize: 12, padding: 8, boxSizing: 'border-box' }\nconst button: CSSProperties = { padding: '5px 12px', borderRadius: 6, cursor: 'pointer' }\nconst primary: CSSProperties = { ...button, background: '#2f6fd0', color: '#fff', border: 'none' }\nconst danger: CSSProperties = { ...button, background: '#a33', color: '#fff', border: 'none' }\n\nasync function readJson<T>(response: Response): Promise<T> { return await response.json() as T }\n\nfunction normalize(value: Record<string, unknown> | undefined): Draft {\n return {\n enabled: value?.enabled === true,\n timeLimitEnabled: value?.timeLimitEnabled !== false,\n timeLimitMinutes: typeof value?.timeLimitMinutes === 'number' ? value.timeLimitMinutes : 90,\n forbiddenPaths: typeof value?.forbiddenPaths === 'string' ? value.forbiddenPaths : '',\n toolBlacklistUseDefault: value?.toolBlacklistUseDefault !== false,\n toolBlacklist: typeof value?.toolBlacklist === 'string' ? value.toolBlacklist : '',\n cloneSource: typeof value?.cloneSource === 'string' && value.cloneSource !== '' ? value.cloneSource : 'github',\n customCloneUrl: typeof value?.customCloneUrl === 'string' ? value.customCloneUrl : '',\n pipIndex: typeof value?.pipIndex === 'string' && value.pipIndex !== '' ? value.pipIndex : 'pypi',\n customPipUrl: typeof value?.customPipUrl === 'string' ? value.customPipUrl : '',\n gitProxyUrl: typeof value?.gitProxyUrl === 'string' ? value.gitProxyUrl : '',\n pipProxyUrl: typeof value?.pipProxyUrl === 'string' ? value.pipProxyUrl : '',\n cifarProxyUrl: typeof value?.cifarProxyUrl === 'string' ? value.cifarProxyUrl : '',\n }\n}\n\n/** The settings card. */\nexport function EvalGuardSettings({ form, t }: Props): ReactElement {\n const snapshot = useSyncExternalStore(form.subscribe, form.getSnapshot, form.getSnapshot)\n const [draft, setDraft] = useState<Draft>(EMPTY)\n const [dirty, setDirty] = useState(false)\n const [state, setState] = useState<GuardState | null>(null)\n const [events, setEvents] = useState<GuardEvent[]>([])\n const [pendingEnable, setPendingEnable] = useState(false)\n const [notice, setNotice] = useState('')\n const [error, setError] = useState('')\n const [workspaceId, setWorkspaceId] = useState(() => typeof localStorage === 'undefined' ? '' : localStorage.getItem('evalGuard.workspaceId') ?? '')\n const [taskId, setTaskId] = useState(() => typeof localStorage === 'undefined' ? '' : localStorage.getItem('evalGuard.taskId') ?? '')\n const [check, setCheck] = useState<CheckResult | null>(null)\n const [manual, setManual] = useState<ManualPaths | null>(null)\n const [prompt, setPrompt] = useState('')\n const [copied, setCopied] = useState('')\n const workspaces = evalBridge()?.workspaces() ?? []\n const [job, setJob] = useState<JobDetail | null>(null)\n const [jobNotice, setJobNotice] = useState('')\n const autoOpenJob = useRef('')\n\n const pollJob = (id: string): void => {\n fetch(JOB_ROUTE + '?id=' + encodeURIComponent(id)).then(readJson<JobDetail>).then(setJob).catch(() => undefined)\n }\n const loadLatestJob = (workspace: string, task: string): void => {\n if (workspace === '' || task === '') { setJob(null); return }\n fetch(JOBS_ROUTE + '?workspaceId=' + encodeURIComponent(workspace) + '&task=' + encodeURIComponent(task))\n .then(readJson<JobInfo[]>).then(items => {\n const latest = items[0]\n if (latest !== undefined) pollJob(latest.id)\n else setJob(null)\n }).catch(() => undefined)\n }\n useEffect(() => {\n if (job === null || (job.status !== 'running' && job.status !== 'queued')) return\n const timer = setInterval(() => { pollJob(job.id) }, 800)\n return () => clearInterval(timer)\n }, [job])\n useEffect(() => { if (job?.status === 'succeeded' && job.kind === 'install' && job.prompt !== undefined) {\n setPrompt(job.prompt); setJobNotice(t('settings.installOk')); loadState()\n if (autoOpenJob.current === job.id) {\n autoOpenJob.current = ''\n evalBridge()?.startSession(job.workspaceId, job.prompt)\n }\n } }, [job])\n useEffect(() => { loadLatestJob(workspaceId, taskId) }, [workspaceId, taskId])\n\n useEffect(() => {\n if (snapshot.status !== 'ready' || snapshot.value === undefined || dirty) return\n setDraft(normalize(snapshot.value))\n }, [snapshot, dirty])\n\n const loadState = (): void => {\n fetch(STATE_ROUTE).then(readJson<GuardState>).then(setState).catch(() => setState(null))\n }\n useEffect(() => {\n loadState()\n let since = 0\n const timer = setInterval(() => {\n fetch(EVENTS_ROUTE + '?since=' + String(since)).then(readJson<{ events: GuardEvent[] }>).then(data => {\n if (data.events.length === 0) return\n since = data.events[data.events.length - 1]!.seq\n setEvents(current => [...data.events, ...current].slice(0, 12))\n }).catch(() => undefined)\n }, 2000)\n return () => clearInterval(timer)\n }, [])\n\n useEffect(() => {\n if (state !== null && state.tasks.length > 0 && (taskId === '' || !state.tasks.some(task => task.id === taskId))) setTaskId(state.tasks[0]!.id)\n }, [state, taskId])\n\n const ready = snapshot.status === 'ready' && snapshot.writable\n const save = async (patch: Partial<Draft>): Promise<void> => {\n if (!ready || snapshot.revision === undefined) return\n const next = { ...draft, ...patch }\n const ops: { op: 'set'; path: string[]; value: unknown }[] = []\n for (const key of Object.keys(patch) as (keyof Draft)[]) ops.push({ op: 'set', path: [key], value: next[key] })\n try {\n const accepted = await form.mutate(ops, snapshot.revision)\n if (!accepted) { setError('保存冲突,请刷新后重试。'); return }\n setDraft(next)\n setDirty(false)\n setError('')\n loadState()\n } catch (reason: unknown) {\n setError(reason instanceof Error ? reason.message : String(reason))\n }\n }\n const edit = (patch: Partial<Draft>): void => {\n setDraft(current => ({ ...current, ...patch }))\n setDirty(true)\n }\n\n const selectTask = (next: string): void => {\n setTaskId(next)\n try { localStorage.setItem('evalGuard.taskId', next) } catch { /* storage is optional */ }\n setCheck(null); setManual(null); setPrompt(''); setJob(null); setJobNotice('')\n if (workspaceId !== '') loadManual(workspaceId, next)\n const task = state?.tasks.find(item => item.id === next)\n if (task === undefined) return\n const remotes = task.remotes ?? []\n const cloneSource = draft.cloneSource === 'custom' || remotes.some(remote => remote.id === draft.cloneSource)\n ? draft.cloneSource : (remotes[0]?.id ?? 'github')\n setDraft(current => ({ ...current, timeLimitMinutes: task.timeLimitMinutes, timeLimitEnabled: task.timeLimitEnabled, cloneSource }))\n setNotice(t('settings.taskDefaults').replace('{minutes}', String(task.timeLimitMinutes)).replace('{state}', task.timeLimitEnabled ? t('settings.on') : t('settings.off')))\n void save({ timeLimitMinutes: task.timeLimitMinutes, timeLimitEnabled: task.timeLimitEnabled, cloneSource })\n }\n\n const toggleEnabled = (next: boolean): void => {\n if (!next) { void save({ enabled: false }); return }\n fetch(STATE_ROUTE).then(readJson<GuardState>).then(latest => {\n setState(latest)\n if (latest.running.length > 0) setPendingEnable(true)\n else void save({ enabled: true })\n }).catch(() => void save({ enabled: true }))\n }\n\n const forceEnable = (): void => {\n setPendingEnable(false)\n void save({ enabled: true })\n }\n\n const loadManual = (id: string, task: string): void => {\n if (id === '') { setCheck(null); setManual(null); setPrompt(''); return }\n fetch(CHECK_ROUTE + '?workspaceId=' + encodeURIComponent(id)).then(readJson<CheckResult>).then(result => {\n setCheck(result)\n if (result.ok) {\n fetch(MANUAL_ROUTE + '?workspaceId=' + encodeURIComponent(id) + '&task=' + encodeURIComponent(task)).then(readJson<ManualPaths>).then(paths => {\n setManual(paths)\n setPrompt(paths.prompt)\n }).catch(() => undefined)\n }\n }).catch((reason: unknown) => setError(reason instanceof Error ? reason.message : String(reason)))\n }\n\n const install = async (): Promise<void> => {\n if (workspaceId === '' || taskId === '') return\n setError(''); setNotice(''); setJobNotice('')\n const checked = await fetch(CHECK_ROUTE + '?workspaceId=' + encodeURIComponent(workspaceId)).then(readJson<CheckResult>)\n setCheck(checked)\n if (!checked.ok || !checked.empty) { setError(checked.error ?? t('settings.nonEmpty')); return }\n const result = await fetch(INSTALL_ROUTE, {\n method: 'POST', headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ workspaceId, task: taskId, cloneSource: draft.cloneSource, customCloneUrl: draft.customCloneUrl,\n pipIndex: draft.pipIndex, customPipUrl: draft.customPipUrl, gitProxyUrl: draft.gitProxyUrl, pipProxyUrl: draft.pipProxyUrl, cifarProxyUrl: draft.cifarProxyUrl }),\n }).then(readJson<{ ok: boolean; jobId?: string; error?: string }>)\n if (!result.ok || result.jobId === undefined) { autoOpenJob.current = ''; setError(result.error ?? '安装失败'); return }\n autoOpenJob.current = result.jobId\n pollJob(result.jobId)\n }\n\n const evaluate = async (): Promise<void> => {\n if (workspaceId === '' || taskId === '') return\n setError(''); setNotice(''); setJobNotice('')\n const result = await fetch(EVAL_ROUTE, {\n method: 'POST', headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ workspaceId, task: taskId }),\n }).then(readJson<{ ok: boolean; jobId?: string; error?: string }>)\n if (!result.ok || result.jobId === undefined) { setError(result.error ?? '评测启动失败'); return }\n pollJob(result.jobId)\n }\n\n const cancelJob = async (): Promise<void> => {\n if (job === null) return\n await fetch(JOB_CANCEL_ROUTE, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ id: job.id }) })\n pollJob(job.id)\n }\n\n const copy = async (label: string, text: string): Promise<void> => {\n try {\n await navigator.clipboard.writeText(text)\n setCopied(label)\n setTimeout(() => setCopied(''), 1500)\n } catch { setError('复制失败') }\n }\n const reveal = (target: string): void => {\n void fetch(REVEAL_ROUTE, {\n method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ path: target }),\n })\n }\n const blacklistText = draft.toolBlacklistUseDefault ? state?.defaultBlacklist ?? '' : draft.toolBlacklist\n\n if (snapshot.status === 'loading') return <div style={box}>{t('settings.loading')}</div>\n return <div>\n {pendingEnable && <div style={{ ...box, borderColor: '#caa23a' }}>\n <strong>{t('settings.warningTitle')}</strong>\n <p style={note}>{t('settings.runningWarning')}</p>\n <ul style={{ ...note, paddingLeft: 18 }}>{(state?.running ?? []).map(item =>\n <li key={item.sessionId}>{item.title} · {item.cwd}{item.jobs > 0 ? ' · jobs: ' + String(item.jobs) : ''}</li>)}</ul>\n <div style={row}>\n <button style={button} onClick={() => { setPendingEnable(false); loadState() }}>{t('settings.runningCancel')}</button>\n <button style={danger} onClick={forceEnable}>{t('settings.runningForce')}</button>\n </div>\n </div>}\n\n <section style={box}>\n <div style={row}>\n <label><input type=\"checkbox\" checked={draft.enabled} disabled={!ready} onChange={event => toggleEnabled(event.target.checked)} /> {t('settings.enabled')}</label>\n </div>\n <p style={note}>{t('settings.enabledHint')}</p>\n </section>\n\n <section style={box}>\n <strong>{t('settings.forbidden')}</strong>\n <p style={note}>{t('settings.forbiddenHint')}</p>\n <textarea style={textarea} value={draft.forbiddenPaths} disabled={!ready}\n onChange={event => edit({ forbiddenPaths: event.target.value })}\n onBlur={() => void save({ forbiddenPaths: draft.forbiddenPaths })} />\n </section>\n\n <section style={box}>\n <div style={row}>\n <strong>{t('settings.blacklist')}</strong>\n <button style={button} disabled={!ready} onClick={() => void save({ toolBlacklistUseDefault: true, toolBlacklist: '' })}>{t('settings.reset')}</button>\n </div>\n <p style={note}>{t('settings.blacklistHint')}</p>\n <textarea style={textarea} value={blacklistText} disabled={!ready}\n onChange={event => edit({ toolBlacklistUseDefault: false, toolBlacklist: event.target.value })}\n onBlur={() => void save({ toolBlacklistUseDefault: draft.toolBlacklistUseDefault, toolBlacklist: draft.toolBlacklist })} />\n {draft.toolBlacklistUseDefault && <p style={note}>{t('settings.editingDefault')}</p>}\n </section>\n\n <section style={box}>\n <strong>{t('settings.task')}</strong>\n <p style={note}>{t('settings.taskHint')}</p>\n <div style={row}>\n <span>{t('settings.taskLabel')}:</span>\n <select value={taskId} disabled={state === null || state.tasks.length === 0}\n onChange={event => selectTask(event.target.value)}>\n {(state?.tasks ?? []).map(task => <option key={task.id} value={task.id}>{task.label}</option>)}\n </select>\n </div>\n {state !== null && <p style={note}>{state.tasks.find(task => task.id === taskId)?.description ?? ''}</p>}\n {(() => {\n const selected = state?.tasks.find(item => item.id === taskId)\n if (selected?.needsSetup !== true) return null\n return <div>\n <div style={row}>\n <span>{t('settings.cloneSource')}:</span>\n <select value={draft.cloneSource} disabled={!ready} onChange={event => void save({ cloneSource: event.target.value })}>\n {(selected.remotes ?? []).map(remote => <option key={remote.id} value={remote.id}>{remote.label}</option>)}\n <option value=\"custom\">{t('settings.custom')}</option>\n </select>\n {draft.cloneSource === 'custom' && <input style={{ width: 260 }} disabled={!ready} value={draft.customCloneUrl}\n onChange={event => edit({ customCloneUrl: event.target.value })} onBlur={() => void save({ customCloneUrl: draft.customCloneUrl })} placeholder=\"https://git.example.com\" />}\n </div>\n <div style={row}>\n <span>{t('settings.pipIndex')}:</span>\n <select value={draft.pipIndex} disabled={!ready} onChange={event => void save({ pipIndex: event.target.value })}>\n {PIP_MIRRORS.map(mirror => <option key={mirror.id} value={mirror.id}>{mirror.label}</option>)}\n <option value=\"custom\">{t('settings.custom')}</option>\n </select>\n {draft.pipIndex === 'custom' && <input style={{ width: 260 }} disabled={!ready} value={draft.customPipUrl}\n onChange={event => edit({ customPipUrl: event.target.value })} onBlur={() => void save({ customPipUrl: draft.customPipUrl })} placeholder=\"https://pypi.example.com/simple\" />}\n </div>\n <div style={row}>\n <span>{t('settings.gitProxy')}:</span>\n <input style={{ width: 260 }} disabled={!ready} value={draft.gitProxyUrl}\n onChange={event => edit({ gitProxyUrl: event.target.value })} onBlur={() => void save({ gitProxyUrl: draft.gitProxyUrl })} placeholder=\"127.0.0.1:7897\" />\n </div>\n <div style={row}>\n <span>{t('settings.pipProxy')}:</span>\n <input style={{ width: 260 }} disabled={!ready} value={draft.pipProxyUrl}\n onChange={event => edit({ pipProxyUrl: event.target.value })} onBlur={() => void save({ pipProxyUrl: draft.pipProxyUrl })} placeholder=\"127.0.0.1:7897\" />\n </div>\n <div style={row}>\n <span>{t('settings.cifarProxy')}:</span>\n <input style={{ width: 260 }} disabled={!ready} value={draft.cifarProxyUrl}\n onChange={event => edit({ cifarProxyUrl: event.target.value })} onBlur={() => void save({ cifarProxyUrl: draft.cifarProxyUrl })} placeholder=\"127.0.0.1:7897\" />\n </div>\n </div>\n })()}\n <div style={row}>\n <span>{t('settings.workspace')}:</span>\n <select value={workspaceId} onChange={event => { const next = event.target.value; setWorkspaceId(next); try { localStorage.setItem('evalGuard.workspaceId', next) } catch { /* storage is optional */ } loadManual(next, taskId); loadLatestJob(next, taskId) }}>\n <option value=\"\">{t('settings.pickWorkspace')}</option>\n {workspaces.map(workspace => <option key={workspace.id} value={workspace.id}>{workspace.label}</option>)}\n </select>\n <button style={primary} disabled={workspaceId === '' || taskId === '' || job?.status === 'running'} onClick={() => void install()}>{t('settings.check')}</button>\n <button style={button} disabled={workspaceId === '' || taskId === '' || job?.status === 'running'} onClick={() => void evaluate()}>{t('settings.evaluate')}</button>\n </div>\n <p style={note}>{t('settings.evalHint')}</p>\n {workspaces.length === 0 && <p style={note}>{t('settings.noWorkspaces')}</p>}\n {check !== null && !check.empty && <p style={{ ...note, color: '#d99' }}>{t('settings.nonEmpty')} ({check.entries.slice(0, 6).join(', ')})</p>}\n {notice !== '' && <p style={{ ...note, color: '#7c7' }}>{notice}</p>}\n {error !== '' && <p style={{ ...note, color: '#d77' }}>{error}</p>}\n {jobNotice !== '' && <p style={{ ...note, color: '#7c7' }}>{jobNotice}</p>}\n {job !== null && <div style={{ ...box, borderColor: job.status === 'failed' ? '#a55' : job.status === 'succeeded' ? '#4a7' : '#3a6' }}>\n <div style={row}><strong>{job.kind === 'install' ? t('settings.installJob') : t('settings.evalJob')}</strong><span>{job.status}</span>\n {job.status === 'running' && <button style={danger} onClick={() => void cancelJob()}>{t('settings.cancel')}</button>}\n {job.kind === 'install' && job.status === 'succeeded' && job.prompt !== undefined && workspaceId !== '' && <button style={primary} onClick={() => evalBridge()?.startSession(workspaceId, job.prompt!)}>{t('settings.startSession')}</button>}</div>\n {job.error !== undefined && <p style={{ ...note, color: '#d77' }}>{job.error}</p>}\n <pre style={{ ...textarea, maxHeight: 260, overflow: 'auto' }}>{job.log || t('settings.waiting')}</pre>\n {job.result !== undefined && <pre style={{ ...textarea, maxHeight: 260, overflow: 'auto' }}>{JSON.stringify(job.result, undefined, 2)}</pre>}\n </div>}\n </section>\n\n <section style={box}>\n <div style={row}>\n <label><input type=\"checkbox\" checked={draft.timeLimitEnabled} disabled={!ready} onChange={event => void save({ timeLimitEnabled: event.target.checked })} /> {t('settings.timeLimit')}</label>\n <input type=\"number\" min={1} max={1440} value={draft.timeLimitMinutes} disabled={!ready}\n style={{ width: 90 }} onChange={event => edit({ timeLimitMinutes: Number(event.target.value) })}\n onBlur={() => void save({ timeLimitMinutes: draft.timeLimitMinutes })} />\n <span style={note}>{t('settings.minutes')}</span>\n </div>\n <p style={note}>{t('settings.timeLimitHint')}</p>\n </section>\n\n <section style={box}>\n <strong>{t('settings.manual')}</strong>\n <p style={note}>{t('settings.manualHint')}</p>\n <div style={row}><span>{t('settings.source')}:</span><code style={{ wordBreak: 'break-all' }}>{manual?.source ?? '—'}</code>\n {manual !== null && <button style={button} onClick={() => reveal(manual.source)}>{t('settings.reveal')}</button>}</div>\n <div style={row}><span>{t('settings.target')}:</span><code style={{ wordBreak: 'break-all' }}>{check?.path ?? '—'}</code>\n {check?.path !== undefined && check.path !== '' && <button style={button} onClick={() => reveal(check.path)}>{t('settings.reveal')}</button>}</div>\n <div style={row}><button style={button} disabled={prompt === ''} onClick={() => void copy('prompt', prompt)}>{copied === 'prompt' ? t('settings.copied') : t('settings.copy')}</button></div>\n <textarea style={{ ...textarea, minHeight: 160 }} readOnly value={prompt} placeholder={t('settings.prompt')} />\n </section>\n\n <section style={box}>\n <strong>{t('settings.recent')}</strong>\n {events.length === 0 && <p style={note}>{t('settings.none')}</p>}\n {events.map(event => <div key={event.seq} style={{ ...note, borderTop: '1px solid #333', paddingTop: 4 }}>\n <strong>[{event.kind}]</strong> {event.tool !== undefined ? event.tool + ' · ' : ''}{event.detail}\n </div>)}\n </section>\n </div>\n}\n","/**\n * Frame-wide warning toasts fed by the host event route.\n * @module dsh-eval-guard/client/Toast\n */\nimport { useEffect, useState, type ReactElement } from 'react'\nimport { EVENTS_ROUTE, type GuardEvent } from '../shared.ts'\n\n/** One toast with a dismiss deadline. */\ninterface Shown { event: GuardEvent; until: number }\n\n/** Poll the host event feed and show new warnings. */\nexport function GuardToast({ t }: { t: (key: string) => string }): ReactElement | null {\n const [shown, setShown] = useState<Shown[]>([])\n useEffect(() => {\n let since = 0\n let alive = true\n const poll = (): void => {\n fetch(EVENTS_ROUTE + '?since=' + String(since)).then(async response => await response.json() as { events: GuardEvent[] }).then(data => {\n if (!alive || data.events.length === 0) return\n since = data.events[data.events.length - 1]!.seq\n const warnings = data.events.filter(event => event.kind !== 'notice')\n if (warnings.length === 0) return\n const now = Date.now()\n setShown(current => [...warnings.map(event => ({ event, until: now + 8000 })), ...current].slice(0, 5))\n }).catch(() => undefined)\n }\n const timer = setInterval(() => {\n poll()\n const now = Date.now()\n setShown(current => current.filter(item => item.until > now))\n }, 1500)\n poll()\n return () => { alive = false; clearInterval(timer) }\n }, [])\n if (shown.length === 0) return null\n return <div style={{ position: 'fixed', right: 18, bottom: 18, zIndex: 9999, display: 'flex', flexDirection: 'column', gap: 8, maxWidth: 420 }}>\n {shown.map(item => <div key={item.event.seq} style={{\n background: '#3a2a12', color: '#ffdca8', border: '1px solid #8a6a2a', borderRadius: 8,\n padding: '10px 12px', fontSize: 12, lineHeight: 1.5, boxShadow: '0 6px 24px rgba(0,0,0,.45)',\n }}>\n <strong>{t('settings.warningTitle')}</strong>\n <div>{item.event.detail}</div>\n </div>)}\n </div>\n}\n","/** Locale namespace and dictionaries for the browser half. */\nexport const NS = 'evalGuard'\n\nexport const zh = {\n 'settings.nav': '评测守护',\n 'settings.title': '评测守护',\n 'settings.enabled': '启用评测守护',\n 'settings.enabledHint': '启用后,所有用户主对话只能读写自己的工作区,禁止联网、子代理与跨 agent 通信,并按任务时限强制终止。默认关闭。',\n 'settings.runningWarning': '当前有正在运行的对话。启用评测守护会立即约束它们,是否强行开启?',\n 'settings.runningCancel': '放弃',\n 'settings.runningForce': '强行开启',\n 'settings.timeLimit': '开启最长时长',\n 'settings.timeLimitHint': '从每条用户消息发送时开始计时;到点只终止当前轮次,并递归清理子代理与后台任务。',\n 'settings.minutes': '分钟',\n 'settings.forbidden': '额外禁止路径',\n 'settings.forbiddenHint': '每行一个绝对路径;# 开头为注释;! 开头表示在禁止范围内放开该子路径;按行顺序生效。默认空。',\n 'settings.blacklist': '工具黑名单',\n 'settings.blacklistHint': '每行一个工具名;默认内容按当前已安装工具生成,不存在的工具会被忽略。',\n 'settings.reset': '恢复默认黑名单',\n 'settings.editingDefault': '编辑后将以自定义黑名单保存。',\n 'settings.task': '安装 / 评测任务',\n 'settings.taskHint': '选择任务和工作区;安装与评测共用这组选择。安装会写入素材并准备环境,评测只对当前工作区运行一次。',\n 'settings.taskLabel': '任务',\n 'settings.workspace': '工作区',\n 'settings.pickWorkspace': '请选择工作区',\n 'settings.check': '安装任务',\n 'settings.nonEmpty': '工作区不是空的;未执行任何操作。',\n 'settings.manual': '手动通道',\n 'settings.manualHint': '手动复制素材:自己把素材目录内容复制到工作区根目录;手动填充提示词:复制下面的提示词。',\n 'settings.source': '素材路径',\n 'settings.target': '工作区路径',\n 'settings.copy': '复制',\n 'settings.copied': '已复制',\n 'settings.prompt': '初始提示词',\n 'settings.reveal': '在文件管理器中打开',\n 'settings.noWorkspaces': '没有可选的工作区。',\n 'settings.installOk': '任务素材已安装,提示词已填入新会话,请自行发送。',\n 'settings.taskDefaults': '已按任务默认值设置限时:{minutes} 分钟,限时开关 {state}。你可以随后手动修改。',\n 'settings.on': '打开',\n 'settings.off': '关闭',\n 'settings.evaluate': '评测当前工作区',\n 'settings.evalJob': '评测任务',\n 'settings.installJob': '安装任务',\n 'settings.cloneSource': '仓库来源',\n 'settings.pipIndex': 'pip 镜像',\n 'settings.custom': '自定义',\n 'settings.cancel': '取消',\n 'settings.waiting': '正在准备…',\n 'settings.evalHint': '只评测单个工作区,不做排名。评测任务与安装共用上面的工作区和任务选择。',\n 'settings.startSession': '填入新会话',\n 'settings.gitProxy': 'Git 代理',\n 'settings.pipProxy': 'pip 代理',\n 'settings.loading': '加载中…',\n 'settings.recent': '最近事件',\n 'settings.none': '暂无。',\n 'settings.warningTitle': '评测守护警告',\n 'settings.close': '关闭',\n} as const\n\nexport type Key = keyof typeof zh\n\nexport const en: Record<Key, string> = {\n 'settings.nav': 'Eval Guard',\n 'settings.title': 'Eval Guard',\n 'settings.enabled': 'Enable evaluation guard',\n 'settings.enabledHint': 'When on, every user main conversation may only read/write its own workspace, with network, subagents and cross-agent channels blocked, and a wall-clock limit. Off by default.',\n 'settings.runningWarning': 'Conversations are running right now. Enabling the guard will constrain them immediately. Force enable?',\n 'settings.runningCancel': 'Cancel',\n 'settings.runningForce': 'Force enable',\n 'settings.timeLimit': 'Enable time limit',\n 'settings.timeLimitHint': 'The clock starts at each user message; at the deadline only the current turn is cancelled, and subagents/jobs are cleaned up recursively.',\n 'settings.minutes': 'minutes',\n 'settings.forbidden': 'Extra forbidden paths',\n 'settings.forbiddenHint': 'One absolute path per line; # comments; ! re-allows a subpath; later lines win. Empty by default.',\n 'settings.blacklist': 'Tool blacklist',\n 'settings.blacklistHint': 'One tool name per line; the default is generated from the tools installed now and missing tools are ignored.',\n 'settings.reset': 'Reset default blacklist',\n 'settings.editingDefault': 'Editing switches this to a custom blacklist.',\n 'settings.task': 'Install / evaluate task',\n 'settings.taskHint': 'Pick a task and workspace; install and evaluation share this selection. Install writes the task and prepares the environment; evaluation runs once on the current workspace.',\n 'settings.taskLabel': 'Task',\n 'settings.workspace': 'Workspace',\n 'settings.pickWorkspace': 'Pick a workspace',\n 'settings.check': 'Install task',\n 'settings.nonEmpty': 'The workspace is not empty; nothing was changed.',\n 'settings.manual': 'Manual channel',\n 'settings.manualHint': 'Manual material copy: copy the source folder contents into the workspace root yourself. Manual prompt: copy the text below.',\n 'settings.source': 'Material path',\n 'settings.target': 'Workspace path',\n 'settings.copy': 'Copy',\n 'settings.copied': 'Copied',\n 'settings.prompt': 'Initial prompt',\n 'settings.reveal': 'Open in file manager',\n 'settings.noWorkspaces': 'No workspace is available.',\n 'settings.installOk': 'Task installed and the prompt was seeded into a new conversation; send it yourself.',\n 'settings.taskDefaults': 'Applied task defaults: {minutes} minutes, time limit {state}. You can change them afterwards.',\n 'settings.on': 'on',\n 'settings.off': 'off',\n 'settings.evaluate': 'Evaluate current workspace',\n 'settings.evalJob': 'Evaluation job',\n 'settings.installJob': 'Install job',\n 'settings.cloneSource': 'Clone source',\n 'settings.pipIndex': 'pip index',\n 'settings.custom': 'Custom',\n 'settings.cancel': 'Cancel',\n 'settings.waiting': 'Preparing…',\n 'settings.evalHint': 'Evaluates one workspace only; no ranking. Uses the same workspace/task selection as install.',\n 'settings.startSession': 'Open in new conversation',\n 'settings.gitProxy': 'Git proxy',\n 'settings.pipProxy': 'pip proxy',\n 'settings.cifarProxy': 'CIFAR download proxy',\n 'settings.loading': 'Loading…',\n 'settings.recent': 'Recent events',\n 'settings.none': 'None.',\n 'settings.warningTitle': 'Eval Guard warning',\n 'settings.close': 'Close',\n}\n","/**\n * Evaluation guard, browser half: the Settings section, the warning toast, and\n * the shell bridge used to seed a new conversation with the task prompt.\n * @module dsh-eval-guard/client\n */\nimport type { Context } from '@deepseek-ai/cordis'\nimport { SETTINGS_NS } from '../shared.ts'\nimport { EvalGuardSettings } from './Settings.tsx'\nimport { GuardToast } from './Toast.tsx'\nimport { configureEvalBridge } from './bridge.ts'\nimport { en, NS, zh, type Key } from './locales.ts'\n\ndeclare module '@deepseek-ai/dsh-client-ui-slots' {\n interface LocaleNamespaceMap {\n evalGuard: Key\n }\n}\n\nexport const inject = ['slots', 'locale', 'configForms', 'uiWorkspace']\n\nexport function apply(ctx: Context): void {\n ctx.effect(() => ctx.locale.register(NS, { zh, en }))\n configureEvalBridge({\n startSession: (workspaceId, prompt) => {\n ctx.uiWorkspace.startSession(workspaceId as Parameters<typeof ctx.uiWorkspace.startSession>[0], { prompt })\n },\n workspaces: () => {\n const service = (ctx as unknown as { get(key: string): unknown }).get('workspaces') as\n { list?: { getSnapshot(): { items?: readonly Record<string, unknown>[] } } } | undefined\n const items = service?.list?.getSnapshot().items ?? []\n return items.map((item, index) => ({\n id: typeof item['workspaceId'] === 'string' ? item['workspaceId'] : String(item['id'] ?? index),\n label: typeof item['title'] === 'string' && item['title'] !== ''\n ? item['title']\n : String(item['path'] ?? item['workspaceId'] ?? ('workspace ' + String(index + 1))),\n }))\n },\n })\n ctx.effect(() => () => { configureEvalBridge(undefined) })\n const t = ctx.locale.bind(NS)\n const form = ctx.configForms.get(SETTINGS_NS) as {\n getSnapshot(): unknown\n subscribe(listener: () => void): () => void\n mutate(ops: never, revision?: number): unknown\n }\n const formFace = {\n getSnapshot: () => form.getSnapshot(),\n subscribe: (listener: () => void) => form.subscribe(listener),\n mutate: (ops: never, revision?: number) => form.mutate(ops, revision),\n }\n ctx.slots.inject('settings.section', () => ctx.slots.register({\n name: 'settings.section', id: SETTINGS_NS, order: 41,\n label: () => t('settings.nav'), locale: NS,\n inject: () => ({ form: formFace }),\n }, EvalGuardSettings))\n ctx.slots.inject('shell.overlay', () => ctx.slots.register({\n name: 'shell.overlay', id: SETTINGS_NS + '.toast', locale: NS,\n inject: () => ({ t }),\n }, GuardToast))\n}\n"],"mappings":"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"}
package/lib/index.js CHANGED
@@ -24,7 +24,8 @@ const Config = z.object({
24
24
  pipIndex: z.string().default("pypi").volatile(),
25
25
  customPipUrl: z.string().default("").volatile(),
26
26
  gitProxyUrl: z.string().default("").volatile(),
27
- pipProxyUrl: z.string().default("").volatile()
27
+ pipProxyUrl: z.string().default("").volatile(),
28
+ cifarProxyUrl: z.string().default("").volatile()
28
29
  });
29
30
  /** Clamp and normalize a live configuration object. */
30
31
  function resolveConfig(value) {
@@ -41,7 +42,8 @@ function resolveConfig(value) {
41
42
  pipIndex: typeof value?.pipIndex === "string" && value.pipIndex !== "" ? value.pipIndex : "pypi",
42
43
  customPipUrl: typeof value?.customPipUrl === "string" ? value.customPipUrl : "",
43
44
  gitProxyUrl: typeof value?.gitProxyUrl === "string" ? value.gitProxyUrl : "",
44
- pipProxyUrl: typeof value?.pipProxyUrl === "string" ? value.pipProxyUrl : ""
45
+ pipProxyUrl: typeof value?.pipProxyUrl === "string" ? value.pipProxyUrl : "",
46
+ cifarProxyUrl: typeof value?.cifarProxyUrl === "string" ? value.cifarProxyUrl : ""
45
47
  };
46
48
  }
47
49
  //#endregion
@@ -78,6 +80,8 @@ const NEURAL_CPP_TASK = "neural-cpp";
78
80
  const NEURAL_CPP_TASK_LABEL = "Neural-CPP · 纯 C++ 张量后端";
79
81
  const NEURAL_FP32_TASK = "neural-fp32";
80
82
  const NEURAL_FP32_TASK_LABEL = "Neural-FP32 · 运算与性能";
83
+ const NEURAL_CIFAR_TASK = "neural-cifar";
84
+ const NEURAL_CIFAR_TASK_LABEL = "Neural-CIFAR · 从零训练图像分类";
81
85
  /** Common pip indexes offered by the settings page. */
82
86
  const PIP_MIRRORS = [
83
87
  {
@@ -820,7 +824,8 @@ var Guard = class {
820
824
  pipIndex: read("pipIndex"),
821
825
  customPipUrl: read("customPipUrl"),
822
826
  gitProxyUrl: read("gitProxyUrl"),
823
- pipProxyUrl: read("pipProxyUrl")
827
+ pipProxyUrl: read("pipProxyUrl"),
828
+ cifarProxyUrl: read("cifarProxyUrl")
824
829
  });
825
830
  }
826
831
  /** Apply a new configuration document. */
@@ -1691,6 +1696,14 @@ const TASKS = [
1691
1696
  timeLimitMinutes: 1440,
1692
1697
  timeLimitEnabled: false,
1693
1698
  needsSetup: true
1699
+ },
1700
+ {
1701
+ id: NEURAL_CIFAR_TASK,
1702
+ label: NEURAL_CIFAR_TASK_LABEL,
1703
+ description: "从零实现纯 C++ 训练框架,构造并训练 CIFAR-10 图像分类网络;保留算子指标并统计验证集准确率与多线程推理性能。",
1704
+ timeLimitMinutes: 1440,
1705
+ timeLimitEnabled: false,
1706
+ needsSetup: true
1694
1707
  }
1695
1708
  ];
1696
1709
  /** The tank task definition (original prompt; only halftime mechanics removed). */
@@ -1960,6 +1973,41 @@ const NEURAL_FP32_DEFINITION = {
1960
1973
  ].join("\n");
1961
1974
  }
1962
1975
  };
1976
+ /** CIFAR-10 training task. */
1977
+ const NEURAL_CIFAR_DEFINITION = {
1978
+ id: NEURAL_CIFAR_TASK,
1979
+ label: NEURAL_CIFAR_TASK_LABEL,
1980
+ description: TASKS[10].description,
1981
+ asset: path.join(packageRoot(), "assets", "neural-cifar", "workspace.zip"),
1982
+ timeLimitMinutes: 1440,
1983
+ timeLimitEnabled: false,
1984
+ needsSetup: true,
1985
+ prompt() {
1986
+ return [
1987
+ "你是一名世界顶尖的神经网络全栈设计与优化工程师,也是一名以“榨干每一分合法算力”为信条的竞赛选手。任务:从零实现纯 C++17、仅 CPU 的 FP32 训练框架(算子、反向、优化器、固定 CLI),并用同一框架训练 CIFAR-10 图像分类网络。评测会分别报告隐藏验证集准确率、推理性能、以及保留的算子正确性/误差/速度;不提供统一总分,各项权重未知——因此不要把任何一项做成短板。",
1988
+ "",
1989
+ "请先完整阅读 TASK.md 与 CLI 协议,它是权威规则;在规则模糊处按本提示的保守口径执行,并把理解写入 NOTES.md。硬约束:仅 Linux + GCC + C++17 标准库,固定 fp32,无 Python/OpenCL/CUDA/BLAS/Eigen/第三方库;必须产出 build/nn_task、build/train、build/infer 并留下可加载的 model/;工作区提供 50k train split,评测使用独立隐藏验证集。线程:由你发起的所有运行(开发、自测、算子基准、训练)一律最多 4 个 worker;`infer --threads N` 必须能正确处理不同线程数,但本地自测固定 4;把分块/归约逻辑与线程数解耦,用纯函数单元测试覆盖不同分块的正确性。算子速度不是准确率的竞争者而是共同乘数:更快的 matmul/conv 意味着同样时间能跑更多 epoch,也直接抬高推理 FPS;但任何速度优化都不能牺牲正确性。",
1990
+ "",
1991
+ "你只需要把全部精力放在把结果做到最好:穷尽优化、持续实验、自我批判。评测由独立数据和外部约束执行,不要让对边界的担心分散注意力;把能复现的结果、命令和文件留在工作区即可。",
1992
+ "",
1993
+ "工作方式:",
1994
+ "0) 先必要算子 + 便宜完整基线:尽快实现让 CIFAR 训练跑通所需的最小算子/反向/优化器/线程池与三个 CLI,短训出 model/,端到端跑通 train→infer,拿到第一个本地 holdout 准确率与单图耗时。先保证可交付,再谈优化。",
1995
+ "1) 补全算子正确性(昂贵搜索前必须过门):用独立 double 标量参考、有限差分梯度检查,以及边界形状/广播/分组/步长/空洞/非方形核/softmax 数值稳定/AdamW step 偏置/N=1/H/W<kernel/fp32 写出等用例,逐算子记录误差到 NOTES.md;每次改 conv/matmul/线程池后重测受影响算子与端到端推理。",
1996
+ "2) 持续探索:不断提出实质性不同的架构/训练假设并做可比较的 pilot,一次只改一个主变量;固定可复现的分层 holdout(种子写死),holdout 仅用于评估,不参与训练、增强或归一化统计;把假设、唯一改动、命令、种子、划分、准确率、耗时、算子指标、结论记入 RESULTS.md 排名表。候选扩大训练前先看 pilot 信号;胜出方向继续做单变量消融,最终选择尽量在另一个独立划分/种子上复核。时间无限,持续寻找更高价值的方向;不要跑一个配置就收。",
1997
+ "3) 深挖:学习率/调度/weight decay/增强/标签平滑/EMA/网络结构/推理优化(BN 融合、卷积实现、多线程分块、内存复用);TTA 与集成只在实测准确率收益值得其 FPS 代价时采用;使用 BatchNorm 必须把 running mean/var 固化进 model/ 并在 infer 使用。任何提升若接近噪声,都要结合 5k holdout 抽样误差、随机种子波动和独立复核划分综合判断,不能当成硬阈值;给出准确率-速度 Pareto 权衡再选配置。",
1998
+ "4) 锁定与重训:冻结配置后用全部 50k 重训最终权重(自测 holdout 回归训练集);反复在同一 holdout 上挑选会产生选择性偏差,报告保守期望而非最好一次;CIFAR-10 测试集约 3.3% 与训练集近重复,自测可能偏乐观,按保守口径。长训练必须 checkpoint + resume。",
1999
+ "5) 交付审计:清空/新建 build 目录后 cmake -S . -B build -DCMAKE_BUILD_TYPE=Release && cmake --build build -j4,确认三个二进制从零构建;跑自己的全操作自测(覆盖协议与边界);用真实图像字节跑 infer(4 线程),核对输出为 N 个 uint8;确认无 NaN/崩溃、无绝对路径、不依赖开发进程或临时构建产物。保留已验证的最佳模型,退步立即回退。",
2000
+ "",
2001
+ "时间无限,持续优化,不要因为基线跑通就结束;始终保证工作区处于可评测状态:三个 CLI 可构建、model/ 可加载、退步可回滚。能跑通或超过朴素基线不代表够强,正式对手远强于此。",
2002
+ "",
2003
+ "自我批判:假设自测数字被高估了 0.5%,找出高估来源(holdout 被反复选择、增强/统计泄漏、数据顺序、随机性、口径不一致、单次运气),用不同种子/划分/更严口径复核;主动红队实现(极端与边界形状、大/小数值、eps/溢出、groups/dilation/stride 组合、线程数与确定性、长训练内存与数值稳定性)。",
2004
+ "",
2005
+ "诚实汇报:完成后给出网络结构与训练方法、自测划分与实测结果、推理 FPS 与单图耗时、算子自测结果与已知风险、留下的命令与文件清单。所有数字必须能由留下的命令复现。",
2006
+ "",
2007
+ "不要向我提问,也不要等待确认,独立完成。"
2008
+ ].join("\n");
2009
+ }
2010
+ };
1963
2011
  /** All task definitions keyed by id. */
1964
2012
  const TASK_DEFINITIONS = {
1965
2013
  [TANK_TASK]: TANK_DEFINITION,
@@ -1971,7 +2019,8 @@ const TASK_DEFINITIONS = {
1971
2019
  [SWE_BENCH_PRO_TASK]: SWE_BENCH_PRO_DEFINITION,
1972
2020
  [FEATUREBENCH_TASK]: FEATUREBENCH_DEFINITION,
1973
2021
  [NEURAL_CPP_TASK]: NEURAL_CPP_DEFINITION,
1974
- [NEURAL_FP32_TASK]: NEURAL_FP32_DEFINITION
2022
+ [NEURAL_FP32_TASK]: NEURAL_FP32_DEFINITION,
2023
+ [NEURAL_CIFAR_TASK]: NEURAL_CIFAR_DEFINITION
1975
2024
  };
1976
2025
  var TaskService = class {
1977
2026
  guard;
@@ -2076,7 +2125,8 @@ var TaskService = class {
2076
2125
  ".repo",
2077
2126
  "setup.sh",
2078
2127
  "remove.patch",
2079
- "spec.pdf.bz2"
2128
+ "spec.pdf.bz2",
2129
+ "cifar_cache.py"
2080
2130
  ]) try {
2081
2131
  fs.rmSync(path.join(workspacePath, name), {
2082
2132
  recursive: true,
@@ -2118,7 +2168,8 @@ var TaskService = class {
2118
2168
  EVAL_PIP_INDEX_URL: this.pipIndexUrl(options),
2119
2169
  GIT_TERMINAL_PROMPT: "0",
2120
2170
  EVAL_GIT_PROXY: this.proxyValue(options.gitProxyUrl),
2121
- EVAL_PIP_PROXY: this.proxyValue(options.pipProxyUrl)
2171
+ EVAL_PIP_PROXY: this.proxyValue(options.pipProxyUrl),
2172
+ EVAL_CIFAR_PROXY: this.proxyValue(options.cifarProxyUrl)
2122
2173
  };
2123
2174
  const command = definition.needsSetup ? ["bash", "setup.sh"] : [
2124
2175
  "bash",
@@ -2193,7 +2244,8 @@ var TaskService = class {
2193
2244
  cwd: packageRoot(),
2194
2245
  env: {
2195
2246
  PYTHONPATH: "",
2196
- PYTHONHOME: ""
2247
+ PYTHONHOME: "",
2248
+ EVAL_CIFAR_PROXY: this.proxyValue(this.guard.configuration.cifarProxyUrl)
2197
2249
  }
2198
2250
  }).id
2199
2251
  };
@@ -2395,7 +2447,8 @@ function registerRoutes(ctx, guard, tasks) {
2395
2447
  pipIndex: typeof body.pipIndex === "string" ? body.pipIndex : config.pipIndex,
2396
2448
  customPipUrl: typeof body.customPipUrl === "string" ? body.customPipUrl : config.customPipUrl,
2397
2449
  gitProxyUrl: typeof body.gitProxyUrl === "string" ? body.gitProxyUrl : config.gitProxyUrl,
2398
- pipProxyUrl: typeof body.pipProxyUrl === "string" ? body.pipProxyUrl : config.pipProxyUrl
2450
+ pipProxyUrl: typeof body.pipProxyUrl === "string" ? body.pipProxyUrl : config.pipProxyUrl,
2451
+ cifarProxyUrl: typeof body.cifarProxyUrl === "string" ? body.cifarProxyUrl : config.cifarProxyUrl
2399
2452
  }));
2400
2453
  }
2401
2454
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-eval-guard",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "type": "module",
5
5
  "description": "Evaluation guard for DSH: workspace-only filesystem, no network/subagents, wall-clock limits, and task installation for the meow-ai-arena tank task.",
6
6
  "license": "MIT",