@godv61/dsh-task-engine 0.5.3 → 0.6.1
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 +25 -3
- package/defaults/eng.json +8 -1
- package/lib/client.js +359 -9
- package/lib/client.js.map +2 -2
- package/lib/controller.d.ts +82 -3
- package/lib/controller.js +175 -3
- package/lib/controller.js.map +1 -1
- package/lib/engine.d.ts +11 -0
- package/lib/engine.js +22 -0
- package/lib/engine.js.map +1 -1
- package/lib/index.js +89 -3
- package/lib/index.js.map +1 -1
- package/package.json +3 -2
- package/rules/coding-conventions.md +7 -0
- package/rules/commit-conventions.md +6 -0
- package/rules/security-redlines.md +6 -0
- package/skills/code-commit/SKILL.md +13 -0
- package/skills/code-implement/SKILL.md +16 -0
- package/skills/code-review/SKILL.md +13 -0
- package/skills/code-verify/SKILL.md +13 -0
- package/skills/requirement-analysis/SKILL.md +16 -0
- package/skills/solution-design/SKILL.md +16 -0
package/README.md
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
- **产物门**:每个阶段可声明必交产物 + 必填字段(需求说明 / 设计文档 / 评审记录…),字段没填全 → 不让流转。
|
|
10
10
|
- **提交门禁**:到检查点才能提交,消息必须匹配 `message_pattern`,`manual` 策略永不自动提交。
|
|
11
11
|
- **文件范围**:任务声明 `files`(本任务该改的文件),提交碰了范围外的文件 → 工具和 git 钩子都拒绝。
|
|
12
|
+
- **skill / rule 挂载(0.6.0)**:每个阶段可挂「这个阶段用什么 skill」+「守哪条 rule」;模型走到该阶段时,`dev_task` 只**渐进披露**这阶段挂载的内容,不一次性全给。内置一套通用库,也能在网页里新建自己的 skill/rule。
|
|
12
13
|
|
|
13
14
|
## 目录
|
|
14
15
|
|
|
@@ -19,8 +20,9 @@ hooks/commit-msg git 提交门禁钩子(install_hook 装进 .git/hooks/
|
|
|
19
20
|
src/engine.ts 纯函数状态机 + 配置校验(无 harness 依赖,双端复用)
|
|
20
21
|
src/index.ts 插件(host):注册 dev_task 工具 + 技能 + 挂 task-engine Remote 控制器
|
|
21
22
|
src/controller.ts Host 端 Remote 控制器:网页读写 .dsh/eng.json
|
|
22
|
-
src/client/ 浏览器半:设置页「工程流程配置」(表单 + 实时校验 +
|
|
23
|
-
skills/
|
|
23
|
+
src/client/ 浏览器半:设置页「工程流程配置」(表单 + 实时校验 + 保存 + 挂载/新建)
|
|
24
|
+
skills/ 内置技能库(需求分析/方案设计/实现/验证/审核/提交/交付编排)
|
|
25
|
+
rules/ 内置规则库(编码规范/提交规范/安全红线)
|
|
24
26
|
preset/preset.yml 预设元数据
|
|
25
27
|
preset/persona.md 预设 persona 文案(复制粘贴用)
|
|
26
28
|
```
|
|
@@ -86,6 +88,24 @@ dsh plugin --profile <name> add .
|
|
|
86
88
|
|
|
87
89
|
> 纯 headless 装机不受影响(只是没有这个页);Web profile 需要包含 `@deepseek-ai/dsh-web-app`。
|
|
88
90
|
|
|
91
|
+
## skill / rule 挂载(0.6.0)
|
|
92
|
+
|
|
93
|
+
流程不止"走到哪个阶段",还有"这个阶段该用哪本手册"。每个阶段可以在 `stage_bindings` 里挂 skill 和 rule:
|
|
94
|
+
|
|
95
|
+
```json
|
|
96
|
+
{
|
|
97
|
+
"stage_bindings": {
|
|
98
|
+
"需求评审": { "skills": ["requirement-analysis"], "rules": ["security-redlines"] },
|
|
99
|
+
"开发": { "skills": ["code-implement"], "rules": ["coding-conventions"] }
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
- **渐进披露**:模型走到某阶段时,`dev_task`(`status` / `advance`)只返回**这个阶段**挂载的 skill 名 + rule 内容;skill 用 DSH 的 `skill` 工具按名加载,rule 直接把正文给出。阶段推进到哪,才给哪。
|
|
105
|
+
- **三层来源**:技能和规则都来自「内置 + 项目 + 用户」三层——内置(本包 `skills/`、`rules/`)、项目(`.dsh/skills/`、`.dsh/rules/`)、用户(`$DSH_HOME/skills/`、`$DSH_HOME/rules/`),同名时项目优先于用户优先于内置。
|
|
106
|
+
- **网页新建**:设置页「新建 skill / rule」填 name + description + 正文,即可写进项目 `.dsh/`(团队共享)或用户 `$DSH_HOME/`(个人全局),写好后自动出现在挂载清单里。
|
|
107
|
+
- **内置库**:6 个节点技能(`requirement-analysis` / `solution-design` / `code-implement` / `code-verify` / `code-review` / `code-commit`)+ 3 条规则(`coding-conventions` / `commit-conventions` / `security-redlines`),开箱即用;想加项目专属的,用 DSH 原生技能机制或网页新建即可。
|
|
108
|
+
|
|
89
109
|
## git 提交门禁(防止绕过)
|
|
90
110
|
|
|
91
111
|
默认提交是「工具校验 + 模型执行 git」,模型理论上能绕过 `dev_task` 直接 `git commit`。装个机械钩子彻底封死:
|
|
@@ -99,4 +119,6 @@ dsh plugin --profile <name> add .
|
|
|
99
119
|
|
|
100
120
|
- **脚本级已验证**:strict `tsc` typecheck/build 零错误;`dsh plugin add` 装进独立实例、`--dump-config` 确认 `task-engine` 进组合树;`validateWorkflow`(配置校验)、`artifacts_present`(产物门)、`file_scope`(文件范围门)、`hooks/commit-msg`(机械门禁)单测/冒烟全过——非法配置逐条报错、产物没填全挡流转、范围外文件挡提交、钩子该放放该拦拦。
|
|
101
121
|
- **真实模型端到端(0.4.1)**:headless + NewAPI DeepSeek 下让真模型走 `dev_task` 全流程,抓到并修掉一个真实 bug——`readText`/`writeText` 调 `fs.resolve()` 漏了 `await`,把 `Promise<FsTarget>` 当 `target` 传给了读写方法,导致 create/record/advance/commit 全部写不了任务文件、读永远返回 undefined。0.4.1 修复(`await fs.resolve(relPath)`),并把 `task_id` 在 create 也必填的说明补进工具 schema 与技能。修复后走真实 `ctx.fs` 路径冒烟全绿。
|
|
102
|
-
- **网页图形化配置界面(0.5.0)**:新增 `src/client/` 设置页「工程流程配置」+ Host 端 `task-engine` Remote 控制器;`@godv61/dsh-task-engine` 升级为双端包(`dsh.client` manifest + `./client` 出品,`exports` 暴露)。已实机验证:`dsh web` 起服务后 boot 数据里 `@godv61/dsh-task-engine` 以 `inject:["@deepseek-ai/dsh-api-gateway"]` 进入 application batch、`/plugins/…/client.js` 正常服务;headless 冒烟确认 boot + `dev_task` 未被新控制器破坏。浏览器点击级 e2e 留到发布后用真浏览器收尾。
|
|
122
|
+
- **网页图形化配置界面(0.5.0)**:新增 `src/client/` 设置页「工程流程配置」+ Host 端 `task-engine` Remote 控制器;`@godv61/dsh-task-engine` 升级为双端包(`dsh.client` manifest + `./client` 出品,`exports` 暴露)。已实机验证:`dsh web` 起服务后 boot 数据里 `@godv61/dsh-task-engine` 以 `inject:["@deepseek-ai/dsh-api-gateway"]` 进入 application batch、`/plugins/…/client.js` 正常服务;headless 冒烟确认 boot + `dev_task` 未被新控制器破坏。浏览器点击级 e2e 留到发布后用真浏览器收尾。
|
|
123
|
+
- **skill/rule 挂载与渐进披露(0.6.0)**:`WorkflowConfig` 新增 `stage_bindings`(每阶段挂 skills/rules,可选字段),`dev_task` 的 `status`/`advance` 按当前阶段披露挂载的 skill 名 + rule 正文;内置 6 技能 + 3 规则库;Host 控制器新增 `listSkills`/`listRules`/`writeSkill`/`writeRule`;设置页新增「节点挂载」和「新建 skill / rule」两块,同时补上 `dev_task` 缺失的 `items` 操作(更新实施项状态)。引擎层 `stage_bindings` 校验(未知阶段/空名)与合并已单测通过。
|
|
124
|
+
- **配置页精简 + 自建 skill 可观测(0.6.1)**:设置页的流转/产物/提交规则/新建默认折叠,「节点挂载」从六阶段全平铺改成「选一个阶段再看它挂了什么」;新建成功提示带回显路径(`.dsh/skills/<name>/SKILL.md` 或 `$DSH_HOME/…`),挂载清单给非内置的 skill/rule 标「(项目)/(用户)」来源。修复 `listSkills` 依赖 host skill registry 导致项目 `.dsh/skills` 自建技能不显示的问题——改为与 `listRules` 一致,直接扫「内置 + 项目 + 用户」三层目录。浏览器 e2e 全绿。
|
package/defaults/eng.json
CHANGED
|
@@ -20,5 +20,12 @@
|
|
|
20
20
|
"checkpoints": ["交付"],
|
|
21
21
|
"file_scope": true
|
|
22
22
|
},
|
|
23
|
-
"high_risk_requires_verification": true
|
|
23
|
+
"high_risk_requires_verification": true,
|
|
24
|
+
"stage_bindings": {
|
|
25
|
+
"需求评审": { "skills": ["requirement-analysis"], "rules": ["security-redlines"] },
|
|
26
|
+
"设计": { "skills": ["solution-design"] },
|
|
27
|
+
"开发": { "skills": ["code-implement"], "rules": ["coding-conventions"] },
|
|
28
|
+
"交付": { "skills": ["code-verify", "code-commit"], "rules": ["coding-conventions", "commit-conventions"] },
|
|
29
|
+
"代码审核": { "skills": ["code-review"], "rules": ["security-redlines"] }
|
|
30
|
+
}
|
|
24
31
|
}
|
package/lib/client.js
CHANGED
|
@@ -4088,13 +4088,18 @@ var commitSchema = external_exports.object({
|
|
|
4088
4088
|
checkpoints: external_exports.array(external_exports.string()),
|
|
4089
4089
|
file_scope: external_exports.boolean()
|
|
4090
4090
|
});
|
|
4091
|
+
var stageBindingSchema = external_exports.object({
|
|
4092
|
+
skills: external_exports.array(external_exports.string()).optional(),
|
|
4093
|
+
rules: external_exports.array(external_exports.string()).optional()
|
|
4094
|
+
});
|
|
4091
4095
|
var configSchema = external_exports.object({
|
|
4092
4096
|
stages: external_exports.array(external_exports.string()),
|
|
4093
4097
|
start_stage: external_exports.string(),
|
|
4094
4098
|
transitions: external_exports.array(transitionSchema),
|
|
4095
4099
|
artifacts: external_exports.array(artifactSchema),
|
|
4096
4100
|
commit: commitSchema,
|
|
4097
|
-
high_risk_requires_verification: external_exports.boolean()
|
|
4101
|
+
high_risk_requires_verification: external_exports.boolean(),
|
|
4102
|
+
stage_bindings: external_exports.record(external_exports.string(), stageBindingSchema).optional()
|
|
4098
4103
|
});
|
|
4099
4104
|
var viewSchema = external_exports.object({
|
|
4100
4105
|
ok: external_exports.boolean(),
|
|
@@ -4106,6 +4111,39 @@ var writeRequestSchema = external_exports.object({
|
|
|
4106
4111
|
path: external_exports.string(),
|
|
4107
4112
|
config: configSchema
|
|
4108
4113
|
});
|
|
4114
|
+
var skillCatalogSchema = external_exports.object({
|
|
4115
|
+
skills: external_exports.array(external_exports.object({
|
|
4116
|
+
name: external_exports.string(),
|
|
4117
|
+
description: external_exports.string(),
|
|
4118
|
+
source: external_exports.string()
|
|
4119
|
+
}))
|
|
4120
|
+
});
|
|
4121
|
+
var ruleCatalogSchema = external_exports.object({
|
|
4122
|
+
rules: external_exports.array(external_exports.object({
|
|
4123
|
+
name: external_exports.string(),
|
|
4124
|
+
source: external_exports.string()
|
|
4125
|
+
}))
|
|
4126
|
+
});
|
|
4127
|
+
var writeSkillRequestSchema = external_exports.object({
|
|
4128
|
+
name: external_exports.string(),
|
|
4129
|
+
description: external_exports.string(),
|
|
4130
|
+
whenToUse: external_exports.string().optional(),
|
|
4131
|
+
content: external_exports.string(),
|
|
4132
|
+
level: external_exports.enum(["project", "user"]),
|
|
4133
|
+
path: external_exports.string().optional()
|
|
4134
|
+
});
|
|
4135
|
+
var writeRuleRequestSchema = external_exports.object({
|
|
4136
|
+
name: external_exports.string(),
|
|
4137
|
+
content: external_exports.string(),
|
|
4138
|
+
level: external_exports.enum(["project", "user"]),
|
|
4139
|
+
path: external_exports.string().optional()
|
|
4140
|
+
});
|
|
4141
|
+
var writeResourceResultSchema = external_exports.object({
|
|
4142
|
+
ok: external_exports.boolean(),
|
|
4143
|
+
name: external_exports.string(),
|
|
4144
|
+
path: external_exports.string(),
|
|
4145
|
+
error: external_exports.string().optional()
|
|
4146
|
+
});
|
|
4109
4147
|
var PACKAGE = "@godv61/dsh-task-engine";
|
|
4110
4148
|
var TYPERT_REMOTE = {
|
|
4111
4149
|
package: PACKAGE,
|
|
@@ -4141,6 +4179,70 @@ var TYPERT_REMOTE = {
|
|
|
4141
4179
|
}
|
|
4142
4180
|
],
|
|
4143
4181
|
result: { mode: "strict", typeSymbol: `${PACKAGE}/types#EngConfigView`, schema: viewSchema }
|
|
4182
|
+
},
|
|
4183
|
+
{
|
|
4184
|
+
id: `${PACKAGE}#task-engine/listSkills`,
|
|
4185
|
+
service: "taskEngineController",
|
|
4186
|
+
namespace: "task-engine",
|
|
4187
|
+
method: "listSkills",
|
|
4188
|
+
invocation: { kind: "direct" },
|
|
4189
|
+
parameters: [
|
|
4190
|
+
{
|
|
4191
|
+
name: "path",
|
|
4192
|
+
wire: "path",
|
|
4193
|
+
source: "json",
|
|
4194
|
+
codec: { mode: "strict", typeSymbol: "string", schema: external_exports.string() }
|
|
4195
|
+
}
|
|
4196
|
+
],
|
|
4197
|
+
result: { mode: "strict", typeSymbol: `${PACKAGE}/types#SkillCatalog`, schema: skillCatalogSchema }
|
|
4198
|
+
},
|
|
4199
|
+
{
|
|
4200
|
+
id: `${PACKAGE}#task-engine/listRules`,
|
|
4201
|
+
service: "taskEngineController",
|
|
4202
|
+
namespace: "task-engine",
|
|
4203
|
+
method: "listRules",
|
|
4204
|
+
invocation: { kind: "direct" },
|
|
4205
|
+
parameters: [
|
|
4206
|
+
{
|
|
4207
|
+
name: "path",
|
|
4208
|
+
wire: "path",
|
|
4209
|
+
source: "json",
|
|
4210
|
+
codec: { mode: "strict", typeSymbol: "string", schema: external_exports.string() }
|
|
4211
|
+
}
|
|
4212
|
+
],
|
|
4213
|
+
result: { mode: "strict", typeSymbol: `${PACKAGE}/types#RuleCatalog`, schema: ruleCatalogSchema }
|
|
4214
|
+
},
|
|
4215
|
+
{
|
|
4216
|
+
id: `${PACKAGE}#task-engine/writeSkill`,
|
|
4217
|
+
service: "taskEngineController",
|
|
4218
|
+
namespace: "task-engine",
|
|
4219
|
+
method: "writeSkill",
|
|
4220
|
+
invocation: { kind: "direct" },
|
|
4221
|
+
parameters: [
|
|
4222
|
+
{
|
|
4223
|
+
name: "request",
|
|
4224
|
+
wire: "request",
|
|
4225
|
+
source: "json",
|
|
4226
|
+
codec: { mode: "strict", typeSymbol: `${PACKAGE}/types#WriteSkillRequest`, schema: writeSkillRequestSchema }
|
|
4227
|
+
}
|
|
4228
|
+
],
|
|
4229
|
+
result: { mode: "strict", typeSymbol: `${PACKAGE}/types#WriteResourceResult`, schema: writeResourceResultSchema }
|
|
4230
|
+
},
|
|
4231
|
+
{
|
|
4232
|
+
id: `${PACKAGE}#task-engine/writeRule`,
|
|
4233
|
+
service: "taskEngineController",
|
|
4234
|
+
namespace: "task-engine",
|
|
4235
|
+
method: "writeRule",
|
|
4236
|
+
invocation: { kind: "direct" },
|
|
4237
|
+
parameters: [
|
|
4238
|
+
{
|
|
4239
|
+
name: "request",
|
|
4240
|
+
wire: "request",
|
|
4241
|
+
source: "json",
|
|
4242
|
+
codec: { mode: "strict", typeSymbol: `${PACKAGE}/types#WriteRuleRequest`, schema: writeRuleRequestSchema }
|
|
4243
|
+
}
|
|
4244
|
+
],
|
|
4245
|
+
result: { mode: "strict", typeSymbol: `${PACKAGE}/types#WriteResourceResult`, schema: writeResourceResultSchema }
|
|
4144
4246
|
}
|
|
4145
4247
|
]
|
|
4146
4248
|
};
|
|
@@ -4206,6 +4308,22 @@ function validateWorkflow(config) {
|
|
|
4206
4308
|
fieldSet.add(field);
|
|
4207
4309
|
}
|
|
4208
4310
|
});
|
|
4311
|
+
const bindings = config.stage_bindings ?? {};
|
|
4312
|
+
for (const [stage, binding] of Object.entries(bindings)) {
|
|
4313
|
+
if (!config.stages.includes(stage)) {
|
|
4314
|
+
problems.push(`stage_bindings: stage "${stage}" is not a stage`);
|
|
4315
|
+
}
|
|
4316
|
+
for (const skill of binding.skills ?? []) {
|
|
4317
|
+
if (typeof skill !== "string" || skill.trim() === "") {
|
|
4318
|
+
problems.push(`stage_bindings "${stage}": empty skill name`);
|
|
4319
|
+
}
|
|
4320
|
+
}
|
|
4321
|
+
for (const rule of binding.rules ?? []) {
|
|
4322
|
+
if (typeof rule !== "string" || rule.trim() === "") {
|
|
4323
|
+
problems.push(`stage_bindings "${stage}": empty rule name`);
|
|
4324
|
+
}
|
|
4325
|
+
}
|
|
4326
|
+
}
|
|
4209
4327
|
if (!["task", "item", "manual"].includes(config.commit.policy)) {
|
|
4210
4328
|
problems.push(`commit.policy "${config.commit.policy}" is not task|item|manual`);
|
|
4211
4329
|
}
|
|
@@ -4454,7 +4572,14 @@ var STANDARD = {
|
|
|
4454
4572
|
checkpoints: ["\u4EA4\u4ED8"],
|
|
4455
4573
|
file_scope: true
|
|
4456
4574
|
},
|
|
4457
|
-
high_risk_requires_verification: true
|
|
4575
|
+
high_risk_requires_verification: true,
|
|
4576
|
+
stage_bindings: {
|
|
4577
|
+
"\u9700\u6C42\u8BC4\u5BA1": { skills: ["requirement-analysis"], rules: ["security-redlines"] },
|
|
4578
|
+
"\u8BBE\u8BA1": { skills: ["solution-design"] },
|
|
4579
|
+
"\u5F00\u53D1": { skills: ["code-implement"], rules: ["coding-conventions"] },
|
|
4580
|
+
"\u4EA4\u4ED8": { skills: ["code-verify", "code-commit"], rules: ["coding-conventions", "commit-conventions"] },
|
|
4581
|
+
"\u4EE3\u7801\u5BA1\u6838": { skills: ["code-review"], rules: ["security-redlines"] }
|
|
4582
|
+
}
|
|
4458
4583
|
};
|
|
4459
4584
|
var AGILE = {
|
|
4460
4585
|
stages: ["\u9700\u6C42", "\u5F00\u53D1", "\u4EA4\u4ED8", "\u5BA1\u67E5"],
|
|
@@ -4474,7 +4599,13 @@ var AGILE = {
|
|
|
4474
4599
|
checkpoints: ["\u4EA4\u4ED8"],
|
|
4475
4600
|
file_scope: true
|
|
4476
4601
|
},
|
|
4477
|
-
high_risk_requires_verification: false
|
|
4602
|
+
high_risk_requires_verification: false,
|
|
4603
|
+
stage_bindings: {
|
|
4604
|
+
"\u9700\u6C42": { skills: ["requirement-analysis"] },
|
|
4605
|
+
"\u5F00\u53D1": { skills: ["code-implement"], rules: ["coding-conventions"] },
|
|
4606
|
+
"\u4EA4\u4ED8": { skills: ["code-verify", "code-commit"], rules: ["commit-conventions"] },
|
|
4607
|
+
"\u5BA1\u67E5": { skills: ["code-review"] }
|
|
4608
|
+
}
|
|
4478
4609
|
};
|
|
4479
4610
|
var MINIMAL = {
|
|
4480
4611
|
stages: ["\u5F00\u53D1", "\u4EA4\u4ED8"],
|
|
@@ -4490,7 +4621,11 @@ var MINIMAL = {
|
|
|
4490
4621
|
checkpoints: ["\u4EA4\u4ED8"],
|
|
4491
4622
|
file_scope: false
|
|
4492
4623
|
},
|
|
4493
|
-
high_risk_requires_verification: false
|
|
4624
|
+
high_risk_requires_verification: false,
|
|
4625
|
+
stage_bindings: {
|
|
4626
|
+
"\u5F00\u53D1": { skills: ["code-implement"] },
|
|
4627
|
+
"\u4EA4\u4ED8": { skills: ["code-commit"], rules: ["commit-conventions"] }
|
|
4628
|
+
}
|
|
4494
4629
|
};
|
|
4495
4630
|
var WORKFLOW_TEMPLATES = [
|
|
4496
4631
|
{ id: "standard", label: "\u6807\u51C6\u7814\u53D1", description: "\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", config: STANDARD },
|
|
@@ -4534,6 +4669,22 @@ var styles = {
|
|
|
4534
4669
|
padding: "8px 10px"
|
|
4535
4670
|
},
|
|
4536
4671
|
inline: { display: "inline-flex", alignItems: "center", gap: 6, marginRight: 8 },
|
|
4672
|
+
textarea: {
|
|
4673
|
+
background: "var(--dsw-alias-bg-layer-1)",
|
|
4674
|
+
border: `1px solid ${border2}`,
|
|
4675
|
+
borderRadius: 8,
|
|
4676
|
+
padding: "8px 10px",
|
|
4677
|
+
color: text,
|
|
4678
|
+
fontSize: 13,
|
|
4679
|
+
minHeight: 90,
|
|
4680
|
+
resize: "vertical",
|
|
4681
|
+
fontFamily: "inherit",
|
|
4682
|
+
width: "100%",
|
|
4683
|
+
boxSizing: "border-box"
|
|
4684
|
+
},
|
|
4685
|
+
sourceBadge: { color: textTertiary2, fontSize: 11 },
|
|
4686
|
+
bindingStage: { display: "flex", flexDirection: "column", gap: 6 },
|
|
4687
|
+
bindingLabel: { color: text, fontSize: 13, fontWeight: 600 },
|
|
4537
4688
|
problems: {
|
|
4538
4689
|
display: "flex",
|
|
4539
4690
|
flexDirection: "column",
|
|
@@ -4601,6 +4752,8 @@ function TaskEngineSection(props) {
|
|
|
4601
4752
|
const [savedAt, setSavedAt] = (0, import_react2.useState)("");
|
|
4602
4753
|
const [loadError, setLoadError] = (0, import_react2.useState)("");
|
|
4603
4754
|
const [loadedProblems, setLoadedProblems] = (0, import_react2.useState)([]);
|
|
4755
|
+
const [skills, setSkills] = (0, import_react2.useState)([]);
|
|
4756
|
+
const [rules, setRules] = (0, import_react2.useState)([]);
|
|
4604
4757
|
(0, import_react2.useEffect)(() => {
|
|
4605
4758
|
if (workspaces.length > 0 && workspace === "") {
|
|
4606
4759
|
setWorkspace(workspaces[0].path);
|
|
@@ -4627,6 +4780,20 @@ function TaskEngineSection(props) {
|
|
|
4627
4780
|
alive = false;
|
|
4628
4781
|
};
|
|
4629
4782
|
}, [remote, workspace]);
|
|
4783
|
+
const refreshCatalogs = (0, import_react2.useCallback)(() => {
|
|
4784
|
+
if (workspace === "") return;
|
|
4785
|
+
void remote.listSkills(workspace).then((result) => {
|
|
4786
|
+
if (result.ok) setSkills(result.value.skills);
|
|
4787
|
+
}, () => {
|
|
4788
|
+
});
|
|
4789
|
+
void remote.listRules(workspace).then((result) => {
|
|
4790
|
+
if (result.ok) setRules(result.value.rules);
|
|
4791
|
+
}, () => {
|
|
4792
|
+
});
|
|
4793
|
+
}, [remote, workspace]);
|
|
4794
|
+
(0, import_react2.useEffect)(() => {
|
|
4795
|
+
refreshCatalogs();
|
|
4796
|
+
}, [refreshCatalogs]);
|
|
4630
4797
|
const problems = (0, import_react2.useMemo)(() => config === null ? [] : validateWorkflow(config), [config]);
|
|
4631
4798
|
const notice = problems.length === 0 && loadedProblems.length > 0 ? loadedProblems : [];
|
|
4632
4799
|
const addTransition = (from, to) => {
|
|
@@ -4690,9 +4857,11 @@ function TaskEngineSection(props) {
|
|
|
4690
4857
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(TemplatePicker, { config, setConfig }),
|
|
4691
4858
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.flowCard, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FlowDiagram, { config, onAddTransition: addTransition, onRemoveTransition: removeTransition }) }),
|
|
4692
4859
|
/* @__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", hint: "\u6D41\u7A0B\u7531\u8FD9\u4E9B\u9636\u6BB5\u6309\u987A\u5E8F\u7EC4\u6210\u3002\u70B9\u4E00\u4E2A\u6807\u7B7E\u53EF\u5220\u9664\u5B83\uFF08\u8D77\u59CB\u9636\u6BB5\u9664\u5916\uFF09\uFF1B\u7528\u4E2D\u6587\u540D\u66F4\u6613\u61C2\uFF0C\u4F8B\u5982\u300C\u9700\u6C42\u8BC4\u5BA1\u300D\u300C\u5F00\u53D1\u300D\u3002", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StageEditor, { config, setConfig }) }),
|
|
4693
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SectionCard, { icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconBranchOutline16, { size: 16 }), title: "\u6D41\u8F6C\uFF08\u9636\u6BB5 \u2192 \u9636\u6BB5\uFF0C\u53EF\u5E26\u5B88\u536B\uFF09", hint: "\u6BCF\u6761\u6D41\u8F6C = \u4ECE\u300C\u4E0A\u4E00\u6B65\u300D\u5230\u300C\u4E0B\u4E00\u6B65\u300D\u5141\u8BB8\u8D70\u7684\u8DEF\uFF1B\u53EF\u9644\u52A0\u5B88\u536B\uFF0C\u6EE1\u8DB3\u5B88\u536B\u624D\u653E\u884C\u3002\u4E5F\u53EF\u5728\u6D41\u7A0B\u56FE\u91CC\u76F4\u63A5\u8FDE\u7EBF/\u70B9\u7BAD\u5934\u5220\u9664\u3002", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TransitionEditor, { config, setConfig }) }),
|
|
4694
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SectionCard, { icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconCheckOutline16, { size: 16 }), title: "\u4EA7\u7269\uFF08\u6BCF\u4E2A\u9636\u6BB5\u8981\u586B\u7684\u5B57\u6BB5\uFF09", hint: "\u7ED9\u67D0\u9636\u6BB5\u58F0\u660E\u8981\u4EA4\u7684\u4EA7\u7269\u548C\u5FC5\u586B\u5B57\u6BB5\uFF1B\u914D\u5408\u6D41\u8F6C\u91CC\u7684\u300C\u4EA7\u7269\u9F50\u5168\u300D\u5B88\u536B\uFF0C\u5B57\u6BB5\u6CA1\u586B\u5168\u5C31\u8FC7\u4E0D\u53BB\u3002", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ArtifactEditor, { config, setConfig }) }),
|
|
4695
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SectionCard, { icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconEditOutline16, { size: 16 }), title: "\u63D0\u4EA4\u89C4\u5219", hint: "\u63D0\u4EA4\u7B56\u7565\u3001\u6D88\u606F\u683C\u5F0F\u3001\u63D0\u4EA4\u68C0\u67E5\u70B9\u3001\u6587\u4EF6\u8303\u56F4\uFF0C\u4EE5\u53CA\u9AD8\u98CE\u9669\u662F\u5426\u5FC5\u987B\u9644\u9A8C\u8BC1\u8BC1\u636E\u3002", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CommitEditor, { config, setConfig }) }),
|
|
4860
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SectionCard, { icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconBranchOutline16, { size: 16 }), title: "\u6D41\u8F6C\uFF08\u9636\u6BB5 \u2192 \u9636\u6BB5\uFF0C\u53EF\u5E26\u5B88\u536B\uFF09", defaultOpen: false, hint: "\u6BCF\u6761\u6D41\u8F6C = \u4ECE\u300C\u4E0A\u4E00\u6B65\u300D\u5230\u300C\u4E0B\u4E00\u6B65\u300D\u5141\u8BB8\u8D70\u7684\u8DEF\uFF1B\u53EF\u9644\u52A0\u5B88\u536B\uFF0C\u6EE1\u8DB3\u5B88\u536B\u624D\u653E\u884C\u3002\u4E5F\u53EF\u5728\u6D41\u7A0B\u56FE\u91CC\u76F4\u63A5\u8FDE\u7EBF/\u70B9\u7BAD\u5934\u5220\u9664\u3002", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TransitionEditor, { config, setConfig }) }),
|
|
4861
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SectionCard, { icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconCheckOutline16, { size: 16 }), title: "\u4EA7\u7269\uFF08\u6BCF\u4E2A\u9636\u6BB5\u8981\u586B\u7684\u5B57\u6BB5\uFF09", defaultOpen: false, hint: "\u7ED9\u67D0\u9636\u6BB5\u58F0\u660E\u8981\u4EA4\u7684\u4EA7\u7269\u548C\u5FC5\u586B\u5B57\u6BB5\uFF1B\u914D\u5408\u6D41\u8F6C\u91CC\u7684\u300C\u4EA7\u7269\u9F50\u5168\u300D\u5B88\u536B\uFF0C\u5B57\u6BB5\u6CA1\u586B\u5168\u5C31\u8FC7\u4E0D\u53BB\u3002", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ArtifactEditor, { config, setConfig }) }),
|
|
4862
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SectionCard, { icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconEditOutline16, { size: 16 }), title: "\u63D0\u4EA4\u89C4\u5219", defaultOpen: false, hint: "\u63D0\u4EA4\u7B56\u7565\u3001\u6D88\u606F\u683C\u5F0F\u3001\u63D0\u4EA4\u68C0\u67E5\u70B9\u3001\u6587\u4EF6\u8303\u56F4\uFF0C\u4EE5\u53CA\u9AD8\u98CE\u9669\u662F\u5426\u5FC5\u987B\u9644\u9A8C\u8BC1\u8BC1\u636E\u3002", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CommitEditor, { config, setConfig }) }),
|
|
4863
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SectionCard, { icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconBranchOutline16, { size: 16 }), title: "\u8282\u70B9\u6302\u8F7D\uFF08skill / rule\uFF09", hint: "\u7ED9\u6BCF\u4E2A\u9636\u6BB5\u6302\u300C\u8FD9\u4E2A\u9636\u6BB5\u7528\u4EC0\u4E48 skill\u300D\u548C\u300C\u5B88\u54EA\u6761 rule\u300D\u3002\u5927\u6A21\u578B\u8D70\u5230\u8BE5\u9636\u6BB5\u65F6\uFF0Cdev_task \u53EA\u62AB\u9732\u8FD9\u9636\u6BB5\u6302\u8F7D\u7684\u5185\u5BB9\u3002", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BindingEditor, { config, setConfig, skills, rules }) }),
|
|
4864
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SectionCard, { icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconPlusOutline16, { size: 16 }), title: "\u65B0\u5EFA skill / rule", defaultOpen: false, hint: "\u6E05\u5355\u91CC\u6CA1\u6709\u5408\u9002\u7684\u5C31\u5F53\u573A\u65B0\u5EFA\uFF0C\u5199\u5230\u9879\u76EE .dsh/ \u6216\u7528\u6237 $DSH_HOME\uFF1B\u5199\u597D\u540E\u81EA\u52A8\u51FA\u73B0\u5728\u4E0A\u9762\u7684\u6302\u8F7D\u6E05\u5355\u3002", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ResourceCreator, { remote, workspace, onCreated: refreshCatalogs }) }),
|
|
4696
4865
|
problems.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.problems, children: [
|
|
4697
4866
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: styles.problemsTitle, children: [
|
|
4698
4867
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.StateDot, { state: "error" }),
|
|
@@ -4743,8 +4912,8 @@ function sourceText(source) {
|
|
|
4743
4912
|
return "\u5185\u7F6E\u9ED8\u8BA4\u914D\u7F6E\uFF08\u5DE5\u4F5C\u533A\u5C1A\u65E0 .dsh/eng.json\uFF09";
|
|
4744
4913
|
}
|
|
4745
4914
|
}
|
|
4746
|
-
function SectionCard({ icon, title, hint, children }) {
|
|
4747
|
-
const [open, setOpen] = (0, import_react2.useState)(
|
|
4915
|
+
function SectionCard({ icon, title, hint, defaultOpen = true, children }) {
|
|
4916
|
+
const [open, setOpen] = (0, import_react2.useState)(defaultOpen);
|
|
4748
4917
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.section, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
4749
4918
|
import_dsh_client_ui_primitives.DisclosureRow,
|
|
4750
4919
|
{
|
|
@@ -5022,6 +5191,187 @@ function CommitEditor({ config, setConfig }) {
|
|
|
5022
5191
|
] })
|
|
5023
5192
|
] });
|
|
5024
5193
|
}
|
|
5194
|
+
function BindingEditor({ config, setConfig, skills, rules }) {
|
|
5195
|
+
const [stage, setStage] = (0, import_react2.useState)(config.stages[0] ?? "");
|
|
5196
|
+
const currentStage = config.stages.includes(stage) ? stage : config.stages[0] ?? "";
|
|
5197
|
+
const toggleSkill = (skill) => {
|
|
5198
|
+
if (currentStage === "") return;
|
|
5199
|
+
update(config, setConfig, (c) => {
|
|
5200
|
+
const bindings = c.stage_bindings ?? {};
|
|
5201
|
+
const current = bindings[currentStage]?.skills ?? [];
|
|
5202
|
+
const next = current.includes(skill) ? current.filter((s) => s !== skill) : [...current, skill].sort();
|
|
5203
|
+
return { ...c, stage_bindings: { ...bindings, [currentStage]: { ...bindings[currentStage] ?? {}, skills: next } } };
|
|
5204
|
+
});
|
|
5205
|
+
};
|
|
5206
|
+
const toggleRule = (rule) => {
|
|
5207
|
+
if (currentStage === "") return;
|
|
5208
|
+
update(config, setConfig, (c) => {
|
|
5209
|
+
const bindings = c.stage_bindings ?? {};
|
|
5210
|
+
const current = bindings[currentStage]?.rules ?? [];
|
|
5211
|
+
const next = current.includes(rule) ? current.filter((s) => s !== rule) : [...current, rule].sort();
|
|
5212
|
+
return { ...c, stage_bindings: { ...bindings, [currentStage]: { ...bindings[currentStage] ?? {}, rules: next } } };
|
|
5213
|
+
});
|
|
5214
|
+
};
|
|
5215
|
+
if (currentStage === "") {
|
|
5216
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.muted, children: "\u5148\u5728\u300C\u9636\u6BB5\u300D\u91CC\u52A0\u4E00\u4E2A\u9636\u6BB5\uFF0C\u518D\u56DE\u6765\u6302 skill / rule\u3002" });
|
|
5217
|
+
}
|
|
5218
|
+
const boundSkills = config.stage_bindings?.[currentStage]?.skills ?? [];
|
|
5219
|
+
const boundRules = config.stage_bindings?.[currentStage]?.rules ?? [];
|
|
5220
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.section, children: [
|
|
5221
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.field, children: [
|
|
5222
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.fieldLabel, children: "\u9009\u62E9\u9636\u6BB5\uFF08\u6539\u54EA\u4E2A\u9636\u6BB5\u7684\u6302\u8F7D\uFF09" }),
|
|
5223
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.chips, children: config.stages.map((s) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Pill, { active: s === currentStage, onClick: () => {
|
|
5224
|
+
setStage(s);
|
|
5225
|
+
}, children: s }, s)) })
|
|
5226
|
+
] }),
|
|
5227
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: cardV, children: [
|
|
5228
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.bindingStage, children: [
|
|
5229
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.fieldLabel, children: "skill\uFF08\u8FD9\u4E2A\u9636\u6BB5\u505A\u4EC0\u4E48\uFF09" }),
|
|
5230
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.chips, children: skills.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.sourceBadge, children: "\u6682\u65E0\u53EF\u7528 skill\uFF0C\u53EF\u5728\u300C\u65B0\u5EFA skill / rule\u300D\u91CC\u5EFA" }) : skills.map((sk) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_dsh_client_ui_primitives.Pill, { active: boundSkills.includes(sk.name), onClick: () => {
|
|
5231
|
+
toggleSkill(sk.name);
|
|
5232
|
+
}, title: `${sk.description}\uFF08${sourceLabel(sk.source)}\uFF09`, children: [
|
|
5233
|
+
sk.name,
|
|
5234
|
+
sk.source !== "bundled" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: styles.sourceBadge, children: [
|
|
5235
|
+
"\uFF08",
|
|
5236
|
+
sourceLabel(sk.source),
|
|
5237
|
+
"\uFF09"
|
|
5238
|
+
] }) : null
|
|
5239
|
+
] }, sk.name)) })
|
|
5240
|
+
] }),
|
|
5241
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.bindingStage, children: [
|
|
5242
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.fieldLabel, children: "rule\uFF08\u8FD9\u4E2A\u9636\u6BB5\u5B88\u4EC0\u4E48\uFF09" }),
|
|
5243
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.chips, children: rules.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.sourceBadge, children: "\u6682\u65E0\u53EF\u7528 rule\uFF0C\u53EF\u5728\u300C\u65B0\u5EFA skill / rule\u300D\u91CC\u5EFA" }) : rules.map((rule) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_dsh_client_ui_primitives.Pill, { active: boundRules.includes(rule.name), onClick: () => {
|
|
5244
|
+
toggleRule(rule.name);
|
|
5245
|
+
}, title: `\u6765\u6E90\uFF1A${sourceLabel(rule.source)}`, children: [
|
|
5246
|
+
rule.name,
|
|
5247
|
+
rule.source !== "bundled" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: styles.sourceBadge, children: [
|
|
5248
|
+
"\uFF08",
|
|
5249
|
+
sourceLabel(rule.source),
|
|
5250
|
+
"\uFF09"
|
|
5251
|
+
] }) : null
|
|
5252
|
+
] }, rule.name)) })
|
|
5253
|
+
] }),
|
|
5254
|
+
boundSkills.length === 0 && boundRules.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.hint, children: "\u8FD9\u4E2A\u9636\u6BB5\u8FD8\u6CA1\u6302\u4EFB\u4F55 skill / rule \u2014\u2014 \u70B9\u4E0A\u9762\u7684\u540D\u79F0\u52FE\u9009\u3002" }) : null
|
|
5255
|
+
] })
|
|
5256
|
+
] });
|
|
5257
|
+
}
|
|
5258
|
+
function ResourceCreator({ remote, workspace, onCreated }) {
|
|
5259
|
+
const [skillName, setSkillName] = (0, import_react2.useState)("");
|
|
5260
|
+
const [skillDesc, setSkillDesc] = (0, import_react2.useState)("");
|
|
5261
|
+
const [skillWhen, setSkillWhen] = (0, import_react2.useState)("");
|
|
5262
|
+
const [skillBody, setSkillBody] = (0, import_react2.useState)("");
|
|
5263
|
+
const [ruleName, setRuleName] = (0, import_react2.useState)("");
|
|
5264
|
+
const [ruleBody, setRuleBody] = (0, import_react2.useState)("");
|
|
5265
|
+
const [level, setLevel] = (0, import_react2.useState)("project");
|
|
5266
|
+
const [msg, setMsg] = (0, import_react2.useState)("");
|
|
5267
|
+
const createSkill = async () => {
|
|
5268
|
+
setMsg("");
|
|
5269
|
+
const result = await remote.writeSkill({
|
|
5270
|
+
name: skillName,
|
|
5271
|
+
description: skillDesc,
|
|
5272
|
+
whenToUse: skillWhen === "" ? void 0 : skillWhen,
|
|
5273
|
+
content: skillBody,
|
|
5274
|
+
level,
|
|
5275
|
+
path: workspace
|
|
5276
|
+
});
|
|
5277
|
+
if (!result.ok) {
|
|
5278
|
+
setMsg("\u65B0\u5EFA skill \u5931\u8D25\uFF1A" + describeError(result.error));
|
|
5279
|
+
return;
|
|
5280
|
+
}
|
|
5281
|
+
if (!result.value.ok) {
|
|
5282
|
+
setMsg("\u65B0\u5EFA skill \u5931\u8D25\uFF1A" + (result.value.error ?? "\u672A\u77E5\u9519\u8BEF"));
|
|
5283
|
+
return;
|
|
5284
|
+
}
|
|
5285
|
+
const loc = level === "project" ? `.dsh/skills/${result.value.name}/SKILL.md` : `$DSH_HOME/skills/${result.value.name}/SKILL.md`;
|
|
5286
|
+
setMsg(`\u5DF2\u65B0\u5EFA skill\u300C${result.value.name}\u300D\u2192 \u5199\u5165 ${loc}\uFF08\u5DF2\u51FA\u73B0\u5728\u4E0A\u65B9\u6302\u8F7D\u6E05\u5355\uFF09`);
|
|
5287
|
+
setSkillName("");
|
|
5288
|
+
setSkillDesc("");
|
|
5289
|
+
setSkillWhen("");
|
|
5290
|
+
setSkillBody("");
|
|
5291
|
+
onCreated();
|
|
5292
|
+
};
|
|
5293
|
+
const createRule = async () => {
|
|
5294
|
+
setMsg("");
|
|
5295
|
+
const result = await remote.writeRule({ name: ruleName, content: ruleBody, level, path: workspace });
|
|
5296
|
+
if (!result.ok) {
|
|
5297
|
+
setMsg("\u65B0\u5EFA rule \u5931\u8D25\uFF1A" + describeError(result.error));
|
|
5298
|
+
return;
|
|
5299
|
+
}
|
|
5300
|
+
if (!result.value.ok) {
|
|
5301
|
+
setMsg("\u65B0\u5EFA rule \u5931\u8D25\uFF1A" + (result.value.error ?? "\u672A\u77E5\u9519\u8BEF"));
|
|
5302
|
+
return;
|
|
5303
|
+
}
|
|
5304
|
+
const loc = level === "project" ? `.dsh/rules/${result.value.name}.md` : `$DSH_HOME/rules/${result.value.name}.md`;
|
|
5305
|
+
setMsg(`\u5DF2\u65B0\u5EFA rule\u300C${result.value.name}\u300D\u2192 \u5199\u5165 ${loc}\uFF08\u5DF2\u51FA\u73B0\u5728\u4E0A\u65B9\u6302\u8F7D\u6E05\u5355\uFF09`);
|
|
5306
|
+
setRuleName("");
|
|
5307
|
+
setRuleBody("");
|
|
5308
|
+
onCreated();
|
|
5309
|
+
};
|
|
5310
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.section, children: [
|
|
5311
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.row, children: [
|
|
5312
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.fieldLabel, children: "\u5199\u5165\u4F4D\u7F6E" }),
|
|
5313
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.chips, children: [
|
|
5314
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Pill, { active: level === "project", onClick: () => {
|
|
5315
|
+
setLevel("project");
|
|
5316
|
+
}, title: "\u5199\u5230\u5DE5\u4F5C\u533A .dsh/\uFF0C\u56E2\u961F\u5171\u4EAB", children: "\u9879\u76EE\u7EA7" }),
|
|
5317
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Pill, { active: level === "user", onClick: () => {
|
|
5318
|
+
setLevel("user");
|
|
5319
|
+
}, title: "\u5199\u5230 $DSH_HOME\uFF0C\u4E2A\u4EBA\u6240\u6709\u9879\u76EE\u53EF\u7528", children: "\u7528\u6237\u7EA7" })
|
|
5320
|
+
] })
|
|
5321
|
+
] }),
|
|
5322
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: cardV, children: [
|
|
5323
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.bindingLabel, children: "\u65B0\u5EFA Skill" }),
|
|
5324
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.row, children: [
|
|
5325
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { style: { ...control, flex: "1 1 140px" }, placeholder: "name\uFF08\u5982 my-skill\uFF09", value: skillName, onChange: (ev) => {
|
|
5326
|
+
setSkillName(ev.target.value);
|
|
5327
|
+
} }),
|
|
5328
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { style: { ...control, flex: "1 1 240px" }, placeholder: "description\uFF08\u4E00\u53E5\u8BDD\u8BF4\u660E\u5B83\u505A\u4EC0\u4E48\uFF09", value: skillDesc, onChange: (ev) => {
|
|
5329
|
+
setSkillDesc(ev.target.value);
|
|
5330
|
+
} })
|
|
5331
|
+
] }),
|
|
5332
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { style: control, placeholder: "whenToUse\uFF08\u53EF\u9009\uFF1A\u4EC0\u4E48\u60C5\u51B5\u8BE5\u7528\uFF09", value: skillWhen, onChange: (ev) => {
|
|
5333
|
+
setSkillWhen(ev.target.value);
|
|
5334
|
+
} }),
|
|
5335
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("textarea", { style: styles.textarea, placeholder: "skill \u6B63\u6587\uFF08\u544A\u8BC9\u5927\u6A21\u578B\u8FD9\u4E2A\u9636\u6BB5\u600E\u4E48\u5E72\uFF09", value: skillBody, onChange: (ev) => {
|
|
5336
|
+
setSkillBody(ev.target.value);
|
|
5337
|
+
} }),
|
|
5338
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { variant: "outline", size: "sm", icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconPlusOutline16, { size: 14 }), disabled: skillName.trim() === "" || skillDesc.trim() === "" || skillBody.trim() === "", onClick: () => {
|
|
5339
|
+
void createSkill();
|
|
5340
|
+
}, children: "\u65B0\u5EFA skill" }) })
|
|
5341
|
+
] }),
|
|
5342
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: cardV, children: [
|
|
5343
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.bindingLabel, children: "\u65B0\u5EFA Rule" }),
|
|
5344
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { style: control, placeholder: "name\uFF08\u5982 my-redlines\uFF09", value: ruleName, onChange: (ev) => {
|
|
5345
|
+
setRuleName(ev.target.value);
|
|
5346
|
+
} }),
|
|
5347
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("textarea", { style: styles.textarea, placeholder: "rule \u6B63\u6587\uFF08\u8FD9\u6761\u89C4\u5219\u7EA6\u675F\u5927\u6A21\u578B\u9075\u5B88\u4EC0\u4E48\uFF09", value: ruleBody, onChange: (ev) => {
|
|
5348
|
+
setRuleBody(ev.target.value);
|
|
5349
|
+
} }),
|
|
5350
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { variant: "outline", size: "sm", icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconPlusOutline16, { size: 14 }), disabled: ruleName.trim() === "" || ruleBody.trim() === "", onClick: () => {
|
|
5351
|
+
void createRule();
|
|
5352
|
+
}, children: "\u65B0\u5EFA rule" }) })
|
|
5353
|
+
] }),
|
|
5354
|
+
msg !== "" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.status, children: msg }) : null
|
|
5355
|
+
] });
|
|
5356
|
+
}
|
|
5357
|
+
function sourceLabel(source) {
|
|
5358
|
+
switch (source) {
|
|
5359
|
+
case "bundled":
|
|
5360
|
+
return "\u5185\u7F6E";
|
|
5361
|
+
case "project":
|
|
5362
|
+
case "project-dsh":
|
|
5363
|
+
case "project-agents":
|
|
5364
|
+
return "\u9879\u76EE";
|
|
5365
|
+
case "user":
|
|
5366
|
+
case "user-dsh":
|
|
5367
|
+
case "user-agents":
|
|
5368
|
+
return "\u7528\u6237";
|
|
5369
|
+
case "custom":
|
|
5370
|
+
return "\u81EA\u5B9A\u4E49";
|
|
5371
|
+
default:
|
|
5372
|
+
return source;
|
|
5373
|
+
}
|
|
5374
|
+
}
|
|
5025
5375
|
function update(config, setConfig, fn) {
|
|
5026
5376
|
setConfig(fn(config));
|
|
5027
5377
|
}
|