@godv61/dsh-task-engine 0.16.0 → 0.18.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 +15 -1
- package/docs/manual.html +33 -12
- package/lib/client.js +50 -14
- package/lib/client.js.map +3 -3
- package/lib/controller.d.ts +1 -1
- package/lib/controller.js +62 -21
- package/lib/controller.js.map +1 -1
- package/lib/dev-task.js +145 -28
- package/lib/dev-task.js.map +1 -1
- package/lib/engine.d.ts +17 -2
- package/lib/engine.js +4 -3
- package/lib/engine.js.map +1 -1
- package/lib/workflows.d.ts +47 -12
- package/lib/workflows.js +89 -19
- package/lib/workflows.js.map +1 -1
- package/package.json +2 -1
- package/rules/coding-conventions.md +1 -1
- package/rules/security-redlines.md +1 -1
- package/skills/eng-delivery/SKILL.md +4 -0
- package/skills/solution-design/SKILL.md +1 -1
package/README.md
CHANGED
|
@@ -136,6 +136,18 @@ dsh plugin --profile <name> add .
|
|
|
136
136
|
|
|
137
137
|
> 钩子读 `.dsh/eng.json` + `.dsh/task-*.json`,跨仓库零依赖、自包含。
|
|
138
138
|
|
|
139
|
+
## 项目初始化(init)
|
|
140
|
+
|
|
141
|
+
二开 / 遗留项目常常没有文档,AI 接手前需要先「认识」这个项目。`dev_task`(operation=init)走 **inspect → propose → apply** 三阶段管理项目根的 `AGENTS.md`,绝不直接覆盖已有治理文件:
|
|
142
|
+
|
|
143
|
+
1. `inspect`——读取现有 `AGENTS.md`(若有)返回给模型;没有则提示扫描项目。
|
|
144
|
+
2. `propose`——模型扫描(目录结构、技术栈、构建/运行命令、约定、红线)后给出全文草稿,此步**只预览不落盘**。
|
|
145
|
+
3. `apply`——落盘。首次创建直接写入;覆盖已有 `AGENTS.md` 必须 `overwrite: true` 且**经人工批准**,否则拒绝。
|
|
146
|
+
|
|
147
|
+
- **为什么是 `AGENTS.md`**:DSH 平台会把项目根的 `AGENTS.md` **自动注入到每个会话**——生成一次,之后每个任务开工 AI 都自带这份项目认知,引擎无需额外的注入逻辑。
|
|
148
|
+
- **行数上限**:`AGENTS.md` 每次都进上下文,200 行(约 4–6K token)是硬约束,逼着只写「项目是什么 → 怎么跑 → 结构 → 约定 → 坑」,而不是塞长篇文档。
|
|
149
|
+
- **治理文件保护**:`AGENTS.md` 默认受保护——已有文件时 `apply` 不裸覆盖,需显式 `overwrite` + 人工批准。
|
|
150
|
+
|
|
139
151
|
## 状态与待办
|
|
140
152
|
|
|
141
153
|
- **脚本级已验证**:strict `tsc` typecheck/build 零错误;`dsh plugin add` 装进独立实例、`--dump-config` 确认 `task-engine` 进组合树;`validateWorkflow`(配置校验)、`artifacts_present`(产物门)、`file_scope`(文件范围门)、`hooks/commit-msg`(机械门禁)单测/冒烟全过——非法配置逐条报错、产物没填全挡流转、范围外文件挡提交、钩子该放放该拦拦。
|
|
@@ -154,4 +166,6 @@ dsh plugin --profile <name> add .
|
|
|
154
166
|
- **两阶段评审硬门(0.13.0)**:`todos_done` 进一步收紧——每个 done 的 item 必须带 spec + quality 都 pass 的评审记录,缺评审或任一阶段 fail 都会挡住「开发 → 交付」,并以具体 item 报出阻塞原因(`todosBlockers`)。派工审计保持软约束。
|
|
155
167
|
- **skill / rule 查看 + 删除(0.14.0)**:内置 skill/rule 从「只读不可见」改为「可查看正文」;自建(项目/用户)skill/rule 新增删除(两步确认)。删改在类型层即把 `bundled` 排除,内置资源永不误删。
|
|
156
168
|
- **弹窗 + markdown 查看(0.15.0)**:skill/rule 的查看与编辑从内联卡片改为居中宽弹窗;查看时正文用 DSH 自带的 `MarkdownText` 渲染成 markdown 富文本(不引入任何新依赖),编辑时正文保持纯文本。
|
|
157
|
-
- **流程预设收敛(0.16.0)**:把「自由编辑阶段图/守卫/产物/提交规则/验证开关」收敛为「选一套内置流程预设 + 给节点挂 skill/rule」。新增 `src/workflows.ts` 内置 `standard` / `agile` / `minimal` 三套流程(阶段图、守卫、产物字段、提交规则、验证证据开关全部固化);`.dsh/eng.json` 从完整配置精简为 `{ flow, stage_bindings }`;工作台删掉流转/产物/提交规则/验证开关编辑 UI,只剩「流程预设 + 流程节点(只读)+ 阶段技能/规则」;git 提交钩子同步按 `flow` 选预设。
|
|
169
|
+
- **流程预设收敛(0.16.0)**:把「自由编辑阶段图/守卫/产物/提交规则/验证开关」收敛为「选一套内置流程预设 + 给节点挂 skill/rule」。新增 `src/workflows.ts` 内置 `standard` / `agile` / `minimal` 三套流程(阶段图、守卫、产物字段、提交规则、验证证据开关全部固化);`.dsh/eng.json` 从完整配置精简为 `{ flow, stage_bindings }`;工作台删掉流转/产物/提交规则/验证开关编辑 UI,只剩「流程预设 + 流程节点(只读)+ 阶段技能/规则」;git 提交钩子同步按 `flow` 选预设。
|
|
170
|
+
- **项目初始化 + 语言无关内置规则(0.17.0)**:`dev_task` 新增 `init` 操作,生成项目根 `AGENTS.md`(DSH 每会话自动注入),落盘前做 200 行硬校验、已存在需 `overwrite` 才覆盖;内置 `solution-design` / `coding-conventions` / `security-redlines` 去掉 Java 专属概念(Impl / DTO / VO、Controller / Mapper),改成语言中立骨架,语言特定规范交给项目自建 rule。
|
|
171
|
+
- **工程可靠性加固(0.18.0)**:① 高风险任务与流程能力绑定——`high_risk` 任务只能在具备「验证门 + 文件范围 + 评审门」能力的流程创建,选 `agile`/`minimal` 直接拒绝;② 任务创建时固化流程快照(预设 id + version + 完整配置),后续 `status`/`advance`/`verify`/`review`/`commit` 一律用快照,中途改 `.dsh/eng.json` 不再漂移在途任务的门禁;③ 未知流程失败关闭——`.dsh/eng.json` 缺 `flow` 或 `flow` 不在预设里一律报错(`UNKNOWN_FLOW` / 缺字段),不再静默回退 `standard`;④ 核心 skill/rule 不可取消、不可被同名覆盖——项目阶段绑定只能追加不能移除预设自带绑定,同名规则/技能读内置版、新建同名被拒;⑤ `init` 升级 `inspect → propose → apply` 三阶段,覆盖已有 `AGENTS.md` 需人工批准。
|
package/docs/manual.html
CHANGED
|
@@ -55,12 +55,13 @@
|
|
|
55
55
|
<a href="#skills">5. Skills</a>
|
|
56
56
|
<a href="#rules">6. Rules</a>
|
|
57
57
|
<a href="#configure">7. 配置流程与挂载</a>
|
|
58
|
-
<a href="#
|
|
59
|
-
<a href="#
|
|
60
|
-
<a href="#
|
|
61
|
-
<a href="#
|
|
62
|
-
<a href="#
|
|
63
|
-
<a href="#
|
|
58
|
+
<a href="#init">8. 项目初始化(init)</a>
|
|
59
|
+
<a href="#start">9. 如何开始一个任务</a>
|
|
60
|
+
<a href="#run">10. 流程如何逐阶段执行</a>
|
|
61
|
+
<a href="#state">11. 任务状态如何记录进度</a>
|
|
62
|
+
<a href="#verify">12. 验证、评审与提交</a>
|
|
63
|
+
<a href="#example">13. 一个标准任务的完整走查</a>
|
|
64
|
+
<a href="#boundaries">14. 边界与常见问题</a>
|
|
64
65
|
</nav>
|
|
65
66
|
|
|
66
67
|
<main>
|
|
@@ -102,6 +103,7 @@ pnpm install && pnpm run build && pnpm dsh web</code></pre>
|
|
|
102
103
|
<section id="structure">
|
|
103
104
|
<h2>3. 文件与目录</h2>
|
|
104
105
|
<pre><code>D:\workspace\
|
|
106
|
+
├─ AGENTS.md ← init 生成的项目描述(DSH 每会话自动注入)
|
|
105
107
|
├─ .dsh\
|
|
106
108
|
│ ├─ eng.json ← 流程预设 + 节点挂载(团队共享,可进 git)
|
|
107
109
|
│ ├─ skills\ ← 项目级 skill
|
|
@@ -139,6 +141,8 @@ pnpm install && pnpm run build && pnpm dsh web</code></pre>
|
|
|
139
141
|
</div>
|
|
140
142
|
<div class="callout warn">
|
|
141
143
|
<p>预设之外,单个任务还有两个模型自动判断的字段:<code>work_size</code>(tiny / standard / complex,决定拆多细)和 <code>risk_level</code>(standard / high_risk,决定验证强度)。它们不是流程档位,是单个任务的规模与风险标签。</p>
|
|
144
|
+
<p><strong>高风险任务只能在 <code>standard</code> 流程建</strong>——引擎要求高风险任务具备「验证门 + 文件范围 + 评审门」,<code>agile</code>/<code>minimal</code> 没有验证门和评审门,建 <code>high_risk</code> 任务会被直接拒绝。要跑高风险就选标准研发,或把风险降到 standard。</p>
|
|
145
|
+
<p>任务创建时会把所选流程<b>固化成快照</b>——之后在途任务一直按创建时的门禁走,中途改 <code>.dsh/eng.json</code> 只影响新任务,不影响已建任务。</p>
|
|
142
146
|
</div>
|
|
143
147
|
</section>
|
|
144
148
|
|
|
@@ -197,8 +201,25 @@ pnpm install && pnpm run build && pnpm dsh web</code></pre>
|
|
|
197
201
|
<p>三层来源与优先级:同名 skill / rule,<strong>项目级 > 用户级 > 内置</strong>。想改内置某条,新建同名项目级版本即可顶替,内置留着兜底。</p>
|
|
198
202
|
</section>
|
|
199
203
|
|
|
204
|
+
<section id="init">
|
|
205
|
+
<h2>8. 项目初始化(init)</h2>
|
|
206
|
+
<p>二开 / 遗留项目没有文档时,先让 AI 给项目建一份「描述文件」——项目根的 <code>AGENTS.md</code>。DSH 平台会把它<b>自动注入到每个会话</b>,生成一次,之后每个任务开工 AI 都自带这份项目认知。</p>
|
|
207
|
+
<div class="callout"><p><strong>什么时候用:</strong>接手一个 AI 还不认识的项目(尤其二次开发的遗留代码)时,先跑一次 init 摸底;全新项目或 AI 已熟悉时可跳过。</p></div>
|
|
208
|
+
<ol>
|
|
209
|
+
<li><b>inspect</b>:对 AI 说「帮我初始化这个项目」;AI 读现有 <code>AGENTS.md</code>(若有)返回,没有则扫目录结构、技术栈、构建 / 运行命令、约定与红线。</li>
|
|
210
|
+
<li><b>propose</b>:AI 写成 <code>AGENTS.md</code> 草稿,此步<b>只预览、不落盘</b>,同时硬校验<b>行数 ≤ 200 行</b>——超了精简到「项目是什么 → 怎么跑 → 结构 → 约定 → 坑」,只留骨架不塞长文。</li>
|
|
211
|
+
<li><b>apply</b>:落盘。首次创建直接写入;覆盖已有 <code>AGENTS.md</code> 必须带 <code>overwrite</code> 且<b>经人工批准</b>,保护项目已有治理文件不被 AI 裸覆盖。</li>
|
|
212
|
+
</ol>
|
|
213
|
+
<pre><code>项目根/
|
|
214
|
+
├─ AGENTS.md ← init 生成,DSH 每会话自动注入
|
|
215
|
+
└─ .dsh/
|
|
216
|
+
├─ eng.json
|
|
217
|
+
├─ skills/ · rules/
|
|
218
|
+
└─ task-*.json</code></pre>
|
|
219
|
+
</section>
|
|
220
|
+
|
|
200
221
|
<section id="start">
|
|
201
|
-
<h2>
|
|
222
|
+
<h2>9. 如何开始一个任务</h2>
|
|
202
223
|
<ol>
|
|
203
224
|
<li>新建会话,预设选「工程化开发引擎」。</li>
|
|
204
225
|
<li>直接描述需求(加功能 / 修 bug)。</li>
|
|
@@ -212,7 +233,7 @@ pnpm install && pnpm run build && pnpm dsh web</code></pre>
|
|
|
212
233
|
</section>
|
|
213
234
|
|
|
214
235
|
<section id="run">
|
|
215
|
-
<h2>
|
|
236
|
+
<h2>10. 流程如何逐阶段执行</h2>
|
|
216
237
|
<div class="table-wrap">
|
|
217
238
|
<table>
|
|
218
239
|
<thead><tr><th>阶段</th><th>AI 在这一站做什么</th><th>过关条件(不满足不让走)</th></tr></thead>
|
|
@@ -235,7 +256,7 @@ pnpm install && pnpm run build && pnpm dsh web</code></pre>
|
|
|
235
256
|
</section>
|
|
236
257
|
|
|
237
258
|
<section id="state">
|
|
238
|
-
<h2>
|
|
259
|
+
<h2>11. 任务状态如何记录进度</h2>
|
|
239
260
|
<p>每个任务一份 <code>.dsh/task-*.json</code>,只保存当前有效状态,不保存聊天全文和流水日志。</p>
|
|
240
261
|
<div class="table-wrap">
|
|
241
262
|
<table>
|
|
@@ -259,7 +280,7 @@ pnpm install && pnpm run build && pnpm dsh web</code></pre>
|
|
|
259
280
|
</section>
|
|
260
281
|
|
|
261
282
|
<section id="verify">
|
|
262
|
-
<h2>
|
|
283
|
+
<h2>12. 验证、评审与提交</h2>
|
|
263
284
|
<h3>验证为什么不该总那么慢</h3>
|
|
264
285
|
<ul>
|
|
265
286
|
<li>实施中优先受影响模块的编译、目标测试与静态检查。</li>
|
|
@@ -285,7 +306,7 @@ pnpm install && pnpm run build && pnpm dsh web</code></pre>
|
|
|
285
306
|
</section>
|
|
286
307
|
|
|
287
308
|
<section id="example">
|
|
288
|
-
<h2>
|
|
309
|
+
<h2>13. 一个标准任务的完整走查</h2>
|
|
289
310
|
<p>假设需求是「给现有查询接口加一个权限校验」。标准流程下,关键决策点应接近下面这样:</p>
|
|
290
311
|
<pre><code>flow: standard // 项目预设
|
|
291
312
|
work_size: standard // 数个文件 + 权限判断
|
|
@@ -315,7 +336,7 @@ risk_level: high_risk // 涉及鉴权,验证要加证据
|
|
|
315
336
|
</section>
|
|
316
337
|
|
|
317
338
|
<section id="boundaries">
|
|
318
|
-
<h2>
|
|
339
|
+
<h2>14. 边界与常见问题</h2>
|
|
319
340
|
<div class="callout danger">
|
|
320
341
|
<p>引擎只允许:读取仓库事实、修改<b>已确认任务范围内</b>的文件、按策略创建<b>范围受控的本地提交</b>。远程 push / 合并 / 发布、数据库写入,需人单独决定。</p>
|
|
321
342
|
</div>
|
package/lib/client.js
CHANGED
|
@@ -4640,17 +4640,49 @@ var MINIMAL = {
|
|
|
4640
4640
|
"\u4EA4\u4ED8": { skills: ["code-commit"], rules: ["commit-conventions"] }
|
|
4641
4641
|
}
|
|
4642
4642
|
};
|
|
4643
|
-
|
|
4644
|
-
|
|
4645
|
-
|
|
4646
|
-
|
|
4643
|
+
function deriveCapabilities(config) {
|
|
4644
|
+
const caps = [];
|
|
4645
|
+
const guards = new Set(config.transitions.flatMap((t) => t.requires ?? []));
|
|
4646
|
+
if (guards.has("verified")) caps.push("verification_gate");
|
|
4647
|
+
if (guards.has("review_passed")) caps.push("review_gate");
|
|
4648
|
+
if (guards.has("artifacts_present")) caps.push("artifact_gate");
|
|
4649
|
+
if (config.commit.file_scope) caps.push("file_scope");
|
|
4650
|
+
return caps;
|
|
4651
|
+
}
|
|
4652
|
+
function preset(id, version, label, description, config) {
|
|
4653
|
+
return { id, version, label, description, capabilities: deriveCapabilities(config), config };
|
|
4654
|
+
}
|
|
4655
|
+
var FLOW_PRESETS = {
|
|
4656
|
+
standard: preset("standard", 1, "\u6807\u51C6\u7814\u53D1", "\u9700\u6C42\u8BC4\u5BA1 \u2192 \u8BBE\u8BA1 \u2192 \u5F00\u53D1 \u2192 \u4EA4\u4ED8 \u2192 \u4EE3\u7801\u5BA1\u6838\uFF0C\u542B\u4EA7\u7269\u95E8 + \u786E\u8BA4\u95E8", STANDARD),
|
|
4657
|
+
agile: preset("agile", 1, "\u654F\u6377\u8F7B\u91CF", "\u9700\u6C42 \u2192 \u5F00\u53D1 \u2192 \u4EA4\u4ED8 \u2192 \u5BA1\u67E5\uFF0C\u56DB\u9636\u6BB5\u3001\u5C11\u4EA7\u7269", AGILE),
|
|
4658
|
+
minimal: preset("minimal", 1, "\u7EAF\u4EE3\u7801", "\u5F00\u53D1 \u2192 \u4EA4\u4ED8\uFF0C\u4E24\u9636\u6BB5\uFF0C\u53EA\u7559\u63D0\u4EA4\u95E8\u7981", MINIMAL)
|
|
4647
4659
|
};
|
|
4648
|
-
function
|
|
4649
|
-
|
|
4650
|
-
|
|
4651
|
-
|
|
4660
|
+
function dedupe(names) {
|
|
4661
|
+
return [...new Set(names)];
|
|
4662
|
+
}
|
|
4663
|
+
function mergeBindings(base, override) {
|
|
4664
|
+
if (override === void 0) return base;
|
|
4665
|
+
let changed = false;
|
|
4666
|
+
const merged = { ...base.stage_bindings };
|
|
4667
|
+
for (const [stage, addition] of Object.entries(override)) {
|
|
4668
|
+
const existing = merged[stage];
|
|
4669
|
+
const skills = dedupe([...existing?.skills ?? [], ...addition.skills ?? []]);
|
|
4670
|
+
const rules = dedupe([...existing?.rules ?? [], ...addition.rules ?? []]);
|
|
4671
|
+
const binding = {};
|
|
4672
|
+
if (skills.length > 0) binding.skills = skills;
|
|
4673
|
+
if (rules.length > 0) binding.rules = rules;
|
|
4674
|
+
merged[stage] = binding;
|
|
4675
|
+
changed = true;
|
|
4676
|
+
}
|
|
4677
|
+
if (!changed) return base;
|
|
4678
|
+
return { ...base, stage_bindings: merged };
|
|
4679
|
+
}
|
|
4680
|
+
function resolveFlow(flow, override) {
|
|
4681
|
+
const preset2 = FLOW_PRESETS[flow];
|
|
4682
|
+
if (preset2 === void 0) {
|
|
4683
|
+
return { ok: false, code: "UNKNOWN_FLOW", flow, knownFlows: Object.keys(FLOW_PRESETS) };
|
|
4652
4684
|
}
|
|
4653
|
-
return
|
|
4685
|
+
return { ok: true, config: mergeBindings(preset2.config, override?.stage_bindings), preset: preset2 };
|
|
4654
4686
|
}
|
|
4655
4687
|
|
|
4656
4688
|
// src/client/shared.ts
|
|
@@ -4680,6 +4712,10 @@ function describeError(error) {
|
|
|
4680
4712
|
|
|
4681
4713
|
// src/client/TaskEngineSection.tsx
|
|
4682
4714
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
4715
|
+
function resolvedConfig(flow, stageBindings) {
|
|
4716
|
+
const resolved = resolveFlow(flow, { stage_bindings: stageBindings });
|
|
4717
|
+
return resolved.ok ? resolved.config : FLOW_PRESETS.standard.config;
|
|
4718
|
+
}
|
|
4683
4719
|
var cardV = {
|
|
4684
4720
|
display: "flex",
|
|
4685
4721
|
flexDirection: "column",
|
|
@@ -4732,14 +4768,14 @@ function TaskEngineSection(props) {
|
|
|
4732
4768
|
(0, import_react.useEffect)(() => {
|
|
4733
4769
|
refreshCatalogs();
|
|
4734
4770
|
}, [refreshCatalogs]);
|
|
4735
|
-
const stages = (0, import_react.useMemo)(() => (
|
|
4771
|
+
const stages = (0, import_react.useMemo)(() => (FLOW_PRESETS[flow] ?? FLOW_PRESETS.standard).config.stages, [flow]);
|
|
4736
4772
|
const problems = (0, import_react.useMemo)(
|
|
4737
|
-
() => validateWorkflow(
|
|
4773
|
+
() => validateWorkflow(resolvedConfig(flow, stageBindings)),
|
|
4738
4774
|
[flow, stageBindings]
|
|
4739
4775
|
);
|
|
4740
4776
|
const selectFlow = (id) => {
|
|
4741
4777
|
setFlow(id);
|
|
4742
|
-
setStageBindings({ ...
|
|
4778
|
+
setStageBindings({ ...FLOW_PRESETS[id]?.config.stage_bindings ?? {} });
|
|
4743
4779
|
};
|
|
4744
4780
|
if (loadError !== "") {
|
|
4745
4781
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.wrap, children: [
|
|
@@ -4769,8 +4805,8 @@ function TaskEngineSection(props) {
|
|
|
4769
4805
|
}, title: option.description, children: option.label }, option.id)) }),
|
|
4770
4806
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.hint, children: FLOW_OPTIONS.find((option) => option.id === flow)?.description })
|
|
4771
4807
|
] }),
|
|
4772
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SectionCard, { icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconBranchOutline16, { size: 16 }), title: "\u6D41\u7A0B\u8282\u70B9", hint: "\u8BE5\u6D41\u7A0B\u9884\u8BBE\u56FA\u5B9A\u7684\u9636\u6BB5\u987A\u5E8F\uFF1B\u6539\u53D8\u6D41\u7A0B\u8BF7\u5207\u6362\u4E0A\u9762\u7684\u9884\u8BBE\u3002", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.chips, children: stages.map((stage) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Pill, { active: stage === (
|
|
4773
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SectionCard, { icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconSettingsOutline16, { size: 16 }), title: "\u9636\u6BB5\u6280\u80FD / \u89C4\u5219", hint: "\u9009\u4E00\u4E2A\u8282\u70B9\uFF0C\u52FE\u9009\u5B83\u300C\u7528\u4EC0\u4E48 skill\uFF08\u6280\u80FD\uFF09\u300D\u548C\u300C\u5B88\u54EA\u6761 rule\uFF08\u89C4\u5219\uFF09\u300D\u3002\
|
|
4808
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SectionCard, { icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconBranchOutline16, { size: 16 }), title: "\u6D41\u7A0B\u8282\u70B9", hint: "\u8BE5\u6D41\u7A0B\u9884\u8BBE\u56FA\u5B9A\u7684\u9636\u6BB5\u987A\u5E8F\uFF1B\u6539\u53D8\u6D41\u7A0B\u8BF7\u5207\u6362\u4E0A\u9762\u7684\u9884\u8BBE\u3002", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.chips, children: stages.map((stage) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Pill, { active: stage === (FLOW_PRESETS[flow]?.config.start_stage ?? ""), title: stage === FLOW_PRESETS[flow]?.config.start_stage ? "\u8D77\u59CB\u9636\u6BB5" : void 0, children: stage }, stage)) }) }),
|
|
4809
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SectionCard, { icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconSettingsOutline16, { size: 16 }), title: "\u9636\u6BB5\u6280\u80FD / \u89C4\u5219", hint: "\u9009\u4E00\u4E2A\u8282\u70B9\uFF0C\u52FE\u9009\u5B83\u300C\u7528\u4EC0\u4E48 skill\uFF08\u6280\u80FD\uFF09\u300D\u548C\u300C\u5B88\u54EA\u6761 rule\uFF08\u89C4\u5219\uFF09\u300D\u3002\u6D41\u7A0B\u81EA\u5E26\u7684\u9ED8\u8BA4\u7ED1\u5B9A\u4E0D\u4F1A\u56E0\u53D6\u6D88\u52FE\u9009\u800C\u79FB\u9664\uFF08\u53EA\u4F1A\u4FDD\u7559\u5E76\u8FFD\u52A0\u4F60\u65B0\u52FE\u9009\u7684\uFF09\uFF1B\u8981\u65B0\u5EFA\u6216\u6539\u6B63\u6587\uFF0C\u5207\u5230\u4E0A\u65B9\u7684\u300C\u6280\u80FD\u300D/\u300C\u89C4\u5219\u300D\u6807\u7B7E\u9875\u3002", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BindingEditor, { stages, stageBindings, setStageBindings, skills, rules }) }),
|
|
4774
4810
|
problems.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.problems, children: [
|
|
4775
4811
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: styles.problemsTitle, children: [
|
|
4776
4812
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.StateDot, { state: "error" }),
|