dsh-eval-guard 0.3.5 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -2
- package/assets/neural-cpp/hidden/test_neural.cpp +631 -0
- package/assets/neural-cpp/workspace.zip +0 -0
- package/eval/__pycache__/common.cpython-310.pyc +0 -0
- package/eval/neural-cpp.py +173 -0
- package/lib/client/index.js.map +1 -1
- package/lib/index.js +36 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -24,13 +24,21 @@
|
|
|
24
24
|
| Commit0 单库 | 480 分钟,默认关闭 |
|
|
25
25
|
| SWE-Bench Pro 单任务 | 1440 分钟,默认关闭 |
|
|
26
26
|
| FeatureBench 单 feature | 1440 分钟,默认关闭 |
|
|
27
|
+
| Neural-CPP 纯 C++ 张量后端 | 1440 分钟,默认关闭 |
|
|
27
28
|
|
|
28
29
|
## 任务与安装
|
|
29
30
|
|
|
30
|
-
|
|
31
|
+
设置页可安装九个任务包:
|
|
31
32
|
|
|
32
33
|
- 原 5 个比赛任务:坦克大战、仓储调度、圈地、炸弹人、夺旗。
|
|
33
34
|
- 3 个长时单任务:Commit0 单库实现、SWE-Bench Pro 单任务、FeatureBench 单 feature。
|
|
35
|
+
- 1 个纯 C++ 项目:Neural-CPP 张量运算与反向传播后端。
|
|
36
|
+
|
|
37
|
+
Neural-CPP 工作区只包含 TASK.md、CMakeLists.txt 和 include/nn/nn.hpp;实现在 src/ 中从零完成,纯 C++17,无 Python/OpenCL/第三方库。
|
|
38
|
+
|
|
39
|
+
评测时在临时目录独立构建,然后从 assets/neural-cpp/hidden/ 注入 C++ 测试源码;测试数据由固定种子在进程内生成,不依赖或复制外部数据文件。
|
|
40
|
+
|
|
41
|
+
结果返回 coreAccuracy(核心 C++ 测试通过率)、matrixAccuracy、逐类型 metrics(f32/int128/MXFP4 的矩阵与反向准确率、平均绝对误差、fwd/bwd 毫秒、fwd/bwd GFLOP/s)、speedGflops,以及按矩阵吞吐计算的 speedGeomeanGflops 和 matrixSizes(f32/i128/MXFP4 均为 256×256×256)。确定性项目使用 4 组独立输入取平均;MXFP4 RNE 和随机舍入分开统计,随机舍入使用 2 组输入×每组 1024 次采样,逐元素比较参考均值/标准差和候选均值/标准差,按 3σ 和 0.1–10× 标准差规则统计正确率。参考值由测试侧独立标量实现先算完,再调用候选实现,参考计算不计入候选耗时。隐藏测试不在工作区,agent 无法读取。开发要求线程数最多 4,评测阶段使用全部逻辑 CPU。
|
|
34
42
|
|
|
35
43
|
原 5 个任务直接放入打包好的 workspace.zip。后 3 个任务在安装时由 host 侧 setup 脚本按固定 commit clone 仓库、创建 .venv 并安装依赖;安装完成后会清理 `.git`、`setup.sh`、`remove.patch`、`spec.pdf.bz2` 等安装产物,工作区只保留任务本身素材。Commit0 的 `pytest.ini` 会去掉 coverage 参数,保证默认测试命令在沙箱内可运行。agent 运行时仍然禁网,使用工作区内的 .venv 跑测试;agent 可以自行 `git init` 或写自己的脚本。
|
|
36
44
|
|
|
@@ -66,10 +74,11 @@ Gitee/GitCode 都使用 git fetch --depth 1 origin <任务 commit> 验证。GitL
|
|
|
66
74
|
|
|
67
75
|
设置页安装/评测共用一组任务和工作区选择;「评测当前工作区」只评测一个结果,不生成排行。
|
|
68
76
|
|
|
69
|
-
插件 eval/ 目录内置全部
|
|
77
|
+
插件 eval/ 目录内置全部 9 个任务的单结果评测脚本:
|
|
70
78
|
|
|
71
79
|
- Commit0:单元测试通过率。
|
|
72
80
|
- SWE-Bench Pro / FeatureBench:隐藏 F2P/P2P 测试;全部通过才 resolved,同时返回 passRate。
|
|
81
|
+
- Neural-CPP:独立编译隐藏 C++ 测试,返回 accuracy 与 matmul speedGflops;数据在测试进程内按固定种子生成。
|
|
73
82
|
- Tank / Warehouse / Land / Bomberman / CTF:运行官方引擎/裁判,只返回当前工作区候选者结果,不生成排名。
|
|
74
83
|
|
|
75
84
|
评测也是后台任务,日志和结果实时显示,持久化在 jobs 目录。
|
|
@@ -0,0 +1,631 @@
|
|
|
1
|
+
#include <nn/nn.hpp>
|
|
2
|
+
|
|
3
|
+
#include <algorithm>
|
|
4
|
+
#include <chrono>
|
|
5
|
+
#include <cmath>
|
|
6
|
+
#include <cstdint>
|
|
7
|
+
#include <cstring>
|
|
8
|
+
#include <cstdio>
|
|
9
|
+
#include <functional>
|
|
10
|
+
#include <random>
|
|
11
|
+
#include <string>
|
|
12
|
+
#include <thread>
|
|
13
|
+
#include <vector>
|
|
14
|
+
|
|
15
|
+
using nn::DType;
|
|
16
|
+
using nn::Shape;
|
|
17
|
+
using nn::Tensor;
|
|
18
|
+
|
|
19
|
+
static int g_passed = 0;
|
|
20
|
+
static int g_failed = 0;
|
|
21
|
+
|
|
22
|
+
static void report(const std::string& name, bool ok) {
|
|
23
|
+
if (ok) { ++g_passed; std::printf("TEST %s PASS\n", name.c_str()); }
|
|
24
|
+
else { ++g_failed; std::printf("TEST %s FAIL\n", name.c_str()); }
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
static bool close(float a, float b, float tol = 1e-4f) {
|
|
28
|
+
return std::fabs(a - b) <= tol * (1.0f + std::fabs(a) + std::fabs(b));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
static std::vector<float> f32_data(const Tensor& t) {
|
|
32
|
+
Tensor c = t.contiguous();
|
|
33
|
+
std::vector<float> out(static_cast<size_t>(c.numel()));
|
|
34
|
+
if (out.empty()) return out;
|
|
35
|
+
std::memcpy(out.data(), c.data(), out.size() * sizeof(float));
|
|
36
|
+
return out;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
static Tensor make_f32(const Shape& shape, const std::vector<float>& values) {
|
|
40
|
+
return Tensor::from_data(values.data(), shape, DType::F32);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
static bool eq_data(const Tensor& t, const std::vector<float>& expected, float tol = 1e-4f) {
|
|
44
|
+
const std::vector<float> got = f32_data(t);
|
|
45
|
+
if (got.size() != expected.size()) return false;
|
|
46
|
+
for (size_t i = 0; i < got.size(); ++i) if (!close(got[i], expected[i], tol)) return false;
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
static bool shape_is(const Tensor& t, const Shape& shape) { return t.shape() == shape; }
|
|
51
|
+
|
|
52
|
+
static void test_dtype_metadata() {
|
|
53
|
+
bool ok = nn::dtype_size(DType::F32) == 4 && nn::dtype_size(DType::F64) == 8 &&
|
|
54
|
+
nn::dtype_size(DType::I8) == 1 && nn::dtype_size(DType::I16) == 2 &&
|
|
55
|
+
nn::dtype_size(DType::I32) == 4 && nn::dtype_size(DType::I64) == 8 &&
|
|
56
|
+
nn::dtype_size(DType::I128) == 16 && nn::dtype_size(DType::U128) == 16 &&
|
|
57
|
+
nn::dtype_size(DType::BF16) == 2 && nn::dtype_size(DType::FP8_E5M2) == 1 &&
|
|
58
|
+
nn::dtype_size(DType::MXFP4) == 1;
|
|
59
|
+
report("dtype_metadata", ok);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
static void test_casts_float() {
|
|
63
|
+
Tensor a = make_f32({3}, {1.5f, -2.25f, 3.0f});
|
|
64
|
+
Tensor d = a.to(DType::F64);
|
|
65
|
+
Tensor back = d.to(DType::F32);
|
|
66
|
+
report("cast_float", d.dtype() == DType::F64 && eq_data(back, {1.5f, -2.25f, 3.0f}));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
static void test_casts_int() {
|
|
70
|
+
Tensor a = make_f32({5}, {3.6f, -1.2f, 300.0f, -300.0f, 0.0f});
|
|
71
|
+
Tensor i = a.to(DType::I32);
|
|
72
|
+
Tensor narrow = a.to(DType::I8);
|
|
73
|
+
int32_t iv[5]{};
|
|
74
|
+
int8_t nv[5]{};
|
|
75
|
+
std::memcpy(iv, i.contiguous().data(), sizeof(iv));
|
|
76
|
+
std::memcpy(nv, narrow.contiguous().data(), sizeof(nv));
|
|
77
|
+
bool ok = iv[0] == 4 && iv[1] == -1 && iv[2] == 300 && iv[3] == -300 && iv[4] == 0;
|
|
78
|
+
ok = ok && nv[0] == 4 && nv[1] == -1 && nv[2] == 127 && nv[3] == -128 && nv[4] == 0;
|
|
79
|
+
report("cast_int_saturate", ok);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
static void test_integer_casts() {
|
|
83
|
+
Tensor a = make_f32({4}, {0.0f, 1.0f, 2.0f, 3.0f});
|
|
84
|
+
bool ok = true;
|
|
85
|
+
for (DType d : {DType::I8, DType::I16, DType::I32, DType::I64, DType::I128,
|
|
86
|
+
DType::U8, DType::U16, DType::U32, DType::U64, DType::U128}) {
|
|
87
|
+
Tensor back = a.to(d).to(DType::F32);
|
|
88
|
+
ok = ok && eq_data(back, {0.0f, 1.0f, 2.0f, 3.0f});
|
|
89
|
+
}
|
|
90
|
+
report("integer_casts", ok);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
static void test_low_precision_casts() {
|
|
94
|
+
Tensor a = make_f32({4}, {1.5f, -2.0f, 0.5f, 0.0f});
|
|
95
|
+
Tensor bf = a.to(DType::BF16).to(DType::F32);
|
|
96
|
+
Tensor fp8 = a.to(DType::FP8_E5M2).to(DType::F32);
|
|
97
|
+
Tensor mx = make_f32({32}, std::vector<float>(32, 1.0f)).to(DType::MXFP4).to(DType::F32);
|
|
98
|
+
bool ok = eq_data(bf, {1.5f, -2.0f, 0.5f, 0.0f}, 0.01f);
|
|
99
|
+
ok = ok && eq_data(fp8, {1.5f, -2.0f, 0.5f, 0.0f}, 0.01f);
|
|
100
|
+
ok = ok && eq_data(mx, std::vector<float>(32, 1.0f), 0.01f);
|
|
101
|
+
report("low_precision_casts", ok);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
static void test_views() {
|
|
105
|
+
std::vector<float> v(24);
|
|
106
|
+
for (int i = 0; i < 24; ++i) v[i] = static_cast<float>(i);
|
|
107
|
+
Tensor a = make_f32({2, 3, 4}, v);
|
|
108
|
+
Tensor p = a.permute({2, 0, 1});
|
|
109
|
+
bool ok = shape_is(p, {4, 2, 3});
|
|
110
|
+
const std::vector<float> pv = f32_data(p);
|
|
111
|
+
ok = ok && pv.size() == 24 && close(pv[0], 0.0f) && close(pv[1], 4.0f) && close(pv[2], 8.0f);
|
|
112
|
+
Tensor c = a.reshape({6, 4});
|
|
113
|
+
ok = ok && shape_is(c, {6, 4}) && eq_data(c, v);
|
|
114
|
+
report("views_permute_reshape", ok);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
static void test_slices() {
|
|
118
|
+
std::vector<float> v(10);
|
|
119
|
+
for (int i = 0; i < 10; ++i) v[i] = static_cast<float>(i);
|
|
120
|
+
Tensor a = make_f32({10}, v);
|
|
121
|
+
Tensor s = a.slice(0, 1, 8, 2);
|
|
122
|
+
Tensor r = a.slice(0, 8, 1, -2);
|
|
123
|
+
bool ok = eq_data(s, {1, 3, 5, 7}) && eq_data(r, {8, 6, 4, 2});
|
|
124
|
+
report("slices_negative_step", ok);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
static void test_elementwise_broadcast() {
|
|
128
|
+
Tensor a = make_f32({2, 3}, {1, 2, 3, 4, 5, 6});
|
|
129
|
+
Tensor b = make_f32({3}, {10, 20, 30});
|
|
130
|
+
Tensor c = nn::add(a, b);
|
|
131
|
+
Tensor d = nn::mul(c, b);
|
|
132
|
+
bool ok = shape_is(c, {2, 3}) && eq_data(c, {11, 22, 33, 14, 25, 36});
|
|
133
|
+
ok = ok && eq_data(d, {110, 440, 990, 140, 500, 1080});
|
|
134
|
+
report("elementwise_broadcast", ok);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
static void test_reductions() {
|
|
138
|
+
Tensor a = make_f32({2, 3}, {1, 2, 3, 4, 5, 6});
|
|
139
|
+
Tensor s = nn::sum(a, 1);
|
|
140
|
+
Tensor m = nn::mean(a, -1);
|
|
141
|
+
report("reductions", eq_data(s, {6, 15}) && close(f32_data(m)[0], 3.5f));
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
static void test_matmul_2d() {
|
|
145
|
+
Tensor a = make_f32({2, 3}, {1, 2, 3, 4, 5, 6});
|
|
146
|
+
Tensor b = make_f32({3, 2}, {7, 8, 9, 10, 11, 12});
|
|
147
|
+
Tensor c = nn::matmul(a, b);
|
|
148
|
+
report("matmul_2d", shape_is(c, {2, 2}) && eq_data(c, {58, 64, 139, 154}));
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
static void test_matmul_batch_and_nd() {
|
|
152
|
+
Tensor a = make_f32({2, 2, 3}, {1, 2, 3, 4, 5, 6, 1, 0, 0, 0, 1, 0});
|
|
153
|
+
Tensor b = make_f32({2, 3, 2}, {1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0});
|
|
154
|
+
Tensor c = nn::matmul(a, b);
|
|
155
|
+
bool ok = shape_is(c, {2, 2, 2}) && eq_data(c, {1, 2, 4, 5, 1, 0, 0, 1});
|
|
156
|
+
Tensor a2 = make_f32({2, 3, 4}, std::vector<float>(24, 1.0f));
|
|
157
|
+
Tensor b2 = make_f32({2, 4, 5}, std::vector<float>(40, 1.0f));
|
|
158
|
+
Tensor c2 = nn::matmul_nd(a2, b2, {0}, {0}, {1, 2}, {1, 2});
|
|
159
|
+
ok = ok && shape_is(c2, {2, 3, 5}) && eq_data(c2, std::vector<float>(30, 4.0f));
|
|
160
|
+
report("matmul_batch_nd", ok);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
static void test_autograd_add_mul() {
|
|
164
|
+
Tensor a = make_f32({2}, {2.0f, 3.0f}); a.set_requires_grad(true);
|
|
165
|
+
Tensor b = make_f32({2}, {5.0f, 7.0f}); b.set_requires_grad(true);
|
|
166
|
+
Tensor c = nn::add(nn::mul(a, b), a);
|
|
167
|
+
nn::sum(c).backward();
|
|
168
|
+
bool ok = eq_data(a.grad(), {6.0f, 8.0f}) && eq_data(b.grad(), {2.0f, 3.0f});
|
|
169
|
+
report("autograd_add_mul", ok);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
static void test_autograd_matmul() {
|
|
173
|
+
Tensor a = make_f32({2, 3}, {1, 2, 3, 4, 5, 6}); a.set_requires_grad(true);
|
|
174
|
+
Tensor b = make_f32({3, 2}, {7, 8, 9, 10, 11, 12}); b.set_requires_grad(true);
|
|
175
|
+
nn::sum(nn::matmul(a, b)).backward();
|
|
176
|
+
bool ok = eq_data(a.grad(), {15, 19, 23, 15, 19, 23});
|
|
177
|
+
ok = ok && eq_data(b.grad(), {5, 5, 7, 7, 9, 9});
|
|
178
|
+
report("autograd_matmul", ok);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
static void test_autograd_view_slice() {
|
|
182
|
+
Tensor x = make_f32({2, 3}, {1, 2, 3, 4, 5, 6}); x.set_requires_grad(true);
|
|
183
|
+
Tensor s = x.slice(1, 0, 2);
|
|
184
|
+
nn::sum(s).backward();
|
|
185
|
+
report("autograd_slice", eq_data(x.grad(), {1, 1, 0, 1, 1, 0}));
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
static void test_stochastic_stats() {
|
|
189
|
+
const float lo = 1.0f;
|
|
190
|
+
const float hi = 1.0078125f; // bf16 adjacent around 1.0
|
|
191
|
+
const float mid = (lo + hi) * 0.5f;
|
|
192
|
+
std::vector<float> vals(4096, mid);
|
|
193
|
+
Tensor a = make_f32({4096}, vals);
|
|
194
|
+
Tensor q = a.to(DType::BF16, nn::Rounding::Stochastic, 12345);
|
|
195
|
+
Tensor f = q.to(DType::F32);
|
|
196
|
+
const std::vector<float> out = f32_data(f);
|
|
197
|
+
int upper = 0;
|
|
198
|
+
for (float v : out) { if (v > mid) ++upper; }
|
|
199
|
+
report("stochastic_stats", upper > 1500 && upper < 2600);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
static void test_threads() {
|
|
203
|
+
nn::set_thread_mode(nn::ThreadMode::Development);
|
|
204
|
+
nn::set_num_threads(4);
|
|
205
|
+
int dev = nn::active_workers();
|
|
206
|
+
bool ok = dev >= 1 && dev <= nn::kDevMaxThreads;
|
|
207
|
+
nn::set_thread_mode(nn::ThreadMode::Evaluation);
|
|
208
|
+
nn::set_num_threads(0);
|
|
209
|
+
ok = ok && nn::active_workers() >= 1;
|
|
210
|
+
report("thread_policy", ok);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
static void test_all_dtype_alloc() {
|
|
214
|
+
bool ok = true;
|
|
215
|
+
for (DType d : {DType::F32, DType::F64, DType::I8, DType::I16, DType::I32, DType::I64,
|
|
216
|
+
DType::I128, DType::U8, DType::U16, DType::U32, DType::U64, DType::U128,
|
|
217
|
+
DType::BF16, DType::FP8_E5M2, DType::MXFP4}) {
|
|
218
|
+
Tensor t = Tensor::empty(d == DType::MXFP4 ? Shape{32} : Shape{2, 3}, d);
|
|
219
|
+
ok = ok && t.numel() == (d == DType::MXFP4 ? 32 : 6) && t.dtype() == d;
|
|
220
|
+
}
|
|
221
|
+
report("all_dtype_alloc", ok);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
static void bench_matmul() {
|
|
225
|
+
const int n = 256;
|
|
226
|
+
std::vector<float> av(static_cast<size_t>(n) * n), bv(static_cast<size_t>(n) * n);
|
|
227
|
+
for (size_t i = 0; i < av.size(); ++i) { av[i] = static_cast<float>((i * 17) % 101) * 0.01f; bv[i] = static_cast<float>((i * 29) % 97) * 0.01f; }
|
|
228
|
+
Tensor a = make_f32({n, n}, av);
|
|
229
|
+
Tensor b = make_f32({n, n}, bv);
|
|
230
|
+
nn::set_thread_mode(nn::ThreadMode::Evaluation);
|
|
231
|
+
nn::set_num_threads(0);
|
|
232
|
+
Tensor warm = nn::matmul(a, b);
|
|
233
|
+
(void)warm;
|
|
234
|
+
const int iters = 3;
|
|
235
|
+
auto start = std::chrono::steady_clock::now();
|
|
236
|
+
for (int i = 0; i < iters; ++i) { Tensor c = nn::matmul(a, b); (void)c; }
|
|
237
|
+
auto end = std::chrono::steady_clock::now();
|
|
238
|
+
double ms = std::chrono::duration<double, std::milli>(end - start).count() / iters;
|
|
239
|
+
double gflops = (2.0 * n * n * n) / (ms * 1e6);
|
|
240
|
+
std::printf("PERF_MS %.6f\nPERF_GFLOPS %.6f\n", ms, gflops);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
// ---------------------------------------------------------------------------
|
|
245
|
+
// Metric section. Reference values are computed by local scalar reference code
|
|
246
|
+
// BEFORE calling the candidate implementation. Candidate timing only wraps
|
|
247
|
+
// candidate calls; reference loops are never inside the timed region.
|
|
248
|
+
// ---------------------------------------------------------------------------
|
|
249
|
+
|
|
250
|
+
static std::vector<float> ref_matmul_f32(const std::vector<float>& a, const std::vector<float>& b,
|
|
251
|
+
int M, int K, int N) {
|
|
252
|
+
std::vector<float> c(static_cast<size_t>(M) * N, 0.0f);
|
|
253
|
+
for (int i = 0; i < M; ++i)
|
|
254
|
+
for (int k = 0; k < K; ++k)
|
|
255
|
+
for (int j = 0; j < N; ++j)
|
|
256
|
+
c[static_cast<size_t>(i) * N + j] += a[static_cast<size_t>(i) * K + k] * b[static_cast<size_t>(k) * N + j];
|
|
257
|
+
return c;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
static const float kMxTable[8] = {0.0f, 0.5f, 1.0f, 1.5f, 2.0f, 3.0f, 4.0f, 6.0f};
|
|
261
|
+
|
|
262
|
+
static float mx_quant_one(float x, float scale, std::mt19937_64* rng) {
|
|
263
|
+
const float q = x / scale;
|
|
264
|
+
const float aq = std::fabs(q);
|
|
265
|
+
int code = 0;
|
|
266
|
+
if (aq >= kMxTable[7]) {
|
|
267
|
+
code = 7;
|
|
268
|
+
} else {
|
|
269
|
+
int lo = 0, hi = 1;
|
|
270
|
+
for (int c = 0; c < 7; ++c) if (kMxTable[c] <= aq && aq <= kMxTable[c + 1]) { lo = c; hi = c + 1; break; }
|
|
271
|
+
const float t = (aq - kMxTable[lo]) / (kMxTable[hi] - kMxTable[lo]);
|
|
272
|
+
if (rng != nullptr && t > 0.0f && t < 1.0f) {
|
|
273
|
+
std::uniform_real_distribution<double> d(0.0, 1.0);
|
|
274
|
+
code = d(*rng) < t ? hi : lo;
|
|
275
|
+
} else {
|
|
276
|
+
code = t < 0.5f ? lo : hi;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
const float v = kMxTable[code] * scale;
|
|
280
|
+
return q < 0 ? -v : v;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
static std::vector<float> mx_quantize(const std::vector<float>& x, std::mt19937_64* rng) {
|
|
284
|
+
std::vector<float> out(x.size());
|
|
285
|
+
for (size_t base = 0; base < x.size(); base += 32) {
|
|
286
|
+
float mx = 0.0f;
|
|
287
|
+
for (size_t j = base; j < std::min(x.size(), base + 32); ++j) mx = std::max(mx, std::fabs(x[j]));
|
|
288
|
+
int e = 127;
|
|
289
|
+
if (mx > 0) e = static_cast<int>(std::floor(std::log2(mx / 4.0f))) + 127;
|
|
290
|
+
e = std::max(0, std::min(254, e));
|
|
291
|
+
const float scale = std::pow(2.0f, e - 127);
|
|
292
|
+
for (size_t j = base; j < std::min(x.size(), base + 32); ++j) out[j] = mx_quant_one(x[j], scale, rng);
|
|
293
|
+
}
|
|
294
|
+
return out;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
static std::vector<float> ref_matmul_mx(const std::vector<float>& a, const std::vector<float>& b,
|
|
298
|
+
int M, int K, int N, std::mt19937_64* rng) {
|
|
299
|
+
std::vector<float> aq = mx_quantize(a, rng), bq = mx_quantize(b, rng);
|
|
300
|
+
std::vector<float> c = ref_matmul_f32(aq, bq, M, K, N);
|
|
301
|
+
return mx_quantize(c, rng);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
static std::vector<__int128> ref_matmul_i128(const std::vector<__int128>& a,
|
|
305
|
+
const std::vector<__int128>& b, int M, int K, int N) {
|
|
306
|
+
std::vector<__int128> c(static_cast<size_t>(M) * N, 0);
|
|
307
|
+
for (int i = 0; i < M; ++i)
|
|
308
|
+
for (int k = 0; k < K; ++k)
|
|
309
|
+
for (int j = 0; j < N; ++j)
|
|
310
|
+
c[static_cast<size_t>(i) * N + j] += a[static_cast<size_t>(i) * K + k] * b[static_cast<size_t>(k) * N + j];
|
|
311
|
+
return c;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
static double mean_abs_error_f32(const std::vector<float>& got, const std::vector<float>& ref) {
|
|
315
|
+
double s = 0.0;
|
|
316
|
+
for (size_t i = 0; i < got.size(); ++i) s += std::fabs(static_cast<double>(got[i]) - ref[i]);
|
|
317
|
+
return got.empty() ? 0.0 : s / got.size();
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
static double mean_abs_error_i128(const std::vector<__int128>& got, const std::vector<__int128>& ref) {
|
|
321
|
+
double s = 0.0;
|
|
322
|
+
for (size_t i = 0; i < got.size(); ++i) {
|
|
323
|
+
__int128 d = got[i] - ref[i];
|
|
324
|
+
if (d < 0) d = -d;
|
|
325
|
+
s += static_cast<double>(d);
|
|
326
|
+
}
|
|
327
|
+
return got.empty() ? 0.0 : s / got.size();
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
static std::vector<__int128> read_i128(const Tensor& t) {
|
|
331
|
+
Tensor c = t.contiguous();
|
|
332
|
+
std::vector<__int128> out(static_cast<size_t>(c.numel()), 0);
|
|
333
|
+
if (c.dtype() != DType::I128) return out;
|
|
334
|
+
std::memcpy(out.data(), c.data(), out.size() * sizeof(__int128));
|
|
335
|
+
return out;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
static void emit_metric(const char* dtype, int stochastic, int M, int K, int N,
|
|
339
|
+
double fwd_acc, double fwd_err, double fwd_ms,
|
|
340
|
+
double bwd_acc, double bwd_err, double bwd_ms) {
|
|
341
|
+
const double ops = 2.0 * M * K * N;
|
|
342
|
+
const double fwd_gflops = fwd_ms > 0 ? ops / (fwd_ms * 1e6) : -1.0;
|
|
343
|
+
const double bwd_gflops = bwd_ms > 0 ? ops / (bwd_ms * 1e6) : -1.0;
|
|
344
|
+
std::printf("METRIC dtype=%s stochastic=%d m=%d k=%d n=%d fwd_accuracy=%.6f fwd_mean_err=%.9g fwd_ms=%.6f fwd_gflops=%.6f bwd_accuracy=%.6f bwd_mean_err=%.9g bwd_ms=%.6f bwd_gflops=%.6f\n",
|
|
345
|
+
dtype, stochastic, M, K, N, fwd_acc, fwd_err, fwd_ms, fwd_gflops,
|
|
346
|
+
bwd_acc, bwd_err, bwd_ms, bwd_gflops);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
static double time_once_ms(const std::function<void()>& fn, int iters = 3) {
|
|
350
|
+
// warmup
|
|
351
|
+
fn();
|
|
352
|
+
auto start = std::chrono::steady_clock::now();
|
|
353
|
+
for (int i = 0; i < iters; ++i) fn();
|
|
354
|
+
auto end = std::chrono::steady_clock::now();
|
|
355
|
+
return std::chrono::duration<double, std::milli>(end - start).count() / iters;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
static void fill_rand(std::vector<float>& v, uint64_t seed, float lo, float hi) {
|
|
359
|
+
std::mt19937_64 rng(seed);
|
|
360
|
+
std::uniform_real_distribution<float> d(lo, hi);
|
|
361
|
+
for (float& x : v) x = d(rng);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
struct StatScore {
|
|
365
|
+
double accuracy = 0.0;
|
|
366
|
+
double mean_err = 0.0;
|
|
367
|
+
double std_ratio = 0.0;
|
|
368
|
+
double ref_mean_avg = 0.0;
|
|
369
|
+
double ref_std_avg = 0.0;
|
|
370
|
+
double cand_mean_avg = 0.0;
|
|
371
|
+
double cand_std_avg = 0.0;
|
|
372
|
+
};
|
|
373
|
+
|
|
374
|
+
static void add_stats(std::vector<double>& sum, std::vector<double>& sq, const std::vector<float>& v) {
|
|
375
|
+
for (size_t i = 0; i < v.size(); ++i) {
|
|
376
|
+
sum[i] += v[i];
|
|
377
|
+
sq[i] += static_cast<double>(v[i]) * v[i];
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
static StatScore score_stats(const std::vector<double>& ref_sum, const std::vector<double>& ref_sq,
|
|
382
|
+
const std::vector<double>& cand_sum, const std::vector<double>& cand_sq,
|
|
383
|
+
int samples) {
|
|
384
|
+
StatScore out;
|
|
385
|
+
const double n = std::max(1, samples);
|
|
386
|
+
int ok = 0;
|
|
387
|
+
for (size_t i = 0; i < ref_sum.size(); ++i) {
|
|
388
|
+
const double rm = ref_sum[i] / n;
|
|
389
|
+
const double rv = std::max(0.0, ref_sq[i] / n - rm * rm);
|
|
390
|
+
const double rs = std::sqrt(rv);
|
|
391
|
+
const double cm = cand_sum[i] / n;
|
|
392
|
+
const double cv = std::max(0.0, cand_sq[i] / n - cm * cm);
|
|
393
|
+
const double cs = std::sqrt(cv);
|
|
394
|
+
bool good = false;
|
|
395
|
+
if (rs <= 1e-12) good = std::fabs(cm - rm) <= 1e-6 && cs <= 1e-6;
|
|
396
|
+
else good = std::fabs(cm - rm) <= 3.0 * rs && cs >= 0.1 * rs && cs <= 10.0 * rs;
|
|
397
|
+
if (good) ++ok;
|
|
398
|
+
out.mean_err += std::fabs(cm - rm);
|
|
399
|
+
out.std_ratio += (rs > 1e-12) ? cs / rs : 1.0;
|
|
400
|
+
out.ref_mean_avg += rm;
|
|
401
|
+
out.ref_std_avg += rs;
|
|
402
|
+
out.cand_mean_avg += cm;
|
|
403
|
+
out.cand_std_avg += cs;
|
|
404
|
+
}
|
|
405
|
+
const double count = static_cast<double>(ref_sum.size());
|
|
406
|
+
out.accuracy = 100.0 * ok / count;
|
|
407
|
+
out.mean_err /= count;
|
|
408
|
+
out.std_ratio /= count;
|
|
409
|
+
out.ref_mean_avg /= count;
|
|
410
|
+
out.ref_std_avg /= count;
|
|
411
|
+
out.cand_mean_avg /= count;
|
|
412
|
+
out.cand_std_avg /= count;
|
|
413
|
+
return out;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
static void metric_f32() {
|
|
417
|
+
const int M = 256, K = 256, N = 256;
|
|
418
|
+
const int DATA = 4;
|
|
419
|
+
double acc_f = 0.0, err_f = 0.0, ms_f = 0.0, acc_b = 0.0, err_b = 0.0, ms_b = 0.0;
|
|
420
|
+
for (int d = 0; d < DATA; ++d) {
|
|
421
|
+
std::vector<float> a(static_cast<size_t>(M) * K), b(static_cast<size_t>(K) * N);
|
|
422
|
+
fill_rand(a, 1000 + d, -1.0f, 1.0f);
|
|
423
|
+
fill_rand(b, 2000 + d, -1.0f, 1.0f);
|
|
424
|
+
const std::vector<float> ref_c = ref_matmul_f32(a, b, M, K, N);
|
|
425
|
+
std::vector<float> ref_da(static_cast<size_t>(M) * K), ref_db(static_cast<size_t>(K) * N);
|
|
426
|
+
for (int i = 0; i < M; ++i) for (int k = 0; k < K; ++k) { float s = 0; for (int j = 0; j < N; ++j) s += b[k * N + j]; ref_da[i * K + k] = s; }
|
|
427
|
+
for (int k = 0; k < K; ++k) for (int j = 0; j < N; ++j) { float s = 0; for (int i = 0; i < M; ++i) s += a[i * K + k]; ref_db[k * N + j] = s; }
|
|
428
|
+
|
|
429
|
+
Tensor at = make_f32({M, K}, a), bt = make_f32({K, N}, b);
|
|
430
|
+
const std::vector<float> got = f32_data(nn::matmul(at, bt));
|
|
431
|
+
double err = mean_abs_error_f32(got, ref_c);
|
|
432
|
+
int ok = 0; for (size_t i = 0; i < got.size(); ++i) if (std::fabs(got[i] - ref_c[i]) <= 1e-3f + 1e-4f * std::fabs(ref_c[i])) ++ok;
|
|
433
|
+
acc_f += 100.0 * ok / got.size(); err_f += err;
|
|
434
|
+
ms_f += time_once_ms([&] { Tensor c = nn::matmul(at, bt); (void)c; });
|
|
435
|
+
|
|
436
|
+
Tensor ag = make_f32({M, K}, a), bg = make_f32({K, N}, b);
|
|
437
|
+
ag.set_requires_grad(true); bg.set_requires_grad(true);
|
|
438
|
+
ms_b += time_once_ms([&] {
|
|
439
|
+
ag = make_f32({M, K}, a); bg = make_f32({K, N}, b);
|
|
440
|
+
ag.set_requires_grad(true); bg.set_requires_grad(true);
|
|
441
|
+
Tensor c = nn::matmul(ag, bg);
|
|
442
|
+
nn::sum(c).backward();
|
|
443
|
+
});
|
|
444
|
+
const std::vector<float> got_da = f32_data(ag.grad()), got_db = f32_data(bg.grad());
|
|
445
|
+
double err_da = mean_abs_error_f32(got_da, ref_da), err_db = mean_abs_error_f32(got_db, ref_db);
|
|
446
|
+
int ok_da = 0, ok_db = 0;
|
|
447
|
+
for (size_t i = 0; i < got_da.size(); ++i) if (std::fabs(got_da[i] - ref_da[i]) <= 1e-3f) ++ok_da;
|
|
448
|
+
for (size_t i = 0; i < got_db.size(); ++i) if (std::fabs(got_db[i] - ref_db[i]) <= 1e-3f) ++ok_db;
|
|
449
|
+
acc_b += 100.0 * (ok_da + ok_db) / (got_da.size() + got_db.size());
|
|
450
|
+
err_b += (err_da + err_db) / 2.0;
|
|
451
|
+
}
|
|
452
|
+
emit_metric("f32", 0, M, K, N, acc_f / DATA, err_f / DATA, ms_f / DATA, acc_b / DATA, err_b / DATA, ms_b / DATA);
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
static void metric_i128() {
|
|
456
|
+
const int M = 256, K = 256, N = 256;
|
|
457
|
+
const int DATA = 4;
|
|
458
|
+
double acc_f = 0.0, err_f = 0.0, ms_f = 0.0, acc_b = 0.0, err_b = 0.0, ms_b = 0.0;
|
|
459
|
+
for (int d = 0; d < DATA; ++d) {
|
|
460
|
+
std::vector<__int128> a(static_cast<size_t>(M) * K), b(static_cast<size_t>(K) * N);
|
|
461
|
+
for (size_t i = 0; i < a.size(); ++i) a[i] = static_cast<int>((i * 17 + d * 13) % 9) - 4;
|
|
462
|
+
for (size_t i = 0; i < b.size(); ++i) b[i] = static_cast<int>((i * 29 + d * 7) % 9) - 4;
|
|
463
|
+
const std::vector<__int128> ref_c = ref_matmul_i128(a, b, M, K, N);
|
|
464
|
+
std::vector<__int128> ref_da(static_cast<size_t>(M) * K), ref_db(static_cast<size_t>(K) * N);
|
|
465
|
+
for (int i = 0; i < M; ++i) for (int k = 0; k < K; ++k) { __int128 s = 0; for (int j = 0; j < N; ++j) s += b[k * N + j]; ref_da[i * K + k] = s; }
|
|
466
|
+
for (int k = 0; k < K; ++k) for (int j = 0; j < N; ++j) { __int128 s = 0; for (int i = 0; i < M; ++i) s += a[i * K + k]; ref_db[k * N + j] = s; }
|
|
467
|
+
|
|
468
|
+
Tensor at = Tensor::from_data(a.data(), {M, K}, DType::I128);
|
|
469
|
+
Tensor bt = Tensor::from_data(b.data(), {K, N}, DType::I128);
|
|
470
|
+
const std::vector<__int128> got = read_i128(nn::matmul(at, bt));
|
|
471
|
+
double err = mean_abs_error_i128(got, ref_c);
|
|
472
|
+
int ok = 0; for (size_t i = 0; i < got.size(); ++i) if (got[i] == ref_c[i]) ++ok;
|
|
473
|
+
acc_f += 100.0 * ok / got.size(); err_f += err;
|
|
474
|
+
ms_f += time_once_ms([&] { Tensor c = nn::matmul(at, bt); (void)c; });
|
|
475
|
+
|
|
476
|
+
Tensor ag = Tensor::from_data(a.data(), {M, K}, DType::I128);
|
|
477
|
+
Tensor bg = Tensor::from_data(b.data(), {K, N}, DType::I128);
|
|
478
|
+
ag.set_requires_grad(true); bg.set_requires_grad(true);
|
|
479
|
+
ms_b += time_once_ms([&] {
|
|
480
|
+
ag = Tensor::from_data(a.data(), {M, K}, DType::I128);
|
|
481
|
+
bg = Tensor::from_data(b.data(), {K, N}, DType::I128);
|
|
482
|
+
ag.set_requires_grad(true); bg.set_requires_grad(true);
|
|
483
|
+
Tensor c = nn::matmul(ag, bg);
|
|
484
|
+
nn::sum(c).backward();
|
|
485
|
+
});
|
|
486
|
+
const std::vector<__int128> got_da = read_i128(ag.grad()), got_db = read_i128(bg.grad());
|
|
487
|
+
double err_da = mean_abs_error_i128(got_da, ref_da), err_db = mean_abs_error_i128(got_db, ref_db);
|
|
488
|
+
int ok_da = 0, ok_db = 0;
|
|
489
|
+
for (size_t i = 0; i < got_da.size(); ++i) if (got_da[i] == ref_da[i]) ++ok_da;
|
|
490
|
+
for (size_t i = 0; i < got_db.size(); ++i) if (got_db[i] == ref_db[i]) ++ok_db;
|
|
491
|
+
acc_b += 100.0 * (ok_da + ok_db) / (got_da.size() + got_db.size());
|
|
492
|
+
err_b += (err_da + err_db) / 2.0;
|
|
493
|
+
}
|
|
494
|
+
emit_metric("i128", 0, M, K, N, acc_f / DATA, err_f / DATA, ms_f / DATA, acc_b / DATA, err_b / DATA, ms_b / DATA);
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
static void metric_mx() {
|
|
498
|
+
const int M = 256, K = 256, N = 256;
|
|
499
|
+
const int DATA = 4;
|
|
500
|
+
double acc_f = 0.0, err_f = 0.0, ms_f = 0.0, acc_b = 0.0, err_b = 0.0, ms_b = 0.0;
|
|
501
|
+
for (int d = 0; d < DATA; ++d) {
|
|
502
|
+
std::vector<float> a(static_cast<size_t>(M) * K), b(static_cast<size_t>(K) * N);
|
|
503
|
+
fill_rand(a, 3000 + d, -2.0f, 2.0f);
|
|
504
|
+
fill_rand(b, 4000 + d, -2.0f, 2.0f);
|
|
505
|
+
std::vector<float> aq = mx_quantize(a, nullptr), bq = mx_quantize(b, nullptr);
|
|
506
|
+
const std::vector<float> ref_c = mx_quantize(ref_matmul_f32(aq, bq, M, K, N), nullptr);
|
|
507
|
+
std::vector<float> ref_da(static_cast<size_t>(M) * K), ref_db(static_cast<size_t>(K) * N);
|
|
508
|
+
for (int i = 0; i < M; ++i) for (int k = 0; k < K; ++k) { float s = 0; for (int j = 0; j < N; ++j) s += bq[k * N + j]; ref_da[i * K + k] = s; }
|
|
509
|
+
for (int k = 0; k < K; ++k) for (int j = 0; j < N; ++j) { float s = 0; for (int i = 0; i < M; ++i) s += aq[i * K + k]; ref_db[k * N + j] = s; }
|
|
510
|
+
ref_da = mx_quantize(ref_da, nullptr); ref_db = mx_quantize(ref_db, nullptr);
|
|
511
|
+
|
|
512
|
+
Tensor at = make_f32({M, K}, a).to(DType::MXFP4);
|
|
513
|
+
Tensor bt = make_f32({K, N}, b).to(DType::MXFP4);
|
|
514
|
+
const std::vector<float> got = f32_data(nn::matmul(at, bt).to(DType::F32));
|
|
515
|
+
double err = mean_abs_error_f32(got, ref_c);
|
|
516
|
+
int ok = 0; for (size_t i = 0; i < got.size(); ++i) if (std::fabs(got[i] - ref_c[i]) <= 0.75f + 0.1f * std::fabs(ref_c[i])) ++ok;
|
|
517
|
+
acc_f += 100.0 * ok / got.size(); err_f += err;
|
|
518
|
+
ms_f += time_once_ms([&] { Tensor c = nn::matmul(at, bt); (void)c; });
|
|
519
|
+
|
|
520
|
+
Tensor ag = make_f32({M, K}, a).to(DType::MXFP4), bg = make_f32({K, N}, b).to(DType::MXFP4);
|
|
521
|
+
ag.set_requires_grad(true); bg.set_requires_grad(true);
|
|
522
|
+
ms_b += time_once_ms([&] {
|
|
523
|
+
ag = make_f32({M, K}, a).to(DType::MXFP4); bg = make_f32({K, N}, b).to(DType::MXFP4);
|
|
524
|
+
ag.set_requires_grad(true); bg.set_requires_grad(true);
|
|
525
|
+
Tensor c = nn::matmul(ag, bg);
|
|
526
|
+
nn::sum(c).backward();
|
|
527
|
+
});
|
|
528
|
+
const std::vector<float> got_da = f32_data(ag.grad().to(DType::F32)), got_db = f32_data(bg.grad().to(DType::F32));
|
|
529
|
+
double err_da = mean_abs_error_f32(got_da, ref_da), err_db = mean_abs_error_f32(got_db, ref_db);
|
|
530
|
+
int ok_da = 0, ok_db = 0;
|
|
531
|
+
for (size_t i = 0; i < got_da.size(); ++i) if (std::fabs(got_da[i] - ref_da[i]) <= 0.75f + 0.1f * std::fabs(ref_da[i])) ++ok_da;
|
|
532
|
+
for (size_t i = 0; i < got_db.size(); ++i) if (std::fabs(got_db[i] - ref_db[i]) <= 0.75f + 0.1f * std::fabs(ref_db[i])) ++ok_db;
|
|
533
|
+
acc_b += 100.0 * (ok_da + ok_db) / (got_da.size() + got_db.size());
|
|
534
|
+
err_b += (err_da + err_db) / 2.0;
|
|
535
|
+
}
|
|
536
|
+
emit_metric("mxfp4", 0, M, K, N, acc_f / DATA, err_f / DATA, ms_f / DATA, acc_b / DATA, err_b / DATA, ms_b / DATA);
|
|
537
|
+
|
|
538
|
+
const int STOCH_DATA = 2;
|
|
539
|
+
const int samples = 1024;
|
|
540
|
+
double s_acc_f = 0.0, s_err_f = 0.0, s_ms_f = 0.0, s_acc_b = 0.0, s_err_b = 0.0, s_ms_b = 0.0;
|
|
541
|
+
double s_ref_mean = 0.0, s_ref_std = 0.0, s_cand_mean = 0.0, s_cand_std = 0.0;
|
|
542
|
+
for (int d = 0; d < STOCH_DATA; ++d) {
|
|
543
|
+
std::vector<float> a(static_cast<size_t>(M) * K), b(static_cast<size_t>(K) * N);
|
|
544
|
+
fill_rand(a, 5000 + d, -2.0f, 2.0f);
|
|
545
|
+
fill_rand(b, 6000 + d, -2.0f, 2.0f);
|
|
546
|
+
const size_t out_n = static_cast<size_t>(M) * N;
|
|
547
|
+
std::vector<double> ref_sum(out_n, 0.0), ref_sq(out_n, 0.0), cand_sum(out_n, 0.0), cand_sq(out_n, 0.0);
|
|
548
|
+
std::vector<double> ref_da_sum(static_cast<size_t>(M) * K, 0.0), ref_da_sq(ref_da_sum.size(), 0.0);
|
|
549
|
+
std::vector<double> ref_db_sum(static_cast<size_t>(K) * N, 0.0), ref_db_sq(ref_db_sum.size(), 0.0);
|
|
550
|
+
std::vector<double> cand_da_sum(ref_da_sum.size(), 0.0), cand_da_sq(ref_da_sum.size(), 0.0);
|
|
551
|
+
std::vector<double> cand_db_sum(ref_db_sum.size(), 0.0), cand_db_sq(ref_db_sum.size(), 0.0);
|
|
552
|
+
std::mt19937_64 ref_rng(0xabcdefULL + d);
|
|
553
|
+
for (int t = 0; t < samples; ++t) {
|
|
554
|
+
const std::vector<float> raq = mx_quantize(a, &ref_rng), rbq = mx_quantize(b, &ref_rng);
|
|
555
|
+
const std::vector<float> rc = mx_quantize(ref_matmul_f32(raq, rbq, M, K, N), &ref_rng);
|
|
556
|
+
add_stats(ref_sum, ref_sq, rc);
|
|
557
|
+
std::vector<float> rda(static_cast<size_t>(M) * K), rdb(static_cast<size_t>(K) * N);
|
|
558
|
+
for (int i = 0; i < M; ++i) for (int k = 0; k < K; ++k) { float s = 0; for (int j = 0; j < N; ++j) s += rbq[k * N + j]; rda[i * K + k] = s; }
|
|
559
|
+
for (int k = 0; k < K; ++k) for (int j = 0; j < N; ++j) { float s = 0; for (int i = 0; i < M; ++i) s += raq[i * K + k]; rdb[k * N + j] = s; }
|
|
560
|
+
rda = mx_quantize(rda, nullptr); rdb = mx_quantize(rdb, nullptr);
|
|
561
|
+
add_stats(ref_da_sum, ref_da_sq, rda); add_stats(ref_db_sum, ref_db_sq, rdb);
|
|
562
|
+
|
|
563
|
+
const uint64_t seed = 100000 + static_cast<uint64_t>(d) * samples + t;
|
|
564
|
+
Tensor qa = make_f32({M, K}, a).to(DType::MXFP4, nn::Rounding::Stochastic, seed);
|
|
565
|
+
Tensor qb = make_f32({K, N}, b).to(DType::MXFP4, nn::Rounding::Stochastic, seed + 7919);
|
|
566
|
+
Tensor c = nn::matmul(qa, qb);
|
|
567
|
+
add_stats(cand_sum, cand_sq, f32_data(c.to(DType::F32)));
|
|
568
|
+
qa.set_requires_grad(true); qb.set_requires_grad(true);
|
|
569
|
+
Tensor cg = nn::matmul(qa, qb);
|
|
570
|
+
nn::sum(cg).backward();
|
|
571
|
+
add_stats(cand_da_sum, cand_da_sq, f32_data(qa.grad().to(DType::F32)));
|
|
572
|
+
add_stats(cand_db_sum, cand_db_sq, f32_data(qb.grad().to(DType::F32)));
|
|
573
|
+
}
|
|
574
|
+
StatScore f = score_stats(ref_sum, ref_sq, cand_sum, cand_sq, samples);
|
|
575
|
+
StatScore bscore = score_stats(ref_da_sum, ref_da_sq, cand_da_sum, cand_da_sq, samples);
|
|
576
|
+
StatScore bs2 = score_stats(ref_db_sum, ref_db_sq, cand_db_sum, cand_db_sq, samples);
|
|
577
|
+
s_acc_f += f.accuracy; s_err_f += f.mean_err;
|
|
578
|
+
s_acc_b += (bscore.accuracy + bs2.accuracy) / 2.0;
|
|
579
|
+
s_err_b += (bscore.mean_err + bs2.mean_err) / 2.0;
|
|
580
|
+
s_ref_mean += f.ref_mean_avg; s_ref_std += f.ref_std_avg;
|
|
581
|
+
s_cand_mean += f.cand_mean_avg; s_cand_std += f.cand_std_avg;
|
|
582
|
+
s_ms_f += time_once_ms([&] {
|
|
583
|
+
Tensor qa = make_f32({M, K}, a).to(DType::MXFP4, nn::Rounding::Stochastic, 7);
|
|
584
|
+
Tensor qb = make_f32({K, N}, b).to(DType::MXFP4, nn::Rounding::Stochastic, 11);
|
|
585
|
+
Tensor c = nn::matmul(qa, qb); (void)c;
|
|
586
|
+
}, 1);
|
|
587
|
+
s_ms_b += time_once_ms([&] {
|
|
588
|
+
Tensor qa = make_f32({M, K}, a).to(DType::MXFP4, nn::Rounding::Stochastic, 7);
|
|
589
|
+
Tensor qb = make_f32({K, N}, b).to(DType::MXFP4, nn::Rounding::Stochastic, 11);
|
|
590
|
+
qa.set_requires_grad(true); qb.set_requires_grad(true);
|
|
591
|
+
Tensor c = nn::matmul(qa, qb);
|
|
592
|
+
nn::sum(c).backward();
|
|
593
|
+
}, 1);
|
|
594
|
+
std::printf("STAT data=%d samples=%d fwd_acc=%.6f fwd_mean_err=%.9g fwd_std_ratio=%.9g bwd_acc=%.6f bwd_mean_err=%.9g bwd_std_ratio=%.9g ref_mean=%.9g ref_std=%.9g cand_mean=%.9g cand_std=%.9g\n",
|
|
595
|
+
d, samples, f.accuracy, f.mean_err, f.std_ratio, (bscore.accuracy + bs2.accuracy) / 2.0,
|
|
596
|
+
(bscore.mean_err + bs2.mean_err) / 2.0, (bscore.std_ratio + bs2.std_ratio) / 2.0,
|
|
597
|
+
f.ref_mean_avg, f.ref_std_avg, f.cand_mean_avg, f.cand_std_avg);
|
|
598
|
+
}
|
|
599
|
+
emit_metric("mxfp4", 1, M, K, N, s_acc_f / STOCH_DATA, s_err_f / STOCH_DATA, s_ms_f / STOCH_DATA,
|
|
600
|
+
s_acc_b / STOCH_DATA, s_err_b / STOCH_DATA, s_ms_b / STOCH_DATA);
|
|
601
|
+
std::printf("STAT dtype=mxfp4 stochastic=1 data=%d samples=%d ref_mean_avg=%.9g ref_std_avg=%.9g cand_mean_avg=%.9g cand_std_avg=%.9g\n",
|
|
602
|
+
STOCH_DATA, samples, s_ref_mean / STOCH_DATA, s_ref_std / STOCH_DATA,
|
|
603
|
+
s_cand_mean / STOCH_DATA, s_cand_std / STOCH_DATA);
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
|
|
607
|
+
int main() {
|
|
608
|
+
test_dtype_metadata();
|
|
609
|
+
test_casts_float();
|
|
610
|
+
test_casts_int();
|
|
611
|
+
test_integer_casts();
|
|
612
|
+
test_low_precision_casts();
|
|
613
|
+
test_views();
|
|
614
|
+
test_slices();
|
|
615
|
+
test_elementwise_broadcast();
|
|
616
|
+
test_reductions();
|
|
617
|
+
test_matmul_2d();
|
|
618
|
+
test_matmul_batch_and_nd();
|
|
619
|
+
test_autograd_add_mul();
|
|
620
|
+
test_autograd_matmul();
|
|
621
|
+
test_autograd_view_slice();
|
|
622
|
+
test_stochastic_stats();
|
|
623
|
+
test_threads();
|
|
624
|
+
test_all_dtype_alloc();
|
|
625
|
+
bench_matmul();
|
|
626
|
+
try { metric_f32(); } catch (const std::exception& e) { std::printf("METRIC dtype=f32 stochastic=0 error=%s\n", e.what()); }
|
|
627
|
+
try { metric_i128(); } catch (const std::exception& e) { std::printf("METRIC dtype=i128 stochastic=0 error=%s\n", e.what()); }
|
|
628
|
+
try { metric_mx(); } catch (const std::exception& e) { std::printf("METRIC dtype=mxfp4 stochastic=0 error=%s\n", e.what()); }
|
|
629
|
+
std::printf("SUMMARY %d %d\n", g_passed, g_failed);
|
|
630
|
+
return g_failed == 0 ? 0 : 1;
|
|
631
|
+
}
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Evaluate the pure C++ Neural-CPP task.
|
|
3
|
+
|
|
4
|
+
The public workspace contains only the API contract and build skeleton. Hidden
|
|
5
|
+
C++ tests are injected from the plugin asset directory and generate their data
|
|
6
|
+
from fixed seeds at run time; no hidden data is copied into the candidate tree.
|
|
7
|
+
"""
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import math
|
|
11
|
+
import os
|
|
12
|
+
import shutil
|
|
13
|
+
import subprocess
|
|
14
|
+
import sys
|
|
15
|
+
import tempfile
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
|
|
18
|
+
from common import EVAL_ROOT, clean_copy, emit, fail, parse_workspace
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def run(cmd: list[str], cwd: Path, timeout: int = 600) -> subprocess.CompletedProcess[str]:
|
|
22
|
+
env = dict(os.environ)
|
|
23
|
+
env.pop('PYTHONPATH', None)
|
|
24
|
+
env.pop('PYTHONHOME', None)
|
|
25
|
+
return subprocess.run(cmd, cwd=str(cwd), capture_output=True, text=True,
|
|
26
|
+
encoding='utf-8', errors='replace', env=env, timeout=timeout)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def main() -> int:
|
|
30
|
+
workspace = parse_workspace()
|
|
31
|
+
hidden = EVAL_ROOT.parent / 'assets' / 'neural-cpp' / 'hidden' / 'test_neural.cpp'
|
|
32
|
+
if not hidden.is_file():
|
|
33
|
+
return fail({'task': 'neural-cpp', 'ok': False, 'error': 'hidden test missing'})
|
|
34
|
+
|
|
35
|
+
with tempfile.TemporaryDirectory(prefix='neural-cpp-eval-') as td:
|
|
36
|
+
root = Path(td)
|
|
37
|
+
candidate = root / 'candidate'
|
|
38
|
+
clean_copy(workspace, candidate)
|
|
39
|
+
build = candidate / 'build'
|
|
40
|
+
if build.exists():
|
|
41
|
+
shutil.rmtree(build, ignore_errors=True)
|
|
42
|
+
build.mkdir()
|
|
43
|
+
|
|
44
|
+
cmake = shutil.which('cmake')
|
|
45
|
+
compiler = shutil.which('g++')
|
|
46
|
+
if cmake is None or compiler is None:
|
|
47
|
+
return fail({'task': 'neural-cpp', 'ok': False, 'error': 'cmake/g++ not available'})
|
|
48
|
+
|
|
49
|
+
cfg = run([cmake, '-S', '.', '-B', 'build', '-DCMAKE_BUILD_TYPE=Release'], candidate, 180)
|
|
50
|
+
if cfg.returncode != 0:
|
|
51
|
+
return fail({'task': 'neural-cpp', 'ok': False, 'error': 'cmake configure failed',
|
|
52
|
+
'output': (cfg.stdout + cfg.stderr)[-5000:]})
|
|
53
|
+
bld = run([cmake, '--build', 'build', '-j4'], candidate, 1800)
|
|
54
|
+
if bld.returncode != 0:
|
|
55
|
+
return fail({'task': 'neural-cpp', 'ok': False, 'error': 'build failed',
|
|
56
|
+
'output': (bld.stdout + bld.stderr)[-5000:]})
|
|
57
|
+
lib = build / 'libnn.a'
|
|
58
|
+
if not lib.is_file():
|
|
59
|
+
return fail({'task': 'neural-cpp', 'ok': False, 'error': 'build/libnn.a missing'})
|
|
60
|
+
|
|
61
|
+
exe = root / 'test_neural'
|
|
62
|
+
cc = run([compiler, '-std=c++17', '-O3', '-pthread',
|
|
63
|
+
'-I', str(candidate / 'include'), str(hidden), str(lib),
|
|
64
|
+
'-lm', '-o', str(exe)], root, 300)
|
|
65
|
+
if cc.returncode != 0:
|
|
66
|
+
return fail({'task': 'neural-cpp', 'ok': False, 'error': 'hidden test compile failed',
|
|
67
|
+
'output': (cc.stdout + cc.stderr)[-5000:]})
|
|
68
|
+
|
|
69
|
+
try:
|
|
70
|
+
proc = run([str(exe)], root, 600)
|
|
71
|
+
except subprocess.TimeoutExpired:
|
|
72
|
+
return fail({'task': 'neural-cpp', 'ok': False, 'error': 'hidden tests timed out'})
|
|
73
|
+
|
|
74
|
+
output = proc.stdout + proc.stderr
|
|
75
|
+
passed = failed = 0
|
|
76
|
+
gflops = 0.0
|
|
77
|
+
metrics: list[dict] = []
|
|
78
|
+
stats: list[dict] = []
|
|
79
|
+
for line in output.splitlines():
|
|
80
|
+
parts = line.strip().split()
|
|
81
|
+
if len(parts) == 4 and parts[0] == 'TEST' and parts[2] == 'PASS':
|
|
82
|
+
passed += 1
|
|
83
|
+
elif len(parts) == 4 and parts[0] == 'TEST' and parts[2] == 'FAIL':
|
|
84
|
+
failed += 1
|
|
85
|
+
elif len(parts) == 3 and parts[0] == 'SUMMARY':
|
|
86
|
+
try:
|
|
87
|
+
passed, failed = int(parts[1]), int(parts[2])
|
|
88
|
+
except ValueError:
|
|
89
|
+
pass
|
|
90
|
+
elif len(parts) == 2 and parts[0] == 'PERF_GFLOPS':
|
|
91
|
+
try:
|
|
92
|
+
gflops = float(parts[1])
|
|
93
|
+
except ValueError:
|
|
94
|
+
pass
|
|
95
|
+
elif parts and parts[0] in {'METRIC', 'STAT'}:
|
|
96
|
+
row: dict[str, object] = {}
|
|
97
|
+
for item in parts[1:]:
|
|
98
|
+
if '=' not in item:
|
|
99
|
+
continue
|
|
100
|
+
key, value = item.split('=', 1)
|
|
101
|
+
try:
|
|
102
|
+
row[key] = float(value)
|
|
103
|
+
except ValueError:
|
|
104
|
+
row[key] = value
|
|
105
|
+
if parts[0] == 'METRIC':
|
|
106
|
+
metrics.append(row)
|
|
107
|
+
else:
|
|
108
|
+
stats.append(row)
|
|
109
|
+
|
|
110
|
+
total = passed + failed
|
|
111
|
+
accuracy = (100.0 * passed / total) if total else 0.0
|
|
112
|
+
metric_scores: list[float] = []
|
|
113
|
+
for row in metrics:
|
|
114
|
+
for key in ('fwd_accuracy', 'bwd_accuracy'):
|
|
115
|
+
value = row.get(key)
|
|
116
|
+
if isinstance(value, (int, float)) and float(value) >= 0:
|
|
117
|
+
metric_scores.append(float(value))
|
|
118
|
+
matrix_accuracy = sum(metric_scores) / len(metric_scores) if metric_scores else 0.0
|
|
119
|
+
matrix_sizes: dict[str, list[int]] = {}
|
|
120
|
+
speed_samples: list[float] = []
|
|
121
|
+
speed_by_dtype: dict[str, list[float]] = {}
|
|
122
|
+
for row in metrics:
|
|
123
|
+
dtype = str(row.get('dtype', ''))
|
|
124
|
+
try:
|
|
125
|
+
m = int(float(row.get('m', 0)))
|
|
126
|
+
k = int(float(row.get('k', 0)))
|
|
127
|
+
n = int(float(row.get('n', 0)))
|
|
128
|
+
except (TypeError, ValueError):
|
|
129
|
+
m = k = n = 0
|
|
130
|
+
if m > 0 and k > 0 and n > 0:
|
|
131
|
+
matrix_sizes.setdefault(dtype, [m, k, n])
|
|
132
|
+
ops = 2.0 * m * k * n
|
|
133
|
+
for key in ('fwd_ms', 'bwd_ms'):
|
|
134
|
+
value = row.get(key)
|
|
135
|
+
if isinstance(value, (int, float)) and float(value) > 0:
|
|
136
|
+
gflops = ops / (float(value) * 1e6)
|
|
137
|
+
speed_samples.append(gflops)
|
|
138
|
+
speed_by_dtype.setdefault(dtype, []).append(gflops)
|
|
139
|
+
if speed_samples:
|
|
140
|
+
speed_geomean = math.exp(sum(math.log(v) for v in speed_samples) / len(speed_samples))
|
|
141
|
+
else:
|
|
142
|
+
speed_geomean = 0.0
|
|
143
|
+
speed_geomean_by_dtype = {
|
|
144
|
+
dtype: round(math.exp(sum(math.log(v) for v in vals) / len(vals)), 3)
|
|
145
|
+
for dtype, vals in speed_by_dtype.items() if vals
|
|
146
|
+
}
|
|
147
|
+
core_ok = total > 0 and failed == 0 and proc.returncode == 0
|
|
148
|
+
resolved = core_ok and matrix_accuracy >= 95.0
|
|
149
|
+
score = round(0.5 * accuracy + 0.5 * matrix_accuracy, 3)
|
|
150
|
+
emit({
|
|
151
|
+
'task': 'neural-cpp',
|
|
152
|
+
'ok': True,
|
|
153
|
+
'score': score,
|
|
154
|
+
'accuracy': accuracy,
|
|
155
|
+
'coreAccuracy': accuracy,
|
|
156
|
+
'matrixAccuracy': round(matrix_accuracy, 3),
|
|
157
|
+
'speedGeomeanGflops': round(speed_geomean, 3),
|
|
158
|
+
'speedGeomeanByDtype': speed_geomean_by_dtype,
|
|
159
|
+
'matrixSizes': matrix_sizes,
|
|
160
|
+
'resolved': resolved,
|
|
161
|
+
'passed': passed,
|
|
162
|
+
'failed': failed,
|
|
163
|
+
'speedGflops': round(gflops, 3),
|
|
164
|
+
'metrics': metrics,
|
|
165
|
+
'stats': stats,
|
|
166
|
+
'returncode': proc.returncode,
|
|
167
|
+
'output': output[-4000:],
|
|
168
|
+
})
|
|
169
|
+
return 0 if resolved else 1
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
if __name__ == '__main__':
|
|
173
|
+
raise SystemExit(main())
|
package/lib/client/index.js.map
CHANGED
|
@@ -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'\n\n/** One validated clone remote for a task. */\nexport interface TaskRemote {\n id: string\n label: string\n url: string\n}\n\n/** Common pip indexes offered by the settings page. */\nexport const PIP_MIRRORS: readonly { id: string; label: string; url: string }[] = [\n { id: 'pypi', label: 'PyPI', url: 'https://pypi.org/simple' },\n { id: 'tsinghua', label: '清华 TUNA', url: 'https://pypi.tuna.tsinghua.edu.cn/simple' },\n { id: 'aliyun', label: '阿里云', url: 'https://mirrors.aliyun.com/pypi/simple' },\n { id: 'tencent', label: '腾讯云', url: 'https://mirrors.cloud.tencent.com/pypi/simple' },\n { id: 'bfsu', label: '北外', url: 'https://mirrors.bfsu.edu.cn/pypi/web/simple' },\n { id: 'sjtu', label: '上海交大', url: 'https://mirror.sjtu.edu.cn/pypi/web/simple' },\n]\n\n/** One task offered by the installer. */\nexport interface TaskInfo {\n id: string\n label: string\n description: string\n /** Default wall-clock limit applied when the user selects this task. */\n timeLimitMinutes: number\n /** Default time-limit switch applied when the user selects this task. */\n timeLimitEnabled: boolean\n /** Whether installation needs a host-side clone / venv setup. */\n needsSetup: boolean\n /** Canonical upstream repository; used to build mirror URLs. */\n repoUrl?: string\n /** Clone remotes verified to contain the exact pinned commit. */\n remotes?: TaskRemote[]\n}\n\nexport type JobKind = 'install' | 'eval'\nexport type JobStatus = 'queued' | 'running' | 'succeeded' | 'failed' | 'cancelled' | 'interrupted'\n\n/** Summary of one background setup or evaluation job. */\nexport interface JobInfo {\n id: string\n kind: JobKind\n task: string\n workspaceId: string\n status: JobStatus\n createdAt: number\n startedAt: number | null\n endedAt: number | null\n updatedAt: number\n error?: string\n}\n\n/** Full job state, including a bounded log and optional result. */\nexport interface JobDetail extends JobInfo {\n log: string\n prompt?: string\n runId?: string\n result?: unknown\n}\n\n/** A live conversation the enable-time warning has to mention. */\nexport interface RunningSession {\n sessionId: string\n title: string\n cwd: string\n running: boolean\n jobs: number\n}\n\n/** One warning surfaced to the browser. */\nexport interface GuardEvent {\n seq: number\n at: number\n sessionId?: string\n runId?: string\n kind: 'tool-blocked' | 'path-denied' | 'process-denied' | 'wait-blocked' | 'timeout' | 'notice'\n tool?: string\n detail: string\n}\n\n/** Host answer for the enable pre-check. */\nexport interface GuardState {\n enabled: boolean\n running: RunningSession[]\n tasks: TaskInfo[]\n defaultBlacklist: string\n generatedDefault: boolean\n workspaceRoot: string\n runsRoot: string\n pipMirrors?: { id: string; label: string; url: string }[]\n}\n\n/** Result of checking one workspace before install. */\nexport interface CheckResult {\n ok: boolean\n workspaceId: string\n path: string\n empty: boolean\n entries: string[]\n error?: string\n}\n\n/** Result of installing the task pack. */\nexport interface InstallResult {\n ok: boolean\n error?: string\n runId?: string\n workspaceId?: string\n workspacePath?: string\n prompt?: string\n}\n\n/** Manual-channel material locations. */\nexport interface ManualPaths {\n source: string\n prompt: string\n}\n\n/** Usage record written next to one run. */\nexport interface RunUsage {\n inputTokens: number\n outputTokens: number\n cacheReadTokens: number\n cacheWriteTokens: number\n reasoningTokens: number\n toolCalls: number\n turns: number\n steps: number\n wallTimeMs: number\n startedAt: number | null\n updatedAt: number\n}\n\n/** Metadata for one guarded task run. */\nexport interface RunRecord {\n runId: string\n task: string\n workspaceId: string\n workspacePath: string\n sessionId: string | null\n createdAt: number\n startedAt: number | null\n endedAt: number | null\n status: 'prepared' | 'active' | 'timeout' | 'ended'\n prompt: string\n timeLimitMinutes: number\n provider?: string\n model?: string\n title?: string\n}\n","/** Shell capabilities published to the Settings panel. */\nexport interface EvalWorkspace { id: string; label: string }\nexport interface EvalBridge {\n startSession(workspaceId: string, prompt: string): void\n workspaces(): readonly EvalWorkspace[]\n}\nlet current: EvalBridge | undefined\nexport function configureEvalBridge(next: EvalBridge | undefined): void { current = next }\nexport function evalBridge(): EvalBridge | undefined { return current }\n","/**\n * Settings panel for the evaluation guard.\n * @module dsh-eval-guard/client/Settings\n */\nimport { useEffect, useRef, useState, useSyncExternalStore, type CSSProperties, type ReactElement } from 'react'\nimport {\n CHECK_ROUTE, EVENTS_ROUTE, INSTALL_ROUTE, MANUAL_ROUTE, REVEAL_ROUTE, STATE_ROUTE,\n JOBS_ROUTE, JOB_ROUTE, JOB_CANCEL_ROUTE, EVAL_ROUTE,\n type CheckResult, type GuardEvent, type GuardState, type InstallResult, type ManualPaths, type JobDetail, type JobInfo,\n PIP_MIRRORS,\n} from '../shared.ts'\nimport { evalBridge } from './bridge.ts'\n\ntype Snapshot = {\n status: 'loading' | 'ready' | 'unavailable'\n value?: Record<string, unknown>\n revision?: number\n writable: boolean\n}\ntype Form = {\n getSnapshot: () => Snapshot\n subscribe: (listener: () => void) => () => void\n mutate: (ops: readonly { op: 'set'; path: string[]; value: unknown }[], revision?: number) => Promise<boolean>\n}\ntype Props = { form: Form; t: (key: string) => string }\n\ninterface Draft {\n enabled: boolean\n timeLimitEnabled: boolean\n timeLimitMinutes: number\n forbiddenPaths: string\n toolBlacklistUseDefault: boolean\n toolBlacklist: string\n cloneSource: string\n customCloneUrl: string\n pipIndex: string\n customPipUrl: string\n gitProxyUrl: string\n pipProxyUrl: string\n}\n\nconst EMPTY: Draft = {\n enabled: false,\n timeLimitEnabled: true,\n timeLimitMinutes: 90,\n forbiddenPaths: '',\n toolBlacklistUseDefault: true,\n toolBlacklist: '',\n cloneSource: 'github',\n customCloneUrl: '',\n pipIndex: 'pypi',\n customPipUrl: '',\n gitProxyUrl: '',\n pipProxyUrl: '',\n}\n\nconst box: CSSProperties = { border: '1px solid var(--vscode-panel-border, #3c3c3c)', borderRadius: 8, padding: 14, marginBottom: 14 }\nconst row: CSSProperties = { display: 'flex', gap: 10, alignItems: 'center', flexWrap: 'wrap', marginBottom: 8 }\nconst note: CSSProperties = { opacity: 0.72, fontSize: 12, lineHeight: 1.5, margin: '6px 0' }\nconst textarea: CSSProperties = { width: '100%', minHeight: 110, fontFamily: 'monospace', fontSize: 12, padding: 8, boxSizing: 'border-box' }\nconst button: CSSProperties = { padding: '5px 12px', borderRadius: 6, cursor: 'pointer' }\nconst primary: CSSProperties = { ...button, background: '#2f6fd0', color: '#fff', border: 'none' }\nconst danger: CSSProperties = { ...button, background: '#a33', color: '#fff', border: 'none' }\n\nasync function readJson<T>(response: Response): Promise<T> { return await response.json() as T }\n\nfunction normalize(value: Record<string, unknown> | undefined): Draft {\n return {\n enabled: value?.enabled === true,\n timeLimitEnabled: value?.timeLimitEnabled !== false,\n timeLimitMinutes: typeof value?.timeLimitMinutes === 'number' ? value.timeLimitMinutes : 90,\n forbiddenPaths: typeof value?.forbiddenPaths === 'string' ? value.forbiddenPaths : '',\n toolBlacklistUseDefault: value?.toolBlacklistUseDefault !== false,\n toolBlacklist: typeof value?.toolBlacklist === 'string' ? value.toolBlacklist : '',\n cloneSource: typeof value?.cloneSource === 'string' && value.cloneSource !== '' ? value.cloneSource : 'github',\n customCloneUrl: typeof value?.customCloneUrl === 'string' ? value.customCloneUrl : '',\n pipIndex: typeof value?.pipIndex === 'string' && value.pipIndex !== '' ? value.pipIndex : 'pypi',\n customPipUrl: typeof value?.customPipUrl === 'string' ? value.customPipUrl : '',\n gitProxyUrl: typeof value?.gitProxyUrl === 'string' ? value.gitProxyUrl : '',\n pipProxyUrl: typeof value?.pipProxyUrl === 'string' ? value.pipProxyUrl : '',\n }\n}\n\n/** The settings card. */\nexport function EvalGuardSettings({ form, t }: Props): ReactElement {\n const snapshot = useSyncExternalStore(form.subscribe, form.getSnapshot, form.getSnapshot)\n const [draft, setDraft] = useState<Draft>(EMPTY)\n const [dirty, setDirty] = useState(false)\n const [state, setState] = useState<GuardState | null>(null)\n const [events, setEvents] = useState<GuardEvent[]>([])\n const [pendingEnable, setPendingEnable] = useState(false)\n const [notice, setNotice] = useState('')\n const [error, setError] = useState('')\n const [workspaceId, setWorkspaceId] = useState(() => typeof localStorage === 'undefined' ? '' : localStorage.getItem('evalGuard.workspaceId') ?? '')\n const [taskId, setTaskId] = useState(() => typeof localStorage === 'undefined' ? '' : localStorage.getItem('evalGuard.taskId') ?? '')\n const [check, setCheck] = useState<CheckResult | null>(null)\n const [manual, setManual] = useState<ManualPaths | null>(null)\n const [prompt, setPrompt] = useState('')\n const [copied, setCopied] = useState('')\n const workspaces = evalBridge()?.workspaces() ?? []\n const [job, setJob] = useState<JobDetail | null>(null)\n const [jobNotice, setJobNotice] = useState('')\n const autoOpenJob = useRef('')\n\n const pollJob = (id: string): void => {\n fetch(JOB_ROUTE + '?id=' + encodeURIComponent(id)).then(readJson<JobDetail>).then(setJob).catch(() => undefined)\n }\n const loadLatestJob = (workspace: string, task: string): void => {\n if (workspace === '' || task === '') { setJob(null); return }\n fetch(JOBS_ROUTE + '?workspaceId=' + encodeURIComponent(workspace) + '&task=' + encodeURIComponent(task))\n .then(readJson<JobInfo[]>).then(items => {\n const latest = items[0]\n if (latest !== undefined) pollJob(latest.id)\n else setJob(null)\n }).catch(() => undefined)\n }\n useEffect(() => {\n if (job === null || (job.status !== 'running' && job.status !== 'queued')) return\n const timer = setInterval(() => { pollJob(job.id) }, 800)\n return () => clearInterval(timer)\n }, [job])\n useEffect(() => { if (job?.status === 'succeeded' && job.kind === 'install' && job.prompt !== undefined) {\n setPrompt(job.prompt); setJobNotice(t('settings.installOk')); loadState()\n if (autoOpenJob.current === job.id) {\n autoOpenJob.current = ''\n evalBridge()?.startSession(job.workspaceId, job.prompt)\n }\n } }, [job])\n useEffect(() => { loadLatestJob(workspaceId, taskId) }, [workspaceId, taskId])\n\n useEffect(() => {\n if (snapshot.status !== 'ready' || snapshot.value === undefined || dirty) return\n setDraft(normalize(snapshot.value))\n }, [snapshot, dirty])\n\n const loadState = (): void => {\n fetch(STATE_ROUTE).then(readJson<GuardState>).then(setState).catch(() => setState(null))\n }\n useEffect(() => {\n loadState()\n let since = 0\n const timer = setInterval(() => {\n fetch(EVENTS_ROUTE + '?since=' + String(since)).then(readJson<{ events: GuardEvent[] }>).then(data => {\n if (data.events.length === 0) return\n since = data.events[data.events.length - 1]!.seq\n setEvents(current => [...data.events, ...current].slice(0, 12))\n }).catch(() => undefined)\n }, 2000)\n return () => clearInterval(timer)\n }, [])\n\n useEffect(() => {\n if (state !== null && state.tasks.length > 0 && (taskId === '' || !state.tasks.some(task => task.id === taskId))) setTaskId(state.tasks[0]!.id)\n }, [state, taskId])\n\n const ready = snapshot.status === 'ready' && snapshot.writable\n const save = async (patch: Partial<Draft>): Promise<void> => {\n if (!ready || snapshot.revision === undefined) return\n const next = { ...draft, ...patch }\n const ops: { op: 'set'; path: string[]; value: unknown }[] = []\n for (const key of Object.keys(patch) as (keyof Draft)[]) ops.push({ op: 'set', path: [key], value: next[key] })\n try {\n const accepted = await form.mutate(ops, snapshot.revision)\n if (!accepted) { setError('保存冲突,请刷新后重试。'); return }\n setDraft(next)\n setDirty(false)\n setError('')\n loadState()\n } catch (reason: unknown) {\n setError(reason instanceof Error ? reason.message : String(reason))\n }\n }\n const edit = (patch: Partial<Draft>): void => {\n setDraft(current => ({ ...current, ...patch }))\n setDirty(true)\n }\n\n const selectTask = (next: string): void => {\n setTaskId(next)\n try { localStorage.setItem('evalGuard.taskId', next) } catch { /* storage is optional */ }\n setCheck(null); setManual(null); setPrompt(''); setJob(null); setJobNotice('')\n if (workspaceId !== '') loadManual(workspaceId, next)\n const task = state?.tasks.find(item => item.id === next)\n if (task === undefined) return\n const remotes = task.remotes ?? []\n const cloneSource = draft.cloneSource === 'custom' || remotes.some(remote => remote.id === draft.cloneSource)\n ? draft.cloneSource : (remotes[0]?.id ?? 'github')\n setDraft(current => ({ ...current, timeLimitMinutes: task.timeLimitMinutes, timeLimitEnabled: task.timeLimitEnabled, cloneSource }))\n setNotice(t('settings.taskDefaults').replace('{minutes}', String(task.timeLimitMinutes)).replace('{state}', task.timeLimitEnabled ? t('settings.on') : t('settings.off')))\n void save({ timeLimitMinutes: task.timeLimitMinutes, timeLimitEnabled: task.timeLimitEnabled, cloneSource })\n }\n\n const toggleEnabled = (next: boolean): void => {\n if (!next) { void save({ enabled: false }); return }\n fetch(STATE_ROUTE).then(readJson<GuardState>).then(latest => {\n setState(latest)\n if (latest.running.length > 0) setPendingEnable(true)\n else void save({ enabled: true })\n }).catch(() => void save({ enabled: true }))\n }\n\n const forceEnable = (): void => {\n setPendingEnable(false)\n void save({ enabled: true })\n }\n\n const loadManual = (id: string, task: string): void => {\n if (id === '') { setCheck(null); setManual(null); setPrompt(''); return }\n fetch(CHECK_ROUTE + '?workspaceId=' + encodeURIComponent(id)).then(readJson<CheckResult>).then(result => {\n setCheck(result)\n if (result.ok) {\n fetch(MANUAL_ROUTE + '?workspaceId=' + encodeURIComponent(id) + '&task=' + encodeURIComponent(task)).then(readJson<ManualPaths>).then(paths => {\n setManual(paths)\n setPrompt(paths.prompt)\n }).catch(() => undefined)\n }\n }).catch((reason: unknown) => setError(reason instanceof Error ? reason.message : String(reason)))\n }\n\n const install = async (): Promise<void> => {\n if (workspaceId === '' || taskId === '') return\n setError(''); setNotice(''); setJobNotice('')\n const checked = await fetch(CHECK_ROUTE + '?workspaceId=' + encodeURIComponent(workspaceId)).then(readJson<CheckResult>)\n setCheck(checked)\n if (!checked.ok || !checked.empty) { setError(checked.error ?? t('settings.nonEmpty')); return }\n const result = await fetch(INSTALL_ROUTE, {\n method: 'POST', headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ workspaceId, task: taskId, cloneSource: draft.cloneSource, customCloneUrl: draft.customCloneUrl,\n pipIndex: draft.pipIndex, customPipUrl: draft.customPipUrl, gitProxyUrl: draft.gitProxyUrl, pipProxyUrl: draft.pipProxyUrl }),\n }).then(readJson<{ ok: boolean; jobId?: string; error?: string }>)\n if (!result.ok || result.jobId === undefined) { autoOpenJob.current = ''; setError(result.error ?? '安装失败'); return }\n autoOpenJob.current = result.jobId\n pollJob(result.jobId)\n }\n\n const evaluate = async (): Promise<void> => {\n if (workspaceId === '' || taskId === '') return\n setError(''); setNotice(''); setJobNotice('')\n const result = await fetch(EVAL_ROUTE, {\n method: 'POST', headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ workspaceId, task: taskId }),\n }).then(readJson<{ ok: boolean; jobId?: string; error?: string }>)\n if (!result.ok || result.jobId === undefined) { setError(result.error ?? '评测启动失败'); return }\n pollJob(result.jobId)\n }\n\n const cancelJob = async (): Promise<void> => {\n if (job === null) return\n await fetch(JOB_CANCEL_ROUTE, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ id: job.id }) })\n pollJob(job.id)\n }\n\n const copy = async (label: string, text: string): Promise<void> => {\n try {\n await navigator.clipboard.writeText(text)\n setCopied(label)\n setTimeout(() => setCopied(''), 1500)\n } catch { setError('复制失败') }\n }\n const reveal = (target: string): void => {\n void fetch(REVEAL_ROUTE, {\n method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ path: target }),\n })\n }\n const blacklistText = draft.toolBlacklistUseDefault ? state?.defaultBlacklist ?? '' : draft.toolBlacklist\n\n if (snapshot.status === 'loading') return <div style={box}>{t('settings.loading')}</div>\n return <div>\n {pendingEnable && <div style={{ ...box, borderColor: '#caa23a' }}>\n <strong>{t('settings.warningTitle')}</strong>\n <p style={note}>{t('settings.runningWarning')}</p>\n <ul style={{ ...note, paddingLeft: 18 }}>{(state?.running ?? []).map(item =>\n <li key={item.sessionId}>{item.title} · {item.cwd}{item.jobs > 0 ? ' · jobs: ' + String(item.jobs) : ''}</li>)}</ul>\n <div style={row}>\n <button style={button} onClick={() => { setPendingEnable(false); loadState() }}>{t('settings.runningCancel')}</button>\n <button style={danger} onClick={forceEnable}>{t('settings.runningForce')}</button>\n </div>\n </div>}\n\n <section style={box}>\n <div style={row}>\n <label><input type=\"checkbox\" checked={draft.enabled} disabled={!ready} onChange={event => toggleEnabled(event.target.checked)} /> {t('settings.enabled')}</label>\n </div>\n <p style={note}>{t('settings.enabledHint')}</p>\n </section>\n\n <section style={box}>\n <strong>{t('settings.forbidden')}</strong>\n <p style={note}>{t('settings.forbiddenHint')}</p>\n <textarea style={textarea} value={draft.forbiddenPaths} disabled={!ready}\n onChange={event => edit({ forbiddenPaths: event.target.value })}\n onBlur={() => void save({ forbiddenPaths: draft.forbiddenPaths })} />\n </section>\n\n <section style={box}>\n <div style={row}>\n <strong>{t('settings.blacklist')}</strong>\n <button style={button} disabled={!ready} onClick={() => void save({ toolBlacklistUseDefault: true, toolBlacklist: '' })}>{t('settings.reset')}</button>\n </div>\n <p style={note}>{t('settings.blacklistHint')}</p>\n <textarea style={textarea} value={blacklistText} disabled={!ready}\n onChange={event => edit({ toolBlacklistUseDefault: false, toolBlacklist: event.target.value })}\n onBlur={() => void save({ toolBlacklistUseDefault: draft.toolBlacklistUseDefault, toolBlacklist: draft.toolBlacklist })} />\n {draft.toolBlacklistUseDefault && <p style={note}>{t('settings.editingDefault')}</p>}\n </section>\n\n <section style={box}>\n <strong>{t('settings.task')}</strong>\n <p style={note}>{t('settings.taskHint')}</p>\n <div style={row}>\n <span>{t('settings.taskLabel')}:</span>\n <select value={taskId} disabled={state === null || state.tasks.length === 0}\n onChange={event => selectTask(event.target.value)}>\n {(state?.tasks ?? []).map(task => <option key={task.id} value={task.id}>{task.label}</option>)}\n </select>\n </div>\n {state !== null && <p style={note}>{state.tasks.find(task => task.id === taskId)?.description ?? ''}</p>}\n {(() => {\n const selected = state?.tasks.find(item => item.id === taskId)\n if (selected?.needsSetup !== true) return null\n return <div>\n <div style={row}>\n <span>{t('settings.cloneSource')}:</span>\n <select value={draft.cloneSource} disabled={!ready} onChange={event => void save({ cloneSource: event.target.value })}>\n {(selected.remotes ?? []).map(remote => <option key={remote.id} value={remote.id}>{remote.label}</option>)}\n <option value=\"custom\">{t('settings.custom')}</option>\n </select>\n {draft.cloneSource === 'custom' && <input style={{ width: 260 }} disabled={!ready} value={draft.customCloneUrl}\n onChange={event => edit({ customCloneUrl: event.target.value })} onBlur={() => void save({ customCloneUrl: draft.customCloneUrl })} placeholder=\"https://git.example.com\" />}\n </div>\n <div style={row}>\n <span>{t('settings.pipIndex')}:</span>\n <select value={draft.pipIndex} disabled={!ready} onChange={event => void save({ pipIndex: event.target.value })}>\n {PIP_MIRRORS.map(mirror => <option key={mirror.id} value={mirror.id}>{mirror.label}</option>)}\n <option value=\"custom\">{t('settings.custom')}</option>\n </select>\n {draft.pipIndex === 'custom' && <input style={{ width: 260 }} disabled={!ready} value={draft.customPipUrl}\n onChange={event => edit({ customPipUrl: event.target.value })} onBlur={() => void save({ customPipUrl: draft.customPipUrl })} placeholder=\"https://pypi.example.com/simple\" />}\n </div>\n <div style={row}>\n <span>{t('settings.gitProxy')}:</span>\n <input style={{ width: 260 }} disabled={!ready} value={draft.gitProxyUrl}\n onChange={event => edit({ gitProxyUrl: event.target.value })} onBlur={() => void save({ gitProxyUrl: draft.gitProxyUrl })} placeholder=\"127.0.0.1:7897\" />\n </div>\n <div style={row}>\n <span>{t('settings.pipProxy')}:</span>\n <input style={{ width: 260 }} disabled={!ready} value={draft.pipProxyUrl}\n onChange={event => edit({ pipProxyUrl: event.target.value })} onBlur={() => void save({ pipProxyUrl: draft.pipProxyUrl })} placeholder=\"127.0.0.1:7897\" />\n </div>\n </div>\n })()}\n <div style={row}>\n <span>{t('settings.workspace')}:</span>\n <select value={workspaceId} onChange={event => { const next = event.target.value; setWorkspaceId(next); try { localStorage.setItem('evalGuard.workspaceId', next) } catch { /* storage is optional */ } loadManual(next, taskId); loadLatestJob(next, taskId) }}>\n <option value=\"\">{t('settings.pickWorkspace')}</option>\n {workspaces.map(workspace => <option key={workspace.id} value={workspace.id}>{workspace.label}</option>)}\n </select>\n <button style={primary} disabled={workspaceId === '' || taskId === '' || job?.status === 'running'} onClick={() => void install()}>{t('settings.check')}</button>\n <button style={button} disabled={workspaceId === '' || taskId === '' || job?.status === 'running'} onClick={() => void evaluate()}>{t('settings.evaluate')}</button>\n </div>\n <p style={note}>{t('settings.evalHint')}</p>\n {workspaces.length === 0 && <p style={note}>{t('settings.noWorkspaces')}</p>}\n {check !== null && !check.empty && <p style={{ ...note, color: '#d99' }}>{t('settings.nonEmpty')} ({check.entries.slice(0, 6).join(', ')})</p>}\n {notice !== '' && <p style={{ ...note, color: '#7c7' }}>{notice}</p>}\n {error !== '' && <p style={{ ...note, color: '#d77' }}>{error}</p>}\n {jobNotice !== '' && <p style={{ ...note, color: '#7c7' }}>{jobNotice}</p>}\n {job !== null && <div style={{ ...box, borderColor: job.status === 'failed' ? '#a55' : job.status === 'succeeded' ? '#4a7' : '#3a6' }}>\n <div style={row}><strong>{job.kind === 'install' ? t('settings.installJob') : t('settings.evalJob')}</strong><span>{job.status}</span>\n {job.status === 'running' && <button style={danger} onClick={() => void cancelJob()}>{t('settings.cancel')}</button>}\n {job.kind === 'install' && job.status === 'succeeded' && job.prompt !== undefined && workspaceId !== '' && <button style={primary} onClick={() => evalBridge()?.startSession(workspaceId, job.prompt!)}>{t('settings.startSession')}</button>}</div>\n {job.error !== undefined && <p style={{ ...note, color: '#d77' }}>{job.error}</p>}\n <pre style={{ ...textarea, maxHeight: 260, overflow: 'auto' }}>{job.log || t('settings.waiting')}</pre>\n {job.result !== undefined && <pre style={{ ...textarea, maxHeight: 260, overflow: 'auto' }}>{JSON.stringify(job.result, undefined, 2)}</pre>}\n </div>}\n </section>\n\n <section style={box}>\n <div style={row}>\n <label><input type=\"checkbox\" checked={draft.timeLimitEnabled} disabled={!ready} onChange={event => void save({ timeLimitEnabled: event.target.checked })} /> {t('settings.timeLimit')}</label>\n <input type=\"number\" min={1} max={1440} value={draft.timeLimitMinutes} disabled={!ready}\n style={{ width: 90 }} onChange={event => edit({ timeLimitMinutes: Number(event.target.value) })}\n onBlur={() => void save({ timeLimitMinutes: draft.timeLimitMinutes })} />\n <span style={note}>{t('settings.minutes')}</span>\n </div>\n <p style={note}>{t('settings.timeLimitHint')}</p>\n </section>\n\n <section style={box}>\n <strong>{t('settings.manual')}</strong>\n <p style={note}>{t('settings.manualHint')}</p>\n <div style={row}><span>{t('settings.source')}:</span><code style={{ wordBreak: 'break-all' }}>{manual?.source ?? '—'}</code>\n {manual !== null && <button style={button} onClick={() => reveal(manual.source)}>{t('settings.reveal')}</button>}</div>\n <div style={row}><span>{t('settings.target')}:</span><code style={{ wordBreak: 'break-all' }}>{check?.path ?? '—'}</code>\n {check?.path !== undefined && check.path !== '' && <button style={button} onClick={() => reveal(check.path)}>{t('settings.reveal')}</button>}</div>\n <div style={row}><button style={button} disabled={prompt === ''} onClick={() => void copy('prompt', prompt)}>{copied === 'prompt' ? t('settings.copied') : t('settings.copy')}</button></div>\n <textarea style={{ ...textarea, minHeight: 160 }} readOnly value={prompt} placeholder={t('settings.prompt')} />\n </section>\n\n <section style={box}>\n <strong>{t('settings.recent')}</strong>\n {events.length === 0 && <p style={note}>{t('settings.none')}</p>}\n {events.map(event => <div key={event.seq} style={{ ...note, borderTop: '1px solid #333', paddingTop: 4 }}>\n <strong>[{event.kind}]</strong> {event.tool !== undefined ? event.tool + ' · ' : ''}{event.detail}\n </div>)}\n </section>\n </div>\n}\n","/**\n * Frame-wide warning toasts fed by the host event route.\n * @module dsh-eval-guard/client/Toast\n */\nimport { useEffect, useState, type ReactElement } from 'react'\nimport { EVENTS_ROUTE, type GuardEvent } from '../shared.ts'\n\n/** One toast with a dismiss deadline. */\ninterface Shown { event: GuardEvent; until: number }\n\n/** Poll the host event feed and show new warnings. */\nexport function GuardToast({ t }: { t: (key: string) => string }): ReactElement | null {\n const [shown, setShown] = useState<Shown[]>([])\n useEffect(() => {\n let since = 0\n let alive = true\n const poll = (): void => {\n fetch(EVENTS_ROUTE + '?since=' + String(since)).then(async response => await response.json() as { events: GuardEvent[] }).then(data => {\n if (!alive || data.events.length === 0) return\n since = data.events[data.events.length - 1]!.seq\n const warnings = data.events.filter(event => event.kind !== 'notice')\n if (warnings.length === 0) return\n const now = Date.now()\n setShown(current => [...warnings.map(event => ({ event, until: now + 8000 })), ...current].slice(0, 5))\n }).catch(() => undefined)\n }\n const timer = setInterval(() => {\n poll()\n const now = Date.now()\n setShown(current => current.filter(item => item.until > now))\n }, 1500)\n poll()\n return () => { alive = false; clearInterval(timer) }\n }, [])\n if (shown.length === 0) return null\n return <div style={{ position: 'fixed', right: 18, bottom: 18, zIndex: 9999, display: 'flex', flexDirection: 'column', gap: 8, maxWidth: 420 }}>\n {shown.map(item => <div key={item.event.seq} style={{\n background: '#3a2a12', color: '#ffdca8', border: '1px solid #8a6a2a', borderRadius: 8,\n padding: '10px 12px', fontSize: 12, lineHeight: 1.5, boxShadow: '0 6px 24px rgba(0,0,0,.45)',\n }}>\n <strong>{t('settings.warningTitle')}</strong>\n <div>{item.event.detail}</div>\n </div>)}\n </div>\n}\n","/** Locale namespace and dictionaries for the browser half. */\nexport const NS = 'evalGuard'\n\nexport const zh = {\n 'settings.nav': '评测守护',\n 'settings.title': '评测守护',\n 'settings.enabled': '启用评测守护',\n 'settings.enabledHint': '启用后,所有用户主对话只能读写自己的工作区,禁止联网、子代理与跨 agent 通信,并按任务时限强制终止。默认关闭。',\n 'settings.runningWarning': '当前有正在运行的对话。启用评测守护会立即约束它们,是否强行开启?',\n 'settings.runningCancel': '放弃',\n 'settings.runningForce': '强行开启',\n 'settings.timeLimit': '开启最长时长',\n 'settings.timeLimitHint': '从每条用户消息发送时开始计时;到点只终止当前轮次,并递归清理子代理与后台任务。',\n 'settings.minutes': '分钟',\n 'settings.forbidden': '额外禁止路径',\n 'settings.forbiddenHint': '每行一个绝对路径;# 开头为注释;! 开头表示在禁止范围内放开该子路径;按行顺序生效。默认空。',\n 'settings.blacklist': '工具黑名单',\n 'settings.blacklistHint': '每行一个工具名;默认内容按当前已安装工具生成,不存在的工具会被忽略。',\n 'settings.reset': '恢复默认黑名单',\n 'settings.editingDefault': '编辑后将以自定义黑名单保存。',\n 'settings.task': '安装 / 评测任务',\n 'settings.taskHint': '选择任务和工作区;安装与评测共用这组选择。安装会写入素材并准备环境,评测只对当前工作区运行一次。',\n 'settings.taskLabel': '任务',\n 'settings.workspace': '工作区',\n 'settings.pickWorkspace': '请选择工作区',\n 'settings.check': '安装任务',\n 'settings.nonEmpty': '工作区不是空的;未执行任何操作。',\n 'settings.manual': '手动通道',\n 'settings.manualHint': '手动复制素材:自己把素材目录内容复制到工作区根目录;手动填充提示词:复制下面的提示词。',\n 'settings.source': '素材路径',\n 'settings.target': '工作区路径',\n 'settings.copy': '复制',\n 'settings.copied': '已复制',\n 'settings.prompt': '初始提示词',\n 'settings.reveal': '在文件管理器中打开',\n 'settings.noWorkspaces': '没有可选的工作区。',\n 'settings.installOk': '任务素材已安装,提示词已填入新会话,请自行发送。',\n 'settings.taskDefaults': '已按任务默认值设置限时:{minutes} 分钟,限时开关 {state}。你可以随后手动修改。',\n 'settings.on': '打开',\n 'settings.off': '关闭',\n 'settings.evaluate': '评测当前工作区',\n 'settings.evalJob': '评测任务',\n 'settings.installJob': '安装任务',\n 'settings.cloneSource': '仓库来源',\n 'settings.pipIndex': 'pip 镜像',\n 'settings.custom': '自定义',\n 'settings.cancel': '取消',\n 'settings.waiting': '正在准备…',\n 'settings.evalHint': '只评测单个工作区,不做排名。评测任务与安装共用上面的工作区和任务选择。',\n 'settings.startSession': '填入新会话',\n 'settings.gitProxy': 'Git 代理',\n 'settings.pipProxy': 'pip 代理',\n 'settings.loading': '加载中…',\n 'settings.recent': '最近事件',\n 'settings.none': '暂无。',\n 'settings.warningTitle': '评测守护警告',\n 'settings.close': '关闭',\n} as const\n\nexport type Key = keyof typeof zh\n\nexport const en: Record<Key, string> = {\n 'settings.nav': 'Eval Guard',\n 'settings.title': 'Eval Guard',\n 'settings.enabled': 'Enable evaluation guard',\n 'settings.enabledHint': 'When on, every user main conversation may only read/write its own workspace, with network, subagents and cross-agent channels blocked, and a wall-clock limit. Off by default.',\n 'settings.runningWarning': 'Conversations are running right now. Enabling the guard will constrain them immediately. Force enable?',\n 'settings.runningCancel': 'Cancel',\n 'settings.runningForce': 'Force enable',\n 'settings.timeLimit': 'Enable time limit',\n 'settings.timeLimitHint': 'The clock starts at each user message; at the deadline only the current turn is cancelled, and subagents/jobs are cleaned up recursively.',\n 'settings.minutes': 'minutes',\n 'settings.forbidden': 'Extra forbidden paths',\n 'settings.forbiddenHint': 'One absolute path per line; # comments; ! re-allows a subpath; later lines win. Empty by default.',\n 'settings.blacklist': 'Tool blacklist',\n 'settings.blacklistHint': 'One tool name per line; the default is generated from the tools installed now and missing tools are ignored.',\n 'settings.reset': 'Reset default blacklist',\n 'settings.editingDefault': 'Editing switches this to a custom blacklist.',\n 'settings.task': 'Install / evaluate task',\n 'settings.taskHint': 'Pick a task and workspace; install and evaluation share this selection. Install writes the task and prepares the environment; evaluation runs once on the current workspace.',\n 'settings.taskLabel': 'Task',\n 'settings.workspace': 'Workspace',\n 'settings.pickWorkspace': 'Pick a workspace',\n 'settings.check': 'Install task',\n 'settings.nonEmpty': 'The workspace is not empty; nothing was changed.',\n 'settings.manual': 'Manual channel',\n 'settings.manualHint': 'Manual material copy: copy the source folder contents into the workspace root yourself. Manual prompt: copy the text below.',\n 'settings.source': 'Material path',\n 'settings.target': 'Workspace path',\n 'settings.copy': 'Copy',\n 'settings.copied': 'Copied',\n 'settings.prompt': 'Initial prompt',\n 'settings.reveal': 'Open in file manager',\n 'settings.noWorkspaces': 'No workspace is available.',\n 'settings.installOk': 'Task installed and the prompt was seeded into a new conversation; send it yourself.',\n 'settings.taskDefaults': 'Applied task defaults: {minutes} minutes, time limit {state}. You can change them afterwards.',\n 'settings.on': 'on',\n 'settings.off': 'off',\n 'settings.evaluate': 'Evaluate current workspace',\n 'settings.evalJob': 'Evaluation job',\n 'settings.installJob': 'Install job',\n 'settings.cloneSource': 'Clone source',\n 'settings.pipIndex': 'pip index',\n 'settings.custom': 'Custom',\n 'settings.cancel': 'Cancel',\n 'settings.waiting': 'Preparing…',\n 'settings.evalHint': 'Evaluates one workspace only; no ranking. Uses the same workspace/task selection as install.',\n 'settings.startSession': 'Open in new conversation',\n 'settings.gitProxy': 'Git proxy',\n 'settings.pipProxy': 'pip proxy',\n 'settings.loading': 'Loading…',\n 'settings.recent': 'Recent events',\n 'settings.none': 'None.',\n 'settings.warningTitle': 'Eval Guard warning',\n 'settings.close': 'Close',\n}\n","/**\n * Evaluation guard, browser half: the Settings section, the warning toast, and\n * the shell bridge used to seed a new conversation with the task prompt.\n * @module dsh-eval-guard/client\n */\nimport type { Context } from '@deepseek-ai/cordis'\nimport { SETTINGS_NS } from '../shared.ts'\nimport { EvalGuardSettings } from './Settings.tsx'\nimport { GuardToast } from './Toast.tsx'\nimport { configureEvalBridge } from './bridge.ts'\nimport { en, NS, zh, type Key } from './locales.ts'\n\ndeclare module '@deepseek-ai/dsh-client-ui-slots' {\n interface LocaleNamespaceMap {\n evalGuard: Key\n }\n}\n\nexport const inject = ['slots', 'locale', 'configForms', 'uiWorkspace']\n\nexport function apply(ctx: Context): void {\n ctx.effect(() => ctx.locale.register(NS, { zh, en }))\n configureEvalBridge({\n startSession: (workspaceId, prompt) => {\n ctx.uiWorkspace.startSession(workspaceId as Parameters<typeof ctx.uiWorkspace.startSession>[0], { prompt })\n },\n workspaces: () => {\n const service = (ctx as unknown as { get(key: string): unknown }).get('workspaces') as\n { list?: { getSnapshot(): { items?: readonly Record<string, unknown>[] } } } | undefined\n const items = service?.list?.getSnapshot().items ?? []\n return items.map((item, index) => ({\n id: typeof item['workspaceId'] === 'string' ? item['workspaceId'] : String(item['id'] ?? index),\n label: typeof item['title'] === 'string' && item['title'] !== ''\n ? item['title']\n : String(item['path'] ?? item['workspaceId'] ?? ('workspace ' + String(index + 1))),\n }))\n },\n })\n ctx.effect(() => () => { configureEvalBridge(undefined) })\n const t = ctx.locale.bind(NS)\n const form = ctx.configForms.get(SETTINGS_NS) as {\n getSnapshot(): unknown\n subscribe(listener: () => void): () => void\n mutate(ops: never, revision?: number): unknown\n }\n const formFace = {\n getSnapshot: () => form.getSnapshot(),\n subscribe: (listener: () => void) => form.subscribe(listener),\n mutate: (ops: never, revision?: number) => form.mutate(ops, revision),\n }\n ctx.slots.inject('settings.section', () => ctx.slots.register({\n name: 'settings.section', id: SETTINGS_NS, order: 41,\n label: () => t('settings.nav'), locale: NS,\n inject: () => ({ form: formFace }),\n }, EvalGuardSettings))\n ctx.slots.inject('shell.overlay', () => ctx.slots.register({\n name: 'shell.overlay', id: SETTINGS_NS + '.toast', locale: NS,\n inject: () => ({ t }),\n }, GuardToast))\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["useSyncExternalStore","useState","useRef","useState"],"sources":["../../src/shared.ts","../../src/client/bridge.ts","../../src/client/Settings.tsx","../../src/client/Toast.tsx","../../src/client/locales.ts","../../src/client/index.ts"],"sourcesContent":["/**\n * Wire types shared by the host and browser halves. Keep this module import-free:\n * the client bundle includes it without pulling host code.\n * @module dsh-eval-guard/shared\n */\n\n/** Settings namespace; also the Loader row id in cordis.patch.yml. */\nexport const SETTINGS_NS = 'eval-guard'\n\n/** Route paths owned by this plugin. */\nexport const STATE_ROUTE = '/api/eval-guard/state'\nexport const CHECK_ROUTE = '/api/eval-guard/check'\nexport const INSTALL_ROUTE = '/api/eval-guard/install'\nexport const PROMPT_ROUTE = '/api/eval-guard/prompt'\nexport const EVENTS_ROUTE = '/api/eval-guard/events'\nexport const REVEAL_ROUTE = '/api/eval-guard/reveal'\nexport const MANUAL_ROUTE = '/api/eval-guard/manual'\nexport const JOBS_ROUTE = '/api/eval-guard/jobs'\nexport const JOB_ROUTE = '/api/eval-guard/job'\nexport const JOB_CANCEL_ROUTE = '/api/eval-guard/job/cancel'\nexport const EVAL_ROUTE = '/api/eval-guard/evaluate'\n\n/** Supported task ids. */\nexport const TANK_TASK = 'tank'\nexport const TANK_TASK_LABEL = '第 6 集 · 坦克大战'\nexport const WAREHOUSE_TASK = 'warehouse'\nexport const WAREHOUSE_TASK_LABEL = '第 5 集 · 仓储调度'\nexport const LAND_TASK = 'land'\nexport const LAND_TASK_LABEL = '第 1 集 · 圈地'\nexport const BOMBERMAN_TASK = 'bomberman'\nexport const BOMBERMAN_TASK_LABEL = '第 2 集 · 炸弹人'\nexport const CTF_TASK = 'ctf'\nexport const CTF_TASK_LABEL = '第 3 集 · 夺旗'\nexport const COMMIT0_TASK = 'commit0'\nexport const COMMIT0_TASK_LABEL = 'Commit0 · 单库实现'\nexport const SWE_BENCH_PRO_TASK = 'swe-bench-pro'\nexport const SWE_BENCH_PRO_TASK_LABEL = 'SWE-Bench Pro · 单任务'\nexport const FEATUREBENCH_TASK = 'featurebench'\nexport const FEATUREBENCH_TASK_LABEL = 'FeatureBench · 单 feature'\nexport const NEURAL_CPP_TASK = 'neural-cpp'\nexport const NEURAL_CPP_TASK_LABEL = 'Neural-CPP · 纯 C++ 张量后端'\n\n/** One validated clone remote for a task. */\nexport interface TaskRemote {\n id: string\n label: string\n url: string\n}\n\n/** Common pip indexes offered by the settings page. */\nexport const PIP_MIRRORS: readonly { id: string; label: string; url: string }[] = [\n { id: 'pypi', label: 'PyPI', url: 'https://pypi.org/simple' },\n { id: 'tsinghua', label: '清华 TUNA', url: 'https://pypi.tuna.tsinghua.edu.cn/simple' },\n { id: 'aliyun', label: '阿里云', url: 'https://mirrors.aliyun.com/pypi/simple' },\n { id: 'tencent', label: '腾讯云', url: 'https://mirrors.cloud.tencent.com/pypi/simple' },\n { id: 'bfsu', label: '北外', url: 'https://mirrors.bfsu.edu.cn/pypi/web/simple' },\n { id: 'sjtu', label: '上海交大', url: 'https://mirror.sjtu.edu.cn/pypi/web/simple' },\n]\n\n/** One task offered by the installer. */\nexport interface TaskInfo {\n id: string\n label: string\n description: string\n /** Default wall-clock limit applied when the user selects this task. */\n timeLimitMinutes: number\n /** Default time-limit switch applied when the user selects this task. */\n timeLimitEnabled: boolean\n /** Whether installation needs a host-side clone / venv setup. */\n needsSetup: boolean\n /** Canonical upstream repository; used to build mirror URLs. */\n repoUrl?: string\n /** Clone remotes verified to contain the exact pinned commit. */\n remotes?: TaskRemote[]\n}\n\nexport type JobKind = 'install' | 'eval'\nexport type JobStatus = 'queued' | 'running' | 'succeeded' | 'failed' | 'cancelled' | 'interrupted'\n\n/** Summary of one background setup or evaluation job. */\nexport interface JobInfo {\n id: string\n kind: JobKind\n task: string\n workspaceId: string\n status: JobStatus\n createdAt: number\n startedAt: number | null\n endedAt: number | null\n updatedAt: number\n error?: string\n}\n\n/** Full job state, including a bounded log and optional result. */\nexport interface JobDetail extends JobInfo {\n log: string\n prompt?: string\n runId?: string\n result?: unknown\n}\n\n/** A live conversation the enable-time warning has to mention. */\nexport interface RunningSession {\n sessionId: string\n title: string\n cwd: string\n running: boolean\n jobs: number\n}\n\n/** One warning surfaced to the browser. */\nexport interface GuardEvent {\n seq: number\n at: number\n sessionId?: string\n runId?: string\n kind: 'tool-blocked' | 'path-denied' | 'process-denied' | 'wait-blocked' | 'timeout' | 'notice'\n tool?: string\n detail: string\n}\n\n/** Host answer for the enable pre-check. */\nexport interface GuardState {\n enabled: boolean\n running: RunningSession[]\n tasks: TaskInfo[]\n defaultBlacklist: string\n generatedDefault: boolean\n workspaceRoot: string\n runsRoot: string\n pipMirrors?: { id: string; label: string; url: string }[]\n}\n\n/** Result of checking one workspace before install. */\nexport interface CheckResult {\n ok: boolean\n workspaceId: string\n path: string\n empty: boolean\n entries: string[]\n error?: string\n}\n\n/** Result of installing the task pack. */\nexport interface InstallResult {\n ok: boolean\n error?: string\n runId?: string\n workspaceId?: string\n workspacePath?: string\n prompt?: string\n}\n\n/** Manual-channel material locations. */\nexport interface ManualPaths {\n source: string\n prompt: string\n}\n\n/** Usage record written next to one run. */\nexport interface RunUsage {\n inputTokens: number\n outputTokens: number\n cacheReadTokens: number\n cacheWriteTokens: number\n reasoningTokens: number\n toolCalls: number\n turns: number\n steps: number\n wallTimeMs: number\n startedAt: number | null\n updatedAt: number\n}\n\n/** Metadata for one guarded task run. */\nexport interface RunRecord {\n runId: string\n task: string\n workspaceId: string\n workspacePath: string\n sessionId: string | null\n createdAt: number\n startedAt: number | null\n endedAt: number | null\n status: 'prepared' | 'active' | 'timeout' | 'ended'\n prompt: string\n timeLimitMinutes: number\n provider?: string\n model?: string\n title?: string\n}\n","/** Shell capabilities published to the Settings panel. */\nexport interface EvalWorkspace { id: string; label: string }\nexport interface EvalBridge {\n startSession(workspaceId: string, prompt: string): void\n workspaces(): readonly EvalWorkspace[]\n}\nlet current: EvalBridge | undefined\nexport function configureEvalBridge(next: EvalBridge | undefined): void { current = next }\nexport function evalBridge(): EvalBridge | undefined { return current }\n","/**\n * Settings panel for the evaluation guard.\n * @module dsh-eval-guard/client/Settings\n */\nimport { useEffect, useRef, useState, useSyncExternalStore, type CSSProperties, type ReactElement } from 'react'\nimport {\n CHECK_ROUTE, EVENTS_ROUTE, INSTALL_ROUTE, MANUAL_ROUTE, REVEAL_ROUTE, STATE_ROUTE,\n JOBS_ROUTE, JOB_ROUTE, JOB_CANCEL_ROUTE, EVAL_ROUTE,\n type CheckResult, type GuardEvent, type GuardState, type InstallResult, type ManualPaths, type JobDetail, type JobInfo,\n PIP_MIRRORS,\n} from '../shared.ts'\nimport { evalBridge } from './bridge.ts'\n\ntype Snapshot = {\n status: 'loading' | 'ready' | 'unavailable'\n value?: Record<string, unknown>\n revision?: number\n writable: boolean\n}\ntype Form = {\n getSnapshot: () => Snapshot\n subscribe: (listener: () => void) => () => void\n mutate: (ops: readonly { op: 'set'; path: string[]; value: unknown }[], revision?: number) => Promise<boolean>\n}\ntype Props = { form: Form; t: (key: string) => string }\n\ninterface Draft {\n enabled: boolean\n timeLimitEnabled: boolean\n timeLimitMinutes: number\n forbiddenPaths: string\n toolBlacklistUseDefault: boolean\n toolBlacklist: string\n cloneSource: string\n customCloneUrl: string\n pipIndex: string\n customPipUrl: string\n gitProxyUrl: string\n pipProxyUrl: string\n}\n\nconst EMPTY: Draft = {\n enabled: false,\n timeLimitEnabled: true,\n timeLimitMinutes: 90,\n forbiddenPaths: '',\n toolBlacklistUseDefault: true,\n toolBlacklist: '',\n cloneSource: 'github',\n customCloneUrl: '',\n pipIndex: 'pypi',\n customPipUrl: '',\n gitProxyUrl: '',\n pipProxyUrl: '',\n}\n\nconst box: CSSProperties = { border: '1px solid var(--vscode-panel-border, #3c3c3c)', borderRadius: 8, padding: 14, marginBottom: 14 }\nconst row: CSSProperties = { display: 'flex', gap: 10, alignItems: 'center', flexWrap: 'wrap', marginBottom: 8 }\nconst note: CSSProperties = { opacity: 0.72, fontSize: 12, lineHeight: 1.5, margin: '6px 0' }\nconst textarea: CSSProperties = { width: '100%', minHeight: 110, fontFamily: 'monospace', fontSize: 12, padding: 8, boxSizing: 'border-box' }\nconst button: CSSProperties = { padding: '5px 12px', borderRadius: 6, cursor: 'pointer' }\nconst primary: CSSProperties = { ...button, background: '#2f6fd0', color: '#fff', border: 'none' }\nconst danger: CSSProperties = { ...button, background: '#a33', color: '#fff', border: 'none' }\n\nasync function readJson<T>(response: Response): Promise<T> { return await response.json() as T }\n\nfunction normalize(value: Record<string, unknown> | undefined): Draft {\n return {\n enabled: value?.enabled === true,\n timeLimitEnabled: value?.timeLimitEnabled !== false,\n timeLimitMinutes: typeof value?.timeLimitMinutes === 'number' ? value.timeLimitMinutes : 90,\n forbiddenPaths: typeof value?.forbiddenPaths === 'string' ? value.forbiddenPaths : '',\n toolBlacklistUseDefault: value?.toolBlacklistUseDefault !== false,\n toolBlacklist: typeof value?.toolBlacklist === 'string' ? value.toolBlacklist : '',\n cloneSource: typeof value?.cloneSource === 'string' && value.cloneSource !== '' ? value.cloneSource : 'github',\n customCloneUrl: typeof value?.customCloneUrl === 'string' ? value.customCloneUrl : '',\n pipIndex: typeof value?.pipIndex === 'string' && value.pipIndex !== '' ? value.pipIndex : 'pypi',\n customPipUrl: typeof value?.customPipUrl === 'string' ? value.customPipUrl : '',\n gitProxyUrl: typeof value?.gitProxyUrl === 'string' ? value.gitProxyUrl : '',\n pipProxyUrl: typeof value?.pipProxyUrl === 'string' ? value.pipProxyUrl : '',\n }\n}\n\n/** The settings card. */\nexport function EvalGuardSettings({ form, t }: Props): ReactElement {\n const snapshot = useSyncExternalStore(form.subscribe, form.getSnapshot, form.getSnapshot)\n const [draft, setDraft] = useState<Draft>(EMPTY)\n const [dirty, setDirty] = useState(false)\n const [state, setState] = useState<GuardState | null>(null)\n const [events, setEvents] = useState<GuardEvent[]>([])\n const [pendingEnable, setPendingEnable] = useState(false)\n const [notice, setNotice] = useState('')\n const [error, setError] = useState('')\n const [workspaceId, setWorkspaceId] = useState(() => typeof localStorage === 'undefined' ? '' : localStorage.getItem('evalGuard.workspaceId') ?? '')\n const [taskId, setTaskId] = useState(() => typeof localStorage === 'undefined' ? '' : localStorage.getItem('evalGuard.taskId') ?? '')\n const [check, setCheck] = useState<CheckResult | null>(null)\n const [manual, setManual] = useState<ManualPaths | null>(null)\n const [prompt, setPrompt] = useState('')\n const [copied, setCopied] = useState('')\n const workspaces = evalBridge()?.workspaces() ?? []\n const [job, setJob] = useState<JobDetail | null>(null)\n const [jobNotice, setJobNotice] = useState('')\n const autoOpenJob = useRef('')\n\n const pollJob = (id: string): void => {\n fetch(JOB_ROUTE + '?id=' + encodeURIComponent(id)).then(readJson<JobDetail>).then(setJob).catch(() => undefined)\n }\n const loadLatestJob = (workspace: string, task: string): void => {\n if (workspace === '' || task === '') { setJob(null); return }\n fetch(JOBS_ROUTE + '?workspaceId=' + encodeURIComponent(workspace) + '&task=' + encodeURIComponent(task))\n .then(readJson<JobInfo[]>).then(items => {\n const latest = items[0]\n if (latest !== undefined) pollJob(latest.id)\n else setJob(null)\n }).catch(() => undefined)\n }\n useEffect(() => {\n if (job === null || (job.status !== 'running' && job.status !== 'queued')) return\n const timer = setInterval(() => { pollJob(job.id) }, 800)\n return () => clearInterval(timer)\n }, [job])\n useEffect(() => { if (job?.status === 'succeeded' && job.kind === 'install' && job.prompt !== undefined) {\n setPrompt(job.prompt); setJobNotice(t('settings.installOk')); loadState()\n if (autoOpenJob.current === job.id) {\n autoOpenJob.current = ''\n evalBridge()?.startSession(job.workspaceId, job.prompt)\n }\n } }, [job])\n useEffect(() => { loadLatestJob(workspaceId, taskId) }, [workspaceId, taskId])\n\n useEffect(() => {\n if (snapshot.status !== 'ready' || snapshot.value === undefined || dirty) return\n setDraft(normalize(snapshot.value))\n }, [snapshot, dirty])\n\n const loadState = (): void => {\n fetch(STATE_ROUTE).then(readJson<GuardState>).then(setState).catch(() => setState(null))\n }\n useEffect(() => {\n loadState()\n let since = 0\n const timer = setInterval(() => {\n fetch(EVENTS_ROUTE + '?since=' + String(since)).then(readJson<{ events: GuardEvent[] }>).then(data => {\n if (data.events.length === 0) return\n since = data.events[data.events.length - 1]!.seq\n setEvents(current => [...data.events, ...current].slice(0, 12))\n }).catch(() => undefined)\n }, 2000)\n return () => clearInterval(timer)\n }, [])\n\n useEffect(() => {\n if (state !== null && state.tasks.length > 0 && (taskId === '' || !state.tasks.some(task => task.id === taskId))) setTaskId(state.tasks[0]!.id)\n }, [state, taskId])\n\n const ready = snapshot.status === 'ready' && snapshot.writable\n const save = async (patch: Partial<Draft>): Promise<void> => {\n if (!ready || snapshot.revision === undefined) return\n const next = { ...draft, ...patch }\n const ops: { op: 'set'; path: string[]; value: unknown }[] = []\n for (const key of Object.keys(patch) as (keyof Draft)[]) ops.push({ op: 'set', path: [key], value: next[key] })\n try {\n const accepted = await form.mutate(ops, snapshot.revision)\n if (!accepted) { setError('保存冲突,请刷新后重试。'); return }\n setDraft(next)\n setDirty(false)\n setError('')\n loadState()\n } catch (reason: unknown) {\n setError(reason instanceof Error ? reason.message : String(reason))\n }\n }\n const edit = (patch: Partial<Draft>): void => {\n setDraft(current => ({ ...current, ...patch }))\n setDirty(true)\n }\n\n const selectTask = (next: string): void => {\n setTaskId(next)\n try { localStorage.setItem('evalGuard.taskId', next) } catch { /* storage is optional */ }\n setCheck(null); setManual(null); setPrompt(''); setJob(null); setJobNotice('')\n if (workspaceId !== '') loadManual(workspaceId, next)\n const task = state?.tasks.find(item => item.id === next)\n if (task === undefined) return\n const remotes = task.remotes ?? []\n const cloneSource = draft.cloneSource === 'custom' || remotes.some(remote => remote.id === draft.cloneSource)\n ? draft.cloneSource : (remotes[0]?.id ?? 'github')\n setDraft(current => ({ ...current, timeLimitMinutes: task.timeLimitMinutes, timeLimitEnabled: task.timeLimitEnabled, cloneSource }))\n setNotice(t('settings.taskDefaults').replace('{minutes}', String(task.timeLimitMinutes)).replace('{state}', task.timeLimitEnabled ? t('settings.on') : t('settings.off')))\n void save({ timeLimitMinutes: task.timeLimitMinutes, timeLimitEnabled: task.timeLimitEnabled, cloneSource })\n }\n\n const toggleEnabled = (next: boolean): void => {\n if (!next) { void save({ enabled: false }); return }\n fetch(STATE_ROUTE).then(readJson<GuardState>).then(latest => {\n setState(latest)\n if (latest.running.length > 0) setPendingEnable(true)\n else void save({ enabled: true })\n }).catch(() => void save({ enabled: true }))\n }\n\n const forceEnable = (): void => {\n setPendingEnable(false)\n void save({ enabled: true })\n }\n\n const loadManual = (id: string, task: string): void => {\n if (id === '') { setCheck(null); setManual(null); setPrompt(''); return }\n fetch(CHECK_ROUTE + '?workspaceId=' + encodeURIComponent(id)).then(readJson<CheckResult>).then(result => {\n setCheck(result)\n if (result.ok) {\n fetch(MANUAL_ROUTE + '?workspaceId=' + encodeURIComponent(id) + '&task=' + encodeURIComponent(task)).then(readJson<ManualPaths>).then(paths => {\n setManual(paths)\n setPrompt(paths.prompt)\n }).catch(() => undefined)\n }\n }).catch((reason: unknown) => setError(reason instanceof Error ? reason.message : String(reason)))\n }\n\n const install = async (): Promise<void> => {\n if (workspaceId === '' || taskId === '') return\n setError(''); setNotice(''); setJobNotice('')\n const checked = await fetch(CHECK_ROUTE + '?workspaceId=' + encodeURIComponent(workspaceId)).then(readJson<CheckResult>)\n setCheck(checked)\n if (!checked.ok || !checked.empty) { setError(checked.error ?? t('settings.nonEmpty')); return }\n const result = await fetch(INSTALL_ROUTE, {\n method: 'POST', headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ workspaceId, task: taskId, cloneSource: draft.cloneSource, customCloneUrl: draft.customCloneUrl,\n pipIndex: draft.pipIndex, customPipUrl: draft.customPipUrl, gitProxyUrl: draft.gitProxyUrl, pipProxyUrl: draft.pipProxyUrl }),\n }).then(readJson<{ ok: boolean; jobId?: string; error?: string }>)\n if (!result.ok || result.jobId === undefined) { autoOpenJob.current = ''; setError(result.error ?? '安装失败'); return }\n autoOpenJob.current = result.jobId\n pollJob(result.jobId)\n }\n\n const evaluate = async (): Promise<void> => {\n if (workspaceId === '' || taskId === '') return\n setError(''); setNotice(''); setJobNotice('')\n const result = await fetch(EVAL_ROUTE, {\n method: 'POST', headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ workspaceId, task: taskId }),\n }).then(readJson<{ ok: boolean; jobId?: string; error?: string }>)\n if (!result.ok || result.jobId === undefined) { setError(result.error ?? '评测启动失败'); return }\n pollJob(result.jobId)\n }\n\n const cancelJob = async (): Promise<void> => {\n if (job === null) return\n await fetch(JOB_CANCEL_ROUTE, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ id: job.id }) })\n pollJob(job.id)\n }\n\n const copy = async (label: string, text: string): Promise<void> => {\n try {\n await navigator.clipboard.writeText(text)\n setCopied(label)\n setTimeout(() => setCopied(''), 1500)\n } catch { setError('复制失败') }\n }\n const reveal = (target: string): void => {\n void fetch(REVEAL_ROUTE, {\n method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ path: target }),\n })\n }\n const blacklistText = draft.toolBlacklistUseDefault ? state?.defaultBlacklist ?? '' : draft.toolBlacklist\n\n if (snapshot.status === 'loading') return <div style={box}>{t('settings.loading')}</div>\n return <div>\n {pendingEnable && <div style={{ ...box, borderColor: '#caa23a' }}>\n <strong>{t('settings.warningTitle')}</strong>\n <p style={note}>{t('settings.runningWarning')}</p>\n <ul style={{ ...note, paddingLeft: 18 }}>{(state?.running ?? []).map(item =>\n <li key={item.sessionId}>{item.title} · {item.cwd}{item.jobs > 0 ? ' · jobs: ' + String(item.jobs) : ''}</li>)}</ul>\n <div style={row}>\n <button style={button} onClick={() => { setPendingEnable(false); loadState() }}>{t('settings.runningCancel')}</button>\n <button style={danger} onClick={forceEnable}>{t('settings.runningForce')}</button>\n </div>\n </div>}\n\n <section style={box}>\n <div style={row}>\n <label><input type=\"checkbox\" checked={draft.enabled} disabled={!ready} onChange={event => toggleEnabled(event.target.checked)} /> {t('settings.enabled')}</label>\n </div>\n <p style={note}>{t('settings.enabledHint')}</p>\n </section>\n\n <section style={box}>\n <strong>{t('settings.forbidden')}</strong>\n <p style={note}>{t('settings.forbiddenHint')}</p>\n <textarea style={textarea} value={draft.forbiddenPaths} disabled={!ready}\n onChange={event => edit({ forbiddenPaths: event.target.value })}\n onBlur={() => void save({ forbiddenPaths: draft.forbiddenPaths })} />\n </section>\n\n <section style={box}>\n <div style={row}>\n <strong>{t('settings.blacklist')}</strong>\n <button style={button} disabled={!ready} onClick={() => void save({ toolBlacklistUseDefault: true, toolBlacklist: '' })}>{t('settings.reset')}</button>\n </div>\n <p style={note}>{t('settings.blacklistHint')}</p>\n <textarea style={textarea} value={blacklistText} disabled={!ready}\n onChange={event => edit({ toolBlacklistUseDefault: false, toolBlacklist: event.target.value })}\n onBlur={() => void save({ toolBlacklistUseDefault: draft.toolBlacklistUseDefault, toolBlacklist: draft.toolBlacklist })} />\n {draft.toolBlacklistUseDefault && <p style={note}>{t('settings.editingDefault')}</p>}\n </section>\n\n <section style={box}>\n <strong>{t('settings.task')}</strong>\n <p style={note}>{t('settings.taskHint')}</p>\n <div style={row}>\n <span>{t('settings.taskLabel')}:</span>\n <select value={taskId} disabled={state === null || state.tasks.length === 0}\n onChange={event => selectTask(event.target.value)}>\n {(state?.tasks ?? []).map(task => <option key={task.id} value={task.id}>{task.label}</option>)}\n </select>\n </div>\n {state !== null && <p style={note}>{state.tasks.find(task => task.id === taskId)?.description ?? ''}</p>}\n {(() => {\n const selected = state?.tasks.find(item => item.id === taskId)\n if (selected?.needsSetup !== true) return null\n return <div>\n <div style={row}>\n <span>{t('settings.cloneSource')}:</span>\n <select value={draft.cloneSource} disabled={!ready} onChange={event => void save({ cloneSource: event.target.value })}>\n {(selected.remotes ?? []).map(remote => <option key={remote.id} value={remote.id}>{remote.label}</option>)}\n <option value=\"custom\">{t('settings.custom')}</option>\n </select>\n {draft.cloneSource === 'custom' && <input style={{ width: 260 }} disabled={!ready} value={draft.customCloneUrl}\n onChange={event => edit({ customCloneUrl: event.target.value })} onBlur={() => void save({ customCloneUrl: draft.customCloneUrl })} placeholder=\"https://git.example.com\" />}\n </div>\n <div style={row}>\n <span>{t('settings.pipIndex')}:</span>\n <select value={draft.pipIndex} disabled={!ready} onChange={event => void save({ pipIndex: event.target.value })}>\n {PIP_MIRRORS.map(mirror => <option key={mirror.id} value={mirror.id}>{mirror.label}</option>)}\n <option value=\"custom\">{t('settings.custom')}</option>\n </select>\n {draft.pipIndex === 'custom' && <input style={{ width: 260 }} disabled={!ready} value={draft.customPipUrl}\n onChange={event => edit({ customPipUrl: event.target.value })} onBlur={() => void save({ customPipUrl: draft.customPipUrl })} placeholder=\"https://pypi.example.com/simple\" />}\n </div>\n <div style={row}>\n <span>{t('settings.gitProxy')}:</span>\n <input style={{ width: 260 }} disabled={!ready} value={draft.gitProxyUrl}\n onChange={event => edit({ gitProxyUrl: event.target.value })} onBlur={() => void save({ gitProxyUrl: draft.gitProxyUrl })} placeholder=\"127.0.0.1:7897\" />\n </div>\n <div style={row}>\n <span>{t('settings.pipProxy')}:</span>\n <input style={{ width: 260 }} disabled={!ready} value={draft.pipProxyUrl}\n onChange={event => edit({ pipProxyUrl: event.target.value })} onBlur={() => void save({ pipProxyUrl: draft.pipProxyUrl })} placeholder=\"127.0.0.1:7897\" />\n </div>\n </div>\n })()}\n <div style={row}>\n <span>{t('settings.workspace')}:</span>\n <select value={workspaceId} onChange={event => { const next = event.target.value; setWorkspaceId(next); try { localStorage.setItem('evalGuard.workspaceId', next) } catch { /* storage is optional */ } loadManual(next, taskId); loadLatestJob(next, taskId) }}>\n <option value=\"\">{t('settings.pickWorkspace')}</option>\n {workspaces.map(workspace => <option key={workspace.id} value={workspace.id}>{workspace.label}</option>)}\n </select>\n <button style={primary} disabled={workspaceId === '' || taskId === '' || job?.status === 'running'} onClick={() => void install()}>{t('settings.check')}</button>\n <button style={button} disabled={workspaceId === '' || taskId === '' || job?.status === 'running'} onClick={() => void evaluate()}>{t('settings.evaluate')}</button>\n </div>\n <p style={note}>{t('settings.evalHint')}</p>\n {workspaces.length === 0 && <p style={note}>{t('settings.noWorkspaces')}</p>}\n {check !== null && !check.empty && <p style={{ ...note, color: '#d99' }}>{t('settings.nonEmpty')} ({check.entries.slice(0, 6).join(', ')})</p>}\n {notice !== '' && <p style={{ ...note, color: '#7c7' }}>{notice}</p>}\n {error !== '' && <p style={{ ...note, color: '#d77' }}>{error}</p>}\n {jobNotice !== '' && <p style={{ ...note, color: '#7c7' }}>{jobNotice}</p>}\n {job !== null && <div style={{ ...box, borderColor: job.status === 'failed' ? '#a55' : job.status === 'succeeded' ? '#4a7' : '#3a6' }}>\n <div style={row}><strong>{job.kind === 'install' ? t('settings.installJob') : t('settings.evalJob')}</strong><span>{job.status}</span>\n {job.status === 'running' && <button style={danger} onClick={() => void cancelJob()}>{t('settings.cancel')}</button>}\n {job.kind === 'install' && job.status === 'succeeded' && job.prompt !== undefined && workspaceId !== '' && <button style={primary} onClick={() => evalBridge()?.startSession(workspaceId, job.prompt!)}>{t('settings.startSession')}</button>}</div>\n {job.error !== undefined && <p style={{ ...note, color: '#d77' }}>{job.error}</p>}\n <pre style={{ ...textarea, maxHeight: 260, overflow: 'auto' }}>{job.log || t('settings.waiting')}</pre>\n {job.result !== undefined && <pre style={{ ...textarea, maxHeight: 260, overflow: 'auto' }}>{JSON.stringify(job.result, undefined, 2)}</pre>}\n </div>}\n </section>\n\n <section style={box}>\n <div style={row}>\n <label><input type=\"checkbox\" checked={draft.timeLimitEnabled} disabled={!ready} onChange={event => void save({ timeLimitEnabled: event.target.checked })} /> {t('settings.timeLimit')}</label>\n <input type=\"number\" min={1} max={1440} value={draft.timeLimitMinutes} disabled={!ready}\n style={{ width: 90 }} onChange={event => edit({ timeLimitMinutes: Number(event.target.value) })}\n onBlur={() => void save({ timeLimitMinutes: draft.timeLimitMinutes })} />\n <span style={note}>{t('settings.minutes')}</span>\n </div>\n <p style={note}>{t('settings.timeLimitHint')}</p>\n </section>\n\n <section style={box}>\n <strong>{t('settings.manual')}</strong>\n <p style={note}>{t('settings.manualHint')}</p>\n <div style={row}><span>{t('settings.source')}:</span><code style={{ wordBreak: 'break-all' }}>{manual?.source ?? '—'}</code>\n {manual !== null && <button style={button} onClick={() => reveal(manual.source)}>{t('settings.reveal')}</button>}</div>\n <div style={row}><span>{t('settings.target')}:</span><code style={{ wordBreak: 'break-all' }}>{check?.path ?? '—'}</code>\n {check?.path !== undefined && check.path !== '' && <button style={button} onClick={() => reveal(check.path)}>{t('settings.reveal')}</button>}</div>\n <div style={row}><button style={button} disabled={prompt === ''} onClick={() => void copy('prompt', prompt)}>{copied === 'prompt' ? t('settings.copied') : t('settings.copy')}</button></div>\n <textarea style={{ ...textarea, minHeight: 160 }} readOnly value={prompt} placeholder={t('settings.prompt')} />\n </section>\n\n <section style={box}>\n <strong>{t('settings.recent')}</strong>\n {events.length === 0 && <p style={note}>{t('settings.none')}</p>}\n {events.map(event => <div key={event.seq} style={{ ...note, borderTop: '1px solid #333', paddingTop: 4 }}>\n <strong>[{event.kind}]</strong> {event.tool !== undefined ? event.tool + ' · ' : ''}{event.detail}\n </div>)}\n </section>\n </div>\n}\n","/**\n * Frame-wide warning toasts fed by the host event route.\n * @module dsh-eval-guard/client/Toast\n */\nimport { useEffect, useState, type ReactElement } from 'react'\nimport { EVENTS_ROUTE, type GuardEvent } from '../shared.ts'\n\n/** One toast with a dismiss deadline. */\ninterface Shown { event: GuardEvent; until: number }\n\n/** Poll the host event feed and show new warnings. */\nexport function GuardToast({ t }: { t: (key: string) => string }): ReactElement | null {\n const [shown, setShown] = useState<Shown[]>([])\n useEffect(() => {\n let since = 0\n let alive = true\n const poll = (): void => {\n fetch(EVENTS_ROUTE + '?since=' + String(since)).then(async response => await response.json() as { events: GuardEvent[] }).then(data => {\n if (!alive || data.events.length === 0) return\n since = data.events[data.events.length - 1]!.seq\n const warnings = data.events.filter(event => event.kind !== 'notice')\n if (warnings.length === 0) return\n const now = Date.now()\n setShown(current => [...warnings.map(event => ({ event, until: now + 8000 })), ...current].slice(0, 5))\n }).catch(() => undefined)\n }\n const timer = setInterval(() => {\n poll()\n const now = Date.now()\n setShown(current => current.filter(item => item.until > now))\n }, 1500)\n poll()\n return () => { alive = false; clearInterval(timer) }\n }, [])\n if (shown.length === 0) return null\n return <div style={{ position: 'fixed', right: 18, bottom: 18, zIndex: 9999, display: 'flex', flexDirection: 'column', gap: 8, maxWidth: 420 }}>\n {shown.map(item => <div key={item.event.seq} style={{\n background: '#3a2a12', color: '#ffdca8', border: '1px solid #8a6a2a', borderRadius: 8,\n padding: '10px 12px', fontSize: 12, lineHeight: 1.5, boxShadow: '0 6px 24px rgba(0,0,0,.45)',\n }}>\n <strong>{t('settings.warningTitle')}</strong>\n <div>{item.event.detail}</div>\n </div>)}\n </div>\n}\n","/** Locale namespace and dictionaries for the browser half. */\nexport const NS = 'evalGuard'\n\nexport const zh = {\n 'settings.nav': '评测守护',\n 'settings.title': '评测守护',\n 'settings.enabled': '启用评测守护',\n 'settings.enabledHint': '启用后,所有用户主对话只能读写自己的工作区,禁止联网、子代理与跨 agent 通信,并按任务时限强制终止。默认关闭。',\n 'settings.runningWarning': '当前有正在运行的对话。启用评测守护会立即约束它们,是否强行开启?',\n 'settings.runningCancel': '放弃',\n 'settings.runningForce': '强行开启',\n 'settings.timeLimit': '开启最长时长',\n 'settings.timeLimitHint': '从每条用户消息发送时开始计时;到点只终止当前轮次,并递归清理子代理与后台任务。',\n 'settings.minutes': '分钟',\n 'settings.forbidden': '额外禁止路径',\n 'settings.forbiddenHint': '每行一个绝对路径;# 开头为注释;! 开头表示在禁止范围内放开该子路径;按行顺序生效。默认空。',\n 'settings.blacklist': '工具黑名单',\n 'settings.blacklistHint': '每行一个工具名;默认内容按当前已安装工具生成,不存在的工具会被忽略。',\n 'settings.reset': '恢复默认黑名单',\n 'settings.editingDefault': '编辑后将以自定义黑名单保存。',\n 'settings.task': '安装 / 评测任务',\n 'settings.taskHint': '选择任务和工作区;安装与评测共用这组选择。安装会写入素材并准备环境,评测只对当前工作区运行一次。',\n 'settings.taskLabel': '任务',\n 'settings.workspace': '工作区',\n 'settings.pickWorkspace': '请选择工作区',\n 'settings.check': '安装任务',\n 'settings.nonEmpty': '工作区不是空的;未执行任何操作。',\n 'settings.manual': '手动通道',\n 'settings.manualHint': '手动复制素材:自己把素材目录内容复制到工作区根目录;手动填充提示词:复制下面的提示词。',\n 'settings.source': '素材路径',\n 'settings.target': '工作区路径',\n 'settings.copy': '复制',\n 'settings.copied': '已复制',\n 'settings.prompt': '初始提示词',\n 'settings.reveal': '在文件管理器中打开',\n 'settings.noWorkspaces': '没有可选的工作区。',\n 'settings.installOk': '任务素材已安装,提示词已填入新会话,请自行发送。',\n 'settings.taskDefaults': '已按任务默认值设置限时:{minutes} 分钟,限时开关 {state}。你可以随后手动修改。',\n 'settings.on': '打开',\n 'settings.off': '关闭',\n 'settings.evaluate': '评测当前工作区',\n 'settings.evalJob': '评测任务',\n 'settings.installJob': '安装任务',\n 'settings.cloneSource': '仓库来源',\n 'settings.pipIndex': 'pip 镜像',\n 'settings.custom': '自定义',\n 'settings.cancel': '取消',\n 'settings.waiting': '正在准备…',\n 'settings.evalHint': '只评测单个工作区,不做排名。评测任务与安装共用上面的工作区和任务选择。',\n 'settings.startSession': '填入新会话',\n 'settings.gitProxy': 'Git 代理',\n 'settings.pipProxy': 'pip 代理',\n 'settings.loading': '加载中…',\n 'settings.recent': '最近事件',\n 'settings.none': '暂无。',\n 'settings.warningTitle': '评测守护警告',\n 'settings.close': '关闭',\n} as const\n\nexport type Key = keyof typeof zh\n\nexport const en: Record<Key, string> = {\n 'settings.nav': 'Eval Guard',\n 'settings.title': 'Eval Guard',\n 'settings.enabled': 'Enable evaluation guard',\n 'settings.enabledHint': 'When on, every user main conversation may only read/write its own workspace, with network, subagents and cross-agent channels blocked, and a wall-clock limit. Off by default.',\n 'settings.runningWarning': 'Conversations are running right now. Enabling the guard will constrain them immediately. Force enable?',\n 'settings.runningCancel': 'Cancel',\n 'settings.runningForce': 'Force enable',\n 'settings.timeLimit': 'Enable time limit',\n 'settings.timeLimitHint': 'The clock starts at each user message; at the deadline only the current turn is cancelled, and subagents/jobs are cleaned up recursively.',\n 'settings.minutes': 'minutes',\n 'settings.forbidden': 'Extra forbidden paths',\n 'settings.forbiddenHint': 'One absolute path per line; # comments; ! re-allows a subpath; later lines win. Empty by default.',\n 'settings.blacklist': 'Tool blacklist',\n 'settings.blacklistHint': 'One tool name per line; the default is generated from the tools installed now and missing tools are ignored.',\n 'settings.reset': 'Reset default blacklist',\n 'settings.editingDefault': 'Editing switches this to a custom blacklist.',\n 'settings.task': 'Install / evaluate task',\n 'settings.taskHint': 'Pick a task and workspace; install and evaluation share this selection. Install writes the task and prepares the environment; evaluation runs once on the current workspace.',\n 'settings.taskLabel': 'Task',\n 'settings.workspace': 'Workspace',\n 'settings.pickWorkspace': 'Pick a workspace',\n 'settings.check': 'Install task',\n 'settings.nonEmpty': 'The workspace is not empty; nothing was changed.',\n 'settings.manual': 'Manual channel',\n 'settings.manualHint': 'Manual material copy: copy the source folder contents into the workspace root yourself. Manual prompt: copy the text below.',\n 'settings.source': 'Material path',\n 'settings.target': 'Workspace path',\n 'settings.copy': 'Copy',\n 'settings.copied': 'Copied',\n 'settings.prompt': 'Initial prompt',\n 'settings.reveal': 'Open in file manager',\n 'settings.noWorkspaces': 'No workspace is available.',\n 'settings.installOk': 'Task installed and the prompt was seeded into a new conversation; send it yourself.',\n 'settings.taskDefaults': 'Applied task defaults: {minutes} minutes, time limit {state}. You can change them afterwards.',\n 'settings.on': 'on',\n 'settings.off': 'off',\n 'settings.evaluate': 'Evaluate current workspace',\n 'settings.evalJob': 'Evaluation job',\n 'settings.installJob': 'Install job',\n 'settings.cloneSource': 'Clone source',\n 'settings.pipIndex': 'pip index',\n 'settings.custom': 'Custom',\n 'settings.cancel': 'Cancel',\n 'settings.waiting': 'Preparing…',\n 'settings.evalHint': 'Evaluates one workspace only; no ranking. Uses the same workspace/task selection as install.',\n 'settings.startSession': 'Open in new conversation',\n 'settings.gitProxy': 'Git proxy',\n 'settings.pipProxy': 'pip proxy',\n 'settings.loading': 'Loading…',\n 'settings.recent': 'Recent events',\n 'settings.none': 'None.',\n 'settings.warningTitle': 'Eval Guard warning',\n 'settings.close': 'Close',\n}\n","/**\n * Evaluation guard, browser half: the Settings section, the warning toast, and\n * the shell bridge used to seed a new conversation with the task prompt.\n * @module dsh-eval-guard/client\n */\nimport type { Context } from '@deepseek-ai/cordis'\nimport { SETTINGS_NS } from '../shared.ts'\nimport { EvalGuardSettings } from './Settings.tsx'\nimport { GuardToast } from './Toast.tsx'\nimport { configureEvalBridge } from './bridge.ts'\nimport { en, NS, zh, type Key } from './locales.ts'\n\ndeclare module '@deepseek-ai/dsh-client-ui-slots' {\n interface LocaleNamespaceMap {\n evalGuard: Key\n }\n}\n\nexport const inject = ['slots', 'locale', 'configForms', 'uiWorkspace']\n\nexport function apply(ctx: Context): void {\n ctx.effect(() => ctx.locale.register(NS, { zh, en }))\n configureEvalBridge({\n startSession: (workspaceId, prompt) => {\n ctx.uiWorkspace.startSession(workspaceId as Parameters<typeof ctx.uiWorkspace.startSession>[0], { prompt })\n },\n workspaces: () => {\n const service = (ctx as unknown as { get(key: string): unknown }).get('workspaces') as\n { list?: { getSnapshot(): { items?: readonly Record<string, unknown>[] } } } | undefined\n const items = service?.list?.getSnapshot().items ?? []\n return items.map((item, index) => ({\n id: typeof item['workspaceId'] === 'string' ? item['workspaceId'] : String(item['id'] ?? index),\n label: typeof item['title'] === 'string' && item['title'] !== ''\n ? item['title']\n : String(item['path'] ?? item['workspaceId'] ?? ('workspace ' + String(index + 1))),\n }))\n },\n })\n ctx.effect(() => () => { configureEvalBridge(undefined) })\n const t = ctx.locale.bind(NS)\n const form = ctx.configForms.get(SETTINGS_NS) as {\n getSnapshot(): unknown\n subscribe(listener: () => void): () => void\n mutate(ops: never, revision?: number): unknown\n }\n const formFace = {\n getSnapshot: () => form.getSnapshot(),\n subscribe: (listener: () => void) => form.subscribe(listener),\n mutate: (ops: never, revision?: number) => form.mutate(ops, revision),\n }\n ctx.slots.inject('settings.section', () => ctx.slots.register({\n name: 'settings.section', id: SETTINGS_NS, order: 41,\n label: () => t('settings.nav'), locale: NS,\n inject: () => ({ form: formFace }),\n }, EvalGuardSettings))\n ctx.slots.inject('shell.overlay', () => ctx.slots.register({\n name: 'shell.overlay', id: SETTINGS_NS + '.toast', locale: NS,\n inject: () => ({ t }),\n }, GuardToast))\n}\n"],"mappings":"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"}
|
package/lib/index.js
CHANGED
|
@@ -74,6 +74,8 @@ const SWE_BENCH_PRO_TASK = "swe-bench-pro";
|
|
|
74
74
|
const SWE_BENCH_PRO_TASK_LABEL = "SWE-Bench Pro · 单任务";
|
|
75
75
|
const FEATUREBENCH_TASK = "featurebench";
|
|
76
76
|
const FEATUREBENCH_TASK_LABEL = "FeatureBench · 单 feature";
|
|
77
|
+
const NEURAL_CPP_TASK = "neural-cpp";
|
|
78
|
+
const NEURAL_CPP_TASK_LABEL = "Neural-CPP · 纯 C++ 张量后端";
|
|
77
79
|
/** Common pip indexes offered by the settings page. */
|
|
78
80
|
const PIP_MIRRORS = [
|
|
79
81
|
{
|
|
@@ -1671,6 +1673,14 @@ const TASKS = [
|
|
|
1671
1673
|
url: "https://gitcode.com/gh_mirrors/se/seaborn.git"
|
|
1672
1674
|
}
|
|
1673
1675
|
]
|
|
1676
|
+
},
|
|
1677
|
+
{
|
|
1678
|
+
id: NEURAL_CPP_TASK,
|
|
1679
|
+
label: NEURAL_CPP_TASK_LABEL,
|
|
1680
|
+
description: "从零实现纯 C++ 张量运算与反向传播后端;隐藏测试统计正确性与速度。",
|
|
1681
|
+
timeLimitMinutes: 1440,
|
|
1682
|
+
timeLimitEnabled: false,
|
|
1683
|
+
needsSetup: false
|
|
1674
1684
|
}
|
|
1675
1685
|
];
|
|
1676
1686
|
/** The tank task definition (original prompt; only halftime mechanics removed). */
|
|
@@ -1891,6 +1901,30 @@ const FEATUREBENCH_DEFINITION = {
|
|
|
1891
1901
|
].join("\n");
|
|
1892
1902
|
}
|
|
1893
1903
|
};
|
|
1904
|
+
/** Pure C++ tensor backend task. */
|
|
1905
|
+
const NEURAL_CPP_DEFINITION = {
|
|
1906
|
+
id: NEURAL_CPP_TASK,
|
|
1907
|
+
label: NEURAL_CPP_TASK_LABEL,
|
|
1908
|
+
description: TASKS[8].description,
|
|
1909
|
+
asset: path.join(packageRoot(), "assets", "neural-cpp", "workspace.zip"),
|
|
1910
|
+
timeLimitMinutes: 1440,
|
|
1911
|
+
timeLimitEnabled: false,
|
|
1912
|
+
needsSetup: false,
|
|
1913
|
+
prompt() {
|
|
1914
|
+
return [
|
|
1915
|
+
"这是一个纯 C++ 张量运算后端任务:从零实现 DType、Tensor、视图/切片、逐元素与矩阵运算、自动求导和线程池;不提供 Python 或 OpenCL 支持。",
|
|
1916
|
+
"",
|
|
1917
|
+
"当前目录有 workspace.zip。请先解压,进入 workspace 目录,阅读 TASK.md 和 include/nn/nn.hpp,按接口约定实现 src/ 下的静态库,并用 CMake 构建。",
|
|
1918
|
+
"",
|
|
1919
|
+
"要求:",
|
|
1920
|
+
"- 仅使用 Linux + GCC + C++17 标准库;不允许引入第三方依赖;",
|
|
1921
|
+
"- 开发/自测阶段线程数最多 4;评测阶段会使用全部逻辑 CPU;",
|
|
1922
|
+
"- 不得修改 include/nn/nn.hpp 的公开接口语义;不要伪造测试或结果;",
|
|
1923
|
+
"- 隐藏测试会独立编译,数据由固定种子在测试时生成;",
|
|
1924
|
+
"- 完成后用几句话总结实现了哪些部分和性能优化。"
|
|
1925
|
+
].join("\n");
|
|
1926
|
+
}
|
|
1927
|
+
};
|
|
1894
1928
|
/** All task definitions keyed by id. */
|
|
1895
1929
|
const TASK_DEFINITIONS = {
|
|
1896
1930
|
[TANK_TASK]: TANK_DEFINITION,
|
|
@@ -1900,7 +1934,8 @@ const TASK_DEFINITIONS = {
|
|
|
1900
1934
|
["ctf"]: CTF_DEFINITION,
|
|
1901
1935
|
[COMMIT0_TASK]: COMMIT0_DEFINITION,
|
|
1902
1936
|
[SWE_BENCH_PRO_TASK]: SWE_BENCH_PRO_DEFINITION,
|
|
1903
|
-
[FEATUREBENCH_TASK]: FEATUREBENCH_DEFINITION
|
|
1937
|
+
[FEATUREBENCH_TASK]: FEATUREBENCH_DEFINITION,
|
|
1938
|
+
[NEURAL_CPP_TASK]: NEURAL_CPP_DEFINITION
|
|
1904
1939
|
};
|
|
1905
1940
|
var TaskService = class {
|
|
1906
1941
|
guard;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-eval-guard",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Evaluation guard for DSH: workspace-only filesystem, no network/subagents, wall-clock limits, and task installation for the meow-ai-arena tank task.",
|
|
6
6
|
"license": "MIT",
|