DeepSeek Harness 的编译器插件:一个 Monaco 编辑器固定面板 + Judge0 代码执行,以及一组 AI 可调用工具(read_code / execute_code),并附带行锚点便签与学习统计。
作者:MM3036 · License:MIT · npm 包名:@mm3036/dsh-plugin-compiler
- 编译器面板:
@monaco-editor/react(Monaco,默认 CDN 加载,免打包 worker),React + Tailwind 实现。 以可移动浮动窗口呈现:标题栏/底部拖拽条拖动、8 向缩放、最小化 / 最大化 / 关闭, 右下角常驻{ }开关,可「弹出到新窗口」拖到任意显示器。 - AI 工具:
read_code—— 读取当前会话编辑器内容,返回{ language, code }。execute_code—— 把代码(或显式传入的code)提交 Judge0 执行,返回状态 / stdout / stderr / 编译输出 / 耗时 / 内存 / 退出码。
- 行锚点便签:按会话存学习笔记(
{ id, line, text }),编辑器右缘记录条 + 右侧展开面板; 选中 AI 消息文字 → 悬浮菜单 → 追加到便签(自动换行)。 - 一键填入:在编译器里选中代码 → 悬浮按钮「覆盖填入 / 追加」→ 写入 AI 输入框草稿。
- 学习统计:学习时间 / Judge0 提交次数 / token 用量,各按最近 24 小时 + 最近 7 天画折线图(token 按 provider/model 分列)。
- 悬浮窗总开关:右下角电源开关,关 = 悬浮窗整体消失且停止一切记录(默认开,状态持久化)。
支持语言:cpp(C++17)、c、python(映射 Judge0 language_id,见 src/components/Judge0Service.ts)。
这是一个双面插件,由宿主半区与客户端半区组成:
┌───────────── 浏览器(Client) ─────────────┐ ┌────────── Node(Host) ──────────┐
│ shell.overlay 浮动层 → 编译器窗口(Monaco) │ │ 组合行 plugin-compiler │
│ CodeEditorPanel / StatsPanel / NotesPanel │ │ ├─ read_code 工具 │
│ │ 编辑(防抖) │ │ └─ execute_code 工具 ──▶ Judge0 │
│ ├─ PUT /compiler-api/state ────────────┼───────▶│ /compiler-api(webServer 路由) │
│ └─ GET /compiler-api/state(挂载) ◀────┼────────┤ 状态按 sessionId 存 host 内存 │
│ 运行按钮 / 工具共享: │ │ │
│ └─ POST /compiler-api/run ─────────────┼───────▶│ 结果 JSON 返回面板 / 工具 │
└───────────────────────────────────────────┘ └───────────────────────────────────┘
- 宿主半区(
lib/index.js,src/index.ts):注册 AI 工具 + 同源 JSON API(/compiler-api), Judge0 在 host 侧执行;编辑器状态按会话(sessionId)存 host 内存。 - 客户端半区(
lib/client.js,src/client.ts):dsh.client浏览器模块,把浮动窗口注册进shell.overlay。构建产物是window.__ModuleLoader__.load({ id, factory })格式,由 Harness 的 client-modules 扫描加载。 - 状态桥:编辑器内容按会话保存在 host 内存;面板编辑时防抖
PUT /state,read_code读同一份状态, 面板挂载时GET /state恢复上次内容。
路径以
$DSH_HOME表示 Harness 用户目录(通常为~/.dsh;Windows 下C:\Users\<你>\.dsh)。
-
复制插件到 profile 的 node_modules:
npm install # 安装依赖 npm run build # = tsc + node scripts/build-client.mjs,产出 lib/index.js 与 lib/client.js
然后把整个目录(不含
node_modules)复制到$DSH_HOME/profiles/node_modules/@mm3036/dsh-plugin-compiler(仓库里的lib/已含构建产物,克隆即可用)。 -
在
cordis.patch.yml加注册行(例如$DSH_HOME/profiles/web/cordis.patch.yml):- id: plugin-compiler name: '@mm3036/dsh-plugin-compiler' config: judge0BaseUrl: 'http://localhost:2358' # 可选,默认 https://ce.judge0.com judge0ApiKey: '' # 可选,公共 API 的 key
若只想在某个自定义 preset(如「算法学习模式」)下暴露工具,可把该行加进那个 preset 的
agent.cordis.yml。 -
重启 dsh:
dsh web。client-modules的插件集合变更需重启生效(包元数据按名缓存)。
启动 Judge0 CE(本机执行):
docker run -d --name judge0-ce -p 2358:2358 judge0/judge0-ce| 变量 | 说明 |
|---|---|
JUDGE0_BASE_URL |
Judge0 基础地址,覆盖默认的 https://ce.judge0.com(本机 Docker 用 http://localhost:2358) |
JUDGE0_API_KEY |
可选 API Key(公共 API 需要;本机 Judge0 CE 无需) |
Judge0 key 只走环境变量或行配置,不硬编码在代码里。行配置项:
judge0BaseUrl、judge0ApiKey、judge0TimeoutMs(毫秒,默认 60000)。
| 工具 | 参数 | 说明 |
|---|---|---|
read_code |
无 | 读取当前会话编辑器内容,返回 { language, code } |
execute_code |
code?、language?、stdin? |
提交 Judge0 执行;缺省用编辑器当前内容 |
npm install安装依赖(@monaco-editor/react、monaco-editor、tailwind 等)。npm run check用 tsc 做类型检查。npm run build产出lib/index.js(宿主,tsc)+lib/client.js(客户端,esbuild 出__ModuleLoader__bundle)。- 面板可在独立 Vite/React 应用中直接
<CodeEditorPanel sessionId="demo" />预览(/compiler-api404 会被静默忽略,面板保持默认代码)。
compiler-notes.json—— 行锚点便签,多会话共享一个文件{ [sessionId]: NoteItem[] },重启不丢。compiler-stats.json—— 学习统计(30 天保留窗口)。compiler-floating.json—— 悬浮窗总开关状态。
- 编辑器状态存 host 内存:进程重启后回到默认代码(便签/统计已持久化,见上)。
/compiler-api未做鉴权(同源、本地工具),公网部署需自行加固。