dsh-eval-guard 0.7.6 → 0.7.8

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/ISSUES.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # dsh-eval-guard 问题清单与修复记录
2
2
 
3
- > 版本:0.7.6 · 审计基线:本仓库工作树(含 0.7.6 的 Neural-Pendulum Tier A 评测)
3
+ > 版本:0.7.8 · 审计基线:本仓库工作树(0.7.8 增加后台任务提醒与未完成 turn 拦截)
4
4
  > 对照 DSH:0.2.1-alpha.1 源码(并核对 git tag 0.1.2 / 0.1.5 / 0.1.7 / 0.2.0-rc.1 / rc.2 / 0.2.1-alpha.1)
5
5
  > 本文件先记录问题,再记录修复状态。状态:✅ 已修复 / 🟡 部分修复 / ⛔ 保留(有明确原因或需要架构级改动)
6
6
  >
@@ -8,7 +8,11 @@
8
8
  >
9
9
  > **2026-10-23 会话回归修复(未发版)**:修复 Neural-Pendulum 仿真器 Coriolis 项多乘 cos 导致高转速下能量注入并产生 NaN;修正关节 3 在绝对角坐标下的广义力矩映射,由 (tau1,0,tau3) 改为 (tau1,-tau3,tau3);TASK/SPEC/prompt 明确 theta 约定并说明工作区无 PyTorch/numpy;网络 syscall 改为 AF_INET/AF_INET6 的 EPERM 软拒绝,避免 pip/NSS 本地检查被误杀。
10
10
 
11
- > **0.7.6**:Neural-Pendulum 切换为 Tier A 评测:每回合随机化隐藏物理参数、初始状态与观测噪声(无摩擦/滞后/延迟),评测改为 100 个隐藏随机回合的成功率,成功率 >= 0.8 完成;计分改为按成功率归一化。训练仿真器与评测仿真器均实现随机化,工作区仍只交付二进制,不提供仿真源码。
11
+ > **0.7.8**:新增后台任务守卫:每 0–60 分钟(默认 5 分钟)在下一次工具结果附带 running host jobs + 本工作区 OS 进程提醒;未 completed 时在 agent/turn-stopping 通过 agent.steer 继续 turn,用户手动停止或既有时间上限放行;eval_test 低分时附加“换方向/清理后台”提醒。
12
+ >
13
+ > **0.7.7**:Neural-Pendulum 完成阈值提高到 0.90;prompt/TASK 声明任务已验证可完成、未 completed 前禁止停止;最终 build/control 必须由神经网络输出层直接产生力矩,最终控制程序不得含显式控制律;禁止逆向已编译文件或读取进程内存。另新增审核人员专用包 neural-pendulum-audit(不进入 workspace/npm 任务资产)。
14
+ >
15
+ > **0.7.6**:Neural-Pendulum 切换为 Tier A 评测:每回合随机化隐藏物理参数、初始状态与观测噪声(无摩擦/滞后/延迟),评测改为 100 个隐藏随机回合的成功率,成功率 >= 0.9 完成;计分改为按成功率归一化。训练仿真器与评测仿真器均实现随机化,工作区仍只交付二进制,不提供仿真源码。
12
16
  >
13
17
  > **0.7.5**:把 0.7.4 误带的开发用 RL 可行性代码从插件中撤除,只保留修正后的 simulator;同时把 agent 训练仿真器与评测仿真器拆开:`assets/neural-pendulum/sim_agent` 只做随机近向下 reset,评测用 `neural-pendulum-eval/sim_eval` 每个 reset 采样新的隐藏物理参数/初始状态/观测噪声;工作区仍只交付二进制,不提供仿真源码。工作区仍只交付二进制,不提供仿真源码。
14
18
  > **下文仍有若干条目标记为 ✅ 但实际未完成,不要再按旧状态理解**:arena legacy 的 `std::thread` 静态规则未移除;`cifar_cache.py` 解压仍无 filter、缓存路径仍用 `Path.home()/.dsh`;CIFAR 隐藏标签仍以文件形式落盘;FP32“30 分钟整轮”仍是 op 间检查;无 baseline 时评测仍 fail-open。其余任务相关修复按用户要求暂不动。
@@ -1,9 +1,9 @@
1
- # Neural-Pendulum 任务规格 v1.5
1
+ # Neural-Pendulum 任务规格 v1.6
2
2
 
3
3
  本文件是已确定的任务内部规格。实现、评测器、workspace 素材以此为准。
4
4
  后续除非明确修改规格,否则不再重新讨论这些规则。
5
5
 
6
- v1.5 变更:Tier A 控制任务。每回合随机化隐藏物理参数、初始状态与观测噪声;评测改为 100 个隐藏随机回合上的成功率,成功率 >= 0.8 完成。基础设施评测协议不变。
6
+ v1.6 变更:完成阈值提高到 0.90;最终 build/control 的力矩必须由神经网络输出层直接产生,最终控制程序不得包含显式控制律;未 completed 不得停止;禁止逆向/进程内存分析。基础设施评测协议不变。
7
7
 
8
8
  ## 1. 任务标识
9
9
 
@@ -19,7 +19,7 @@ agent 必须:
19
19
 
20
20
  1. 从零实现一套神经网络基础设施(张量、算子、反向传播、优化器、线程池;控制器权重的打包方式自定,评测不要求特定序列化格式)。
21
21
  2. 使用该基础设施训练一个神经网络控制器。
22
- 3. 控制预编译双驱动三节摆:第一、第三关节施加有限力矩,中间关节被动,从全向下起摆,并保持三根杆全部向上至少 t_tgt = 10.0 s;评测在 100 个随机隐藏回合上统计成功率,成功率 >= 0.8 完成。
22
+ 3. 控制预编译双驱动三节摆:第一、第三关节施加有限力矩,中间关节被动,从全向下起摆,并保持三根杆全部向上至少 t_tgt = 10.0 s;评测在 100 个随机隐藏回合上统计成功率,成功率 >= 0.9 完成。
23
23
  4. 保证基础设施通过 `build/nn_task` 固定 CLI 的数值评测:评测侧用 PyTorch 在相同数据上计算参考值,逐操作比较加权平均相对误差并对照阈值。
24
24
  5. 提交的源码中不得出现 torch;候选运行时不提供 Python/torch。
25
25
 
@@ -248,7 +248,7 @@ dt = 0.01 s
248
248
  t_tgt = 10.0 s
249
249
  全向上容差 = 每根杆与竖直方向夹角 <= 0.05 rad
250
250
  评测回合数 = 100
251
- 完成成功率阈值 = 0.8
251
+ 完成成功率阈值 = 0.9
252
252
  ~~~
253
253
 
254
254
  单回合 t_can 定义:
@@ -270,7 +270,7 @@ t_can = 100 回合 t_can 的平均值(仅用于报告)
270
270
 
271
271
  ~~~
272
272
  infra_ok == true(全部算子可执行且误差不超阈值)
273
- 且 success_rate >= 0.8
273
+ 且 success_rate >= 0.9
274
274
  ~~~
275
275
 
276
276
  ## 10. 提交与测试事件
@@ -309,8 +309,8 @@ compile CMake 构建失败,或未产出 build/nn_task / build/control
309
309
  infra build/nn_task 算子数值评测失败(不可执行/崩溃/超时/输出缺失/误差超阈值)
310
310
  controller 控制器启动/协议/崩溃/超时/非法输出
311
311
  simulation 仿真异常/NaN/仿真超时
312
- scoring 正常测试但 success_rate < 0.8
313
- completed success_rate >= 0.8,任务完成
312
+ scoring 正常测试但 success_rate < 0.9
313
+ completed success_rate >= 0.9,任务完成
314
314
  ~~~
315
315
 
316
316
  ### 返回给 agent 的测试结果
@@ -344,7 +344,7 @@ score = -1
344
344
  有效测试:
345
345
 
346
346
  ~~~
347
- score = (min(success_rate, 0.8) - 0.8) / 0.8
347
+ score = (min(success_rate, 0.9) - 0.9) / 0.9
348
348
  ~~~
349
349
 
350
350
  范围:
@@ -380,7 +380,7 @@ T_done 是第一次返回 stage = completed 的测试请求时间。
380
380
 
381
381
  ~~~
382
382
  stage = completed
383
- success_rate >= 0.8
383
+ success_rate >= 0.9
384
384
  infra_ok = true
385
385
  ~~~
386
386
 
@@ -98,11 +98,22 @@ success_rate = 成功回合数 / 100
98
98
 
99
99
  当:
100
100
 
101
- success_rate >= 0.8
101
+ success_rate >= 0.9
102
102
  且神经网络基础设施数值评测全部通过
103
103
 
104
104
  任务完成,计时停止。
105
105
 
106
+ 该任务已由内部基线验证:100 回合成功率 >= 0.90 是可达的,不要怀疑可行性。在 eval_test 返回 stage=completed 之前,绝对不允许停止、总结或放弃;不要因为成功率接近 0.90、遇到平台期或短期没有提升就收尾。只要没有完成,就必须继续训练、改进、提交和测试,直到完成或外部强制停止。
107
+
108
+ 最终提交的 build/control 必须由神经网络输出层直接产生两个力矩;最终控制程序中不得包含任何显式控制律(PID/LQR/MPC/滑模/自抗扰等),也不得在神经网络之外根据状态计算或修正力矩。
109
+
110
+ 不得对已编译文件进行任何形式的逆向、反汇编、strings/objdump/readelf/gdb 分析,也不得读取 /proc 或其它进程内存。环境信息只能来自本文件/SPEC.md 和正常使用 tools/sim 的 reset/step 输入输出;违规者成绩无效。
111
+
112
+ 后台任务管理:长时间实验必须使用宿主管理的 run_in_background,禁止 nohup、setsid、disown 或尾随 & 脱管。启动任何长任务前先 job_list;同时最多保留 2 个后台任务;同一实验不要重复启动;读完日志且不再需要后立即 job_kill 或用受控方式清理。每约 5 分钟,下一次工具结果会附带当前 running 后台任务和本工作区 OS 进程提醒;看到提醒必须立即处理,不要等用户提醒。开始新方向、提交或最终回答前,必须清理所有不用的 job、训练进程和 tools/sim,确认没有残留。
113
+
114
+ 如果当前方向失败,必须记录失败原因、清理无用后台任务,并换一个实质性不同的方向继续;不要重复同一配置,也不要因为一次失败就断定任务不可做。只有 stage=completed 或外部手动停止才是结束条件。
115
+
116
+
106
117
  ## 训练用仿真接口
107
118
 
108
119
  tools/sim 使用 JSONL 协议。
@@ -358,8 +369,8 @@ completed
358
369
  - infra:build/nn_task 算子数值评测失败(不可执行、崩溃、超时、输出缺失或误差超阈值)
359
370
  - controller:控制器启动、协议、崩溃、超时或输出非法
360
371
  - simulation:隐藏仿真推进异常、NaN 或超时
361
- - scoring:测试有效,但 `success_rate < 0.8`
362
- - completed:基础设施和仿真均通过,且 `success_rate >= 0.8`
372
+ - scoring:测试有效,但 `success_rate < 0.9`
373
+ - completed:基础设施和仿真均通过,且 `success_rate >= 0.9`
363
374
 
364
375
  最终排行分数不会返回给你,只用于赛后排名。
365
376
 
@@ -369,7 +380,7 @@ completed
369
380
 
370
381
  ~~~
371
382
  stage = completed
372
- success_rate >= 0.8
383
+ success_rate >= 0.9
373
384
  ~~~
374
385
 
375
386
  即任务完成。
@@ -410,13 +421,13 @@ success_rate >= 0.8
410
421
  score(t) = -1
411
422
 
412
423
  有效测试:
413
- score(t) = (min(success_rate, 0.8) - 0.8) / 0.8
424
+ score(t) = (min(success_rate, 0.9) - 0.9) / 0.9
414
425
 
415
426
  其中:
416
427
 
417
428
  success_rate 的范围是 [0, 1]
418
429
  success_rate = 0 时 score = -1
419
- success_rate >= 0.8 时 score = 0
430
+ success_rate >= 0.9 时 score = 0
420
431
 
421
432
  分数从测试请求时刻开始生效,直到下一次测试请求。
422
433
 
@@ -458,5 +469,5 @@ T_done 是第一次返回 completed 的测试请求时间。
458
469
  2. 先实现最小可用的 tensor/算子/反向/优化器/线程池,并让 build/nn_task 跑通
459
470
  3. 用独立 double 标量参考、有限差分梯度检查逐算子核对误差,边界形状/广播/groups/stride/dilation 都要覆盖(工作区没有 PyTorch/numpy)
460
471
  4. 用 tools/sim 采集数据并训练控制器,导出权重供 build/control 使用
461
- 5. 反复提交和测试,优先把 100 回合成功率提升到 80%
472
+ 5. 反复提交和测试,优先把 100 回合成功率提升到 90%
462
473
  6. 完成后立即总结
@@ -83,6 +83,7 @@ window.__ModuleLoader__.load({
83
83
  enabled: false,
84
84
  timeLimitEnabled: true,
85
85
  timeLimitMinutes: 90,
86
+ jobReminderMinutes: 5,
86
87
  forbiddenPaths: "",
87
88
  toolBlacklistUseDefault: true,
88
89
  toolBlacklist: "",
@@ -150,6 +151,7 @@ window.__ModuleLoader__.load({
150
151
  enabled: value?.enabled === true,
151
152
  timeLimitEnabled: value?.timeLimitEnabled !== false,
152
153
  timeLimitMinutes: typeof value?.timeLimitMinutes === "number" ? value.timeLimitMinutes : 90,
154
+ jobReminderMinutes: typeof value?.jobReminderMinutes === "number" ? value.jobReminderMinutes : 5,
153
155
  forbiddenPaths: typeof value?.forbiddenPaths === "string" ? value.forbiddenPaths : "",
154
156
  toolBlacklistUseDefault: value?.toolBlacklistUseDefault !== false,
155
157
  toolBlacklist: typeof value?.toolBlacklist === "string" ? value.toolBlacklist : "",
@@ -855,38 +857,65 @@ window.__ModuleLoader__.load({
855
857
  }),
856
858
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
857
859
  style: box,
858
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
859
- style: row,
860
- children: [
861
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", { children: [
860
+ children: [
861
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
862
+ style: row,
863
+ children: [
864
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", { children: [
865
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
866
+ type: "checkbox",
867
+ checked: draft.timeLimitEnabled,
868
+ disabled: !ready,
869
+ onChange: (event) => void save({ timeLimitEnabled: event.target.checked })
870
+ }),
871
+ " ",
872
+ t("settings.timeLimit")
873
+ ] }),
862
874
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
863
- type: "checkbox",
864
- checked: draft.timeLimitEnabled,
875
+ type: "number",
876
+ min: 1,
877
+ max: 1440,
878
+ value: draft.timeLimitMinutes,
865
879
  disabled: !ready,
866
- onChange: (event) => void save({ timeLimitEnabled: event.target.checked })
880
+ style: { width: 90 },
881
+ onChange: (event) => edit({ timeLimitMinutes: Number(event.target.value) }),
882
+ onBlur: () => void save({ timeLimitMinutes: draft.timeLimitMinutes })
867
883
  }),
868
- " ",
869
- t("settings.timeLimit")
870
- ] }),
871
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
872
- type: "number",
873
- min: 1,
874
- max: 1440,
875
- value: draft.timeLimitMinutes,
876
- disabled: !ready,
877
- style: { width: 90 },
878
- onChange: (event) => edit({ timeLimitMinutes: Number(event.target.value) }),
879
- onBlur: () => void save({ timeLimitMinutes: draft.timeLimitMinutes })
880
- }),
881
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
882
- style: note,
883
- children: t("settings.minutes")
884
- })
885
- ]
886
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
887
- style: note,
888
- children: t("settings.timeLimitHint")
889
- })]
884
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
885
+ style: note,
886
+ children: t("settings.minutes")
887
+ })
888
+ ]
889
+ }),
890
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
891
+ style: note,
892
+ children: t("settings.timeLimitHint")
893
+ }),
894
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
895
+ style: row,
896
+ children: [
897
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", { children: t("settings.jobReminder") }),
898
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
899
+ type: "number",
900
+ min: 0,
901
+ max: 60,
902
+ value: draft.jobReminderMinutes,
903
+ disabled: !ready,
904
+ style: { width: 90 },
905
+ onChange: (event) => edit({ jobReminderMinutes: Number(event.target.value) }),
906
+ onBlur: () => void save({ jobReminderMinutes: draft.jobReminderMinutes })
907
+ }),
908
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
909
+ style: note,
910
+ children: t("settings.minutes")
911
+ })
912
+ ]
913
+ }),
914
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
915
+ style: note,
916
+ children: t("settings.jobReminderHint")
917
+ })
918
+ ]
890
919
  }),
891
920
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
892
921
  style: box,
@@ -1052,6 +1081,8 @@ window.__ModuleLoader__.load({
1052
1081
  "settings.runningForce": "强行开启",
1053
1082
  "settings.timeLimit": "开启最长时长",
1054
1083
  "settings.timeLimitHint": "从每条用户消息发送时开始计时;到点只终止当前轮次,并递归清理子代理与后台任务。",
1084
+ "settings.jobReminder": "后台任务提醒间隔",
1085
+ "settings.jobReminderHint": "每隔这么多分钟,在下一次工具结果中附带当前 running jobs 和本工作区 OS 进程;设为 0 关闭。默认 5 分钟。",
1055
1086
  "settings.parallelEval": "多 agent 并行评测",
1056
1087
  "settings.parallelEvalHint": "启用后,安装任务时会在提示词中提醒 agent:运行环境可能因其他 agent 的行为而波动,需要自行适应。",
1057
1088
  "settings.minutes": "分钟",
@@ -1113,6 +1144,8 @@ window.__ModuleLoader__.load({
1113
1144
  "settings.runningForce": "Force enable",
1114
1145
  "settings.timeLimit": "Enable time limit",
1115
1146
  "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.",
1147
+ "settings.jobReminder": "Background-job reminder interval",
1148
+ "settings.jobReminderHint": "Every this many minutes, attach running host jobs and OS processes with cwd in this workspace to the next tool result; 0 disables. Default 5 minutes.",
1116
1149
  "settings.parallelEval": "Parallel agent evaluation",
1117
1150
  "settings.parallelEvalHint": "When enabled, install prompts warn the agent that the runtime may fluctuate because other agents share the machine; it must adapt.",
1118
1151
  "settings.minutes": "minutes",
@@ -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 · 运算与性能'\nexport const NEURAL_CIFAR_TASK = 'neural-cifar'\nexport const NEURAL_CIFAR_TASK_LABEL = 'Neural-CIFAR · 从零训练图像分类'\nexport const NEURAL_PENDULUM_TASK = 'neural-pendulum'\nexport const NEURAL_PENDULUM_TASK_LABEL = 'Neural-Pendulum · 从零训练三节摆控制器'\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 CIFAR_MIRRORS: readonly { id: string; label: string; url: string }[] = [\n { id: 'toronto', label: 'Toronto 官方', url: 'https://www.cs.toronto.edu/~kriz/cifar-10-binary.tar.gz' },\n { id: 'cave', label: 'Toronto Cave', url: 'https://cave.cs.toronto.edu/kriz/cifar-10-binary.tar.gz' },\n]\n\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 /** Why the last enable attempt was refused (for example missing bwrap). */\n error?: string\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, CIFAR_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 cifarMirror: string\n customCifarUrl: string\n parallelEval: boolean\n taskId: 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 cifarMirror: 'toronto',\n customCifarUrl: '',\n parallelEval: false,\n taskId: '',\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 cifarMirror: typeof value?.cifarMirror === 'string' && value.cifarMirror !== '' ? value.cifarMirror : 'toronto',\n customCifarUrl: typeof value?.customCifarUrl === 'string' ? value.customCifarUrl : '',\n parallelEval: value?.parallelEval === true,\n taskId: typeof value?.taskId === 'string' ? value.taskId : '',\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))) {\n if (draft.taskId !== '' && state.tasks.some(task => task.id === draft.taskId)) setTaskId(draft.taskId)\n else setTaskId(state.tasks[0]!.id)\n }\n }, [state, taskId, draft.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) {\n void save({ taskId: next })\n return\n }\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 const patch: Partial<Draft> = {\n taskId: next,\n timeLimitMinutes: task.timeLimitMinutes,\n timeLimitEnabled: task.timeLimitEnabled,\n cloneSource,\n }\n // All task defaults travel in one atomic mutation. Two concurrent mutate()\n // calls with the same revision lose the second half to the CAS guard.\n setDraft(current => ({ ...current, ...patch }))\n setNotice(t('settings.taskDefaults').replace('{minutes}', String(task.timeLimitMinutes)).replace('{state}', task.timeLimitEnabled ? t('settings.on') : t('settings.off')))\n void save(patch)\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 await save({ taskId })\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, cifarMirror: draft.cifarMirror, customCifarUrl: draft.customCifarUrl }),\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 await save({ taskId })\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 {state?.error !== undefined && <p style={{ ...note, color: '#d99' }}>{t('settings.enableError')}: {state.error}</p>}\n {draft.enabled && state !== null && !state.enabled && <p style={{ ...note, color: '#d99' }}>{t('settings.enableInactive')}</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.cifarMirror')}:</span>\n <select value={draft.cifarMirror} disabled={!ready} onChange={event => void save({ cifarMirror: event.target.value })}>\n {CIFAR_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.cifarMirror === 'custom' && <input style={{ width: 320 }} disabled={!ready} value={draft.customCifarUrl}\n onChange={event => edit({ customCifarUrl: event.target.value })} onBlur={() => void save({ customCifarUrl: draft.customCifarUrl })} placeholder=\"https://.../cifar-10-binary.tar.gz\" />}\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 <div style={row}>\n <label><input type=\"checkbox\" checked={draft.parallelEval} disabled={!ready} onChange={event => void save({ parallelEval: event.target.checked })} /> {t('settings.parallelEval')}</label>\n </div>\n <p style={note}>{t('settings.parallelEvalHint')}</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 || (job.status === 'running' || job.status === 'queued' ? 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': '启用后,用户主对话的文件工具被限制在会话工作区(系统目录只读可见,/tmp 为工作区私有临时目录);禁止联网、子代理与跨 agent 通信;并按任务时限强制终止。默认关闭。',\n 'settings.runningWarning': '当前有正在运行的对话。启用评测守护会立即约束它们,是否强行开启?',\n 'settings.runningCancel': '放弃',\n 'settings.runningForce': '强行开启',\n 'settings.timeLimit': '开启最长时长',\n 'settings.timeLimitHint': '从每条用户消息发送时开始计时;到点只终止当前轮次,并递归清理子代理与后台任务。',\n 'settings.parallelEval': '多 agent 并行评测',\n 'settings.parallelEvalHint': '启用后,安装任务时会在提示词中提醒 agent:运行环境可能因其他 agent 的行为而波动,需要自行适应。',\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.enableError': '启用失败',\n 'settings.enableInactive': '开关已保存,但守护未生效:请查看上方错误信息并修复依赖后重试。',\n 'settings.cifarProxy': 'CIFAR 下载代理',\n 'settings.cifarMirror': 'CIFAR 下载镜像',\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, user main conversations keep file tools inside their session workspace (system directories stay read-only visible; /tmp is a private workspace temp dir), network/subagents/cross-agent channels are blocked, and a wall-clock limit applies. 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.parallelEval': 'Parallel agent evaluation',\n 'settings.parallelEvalHint': 'When enabled, install prompts warn the agent that the runtime may fluctuate because other agents share the machine; it must adapt.',\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; a line with * or ? applies to the prefix before the first wildcard. 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.cifarMirror': 'CIFAR download mirror',\n 'settings.loading': 'Loading…',\n 'settings.recent': 'Recent events',\n 'settings.none': 'None.',\n 'settings.warningTitle': 'Eval Guard warning',\n 'settings.enableError': 'Enable failed',\n 'settings.enableInactive': 'The switch was saved, but the guard is not active. See the error above, fix the dependency, then retry.',\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 · 从零训练图像分类'\nexport const NEURAL_PENDULUM_TASK = 'neural-pendulum'\nexport const NEURAL_PENDULUM_TASK_LABEL = 'Neural-Pendulum · 从零训练三节摆控制器'\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 CIFAR_MIRRORS: readonly { id: string; label: string; url: string }[] = [\n { id: 'toronto', label: 'Toronto 官方', url: 'https://www.cs.toronto.edu/~kriz/cifar-10-binary.tar.gz' },\n { id: 'cave', label: 'Toronto Cave', url: 'https://cave.cs.toronto.edu/kriz/cifar-10-binary.tar.gz' },\n]\n\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 /** Why the last enable attempt was refused (for example missing bwrap). */\n error?: string\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, CIFAR_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 jobReminderMinutes: 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 cifarMirror: string\n customCifarUrl: string\n parallelEval: boolean\n taskId: string\n}\n\nconst EMPTY: Draft = {\n enabled: false,\n timeLimitEnabled: true,\n timeLimitMinutes: 90,\n jobReminderMinutes: 5,\n forbiddenPaths: '',\n toolBlacklistUseDefault: true,\n toolBlacklist: '',\n cloneSource: 'github',\n customCloneUrl: '',\n pipIndex: 'pypi',\n customPipUrl: '',\n gitProxyUrl: '',\n pipProxyUrl: '',\n cifarProxyUrl: '',\n cifarMirror: 'toronto',\n customCifarUrl: '',\n parallelEval: false,\n taskId: '',\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 jobReminderMinutes: typeof value?.jobReminderMinutes === 'number' ? value.jobReminderMinutes : 5,\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 cifarMirror: typeof value?.cifarMirror === 'string' && value.cifarMirror !== '' ? value.cifarMirror : 'toronto',\n customCifarUrl: typeof value?.customCifarUrl === 'string' ? value.customCifarUrl : '',\n parallelEval: value?.parallelEval === true,\n taskId: typeof value?.taskId === 'string' ? value.taskId : '',\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))) {\n if (draft.taskId !== '' && state.tasks.some(task => task.id === draft.taskId)) setTaskId(draft.taskId)\n else setTaskId(state.tasks[0]!.id)\n }\n }, [state, taskId, draft.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) {\n void save({ taskId: next })\n return\n }\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 const patch: Partial<Draft> = {\n taskId: next,\n timeLimitMinutes: task.timeLimitMinutes,\n timeLimitEnabled: task.timeLimitEnabled,\n cloneSource,\n }\n // All task defaults travel in one atomic mutation. Two concurrent mutate()\n // calls with the same revision lose the second half to the CAS guard.\n setDraft(current => ({ ...current, ...patch }))\n setNotice(t('settings.taskDefaults').replace('{minutes}', String(task.timeLimitMinutes)).replace('{state}', task.timeLimitEnabled ? t('settings.on') : t('settings.off')))\n void save(patch)\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 await save({ taskId })\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, cifarMirror: draft.cifarMirror, customCifarUrl: draft.customCifarUrl }),\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 await save({ taskId })\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 {state?.error !== undefined && <p style={{ ...note, color: '#d99' }}>{t('settings.enableError')}: {state.error}</p>}\n {draft.enabled && state !== null && !state.enabled && <p style={{ ...note, color: '#d99' }}>{t('settings.enableInactive')}</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.cifarMirror')}:</span>\n <select value={draft.cifarMirror} disabled={!ready} onChange={event => void save({ cifarMirror: event.target.value })}>\n {CIFAR_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.cifarMirror === 'custom' && <input style={{ width: 320 }} disabled={!ready} value={draft.customCifarUrl}\n onChange={event => edit({ customCifarUrl: event.target.value })} onBlur={() => void save({ customCifarUrl: draft.customCifarUrl })} placeholder=\"https://.../cifar-10-binary.tar.gz\" />}\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 <div style={row}>\n <label><input type=\"checkbox\" checked={draft.parallelEval} disabled={!ready} onChange={event => void save({ parallelEval: event.target.checked })} /> {t('settings.parallelEval')}</label>\n </div>\n <p style={note}>{t('settings.parallelEvalHint')}</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 || (job.status === 'running' || job.status === 'queued' ? 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 <div style={row}>\n <label>{t('settings.jobReminder')}</label>\n <input type=\"number\" min={0} max={60} value={draft.jobReminderMinutes} disabled={!ready}\n style={{ width: 90 }} onChange={event => edit({ jobReminderMinutes: Number(event.target.value) })}\n onBlur={() => void save({ jobReminderMinutes: draft.jobReminderMinutes })} />\n <span style={note}>{t('settings.minutes')}</span>\n </div>\n <p style={note}>{t('settings.jobReminderHint')}</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': '启用后,用户主对话的文件工具被限制在会话工作区(系统目录只读可见,/tmp 为工作区私有临时目录);禁止联网、子代理与跨 agent 通信;并按任务时限强制终止。默认关闭。',\n 'settings.runningWarning': '当前有正在运行的对话。启用评测守护会立即约束它们,是否强行开启?',\n 'settings.runningCancel': '放弃',\n 'settings.runningForce': '强行开启',\n 'settings.timeLimit': '开启最长时长',\n 'settings.timeLimitHint': '从每条用户消息发送时开始计时;到点只终止当前轮次,并递归清理子代理与后台任务。',\n 'settings.jobReminder': '后台任务提醒间隔',\n 'settings.jobReminderHint': '每隔这么多分钟,在下一次工具结果中附带当前 running jobs 和本工作区 OS 进程;设为 0 关闭。默认 5 分钟。',\n 'settings.parallelEval': '多 agent 并行评测',\n 'settings.parallelEvalHint': '启用后,安装任务时会在提示词中提醒 agent:运行环境可能因其他 agent 的行为而波动,需要自行适应。',\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.enableError': '启用失败',\n 'settings.enableInactive': '开关已保存,但守护未生效:请查看上方错误信息并修复依赖后重试。',\n 'settings.cifarProxy': 'CIFAR 下载代理',\n 'settings.cifarMirror': 'CIFAR 下载镜像',\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, user main conversations keep file tools inside their session workspace (system directories stay read-only visible; /tmp is a private workspace temp dir), network/subagents/cross-agent channels are blocked, and a wall-clock limit applies. 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.jobReminder': 'Background-job reminder interval',\n 'settings.jobReminderHint': 'Every this many minutes, attach running host jobs and OS processes with cwd in this workspace to the next tool result; 0 disables. Default 5 minutes.',\n 'settings.parallelEval': 'Parallel agent evaluation',\n 'settings.parallelEvalHint': 'When enabled, install prompts warn the agent that the runtime may fluctuate because other agents share the machine; it must adapt.',\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; a line with * or ? applies to the prefix before the first wildcard. 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.cifarMirror': 'CIFAR download mirror',\n 'settings.loading': 'Loading…',\n 'settings.recent': 'Recent events',\n 'settings.none': 'None.',\n 'settings.warningTitle': 'Eval Guard warning',\n 'settings.enableError': 'Enable failed',\n 'settings.enableInactive': 'The switch was saved, but the guard is not active. See the error above, fix the dependency, then retry.',\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
@@ -5,7 +5,7 @@ import path from "node:path";
5
5
  import { execFileSync, spawn, spawnSync } from "node:child_process";
6
6
  import os from "node:os";
7
7
  import { fileURLToPath } from "node:url";
8
- import { createHash } from "node:crypto";
8
+ import { createHash, randomUUID } from "node:crypto";
9
9
  //#region src/config.ts
10
10
  /**
11
11
  * Plugin configuration. The Settings page writes this document through the
@@ -17,6 +17,7 @@ const Config = z.object({
17
17
  enabled: z.boolean().default(false).volatile(),
18
18
  timeLimitEnabled: z.boolean().default(true).volatile(),
19
19
  timeLimitMinutes: z.number().default(90).volatile(),
20
+ jobReminderMinutes: z.number().default(5).volatile(),
20
21
  forbiddenPaths: z.string().default("").volatile(),
21
22
  toolBlacklistUseDefault: z.boolean().default(true).volatile(),
22
23
  toolBlacklist: z.string().default("").volatile(),
@@ -39,6 +40,7 @@ function resolveConfig(value) {
39
40
  enabled: value?.enabled === true,
40
41
  timeLimitEnabled: value?.timeLimitEnabled !== false,
41
42
  timeLimitMinutes: Math.min(1440, Math.max(1, Math.round(minutes))),
43
+ jobReminderMinutes: Math.min(60, Math.max(0, Math.round(Number.isFinite(value?.jobReminderMinutes) ? Number(value?.jobReminderMinutes) : 5))),
42
44
  forbiddenPaths: typeof value?.forbiddenPaths === "string" ? value.forbiddenPaths : "",
43
45
  toolBlacklistUseDefault: value?.toolBlacklistUseDefault !== false,
44
46
  toolBlacklist: typeof value?.toolBlacklist === "string" ? value.toolBlacklist : "",
@@ -2484,7 +2486,17 @@ const NEURAL_PENDULUM_DEFINITION = {
2484
2486
  "",
2485
2487
  "环境细节:joint1 与 joint3 驱动,joint2 被动;控制频率 100 Hz;每回合最多 3000 步(30 s),达到上限后继续 step 返回 {\"error\":\"episode_finished\"},必须 reset。theta=0 表示竖直向下、theta=pi 表示竖直向上;观测 a_i=wrap(theta_i-pi),即三个关节角度(弧度,不除 pi)。环境不返回 reward/loss/cost/done;不提供杆长、质量、惯量、角速度或 tip。训练与评测的每个回合都会随机化物理参数、初始状态和观测噪声;评测在 100 个隐藏随机回合上统计成功率,单回合连续全向上保持 10 s 记成功。",
2486
2488
  "",
2487
- "优化目标:从接近全向下起摆,使三根杆全部进入 0.05 rad 的竖直向上容差并保持;评测指标为 100 个隐藏随机回合上的成功率(每回合连续保持 10 s 记成功),成功率 >= 80% 即完成。损失函数、奖励、优化器、网络结构和训练方法由你自行设计,不规定任何训练方案。",
2489
+ "优化目标:从接近全向下起摆,使三根杆全部进入 0.05 rad 的竖直向上容差并保持;评测指标为 100 个隐藏随机回合上的成功率(每回合连续保持 10 s 记成功),成功率 >= 90% 即完成。损失函数、奖励、优化器、网络结构和训练方法由你自行设计,不规定任何训练方案。",
2490
+ "",
2491
+ "该任务已由内部基线验证:100 回合成功率 >= 0.90 是可达的,不要怀疑可行性。在 eval_test 返回 stage=completed 之前,绝对不允许停止、总结或放弃;不要因为成功率接近 0.90、遇到平台期或短期没有提升就收尾。只要没有完成,就必须继续训练、改进、提交和测试,直到完成或外部强制停止。",
2492
+ "",
2493
+ "最终提交的 build/control 必须由神经网络输出层直接产生两个力矩;最终控制程序中不得包含任何显式控制律(PID/LQR/MPC/滑模/自抗扰等),也不得在神经网络之外根据状态计算或修正力矩。",
2494
+ "",
2495
+ "不得对已编译文件进行任何形式的逆向、反汇编、strings/objdump/readelf/gdb 分析,也不得读取 /proc 或其它进程内存。环境信息只能来自 TASK.md/SPEC.md 和正常使用 tools/sim 的 reset/step 输入输出;违规者成绩无效。",
2496
+ "",
2497
+ "后台任务管理:长时间实验必须使用宿主管理的 run_in_background,禁止 nohup、setsid、disown 或尾随 & 脱管。启动任何长任务前先 job_list;同时最多保留 2 个后台任务;同一实验不要重复启动;读完日志且不再需要后立即 job_kill 或用受控方式清理。每约 5 分钟,下一次工具结果会附带当前 running 后台任务和本工作区 OS 进程提醒;看到提醒必须立即处理,不要等用户提醒。开始新方向、提交或最终回答前,必须清理所有不用的 job、训练进程和 tools/sim,确认没有残留。",
2498
+ "",
2499
+ "如果当前方向失败,必须记录失败原因、清理无用后台任务,并换一个实质性不同的方向继续;不要重复同一配置,也不要因为一次失败就断定任务不可做。只有 stage=completed 或外部手动停止才是结束条件。",
2488
2500
  "",
2489
2501
  "注意:评测侧用 PyTorch 计算算子参考值,但工作区/候选运行时不提供 PyTorch 或 numpy,也没有网络,无法 pip 安装;开发阶段请用 C++ 或 Python 标准库/独立 double 实现做数值对照。",
2490
2502
  "",
@@ -2681,7 +2693,7 @@ var TaskService = class TaskService {
2681
2693
  return "simulation";
2682
2694
  }
2683
2695
  /** Evaluation success-rate target used by the neural-pendulum scoring integral. */
2684
- static FINAL_SUCCESS_TARGET = .8;
2696
+ static FINAL_SUCCESS_TARGET = .9;
2685
2697
  /** One test event's instantaneous score, mirroring the task specification. */
2686
2698
  static eventScore(event) {
2687
2699
  const stage = String(event["stage"] ?? "");
@@ -2735,6 +2747,32 @@ var TaskService = class TaskService {
2735
2747
  return out;
2736
2748
  }
2737
2749
  /** The task start time recorded at first submission, falling back to the run creation time. */
2750
+ /** Whether this run has reached the completed state. */
2751
+ isCompleted(run) {
2752
+ try {
2753
+ return fs.existsSync(path.join(this.hostDir(run.workspaceId), "done"));
2754
+ } catch {
2755
+ return false;
2756
+ }
2757
+ }
2758
+ /** The latest host test event, if any. */
2759
+ lastTest(run) {
2760
+ try {
2761
+ const file = this.hostEvents(run.workspaceId);
2762
+ if (!fs.existsSync(file)) return void 0;
2763
+ let last;
2764
+ for (const line of fs.readFileSync(file, "utf8").split("\n")) {
2765
+ if (line.trim() === "") continue;
2766
+ try {
2767
+ const event = JSON.parse(line);
2768
+ if (event["event"] === "test") last = event;
2769
+ } catch {}
2770
+ }
2771
+ return last;
2772
+ } catch {
2773
+ return;
2774
+ }
2775
+ }
2738
2776
  hostStartedAt(workspaceId, run) {
2739
2777
  try {
2740
2778
  const meta = JSON.parse(fs.readFileSync(path.join(this.hostDir(workspaceId), "meta.json"), "utf8"));
@@ -3660,6 +3698,185 @@ function registerAgentSubmissionTools(agent, guard, tasks) {
3660
3698
  });
3661
3699
  }
3662
3700
  //#endregion
3701
+ //#region src/agent-guards.ts
3702
+ /**
3703
+ * Per-run agent guards:
3704
+ * - periodic background-job reminder attached to the next tool result;
3705
+ * - turn-stopping continuation while the evaluation is incomplete;
3706
+ * - a short strategy reminder after a failed eval_test.
3707
+ *
3708
+ * Auditor/agent-facing text never lists allowed implementation techniques.
3709
+ */
3710
+ function sessionIdOf(agent) {
3711
+ return String(agent.session?.id ?? agent.id);
3712
+ }
3713
+ function makeNotice(text) {
3714
+ return {
3715
+ id: randomUUID(),
3716
+ role: "user",
3717
+ content: [{
3718
+ type: "text",
3719
+ text
3720
+ }],
3721
+ source: { kind: "user" }
3722
+ };
3723
+ }
3724
+ function ageMinutes(startedAt) {
3725
+ const value = Number(startedAt);
3726
+ if (!Number.isFinite(value) || value <= 0) return "?";
3727
+ const minutes = Math.max(0, Math.floor((Date.now() - value) / 6e4));
3728
+ return minutes < 60 ? minutes + "m" : Math.floor(minutes / 60) + "h" + String(minutes % 60).padStart(2, "0");
3729
+ }
3730
+ function activeJobs(services, sessionId) {
3731
+ try {
3732
+ return (services.jobs?.list(sessionId) ?? []).filter((job) => job?.status === "running" || job?.status === "stopping");
3733
+ } catch {
3734
+ return [];
3735
+ }
3736
+ }
3737
+ function workspaceProcesses(workspace) {
3738
+ let root;
3739
+ try {
3740
+ root = fs.realpathSync(workspace);
3741
+ } catch {
3742
+ root = path.resolve(workspace);
3743
+ }
3744
+ const out = [];
3745
+ let entries = [];
3746
+ try {
3747
+ entries = fs.readdirSync("/proc");
3748
+ } catch {
3749
+ return out;
3750
+ }
3751
+ for (const name of entries) {
3752
+ if (!/^[0-9]+$/.test(name)) continue;
3753
+ const pid = Number(name);
3754
+ if (pid === process.pid) continue;
3755
+ let cwd = "";
3756
+ try {
3757
+ cwd = fs.realpathSync("/proc/" + name + "/cwd");
3758
+ } catch {
3759
+ continue;
3760
+ }
3761
+ if (cwd !== root && !cwd.startsWith(root + path.sep)) continue;
3762
+ let cmd = "";
3763
+ try {
3764
+ cmd = fs.readFileSync("/proc/" + name + "/cmdline", "utf8").split("\0").filter(Boolean).join(" ");
3765
+ } catch {
3766
+ continue;
3767
+ }
3768
+ if (cmd === "") continue;
3769
+ out.push({
3770
+ pid,
3771
+ cmd
3772
+ });
3773
+ if (out.length >= 12) break;
3774
+ }
3775
+ return out;
3776
+ }
3777
+ function jobReminderText(services, sessionId, run) {
3778
+ const jobs = activeJobs(services, sessionId);
3779
+ const procs = workspaceProcesses(run.workspacePath);
3780
+ if (jobs.length === 0 && procs.length === 0) return void 0;
3781
+ const lines = ["[eval-guard: background jobs]"];
3782
+ if (jobs.length > 0) {
3783
+ lines.push("Host-managed running jobs: " + String(jobs.length));
3784
+ for (const job of jobs.slice(0, 8)) lines.push("- " + String(job.id) + " " + String(job.kind ?? "") + " " + ageMinutes(job.startedAt) + " — " + String(job.label ?? "").split("\n")[0].slice(0, 180));
3785
+ }
3786
+ if (procs.length > 0) {
3787
+ lines.push("OS processes with cwd in this workspace: " + String(procs.length));
3788
+ for (const proc of procs.slice(0, 8)) lines.push("- pid " + String(proc.pid) + " — " + proc.cmd.slice(0, 220));
3789
+ }
3790
+ lines.push("Kill unused jobs/processes now. Do not launch a duplicate trainer. Use managed run_in_background; never nohup/setsid/&. Keep at most 2 long-running jobs.");
3791
+ return lines.join("\n");
3792
+ }
3793
+ function failureText(last, failures) {
3794
+ const rate = last?.["success_rate"];
3795
+ const stage = String(last?.["stage"] ?? "unknown");
3796
+ let text = "[eval-guard: evaluation not complete] " + (rate === void 0 ? "stage=" + stage : "stage=" + stage + ", success_rate=" + String(rate)) + ". Do not stop, summarize, or finalize. Clean unused background jobs, then continue with a materially different approach. Only stage=completed (success_rate >= 0.90) or an external manual stop ends the task.";
3797
+ if (failures >= 2) text += " This is the " + String(failures) + "th consecutive failed/low evaluation. Do not repeat the same configuration; change the hypothesis or method substantially.";
3798
+ return text;
3799
+ }
3800
+ /** Install the per-run reminders once for all agents; each listener filters by run. */
3801
+ function installAgentRunGuards(ctx, services, guard, tasks) {
3802
+ const states = /* @__PURE__ */ new Map();
3803
+ const stateFor = (sessionId) => {
3804
+ let state = states.get(sessionId);
3805
+ if (state === void 0) {
3806
+ state = {
3807
+ lastJobReminder: 0,
3808
+ evalFailures: 0,
3809
+ ownMessageIds: /* @__PURE__ */ new Set()
3810
+ };
3811
+ states.set(sessionId, state);
3812
+ }
3813
+ return state;
3814
+ };
3815
+ const runFor = (agent) => {
3816
+ if (agent === void 0) return void 0;
3817
+ try {
3818
+ return guard.runForSession(sessionIdOf(agent));
3819
+ } catch {
3820
+ return;
3821
+ }
3822
+ };
3823
+ const isPendulumActive = (run) => {
3824
+ return run !== void 0 && run.task === "neural-pendulum" && run.status === "active" && !tasks.isCompleted(run);
3825
+ };
3826
+ ctx.on("tools/post-execute", async (exec, result, next) => {
3827
+ const downstream = await next();
3828
+ const run = runFor(exec.agent);
3829
+ if (!isPendulumActive(run)) return downstream;
3830
+ const sessionId = sessionIdOf(exec.agent);
3831
+ const state = stateFor(sessionId);
3832
+ const notes = [];
3833
+ const cfg = guard.configuration;
3834
+ const interval = Number(cfg.jobReminderMinutes ?? 5) * 6e4;
3835
+ const now = Date.now();
3836
+ if (interval > 0 && now - state.lastJobReminder >= interval) {
3837
+ state.lastJobReminder = now;
3838
+ const reminder = jobReminderText(services, sessionId, run);
3839
+ if (reminder !== void 0) notes.push(reminder);
3840
+ }
3841
+ if (exec.name === "eval_test") {
3842
+ const value = result?.value;
3843
+ const rate = typeof value?.success_rate === "number" ? value.success_rate : void 0;
3844
+ const stage = String(value?.stage ?? "");
3845
+ if (rate !== void 0 && rate < .9) {
3846
+ state.evalFailures += 1;
3847
+ notes.push(failureText(tasks.lastTest(run), state.evalFailures));
3848
+ } else if (stage === "completed" || rate !== void 0 && rate >= .9) state.evalFailures = 0;
3849
+ }
3850
+ if (notes.length === 0) return downstream;
3851
+ const contexts = notes.map(makeNotice);
3852
+ for (const message of contexts) state.ownMessageIds.add(String(message.id));
3853
+ if (downstream?.kind === "block") return {
3854
+ kind: "block",
3855
+ feedback: downstream.feedback,
3856
+ additionalContexts: [...contexts, ...downstream.additionalContexts ?? []]
3857
+ };
3858
+ return {
3859
+ ...downstream,
3860
+ additionalContexts: [...contexts, ...downstream?.additionalContexts ?? []]
3861
+ };
3862
+ });
3863
+ ctx.on("agent/turn-stopping", ({ agent, signal }) => {
3864
+ if (signal.aborted) return;
3865
+ const run = runFor(agent);
3866
+ if (!isPendulumActive(run)) return;
3867
+ const sessionId = sessionIdOf(agent);
3868
+ const state = stateFor(sessionId);
3869
+ if ([...agent.inbox?.nextTurn ?? [], ...agent.inbox?.nextStep ?? []].some((message) => message?.source?.kind === "user" && !state.ownMessageIds.has(String(message?.id)))) return;
3870
+ if (typeof agent.steer !== "function") return;
3871
+ const last = tasks.lastTest(run);
3872
+ const jobs = activeJobs(services, sessionId).length;
3873
+ const procs = workspaceProcesses(run.workspacePath).length;
3874
+ const message = makeNotice(failureText(last, state.evalFailures) + (jobs + procs > 0 ? "\nThere are " + String(jobs) + " host jobs and " + String(procs) + " workspace processes running; clean the unused ones first." : ""));
3875
+ state.ownMessageIds.add(String(message.id));
3876
+ agent.steer(message);
3877
+ });
3878
+ }
3879
+ //#endregion
3663
3880
  //#region src/index.ts
3664
3881
  /** Stable Cordis plugin name. */
3665
3882
  const name = "eval-guard";
@@ -3710,6 +3927,7 @@ function apply(ctx, config) {
3710
3927
  };
3711
3928
  guard.onAutoRun = (agent, cwd) => tasks.autoBind(agent, cwd);
3712
3929
  registerRoutes(ctx, guard, tasks);
3930
+ installAgentRunGuards(child, { jobs: services.jobs }, guard, tasks);
3713
3931
  child.inject(["settings"], (settingsCtx) => {
3714
3932
  const settings = settingsCtx.get("settings");
3715
3933
  settingsCtx.effect(() => settings.configure({ auto: false }, ctx.fiber), "eval-guard: settings page");
@@ -45,7 +45,7 @@ MAX_STEPS = 3000
45
45
  T_TGT = 10.0
46
46
  UP_TOL = 0.05
47
47
  EPISODES = 100
48
- SUCCESS_TARGET = 0.8
48
+ SUCCESS_TARGET = 0.9
49
49
  # The score changes at the test request instant. This process is started for
50
50
  # one request, so module import is the closest available request timestamp.
51
51
  TEST_TIME = time.time()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-eval-guard",
3
- "version": "0.7.6",
3
+ "version": "0.7.8",
4
4
  "type": "module",
5
5
  "description": "Evaluation guard for DSH: workspace-only filesystem, no network/subagents, wall-clock limits, and task installation for meow-ai-arena and benchmark tasks.",
6
6
  "license": "MIT",
@@ -48,7 +48,7 @@
48
48
  "build": "tsdown && node scripts/build-native.mjs",
49
49
  "build:native": "node scripts/build-native.mjs",
50
50
  "prepare": "tsdown",
51
- "test": "node test/simulate.ts && node test/scoring.ts && node test/jobs.ts && node test/pendulum-sim.ts",
51
+ "test": "node test/simulate.ts && node test/scoring.ts && node test/jobs.ts && node test/pendulum-sim.ts && node test/agent-guards.ts",
52
52
  "typecheck": "tsc --noEmit -p tsconfig.json"
53
53
  },
54
54
  "dsh": {