@godv61/dsh-task-engine 0.14.0 → 0.16.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/lib/client.js CHANGED
@@ -4104,12 +4104,14 @@ var configSchema = external_exports.object({
4104
4104
  var viewSchema = external_exports.object({
4105
4105
  ok: external_exports.boolean(),
4106
4106
  source: external_exports.enum(["default", "project", "invalid"]),
4107
+ flow: external_exports.string(),
4107
4108
  config: configSchema,
4108
4109
  problems: external_exports.array(external_exports.string())
4109
4110
  });
4110
4111
  var writeRequestSchema = external_exports.object({
4111
4112
  path: external_exports.string(),
4112
- config: configSchema
4113
+ flow: external_exports.string(),
4114
+ stage_bindings: external_exports.record(external_exports.string(), stageBindingSchema).optional()
4113
4115
  });
4114
4116
  var skillCatalogSchema = external_exports.object({
4115
4117
  skills: external_exports.array(external_exports.object({
@@ -4383,7 +4385,7 @@ var remote_default = TYPERT_REMOTE;
4383
4385
 
4384
4386
  // src/client/Workbench.tsx
4385
4387
  var import_react6 = require("react");
4386
- var import_dsh_client_ui_primitives5 = require("@deepseek-ai/dsh-client-ui-primitives");
4388
+ var import_dsh_client_ui_primitives6 = require("@deepseek-ai/dsh-client-ui-primitives");
4387
4389
 
4388
4390
  // src/client/styles.ts
4389
4391
  var text = "var(--dsw-alias-label-primary)";
@@ -4462,7 +4464,7 @@ var styles = {
4462
4464
  };
4463
4465
 
4464
4466
  // src/client/TaskEngineSection.tsx
4465
- var import_react2 = require("react");
4467
+ var import_react = require("react");
4466
4468
  var import_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
4467
4469
 
4468
4470
  // src/engine.ts
@@ -4555,214 +4557,12 @@ function validateWorkflow(config) {
4555
4557
  return problems;
4556
4558
  }
4557
4559
 
4558
- // src/client/FlowDiagram.tsx
4559
- var import_react = require("react");
4560
- var nodeW = 108;
4561
- var nodeH = 40;
4562
- var stepX = nodeW + 56;
4563
- var margin = 40;
4564
- var nodeTop = 92;
4565
- var nodeCenterY = nodeTop + nodeH / 2;
4566
- var textTertiary2 = "var(--dsw-alias-label-tertiary)";
4567
- var textSecondary2 = "var(--dsw-alias-label-secondary)";
4568
- var border2 = "var(--dsw-alias-border-l2)";
4569
- var surface2 = "var(--dsw-alias-bg-layer-2)";
4570
- var brand = "var(--dsw-alias-state-business-primary)";
4571
- var danger2 = "var(--dsw-alias-state-error-primary)";
4572
- function edgeList(config) {
4573
- return config.transitions.map((t) => {
4574
- const label = (t.requires ?? []).length > 0 ? (t.requires ?? []).join(" \xB7 ") : null;
4575
- const orphaned = !config.stages.includes(t.from) || !config.stages.includes(t.to);
4576
- return { from: t.from, to: t.to, label, orphaned };
4577
- });
4578
- }
4579
- function nodeX(index, stageCount) {
4580
- return index < 0 ? margin + stageCount * stepX + nodeW : margin + index * stepX;
4581
- }
4582
- function FlowDiagram({ config, onAddTransition, onRemoveTransition }) {
4583
- const [dragFrom, setDragFrom] = (0, import_react.useState)(null);
4584
- const [dragPos, setDragPos] = (0, import_react.useState)(null);
4585
- const svgRef = (0, import_react.useRef)(null);
4586
- const stages = config.stages;
4587
- const edges = edgeList(config);
4588
- const stageCount = stages.length;
4589
- const indexOf = (s) => {
4590
- const i = stages.indexOf(s);
4591
- return i < 0 ? -1 : i;
4592
- };
4593
- const width = Math.max(margin * 2 + stageCount * stepX, 360);
4594
- const height = 210;
4595
- const toSvg = (e) => {
4596
- const rect = svgRef.current.getBoundingClientRect();
4597
- return { x: e.clientX - rect.left, y: e.clientY - rect.top };
4598
- };
4599
- const startDrag = (stage, e) => {
4600
- setDragFrom(stage);
4601
- setDragPos(toSvg(e));
4602
- };
4603
- const dropOn = (stage) => {
4604
- if (dragFrom !== null && dragFrom !== stage) onAddTransition(dragFrom, stage);
4605
- setDragFrom(null);
4606
- setDragPos(null);
4607
- };
4608
- const cancelDrag = () => {
4609
- setDragFrom(null);
4610
- setDragPos(null);
4611
- };
4612
- const forwardPath = (from, to) => {
4613
- const x1 = nodeX(from, stageCount) + nodeW;
4614
- const x2 = nodeX(to, stageCount);
4615
- if (to === from + 1) return `M ${x1} ${nodeCenterY} L ${x2} ${nodeCenterY}`;
4616
- const cx = (x1 + x2) / 2;
4617
- const cy = nodeCenterY + (to - from) * 20;
4618
- return `M ${x1} ${nodeCenterY} Q ${cx} ${cy} ${x2} ${nodeCenterY}`;
4619
- };
4620
- const returnPath = (from, to) => {
4621
- const x1 = nodeX(from, stageCount) + nodeW / 2;
4622
- const x2 = nodeX(to, stageCount) + nodeW / 2;
4623
- const y1 = nodeTop;
4624
- const lift = 26 + Math.abs(from - to) * 6;
4625
- if (from === to) {
4626
- const cx2 = x1 + nodeW / 2 + 8;
4627
- return `M ${x1 + nodeW / 2} ${y1} Q ${cx2} ${y1 - lift} ${x1 + nodeW / 2 + 18} ${y1}`;
4628
- }
4629
- const cx = (x1 + x2) / 2;
4630
- return `M ${x1} ${y1} Q ${cx} ${y1 - lift} ${x2} ${y1}`;
4631
- };
4632
- const forwardLabelY = (from, to) => to === from + 1 ? nodeCenterY - 8 : nodeCenterY + (to - from) * 20 + 16;
4633
- const returnLabelY = (from, to) => nodeTop - 30 - Math.abs(from - to) * 6;
4634
- const dragLine = dragFrom !== null && dragPos !== null ? (() => {
4635
- const from = indexOf(dragFrom);
4636
- const cx = from < 0 ? nodeX(-1, stageCount) + nodeW / 2 : nodeX(from, stageCount) + nodeW / 2;
4637
- const cy = nodeTop;
4638
- return (0, import_react.createElement)("line", {
4639
- x1: cx,
4640
- y1: cy,
4641
- x2: dragPos.x,
4642
- y2: dragPos.y,
4643
- stroke: brand,
4644
- strokeWidth: 1.5,
4645
- strokeDasharray: "5 3",
4646
- pointerEvents: "none"
4647
- });
4648
- })() : null;
4649
- return (0, import_react.createElement)(
4650
- "svg",
4651
- {
4652
- ref: svgRef,
4653
- width,
4654
- height,
4655
- viewBox: `0 0 ${width} ${height}`,
4656
- style: { display: "block", minWidth: "100%", fontFamily: "inherit" },
4657
- role: "img",
4658
- "aria-label": "\u5DE5\u7A0B\u9636\u6BB5\u6D41\u8F6C\u56FE\uFF08\u53EF\u62D6\u62FD\u8FDE\u7EBF\u3001\u70B9\u51FB\u7BAD\u5934\u5220\u9664\uFF09",
4659
- onMouseMove: dragFrom === null ? void 0 : (e) => {
4660
- setDragPos(toSvg(e));
4661
- },
4662
- onMouseUp: cancelDrag,
4663
- onMouseLeave: cancelDrag
4664
- },
4665
- (0, import_react.createElement)(
4666
- "defs",
4667
- null,
4668
- (0, import_react.createElement)("marker", {
4669
- id: "flow-arrow",
4670
- viewBox: "0 0 10 10",
4671
- refX: 8,
4672
- refY: 5,
4673
- markerWidth: 7,
4674
- markerHeight: 7,
4675
- orient: "auto"
4676
- }, (0, import_react.createElement)("path", { d: "M 0 0 L 10 5 L 0 10 z", fill: "context-stroke" }))
4677
- ),
4678
- ...edges.map((edge, i) => {
4679
- const from = indexOf(edge.from);
4680
- const to = indexOf(edge.to);
4681
- const stroke = edge.orphaned ? danger2 : textTertiary2;
4682
- const d = from < to ? forwardPath(from, to) : returnPath(from, to < 0 ? from : to);
4683
- const labelY = from < to ? forwardLabelY(from, to) : returnLabelY(from, to < 0 ? from : to);
4684
- const labelX = from < to ? (nodeX(from, stageCount) + nodeW + nodeX(to, stageCount)) / 2 : (nodeX(from, stageCount) + nodeX(to < 0 ? from : to, stageCount) + nodeW) / 2;
4685
- const common = {
4686
- key: `edge-${i}`,
4687
- d,
4688
- fill: "none",
4689
- stroke,
4690
- strokeWidth: 1.5,
4691
- markerEnd: "url(#flow-arrow)",
4692
- style: { cursor: "pointer" },
4693
- onClick: () => {
4694
- onRemoveTransition(i);
4695
- },
4696
- ...edge.orphaned ? { strokeDasharray: "4 3" } : {}
4697
- };
4698
- const label = edge.label === null ? null : (0, import_react.createElement)("text", {
4699
- x: labelX,
4700
- y: labelY,
4701
- textAnchor: "middle",
4702
- fontSize: 11,
4703
- fill: edge.orphaned ? danger2 : textSecondary2
4704
- }, edge.label);
4705
- return (0, import_react.createElement)(
4706
- "g",
4707
- { key: `edgeg-${i}` },
4708
- (0, import_react.createElement)(
4709
- "path",
4710
- {
4711
- ...common,
4712
- strokeWidth: 6,
4713
- stroke: "transparent",
4714
- fill: "none",
4715
- markerEnd: void 0,
4716
- strokeDasharray: void 0
4717
- }
4718
- ),
4719
- (0, import_react.createElement)("path", common),
4720
- label
4721
- );
4722
- }),
4723
- ...stages.map((stage, i) => {
4724
- const x = nodeX(i, stageCount);
4725
- const isStart = stage === config.start_stage;
4726
- return (0, import_react.createElement)(
4727
- "g",
4728
- {
4729
- key: stage,
4730
- style: { cursor: dragFrom === null ? "crosshair" : "pointer" },
4731
- onMouseDown: (e) => {
4732
- startDrag(stage, e);
4733
- },
4734
- onMouseUp: () => {
4735
- dropOn(stage);
4736
- }
4737
- },
4738
- (0, import_react.createElement)("rect", {
4739
- x,
4740
- y: nodeTop,
4741
- width: nodeW,
4742
- height: nodeH,
4743
- rx: 20,
4744
- ry: 20,
4745
- fill: surface2,
4746
- stroke: isStart ? brand : border2,
4747
- strokeWidth: isStart ? 2 : 1.5
4748
- }),
4749
- (0, import_react.createElement)("text", {
4750
- x: x + nodeW / 2,
4751
- y: nodeCenterY,
4752
- textAnchor: "middle",
4753
- alignmentBaseline: "middle",
4754
- fontSize: 12,
4755
- fill: "var(--dsw-alias-label-primary)",
4756
- fontWeight: isStart ? 600 : 400
4757
- }, stage),
4758
- (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`)
4759
- );
4760
- }),
4761
- dragLine
4762
- );
4763
- }
4764
-
4765
- // src/client/templates.ts
4560
+ // src/workflows.ts
4561
+ var FLOW_OPTIONS = [
4562
+ { 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" },
4563
+ { 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" },
4564
+ { id: "minimal", label: "\u7EAF\u4EE3\u7801", description: "\u5F00\u53D1 \u2192 \u4EA4\u4ED8\uFF0C\u4E24\u9636\u6BB5\uFF0C\u53EA\u7559\u63D0\u4EA4\u95E8\u7981" }
4565
+ ];
4766
4566
  var STANDARD = {
4767
4567
  stages: ["\u9700\u6C42\u8BC4\u5BA1", "\u8BBE\u8BA1", "\u5F00\u53D1", "\u4EA4\u4ED8", "\u4EE3\u7801\u5BA1\u6838", "\u5B8C\u6210"],
4768
4568
  start_stage: "\u9700\u6C42\u8BC4\u5BA1",
@@ -4840,11 +4640,18 @@ var MINIMAL = {
4840
4640
  "\u4EA4\u4ED8": { skills: ["code-commit"], rules: ["commit-conventions"] }
4841
4641
  }
4842
4642
  };
4843
- var WORKFLOW_TEMPLATES = [
4844
- { 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 },
4845
- { 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 },
4846
- { 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 }
4847
- ];
4643
+ var FLOW_CONFIGS = {
4644
+ standard: STANDARD,
4645
+ agile: AGILE,
4646
+ minimal: MINIMAL
4647
+ };
4648
+ function resolveFlowConfig(flow, override) {
4649
+ const base = FLOW_CONFIGS[flow] ?? STANDARD;
4650
+ if (override?.stage_bindings !== void 0) {
4651
+ return { ...base, stage_bindings: { ...override.stage_bindings } };
4652
+ }
4653
+ return base;
4654
+ }
4848
4655
 
4849
4656
  // src/client/shared.ts
4850
4657
  function sourceLabel(source) {
@@ -4873,17 +4680,6 @@ function describeError(error) {
4873
4680
 
4874
4681
  // src/client/TaskEngineSection.tsx
4875
4682
  var import_jsx_runtime = require("react/jsx-runtime");
4876
- var text2 = "var(--dsw-alias-label-primary)";
4877
- var textTertiary3 = "var(--dsw-alias-label-tertiary)";
4878
- var control = {
4879
- background: "var(--dsw-alias-bg-layer-1)",
4880
- border: `1px solid ${border}`,
4881
- borderRadius: 8,
4882
- padding: "5px 8px",
4883
- color: text2,
4884
- fontSize: 13,
4885
- minWidth: 0
4886
- };
4887
4683
  var cardV = {
4888
4684
  display: "flex",
4889
4685
  flexDirection: "column",
@@ -4892,38 +4688,25 @@ var cardV = {
4892
4688
  borderRadius: 8,
4893
4689
  padding: "10px 12px"
4894
4690
  };
4895
- var GUARD_OPTIONS = [
4896
- { value: "requirement_confirmation", label: "\u9700\u6C42\u786E\u8BA4", hint: "\u9700\u6C42\u5DF2\u7ECF\u4EBA\u786E\u8BA4\u8FC7" },
4897
- { value: "solution_confirmation", label: "\u65B9\u6848\u786E\u8BA4", hint: "\u65B9\u6848\u5DF2\u7ECF\u4EBA\u786E\u8BA4\u8FC7" },
4898
- { value: "todos_done", label: "\u5F85\u529E\u5B8C\u6210", hint: "\u4EFB\u52A1\u6E05\u5355\u91CC\u7684\u6BCF\u4E00\u9879\u90FD\u5DF2\u52FE\u9009\u5B8C\u6210" },
4899
- { value: "verified", label: "\u5DF2\u9A8C\u8BC1", hint: "\u5DF2\u901A\u8FC7\u9A8C\u8BC1\uFF08\u9AD8\u98CE\u9669\u4EFB\u52A1\u8FD8\u5FC5\u987B\u9644\u9A8C\u8BC1\u8BC1\u636E\uFF09" },
4900
- { value: "review_passed", label: "\u8BC4\u5BA1\u901A\u8FC7", hint: "\u4EE3\u7801\u5BA1\u6838\u7ED3\u8BBA\u4E3A\u901A\u8FC7" },
4901
- { value: "artifacts_present", label: "\u4EA7\u7269\u5B57\u6BB5\u5DF2\u586B\u5168", hint: "\u8BE5\u9636\u6BB5\u58F0\u660E\u7684\u6BCF\u4E00\u4E2A\u4EA7\u7269\u5B57\u6BB5\u90FD\u5DF2\u586B\u4E0A\u5185\u5BB9" }
4902
- ];
4903
- var POLICY_OPTIONS = [
4904
- { value: "task", label: "task", hint: "\u68C0\u67E5\u70B9\u4E00\u6B21\u63D0\u4EA4" },
4905
- { value: "item", label: "item", hint: "\u9010\u9879\u63D0\u4EA4 + \u6536\u5C3E TASK" },
4906
- { value: "manual", label: "manual", hint: "\u4EBA\u5DE5\u6307\u793A" }
4907
- ];
4908
4691
  function TaskEngineSection(props) {
4909
4692
  const { remote, workspace } = props;
4910
- const [config, setConfig] = (0, import_react2.useState)(null);
4911
- const [source, setSource] = (0, import_react2.useState)("default");
4912
- const [savedAt, setSavedAt] = (0, import_react2.useState)("");
4913
- const [loadError, setLoadError] = (0, import_react2.useState)("");
4914
- const [loadedProblems, setLoadedProblems] = (0, import_react2.useState)([]);
4915
- const [skills, setSkills] = (0, import_react2.useState)([]);
4916
- const [rules, setRules] = (0, import_react2.useState)([]);
4917
- (0, import_react2.useEffect)(() => {
4693
+ const [flow, setFlow] = (0, import_react.useState)("standard");
4694
+ const [stageBindings, setStageBindings] = (0, import_react.useState)({});
4695
+ const [source, setSource] = (0, import_react.useState)("default");
4696
+ const [savedAt, setSavedAt] = (0, import_react.useState)("");
4697
+ const [loadError, setLoadError] = (0, import_react.useState)("");
4698
+ const [skills, setSkills] = (0, import_react.useState)([]);
4699
+ const [rules, setRules] = (0, import_react.useState)([]);
4700
+ (0, import_react.useEffect)(() => {
4918
4701
  if (workspace === "") return;
4919
4702
  let alive = true;
4920
4703
  setLoadError("");
4921
4704
  void remote.read(workspace).then((result) => {
4922
4705
  if (!alive) return;
4923
4706
  if (result.ok) {
4924
- setConfig(result.value.config);
4707
+ setFlow(result.value.flow);
4708
+ setStageBindings(result.value.config.stage_bindings ?? {});
4925
4709
  setSource(result.value.source);
4926
- setLoadedProblems(result.value.source === "invalid" ? result.value.problems : []);
4927
4710
  setSavedAt("");
4928
4711
  } else {
4929
4712
  setLoadError("\u8BFB\u53D6\u914D\u7F6E\u5931\u8D25\uFF1A" + describeError(result.error));
@@ -4935,7 +4718,7 @@ function TaskEngineSection(props) {
4935
4718
  alive = false;
4936
4719
  };
4937
4720
  }, [remote, workspace]);
4938
- const refreshCatalogs = (0, import_react2.useCallback)(() => {
4721
+ const refreshCatalogs = (0, import_react.useCallback)(() => {
4939
4722
  if (workspace === "") return;
4940
4723
  void remote.listSkills(workspace).then((result) => {
4941
4724
  if (result.ok) setSkills(result.value.skills);
@@ -4946,21 +4729,17 @@ function TaskEngineSection(props) {
4946
4729
  }, () => {
4947
4730
  });
4948
4731
  }, [remote, workspace]);
4949
- (0, import_react2.useEffect)(() => {
4732
+ (0, import_react.useEffect)(() => {
4950
4733
  refreshCatalogs();
4951
4734
  }, [refreshCatalogs]);
4952
- const problems = (0, import_react2.useMemo)(() => config === null ? [] : validateWorkflow(config), [config]);
4953
- const notice = problems.length === 0 && loadedProblems.length > 0 ? loadedProblems : [];
4954
- const addTransition = (from, to) => {
4955
- if (config === null || from === "" || to === "") return;
4956
- update(config, setConfig, (c) => ({
4957
- ...c,
4958
- transitions: [...c.transitions, { from, to }]
4959
- }));
4960
- };
4961
- const removeTransition = (index) => {
4962
- if (config === null) return;
4963
- update(config, setConfig, (c) => ({ ...c, transitions: c.transitions.filter((_, j) => j !== index) }));
4735
+ const stages = (0, import_react.useMemo)(() => (FLOW_CONFIGS[flow] ?? FLOW_CONFIGS.standard).stages, [flow]);
4736
+ const problems = (0, import_react.useMemo)(
4737
+ () => validateWorkflow(resolveFlowConfig(flow, { stage_bindings: stageBindings })),
4738
+ [flow, stageBindings]
4739
+ );
4740
+ const selectFlow = (id) => {
4741
+ setFlow(id);
4742
+ setStageBindings({ ...FLOW_CONFIGS[id]?.stage_bindings ?? {} });
4964
4743
  };
4965
4744
  if (loadError !== "") {
4966
4745
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.wrap, children: [
@@ -4974,28 +4753,24 @@ function TaskEngineSection(props) {
4974
4753
  ] })
4975
4754
  ] });
4976
4755
  }
4977
- if (config === null) {
4978
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.wrap, children: [
4979
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { style: styles.title, children: "\u5DE5\u7A0B\u6D41\u7A0B\u914D\u7F6E" }),
4980
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.muted, children: "\u52A0\u8F7D\u4E2D\u2026" })
4981
- ] });
4982
- }
4983
4756
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.wrap, children: [
4984
4757
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.head, children: [
4985
4758
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { style: styles.title, children: "\u5DE5\u7A0B\u6D41\u7A0B\u914D\u7F6E" }),
4986
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.muted, children: "\u8FD9\u4EFD\u914D\u7F6E\u540C\u65F6\u9A71\u52A8 dev_task \u7684\u786C\u95E8\u7981\uFF1B\u6709\u95EE\u9898\u7684\u914D\u7F6E\u4E0D\u4F1A\u88AB\u4FDD\u5B58\u3002" })
4759
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.muted, children: "\u9009\u4E00\u5957\u6D41\u7A0B\uFF0C\u518D\u7ED9\u6BCF\u4E2A\u8282\u70B9\u6302\u4E0A skill / rule\u3002\u9636\u6BB5\u6D41\u8F6C\u3001\u5B88\u536B\u3001\u63D0\u4EA4\u89C4\u5219\u90FD\u7531\u6D41\u7A0B\u9884\u8BBE\u56FA\u5316\uFF0C\u65E0\u9700\u624B\u5DE5\u914D\u7F6E\u3002" })
4987
4760
  ] }),
4988
4761
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.sourceRow, children: [
4989
4762
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.StateDot, { state: source === "project" ? "done" : source === "invalid" ? "warning" : "ongoing" }),
4990
4763
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.sourceText, children: sourceText(source) })
4991
4764
  ] }),
4992
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TemplatePicker, { config, setConfig }),
4993
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.flowCard, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FlowDiagram, { config, onAddTransition: addTransition, onRemoveTransition: removeTransition }) }),
4994
- /* @__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 }) }),
4995
- /* @__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 }) }),
4996
- /* @__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\u5199\u6E05\u695A\u7684\u8BB0\u5F55\uFF09", defaultOpen: false, hint: "\u4EA7\u7269 = \u67D0\u9636\u6BB5\u5FC5\u987B\u4EA4\u4ED8\u7684\u4E00\u4EFD\u300C\u586B\u5199\u8BB0\u5F55\u300D\uFF1B\u5B57\u6BB5 = \u8FD9\u4EFD\u8BB0\u5F55\u91CC\u5927\u6A21\u578B\u5FC5\u987B\u586B\u4E0A\u7684\u7A7A\u3002\u4F8B\u5982\u300C\u9700\u6C42\u8BC4\u5BA1\u300D\u9636\u6BB5\u7684\u4EA7\u7269\u300C\u9700\u6C42\u8BF4\u660E\u300D\u8981\u586B scope\uFF08\u8303\u56F4\uFF09\u3001acceptance_criteria\uFF08\u9A8C\u6536\u6807\u51C6\uFF09\u4E24\u4E2A\u5B57\u6BB5\uFF1B\u518D\u7ED9\u300C\u9700\u6C42\u8BC4\u5BA1 \u2192 \u8BBE\u8BA1\u300D\u8FD9\u6761\u6D41\u8F6C\u6302\u4E0A\u300C\u4EA7\u7269\u5B57\u6BB5\u5DF2\u586B\u5168\u300D\u5B88\u536B\uFF0C\u5B57\u6BB5\u6CA1\u586B\u5168\u5C31\u8FDB\u4E0D\u4E86\u4E0B\u4E00\u9636\u6BB5\u3002", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ArtifactEditor, { config, setConfig }) }),
4997
- /* @__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 }) }),
4998
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SectionCard, { icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconBranchOutline16, { size: 16 }), title: "\u9636\u6BB5\u6280\u80FD / \u89C4\u5219", hint: "\u9009\u4E00\u4E2A\u9636\u6BB5\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\u5927\u6A21\u578B\u8D70\u5230\u8BE5\u9636\u6BB5\u65F6\uFF0C\u53EA\u4F1A\u770B\u5230\u7ED9\u5B83\u6302\u8F7D\u7684\u8FD9\u51E0\u6761\u6280\u80FD\u4E0E\u89C4\u5219\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, { config, setConfig, skills, rules }) }),
4765
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.field, children: [
4766
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.fieldLabel, children: "\u6D41\u7A0B\u9884\u8BBE" }),
4767
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.chips, children: FLOW_OPTIONS.map((option) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Pill, { active: flow === option.id, onClick: () => {
4768
+ selectFlow(option.id);
4769
+ }, title: option.description, children: option.label }, option.id)) }),
4770
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.hint, children: FLOW_OPTIONS.find((option) => option.id === flow)?.description })
4771
+ ] }),
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 === (FLOW_CONFIGS[flow]?.start_stage ?? ""), title: stage === FLOW_CONFIGS[flow]?.start_stage ? "\u8D77\u59CB\u9636\u6BB5" : void 0, children: stage }, 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\u6A21\u578B\u8D70\u5230\u8BE5\u8282\u70B9\u65F6\u53EA\u4F1A\u770B\u5230\u4F60\u6302\u8F7D\u7684\u8FD9\u51E0\u6761\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 }) }),
4999
4774
  problems.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.problems, children: [
5000
4775
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: styles.problemsTitle, children: [
5001
4776
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.StateDot, { state: "error" }),
@@ -5004,16 +4779,9 @@ function TaskEngineSection(props) {
5004
4779
  " \u4E2A\u95EE\u9898\uFF08\u4FDD\u5B58\u4F1A\u88AB\u62D2\u7EDD\uFF09"
5005
4780
  ] }),
5006
4781
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { style: styles.problemsList, children: problems.map((p) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("li", { children: p }, p)) })
5007
- ] }) : notice.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.noticeBox, children: [
5008
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: styles.noticeTitle, children: [
5009
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.StateDot, { state: "warning" }),
5010
- "\u539F .dsh/eng.json \u65E0\u6CD5\u89E3\u6790"
5011
- ] }),
5012
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { style: styles.problemsList, children: notice.map((p) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("li", { children: p }, p)) }),
5013
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.muted, children: "\u5F53\u524D\u663E\u793A\u5185\u7F6E\u9ED8\u8BA4\u914D\u7F6E\uFF1B\u70B9\u51FB\u4FDD\u5B58\u4F1A\u8986\u76D6\u539F\u6587\u4EF6\u3002" })
5014
4782
  ] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: styles.okText, children: [
5015
4783
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.StateDot, { state: "done" }),
5016
- source === "default" ? "\u5F53\u524D\u4F7F\u7528\u5185\u7F6E\u9ED8\u8BA4\u914D\u7F6E" : "\u914D\u7F6E\u6709\u6548"
4784
+ source === "project" ? "\u914D\u7F6E\u6709\u6548" : "\u4F7F\u7528\u6D41\u7A0B\u9884\u8BBE\u9ED8\u8BA4\u7ED1\u5B9A\uFF08\u5C1A\u672A\u4FDD\u5B58\uFF09"
5017
4785
  ] }),
5018
4786
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.actions, children: [
5019
4787
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
@@ -5024,7 +4792,7 @@ function TaskEngineSection(props) {
5024
4792
  icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconCheckOutline16, { size: 16 }),
5025
4793
  disabled: problems.length > 0,
5026
4794
  onClick: () => {
5027
- void save(remote, config, workspace, setSavedAt, setSource, setLoadedProblems);
4795
+ void save(remote, flow, stageBindings, workspace, setSavedAt, setSource);
5028
4796
  },
5029
4797
  children: "\u4FDD\u5B58\u5230 .dsh/eng.json"
5030
4798
  }
@@ -5041,13 +4809,13 @@ function sourceText(source) {
5041
4809
  case "project":
5042
4810
  return "\u9879\u76EE\u914D\u7F6E\uFF08.dsh/eng.json\uFF09";
5043
4811
  case "invalid":
5044
- return "\u539F\u6587\u4EF6\u65E0\u6CD5\u89E3\u6790\uFF0C\u663E\u793A\u5185\u7F6E\u9ED8\u8BA4\u914D\u7F6E";
4812
+ return "\u539F\u6587\u4EF6\u65E0\u6CD5\u89E3\u6790\uFF0C\u663E\u793A\u6807\u51C6\u9884\u8BBE";
5045
4813
  default:
5046
- return "\u5185\u7F6E\u9ED8\u8BA4\u914D\u7F6E\uFF08\u5DE5\u4F5C\u533A\u5C1A\u65E0 .dsh/eng.json\uFF09";
4814
+ return "\u6807\u51C6\u9884\u8BBE\uFF08\u5DE5\u4F5C\u533A\u5C1A\u65E0 .dsh/eng.json\uFF09";
5047
4815
  }
5048
4816
  }
5049
- function SectionCard({ icon, title, hint, defaultOpen = true, children }) {
5050
- const [open, setOpen] = (0, import_react2.useState)(defaultOpen);
4817
+ function SectionCard({ icon, title, hint, children }) {
4818
+ const [open, setOpen] = (0, import_react.useState)(true);
5051
4819
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.section, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
5052
4820
  import_dsh_client_ui_primitives.DisclosureRow,
5053
4821
  {
@@ -5066,301 +4834,36 @@ function SectionCard({ icon, title, hint, defaultOpen = true, children }) {
5066
4834
  }
5067
4835
  ) });
5068
4836
  }
5069
- function TemplatePicker({ config, setConfig }) {
5070
- const apply2 = (id) => {
5071
- const template = WORKFLOW_TEMPLATES.find((t) => t.id === id);
5072
- if (template === void 0) return;
5073
- setConfig(cloneConfig(template.config));
5074
- };
5075
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.field, children: [
5076
- /* @__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" }),
5077
- /* @__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: () => {
5078
- apply2(t.id);
5079
- }, title: t.description, children: t.label }, t.id)) }),
5080
- /* @__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" })
5081
- ] });
5082
- }
5083
- function cloneConfig(config) {
5084
- return JSON.parse(JSON.stringify(config));
5085
- }
5086
- function StageEditor({ config, setConfig }) {
5087
- const [draft, setDraft] = (0, import_react2.useState)("");
5088
- const addStage = () => {
5089
- const name = draft.trim();
5090
- if (name === "" || config.stages.includes(name)) return;
5091
- update(config, setConfig, (c) => ({ ...c, stages: [...c.stages, name] }));
5092
- setDraft("");
5093
- };
5094
- const removeStage = (stage) => {
5095
- update(config, setConfig, (c) => {
5096
- const stages = c.stages.filter((s) => s !== stage);
5097
- return {
5098
- ...c,
5099
- stages,
5100
- start_stage: c.start_stage === stage ? stages[0] ?? "" : c.start_stage
5101
- };
5102
- });
5103
- };
5104
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.section, children: [
5105
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.chips, children: config.stages.map((stage) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
5106
- import_dsh_client_ui_primitives.Pill,
5107
- {
5108
- active: stage === config.start_stage,
5109
- onClick: stage === config.start_stage ? void 0 : () => {
5110
- removeStage(stage);
5111
- },
5112
- title: stage === config.start_stage ? "\u8D77\u59CB\u9636\u6BB5" : `\u70B9\u51FB\u5220\u9664 ${stage}`,
5113
- children: stage
5114
- },
5115
- stage
5116
- )) }),
5117
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.row, children: [
5118
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
5119
- "input",
5120
- {
5121
- style: { ...control, flex: "1 1 180px" },
5122
- placeholder: "\u65B0\u9636\u6BB5\u540D",
5123
- value: draft,
5124
- onChange: (ev) => {
5125
- setDraft(ev.target.value);
5126
- },
5127
- onKeyDown: (ev) => {
5128
- if (ev.key === "Enter") addStage();
5129
- }
5130
- }
5131
- ),
5132
- /* @__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: draft.trim() === "", onClick: addStage, children: "\u6DFB\u52A0\u9636\u6BB5" })
5133
- ] }),
5134
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.row, children: [
5135
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.fieldLabel, children: "\u8D77\u59CB\u9636\u6BB5" }),
5136
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
5137
- "select",
5138
- {
5139
- style: control,
5140
- value: config.start_stage,
5141
- onChange: (ev) => {
5142
- update(config, setConfig, (c) => ({ ...c, start_stage: ev.target.value }));
5143
- },
5144
- children: config.stages.map((s) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: s, children: s }, s))
5145
- }
5146
- )
5147
- ] })
5148
- ] });
5149
- }
5150
- function TransitionEditor({ config, setConfig }) {
5151
- const setTransition = (i, patch) => {
5152
- update(config, setConfig, (c) => ({
5153
- ...c,
5154
- transitions: c.transitions.map((t, j) => j === i ? { ...t, ...patch } : t)
5155
- }));
5156
- };
5157
- const toggleGuard = (i, guard) => {
5158
- const t = config.transitions[i];
5159
- if (t === void 0) return;
5160
- const current = t.requires ?? [];
5161
- const next = current.includes(guard) ? current.filter((g) => g !== guard) : [...current, guard];
5162
- setTransition(i, { requires: next });
5163
- };
5164
- const remove = (i) => {
5165
- update(config, setConfig, (c) => ({ ...c, transitions: c.transitions.filter((_, j) => j !== i) }));
5166
- };
5167
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.section, children: [
5168
- config.transitions.map((t, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: cardV, children: [
5169
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.row, children: [
5170
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("select", { style: control, value: t.from, onChange: (ev) => {
5171
- setTransition(i, { from: ev.target.value });
5172
- }, children: config.stages.map((s) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: s, children: s }, s)) }),
5173
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { color: textTertiary3 }, children: "\u2192" }),
5174
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("select", { style: control, value: t.to, onChange: (ev) => {
5175
- setTransition(i, { to: ev.target.value });
5176
- }, children: config.stages.map((s) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: s, children: s }, s)) }),
5177
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { variant: "ghost", size: "sm", icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconCloseOutline16, { size: 14 }), onClick: () => {
5178
- remove(i);
5179
- }, title: "\u5220\u9664\u8FD9\u6761\u6D41\u8F6C" })
5180
- ] }),
5181
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.chips, children: GUARD_OPTIONS.map((g) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
5182
- import_dsh_client_ui_primitives.Pill,
5183
- {
5184
- active: (t.requires ?? []).includes(g.value),
5185
- onClick: () => {
5186
- toggleGuard(i, g.value);
5187
- },
5188
- title: g.hint,
5189
- children: g.label
5190
- },
5191
- g.value
5192
- )) })
5193
- ] }, i)),
5194
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
5195
- import_dsh_client_ui_primitives.Button,
5196
- {
5197
- variant: "outline",
5198
- size: "sm",
5199
- icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconPlusOutline16, { size: 14 }),
5200
- onClick: () => {
5201
- update(config, setConfig, (c) => ({ ...c, transitions: [...c.transitions, { from: c.start_stage, to: c.start_stage }] }));
5202
- },
5203
- children: "\u52A0\u4E00\u6761\u6D41\u8F6C"
5204
- }
5205
- ) })
5206
- ] });
5207
- }
5208
- function ArtifactEditor({ config, setConfig }) {
5209
- const setArtifact = (i, patch) => {
5210
- update(config, setConfig, (c) => ({
5211
- ...c,
5212
- artifacts: c.artifacts.map((a, j) => j === i ? { ...a, ...patch } : a)
5213
- }));
5214
- };
5215
- const remove = (i) => {
5216
- update(config, setConfig, (c) => ({ ...c, artifacts: c.artifacts.filter((_, j) => j !== i) }));
5217
- };
5218
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.section, children: [
5219
- config.artifacts.map((a, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: cardV, children: [
5220
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.row, children: [
5221
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("select", { style: control, value: a.stage, onChange: (ev) => {
5222
- setArtifact(i, { stage: ev.target.value });
5223
- }, children: config.stages.map((s) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: s, children: s }, s)) }),
5224
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { style: { ...control, flex: "1 1 110px" }, placeholder: "\u82F1\u6587 id\uFF08\u5982 requirement\uFF09", value: a.id, onChange: (ev) => {
5225
- setArtifact(i, { id: ev.target.value });
5226
- } }),
5227
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { style: { ...control, flex: "1 1 130px" }, placeholder: "\u540D\u79F0\uFF08\u7ED9\u4EBA\u770B\uFF0C\u5982 \u9700\u6C42\u8BF4\u660E\uFF09", value: a.name, onChange: (ev) => {
5228
- setArtifact(i, { name: ev.target.value });
5229
- } }),
5230
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { variant: "ghost", size: "sm", icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconCloseOutline16, { size: 14 }), onClick: () => {
5231
- remove(i);
5232
- }, title: "\u5220\u9664\u8FD9\u4E2A\u4EA7\u7269" })
5233
- ] }),
5234
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
5235
- "input",
5236
- {
5237
- style: control,
5238
- placeholder: "\u8981\u586B\u7684\u5B57\u6BB5\uFF0C\u9017\u53F7\u5206\u9694\uFF08\u5982 scope, acceptance_criteria\uFF09",
5239
- value: a.fields.join(", "),
5240
- onChange: (ev) => {
5241
- setArtifact(i, { fields: splitList(ev.target.value) });
5242
- }
5243
- }
5244
- )
5245
- ] }, i)),
5246
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
5247
- import_dsh_client_ui_primitives.Button,
5248
- {
5249
- variant: "outline",
5250
- size: "sm",
5251
- icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconPlusOutline16, { size: 14 }),
5252
- onClick: () => {
5253
- update(config, setConfig, (c) => ({ ...c, artifacts: [...c.artifacts, { stage: c.start_stage, id: "", name: "", fields: [] }] }));
5254
- },
5255
- children: "\u52A0\u4E00\u4E2A\u4EA7\u7269"
5256
- }
5257
- ) })
5258
- ] });
5259
- }
5260
- function CommitEditor({ config, setConfig }) {
5261
- const commit = config.commit;
5262
- const setCommit = (patch) => {
5263
- update(config, setConfig, (c) => ({ ...c, commit: { ...c.commit, ...patch } }));
5264
- };
5265
- const toggleCheckpoint = (stage) => {
5266
- const current = commit.checkpoints;
5267
- const next = current.includes(stage) ? current.filter((s) => s !== stage) : [...current, stage];
5268
- setCommit({ checkpoints: next });
5269
- };
5270
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.section, children: [
5271
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.field, children: [
5272
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.fieldLabel, children: "\u63D0\u4EA4\u7B56\u7565" }),
5273
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.chips, children: POLICY_OPTIONS.map((p) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Pill, { active: commit.policy === p.value, onClick: () => {
5274
- setCommit({ policy: p.value });
5275
- }, title: p.hint, children: p.label }, p.value)) }),
5276
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.hint, children: POLICY_OPTIONS.find((p) => p.value === commit.policy)?.hint })
5277
- ] }),
5278
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.row, children: [
5279
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { style: styles.field, children: [
5280
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.fieldLabel, children: "\u63D0\u4EA4\u6D88\u606F\u683C\u5F0F\uFF08\u6B63\u5219\uFF0C\u7559\u7A7A\u5219\u4E0D\u6821\u9A8C\uFF09" }),
5281
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { style: control, value: commit.message_pattern, onChange: (ev) => {
5282
- setCommit({ message_pattern: ev.target.value });
5283
- } })
5284
- ] }),
5285
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { style: styles.field, children: [
5286
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.fieldLabel, children: "\u683C\u5F0F\u8BF4\u660E" }),
5287
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { style: control, value: commit.message_hint, onChange: (ev) => {
5288
- setCommit({ message_hint: ev.target.value });
5289
- } })
5290
- ] })
5291
- ] }),
5292
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.field, children: [
5293
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.fieldLabel, children: "\u63D0\u4EA4\u68C0\u67E5\u70B9\uFF08\u5230\u8FBE\u8FD9\u4E9B\u9636\u6BB5\u524D\u9700\u63D0\u4EA4\uFF09" }),
5294
- /* @__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: commit.checkpoints.includes(s), onClick: () => {
5295
- toggleCheckpoint(s);
5296
- }, title: `\u68C0\u67E5\u70B9 ${s}`, children: s }, s)) })
5297
- ] }),
5298
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.field, children: [
5299
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.inline, children: [
5300
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
5301
- "input",
5302
- {
5303
- type: "checkbox",
5304
- checked: commit.file_scope,
5305
- onChange: (ev) => {
5306
- setCommit({ file_scope: ev.target.checked });
5307
- }
5308
- }
5309
- ),
5310
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.fieldLabel, children: "\u6587\u4EF6\u8303\u56F4\u5F00\u5173\uFF08\u63D0\u4EA4\u53EA\u5141\u8BB8\u4EFB\u52A1\u91CC\u58F0\u660E\u7684\u6587\u4EF6\uFF09" })
5311
- ] }),
5312
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.inline, children: [
5313
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
5314
- "input",
5315
- {
5316
- type: "checkbox",
5317
- checked: config.high_risk_requires_verification,
5318
- onChange: (ev) => {
5319
- update(config, setConfig, (c) => ({ ...c, high_risk_requires_verification: ev.target.checked }));
5320
- }
5321
- }
5322
- ),
5323
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.fieldLabel, children: "\u9AD8\u98CE\u9669\u4EFB\u52A1\u5FC5\u987B\u9644\u9A8C\u8BC1\u8BC1\u636E\u624D\u80FD\u8FC7 verified \u5B88\u536B" })
5324
- ] })
5325
- ] })
5326
- ] });
5327
- }
5328
- function BindingEditor({ config, setConfig, skills, rules }) {
5329
- const [stage, setStage] = (0, import_react2.useState)(config.stages[0] ?? "");
5330
- const currentStage = config.stages.includes(stage) ? stage : config.stages[0] ?? "";
4837
+ function BindingEditor({ stages, stageBindings, setStageBindings, skills, rules }) {
4838
+ const [stage, setStage] = (0, import_react.useState)(stages[0] ?? "");
4839
+ const currentStage = stages.includes(stage) ? stage : stages[0] ?? "";
5331
4840
  const toggleSkill = (skill) => {
5332
4841
  if (currentStage === "") return;
5333
- update(config, setConfig, (c) => {
5334
- const bindings = c.stage_bindings ?? {};
5335
- const current = bindings[currentStage]?.skills ?? [];
5336
- const next = current.includes(skill) ? current.filter((s) => s !== skill) : [...current, skill].sort();
5337
- return { ...c, stage_bindings: { ...bindings, [currentStage]: { ...bindings[currentStage] ?? {}, skills: next } } };
5338
- });
4842
+ const current = stageBindings[currentStage]?.skills ?? [];
4843
+ const next = current.includes(skill) ? current.filter((s) => s !== skill) : [...current, skill].sort();
4844
+ setStageBindings({ ...stageBindings, [currentStage]: { ...stageBindings[currentStage] ?? {}, skills: next } });
5339
4845
  };
5340
4846
  const toggleRule = (rule) => {
5341
4847
  if (currentStage === "") return;
5342
- update(config, setConfig, (c) => {
5343
- const bindings = c.stage_bindings ?? {};
5344
- const current = bindings[currentStage]?.rules ?? [];
5345
- const next = current.includes(rule) ? current.filter((s) => s !== rule) : [...current, rule].sort();
5346
- return { ...c, stage_bindings: { ...bindings, [currentStage]: { ...bindings[currentStage] ?? {}, rules: next } } };
5347
- });
4848
+ const current = stageBindings[currentStage]?.rules ?? [];
4849
+ const next = current.includes(rule) ? current.filter((s) => s !== rule) : [...current, rule].sort();
4850
+ setStageBindings({ ...stageBindings, [currentStage]: { ...stageBindings[currentStage] ?? {}, rules: next } });
5348
4851
  };
5349
4852
  if (currentStage === "") {
5350
- 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" });
4853
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.muted, children: "\u5F53\u524D\u6D41\u7A0B\u6CA1\u6709\u8282\u70B9\u3002" });
5351
4854
  }
5352
- const boundSkills = config.stage_bindings?.[currentStage]?.skills ?? [];
5353
- const boundRules = config.stage_bindings?.[currentStage]?.rules ?? [];
4855
+ const boundSkills = stageBindings[currentStage]?.skills ?? [];
4856
+ const boundRules = stageBindings[currentStage]?.rules ?? [];
5354
4857
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.section, children: [
5355
4858
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.field, children: [
5356
- /* @__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" }),
5357
- /* @__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: () => {
4859
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.fieldLabel, children: "\u9009\u62E9\u8282\u70B9\uFF08\u6539\u54EA\u4E2A\u8282\u70B9\u7684\u6302\u8F7D\uFF09" }),
4860
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.chips, children: stages.map((s) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Pill, { active: s === currentStage, onClick: () => {
5358
4861
  setStage(s);
5359
4862
  }, children: s }, s)) })
5360
4863
  ] }),
5361
4864
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: cardV, children: [
5362
4865
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.bindingStage, children: [
5363
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.fieldLabel, children: "skill\uFF08\u8FD9\u4E2A\u9636\u6BB5\u505A\u4EC0\u4E48\uFF09" }),
4866
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.fieldLabel, children: "skill\uFF08\u8FD9\u4E2A\u8282\u70B9\u505A\u4EC0\u4E48\uFF09" }),
5364
4867
  /* @__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 \u2014\u2014 \u5207\u5230\u4E0A\u65B9\u300C\u6280\u80FD\u300D\u6807\u7B7E\u9875\u65B0\u5EFA" }) : skills.map((sk) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_dsh_client_ui_primitives.Pill, { active: boundSkills.includes(sk.name), onClick: () => {
5365
4868
  toggleSkill(sk.name);
5366
4869
  }, title: `${sk.description}\uFF08${sourceLabel(sk.source)}\uFF09`, children: [
@@ -5373,7 +4876,7 @@ function BindingEditor({ config, setConfig, skills, rules }) {
5373
4876
  ] }, sk.name)) })
5374
4877
  ] }),
5375
4878
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.bindingStage, children: [
5376
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.fieldLabel, children: "rule\uFF08\u8FD9\u4E2A\u9636\u6BB5\u5B88\u4EC0\u4E48\uFF09" }),
4879
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.fieldLabel, children: "rule\uFF08\u8FD9\u4E2A\u8282\u70B9\u5B88\u4EC0\u4E48\uFF09" }),
5377
4880
  /* @__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 \u2014\u2014 \u5207\u5230\u4E0A\u65B9\u300C\u89C4\u5219\u300D\u6807\u7B7E\u9875\u65B0\u5EFA" }) : rules.map((rule) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_dsh_client_ui_primitives.Pill, { active: boundRules.includes(rule.name), onClick: () => {
5378
4881
  toggleRule(rule.name);
5379
4882
  }, title: `\u6765\u6E90\uFF1A${sourceLabel(rule.source)}`, children: [
@@ -5385,31 +4888,148 @@ function BindingEditor({ config, setConfig, skills, rules }) {
5385
4888
  ] }) : null
5386
4889
  ] }, rule.name)) })
5387
4890
  ] }),
5388
- 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
4891
+ boundSkills.length === 0 && boundRules.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.hint, children: "\u8FD9\u4E2A\u8282\u70B9\u8FD8\u6CA1\u6302\u4EFB\u4F55 skill / rule \u2014\u2014 \u70B9\u4E0A\u9762\u7684\u540D\u79F0\u52FE\u9009\u3002" }) : null
5389
4892
  ] })
5390
4893
  ] });
5391
4894
  }
5392
- function update(config, setConfig, fn) {
5393
- setConfig(fn(config));
5394
- }
5395
- async function save(remote, config, workspace, setSavedAt, setSource, setLoadedProblems) {
5396
- const result = await remote.write({ path: workspace, config });
4895
+ async function save(remote, flow, stageBindings, workspace, setSavedAt, setSource) {
4896
+ const result = await remote.write({ path: workspace, flow, stage_bindings: stageBindings });
5397
4897
  if (!result.ok) {
5398
4898
  setSavedAt("\u4FDD\u5B58\u5931\u8D25\uFF1A" + describeError(result.error));
5399
4899
  return;
5400
4900
  }
5401
4901
  setSource(result.value.source);
5402
- setLoadedProblems(result.value.source === "invalid" ? result.value.problems : []);
5403
4902
  setSavedAt(result.value.ok ? "\u5DF2\u4FDD\u5B58" : "");
5404
4903
  }
5405
- function splitList(textInput) {
5406
- return textInput.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
5407
- }
5408
4904
 
5409
4905
  // src/client/SkillManager.tsx
5410
4906
  var import_react3 = require("react");
4907
+ var import_dsh_client_ui_primitives3 = require("@deepseek-ai/dsh-client-ui-primitives");
4908
+
4909
+ // src/client/ResourceModal.tsx
4910
+ var import_react2 = require("react");
4911
+ var import_react_dom = require("react-dom");
5411
4912
  var import_dsh_client_ui_primitives2 = require("@deepseek-ai/dsh-client-ui-primitives");
5412
- var control2 = {
4913
+ var rootStyle = {
4914
+ position: "fixed",
4915
+ inset: 0,
4916
+ zIndex: 1e3,
4917
+ display: "flex",
4918
+ alignItems: "center",
4919
+ justifyContent: "center",
4920
+ padding: 24
4921
+ };
4922
+ var maskStyle = {
4923
+ position: "absolute",
4924
+ inset: 0,
4925
+ background: "var(--dsw-alias-bg-mask-1)",
4926
+ backdropFilter: "var(--dsw-mask-blur)"
4927
+ };
4928
+ var dialogStyle = {
4929
+ position: "relative",
4930
+ zIndex: 1,
4931
+ display: "flex",
4932
+ flexDirection: "column",
4933
+ width: "min(760px, 100%)",
4934
+ maxHeight: "85vh",
4935
+ borderRadius: 24,
4936
+ background: "var(--dsw-alias-bg-layer-2)",
4937
+ boxShadow: "var(--dsw-elevation-prominent)",
4938
+ overflow: "hidden"
4939
+ };
4940
+ var headerStyle = {
4941
+ display: "flex",
4942
+ alignItems: "center",
4943
+ justifyContent: "space-between",
4944
+ gap: 8,
4945
+ padding: "18px 18px 10px 24px",
4946
+ flex: "none"
4947
+ };
4948
+ var titleStyle = {
4949
+ margin: 0,
4950
+ fontSize: 16,
4951
+ lineHeight: "24px",
4952
+ fontWeight: 500,
4953
+ color: "var(--dsw-alias-label-primary)"
4954
+ };
4955
+ var closeBtnStyle = {
4956
+ flex: "none",
4957
+ display: "inline-flex",
4958
+ alignItems: "center",
4959
+ justifyContent: "center",
4960
+ width: 28,
4961
+ height: 28,
4962
+ border: "none",
4963
+ borderRadius: 8,
4964
+ background: "transparent",
4965
+ cursor: "pointer",
4966
+ color: "var(--dsw-alias-label-secondary)",
4967
+ padding: 0
4968
+ };
4969
+ var descStyle = {
4970
+ margin: 0,
4971
+ padding: "0 24px",
4972
+ fontSize: 13,
4973
+ lineHeight: "20px",
4974
+ color: "var(--dsw-alias-label-secondary)",
4975
+ flex: "none"
4976
+ };
4977
+ var bodyStyle = {
4978
+ flex: "1 1 auto",
4979
+ minHeight: 0,
4980
+ overflowY: "auto",
4981
+ padding: "16px 24px 4px",
4982
+ display: "flex",
4983
+ flexDirection: "column"
4984
+ };
4985
+ var footerStyle = {
4986
+ display: "flex",
4987
+ alignItems: "center",
4988
+ justifyContent: "flex-end",
4989
+ gap: 8,
4990
+ padding: "12px 24px 20px",
4991
+ flex: "none"
4992
+ };
4993
+ function ResourceModal({ title, description, onClose, footer, children }) {
4994
+ (0, import_react2.useEffect)(() => {
4995
+ const onKey = (e) => {
4996
+ if (e.key === "Escape") onClose();
4997
+ };
4998
+ document.addEventListener("keydown", onKey);
4999
+ return () => {
5000
+ document.removeEventListener("keydown", onKey);
5001
+ };
5002
+ }, [onClose]);
5003
+ return (0, import_react_dom.createPortal)(
5004
+ (0, import_react2.createElement)(
5005
+ "div",
5006
+ { style: rootStyle, role: "presentation" },
5007
+ (0, import_react2.createElement)("div", { style: maskStyle, "aria-hidden": true, onClick: onClose }),
5008
+ (0, import_react2.createElement)(
5009
+ "div",
5010
+ { style: dialogStyle, role: "dialog", "aria-modal": true, "aria-label": title },
5011
+ (0, import_react2.createElement)(
5012
+ "div",
5013
+ { style: headerStyle },
5014
+ (0, import_react2.createElement)("h2", { style: titleStyle }, title),
5015
+ (0, import_react2.createElement)(
5016
+ "button",
5017
+ { type: "button", style: closeBtnStyle, "aria-label": "\u5173\u95ED", onClick: onClose },
5018
+ (0, import_react2.createElement)(import_dsh_client_ui_primitives2.IconCloseOutline16, { size: 14 })
5019
+ )
5020
+ ),
5021
+ description !== void 0 && description !== "" ? (0, import_react2.createElement)("p", { style: descStyle }, description) : null,
5022
+ (0, import_react2.createElement)("div", { style: bodyStyle }, children),
5023
+ footer !== void 0 ? (0, import_react2.createElement)("div", { style: footerStyle }, footer) : null
5024
+ )
5025
+ ),
5026
+ document.body
5027
+ );
5028
+ }
5029
+
5030
+ // src/client/SkillManager.tsx
5031
+ var MD_LABELS = { code: { copyLabel: "\u590D\u5236", copiedLabel: "\u5DF2\u590D\u5236" }, footnotes: "\u811A\u6CE8" };
5032
+ var control = {
5413
5033
  background: "var(--dsw-alias-bg-layer-1)",
5414
5034
  border: "1px solid var(--dsw-alias-border-l2)",
5415
5035
  borderRadius: 8,
@@ -5561,17 +5181,17 @@ function SkillManager({ workspace, remote }) {
5561
5181
  ),
5562
5182
  (0, import_react3.createElement)("span", { style: styles.sourceBadge }, sk.description)
5563
5183
  ),
5564
- sk.source === "bundled" ? (0, import_react3.createElement)(import_dsh_client_ui_primitives2.Button, { variant: "outline", size: "sm", onClick: () => {
5184
+ sk.source === "bundled" ? (0, import_react3.createElement)(import_dsh_client_ui_primitives3.Button, { variant: "outline", size: "sm", onClick: () => {
5565
5185
  startView(sk);
5566
5186
  } }, "\u67E5\u770B") : (0, import_react3.createElement)(
5567
5187
  "div",
5568
5188
  { style: { display: "flex", gap: 6 } },
5569
- (0, import_react3.createElement)(import_dsh_client_ui_primitives2.Button, { variant: "outline", size: "sm", onClick: () => {
5189
+ (0, import_react3.createElement)(import_dsh_client_ui_primitives3.Button, { variant: "outline", size: "sm", onClick: () => {
5570
5190
  startEdit(sk);
5571
5191
  } }, "\u7F16\u8F91"),
5572
- confirming === sk.name ? (0, import_react3.createElement)(import_dsh_client_ui_primitives2.Button, { variant: "primary", size: "sm", onClick: () => {
5192
+ confirming === sk.name ? (0, import_react3.createElement)(import_dsh_client_ui_primitives3.Button, { variant: "primary", size: "sm", onClick: () => {
5573
5193
  void remove(sk);
5574
- } }, "\u786E\u8BA4\u5220\u9664") : (0, import_react3.createElement)(import_dsh_client_ui_primitives2.Button, { variant: "ghost", size: "sm", onClick: () => {
5194
+ } }, "\u786E\u8BA4\u5220\u9664") : (0, import_react3.createElement)(import_dsh_client_ui_primitives3.Button, { variant: "ghost", size: "sm", onClick: () => {
5575
5195
  setConfirming(sk.name);
5576
5196
  } }, "\u5220\u9664")
5577
5197
  )
@@ -5579,60 +5199,57 @@ function SkillManager({ workspace, remote }) {
5579
5199
  const renderForm = () => {
5580
5200
  if (viewing) {
5581
5201
  return (0, import_react3.createElement)(
5582
- "div",
5583
- { style: card },
5584
- (0, import_react3.createElement)("span", { style: styles.bindingLabel }, `\u67E5\u770B skill\u300C${editing ?? ""}\u300D\uFF08\u5185\u7F6E \xB7 \u53EA\u8BFB\uFF09`),
5585
- (0, import_react3.createElement)("input", { style: control2, value: name, disabled: true, readOnly: true }),
5586
- (0, import_react3.createElement)("input", { style: control2, value: description, disabled: true, readOnly: true }),
5587
- (0, import_react3.createElement)("input", { style: control2, value: whenToUse, disabled: true, readOnly: true }),
5588
- (0, import_react3.createElement)("textarea", { style: { ...styles.textarea, minHeight: 220 }, value: body2, disabled: true, readOnly: true }),
5589
- (0, import_react3.createElement)(
5590
- "div",
5591
- { style: styles.row },
5592
- (0, import_react3.createElement)(import_dsh_client_ui_primitives2.Button, { variant: "ghost", size: "sm", onClick: closeForm }, "\u5173\u95ED")
5593
- ),
5594
- msg !== "" ? (0, import_react3.createElement)("p", { style: styles.status }, msg) : null
5202
+ ResourceModal,
5203
+ {
5204
+ title: `\u67E5\u770B skill\u300C${editing ?? ""}\u300D`,
5205
+ description: "\u5185\u7F6E \xB7 \u53EA\u8BFB" + (whenToUse !== "" && whenToUse !== void 0 ? ` \xB7 \u4F7F\u7528\u65F6\u673A\uFF1A${whenToUse}` : ""),
5206
+ onClose: closeForm,
5207
+ footer: (0, import_react3.createElement)(import_dsh_client_ui_primitives3.Button, { variant: "ghost", size: "sm", onClick: closeForm }, "\u5173\u95ED")
5208
+ },
5209
+ (0, import_react3.createElement)(import_dsh_client_ui_primitives3.MarkdownText, { text: body2, labels: MD_LABELS })
5595
5210
  );
5596
5211
  }
5597
5212
  return (0, import_react3.createElement)(
5598
- "div",
5599
- { style: card },
5600
- (0, import_react3.createElement)("span", { style: styles.bindingLabel }, editing === null ? "\u65B0\u5EFA skill" : `\u7F16\u8F91 skill\u300C${editing}\u300D`),
5213
+ ResourceModal,
5214
+ {
5215
+ title: editing === null ? "\u65B0\u5EFA skill" : `\u7F16\u8F91 skill\u300C${editing ?? ""}\u300D`,
5216
+ onClose: closeForm,
5217
+ footer: (0, import_react3.createElement)(
5218
+ "div",
5219
+ { style: styles.row },
5220
+ (0, import_react3.createElement)(import_dsh_client_ui_primitives3.Button, {
5221
+ variant: "primary",
5222
+ size: "sm",
5223
+ disabled: editing === null && name.trim() === "" || description.trim() === "" || body2.trim() === "",
5224
+ onClick: () => {
5225
+ void submit();
5226
+ }
5227
+ }, "\u4FDD\u5B58"),
5228
+ (0, import_react3.createElement)(import_dsh_client_ui_primitives3.Button, { variant: "ghost", size: "sm", onClick: closeForm }, "\u53D6\u6D88")
5229
+ )
5230
+ },
5601
5231
  (0, import_react3.createElement)(
5602
5232
  "div",
5603
5233
  { style: styles.chips },
5604
- (0, import_react3.createElement)(import_dsh_client_ui_primitives2.Pill, { active: level === "project", onClick: () => {
5234
+ (0, import_react3.createElement)(import_dsh_client_ui_primitives3.Pill, { active: level === "project", onClick: () => {
5605
5235
  setLevel("project");
5606
5236
  }, title: "\u5199\u5230\u5DE5\u4F5C\u533A .dsh/skills\uFF0C\u56E2\u961F\u5171\u4EAB" }, "\u9879\u76EE\u7EA7"),
5607
- (0, import_react3.createElement)(import_dsh_client_ui_primitives2.Pill, { active: level === "user", onClick: () => {
5237
+ (0, import_react3.createElement)(import_dsh_client_ui_primitives3.Pill, { active: level === "user", onClick: () => {
5608
5238
  setLevel("user");
5609
5239
  }, title: "\u5199\u5230 $DSH_HOME/skills\uFF0C\u4E2A\u4EBA\u6240\u6709\u9879\u76EE\u53EF\u7528" }, "\u7528\u6237\u7EA7")
5610
5240
  ),
5611
- editing === null ? (0, import_react3.createElement)("input", { style: control2, placeholder: "name\uFF08\u5982 my-skill\uFF0C\u53EA\u542B\u5C0F\u5199\u5B57\u6BCD\u6570\u5B57\u548C -\uFF09", value: name, onChange: (ev) => {
5241
+ editing === null ? (0, import_react3.createElement)("input", { style: control, placeholder: "name\uFF08\u5982 my-skill\uFF0C\u53EA\u542B\u5C0F\u5199\u5B57\u6BCD\u6570\u5B57\u548C -\uFF09", value: name, onChange: (ev) => {
5612
5242
  setName(ev.target.value);
5613
5243
  } }) : (0, import_react3.createElement)("span", { style: styles.sourceBadge }, `name \u56FA\u5B9A\u4E3A ${name}\uFF08\u6539\u540D\u8BF7\u5220\u9664\u540E\u91CD\u5EFA\uFF09`),
5614
- (0, import_react3.createElement)("input", { style: control2, placeholder: "description\uFF08\u4E00\u53E5\u8BDD\u8BF4\u660E\u5B83\u505A\u4EC0\u4E48\uFF09", value: description, onChange: (ev) => {
5244
+ (0, import_react3.createElement)("input", { style: control, placeholder: "description\uFF08\u4E00\u53E5\u8BDD\u8BF4\u660E\u5B83\u505A\u4EC0\u4E48\uFF09", value: description, onChange: (ev) => {
5615
5245
  setDescription(ev.target.value);
5616
5246
  } }),
5617
- (0, import_react3.createElement)("input", { style: control2, placeholder: "whenToUse\uFF08\u53EF\u9009\uFF1A\u4EC0\u4E48\u60C5\u51B5\u8BE5\u7528\uFF09", value: whenToUse, onChange: (ev) => {
5247
+ (0, import_react3.createElement)("input", { style: control, placeholder: "whenToUse\uFF08\u53EF\u9009\uFF1A\u4EC0\u4E48\u60C5\u51B5\u8BE5\u7528\uFF09", value: whenToUse, onChange: (ev) => {
5618
5248
  setWhenToUse(ev.target.value);
5619
5249
  } }),
5620
- (0, import_react3.createElement)("textarea", { style: { ...styles.textarea, minHeight: 220 }, placeholder: "\u6B63\u6587\uFF08\u544A\u8BC9\u5927\u6A21\u578B\u8FD9\u4E2A\u9636\u6BB5\u600E\u4E48\u5E72\uFF09", value: body2, onChange: (ev) => {
5250
+ (0, import_react3.createElement)("textarea", { style: { ...styles.textarea, minHeight: 300 }, placeholder: "\u6B63\u6587\uFF08\u544A\u8BC9\u5927\u6A21\u578B\u8FD9\u4E2A\u9636\u6BB5\u600E\u4E48\u5E72\uFF09", value: body2, onChange: (ev) => {
5621
5251
  setBody(ev.target.value);
5622
5252
  } }),
5623
- (0, import_react3.createElement)(
5624
- "div",
5625
- { style: styles.row },
5626
- (0, import_react3.createElement)(import_dsh_client_ui_primitives2.Button, {
5627
- variant: "primary",
5628
- size: "sm",
5629
- disabled: editing === null && name.trim() === "" || description.trim() === "" || body2.trim() === "",
5630
- onClick: () => {
5631
- void submit();
5632
- }
5633
- }, "\u4FDD\u5B58"),
5634
- (0, import_react3.createElement)(import_dsh_client_ui_primitives2.Button, { variant: "ghost", size: "sm", onClick: closeForm }, "\u53D6\u6D88")
5635
- ),
5636
5253
  msg !== "" ? (0, import_react3.createElement)("p", { style: styles.status }, msg) : null
5637
5254
  );
5638
5255
  };
@@ -5651,20 +5268,18 @@ function SkillManager({ workspace, remote }) {
5651
5268
  { style: styles.section },
5652
5269
  ...skills.map(renderRow)
5653
5270
  )
5654
- )
5271
+ ),
5272
+ (0, import_react3.createElement)(import_dsh_client_ui_primitives3.Button, { variant: "outline", size: "md", onClick: startCreate }, "\u65B0\u5EFA skill")
5655
5273
  ),
5656
- formOpen ? renderForm() : (0, import_react3.createElement)(
5657
- "div",
5658
- null,
5659
- (0, import_react3.createElement)(import_dsh_client_ui_primitives2.Button, { variant: "outline", size: "md", onClick: startCreate }, "\u65B0\u5EFA skill")
5660
- )
5274
+ formOpen ? renderForm() : null
5661
5275
  );
5662
5276
  }
5663
5277
 
5664
5278
  // src/client/RuleManager.tsx
5665
5279
  var import_react4 = require("react");
5666
- var import_dsh_client_ui_primitives3 = require("@deepseek-ai/dsh-client-ui-primitives");
5667
- var control3 = {
5280
+ var import_dsh_client_ui_primitives4 = require("@deepseek-ai/dsh-client-ui-primitives");
5281
+ var MD_LABELS2 = { code: { copyLabel: "\u590D\u5236", copiedLabel: "\u5DF2\u590D\u5236" }, footnotes: "\u811A\u6CE8" };
5282
+ var control2 = {
5668
5283
  background: "var(--dsw-alias-bg-layer-1)",
5669
5284
  border: "1px solid var(--dsw-alias-border-l2)",
5670
5285
  borderRadius: 8,
@@ -5800,17 +5415,17 @@ function RuleManager({ workspace, remote }) {
5800
5415
  rule.name,
5801
5416
  rule.source !== "bundled" ? (0, import_react4.createElement)("span", { style: styles.sourceBadge }, `\uFF08${sourceLabel(rule.source)}\uFF09`) : null
5802
5417
  ),
5803
- rule.source === "bundled" ? (0, import_react4.createElement)(import_dsh_client_ui_primitives3.Button, { variant: "outline", size: "sm", onClick: () => {
5418
+ rule.source === "bundled" ? (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "outline", size: "sm", onClick: () => {
5804
5419
  startView(rule);
5805
5420
  } }, "\u67E5\u770B") : (0, import_react4.createElement)(
5806
5421
  "div",
5807
5422
  { style: { display: "flex", gap: 6 } },
5808
- (0, import_react4.createElement)(import_dsh_client_ui_primitives3.Button, { variant: "outline", size: "sm", onClick: () => {
5423
+ (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "outline", size: "sm", onClick: () => {
5809
5424
  startEdit(rule);
5810
5425
  } }, "\u7F16\u8F91"),
5811
- confirming === rule.name ? (0, import_react4.createElement)(import_dsh_client_ui_primitives3.Button, { variant: "primary", size: "sm", onClick: () => {
5426
+ confirming === rule.name ? (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "primary", size: "sm", onClick: () => {
5812
5427
  void remove(rule);
5813
- } }, "\u786E\u8BA4\u5220\u9664") : (0, import_react4.createElement)(import_dsh_client_ui_primitives3.Button, { variant: "ghost", size: "sm", onClick: () => {
5428
+ } }, "\u786E\u8BA4\u5220\u9664") : (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "ghost", size: "sm", onClick: () => {
5814
5429
  setConfirming(rule.name);
5815
5430
  } }, "\u5220\u9664")
5816
5431
  )
@@ -5818,51 +5433,51 @@ function RuleManager({ workspace, remote }) {
5818
5433
  const renderForm = () => {
5819
5434
  if (viewing) {
5820
5435
  return (0, import_react4.createElement)(
5821
- "div",
5822
- { style: card2 },
5823
- (0, import_react4.createElement)("span", { style: styles.bindingLabel }, `\u67E5\u770B rule\u300C${editing ?? ""}\u300D\uFF08\u5185\u7F6E \xB7 \u53EA\u8BFB\uFF09`),
5824
- (0, import_react4.createElement)("textarea", { style: { ...styles.textarea, minHeight: 240 }, value: body2, disabled: true, readOnly: true }),
5825
- (0, import_react4.createElement)(
5826
- "div",
5827
- { style: styles.row },
5828
- (0, import_react4.createElement)(import_dsh_client_ui_primitives3.Button, { variant: "ghost", size: "sm", onClick: closeForm }, "\u5173\u95ED")
5829
- ),
5830
- msg !== "" ? (0, import_react4.createElement)("p", { style: styles.status }, msg) : null
5436
+ ResourceModal,
5437
+ {
5438
+ title: `\u67E5\u770B rule\u300C${editing ?? ""}\u300D`,
5439
+ description: "\u5185\u7F6E \xB7 \u53EA\u8BFB",
5440
+ onClose: closeForm,
5441
+ footer: (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "ghost", size: "sm", onClick: closeForm }, "\u5173\u95ED")
5442
+ },
5443
+ (0, import_react4.createElement)(import_dsh_client_ui_primitives4.MarkdownText, { text: body2, labels: MD_LABELS2 })
5831
5444
  );
5832
5445
  }
5833
5446
  return (0, import_react4.createElement)(
5834
- "div",
5835
- { style: card2 },
5836
- (0, import_react4.createElement)("span", { style: styles.bindingLabel }, editing === null ? "\u65B0\u5EFA rule" : `\u7F16\u8F91 rule\u300C${editing}\u300D`),
5447
+ ResourceModal,
5448
+ {
5449
+ title: editing === null ? "\u65B0\u5EFA rule" : `\u7F16\u8F91 rule\u300C${editing ?? ""}\u300D`,
5450
+ onClose: closeForm,
5451
+ footer: (0, import_react4.createElement)(
5452
+ "div",
5453
+ { style: styles.row },
5454
+ (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, {
5455
+ variant: "primary",
5456
+ size: "sm",
5457
+ disabled: editing === null && name.trim() === "" || body2.trim() === "",
5458
+ onClick: () => {
5459
+ void submit();
5460
+ }
5461
+ }, "\u4FDD\u5B58"),
5462
+ (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "ghost", size: "sm", onClick: closeForm }, "\u53D6\u6D88")
5463
+ )
5464
+ },
5837
5465
  (0, import_react4.createElement)(
5838
5466
  "div",
5839
5467
  { style: styles.chips },
5840
- (0, import_react4.createElement)(import_dsh_client_ui_primitives3.Pill, { active: level === "project", onClick: () => {
5468
+ (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Pill, { active: level === "project", onClick: () => {
5841
5469
  setLevel("project");
5842
5470
  }, title: "\u5199\u5230\u5DE5\u4F5C\u533A .dsh/rules\uFF0C\u56E2\u961F\u5171\u4EAB" }, "\u9879\u76EE\u7EA7"),
5843
- (0, import_react4.createElement)(import_dsh_client_ui_primitives3.Pill, { active: level === "user", onClick: () => {
5471
+ (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Pill, { active: level === "user", onClick: () => {
5844
5472
  setLevel("user");
5845
5473
  }, title: "\u5199\u5230 $DSH_HOME/rules\uFF0C\u4E2A\u4EBA\u6240\u6709\u9879\u76EE\u53EF\u7528" }, "\u7528\u6237\u7EA7")
5846
5474
  ),
5847
- editing === null ? (0, import_react4.createElement)("input", { style: control3, placeholder: "name\uFF08\u5982 my-redlines\uFF0C\u53EA\u542B\u5C0F\u5199\u5B57\u6BCD\u6570\u5B57\u548C -\uFF09", value: name, onChange: (ev) => {
5475
+ editing === null ? (0, import_react4.createElement)("input", { style: control2, placeholder: "name\uFF08\u5982 my-redlines\uFF0C\u53EA\u542B\u5C0F\u5199\u5B57\u6BCD\u6570\u5B57\u548C -\uFF09", value: name, onChange: (ev) => {
5848
5476
  setName(ev.target.value);
5849
5477
  } }) : (0, import_react4.createElement)("span", { style: styles.sourceBadge }, `name \u56FA\u5B9A\u4E3A ${name}\uFF08\u6539\u540D\u8BF7\u5220\u9664\u540E\u91CD\u5EFA\uFF09`),
5850
- (0, import_react4.createElement)("textarea", { style: { ...styles.textarea, minHeight: 240 }, placeholder: "\u6B63\u6587\uFF08\u8FD9\u6761\u89C4\u5219\u7EA6\u675F\u5927\u6A21\u578B\u9075\u5B88\u4EC0\u4E48\uFF09", value: body2, onChange: (ev) => {
5478
+ (0, import_react4.createElement)("textarea", { style: { ...styles.textarea, minHeight: 260 }, placeholder: "\u6B63\u6587\uFF08\u8FD9\u6761\u89C4\u5219\u7EA6\u675F\u5927\u6A21\u578B\u9075\u5B88\u4EC0\u4E48\uFF09", value: body2, onChange: (ev) => {
5851
5479
  setBody(ev.target.value);
5852
5480
  } }),
5853
- (0, import_react4.createElement)(
5854
- "div",
5855
- { style: styles.row },
5856
- (0, import_react4.createElement)(import_dsh_client_ui_primitives3.Button, {
5857
- variant: "primary",
5858
- size: "sm",
5859
- disabled: editing === null && name.trim() === "" || body2.trim() === "",
5860
- onClick: () => {
5861
- void submit();
5862
- }
5863
- }, "\u4FDD\u5B58"),
5864
- (0, import_react4.createElement)(import_dsh_client_ui_primitives3.Button, { variant: "ghost", size: "sm", onClick: closeForm }, "\u53D6\u6D88")
5865
- ),
5866
5481
  msg !== "" ? (0, import_react4.createElement)("p", { style: styles.status }, msg) : null
5867
5482
  );
5868
5483
  };
@@ -5881,19 +5496,16 @@ function RuleManager({ workspace, remote }) {
5881
5496
  { style: styles.section },
5882
5497
  ...rules.map(renderRow)
5883
5498
  )
5884
- )
5499
+ ),
5500
+ (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "outline", size: "md", onClick: startCreate }, "\u65B0\u5EFA rule")
5885
5501
  ),
5886
- formOpen ? renderForm() : (0, import_react4.createElement)(
5887
- "div",
5888
- null,
5889
- (0, import_react4.createElement)(import_dsh_client_ui_primitives3.Button, { variant: "outline", size: "md", onClick: startCreate }, "\u65B0\u5EFA rule")
5890
- )
5502
+ formOpen ? renderForm() : null
5891
5503
  );
5892
5504
  }
5893
5505
 
5894
5506
  // src/client/TaskLedger.tsx
5895
5507
  var import_react5 = require("react");
5896
- var import_dsh_client_ui_primitives4 = require("@deepseek-ai/dsh-client-ui-primitives");
5508
+ var import_dsh_client_ui_primitives5 = require("@deepseek-ai/dsh-client-ui-primitives");
5897
5509
  var card3 = {
5898
5510
  display: "flex",
5899
5511
  flexDirection: "column",
@@ -5931,10 +5543,10 @@ var badge = {
5931
5543
  color: "var(--dsw-alias-label-secondary)"
5932
5544
  };
5933
5545
  function verdictDot(outcome) {
5934
- return (0, import_react5.createElement)(import_dsh_client_ui_primitives4.StateDot, { state: outcome === "pass" ? "done" : "error" });
5546
+ return (0, import_react5.createElement)(import_dsh_client_ui_primitives5.StateDot, { state: outcome === "pass" ? "done" : "error" });
5935
5547
  }
5936
5548
  function itemStatusDot(status) {
5937
- return (0, import_react5.createElement)(import_dsh_client_ui_primitives4.StateDot, { state: status === "done" ? "done" : "ongoing" });
5549
+ return (0, import_react5.createElement)(import_dsh_client_ui_primitives5.StateDot, { state: status === "done" ? "done" : "ongoing" });
5938
5550
  }
5939
5551
  function timeText(at) {
5940
5552
  return at.slice(0, 19).replace("T", " ");
@@ -6000,7 +5612,7 @@ function TaskLedger({ workspace, remote }) {
6000
5612
  { style: headerRow },
6001
5613
  (0, import_react5.createElement)("span", { style: styles.bindingLabel }, "\u4EFB\u52A1\u53F0\u8D26"),
6002
5614
  (0, import_react5.createElement)("span", { style: styles.sourceBadge }, "\u53EA\u8BFB \xB7 \u6765\u81EA .dsh/task-*.json"),
6003
- (0, import_react5.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "outline", size: "sm", onClick: refresh }, "\u5237\u65B0")
5615
+ (0, import_react5.createElement)(import_dsh_client_ui_primitives5.Button, { variant: "outline", size: "sm", onClick: refresh }, "\u5237\u65B0")
6004
5616
  ),
6005
5617
  error !== "" ? (0, import_react5.createElement)("p", { style: styles.status }, error) : tasks.length === 0 ? (0, import_react5.createElement)("p", { style: styles.muted }, "\u5F53\u524D\u5DE5\u4F5C\u533A\u8FD8\u6CA1\u6709\u4EFB\u52A1\uFF1A\u5F00\u5DE5\u540E\uFF08dev_task create\uFF09\u4F1A\u5728\u8FD9\u91CC\u5217\u51FA\u6D3E\u53D1\u4E0E\u5BA1\u67E5\u7559\u75D5\u3002") : (0, import_react5.createElement)(
6006
5618
  "div",
@@ -6111,13 +5723,13 @@ function Workbench({ useStore, actions, useWorkspaces, remote }) {
6111
5723
  { type: "button", title: "\u5173\u95ED", onClick: () => {
6112
5724
  actions.close();
6113
5725
  }, style: closeStyle },
6114
- (0, import_react6.createElement)(import_dsh_client_ui_primitives5.IconCloseOutline16, { size: 16 })
5726
+ (0, import_react6.createElement)(import_dsh_client_ui_primitives6.IconCloseOutline16, { size: 16 })
6115
5727
  )
6116
5728
  ),
6117
5729
  (0, import_react6.createElement)(
6118
5730
  "div",
6119
5731
  { style: tabbar },
6120
- ...TABS.map((t) => (0, import_react6.createElement)(import_dsh_client_ui_primitives5.Pill, { key: t.id, active: tab === t.id, onClick: () => {
5732
+ ...TABS.map((t) => (0, import_react6.createElement)(import_dsh_client_ui_primitives6.Pill, { key: t.id, active: tab === t.id, onClick: () => {
6121
5733
  setTab(t.id);
6122
5734
  } }, t.label)),
6123
5735
  workspaces.length > 0 ? (0, import_react6.createElement)("select", {
@@ -6138,7 +5750,7 @@ function Workbench({ useStore, actions, useWorkspaces, remote }) {
6138
5750
 
6139
5751
  // src/client/TriggerButton.tsx
6140
5752
  var import_react7 = require("react");
6141
- var import_dsh_client_ui_primitives6 = require("@deepseek-ai/dsh-client-ui-primitives");
5753
+ var import_dsh_client_ui_primitives7 = require("@deepseek-ai/dsh-client-ui-primitives");
6142
5754
  function TriggerButton({ wide, actions }) {
6143
5755
  return (0, import_react7.createElement)(
6144
5756
  "button",
@@ -6165,7 +5777,7 @@ function TriggerButton({ wide, actions }) {
6165
5777
  boxSizing: "border-box"
6166
5778
  }
6167
5779
  },
6168
- (0, import_react7.createElement)(import_dsh_client_ui_primitives6.IconSettingsOutline16, { size: wide ? 16 : 18 }),
5780
+ (0, import_react7.createElement)(import_dsh_client_ui_primitives7.IconSettingsOutline16, { size: wide ? 16 : 18 }),
6169
5781
  wide ? (0, import_react7.createElement)("span", { style: { fontSize: 13 } }, "\u5DE5\u7A0B\u6D41\u7A0B") : null
6170
5782
  );
6171
5783
  }