dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
机械技术工程师福音!!!专为SW和CAD设计的插件!现在,内置DeepSeek Harness“工程模式”,让DeepSeek Harness以“完成工图”作为第一目标,避免分心,此插件还可以以SW一键转化为CAD图纸,无需任何操作。现在,你只需要说一句命令,就可以去睡觉了,让此插件帮你完成任务吧!
面向 CAD / SolidWorks 机械设计的 DeepSeek Harness Agent 预设。 以「完成工图」为唯一目标:需求访谈 → 三维建模 → 有限元校核 → 出图交付, 每一道关键闸门都写在 Python 代码里 —— 不通过,流程走不下去。
📦 长流程产物和日志:https://share.feijipan.com/s/tryFb4AU
一句话:它不是一个"帮你写建模脚本的助手"。 它是一个会自己判断能不能交付的机械设计工程师。
| 项目 | 值 |
|---|---|
| 目标平台 | DeepSeek Harness 0.2.x(Electron 桌面版 / dsh web) |
| 预设 ID | engineering · 显示名「工程模式」· order: 4 |
| UI 插件 | dsh-engineering-ui v1.2.0 |
| 技能 | 7 个 |
| 门禁 / 桥接脚本 | 12 个核心脚本 + 14 个物理模块 |
| 回归测试 | 30 个 Python + 12 个插件测试 |
| 许可 | MIT |
真实会话录像,2 倍速播放(原片约 60 秒)。一句「帮我制造一个机械工厂用的机械臂」进去, 出来的是:需求访谈 → 门禁判定 → 拆成多个建模小屋 → 并行驱动 SolidWorks → 汇合总装。 后面每一节,就是这段录像里的一环。
DSH 的插件分三个平面,放错位置会互相连坐:
| 平面 | 位置 | 内容 | 生效方式 |
|---|---|---|---|
| 宿主层(进程级) | profiles/<profile>/cordis.patch.yml | 权限预设表、全局服务 | 必须重启 DSH |
| preset 层(会话子作用域) | 插件 bundle 里的 preset-engineering.patch.yml | 人设、工具、技能 | 热生效 |
| profile bundle | profiles/<profile>/package.json 的 dependencies + dsh.profile.bundles | UI 插件(客户端半) | 必须重启 DSH |
⛔ 绝对不要把
- id: permission写进 preset。@deepseek-ai/dsh-permission-presets是宿主层进程级服务,preset 里再声明一次 = 重复注册同名服务, loader 直接拒绝,后果是新建会话 / 切预设 / 选模型三件事一起坏。
💡 DSH 0.2.x 不再读取
.agent-presets目录。 仓库里的engineering/agent.cordis.yml只是历史对照,运行时真正加载的是 插件 bundle 声明的那份preset-engineering.patch.yml。
| 能力 | 实现 |
|---|---|
| 真的驱动 SolidWorks 建模 | Python win32com,SW 2018 ~ 2025,单位 mm |
| 自己算有限元 | 纯 Python + numpy(2D CST / 3D CTE),可选 Gmsh / CalculiX / Code_Aster / SW Simulation |
| 疲劳与寿命校核 | Basquin S-N + Marin 修正 + Miner 累积损伤,默认 30 年设计寿命 |
| 出工程图 | 三视图 + 等轴测 → .SLDDRW / .DWG / .DXF / .PDF,GB/T 排版规范 |
| 图纸几何校验 | CADX 七项检查(图层 / 图幅 / 线型 / 重叠 / 尺寸链 …) |
| 多零件协作 | 拆分「房间」,子代理串行或并行建模,SW 进程级 FIFO 锁 |
| 判断能不能交付 | 材料 / 物理 / 领域 三大防线 + 看图证据 + 台账一致性 |
| 模式 | 场景 | 执行方式 |
|---|---|---|
| 模式 1 | 单个零件、几何简单 | 单线程直接建模出图 |
| 模式 2 | 多零件 / 机构 / 传动系统 | 门禁流水线 + 多子代理「多屋」协作 |
| 模式 3 | 用户发来图片 / 截图 | 单线程识图、提尺寸、重建、出图 |
三种模式共用同一套 SW / CAD / 物理工具链,区别只在要不要走门禁、要不要开子代理。
门禁启动后的第一件事不是让 AI 直接开画,而是先问你两个互相独立的问题。 这两问写死在
tools/choice_contract.py里,题面和选项由代码给出,AI 不能改写。
| 选项 | 含义 | 适合 |
|---|---|---|
| D | 部分小屋并行,按波次分批启动 | 零件多、彼此独立、想快 |
| E | 单小屋串联,一次一个房间 | 零件之间有强耦合、想稳 |
| 选项 | 含义 | 交互强度 |
|---|---|---|
| A | 完全自主搭建,AI 自主决策关键尺寸与材料 | 几乎不打扰你 |
| B | 部分自主,关键节点询问 | 中等 |
| C | 步步确认,每个零件建模前都出参数表给你确认 | 最严,全程把关 |
C 模式是代码级强制的:每件零件必须单独提问、单独得到答复,
由主对话执行 mode_gate.py confirm-part <房间> <零件> 才能写入授权令牌。
沿用上一件零件的确认会被拒绝,并记进 violations.json。
python "<根>\tools\workflow_gate.py" select C,E
写法很宽松,以下全部等价:select C,E / select C E / select "C, E" /
select c e / select --choice C --parallel E。
select 会把结论当场写进 workflow_state.json,并与 mode_state.json 自动对齐 ——
不会出现两个命令读到相反结论的情况。
工程模式的第一条纪律:不猜参数。 材料、公差、配合类型、载荷来源,不确定就必须问你 —— 但也不是一股脑把几十道题全砸过来。
门禁第 2 步只问一个问题:本次任务要不要严格把关参数?
| 你的回答 | 题数区间 | 说明 |
|---|---|---|
| 强需求(严格校核) | 10 ~ 50 题 | 载荷、尺寸、公差、材料都要有设计依据 |
| 不强 / 精简 | 5 ~ 10 题 | 先出大致结构,细节按工程经验定 |
区间由 mode2_flow.validate_question_budget() 强制:超上限直接拒绝,
收尾时未达下限同样拒绝交付 —— 既不许敷衍,也不许审问到死。
旧做法是开局把候选题目全部抛出,用户答到手软。 现在改成按需提问:AI 先沿十阶段往下推,推到某个阶段发现缺信息,才问那一题,并写明理由。
🆕 十阶段不再由主对话自己跑:它由一个真实子代理「总计子代理」推进 (开工先
analyst-bind绑定自己的 sessionId),主对话只负责编排与建小屋。 主对话若自己调begin-stage会被ANALYST_ACTOR_REQUIRED拒绝。
十阶段设计流水线(顺序即契约,跳阶段会被拒):
TaskUnderstanding 任务理解 结构化 TaskSpec:目标 / 环境 / 载荷 / 约束 / 未知量
FunctionalDecomposition 功能分解 FunctionTree:子功能 + 输入输出 + 依赖
PhysicsReasoning 物理推导 运动 / 力 / 转矩 / 能量 / 自由度 + 假定
PrincipleSynthesis 工作原理探索 多个候选原理 + 淘汰理由
MechanismSynthesis 机构综合 MechanismGraph:构件 + 连接 + 自由度
RecursivePartReasoning 递归零件推导 PartRequirementGraph:每个零件为何存在
PartSynthesis 零件设计与选型 标准件 / 自定义件 + 几何与接口定义
EngineeringValidation 工程验证 PASS / FAIL / UNKNOWN + 证据
DesignIteration 自主迭代 回退位置 + 版本 + 未解决问题
ExplainableDesignOutput 可解释输出 完整设计报告 + 可追溯性
提问必须挂在已经推进到的阶段上:
# 1) 先推进阶段(必须按序)
python "<根>\tools\workflow_gate.py" mode2 begin-stage TaskUnderstanding
# 2) 真的缺信息了,才问 —— 且必须写明理由
python "<根>\tools\workflow_gate.py" mode2 ask "使用场合是什么" --stage TaskUnderstanding --reason "决定材料与防护等级"
阶段没 begin-stage 就提问 → 拒绝;无理由提问 → 拒绝。
这就是「不许开局把题全抛出去」的机器判据。
回答完还要落盘(answer-question)—— 题目一旦有答复,挂在它上面的阶段产物会立刻标 stale,
必须用新的产物重做那一段才能继续,防止下游拿着过期参数去建模。
曾经踩过一个很典型的坑:门禁按 1000 N 估算、physics 按 100 N 校核 —— 两套数值,报告当然对不上。
现在载荷只有一条通路:
门禁问答 ──落盘──> tools/load_cases/gate_load_case.json ──读取──> 有限元 / 疲劳
| 规则 | 说明 |
|---|---|
| 优先读用户写的数值 | 「100N」「10kg」「0.1kN」会被直接识别为额定载荷 |
| 冲击只是系数 | 出现冲击 / 动态关键词,只放大动载系数,不改额定值 |
| 落盘即真相 | 额定载荷 = magnitude_n,physics 严禁另写数值 |
| 估算必须复核 | 返回 load_is_estimate=true 时,AI 必须先向你确认才能继续 |
装配体不是一个大脚本能画完的。工程模式把它拆成若干房间, 每个房间一个子代理,房间之间靠 SW 进程锁排队 —— 而不是靠人盯着。
| 角色 | 干什么 | 边界 |
|---|---|---|
| 主对话(大屋) | 问答、编排、建小屋、收尾 | 不自己跑十阶段;只能调根会话命令 |
| 总计子代理 | analyst-bind 后跑十阶段分析、按需提问、决定房间编制 | 只有它能写阶段与编制 |
| 建模小屋 + 总理子代理 | 各自建模;总理同波监工、收上报、校验相邻尺寸 | 只做本房间 |
房间数量不再固定 3 个:由总计子代理按分析结论登记(1 ~ 24 个),
每个房间必须写清 parts(负责哪些零件)与 why(为什么需要它)。
set-subagent-plan --decided-by 总计子代理 是硬要求,别人署名直接判越权。
| 波次 | 房间 | 干什么 |
|---|---|---|
| 第 1 波 | 建模小屋 1..N + 总理子代理 | 并行建模;总理与建模同波启动,长生命周期监工 |
| 第 2 波 | 总装与验证 | 只有第 1 波全部 room-end 后才允许开始 |
| 第 3 波 | 工程图输出 | 总装完成后出三视图 / 剖视 / 标注 |
| 机制 | 行为 |
|---|---|
| 排队 | 谁先请求谁先用,队列保留;返回 sw_busy 就等 90 秒重试同一条命令 |
| 公平轮转 | 有人排队时,单房间最多连续 3 条命令或独占 180 秒,超出强制让位(防饿死) |
| 心跳 | 子代理每 60 秒续一次,但已降级为辅助证据 |
| 清场 | 每波开始前 close-all,确认没有残留的 SLDWORKS.EXE |
python "<根>\tools\mode_gate.py" room-board --json
room-board 给每个房间一个一等状态,外加 safe_to_restart 与 next_action:
| 状态 | 含义 | 能不能重启 |
|---|---|---|
starting | 刚建,宽限期内 | 否 |
running | 正常干活中 —— 不许说"没反应" | 否 |
waiting_sw | 在 SW 队列里正常等锁,不是死了 | 否(严禁判死) |
idle | 平台侧活着,当前没有可观察动作 | 否 |
unbound | 平台侧活着但忘了 subagent-assign | 否,补绑定即可,禁止 reset |
done / failed | 已收工 / 已失败 | 按需 recover |
dead | 真的没了 | 是 —— 唯一允许 recover/restart 的状态 |
旧实现的六态分类会把排队等锁的屋子误判成死,于是主对话重启一个其实活着的屋,
两个子代理抢同一份 SW 文件。现在 waiting_sw 是一等状态,看板直接给 safe_to_restart=false。
mode_gate / workflow_gate / list_agents /
subagent_fork,只做本房间的建模与验证。
唯一例外是总计子代理 —— 它只能用 mode2_flow.py 的阶段 / 提问 / 编制命令,
以及 ask_user.py 提问桥。init / provide_context / select / confirm-assembly /
recover / restart / reset 只许主对话调用,子代理调一律返回 ROOT_SESSION_REQUIRED。这两条都在代码里按 sessionId 校验,不是提示词约定 —— 越权不是"不应该",是调不通。
DSH 不允许子代理直接向用户提问(userQuestions.ask() 会校验 agents.roots(),
子代理必抛 DELEGATED_CALLER)。ask_user.py 把问题登记到本小屋 → 卡片出现在右侧面板 →
原地阻塞轮询直到你作答 → 答案以 tool_result 回到提问方。全程不结束回合。
这是它和「普通 CAD 助手」最大的区别:质量校验不是建议,是硬门禁。
| # | 防线 | 凭据 | 判不通过的依据 |
|---|---|---|---|
| ① | 材料 | 每个 .sldprt 旁的 <零件>.SLDPRT.material.json | 缺凭据 / 密度 = 1000(水)/ 跨标准静默替代 |
| ② | 物理 | reports/<房间>.physics.json | overall == FAIL,或静力过了但寿命不够 |
| ③ | 领域 | reports/<房间>.domain.json | 存在 CRITICAL 违规(按 GB/T 规则库判) |
sw_bridge.py run → ① 材料
mode_gate.py room-end <房间> → ①②③(该房间)+ 看图证据
workflow_gate.py confirm-assembly → ①②③(全部建模房间)
workflow_gate.py select (收尾) → ①②③(全任务)
凭据由宿主进程签名:HMAC-SHA256,密钥只存在宿主内存里,绝不落盘。 Python 侧不持有密钥,签名与验签都得请求宿主; 宿主不可用时不是"放行",而是 fail-closed —— 无法验签即视为未通过。
所以哪怕 AI 能读写工程模式目录里的所有文件,也写不出一份能验签的凭据。 宿主自己会读磁盘上的真实报告再签,调用方没法让它为"不存在的运行"背书。
签名有效期默认 24 小时(
DSH_DEFENSE_SIG_TTL_MS可覆盖)。 早先设成 10 分钟时,只要一个房间里零件保存跨度超过 10 分钟,room-end就必然失败 —— 多零件装配等于永远过不了门。
建模房间下线前,本房间产出过的每个零件都必须留下经核实的看图证据:
截图真实存在、非 0 字节、闭环判定 PASS。缺任何一件 → VISUAL_EVIDENCE_REQUIRED,拒绝下线。
python mode_gate.py room-end "<房间>" --force # 显式强制
$env:DSH_DEFENSE_BYPASS = 1 # 环境变量
两条路都会写进 reports/defense_bypass.json —— 绝不静默放行。
建模不是终点。每个房间都要出一份物理校核报告,FAIL 或寿命不足就拒绝下线。
按本机装了什么自动降级,没有外部 FEA 软件也照样算:
| 级别 | 后端 | 依赖 |
|---|---|---|
| L0 | 解析解(梁理论) | 无 |
| L1 | 纯 Python FEA(numpy CST 三角形 / CTE 四面体) | numpy |
| L2 | Gmsh + CalculiX | 可选安装 |
| L3 | Gmsh + Code_Aster | 可选安装 |
| L4 | Gmsh + Elmer | 可选安装 |
| L5 | SolidWorks Simulation API | SW Premium 许可 |
solve_fea 之后自动追加,结论并入 gates 与 overallFAIL,不再误判为 PASS同一个闸口 ID 曾出现几何层与 FEA 层给出相反结论的情况。现在 physics/simulation_report.py 用
GATE_OWNER 给每个闸口声明唯一归属层,聚合时只采信归属层:
| 闸口 | 归属 |
|---|---|
DESIGN_SPACE / CONNECTIVITY / WALL_THICKNESS | 几何层 |
SAFETY_FACTOR / MAX_DISPLACEMENT / FATIGUE / MESH_QUALITY | FEA 层 |
建模阶段只做三件事:草图完全定义 → 特征建模 → 圆角倒角孔。
然后是一条固定链路:run → drawing → dwg → show,出图后截图验收。
python "<根>\tools\sw_bridge.py" run <建模脚本.py> # 画零件
python "<根>\tools\sw_bridge.py" drawing <零件> # 出 .slddrw
python "<根>\tools\sw_bridge.py" dwg <零件> # 导 DWG(AutoCAD 可编辑)
python "<根>\tools\sw_bridge.py" show # 截图看一眼
工程图含三视图(前 / 俯 / 右)+ 等轴测,导出 .SLDDRW / .DWG / .DXF / .PDF。
画布归一 1.0 × 1.0,原点左下,各纸型同比例。
| 规则 | 值 |
|---|---|
| 安全区 | (0.05, 0.05) ~ (0.95, 0.95),唯一合法区域 |
| 标题栏禁区 | (0.80, 0.90) ~ (1.00, 1.00) |
| 主视 / 俯视 | (0.30, 0.72) / (0.30, 0.28) |
| 右视 / 等轴测 | (0.75, 0.72) / (0.75, 0.28) |
| 投影关系 | 主俯同 x(长对正),主右同 y(高平齐) |
| 视图间距 | 任意两视图 ≥ 35 mm(约 0.04) |
宁可升纸型,也不许越界。轴类零件画中心线(点划线),特征交界画分界线,禁边线重合。
DSH_ + 中文名,例如 DSH_关节轴.sldprt。new_part() 就赋材,杜绝「密度恒为 1000(水)」导致的整条校核失真。UI 插件 dsh-engineering-ui 只在工程模式下生效,可在设置里关掉。
| 区域 | 内容 |
|---|---|
| 主对话(约 3/4) | DSH 原生会话区,检测到子代理时自动收窄 |
| 中间竖排频道 | 每个子代理一个按钮,绿点 = 运行中,点击切换右侧屏幕 |
| 右侧工作区(约 1/4) | 所选子代理的实时输出、工具调用与参数、运行状态、可直接作答的提问卡片 |
没有子代理时三栏全部隐藏,回到全宽聊天。
connection_state.json,AI 与设置页共读同一份;| 项 | 要求 |
|---|---|
| 系统 | Windows(SolidWorks / AutoCAD 自动化依赖 win32com) |
| DSH | 0.2.x(Electron 桌面版或 dsh web) |
| Python | 3.8+ 64 位,需 pywin32;物理校核另需 numpy |
| 可选 | ezdxf + shapely(DXF 几何校验)、Pillow(看图)、Gmsh / CalculiX(高阶 FEA) |
| 软件 | SolidWorks 2018 ~ 2025;AutoCAD(仅出 DWG 时需要) |
cd <本仓库>
.\install-0.2.0.ps1
# 只装指定 profile:
.\install-0.2.0.ps1 -Profile web,desktop
脚本会做四件事:
engineering/tools 复制到 ~/.dsh/.agent-presets/engineering/tools(门禁脚本);engineering/skills 复制到 ~/.dsh/skills(技能);node_modules,并登记进 package.json
(dependencies + dsh.profile.bundles);cordis.patch.yml(权限三档),绝不覆盖已有 patch。⚠️ 装完必须重启 DSH。宿主层与插件 host 半都是进程级配置,热更新无效。 只改客户端半(
lib/client.js)时,刷新页面即可。
仓库里的 engineering/ 是源码,DSH 真正加载的是安装副本。改完要同步:
.\sync-to-dsh.ps1 -DryRun # 先看要动哪些文件
.\sync-to-dsh.ps1 # 实际同步(逐个备份 .bak-sync-<时间戳>)
python engineering\tools\verify_sync.py # 逐文件 SHA-256 比对,确认真的同步了
运行时状态文件(
mode_state.json/workflow_state.json/sw_state.json/connection_state.json/settings.json)是会话现场数据,同步时会被跳过 —— 不要手动覆盖,否则流程会误判。
门禁的入口全是命令行脚本,不是 DSH 工具。 历史文档里出现过的
workflow-gate-init这类"工具名"在本环境并不存在,照抄会失败。
$T = "<工程模式根目录>\tools" # 含 mode_gate.py 与 workflow_gate.py 的那个目录
python "$T\_root.py" # 不确定根目录?先跑这个自检
workflow_gate.py — 门禁大脑| 子命令 | 用途 |
|---|---|
init "<任务>" | 初始化任务,返回第 1 步(模式确认 + 并行策略 D/E + 搭建方式 A/B/C) |
provide_context "<回答>" | 推进状态机,需调用 3 次(模式确认 → 需求强度 → 汇总估算) |
select C,E | 锁定搭建方式与并行策略 |
confirm-assembly "<清单>" | 第 1 波完成后确认总装 |
check-part / verify-ownership | 零件归属校验 / 总装前去重核对 |
status / gate-summary / check | 状态 / 总览 / 是否允许建模 |
recover / restart <房间> / reset | 恢复卡住 / 重做房间 / 清空重来 |
mode2 <子命令> | 十阶段契约:begin-stage / ask / prime-report / prime-verify … |
stage-status / pre-delivery | 阶段进度 / 交付前总闸 |
除
status/gate-summary这类只读命令外,只许根会话调用; 子代理调init/select/reset会拿到ROOT_SESSION_REQUIRED。
mode_gate.py — 房间状态机 + SW 锁| 类别 | 子命令 |
|---|---|
| 看板(权威) | room-board [--room X] [--json] — 八态 + safe_to_restart + next_action |
| 房间 | room-start / room-end / room-fail / room-status / room-report / room-report-read |
| SW 锁 | sw-request / sw-wait / sw-release / sw-status / sw-proc / lock-doctor / close-all |
| 子代理 | subagent-assign(每次 fork 后必做) / subagent-free / subagent-status / whoami |
| 心跳 | room-heartbeat(辅助证据) / room-heartbeat-check |
| 授权 | confirm-part <房间> <零件>(C 模式) / room-artifact |
| 看护 | sw-guard-start / sw-guard-stop / sw-guard-status(CPU / 内存 > 85% 立刻关 SW) |
| 维护 | doctor / rooms-reset / stale-artifacts / residue-check / platform-refresh |
mode2_flow.py — 十阶段 / 编制 / 总理| 子命令 | 用途 |
|---|---|
analyst-bind / analyst-status | 总计子代理绑定自己的 sessionId / 查看是否已绑定 |
begin-stage / mark-stage-done | 按序推进阶段 / 登记产物(只认总计子代理身份) |
ask / answer-question / refresh-stage | 按需提问 / 落盘答复 / 重做过期阶段 |
set-subagent-plan --rooms-json ... --decided-by 总计子代理 | 登记本轮房间编制 |
prime-board / prime-report / check-consistency | 监工看板 / 收上报 / 相邻尺寸一致性 |
prime-verify / export-docx / pre-delivery | 统一核实 / 汇总 docx / 交付前总闸 |
| 脚本 | 用途 |
|---|---|
defense_gate.py check-room <房间> / check-task | 三大防线自查 |
sw_bridge.py <命令> | SW 桥接(run / drawing / dwg / physics-* / conn-* / cad-*) |
physics_bridge.py <子命令> | 物理验证 CLI(validate-case / optimize / fatigue / validate-domain) |
visual_check.py gate --part <零件> --expect <json> | 看图闭环校核 |
ask_user.py --room <房间> --child <id> ... | 子代理阻塞式提问 |
part_registry.py | 零件台账:相邻尺寸一致性 / SHA-256 防篡改 / 导出 docx |
settings.py report / env_check.py probe | 本机设置 / 环境自检 |
DSH-SW-and-CAD-main/
├── README.md # 本文件
├── assets/gifs/ # 四段实录动图
├── install-0.2.0.ps1 # DSH 0.2.x 安装(装进所有 profile)
├── install.ps1 / install.sh # DSH 0.1.x 安装(Win / macOS-Linux)
├── sync-to-dsh.ps1 # 源码 -> 安装副本同步
├── patch-incompatible.ps1 # 第三方插件 peer range 修补
├── RUNNING_WORKFLOW.md # 源码级全链路追踪(从一条消息到一次 COM 调用)
├── engineering/ # ★ 预设本体
│ ├── preset.yml # 显示元数据
│ ├── agent.cordis.yml # 历史清单(运行时不加载,仅对照)
│ ├── README.md # 架构与门禁细节(更技术向)
│ ├── skills/ # 8 个技能
│ │ ├── mode-selection/ # 强制入口:模式选择 + 门禁流程
│ │ ├── assembly-orchestration/ # 多屋编排
│ │ ├── cad-workflow/ # AutoCAD 工作流
│ │ ├── sw-design/ # SW 设计 + GB/T 制图
│ │ ├── solidworks-bridge/ # SW 桥接
│ │ ├── sw-to-cad/ # SW -> CAD
│ │ ├── physics-in-loop/ # 物理在环
│ │ └── webots-simulation/ # Webots 仿真(可选,见 docs/webots-mcp)
│ ├── tools/ # ★ Python 工具链
│ │ ├── workflow_gate.py # 门禁大脑
│ │ ├── mode_gate.py # 房间状态机 + SW 锁 + room-board
│ │ ├── mode2_flow.py # 十阶段契约 / 编制 / 总理
│ │ ├── defense_gate.py # 三大防线
│ │ ├── sw_bridge.py # SW 桥接执行器
│ │ ├── swapi.py # 高层建模 API
│ │ ├── part_registry.py # 零件台账 + 一致性校验
│ │ ├── visual_check.py # 看图闭环
│ │ ├── webots_env.py # ★ Webots 仿真可用性自检(只读)
│ │ ├── webots_mcp/ # ★ Webots MCP server / 转换 / 证据(可选)
│ │ ├── physics/ # 物理子系统(FEA / 疲劳 / 规则库)
│ │ ├── physics/rules/ # GB/T 规则包
│ │ ├── load_cases/ # 载荷工况(gate_load_case.json)
│ │ ├── reports/ # 防线凭据 + 房间报告
│ │ └── test_regression_*.py # 31 个回归测试
│ └── plugins/dsh-engineering-ui/ # UI 插件
│ ├── lib/index.js # Host 半(HTTP 路由 / 提问桥接 / 防线签名)
│ ├── lib/client.js # 浏览器半(三栏工作区)
│ ├── lib/defense-sign.js # HMAC 凭据签名
│ ├── lib/job-wait-guard.js # ★ job_output 长等待守卫(防"卡死",见下)
│ ├── preset-engineering.patch.yml # ★ 运行时真正加载的人设
│ ├── lib/webots.js # ★ Webots 只读宿主门(归属校验 + 4 条路由)
│ └── test/ # 15 个插件测试
├── profiles/ # 宿主层 patch 模板
└── third-party-patched/ # 打过补丁的第三方插件
动手改之前先读
engineering/README.md:那里记着每个历史 bug 的现场现象 / 根因 / 修复判据, 很多看起来"多余"的代码,是为了防止某个已经踩过两次的坑复发。
接入的是官方交付补丁
f04ac75a(86 文件:engineering/tools/webots_mcp/的 MCP server、 转换器、证据读取器 + 12 份契约文档 + 测试)。它是外围承载,不是物理核心 —— 原生 SW 导出、关节推断、自动回写与真实物理判定仍未实现,状态里会明写core_ready=false/CALIBRATION_REQUIRED。
不是第四种模式。仿真发生在模型已经存在之后:
Mode 1/2/3 判定 → 门禁 → 建模 → 三大防线 → 出图
↘ (可选)Webots 仿真 → 报告/证据 → 只读回看
它消费 select 建立的 task/room 身份,所以必须在 select 之后、room-end 之前跑;
房间收尾后没有合法身份,只读接口会返回 CONTEXT_UNAVAILABLE。
| 入口 | 用法 |
|---|---|
| 自检(先跑这个) | python "<根>\tools\webots_env.py" --json → 看 sim_available / blocking |
| 桥接命令 | sw_bridge.py sim-status / sim-env / sim-list / sim-report(不连 SW、不取 SW 锁) |
| MCP 工具 | mcp__webots__sim_status / sim_launch / sim_job / sim_report / sim_evidence …(需 DSH_WEBOTS_ENABLE=1) |
宿主侧新开了 4 条只读 GET 路由(webots-context / -report / -evidence / -attribute),
走的是和 conn-state 同一套 guardRoute(loopback + Origin 校验 + 限流)。
⚠️ 设置页「连接区」里那块「▶ Webots 仿真报告与证据(只读)」已按用户要求移除(2026-11-05)。 组件(
EngWebotsPanel/EngWebotsSnapshot/EngWebotsReport)仍保留并导出, 供子代理工作区或后续版本复用;要接回设置页只需恢复一行h(EngWebotsPanel, {})。
$env:DSH_WEBOTS_ENABLE = '1'
$env:DSH_WEBOTS_PYTHON = '<绝对路径>\python.exe' # 已装 webots_mcp/requirements.txt
$env:DSH_WEBOTS_INPUT_ROOT = '<已存在的只读输入根>'
$env:DSH_STATE_DIR = '<已存在的绝对 state 目录>'
$env:DSH_ENGINEERING_ROOT = '<工程模式根>\engineering'
$env:WEBOTS_HOME = 'D:\Webots'
# 可选:$env:DSH_WEBOTS_RUNTIME_CONFIG = '<绝对路径>\runtime.json'
依赖安装(一次性):
python -m venv $env:USERPROFILE\.dsh\engineering-webots\venv
& $env:USERPROFILE\.dsh\engineering-webots\venv\Scripts\python.exe -m pip install -r engineering\tools\webots_mcp\requirements.txt
| 能做 | 不能做 |
|---|---|
| 离线把零件捕获转成 URDF + PROTO(urdf2webots 2025.0.0) | 原生 SW→URDF 的坐标/惯量标定(A01) |
| 读已存报告与日志证据(字节分页 + SHA-256) | 自动关节推断(A02) |
| 归属校验 / 代际 / 操作幂等 | 自动根因回写 SW(A03/A04) |
sim_status 等只读查询 | 真实物理 PASS 判定(恒 physical_validation=not_run) |
fake / fixture / synthetic / 静态校验 / 空接触 都不等于物理 PASS;
OUTCOME_UNKNOWN 禁止重发动作。详见 engineering/docs/webots-mcp/。
job_output 长等待守卫2026-10-31 事故:
job_output { wait: true, timeout_ms: 270000 }静默阻塞数分钟, GUI 毫无反馈 → 用户以为 DSH 死机 → 强制退出 → 退出瞬间所有插件 fiber 失活 →cannot get required service "jobs" in inactive context→turn/end{interrupted},整轮对话作废。 完整复盘见 docs/DSH卡死事故分析_job_output阻塞.md。
修复分两层,两层都装才完整:
| 层 | 位置 | 生效方式 |
|---|---|---|
| 宿主层 | plugins/dsh-engineering-ui/lib/job-wait-guard.js(经官方 ctx.on('tools/execute') 接线) | 装进 profile 后重启 DSH |
| 仓库层 | preset-engineering.patch.yml 人设 + 各 SKILL + ask_user.py | 热生效(同步到安装副本即可) |
宿主层做两件事:
JOB_CONTEXT_LOST 工具错误(isError=true + 操作指引),
不再让框架异常冒到 turn 级把整轮打断。安装 / 重装(DSH 每次升级都会覆盖安装目录,升级后重跑一次即可):
.\install-job-wait-guard.ps1 -DryRun # 先看会动哪些文件
.\install-job-wait-guard.ps1 # 装进每个 profile(逐文件 .bak-guard-时间戳)
.\install-job-wait-guard.ps1 -Verify # 只核对
| 环境变量 | 默认 | 作用 |
|---|---|---|
DSH_ENG_JOB_WAIT_GUARD | 开 | 设 0 关闭守卫 |
DSH_ENG_JOB_WAIT_MAX_MS | 45000 | 单次等待窗口上限(最小 5000) |
回归:node --test engineering\plugins\dsh-engineering-ui\test\job-wait-guard.test.mjs(6/6)。
旧人设里有一句「必须等后台 job 时:单次 sleep ≤30s,timeout_ms ≤30000,宁可多轮短等」——
这句把"轮询"写成了等待的第一选择,实测被照抄成单轮 477 次 sleep(30)、轮询 4 小时 02 分
(占墙钟 66%),期间零产物。现已改写为:
time.sleep / Start-Sleep 轮询等子代理、等房间、等 SW 锁;mode_gate.py wait-rooms "<房间>" --timeout 900 /
mode_gate.py room-board --wait 900 / mode_gate.py sw-wait <房间> --timeout 90;sw_bridge run 的后台 job 收尾)才允许短 sleep,
且同一等待目标连续不得超过 3 次;[WAITING] 在等:…;判据:room-board state=…;唤醒条件:…
(该终止态由 Host 半实现,现阶段须自己写清摘要;房间已是 done/failed/dead 时必须先处置,
禁止用它掩盖"其实已经完事")。人设里新增铁律:工具输出里出现 U+FFFD / � 时禁止据此下结论,
必须补上 $env:PYTHONIOENCODING='utf-8'; $env:PYTHONUTF8='1' 重跑,
或用 read 工具直接读磁盘原文核对(磁盘上的 .json/.md 不经控制台代码页)。
注入式根治在插件 lib/index.js 的宿主半,人设层只做流程约束。
massprops、GetBodyBox 等)。ezdxf + shapely,两者缺失时该项自动跳过 —— 别把它当成"已通过"。Get-Content 会按 ANSI 解码,
读中文 JSON 容易报「传入的对象无效」。用 python -c "..." 或 DSH 的 read 工具读。| 提交 / 日期 | 说明 |
|---|---|
| 2026-10-28 | 总计子代理真实化(analyst-bind + 身份校验)+ 总理子代理同波启动与监工 + room-board 状态可信化(waiting_sw / unbound)+ 子代理禁令(ROOT_SESSION_REQUIRED)+ 插件自动平台登记 |
e12d665 | 为移动端 DSH Go 做适配性调整 |
fe671a3 | mode2_flow 与防御门控完善,新增回归测试与物理运行记录 |
b2a11b1 | 已适配 DSH 0.2.1-rc.2 |
578818e | 模式二流程改造:十阶段契约 + 总理核实 + 看图闭环 + SW 双路看护 |
eb55f4a | 适配 DSH 0.2.0 桌面版(bundle 路径、desktop profile、三栏 UI) |
d2e6828 | 工程工作流更新:技能、mode gate、插件、SW 桥接改进 |
DSH Engineering Mode is an Agent Preset for DeepSeek Harness, built for CAD / SolidWorks mechanical design. Its single goal is a finished engineering drawing.
What makes it different from a chat assistant that writes CAD scripts: