@godv61/dsh-task-engine 0.5.2 → 0.6.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 +24 -3
- package/defaults/eng.json +19 -12
- package/hooks/commit-msg +11 -11
- package/lib/client.js +521 -20
- package/lib/client.js.map +4 -4
- package/lib/controller.d.ts +79 -3
- package/lib/controller.js +178 -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/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
|
}
|
|
@@ -4248,7 +4366,10 @@ function edgeList(config) {
|
|
|
4248
4366
|
function nodeX(index, stageCount) {
|
|
4249
4367
|
return index < 0 ? margin + stageCount * stepX + nodeW : margin + index * stepX;
|
|
4250
4368
|
}
|
|
4251
|
-
function FlowDiagram({ config }) {
|
|
4369
|
+
function FlowDiagram({ config, onAddTransition, onRemoveTransition }) {
|
|
4370
|
+
const [dragFrom, setDragFrom] = (0, import_react.useState)(null);
|
|
4371
|
+
const [dragPos, setDragPos] = (0, import_react.useState)(null);
|
|
4372
|
+
const svgRef = (0, import_react.useRef)(null);
|
|
4252
4373
|
const stages = config.stages;
|
|
4253
4374
|
const edges = edgeList(config);
|
|
4254
4375
|
const stageCount = stages.length;
|
|
@@ -4258,13 +4379,27 @@ function FlowDiagram({ config }) {
|
|
|
4258
4379
|
};
|
|
4259
4380
|
const width = Math.max(margin * 2 + stageCount * stepX, 360);
|
|
4260
4381
|
const height = 210;
|
|
4261
|
-
const
|
|
4382
|
+
const toSvg = (e) => {
|
|
4383
|
+
const rect = svgRef.current.getBoundingClientRect();
|
|
4384
|
+
return { x: e.clientX - rect.left, y: e.clientY - rect.top };
|
|
4385
|
+
};
|
|
4386
|
+
const startDrag = (stage, e) => {
|
|
4387
|
+
setDragFrom(stage);
|
|
4388
|
+
setDragPos(toSvg(e));
|
|
4389
|
+
};
|
|
4390
|
+
const dropOn = (stage) => {
|
|
4391
|
+
if (dragFrom !== null && dragFrom !== stage) onAddTransition(dragFrom, stage);
|
|
4392
|
+
setDragFrom(null);
|
|
4393
|
+
setDragPos(null);
|
|
4394
|
+
};
|
|
4395
|
+
const cancelDrag = () => {
|
|
4396
|
+
setDragFrom(null);
|
|
4397
|
+
setDragPos(null);
|
|
4398
|
+
};
|
|
4262
4399
|
const forwardPath = (from, to) => {
|
|
4263
4400
|
const x1 = nodeX(from, stageCount) + nodeW;
|
|
4264
4401
|
const x2 = nodeX(to, stageCount);
|
|
4265
|
-
if (to === from + 1) {
|
|
4266
|
-
return `M ${x1} ${nodeCenterY} L ${x2} ${nodeCenterY}`;
|
|
4267
|
-
}
|
|
4402
|
+
if (to === from + 1) return `M ${x1} ${nodeCenterY} L ${x2} ${nodeCenterY}`;
|
|
4268
4403
|
const cx = (x1 + x2) / 2;
|
|
4269
4404
|
const cy = nodeCenterY + (to - from) * 20;
|
|
4270
4405
|
return `M ${x1} ${nodeCenterY} Q ${cx} ${cy} ${x2} ${nodeCenterY}`;
|
|
@@ -4281,18 +4416,38 @@ function FlowDiagram({ config }) {
|
|
|
4281
4416
|
const cx = (x1 + x2) / 2;
|
|
4282
4417
|
return `M ${x1} ${y1} Q ${cx} ${y1 - lift} ${x2} ${y1}`;
|
|
4283
4418
|
};
|
|
4284
|
-
const strokeOf = (edge) => edge.orphaned ? danger : textTertiary;
|
|
4285
4419
|
const forwardLabelY = (from, to) => to === from + 1 ? nodeCenterY - 8 : nodeCenterY + (to - from) * 20 + 16;
|
|
4286
4420
|
const returnLabelY = (from, to) => nodeTop - 30 - Math.abs(from - to) * 6;
|
|
4421
|
+
const dragLine = dragFrom !== null && dragPos !== null ? (() => {
|
|
4422
|
+
const from = indexOf(dragFrom);
|
|
4423
|
+
const cx = from < 0 ? nodeX(-1, stageCount) + nodeW / 2 : nodeX(from, stageCount) + nodeW / 2;
|
|
4424
|
+
const cy = nodeTop;
|
|
4425
|
+
return (0, import_react.createElement)("line", {
|
|
4426
|
+
x1: cx,
|
|
4427
|
+
y1: cy,
|
|
4428
|
+
x2: dragPos.x,
|
|
4429
|
+
y2: dragPos.y,
|
|
4430
|
+
stroke: brand,
|
|
4431
|
+
strokeWidth: 1.5,
|
|
4432
|
+
strokeDasharray: "5 3",
|
|
4433
|
+
pointerEvents: "none"
|
|
4434
|
+
});
|
|
4435
|
+
})() : null;
|
|
4287
4436
|
return (0, import_react.createElement)(
|
|
4288
4437
|
"svg",
|
|
4289
4438
|
{
|
|
4439
|
+
ref: svgRef,
|
|
4290
4440
|
width,
|
|
4291
4441
|
height,
|
|
4292
4442
|
viewBox: `0 0 ${width} ${height}`,
|
|
4293
4443
|
style: { display: "block", minWidth: "100%", fontFamily: "inherit" },
|
|
4294
4444
|
role: "img",
|
|
4295
|
-
"aria-label": "\u5DE5\u7A0B\u9636\u6BB5\u6D41\u8F6C\u56FE"
|
|
4445
|
+
"aria-label": "\u5DE5\u7A0B\u9636\u6BB5\u6D41\u8F6C\u56FE\uFF08\u53EF\u62D6\u62FD\u8FDE\u7EBF\u3001\u70B9\u51FB\u7BAD\u5934\u5220\u9664\uFF09",
|
|
4446
|
+
onMouseMove: dragFrom === null ? void 0 : (e) => {
|
|
4447
|
+
setDragPos(toSvg(e));
|
|
4448
|
+
},
|
|
4449
|
+
onMouseUp: cancelDrag,
|
|
4450
|
+
onMouseLeave: cancelDrag
|
|
4296
4451
|
},
|
|
4297
4452
|
(0, import_react.createElement)(
|
|
4298
4453
|
"defs",
|
|
@@ -4310,7 +4465,7 @@ function FlowDiagram({ config }) {
|
|
|
4310
4465
|
...edges.map((edge, i) => {
|
|
4311
4466
|
const from = indexOf(edge.from);
|
|
4312
4467
|
const to = indexOf(edge.to);
|
|
4313
|
-
const stroke =
|
|
4468
|
+
const stroke = edge.orphaned ? danger : textTertiary;
|
|
4314
4469
|
const d = from < to ? forwardPath(from, to) : returnPath(from, to < 0 ? from : to);
|
|
4315
4470
|
const labelY = from < to ? forwardLabelY(from, to) : returnLabelY(from, to < 0 ? from : to);
|
|
4316
4471
|
const labelX = from < to ? (nodeX(from, stageCount) + nodeW + nodeX(to, stageCount)) / 2 : (nodeX(from, stageCount) + nodeX(to < 0 ? from : to, stageCount) + nodeW) / 2;
|
|
@@ -4321,6 +4476,10 @@ function FlowDiagram({ config }) {
|
|
|
4321
4476
|
stroke,
|
|
4322
4477
|
strokeWidth: 1.5,
|
|
4323
4478
|
markerEnd: "url(#flow-arrow)",
|
|
4479
|
+
style: { cursor: "pointer" },
|
|
4480
|
+
onClick: () => {
|
|
4481
|
+
onRemoveTransition(i);
|
|
4482
|
+
},
|
|
4324
4483
|
...edge.orphaned ? { strokeDasharray: "4 3" } : {}
|
|
4325
4484
|
};
|
|
4326
4485
|
const label = edge.label === null ? null : (0, import_react.createElement)("text", {
|
|
@@ -4329,10 +4488,21 @@ function FlowDiagram({ config }) {
|
|
|
4329
4488
|
textAnchor: "middle",
|
|
4330
4489
|
fontSize: 11,
|
|
4331
4490
|
fill: edge.orphaned ? danger : textSecondary
|
|
4332
|
-
}, edge.
|
|
4491
|
+
}, edge.label);
|
|
4333
4492
|
return (0, import_react.createElement)(
|
|
4334
4493
|
"g",
|
|
4335
4494
|
{ key: `edgeg-${i}` },
|
|
4495
|
+
(0, import_react.createElement)(
|
|
4496
|
+
"path",
|
|
4497
|
+
{
|
|
4498
|
+
...common,
|
|
4499
|
+
strokeWidth: 6,
|
|
4500
|
+
stroke: "transparent",
|
|
4501
|
+
fill: "none",
|
|
4502
|
+
markerEnd: void 0,
|
|
4503
|
+
strokeDasharray: void 0
|
|
4504
|
+
}
|
|
4505
|
+
),
|
|
4336
4506
|
(0, import_react.createElement)("path", common),
|
|
4337
4507
|
label
|
|
4338
4508
|
);
|
|
@@ -4342,7 +4512,16 @@ function FlowDiagram({ config }) {
|
|
|
4342
4512
|
const isStart = stage === config.start_stage;
|
|
4343
4513
|
return (0, import_react.createElement)(
|
|
4344
4514
|
"g",
|
|
4345
|
-
{
|
|
4515
|
+
{
|
|
4516
|
+
key: stage,
|
|
4517
|
+
style: { cursor: dragFrom === null ? "crosshair" : "pointer" },
|
|
4518
|
+
onMouseDown: (e) => {
|
|
4519
|
+
startDrag(stage, e);
|
|
4520
|
+
},
|
|
4521
|
+
onMouseUp: () => {
|
|
4522
|
+
dropOn(stage);
|
|
4523
|
+
}
|
|
4524
|
+
},
|
|
4346
4525
|
(0, import_react.createElement)("rect", {
|
|
4347
4526
|
x,
|
|
4348
4527
|
y: nodeTop,
|
|
@@ -4363,12 +4542,97 @@ function FlowDiagram({ config }) {
|
|
|
4363
4542
|
fill: "var(--dsw-alias-label-primary)",
|
|
4364
4543
|
fontWeight: isStart ? 600 : 400
|
|
4365
4544
|
}, stage),
|
|
4366
|
-
(0, import_react.createElement)("title", null,
|
|
4545
|
+
(0, import_react.createElement)("title", null, `${stage}${stage === config.start_stage ? "\uFF08\u8D77\u59CB\uFF09" : ""} \u2014 \u62D6\u5230\u53E6\u4E00\u9636\u6BB5\u65B0\u5EFA\u6D41\u8F6C`)
|
|
4367
4546
|
);
|
|
4368
|
-
})
|
|
4547
|
+
}),
|
|
4548
|
+
dragLine
|
|
4369
4549
|
);
|
|
4370
4550
|
}
|
|
4371
4551
|
|
|
4552
|
+
// src/client/templates.ts
|
|
4553
|
+
var STANDARD = {
|
|
4554
|
+
stages: ["\u9700\u6C42\u8BC4\u5BA1", "\u8BBE\u8BA1", "\u5F00\u53D1", "\u4EA4\u4ED8", "\u4EE3\u7801\u5BA1\u6838", "\u5B8C\u6210"],
|
|
4555
|
+
start_stage: "\u9700\u6C42\u8BC4\u5BA1",
|
|
4556
|
+
transitions: [
|
|
4557
|
+
{ from: "\u9700\u6C42\u8BC4\u5BA1", to: "\u8BBE\u8BA1", requires: ["requirement_confirmation", "artifacts_present"] },
|
|
4558
|
+
{ from: "\u8BBE\u8BA1", to: "\u5F00\u53D1", requires: ["solution_confirmation", "artifacts_present"] },
|
|
4559
|
+
{ from: "\u5F00\u53D1", to: "\u4EA4\u4ED8", requires: ["todos_done"] },
|
|
4560
|
+
{ from: "\u4EA4\u4ED8", to: "\u4EE3\u7801\u5BA1\u6838", requires: ["verified"] },
|
|
4561
|
+
{ from: "\u4EE3\u7801\u5BA1\u6838", to: "\u5B8C\u6210", requires: ["review_passed", "artifacts_present"] }
|
|
4562
|
+
],
|
|
4563
|
+
artifacts: [
|
|
4564
|
+
{ stage: "\u9700\u6C42\u8BC4\u5BA1", id: "requirement", name: "\u9700\u6C42\u8BF4\u660E", fields: ["scope", "acceptance_criteria"] },
|
|
4565
|
+
{ stage: "\u8BBE\u8BA1", id: "design", name: "\u8BBE\u8BA1\u6587\u6863", fields: ["approach", "risks", "impact"] },
|
|
4566
|
+
{ stage: "\u4EE3\u7801\u5BA1\u6838", id: "review", name: "\u8BC4\u5BA1\u8BB0\u5F55", fields: ["conclusion", "issues"] }
|
|
4567
|
+
],
|
|
4568
|
+
commit: {
|
|
4569
|
+
policy: "task",
|
|
4570
|
+
message_pattern: "^\u3010(\\S+)\u3011\u3010(?:TASK|T\\d+)\u3011.+",
|
|
4571
|
+
message_hint: "\u3010<module>\u3011\u3010TASK/T1\u3011\u8BF4\u660E \u2014\u2014 \u5199\u7ED3\u679C\uFF0C\u4E0D\u5199\u7A7A\u6CDB\u52A8\u4F5C",
|
|
4572
|
+
checkpoints: ["\u4EA4\u4ED8"],
|
|
4573
|
+
file_scope: true
|
|
4574
|
+
},
|
|
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
|
+
}
|
|
4583
|
+
};
|
|
4584
|
+
var AGILE = {
|
|
4585
|
+
stages: ["\u9700\u6C42", "\u5F00\u53D1", "\u4EA4\u4ED8", "\u5BA1\u67E5"],
|
|
4586
|
+
start_stage: "\u9700\u6C42",
|
|
4587
|
+
transitions: [
|
|
4588
|
+
{ from: "\u9700\u6C42", to: "\u5F00\u53D1", requires: ["requirement_confirmation"] },
|
|
4589
|
+
{ from: "\u5F00\u53D1", to: "\u4EA4\u4ED8", requires: ["todos_done"] },
|
|
4590
|
+
{ from: "\u4EA4\u4ED8", to: "\u5BA1\u67E5", requires: [] }
|
|
4591
|
+
],
|
|
4592
|
+
artifacts: [
|
|
4593
|
+
{ stage: "\u9700\u6C42", id: "requirement", name: "\u9700\u6C42\u8BF4\u660E", fields: ["scope"] }
|
|
4594
|
+
],
|
|
4595
|
+
commit: {
|
|
4596
|
+
policy: "item",
|
|
4597
|
+
message_pattern: "^\u3010(\\S+)\u3011\u3010T\\d+\u3011.+",
|
|
4598
|
+
message_hint: "\u3010<module>\u3011\u3010T1\u3011\u8BF4\u660E",
|
|
4599
|
+
checkpoints: ["\u4EA4\u4ED8"],
|
|
4600
|
+
file_scope: true
|
|
4601
|
+
},
|
|
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
|
+
}
|
|
4609
|
+
};
|
|
4610
|
+
var MINIMAL = {
|
|
4611
|
+
stages: ["\u5F00\u53D1", "\u4EA4\u4ED8"],
|
|
4612
|
+
start_stage: "\u5F00\u53D1",
|
|
4613
|
+
transitions: [
|
|
4614
|
+
{ from: "\u5F00\u53D1", to: "\u4EA4\u4ED8", requires: ["todos_done"] }
|
|
4615
|
+
],
|
|
4616
|
+
artifacts: [],
|
|
4617
|
+
commit: {
|
|
4618
|
+
policy: "task",
|
|
4619
|
+
message_pattern: "",
|
|
4620
|
+
message_hint: "\u65E0\u683C\u5F0F\u8981\u6C42",
|
|
4621
|
+
checkpoints: ["\u4EA4\u4ED8"],
|
|
4622
|
+
file_scope: false
|
|
4623
|
+
},
|
|
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
|
+
}
|
|
4629
|
+
};
|
|
4630
|
+
var WORKFLOW_TEMPLATES = [
|
|
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 },
|
|
4632
|
+
{ id: "agile", label: "\u654F\u6377\u8F7B\u91CF", description: "\u9700\u6C42 \u2192 \u5F00\u53D1 \u2192 \u4EA4\u4ED8 \u2192 \u5BA1\u67E5\uFF0C\u56DB\u9636\u6BB5\u3001\u5C11\u4EA7\u7269", config: AGILE },
|
|
4633
|
+
{ id: "minimal", label: "\u7EAF\u4EE3\u7801", description: "\u5F00\u53D1 \u2192 \u4EA4\u4ED8\uFF0C\u4E24\u9636\u6BB5\uFF0C\u53EA\u7559\u63D0\u4EA4\u95E8\u7981", config: MINIMAL }
|
|
4634
|
+
];
|
|
4635
|
+
|
|
4372
4636
|
// src/client/styles.ts
|
|
4373
4637
|
var text = "var(--dsw-alias-label-primary)";
|
|
4374
4638
|
var textSecondary2 = "var(--dsw-alias-label-secondary)";
|
|
@@ -4405,6 +4669,22 @@ var styles = {
|
|
|
4405
4669
|
padding: "8px 10px"
|
|
4406
4670
|
},
|
|
4407
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 },
|
|
4408
4688
|
problems: {
|
|
4409
4689
|
display: "flex",
|
|
4410
4690
|
flexDirection: "column",
|
|
@@ -4472,6 +4752,8 @@ function TaskEngineSection(props) {
|
|
|
4472
4752
|
const [savedAt, setSavedAt] = (0, import_react2.useState)("");
|
|
4473
4753
|
const [loadError, setLoadError] = (0, import_react2.useState)("");
|
|
4474
4754
|
const [loadedProblems, setLoadedProblems] = (0, import_react2.useState)([]);
|
|
4755
|
+
const [skills, setSkills] = (0, import_react2.useState)([]);
|
|
4756
|
+
const [rules, setRules] = (0, import_react2.useState)([]);
|
|
4475
4757
|
(0, import_react2.useEffect)(() => {
|
|
4476
4758
|
if (workspaces.length > 0 && workspace === "") {
|
|
4477
4759
|
setWorkspace(workspaces[0].path);
|
|
@@ -4498,8 +4780,33 @@ function TaskEngineSection(props) {
|
|
|
4498
4780
|
alive = false;
|
|
4499
4781
|
};
|
|
4500
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]);
|
|
4501
4797
|
const problems = (0, import_react2.useMemo)(() => config === null ? [] : validateWorkflow(config), [config]);
|
|
4502
4798
|
const notice = problems.length === 0 && loadedProblems.length > 0 ? loadedProblems : [];
|
|
4799
|
+
const addTransition = (from, to) => {
|
|
4800
|
+
if (config === null || from === "" || to === "") return;
|
|
4801
|
+
update(config, setConfig, (c) => ({
|
|
4802
|
+
...c,
|
|
4803
|
+
transitions: [...c.transitions, { from, to }]
|
|
4804
|
+
}));
|
|
4805
|
+
};
|
|
4806
|
+
const removeTransition = (index) => {
|
|
4807
|
+
if (config === null) return;
|
|
4808
|
+
update(config, setConfig, (c) => ({ ...c, transitions: c.transitions.filter((_, j) => j !== index) }));
|
|
4809
|
+
};
|
|
4503
4810
|
if (workspaces.length === 0) {
|
|
4504
4811
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.wrap, children: [
|
|
4505
4812
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { style: styles.title, children: "\u5DE5\u7A0B\u6D41\u7A0B\u914D\u7F6E" }),
|
|
@@ -4547,11 +4854,14 @@ function TaskEngineSection(props) {
|
|
|
4547
4854
|
}
|
|
4548
4855
|
)
|
|
4549
4856
|
] }),
|
|
4550
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
4551
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
4552
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SectionCard, { icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.
|
|
4553
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SectionCard, { icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.
|
|
4554
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SectionCard, { icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.
|
|
4857
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(TemplatePicker, { config, setConfig }),
|
|
4858
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.flowCard, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FlowDiagram, { config, onAddTransition: addTransition, onRemoveTransition: removeTransition }) }),
|
|
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 }) }),
|
|
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", 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", 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", 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", 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 }) }),
|
|
4555
4865
|
problems.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.problems, children: [
|
|
4556
4866
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: styles.problemsTitle, children: [
|
|
4557
4867
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.StateDot, { state: "error" }),
|
|
@@ -4602,7 +4912,7 @@ function sourceText(source) {
|
|
|
4602
4912
|
return "\u5185\u7F6E\u9ED8\u8BA4\u914D\u7F6E\uFF08\u5DE5\u4F5C\u533A\u5C1A\u65E0 .dsh/eng.json\uFF09";
|
|
4603
4913
|
}
|
|
4604
4914
|
}
|
|
4605
|
-
function SectionCard({ icon, title, children }) {
|
|
4915
|
+
function SectionCard({ icon, title, hint, children }) {
|
|
4606
4916
|
const [open, setOpen] = (0, import_react2.useState)(true);
|
|
4607
4917
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.section, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
4608
4918
|
import_dsh_client_ui_primitives.DisclosureRow,
|
|
@@ -4615,10 +4925,30 @@ function SectionCard({ icon, title, children }) {
|
|
|
4615
4925
|
setOpen(!open);
|
|
4616
4926
|
},
|
|
4617
4927
|
keepContentWhenOpen: true,
|
|
4618
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.
|
|
4928
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.cardBody, children: [
|
|
4929
|
+
hint !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.muted, children: hint }) : null,
|
|
4930
|
+
children
|
|
4931
|
+
] })
|
|
4619
4932
|
}
|
|
4620
4933
|
) });
|
|
4621
4934
|
}
|
|
4935
|
+
function TemplatePicker({ config, setConfig }) {
|
|
4936
|
+
const apply2 = (id) => {
|
|
4937
|
+
const template = WORKFLOW_TEMPLATES.find((t) => t.id === id);
|
|
4938
|
+
if (template === void 0) return;
|
|
4939
|
+
setConfig(cloneConfig(template.config));
|
|
4940
|
+
};
|
|
4941
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.field, children: [
|
|
4942
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.fieldLabel, children: "\u6D41\u7A0B\u6A21\u677F\uFF08\u70B9\u4E00\u4E0B\u6574\u4F53\u5957\u7528\uFF0C\u4F1A\u8986\u76D6\u5F53\u524D\u7F16\u8F91\uFF09" }),
|
|
4943
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.chips, children: WORKFLOW_TEMPLATES.map((t) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Pill, { active: config.stages.join(",") === t.config.stages.join(","), onClick: () => {
|
|
4944
|
+
apply2(t.id);
|
|
4945
|
+
}, title: t.description, children: t.label }, t.id)) }),
|
|
4946
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.hint, children: "\u4E0D\u786E\u5B9A\u600E\u4E48\u914D\u5C31\u4ECE\u300C\u6807\u51C6\u7814\u53D1\u300D\u8D77\u6B65\uFF0C\u5957\u7528\u540E\u518D\u5FAE\u8C03\uFF1B\u4E5F\u53EF\u4EE5\u5148\u5957\u6A21\u677F\uFF0C\u518D\u7528\u4E0B\u9762\u7684\u5361\u7247\u6539\u3002" })
|
|
4947
|
+
] });
|
|
4948
|
+
}
|
|
4949
|
+
function cloneConfig(config) {
|
|
4950
|
+
return JSON.parse(JSON.stringify(config));
|
|
4951
|
+
}
|
|
4622
4952
|
function StageEditor({ config, setConfig }) {
|
|
4623
4953
|
const [draft, setDraft] = (0, import_react2.useState)("");
|
|
4624
4954
|
const addStage = () => {
|
|
@@ -4861,6 +5191,177 @@ function CommitEditor({ config, setConfig }) {
|
|
|
4861
5191
|
] })
|
|
4862
5192
|
] });
|
|
4863
5193
|
}
|
|
5194
|
+
function BindingEditor({ config, setConfig, skills, rules }) {
|
|
5195
|
+
const toggleSkill = (stage, skill) => {
|
|
5196
|
+
update(config, setConfig, (c) => {
|
|
5197
|
+
const bindings = c.stage_bindings ?? {};
|
|
5198
|
+
const current = bindings[stage]?.skills ?? [];
|
|
5199
|
+
const next = current.includes(skill) ? current.filter((s) => s !== skill) : [...current, skill].sort();
|
|
5200
|
+
return { ...c, stage_bindings: { ...bindings, [stage]: { ...bindings[stage] ?? {}, skills: next } } };
|
|
5201
|
+
});
|
|
5202
|
+
};
|
|
5203
|
+
const toggleRule = (stage, rule) => {
|
|
5204
|
+
update(config, setConfig, (c) => {
|
|
5205
|
+
const bindings = c.stage_bindings ?? {};
|
|
5206
|
+
const current = bindings[stage]?.rules ?? [];
|
|
5207
|
+
const next = current.includes(rule) ? current.filter((s) => s !== rule) : [...current, rule].sort();
|
|
5208
|
+
return { ...c, stage_bindings: { ...bindings, [stage]: { ...bindings[stage] ?? {}, rules: next } } };
|
|
5209
|
+
});
|
|
5210
|
+
};
|
|
5211
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.section, children: config.stages.map((stage) => {
|
|
5212
|
+
const binding = config.stage_bindings?.[stage];
|
|
5213
|
+
const boundSkills = binding?.skills ?? [];
|
|
5214
|
+
const boundRules = binding?.rules ?? [];
|
|
5215
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: cardV, children: [
|
|
5216
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.bindingLabel, children: stage }),
|
|
5217
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.bindingStage, children: [
|
|
5218
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.fieldLabel, children: "skill\uFF08\u505A\u4EC0\u4E48\uFF09" }),
|
|
5219
|
+
/* @__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\u4E0B\u65B9\u65B0\u5EFA" }) : skills.map((sk) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
5220
|
+
import_dsh_client_ui_primitives.Pill,
|
|
5221
|
+
{
|
|
5222
|
+
active: boundSkills.includes(sk.name),
|
|
5223
|
+
onClick: () => {
|
|
5224
|
+
toggleSkill(stage, sk.name);
|
|
5225
|
+
},
|
|
5226
|
+
title: `${sk.description}\uFF08${sourceLabel(sk.source)}\uFF09`,
|
|
5227
|
+
children: sk.name
|
|
5228
|
+
},
|
|
5229
|
+
sk.name
|
|
5230
|
+
)) })
|
|
5231
|
+
] }),
|
|
5232
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.bindingStage, children: [
|
|
5233
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.fieldLabel, children: "rule\uFF08\u5B88\u4EC0\u4E48\uFF09" }),
|
|
5234
|
+
/* @__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\u4E0B\u65B9\u65B0\u5EFA" }) : rules.map((rule) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
5235
|
+
import_dsh_client_ui_primitives.Pill,
|
|
5236
|
+
{
|
|
5237
|
+
active: boundRules.includes(rule.name),
|
|
5238
|
+
onClick: () => {
|
|
5239
|
+
toggleRule(stage, rule.name);
|
|
5240
|
+
},
|
|
5241
|
+
title: `\u6765\u6E90\uFF1A${sourceLabel(rule.source)}`,
|
|
5242
|
+
children: rule.name
|
|
5243
|
+
},
|
|
5244
|
+
rule.name
|
|
5245
|
+
)) })
|
|
5246
|
+
] })
|
|
5247
|
+
] }, stage);
|
|
5248
|
+
}) });
|
|
5249
|
+
}
|
|
5250
|
+
function ResourceCreator({ remote, workspace, onCreated }) {
|
|
5251
|
+
const [skillName, setSkillName] = (0, import_react2.useState)("");
|
|
5252
|
+
const [skillDesc, setSkillDesc] = (0, import_react2.useState)("");
|
|
5253
|
+
const [skillWhen, setSkillWhen] = (0, import_react2.useState)("");
|
|
5254
|
+
const [skillBody, setSkillBody] = (0, import_react2.useState)("");
|
|
5255
|
+
const [ruleName, setRuleName] = (0, import_react2.useState)("");
|
|
5256
|
+
const [ruleBody, setRuleBody] = (0, import_react2.useState)("");
|
|
5257
|
+
const [level, setLevel] = (0, import_react2.useState)("project");
|
|
5258
|
+
const [msg, setMsg] = (0, import_react2.useState)("");
|
|
5259
|
+
const createSkill = async () => {
|
|
5260
|
+
setMsg("");
|
|
5261
|
+
const result = await remote.writeSkill({
|
|
5262
|
+
name: skillName,
|
|
5263
|
+
description: skillDesc,
|
|
5264
|
+
whenToUse: skillWhen === "" ? void 0 : skillWhen,
|
|
5265
|
+
content: skillBody,
|
|
5266
|
+
level,
|
|
5267
|
+
path: workspace
|
|
5268
|
+
});
|
|
5269
|
+
if (!result.ok) {
|
|
5270
|
+
setMsg("\u65B0\u5EFA skill \u5931\u8D25\uFF1A" + describeError(result.error));
|
|
5271
|
+
return;
|
|
5272
|
+
}
|
|
5273
|
+
if (!result.value.ok) {
|
|
5274
|
+
setMsg("\u65B0\u5EFA skill \u5931\u8D25\uFF1A" + (result.value.error ?? "\u672A\u77E5\u9519\u8BEF"));
|
|
5275
|
+
return;
|
|
5276
|
+
}
|
|
5277
|
+
setMsg(`\u5DF2\u65B0\u5EFA skill\u300C${result.value.name}\u300D`);
|
|
5278
|
+
setSkillName("");
|
|
5279
|
+
setSkillDesc("");
|
|
5280
|
+
setSkillWhen("");
|
|
5281
|
+
setSkillBody("");
|
|
5282
|
+
onCreated();
|
|
5283
|
+
};
|
|
5284
|
+
const createRule = async () => {
|
|
5285
|
+
setMsg("");
|
|
5286
|
+
const result = await remote.writeRule({ name: ruleName, content: ruleBody, level, path: workspace });
|
|
5287
|
+
if (!result.ok) {
|
|
5288
|
+
setMsg("\u65B0\u5EFA rule \u5931\u8D25\uFF1A" + describeError(result.error));
|
|
5289
|
+
return;
|
|
5290
|
+
}
|
|
5291
|
+
if (!result.value.ok) {
|
|
5292
|
+
setMsg("\u65B0\u5EFA rule \u5931\u8D25\uFF1A" + (result.value.error ?? "\u672A\u77E5\u9519\u8BEF"));
|
|
5293
|
+
return;
|
|
5294
|
+
}
|
|
5295
|
+
setMsg(`\u5DF2\u65B0\u5EFA rule\u300C${result.value.name}\u300D`);
|
|
5296
|
+
setRuleName("");
|
|
5297
|
+
setRuleBody("");
|
|
5298
|
+
onCreated();
|
|
5299
|
+
};
|
|
5300
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.section, children: [
|
|
5301
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.row, children: [
|
|
5302
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.fieldLabel, children: "\u5199\u5165\u4F4D\u7F6E" }),
|
|
5303
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.chips, children: [
|
|
5304
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Pill, { active: level === "project", onClick: () => {
|
|
5305
|
+
setLevel("project");
|
|
5306
|
+
}, title: "\u5199\u5230\u5DE5\u4F5C\u533A .dsh/\uFF0C\u56E2\u961F\u5171\u4EAB", children: "\u9879\u76EE\u7EA7" }),
|
|
5307
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Pill, { active: level === "user", onClick: () => {
|
|
5308
|
+
setLevel("user");
|
|
5309
|
+
}, title: "\u5199\u5230 $DSH_HOME\uFF0C\u4E2A\u4EBA\u6240\u6709\u9879\u76EE\u53EF\u7528", children: "\u7528\u6237\u7EA7" })
|
|
5310
|
+
] })
|
|
5311
|
+
] }),
|
|
5312
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: cardV, children: [
|
|
5313
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.bindingLabel, children: "\u65B0\u5EFA Skill" }),
|
|
5314
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.row, children: [
|
|
5315
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { style: { ...control, flex: "1 1 140px" }, placeholder: "name\uFF08\u5982 my-skill\uFF09", value: skillName, onChange: (ev) => {
|
|
5316
|
+
setSkillName(ev.target.value);
|
|
5317
|
+
} }),
|
|
5318
|
+
/* @__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) => {
|
|
5319
|
+
setSkillDesc(ev.target.value);
|
|
5320
|
+
} })
|
|
5321
|
+
] }),
|
|
5322
|
+
/* @__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) => {
|
|
5323
|
+
setSkillWhen(ev.target.value);
|
|
5324
|
+
} }),
|
|
5325
|
+
/* @__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) => {
|
|
5326
|
+
setSkillBody(ev.target.value);
|
|
5327
|
+
} }),
|
|
5328
|
+
/* @__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: () => {
|
|
5329
|
+
void createSkill();
|
|
5330
|
+
}, children: "\u65B0\u5EFA skill" }) })
|
|
5331
|
+
] }),
|
|
5332
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: cardV, children: [
|
|
5333
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.bindingLabel, children: "\u65B0\u5EFA Rule" }),
|
|
5334
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { style: control, placeholder: "name\uFF08\u5982 my-redlines\uFF09", value: ruleName, onChange: (ev) => {
|
|
5335
|
+
setRuleName(ev.target.value);
|
|
5336
|
+
} }),
|
|
5337
|
+
/* @__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) => {
|
|
5338
|
+
setRuleBody(ev.target.value);
|
|
5339
|
+
} }),
|
|
5340
|
+
/* @__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: () => {
|
|
5341
|
+
void createRule();
|
|
5342
|
+
}, children: "\u65B0\u5EFA rule" }) })
|
|
5343
|
+
] }),
|
|
5344
|
+
msg !== "" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.status, children: msg }) : null
|
|
5345
|
+
] });
|
|
5346
|
+
}
|
|
5347
|
+
function sourceLabel(source) {
|
|
5348
|
+
switch (source) {
|
|
5349
|
+
case "bundled":
|
|
5350
|
+
return "\u5185\u7F6E";
|
|
5351
|
+
case "project":
|
|
5352
|
+
case "project-dsh":
|
|
5353
|
+
case "project-agents":
|
|
5354
|
+
return "\u9879\u76EE";
|
|
5355
|
+
case "user":
|
|
5356
|
+
case "user-dsh":
|
|
5357
|
+
case "user-agents":
|
|
5358
|
+
return "\u7528\u6237";
|
|
5359
|
+
case "custom":
|
|
5360
|
+
return "\u81EA\u5B9A\u4E49";
|
|
5361
|
+
default:
|
|
5362
|
+
return source;
|
|
5363
|
+
}
|
|
5364
|
+
}
|
|
4864
5365
|
function update(config, setConfig, fn) {
|
|
4865
5366
|
setConfig(fn(config));
|
|
4866
5367
|
}
|