@godv61/dsh-task-engine 0.23.9 → 0.24.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
@@ -4536,7 +4536,7 @@ var TYPERT_REMOTE = {
4536
4536
  var remote_default = TYPERT_REMOTE;
4537
4537
 
4538
4538
  // src/client/Workbench.tsx
4539
- var import_react9 = require("react");
4539
+ var import_react8 = require("react");
4540
4540
  var import_dsh_client_ui_primitives6 = require("@deepseek-ai/dsh-client-ui-primitives");
4541
4541
 
4542
4542
  // src/client/workbench-theme.ts
@@ -4736,10 +4736,18 @@ var styles = {
4736
4736
  };
4737
4737
 
4738
4738
  // src/client/TaskEngineSection.tsx
4739
- var import_react2 = require("react");
4739
+ var import_react = require("react");
4740
4740
  var import_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
4741
4741
 
4742
4742
  // src/engine.ts
4743
+ function formatResourceRef(ref) {
4744
+ return `${ref.source}:${ref.name}`;
4745
+ }
4746
+ function parseResourceRef(text2) {
4747
+ const match = /^(bundled|project|user):(.+)$/u.exec(text2);
4748
+ if (match === null) return void 0;
4749
+ return { source: match[1], name: match[2] };
4750
+ }
4743
4751
  var GUARD_NAMES = [
4744
4752
  "requirement_confirmation",
4745
4753
  "solution_confirmation",
@@ -4800,15 +4808,26 @@ function validateWorkflow(config) {
4800
4808
  if (!config.stages.includes(stage)) {
4801
4809
  problems.push(`stage_bindings: stage "${stage}" is not a stage`);
4802
4810
  }
4803
- for (const skill of binding.skills ?? []) {
4804
- if (typeof skill !== "string" || skill.trim() === "") {
4805
- problems.push(`stage_bindings "${stage}": empty skill name`);
4811
+ for (const [index, entry] of (binding.skills ?? []).entries()) {
4812
+ if (typeof entry?.skill?.name !== "string" || entry.skill.name.trim() === "") {
4813
+ problems.push(`stage_bindings "${stage}": skill ${index + 1} has no name`);
4814
+ continue;
4806
4815
  }
4807
- }
4808
- for (const rule of binding.rules ?? []) {
4809
- if (typeof rule !== "string" || rule.trim() === "") {
4810
- problems.push(`stage_bindings "${stage}": empty rule name`);
4816
+ if (!["bundled", "project", "user"].includes(entry.skill.source)) {
4817
+ problems.push(`stage_bindings "${stage}": skill "${entry.skill.name}" has unknown source "${String(entry.skill.source)}"`);
4811
4818
  }
4819
+ for (const rule of entry.rules ?? []) {
4820
+ if (typeof rule?.name !== "string" || rule.name.trim() === "") {
4821
+ problems.push(`stage_bindings "${stage}": skill "${entry.skill.name}" has a rule with no name`);
4822
+ continue;
4823
+ }
4824
+ if (!["bundled", "project", "user"].includes(rule.source)) {
4825
+ problems.push(`stage_bindings "${stage}": skill "${entry.skill.name}" rule "${rule.name}" has unknown source "${String(rule.source)}"`);
4826
+ }
4827
+ }
4828
+ }
4829
+ if ((binding.legacy_rules ?? []).length > 0) {
4830
+ problems.push(`stage_bindings "${stage}": ${binding.legacy_rules.length} legacy stage-level rule(s) are unassigned and still in force; assign each to the skill that should carry it`);
4812
4831
  }
4813
4832
  }
4814
4833
  if (!["task", "item", "manual"].includes(config.commit.policy)) {
@@ -4826,14 +4845,21 @@ function validateWorkflow(config) {
4826
4845
  problems.push("commit.message_pattern is not a valid regular expression");
4827
4846
  }
4828
4847
  }
4848
+ if (config.review_depth !== void 0 && config.review_depth !== "two-stage" && config.review_depth !== "single") {
4849
+ problems.push(`review_depth "${String(config.review_depth)}" is not one of: two-stage, single`);
4850
+ }
4829
4851
  return problems;
4830
4852
  }
4831
4853
 
4832
4854
  // src/workflows.ts
4855
+ function bundled(skill, ...rules) {
4856
+ const ref = (name) => ({ source: "bundled", name });
4857
+ return { skill: ref(skill), rules: rules.map(ref) };
4858
+ }
4833
4859
  var FLOW_OPTIONS = [
4834
- { 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" },
4835
- { 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" },
4836
- { id: "minimal", label: "\u7EAF\u4EE3\u7801", description: "\u5F00\u53D1 \u2192 \u4EA4\u4ED8\uFF0C\u4E24\u9636\u6BB5\uFF0C\u53EA\u7559\u63D0\u4EA4\u95E8\u7981" }
4860
+ { id: "standard", label: "\u5B8C\u6574\u7814\u53D1", description: "\u65B0\u529F\u80FD\u3001\u67B6\u6784\u6216\u8DE8\u6A21\u5757\u6539\u52A8\u3001\u9AD8\u98CE\u9669\u4EFB\u52A1\uFF1A\u9700\u6C42\u786E\u8BA4 \u2192 \u65B9\u6848\u786E\u8BA4 \u2192 \u5B9E\u73B0 \u2192 \u9A8C\u8BC1 \u2192 \u5BA1\u6838 \u2192 \u63D0\u4EA4" },
4861
+ { id: "agile", label: "\u65E5\u5E38\u8FED\u4EE3", description: "\u76EE\u6807\u660E\u786E\u7684\u5E38\u89C4\u529F\u80FD\u4E0E\u7F3A\u9677\u4FEE\u590D\uFF1A\u76EE\u6807\u4E0E\u9A8C\u6536 \u2192 \u5B9E\u73B0 \u2192 \u9A8C\u6536\u4E0E\u5BA1\u67E5 \u2192 \u63D0\u4EA4" },
4862
+ { id: "minimal", label: "\u5FEB\u901F\u4FEE\u6539", description: "\u5C40\u90E8\u3001\u4F4E\u98CE\u9669\u3001\u65B9\u6848\u660E\u786E\u7684\u6539\u52A8\uFF1A\u4FEE\u6539 \u2192 \u68C0\u67E5\u4E0E\u63D0\u4EA4" }
4837
4863
  ];
4838
4864
  var STANDARD = {
4839
4865
  stages: ["\u9700\u6C42\u8BC4\u5BA1", "\u8BBE\u8BA1", "\u5F00\u53D1", "\u4EA4\u4ED8", "\u4EE3\u7801\u5BA1\u6838", "\u5B8C\u6210"],
@@ -4859,11 +4885,16 @@ var STANDARD = {
4859
4885
  },
4860
4886
  high_risk_requires_verification: true,
4861
4887
  stage_bindings: {
4862
- "\u9700\u6C42\u8BC4\u5BA1": { skills: ["requirement-analysis"], rules: ["security-redlines"] },
4863
- "\u8BBE\u8BA1": { skills: ["solution-design"] },
4864
- "\u5F00\u53D1": { skills: ["code-implement"], rules: ["coding-conventions"] },
4865
- "\u4EA4\u4ED8": { skills: ["code-verify"], rules: ["coding-conventions"] },
4866
- "\u4EE3\u7801\u5BA1\u6838": { skills: ["code-review", "code-commit"], rules: ["security-redlines", "commit-conventions"] }
4888
+ "\u9700\u6C42\u8BC4\u5BA1": { skills: [bundled("requirement-analysis", "security-redlines")] },
4889
+ "\u8BBE\u8BA1": { skills: [bundled("solution-design")] },
4890
+ "\u5F00\u53D1": { skills: [bundled("code-implement", "coding-conventions", "security-redlines")] },
4891
+ "\u4EA4\u4ED8": { skills: [bundled("code-verify")] },
4892
+ "\u4EE3\u7801\u5BA1\u6838": {
4893
+ skills: [
4894
+ bundled("code-review", "coding-conventions", "security-redlines"),
4895
+ bundled("code-commit", "commit-conventions")
4896
+ ]
4897
+ }
4867
4898
  }
4868
4899
  };
4869
4900
  var AGILE = {
@@ -4875,21 +4906,32 @@ var AGILE = {
4875
4906
  { from: "\u4EA4\u4ED8", to: "\u5BA1\u67E5", requires: [] }
4876
4907
  ],
4877
4908
  artifacts: [
4878
- { stage: "\u9700\u6C42", id: "requirement", name: "\u9700\u6C42\u8BF4\u660E", fields: ["scope"] }
4909
+ { stage: "\u9700\u6C42", id: "requirement", name: "\u9700\u6C42\u8BF4\u660E", fields: ["scope"] },
4910
+ // The 审查 stage binds code-review, whose instructions write this artifact with
4911
+ // `record artifact=review`. Declaring it here keeps that binding executable:
4912
+ // the engine refuses an undeclared artifact, so a bound skill pointing at one
4913
+ // would be a contract the preset itself made impossible to satisfy.
4914
+ { stage: "\u5BA1\u67E5", id: "review", name: "\u8BC4\u5BA1\u8BB0\u5F55", fields: ["conclusion", "issues"] }
4879
4915
  ],
4880
4916
  commit: {
4917
+ // `item` policy emits two label shapes: `T<n>` for a mid-flow item commit and
4918
+ // `TASK` for the closing commit at the checkpoint. The pattern below accepts
4919
+ // BOTH, so the label the engine hands the model always satisfies the preset's
4920
+ // own rule. Previously it accepted only `T\d+` while the checkpoint stage
4921
+ // returned `TASK`, which made the closing commit impossible to phrase: the
4922
+ // status line and the validator disagreed about the contract.
4881
4923
  policy: "item",
4882
- message_pattern: "^\u3010(\\S+)\u3011\u3010T\\d+\u3011.+",
4883
- message_hint: "\u3010<task_id>\u3011\u3010T1\u3011\u8BF4\u660E \u2014\u2014 \u7B2C\u4E00\u6BB5\u586B\u672C\u4EFB\u52A1 id",
4924
+ message_pattern: "^\u3010(\\S+)\u3011\u3010(?:TASK|T\\d+)\u3011.+",
4925
+ message_hint: "\u3010<task_id>\u3011\u3010TASK/T1\u3011\u8BF4\u660E \u2014\u2014 \u7B2C\u4E00\u6BB5\u586B\u672C\u4EFB\u52A1 id\uFF1B\u5B9E\u65BD\u9879\u63D0\u4EA4\u7528 T1\u3001T2\uFF0C\u6536\u5C3E\u63D0\u4EA4\u7528 TASK",
4884
4926
  checkpoints: ["\u4EA4\u4ED8"],
4885
4927
  file_scope: true
4886
4928
  },
4887
4929
  high_risk_requires_verification: false,
4888
4930
  stage_bindings: {
4889
- "\u9700\u6C42": { skills: ["requirement-analysis"] },
4890
- "\u5F00\u53D1": { skills: ["code-implement"], rules: ["coding-conventions"] },
4891
- "\u4EA4\u4ED8": { skills: ["code-verify", "code-commit"], rules: ["commit-conventions"] },
4892
- "\u5BA1\u67E5": { skills: ["code-review"] }
4931
+ "\u9700\u6C42": { skills: [bundled("requirement-analysis", "security-redlines")] },
4932
+ "\u5F00\u53D1": { skills: [bundled("code-implement", "coding-conventions", "security-redlines")] },
4933
+ "\u4EA4\u4ED8": { skills: [bundled("code-verify"), bundled("code-commit", "commit-conventions")] },
4934
+ "\u5BA1\u67E5": { skills: [bundled("code-review", "coding-conventions", "security-redlines")] }
4893
4935
  }
4894
4936
  };
4895
4937
  var MINIMAL = {
@@ -4907,9 +4949,14 @@ var MINIMAL = {
4907
4949
  file_scope: false
4908
4950
  },
4909
4951
  high_risk_requires_verification: false,
4952
+ // A fast-change flow checks each change once, not twice under two headings a
4953
+ // short change rarely distinguishes. The item still has to be reviewed — what
4954
+ // drops is the duplicated verdict, which is where the weight actually was: this
4955
+ // flow used to carry the same per-item audit burden as the full one.
4956
+ review_depth: "single",
4910
4957
  stage_bindings: {
4911
- "\u5F00\u53D1": { skills: ["code-implement"] },
4912
- "\u4EA4\u4ED8": { skills: ["code-commit"], rules: ["commit-conventions"] }
4958
+ "\u5F00\u53D1": { skills: [bundled("code-implement", "coding-conventions", "security-redlines")] },
4959
+ "\u4EA4\u4ED8": { skills: [bundled("code-commit", "commit-conventions")] }
4913
4960
  }
4914
4961
  };
4915
4962
  function deriveCapabilities(config) {
@@ -4925,9 +4972,16 @@ function preset(id, version, label2, description, config) {
4925
4972
  return { id, version, label: label2, description, capabilities: deriveCapabilities(config), config };
4926
4973
  }
4927
4974
  var FLOW_PRESETS = {
4928
- standard: preset("standard", 2, "\u6807\u51C6\u7814\u53D1", "\u9700\u6C42\u8BC4\u5BA1 \u2192 \u8BBE\u8BA1 \u2192 \u5F00\u53D1 \u2192 \u4EA4\u4ED8 \u2192 \u4EE3\u7801\u5BA1\u6838\uFF0C\u5BA1\u6838\u540E\u63D0\u4EA4", STANDARD),
4929
- agile: preset("agile", 1, "\u654F\u6377\u8F7B\u91CF", "\u9700\u6C42 \u2192 \u5F00\u53D1 \u2192 \u4EA4\u4ED8 \u2192 \u5BA1\u67E5\uFF0C\u56DB\u9636\u6BB5\u3001\u5C11\u4EA7\u7269", AGILE),
4930
- minimal: preset("minimal", 1, "\u7EAF\u4EE3\u7801", "\u5F00\u53D1 \u2192 \u4EA4\u4ED8\uFF0C\u4E24\u9636\u6BB5\uFF0C\u53EA\u7559\u63D0\u4EA4\u95E8\u7981", MINIMAL)
4975
+ standard: preset("standard", 2, "\u5B8C\u6574\u7814\u53D1", "\u65B0\u529F\u80FD\u3001\u67B6\u6784\u6216\u8DE8\u6A21\u5757\u6539\u52A8\u3001\u9AD8\u98CE\u9669\u4EFB\u52A1\uFF1A\u9700\u6C42\u786E\u8BA4 \u2192 \u65B9\u6848\u786E\u8BA4 \u2192 \u5B9E\u73B0 \u2192 \u9A8C\u8BC1 \u2192 \u5BA1\u6838 \u2192 \u63D0\u4EA4", STANDARD),
4976
+ // Version 2: the closing-commit label shape was unified with the message pattern,
4977
+ // and the `review` artifact the bound code-review skill writes was declared. Tasks
4978
+ // created before this keep their frozen version 1 config and are unaffected.
4979
+ agile: preset("agile", 2, "\u65E5\u5E38\u8FED\u4EE3", "\u76EE\u6807\u660E\u786E\u7684\u5E38\u89C4\u529F\u80FD\u4E0E\u7F3A\u9677\u4FEE\u590D\uFF1A\u76EE\u6807\u4E0E\u9A8C\u6536 \u2192 \u5B9E\u73B0 \u2192 \u9A8C\u6536\u4E0E\u5BA1\u67E5 \u2192 \u63D0\u4EA4", AGILE),
4980
+ // Version 2: per-item review depth is declared as `single` instead of inheriting
4981
+ // the full flow's two verdicts per item. Tasks created before this keep their
4982
+ // frozen version 1 config, which has no `review_depth` and therefore reads as
4983
+ // two-stage exactly as it behaved.
4984
+ minimal: preset("minimal", 2, "\u5FEB\u901F\u4FEE\u6539", "\u5C40\u90E8\u3001\u4F4E\u98CE\u9669\u3001\u65B9\u6848\u660E\u786E\u7684\u6539\u52A8\uFF1A\u4FEE\u6539 \u2192 \u68C0\u67E5\u4E0E\u63D0\u4EA4\uFF0C\u6BCF\u9879\u4E00\u6B21\u68C0\u67E5", MINIMAL)
4931
4985
  };
4932
4986
  function dedupe(names) {
4933
4987
  return [...new Set(names)];
@@ -4938,11 +4992,18 @@ function mergeBindings(base, override) {
4938
4992
  const merged = { ...base.stage_bindings };
4939
4993
  for (const [stage, addition] of Object.entries(override)) {
4940
4994
  const existing = merged[stage];
4941
- const skills = dedupe([...existing?.skills ?? [], ...addition.skills ?? []]);
4942
- const rules = dedupe([...existing?.rules ?? [], ...addition.rules ?? []]);
4995
+ const skills = [...existing?.skills ?? []];
4996
+ const seen = new Set(skills.map((skill) => formatResourceRef(skill.skill)));
4997
+ for (const skill of addition.skills ?? []) {
4998
+ const key = formatResourceRef(skill.skill);
4999
+ if (seen.has(key)) continue;
5000
+ seen.add(key);
5001
+ skills.push(skill);
5002
+ }
5003
+ const legacy = dedupe([...existing?.legacy_rules ?? [], ...addition.legacy_rules ?? []]);
4943
5004
  const binding = {};
4944
5005
  if (skills.length > 0) binding.skills = skills;
4945
- if (rules.length > 0) binding.rules = rules;
5006
+ if (legacy.length > 0) binding.legacy_rules = legacy;
4946
5007
  merged[stage] = binding;
4947
5008
  changed = true;
4948
5009
  }
@@ -4958,113 +5019,36 @@ function resolveFlow(flow, override) {
4958
5019
  }
4959
5020
 
4960
5021
  // src/client/shared.ts
4961
- function sourceLabel(source) {
4962
- switch (source) {
4963
- case "bundled":
4964
- return "\u5185\u7F6E";
4965
- case "project":
4966
- case "project-dsh":
4967
- case "project-agents":
4968
- return "\u9879\u76EE";
4969
- case "user":
4970
- case "user-dsh":
4971
- case "user-agents":
4972
- return "\u7528\u6237";
4973
- case "custom":
4974
- return "\u81EA\u5B9A\u4E49";
4975
- default:
4976
- return source;
4977
- }
4978
- }
4979
5022
  function describeError(error) {
4980
5023
  if (error instanceof Error) return error.message;
4981
5024
  if (typeof error === "string") return error;
4982
5025
  return "\u672A\u77E5\u9519\u8BEF";
4983
5026
  }
4984
5027
 
4985
- // src/client/BindingPicker.tsx
4986
- var import_react = require("react");
5028
+ // src/client/TaskEngineSection.tsx
4987
5029
  var import_jsx_runtime = require("react/jsx-runtime");
4988
- function BindingPicker({ title, resources, selected, defaults, onToggle }) {
4989
- const [query, setQuery] = (0, import_react.useState)("");
4990
- const [selectedOnly, setSelectedOnly] = (0, import_react.useState)(false);
4991
- const chosen = (0, import_react.useMemo)(() => /* @__PURE__ */ new Set([...defaults, ...selected]), [defaults, selected]);
4992
- const catalog = (0, import_react.useMemo)(() => {
4993
- const entries = /* @__PURE__ */ new Map();
4994
- for (const resource of resources) {
4995
- if (!entries.has(resource.name)) entries.set(resource.name, resource);
4996
- }
4997
- for (const name of chosen) {
4998
- if (!entries.has(name)) entries.set(name, { name, source: "missing" });
4999
- }
5000
- return [...entries.values()];
5001
- }, [resources, chosen]);
5002
- const search = query.trim().toLocaleLowerCase();
5003
- const visible = catalog.filter((resource) => (!selectedOnly || chosen.has(resource.name)) && `${resource.name} ${resource.description ?? ""}`.toLocaleLowerCase().includes(search));
5004
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "te-binding-picker", "aria-label": `${title}\u7ED1\u5B9A`, children: [
5005
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "te-binding-heading", children: [
5006
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h4", { children: title }),
5007
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "te-binding-count", children: [
5008
- "\u5DF2\u9009 ",
5009
- chosen.size,
5010
- " / ",
5011
- catalog.length
5012
- ] })
5013
- ] }),
5014
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "te-binding-tools", children: [
5015
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "search", className: "te-input", "aria-label": `\u641C\u7D22${title}`, placeholder: `\u641C\u7D22${title}\u540D\u79F0${title === "\u6280\u80FD" ? "\u6216\u63CF\u8FF0" : ""}`, value: query, onChange: (event) => setQuery(event.target.value) }),
5016
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "te-binding-filter", children: [
5017
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "checkbox", checked: selectedOnly, onChange: (event) => setSelectedOnly(event.target.checked) }),
5018
- "\u4EC5\u770B\u5DF2\u9009"
5019
- ] })
5020
- ] }),
5021
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "te-binding-list", role: "group", "aria-label": `${title}\u5217\u8868`, tabIndex: 0, children: [
5022
- visible.map((resource) => {
5023
- const fixed = defaults.includes(resource.name);
5024
- const checked = chosen.has(resource.name);
5025
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: `te-binding-option${checked ? " is-selected" : ""}${fixed ? " is-fixed" : ""}`, children: [
5026
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "checkbox", "aria-label": resource.name, checked, disabled: fixed, onChange: () => onToggle(resource.name) }),
5027
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "te-binding-detail", children: [
5028
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "te-binding-name", children: resource.name }),
5029
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "te-binding-meta", children: [
5030
- resource.source === "missing" ? "\u8D44\u6E90\u672A\u627E\u5230" : sourceLabel(resource.source),
5031
- fixed ? " \xB7 \u9884\u8BBE\u9ED8\u8BA4" : ""
5032
- ] }),
5033
- resource.description ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "te-binding-description", title: resource.description, children: resource.description }) : null
5034
- ] })
5035
- ] }, resource.name);
5036
- }),
5037
- visible.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "te-binding-empty", children: catalog.length === 0 ? `\u6682\u65E0${title}\uFF0C\u8BF7\u5728\u4E0A\u65B9\u201C${title}\u201D\u9875\u6DFB\u52A0\u3002` : search ? "\u6CA1\u6709\u5339\u914D\u9879\uFF0C\u8BF7\u5C1D\u8BD5\u5176\u4ED6\u5173\u952E\u8BCD\u3002" : "\u5F53\u524D\u8282\u70B9\u5C1A\u672A\u9009\u62E9\u9644\u52A0\u9879\u3002" }) : null
5038
- ] }),
5039
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "te-binding-count", role: "status", children: [
5040
- "\u663E\u793A ",
5041
- visible.length,
5042
- " \u9879",
5043
- search || selectedOnly ? "\uFF08\u5DF2\u7B5B\u9009\uFF09" : ""
5044
- ] })
5045
- ] });
5030
+ function refFromText(text2) {
5031
+ return parseResourceRef(text2) ?? { source: "bundled", name: text2 };
5046
5032
  }
5047
-
5048
- // src/client/TaskEngineSection.tsx
5049
- var import_jsx_runtime2 = require("react/jsx-runtime");
5050
5033
  function resolvedConfig(flow, stageBindings) {
5051
5034
  const resolved = resolveFlow(flow, { stage_bindings: stageBindings });
5052
5035
  return resolved.ok ? resolved.config : FLOW_PRESETS.standard.config;
5053
5036
  }
5054
5037
  function TaskEngineSection(props) {
5055
5038
  const { remote, workspace } = props;
5056
- const [flow, setFlow] = (0, import_react2.useState)("standard");
5057
- const [stageBindings, setStageBindings] = (0, import_react2.useState)({});
5058
- const [source, setSource] = (0, import_react2.useState)("default");
5059
- const [savedAt, setSavedAt] = (0, import_react2.useState)("");
5060
- const [loadError, setLoadError] = (0, import_react2.useState)("");
5061
- const [saving, setSaving] = (0, import_react2.useState)(false);
5062
- const [loading, setLoading] = (0, import_react2.useState)(true);
5063
- const [loadAttempt, setLoadAttempt] = (0, import_react2.useState)(0);
5064
- const [configProblems, setConfigProblems] = (0, import_react2.useState)([]);
5065
- const [skills, setSkills] = (0, import_react2.useState)([]);
5066
- const [rules, setRules] = (0, import_react2.useState)([]);
5067
- (0, import_react2.useEffect)(() => {
5039
+ const [flow, setFlow] = (0, import_react.useState)("standard");
5040
+ const [stageBindings, setStageBindings] = (0, import_react.useState)({});
5041
+ const [source, setSource] = (0, import_react.useState)("default");
5042
+ const [savedAt, setSavedAt] = (0, import_react.useState)("");
5043
+ const [dirty, setDirty] = (0, import_react.useState)(false);
5044
+ const [loadError, setLoadError] = (0, import_react.useState)("");
5045
+ const [saving, setSaving] = (0, import_react.useState)(false);
5046
+ const [loading, setLoading] = (0, import_react.useState)(true);
5047
+ const [loadAttempt, setLoadAttempt] = (0, import_react.useState)(0);
5048
+ const [configProblems, setConfigProblems] = (0, import_react.useState)([]);
5049
+ const [skills, setSkills] = (0, import_react.useState)([]);
5050
+ const [rules, setRules] = (0, import_react.useState)([]);
5051
+ (0, import_react.useEffect)(() => {
5068
5052
  if (workspace === "") return;
5069
5053
  let alive = true;
5070
5054
  setLoadError("");
@@ -5091,7 +5075,7 @@ function TaskEngineSection(props) {
5091
5075
  alive = false;
5092
5076
  };
5093
5077
  }, [remote, workspace, loadAttempt]);
5094
- const refreshCatalogs = (0, import_react2.useCallback)(() => {
5078
+ const refreshCatalogs = (0, import_react.useCallback)(() => {
5095
5079
  if (workspace === "") return;
5096
5080
  void remote.listSkills(workspace).then((result) => {
5097
5081
  if (result.ok) setSkills(result.value.skills);
@@ -5102,51 +5086,55 @@ function TaskEngineSection(props) {
5102
5086
  }, () => {
5103
5087
  });
5104
5088
  }, [remote, workspace]);
5105
- (0, import_react2.useEffect)(() => {
5089
+ (0, import_react.useEffect)(() => {
5106
5090
  refreshCatalogs();
5107
5091
  }, [refreshCatalogs]);
5108
- const stages = (0, import_react2.useMemo)(() => (FLOW_PRESETS[flow] ?? FLOW_PRESETS.standard).config.stages, [flow]);
5109
- const problems = (0, import_react2.useMemo)(
5092
+ const stages = (0, import_react.useMemo)(() => (FLOW_PRESETS[flow] ?? FLOW_PRESETS.standard).config.stages, [flow]);
5093
+ const problems = (0, import_react.useMemo)(
5110
5094
  () => validateWorkflow(resolvedConfig(flow, stageBindings)),
5111
5095
  [flow, stageBindings]
5112
5096
  );
5113
5097
  const selectFlow = (id) => {
5098
+ if (id === flow) return;
5099
+ if (dirty && !window.confirm("\u5F53\u524D\u6D41\u7A0B\u914D\u7F6E\u6709\u672A\u4FDD\u5B58\u7684\u4FEE\u6539\uFF0C\u5207\u6362\u6D41\u7A0B\u4F1A\u4E22\u5F03\u5B83\u4EEC\u3002\u7EE7\u7EED\u5207\u6362\uFF1F")) return;
5114
5100
  setFlow(id);
5115
5101
  setStageBindings({ ...FLOW_PRESETS[id]?.config.stage_bindings ?? {} });
5102
+ setDirty(true);
5103
+ setSavedAt("");
5116
5104
  };
5117
5105
  if (loadError !== "") {
5118
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles.wrap, children: [
5119
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h2", { style: styles.title, children: "\u5DE5\u7A0B\u6D41\u7A0B\u914D\u7F6E" }),
5120
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles.problems, children: [
5121
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { style: styles.problemsTitle, children: [
5122
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives.StateDot, { state: "error" }),
5106
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.wrap, children: [
5107
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { style: styles.title, children: "\u5DE5\u7A0B\u6D41\u7A0B\u914D\u7F6E" }),
5108
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.problems, children: [
5109
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: styles.problemsTitle, children: [
5110
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.StateDot, { state: "error" }),
5123
5111
  "\u8BFB\u53D6\u5931\u8D25"
5124
5112
  ] }),
5125
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { style: styles.muted, children: loadError }),
5126
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives.Button, { onClick: () => setLoadAttempt((n) => n + 1), children: "\u91CD\u8BD5" })
5113
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.muted, children: loadError }),
5114
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { onClick: () => setLoadAttempt((n) => n + 1), children: "\u91CD\u8BD5" })
5127
5115
  ] })
5128
5116
  ] });
5129
5117
  }
5130
- if (loading) return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { role: "status", children: "\u6B63\u5728\u8BFB\u53D6\u6D41\u7A0B\u914D\u7F6E\u2026" });
5131
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles.wrap, children: [
5132
- configProblems.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("p", { role: "alert", style: styles.problems, children: [
5118
+ if (loading) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { role: "status", children: "\u6B63\u5728\u8BFB\u53D6\u6D41\u7A0B\u914D\u7F6E\u2026" });
5119
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.wrap, children: [
5120
+ configProblems.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { role: "alert", style: styles.problems, children: [
5133
5121
  "\u539F\u914D\u7F6E\u6709\u95EE\u9898\uFF1A",
5134
5122
  configProblems.join("\uFF1B"),
5135
5123
  "\u3002\u8BF7\u9009\u62E9\u6709\u6548\u9884\u8BBE\u5E76\u4FDD\u5B58\u4FEE\u590D\u3002"
5136
5124
  ] }),
5137
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles.head, children: [
5138
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h2", { style: styles.title, children: "\u5DE5\u7A0B\u6D41\u7A0B\u914D\u7F6E" }),
5139
- /* @__PURE__ */ (0, import_jsx_runtime2.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" })
5125
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.head, children: [
5126
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { style: styles.title, children: "\u5DE5\u7A0B\u6D41\u7A0B\u914D\u7F6E" }),
5127
+ /* @__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" })
5140
5128
  ] }),
5141
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles.sourceRow, children: [
5142
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives.StateDot, { state: source === "project" ? "done" : source === "invalid" ? "warning" : "ongoing" }),
5143
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: styles.sourceText, children: sourceText(source) })
5129
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.sourceRow, children: [
5130
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.StateDot, { state: source === "project" ? "done" : source === "invalid" ? "warning" : "ongoing" }),
5131
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.sourceText, children: sourceText(source) })
5144
5132
  ] }),
5145
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles.field, children: [
5146
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { children: "\u6D41\u7A0B\u9884\u8BBE" }),
5147
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: styles.flowGrid, children: FLOW_OPTIONS.map((option) => {
5133
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.field, children: [
5134
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { children: "\u6D41\u7A0B\u9884\u8BBE" }),
5135
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.flowGrid, children: FLOW_OPTIONS.map((option) => {
5148
5136
  const active = flow === option.id;
5149
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
5137
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
5150
5138
  "button",
5151
5139
  {
5152
5140
  type: "button",
@@ -5156,49 +5144,56 @@ function TaskEngineSection(props) {
5156
5144
  },
5157
5145
  style: { ...styles.flowOption, ...active ? styles.flowOptionActive : {} },
5158
5146
  children: [
5159
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { style: styles.flowOptionTitle, children: [
5160
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives.StateDot, { state: active ? "done" : "ongoing", size: 8 }),
5147
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: styles.flowOptionTitle, children: [
5148
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.StateDot, { state: active ? "done" : "ongoing", size: 8 }),
5161
5149
  option.label
5162
5150
  ] }),
5163
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { style: styles.flowOptionDesc, children: option.description })
5151
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.flowOptionDesc, children: option.description })
5164
5152
  ]
5165
5153
  },
5166
5154
  option.id
5167
5155
  );
5168
5156
  }) })
5169
5157
  ] }),
5170
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(SectionCard, { icon: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives.IconSettingsOutline16, { size: 16 }), title: "\u9636\u6BB5\u6280\u80FD / \u89C4\u5219", hint: "\u9009\u62E9\u8282\u70B9\uFF0C\u518D\u52FE\u9009\u9644\u52A0\u6280\u80FD\u4E0E\u89C4\u5219\u3002\u9884\u8BBE\u9ED8\u8BA4\u7ED1\u5B9A\u56FA\u5B9A\u4FDD\u7559\uFF1B\u65B0\u5EFA\u6216\u7F16\u8F91\u5185\u5BB9\u8BF7\u524D\u5F80\u4E0A\u65B9\u201C\u6280\u80FD\u201D\u6216\u201C\u89C4\u5219\u201D\u9875\u3002", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(BindingEditor, { stages, defaults: (FLOW_PRESETS[flow] ?? FLOW_PRESETS.standard).config.stage_bindings ?? {}, stageBindings, setStageBindings, skills, rules }) }),
5171
- problems.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles.problems, children: [
5172
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { style: styles.problemsTitle, children: [
5173
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives.StateDot, { state: "error" }),
5158
+ /* @__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\u62E9\u8282\u70B9\uFF0C\u518D\u52FE\u9009\u9644\u52A0\u6280\u80FD\u4E0E\u89C4\u5219\u3002\u9884\u8BBE\u9ED8\u8BA4\u7ED1\u5B9A\u56FA\u5B9A\u4FDD\u7559\uFF1B\u65B0\u5EFA\u6216\u7F16\u8F91\u5185\u5BB9\u8BF7\u524D\u5F80\u4E0A\u65B9\u201C\u6280\u80FD\u201D\u6216\u201C\u89C4\u5219\u201D\u9875\u3002", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BindingEditor, { stages, defaults: (FLOW_PRESETS[flow] ?? FLOW_PRESETS.standard).config.stage_bindings ?? {}, stageBindings, setStageBindings: (next) => {
5159
+ setStageBindings(next);
5160
+ setDirty(true);
5161
+ setSavedAt("");
5162
+ }, skills, rules }) }),
5163
+ problems.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.problems, children: [
5164
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: styles.problemsTitle, children: [
5165
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.StateDot, { state: "error" }),
5174
5166
  "\u6709 ",
5175
5167
  problems.length,
5176
5168
  " \u4E2A\u95EE\u9898\uFF08\u4FDD\u5B58\u4F1A\u88AB\u62D2\u7EDD\uFF09"
5177
5169
  ] }),
5178
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("ul", { style: styles.problemsList, children: problems.map((p) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("li", { children: p }, p)) })
5179
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { style: styles.okText, children: [
5180
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives.StateDot, { state: "done" }),
5170
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { style: styles.problemsList, children: problems.map((p) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("li", { children: p }, p)) })
5171
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: styles.okText, children: [
5172
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.StateDot, { state: "done" }),
5181
5173
  source === "project" ? "\u914D\u7F6E\u6709\u6548" : "\u4F7F\u7528\u6D41\u7A0B\u9884\u8BBE\u9ED8\u8BA4\u7ED1\u5B9A\uFF08\u5C1A\u672A\u4FDD\u5B58\uFF09"
5182
5174
  ] }),
5183
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles.actions, children: [
5184
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
5175
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.actions, children: [
5176
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
5185
5177
  import_dsh_client_ui_primitives.Button,
5186
5178
  {
5187
5179
  variant: "primary",
5188
5180
  size: "md",
5189
- icon: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives.IconCheckOutline16, { size: 16 }),
5181
+ icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconCheckOutline16, { size: 16 }),
5190
5182
  disabled: problems.length > 0 || saving,
5191
5183
  onClick: () => {
5192
5184
  setSaving(true);
5193
5185
  void save(remote, flow, stageBindings, workspace, setSavedAt, setSource).then((ok) => {
5194
- if (ok) setConfigProblems([]);
5186
+ if (ok) {
5187
+ setConfigProblems([]);
5188
+ setDirty(false);
5189
+ }
5195
5190
  }).finally(() => setSaving(false));
5196
5191
  },
5197
- children: saving ? "\u6B63\u5728\u4FDD\u5B58\u2026" : "\u4FDD\u5B58\u5230 .dsh/eng.json"
5192
+ children: saving ? "\u6B63\u5728\u4FDD\u5B58\u2026" : dirty ? "\u4FDD\u5B58\u5230 .dsh/eng.json" : "\u5DF2\u4FDD\u5B58 \xB7 \u65E0\u9700\u4FDD\u5B58"
5198
5193
  }
5199
5194
  ),
5200
- savedAt !== "" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { style: styles.okText, children: [
5201
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives.StateDot, { state: savedAt.startsWith("\u5DF2") ? "done" : "error" }),
5195
+ savedAt !== "" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: styles.okText, children: [
5196
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.StateDot, { state: savedAt.startsWith("\u5DF2") ? "done" : "error" }),
5202
5197
  savedAt
5203
5198
  ] }) : null
5204
5199
  ] })
@@ -5215,8 +5210,8 @@ function sourceText(source) {
5215
5210
  }
5216
5211
  }
5217
5212
  function SectionCard({ icon, title, hint, children }) {
5218
- const [open, setOpen] = (0, import_react2.useState)(true);
5219
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: styles.section, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
5213
+ const [open, setOpen] = (0, import_react.useState)(true);
5214
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.section, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
5220
5215
  import_dsh_client_ui_primitives.DisclosureRow,
5221
5216
  {
5222
5217
  icon,
@@ -5229,45 +5224,120 @@ function SectionCard({ icon, title, hint, children }) {
5229
5224
  setOpen(!open);
5230
5225
  },
5231
5226
  keepContentWhenOpen: true,
5232
- children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles.cardBody, children: [
5233
- hint !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { style: styles.muted, children: hint }) : null,
5227
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.cardBody, children: [
5228
+ hint !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.muted, children: hint }) : null,
5234
5229
  children
5235
5230
  ] })
5236
5231
  }
5237
5232
  ) });
5238
5233
  }
5239
5234
  function BindingEditor({ stages, defaults, stageBindings, setStageBindings, skills, rules }) {
5240
- const [stage, setStage] = (0, import_react2.useState)(stages[0] ?? "");
5235
+ const [stage, setStage] = (0, import_react.useState)(stages[0] ?? "");
5236
+ const [expanded, setExpanded] = (0, import_react.useState)(null);
5241
5237
  const currentStage = stages.includes(stage) ? stage : stages[0] ?? "";
5242
- const toggleSkill = (skill) => {
5243
- if (currentStage === "") return;
5244
- const current = stageBindings[currentStage]?.skills ?? [];
5245
- const next = current.includes(skill) ? current.filter((s) => s !== skill) : [...current, skill].sort();
5246
- setStageBindings({ ...stageBindings, [currentStage]: { ...stageBindings[currentStage] ?? {}, skills: next } });
5238
+ const bindingFor = (name) => stageBindings[name] ?? {};
5239
+ const presetSkills = (name) => defaults[name]?.skills ?? [];
5240
+ const isPresetSkill = (name, raw) => presetSkills(name).some((entry) => formatResourceRef(entry.skill) === raw);
5241
+ const setSkills = (name, next) => {
5242
+ setStageBindings({ ...stageBindings, [name]: { ...bindingFor(name), skills: next } });
5247
5243
  };
5248
- const toggleRule = (rule) => {
5244
+ const toggleSkill = (raw) => {
5245
+ if (currentStage === "" || isPresetSkill(currentStage, raw)) return;
5246
+ const current = bindingFor(currentStage).skills ?? [];
5247
+ const next = current.some((entry) => formatResourceRef(entry.skill) === raw) ? current.filter((entry) => formatResourceRef(entry.skill) !== raw) : [...current, { skill: refFromText(raw), rules: [] }].sort((a, b) => formatResourceRef(a.skill).localeCompare(formatResourceRef(b.skill)));
5248
+ setSkills(currentStage, next);
5249
+ };
5250
+ const toggleRule = (skillRaw, ruleRaw) => {
5249
5251
  if (currentStage === "") return;
5250
- const current = stageBindings[currentStage]?.rules ?? [];
5251
- const next = current.includes(rule) ? current.filter((s) => s !== rule) : [...current, rule].sort();
5252
- setStageBindings({ ...stageBindings, [currentStage]: { ...stageBindings[currentStage] ?? {}, rules: next } });
5252
+ const current = bindingFor(currentStage).skills ?? [];
5253
+ setSkills(currentStage, current.map((entry) => {
5254
+ if (formatResourceRef(entry.skill) !== skillRaw) return entry;
5255
+ const has = entry.rules.some((rule) => formatResourceRef(rule) === ruleRaw);
5256
+ const next = has ? entry.rules.filter((rule) => formatResourceRef(rule) !== ruleRaw) : [...entry.rules, refFromText(ruleRaw)].sort((a, b) => formatResourceRef(a).localeCompare(formatResourceRef(b)));
5257
+ return { ...entry, rules: next };
5258
+ }));
5253
5259
  };
5254
5260
  if (currentStage === "") {
5255
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { style: styles.muted, children: "\u5F53\u524D\u6D41\u7A0B\u6CA1\u6709\u8282\u70B9\u3002" });
5256
- }
5257
- const boundSkills = stageBindings[currentStage]?.skills ?? [];
5258
- const boundRules = stageBindings[currentStage]?.rules ?? [];
5259
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles.section, children: [
5260
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { style: styles.hint, children: "\u7ED1\u5B9A\u6309\u540D\u79F0\u751F\u6548\uFF1B\u540C\u540D\u8D44\u6E90\u53EF\u5728\u8D44\u6E90\u7BA1\u7406\u4E2D\u6309\u9879\u76EE\uFF0F\u4E2A\u4EBA\u5206\u522B\u67E5\u770B\u3002\u5B8C\u6210\u8282\u70B9\u7684\u6280\u80FD\u5FC5\u987B\u5728\u8FDB\u5165\u5B8C\u6210\u524D\u6267\u884C\uFF0C\u6D4B\u8BD5\u6280\u80FD\u5EFA\u8BAE\u653E\u5728\u4EA4\u4ED8\u8282\u70B9\u3002" }),
5261
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles.field, children: [
5262
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: styles.bindingLabel, children: "\u9009\u62E9\u8282\u70B9" }),
5263
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: styles.chips, children: stages.map((s) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives.Pill, { active: s === currentStage, onClick: () => {
5261
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.muted, children: "\u5F53\u524D\u6D41\u7A0B\u6CA1\u6709\u8282\u70B9\u3002" });
5262
+ }
5263
+ const boundSkills = bindingFor(currentStage).skills ?? [];
5264
+ const unassigned = bindingFor(currentStage).legacy_rules ?? [];
5265
+ const presetCount = presetSkills(currentStage).length;
5266
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.section, children: [
5267
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.hint, children: "\u8282\u70B9\u53EA\u9009\u62E9\u6280\u80FD\uFF1B\u89C4\u5219\u5C5E\u4E8E\u6280\u80FD\u2014\u2014\u70B9\u5F00\u4E00\u4E2A\u6280\u80FD\u5C31\u80FD\u770B\u5230\u5B83\u5B8C\u6574\u7684\u89C4\u5219\u5217\u8868\uFF0C\u6302\u5230\u4EFB\u4F55\u8282\u70B9\u90FD\u662F\u540C\u4E00\u5957\u89C4\u5219\u3002 \u9700\u8981\u540C\u4E00\u6280\u80FD\u7528\u4E0D\u540C\u89C4\u5219\u65F6\uFF0C\u590D\u5236\u6210\u53E6\u4E00\u4E2A\u6280\u80FD\u518D\u5206\u522B\u914D\u7F6E\u3002" }),
5268
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.field, children: [
5269
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.bindingLabel, children: "\u9009\u62E9\u8282\u70B9" }),
5270
+ /* @__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: () => {
5264
5271
  setStage(s);
5265
5272
  }, children: s }, s)) })
5266
5273
  ] }),
5267
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "te-binding-grid", children: [
5268
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(BindingPicker, { title: "\u6280\u80FD", resources: skills, selected: boundSkills, defaults: defaults[currentStage]?.skills ?? [], onToggle: toggleSkill }),
5269
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(BindingPicker, { title: "\u89C4\u5219", resources: rules, selected: boundRules, defaults: defaults[currentStage]?.rules ?? [], onToggle: toggleRule })
5270
- ] }, currentStage)
5274
+ unassigned.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "te-alert", children: [
5275
+ "\u4EE5\u4E0B\u89C4\u5219\u5C5E\u4E8E",
5276
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: "\u8282\u70B9" }),
5277
+ "\u800C\u4E0D\u662F\u4EFB\u4F55\u6280\u80FD\uFF08\u65E7\u914D\u7F6E\uFF09\uFF1A",
5278
+ unassigned.join("\u3001"),
5279
+ "\u3002 \u5B83\u4EEC\u4ECD\u7136\u751F\u6548\uFF0C\u4F46\u9700\u8981\u6307\u5B9A\u5F52\u5C5E\u2014\u2014\u628A\u6BCF\u6761\u89C4\u5219\u52A0\u5230\u4F60\u5E0C\u671B\u627F\u8F7D\u5B83\u7684\u6280\u80FD\u4E0B\uFF0C\u7136\u540E\u4ECE\u8FD9\u91CC\u79FB\u9664\uFF1B \u82E5\u540C\u4E00\u6280\u80FD\u5728\u4E0D\u540C\u8282\u70B9\u9700\u8981\u4E0D\u540C\u89C4\u5219\uFF0C\u8BF7\u590D\u5236\u8BE5\u6280\u80FD\u518D\u5206\u522B\u914D\u7F6E\u3002"
5280
+ ] }) : null,
5281
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "te-binding-grid", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "te-binding-picker", "aria-label": "\u6280\u80FD\u7ED1\u5B9A", children: [
5282
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "te-binding-heading", children: [
5283
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h4", { children: "\u6280\u80FD" }),
5284
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "te-binding-count", children: [
5285
+ "\u5DF2\u9009 ",
5286
+ boundSkills.length,
5287
+ presetCount > 0 ? `\uFF08\u542B ${presetCount} \u9879\u9884\u8BBE\uFF09` : ""
5288
+ ] })
5289
+ ] }),
5290
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "te-binding-list", role: "group", "aria-label": "\u6280\u80FD\u5217\u8868", tabIndex: 0, children: [
5291
+ skills.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "te-binding-empty", children: "\u6682\u65E0\u6280\u80FD\uFF0C\u8BF7\u5728\u4E0A\u65B9\u201C\u6280\u80FD\u201D\u9875\u6DFB\u52A0\u3002" }) : null,
5292
+ skills.map((entry) => {
5293
+ const raw = formatResourceRef(entry.ref);
5294
+ const bound = boundSkills.find((candidate) => formatResourceRef(candidate.skill) === raw);
5295
+ const preset2 = isPresetSkill(currentStage, raw);
5296
+ const open = expanded === raw;
5297
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: `te-binding-option${bound !== void 0 ? " is-selected" : ""}`, children: [
5298
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
5299
+ "input",
5300
+ {
5301
+ type: "checkbox",
5302
+ "aria-label": raw,
5303
+ checked: bound !== void 0,
5304
+ disabled: preset2,
5305
+ onChange: () => toggleSkill(raw)
5306
+ }
5307
+ ),
5308
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "te-binding-detail", children: [
5309
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "te-binding-name", children: [
5310
+ entry.name,
5311
+ preset2 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "te-source-badge", children: "\u9884\u8BBE" }) : null
5312
+ ] }),
5313
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "te-binding-meta", children: [
5314
+ entry.sourceLabel,
5315
+ " \xB7 ",
5316
+ bound === void 0 ? "\u672A\u7ED1\u5B9A" : `${bound.rules.length} \u6761\u89C4\u5219`
5317
+ ] }),
5318
+ bound !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "te-link", onClick: () => setExpanded(open ? null : raw), children: open ? "\u6536\u8D77\u89C4\u5219" : "\u89C4\u5219\u8BBE\u7F6E" }) : null,
5319
+ open && bound !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "te-rule-list", children: [
5320
+ rules.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "te-binding-meta", children: "\u89C4\u5219\u5E93\u4E3A\u7A7A\u3002" }) : null,
5321
+ rules.map((rule) => {
5322
+ const ruleRaw = formatResourceRef(rule.ref);
5323
+ const on = bound.rules.some((candidate) => formatResourceRef(candidate) === ruleRaw);
5324
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "te-binding-filter", children: [
5325
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "checkbox", checked: on, onChange: () => toggleRule(raw, ruleRaw) }),
5326
+ " ",
5327
+ rule.name,
5328
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "te-binding-meta", children: [
5329
+ "\uFF08",
5330
+ rule.sourceLabel,
5331
+ "\uFF09"
5332
+ ] })
5333
+ ] }, ruleRaw);
5334
+ })
5335
+ ] }) : null
5336
+ ] })
5337
+ ] }, raw);
5338
+ })
5339
+ ] })
5340
+ ] }) }, currentStage)
5271
5341
  ] });
5272
5342
  }
5273
5343
  async function save(remote, flow, stageBindings, workspace, setSavedAt, setSource) {
@@ -5291,7 +5361,7 @@ async function save(remote, flow, stageBindings, workspace, setSavedAt, setSourc
5291
5361
  }
5292
5362
 
5293
5363
  // src/client/InitPanel.tsx
5294
- var import_react3 = require("react");
5364
+ var import_react2 = require("react");
5295
5365
  var import_dsh_client_ui_primitives2 = require("@deepseek-ai/dsh-client-ui-primitives");
5296
5366
  var MD_LABELS = { code: { copyLabel: "\u590D\u5236", copiedLabel: "\u5DF2\u590D\u5236" }, footnotes: "\u811A\u6CE8" };
5297
5367
  var INIT_TIMEOUT_S = 150;
@@ -5304,14 +5374,14 @@ var card = {
5304
5374
  padding: "12px 14px"
5305
5375
  };
5306
5376
  function InitPanel({ workspace, remote }) {
5307
- const [view, setView] = (0, import_react3.useState)(null);
5308
- const [generating, setGenerating] = (0, import_react3.useState)(false);
5309
- const [elapsed, setElapsed] = (0, import_react3.useState)(0);
5310
- const [draft, setDraft] = (0, import_react3.useState)(null);
5311
- const [editing, setEditing] = (0, import_react3.useState)(false);
5312
- const [body2, setBody] = (0, import_react3.useState)("");
5313
- const [msg, setMsg] = (0, import_react3.useState)("");
5314
- (0, import_react3.useEffect)(() => {
5377
+ const [view, setView] = (0, import_react2.useState)(null);
5378
+ const [generating, setGenerating] = (0, import_react2.useState)(false);
5379
+ const [elapsed, setElapsed] = (0, import_react2.useState)(0);
5380
+ const [draft, setDraft] = (0, import_react2.useState)(null);
5381
+ const [editing, setEditing] = (0, import_react2.useState)(false);
5382
+ const [body2, setBody] = (0, import_react2.useState)("");
5383
+ const [msg, setMsg] = (0, import_react2.useState)("");
5384
+ (0, import_react2.useEffect)(() => {
5315
5385
  if (!generating) {
5316
5386
  setElapsed(0);
5317
5387
  return;
@@ -5325,13 +5395,13 @@ function InitPanel({ workspace, remote }) {
5325
5395
  clearInterval(timer);
5326
5396
  };
5327
5397
  }, [generating]);
5328
- const refresh = (0, import_react3.useCallback)(() => {
5398
+ const refresh = (0, import_react2.useCallback)(() => {
5329
5399
  void remote.readInit(workspace).then((r) => {
5330
5400
  if (r.ok) setView(r.value);
5331
5401
  }, () => {
5332
5402
  });
5333
5403
  }, [remote, workspace]);
5334
- (0, import_react3.useEffect)(() => {
5404
+ (0, import_react2.useEffect)(() => {
5335
5405
  refresh();
5336
5406
  }, [refresh]);
5337
5407
  const generate = async () => {
@@ -5374,45 +5444,45 @@ function InitPanel({ workspace, remote }) {
5374
5444
  setMsg("");
5375
5445
  };
5376
5446
  const exists = view?.exists === true;
5377
- return (0, import_react3.createElement)(
5447
+ return (0, import_react2.createElement)(
5378
5448
  "div",
5379
5449
  { style: styles.section },
5380
- (0, import_react3.createElement)(
5450
+ (0, import_react2.createElement)(
5381
5451
  "div",
5382
5452
  { style: card },
5383
- (0, import_react3.createElement)(
5453
+ (0, import_react2.createElement)(
5384
5454
  "div",
5385
5455
  { style: { display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap" } },
5386
- (0, import_react3.createElement)(import_dsh_client_ui_primitives2.StateDot, { state: exists ? "done" : "ongoing" }),
5387
- (0, import_react3.createElement)("span", { style: styles.bindingLabel }, exists ? `\u5DF2\u521D\u59CB\u5316 \xB7 ${view.lines} \u884C\uFF08\u4E0A\u9650 200\uFF09` : "\u672A\u521D\u59CB\u5316"),
5388
- view?.path !== void 0 ? (0, import_react3.createElement)("span", { style: styles.sourceBadge }, `\u5DF2\u5B9A\u4F4D\u5230 ${view.path}`) : null
5456
+ (0, import_react2.createElement)(import_dsh_client_ui_primitives2.StateDot, { state: exists ? "done" : "ongoing" }),
5457
+ (0, import_react2.createElement)("span", { style: styles.bindingLabel }, exists ? `\u5DF2\u521D\u59CB\u5316 \xB7 ${view.lines} \u884C\uFF08\u4E0A\u9650 200\uFF09` : "\u672A\u521D\u59CB\u5316"),
5458
+ view?.path !== void 0 ? (0, import_react2.createElement)("span", { style: styles.sourceBadge }, `\u5DF2\u5B9A\u4F4D\u5230 ${view.path}`) : null
5389
5459
  ),
5390
- (0, import_react3.createElement)(
5460
+ (0, import_react2.createElement)(
5391
5461
  "p",
5392
5462
  { style: styles.muted },
5393
5463
  "\u9879\u76EE\u6839 AGENTS.md \u4F1A\u88AB DSH \u81EA\u52A8\u6CE8\u5165\u5230\u6BCF\u4E2A\u4F1A\u8BDD\u3002\u521D\u59CB\u5316\u4E00\u6B21\uFF0C\u4E4B\u540E\u6BCF\u6B21\u4EFB\u52A1\u5F00\u5DE5 AI \u90FD\u81EA\u5E26\u8FD9\u4EFD\u9879\u76EE\u8BA4\u77E5\uFF08\u9879\u76EE\u662F\u4EC0\u4E48 \u2192 \u600E\u4E48\u8DD1 \u2192 \u7ED3\u6784 \u2192 \u7EA6\u5B9A \u2192 \u5751\uFF09\u3002"
5394
5464
  ),
5395
- exists && !editing && draft === null ? (0, import_react3.createElement)(
5465
+ exists && !editing && draft === null ? (0, import_react2.createElement)(
5396
5466
  "div",
5397
5467
  { style: styles.mdPreview },
5398
- (0, import_react3.createElement)(import_dsh_client_ui_primitives2.MarkdownText, { text: view.content, labels: MD_LABELS })
5468
+ (0, import_react2.createElement)(import_dsh_client_ui_primitives2.MarkdownText, { text: view.content, labels: MD_LABELS })
5399
5469
  ) : null,
5400
- draft !== null ? (0, import_react3.createElement)(
5470
+ draft !== null ? (0, import_react2.createElement)(
5401
5471
  "div",
5402
5472
  { style: styles.section },
5403
- (0, import_react3.createElement)(
5473
+ (0, import_react2.createElement)(
5404
5474
  "div",
5405
5475
  { style: styles.sourceRow },
5406
- (0, import_react3.createElement)(import_dsh_client_ui_primitives2.StateDot, { state: "ongoing", size: 8 }),
5407
- (0, import_react3.createElement)("span", { style: styles.sourceBadge }, `AI \u8349\u7A3F \xB7 ${draft.lines} \u884C \xB7 \u5C1A\u672A\u5199\u5165`)
5476
+ (0, import_react2.createElement)(import_dsh_client_ui_primitives2.StateDot, { state: "ongoing", size: 8 }),
5477
+ (0, import_react2.createElement)("span", { style: styles.sourceBadge }, `AI \u8349\u7A3F \xB7 ${draft.lines} \u884C \xB7 \u5C1A\u672A\u5199\u5165`)
5408
5478
  ),
5409
- (0, import_react3.createElement)(
5479
+ (0, import_react2.createElement)(
5410
5480
  "div",
5411
5481
  { style: styles.mdPreview },
5412
- (0, import_react3.createElement)(import_dsh_client_ui_primitives2.MarkdownText, { text: draft.content, labels: MD_LABELS })
5482
+ (0, import_react2.createElement)(import_dsh_client_ui_primitives2.MarkdownText, { text: draft.content, labels: MD_LABELS })
5413
5483
  )
5414
5484
  ) : null,
5415
- editing ? (0, import_react3.createElement)("textarea", {
5485
+ editing ? (0, import_react2.createElement)("textarea", {
5416
5486
  style: { ...styles.textarea, minHeight: 300 },
5417
5487
  placeholder: "AGENTS.md \u6B63\u6587\uFF08Markdown\uFF0C\u2264200 \u884C\uFF09",
5418
5488
  value: body2,
@@ -5420,16 +5490,16 @@ function InitPanel({ workspace, remote }) {
5420
5490
  setBody(ev.target.value);
5421
5491
  }
5422
5492
  }) : null,
5423
- generating ? (0, import_react3.createElement)(
5493
+ generating ? (0, import_react2.createElement)(
5424
5494
  "p",
5425
5495
  { style: styles.status },
5426
5496
  `AI \u6B63\u5728\u626B\u63CF\u9879\u76EE\u5E76\u751F\u6210\u8349\u7A3F\u2026 \u5DF2\u8017\u65F6 ${elapsed} \u79D2\uFF08\u6700\u957F ${INIT_TIMEOUT_S} \u79D2\uFF09\uFF0C\u8BF7\u7A0D\u5019`
5427
5497
  ) : null,
5428
- msg !== "" ? (0, import_react3.createElement)("p", { style: styles.status }, msg) : null,
5429
- draft !== null ? (0, import_react3.createElement)(
5498
+ msg !== "" ? (0, import_react2.createElement)("p", { style: styles.status }, msg) : null,
5499
+ draft !== null ? (0, import_react2.createElement)(
5430
5500
  "div",
5431
5501
  { style: styles.row },
5432
- (0, import_react3.createElement)(import_dsh_client_ui_primitives2.Button, {
5502
+ (0, import_react2.createElement)(import_dsh_client_ui_primitives2.Button, {
5433
5503
  variant: "primary",
5434
5504
  size: "md",
5435
5505
  disabled: draft.lines > 200,
@@ -5438,14 +5508,14 @@ function InitPanel({ workspace, remote }) {
5438
5508
  void write(draft.content, exists);
5439
5509
  }
5440
5510
  }, exists ? "\u4FDD\u5B58\u5E76\u8986\u76D6" : "\u4FDD\u5B58"),
5441
- draft.lines > 200 ? (0, import_react3.createElement)("span", { style: styles.sourceBadge }, `\u8349\u7A3F ${draft.lines} \u884C\u8D85\u9650\uFF0C\u8BF7\u70B9\u300C\u653E\u5F03\u300D\u540E\u91CD\u8BD5`) : null,
5442
- (0, import_react3.createElement)(import_dsh_client_ui_primitives2.Button, { variant: "ghost", size: "md", onClick: () => {
5511
+ draft.lines > 200 ? (0, import_react2.createElement)("span", { style: styles.sourceBadge }, `\u8349\u7A3F ${draft.lines} \u884C\u8D85\u9650\uFF0C\u8BF7\u70B9\u300C\u653E\u5F03\u300D\u540E\u91CD\u8BD5`) : null,
5512
+ (0, import_react2.createElement)(import_dsh_client_ui_primitives2.Button, { variant: "ghost", size: "md", onClick: () => {
5443
5513
  setDraft(null);
5444
5514
  } }, "\u653E\u5F03")
5445
- ) : editing ? (0, import_react3.createElement)(
5515
+ ) : editing ? (0, import_react2.createElement)(
5446
5516
  "div",
5447
5517
  { style: styles.row },
5448
- (0, import_react3.createElement)(import_dsh_client_ui_primitives2.Button, {
5518
+ (0, import_react2.createElement)(import_dsh_client_ui_primitives2.Button, {
5449
5519
  variant: "primary",
5450
5520
  size: "md",
5451
5521
  disabled: body2.trim() === "",
@@ -5454,13 +5524,13 @@ function InitPanel({ workspace, remote }) {
5454
5524
  void write(body2, exists);
5455
5525
  }
5456
5526
  }, exists ? "\u4FDD\u5B58\u5E76\u8986\u76D6" : "\u4FDD\u5B58"),
5457
- (0, import_react3.createElement)(import_dsh_client_ui_primitives2.Button, { variant: "ghost", size: "md", onClick: () => {
5527
+ (0, import_react2.createElement)(import_dsh_client_ui_primitives2.Button, { variant: "ghost", size: "md", onClick: () => {
5458
5528
  setEditing(false);
5459
5529
  } }, "\u53D6\u6D88")
5460
- ) : (0, import_react3.createElement)(
5530
+ ) : (0, import_react2.createElement)(
5461
5531
  "div",
5462
5532
  { style: styles.row },
5463
- (0, import_react3.createElement)(import_dsh_client_ui_primitives2.Button, {
5533
+ (0, import_react2.createElement)(import_dsh_client_ui_primitives2.Button, {
5464
5534
  variant: "primary",
5465
5535
  size: "md",
5466
5536
  disabled: generating,
@@ -5469,21 +5539,21 @@ function InitPanel({ workspace, remote }) {
5469
5539
  void generate();
5470
5540
  }
5471
5541
  }, exists ? "\u91CD\u65B0\u521D\u59CB\u5316\uFF08AI \u626B\u63CF\u8986\u76D6\uFF09" : "\u8BA9 AI \u521D\u59CB\u5316"),
5472
- exists ? (0, import_react3.createElement)(import_dsh_client_ui_primitives2.Button, { variant: "outline", size: "md", onClick: startEdit }, "\u624B\u52A8\u7F16\u8F91") : null
5542
+ exists ? (0, import_react2.createElement)(import_dsh_client_ui_primitives2.Button, { variant: "outline", size: "md", onClick: startEdit }, "\u624B\u52A8\u7F16\u8F91") : null
5473
5543
  )
5474
5544
  )
5475
5545
  );
5476
5546
  }
5477
5547
 
5478
5548
  // src/client/SkillManager.tsx
5479
- var import_react6 = require("react");
5549
+ var import_react5 = require("react");
5480
5550
 
5481
5551
  // src/client/ResourceManager.tsx
5482
- var import_react5 = require("react");
5552
+ var import_react4 = require("react");
5483
5553
  var import_dsh_client_ui_primitives4 = require("@deepseek-ai/dsh-client-ui-primitives");
5484
5554
 
5485
5555
  // src/client/ResourceModal.tsx
5486
- var import_react4 = require("react");
5556
+ var import_react3 = require("react");
5487
5557
  var import_react_dom = require("react-dom");
5488
5558
  var import_dsh_client_ui_primitives3 = require("@deepseek-ai/dsh-client-ui-primitives");
5489
5559
  var rootStyle = {
@@ -5567,10 +5637,10 @@ var footerStyle = {
5567
5637
  flex: "none"
5568
5638
  };
5569
5639
  function ResourceModal({ title, description, onClose, footer, children }) {
5570
- const dialog = (0, import_react4.useRef)(null);
5571
- const closer = (0, import_react4.useRef)(onClose);
5640
+ const dialog = (0, import_react3.useRef)(null);
5641
+ const closer = (0, import_react3.useRef)(onClose);
5572
5642
  closer.current = onClose;
5573
- (0, import_react4.useEffect)(() => {
5643
+ (0, import_react3.useEffect)(() => {
5574
5644
  const previous = document.activeElement;
5575
5645
  dialog.current?.focus();
5576
5646
  const onKey = (e) => {
@@ -5603,26 +5673,26 @@ function ResourceModal({ title, description, onClose, footer, children }) {
5603
5673
  };
5604
5674
  }, []);
5605
5675
  return (0, import_react_dom.createPortal)(
5606
- (0, import_react4.createElement)(
5676
+ (0, import_react3.createElement)(
5607
5677
  "div",
5608
5678
  { style: rootStyle, className: "te-modal", role: "presentation" },
5609
- (0, import_react4.createElement)("div", { style: maskStyle, "aria-hidden": true, onClick: onClose }),
5610
- (0, import_react4.createElement)(
5679
+ (0, import_react3.createElement)("div", { style: maskStyle, "aria-hidden": true, onClick: onClose }),
5680
+ (0, import_react3.createElement)(
5611
5681
  "div",
5612
5682
  { style: dialogStyle, ref: dialog, tabIndex: -1, role: "dialog", "aria-modal": true, "aria-label": title },
5613
- (0, import_react4.createElement)(
5683
+ (0, import_react3.createElement)(
5614
5684
  "div",
5615
5685
  { style: headerStyle },
5616
- (0, import_react4.createElement)("h2", { style: titleStyle }, title),
5617
- (0, import_react4.createElement)(
5686
+ (0, import_react3.createElement)("h2", { style: titleStyle }, title),
5687
+ (0, import_react3.createElement)(
5618
5688
  "button",
5619
5689
  { type: "button", style: closeBtnStyle, "aria-label": "\u5173\u95ED", onClick: onClose },
5620
- (0, import_react4.createElement)(import_dsh_client_ui_primitives3.IconCloseOutline16, { size: 14 })
5690
+ (0, import_react3.createElement)(import_dsh_client_ui_primitives3.IconCloseOutline16, { size: 14 })
5621
5691
  )
5622
5692
  ),
5623
- description !== void 0 && description !== "" ? (0, import_react4.createElement)("p", { style: descStyle }, description) : null,
5624
- (0, import_react4.createElement)("div", { style: bodyStyle }, children),
5625
- footer !== void 0 ? (0, import_react4.createElement)("div", { style: footerStyle }, footer) : null
5693
+ description !== void 0 && description !== "" ? (0, import_react3.createElement)("p", { style: descStyle }, description) : null,
5694
+ (0, import_react3.createElement)("div", { style: bodyStyle }, children),
5695
+ footer !== void 0 ? (0, import_react3.createElement)("div", { style: footerStyle }, footer) : null
5626
5696
  )
5627
5697
  ),
5628
5698
  document.body
@@ -5637,35 +5707,35 @@ var sizeText = (bytes) => bytes < 1024 ? `${bytes} B` : bytes < 1024 * 1024 ? `$
5637
5707
  var fail = (r) => describeError(r.error ?? "\u64CD\u4F5C\u5931\u8D25");
5638
5708
  function ResourceManager({ workspace, remote, kind }) {
5639
5709
  const noun = kind === "skill" ? "\u6280\u80FD" : "\u89C4\u5219";
5640
- const [rows, setRows] = (0, import_react5.useState)([]);
5641
- const [query, setQuery] = (0, import_react5.useState)("");
5642
- const [filter, setFilter] = (0, import_react5.useState)("all");
5643
- const [notice, setNotice] = (0, import_react5.useState)("");
5644
- const [error, setError] = (0, import_react5.useState)("");
5645
- const [loading, setLoading] = (0, import_react5.useState)(true);
5646
- const [revision, refresh] = (0, import_react5.useState)(0);
5647
- const [busy, setBusy] = (0, import_react5.useState)(false);
5648
- const [roots, setRoots] = (0, import_react5.useState)(null);
5649
- const [importing, setImporting] = (0, import_react5.useState)(false);
5650
- const [request, setRequest] = (0, import_react5.useState)(null);
5651
- const [preview, setPreview] = (0, import_react5.useState)(null);
5652
- const [level, setLevel] = (0, import_react5.useState)("project");
5653
- const [manual, setManual] = (0, import_react5.useState)(false);
5654
- const [sourceDir, setSourceDir] = (0, import_react5.useState)("");
5655
- const [dirs, setDirs] = (0, import_react5.useState)([]);
5656
- const [browsePath, setBrowsePath] = (0, import_react5.useState)("");
5657
- const [editing, setEditing] = (0, import_react5.useState)(null);
5658
- const [viewing, setViewing] = (0, import_react5.useState)(false);
5659
- const [name, setName] = (0, import_react5.useState)("");
5660
- const [description, setDescription] = (0, import_react5.useState)("");
5661
- const [whenToUse, setWhenToUse] = (0, import_react5.useState)("");
5662
- const [body2, setBody] = (0, import_react5.useState)("");
5663
- const [deleting, setDeleting] = (0, import_react5.useState)(null);
5664
- const input = (0, import_react5.useRef)(null);
5665
- const fileEpoch = (0, import_react5.useRef)(0);
5666
- const browseEpoch = (0, import_react5.useRef)(0);
5710
+ const [rows, setRows] = (0, import_react4.useState)([]);
5711
+ const [query, setQuery] = (0, import_react4.useState)("");
5712
+ const [filter, setFilter] = (0, import_react4.useState)("all");
5713
+ const [notice, setNotice] = (0, import_react4.useState)("");
5714
+ const [error, setError] = (0, import_react4.useState)("");
5715
+ const [loading, setLoading] = (0, import_react4.useState)(true);
5716
+ const [revision, refresh] = (0, import_react4.useState)(0);
5717
+ const [busy, setBusy] = (0, import_react4.useState)(false);
5718
+ const [roots, setRoots] = (0, import_react4.useState)(null);
5719
+ const [importing, setImporting] = (0, import_react4.useState)(false);
5720
+ const [request, setRequest] = (0, import_react4.useState)(null);
5721
+ const [preview, setPreview] = (0, import_react4.useState)(null);
5722
+ const [level, setLevel] = (0, import_react4.useState)("project");
5723
+ const [manual, setManual] = (0, import_react4.useState)(false);
5724
+ const [sourceDir, setSourceDir] = (0, import_react4.useState)("");
5725
+ const [dirs, setDirs] = (0, import_react4.useState)([]);
5726
+ const [browsePath, setBrowsePath] = (0, import_react4.useState)("");
5727
+ const [editing, setEditing] = (0, import_react4.useState)(null);
5728
+ const [viewing, setViewing] = (0, import_react4.useState)(false);
5729
+ const [name, setName] = (0, import_react4.useState)("");
5730
+ const [description, setDescription] = (0, import_react4.useState)("");
5731
+ const [whenToUse, setWhenToUse] = (0, import_react4.useState)("");
5732
+ const [body2, setBody] = (0, import_react4.useState)("");
5733
+ const [deleting, setDeleting] = (0, import_react4.useState)(null);
5734
+ const input = (0, import_react4.useRef)(null);
5735
+ const fileEpoch = (0, import_react4.useRef)(0);
5736
+ const browseEpoch = (0, import_react4.useRef)(0);
5667
5737
  const readonly = editing !== null && editing !== "new" && levelOf(editing) === "bundled";
5668
- (0, import_react5.useEffect)(() => {
5738
+ (0, import_react4.useEffect)(() => {
5669
5739
  let active = true;
5670
5740
  setLoading(true);
5671
5741
  setRows([]);
@@ -5692,7 +5762,7 @@ function ResourceManager({ workspace, remote, kind }) {
5692
5762
  fileEpoch.current++;
5693
5763
  };
5694
5764
  }, [workspace, remote, kind, revision]);
5695
- (0, import_react5.useEffect)(() => {
5765
+ (0, import_react4.useEffect)(() => {
5696
5766
  let active = true;
5697
5767
  setPreview(null);
5698
5768
  if (!request) return;
@@ -5856,104 +5926,104 @@ function ResourceManager({ workspace, remote, kind }) {
5856
5926
  setBusy(false);
5857
5927
  }
5858
5928
  };
5859
- const status = () => error ? (0, import_react5.createElement)("div", { className: "te-alert", role: "alert" }, error) : null;
5860
- const targets = () => (0, import_react5.createElement)(
5929
+ const status = () => error ? (0, import_react4.createElement)("div", { className: "te-alert", role: "alert" }, error) : null;
5930
+ const targets = () => (0, import_react4.createElement)(
5861
5931
  "div",
5862
5932
  { className: "te-targets" },
5863
- ...["project", "user"].map((lvl) => (0, import_react5.createElement)(
5933
+ ...["project", "user"].map((lvl) => (0, import_react4.createElement)(
5864
5934
  "button",
5865
5935
  { type: "button", key: lvl, className: `te-target ${level === lvl ? "selected" : ""}`, "aria-pressed": level === lvl, disabled: busy || editing !== null && editing !== "new", onClick: () => {
5866
5936
  setPreview(null);
5867
5937
  setLevel(lvl);
5868
5938
  } },
5869
- (0, import_react5.createElement)("strong", null, lvl === "project" ? "\u9879\u76EE\u5171\u4EAB" : "\u4E2A\u4EBA\u5168\u5C40"),
5870
- (0, import_react5.createElement)("small", null, lvl === "project" ? "\u4EC5\u5F53\u524D\u5DE5\u4F5C\u533A\u4F7F\u7528" : "\u6B64\u4E3B\u673A\u4E0A\u7684\u6240\u6709\u9879\u76EE\u53EF\u7528")
5939
+ (0, import_react4.createElement)("strong", null, lvl === "project" ? "\u9879\u76EE\u5171\u4EAB" : "\u4E2A\u4EBA\u5168\u5C40"),
5940
+ (0, import_react4.createElement)("small", null, lvl === "project" ? "\u4EC5\u5F53\u524D\u5DE5\u4F5C\u533A\u4F7F\u7528" : "\u6B64\u4E3B\u673A\u4E0A\u7684\u6240\u6709\u9879\u76EE\u53EF\u7528")
5871
5941
  )),
5872
- (0, import_react5.createElement)("code", { className: "te-path" }, roots?.[level] ?? (level === "project" ? `${workspace}/.dsh/${kind}s` : `DSH_HOME/${kind}s`))
5942
+ (0, import_react4.createElement)("code", { className: "te-path" }, roots?.[level] ?? (level === "project" ? `${workspace}/.dsh/${kind}s` : `DSH_HOME/${kind}s`))
5873
5943
  );
5874
5944
  const visible = rows.filter((r) => `${r.name} ${r.description ?? ""}`.toLowerCase().includes(query.toLowerCase()) && (filter === "all" || levelOf(r) === filter));
5875
- return (0, import_react5.createElement)(
5945
+ return (0, import_react4.createElement)(
5876
5946
  "section",
5877
5947
  { className: "te-resource" },
5878
- (0, import_react5.createElement)("input", { type: "file", ref: input, hidden: true, "aria-label": kind === "skill" ? "\u9009\u62E9\u6280\u80FD\u6587\u4EF6\u5939" : "\u9009\u62E9\u89C4\u5219\u6587\u4EF6", ...kind === "skill" ? { webkitdirectory: "", multiple: true } : { accept: ".md,text/markdown" }, onChange: (e) => {
5948
+ (0, import_react4.createElement)("input", { type: "file", ref: input, hidden: true, "aria-label": kind === "skill" ? "\u9009\u62E9\u6280\u80FD\u6587\u4EF6\u5939" : "\u9009\u62E9\u89C4\u5219\u6587\u4EF6", ...kind === "skill" ? { webkitdirectory: "", multiple: true } : { accept: ".md,text/markdown" }, onChange: (e) => {
5879
5949
  void selected(Array.from(e.target.files ?? []));
5880
5950
  } }),
5881
- (0, import_react5.createElement)("div", { className: "te-section-heading" }, (0, import_react5.createElement)("div", null, (0, import_react5.createElement)("h2", null, `${noun}\u5E93`), (0, import_react5.createElement)("p", null, kind === "skill" ? "\u628A\u53EF\u590D\u7528\u7684\u5DE5\u4F5C\u65B9\u6CD5\u5E26\u5165\u9879\u76EE\u3002" : "\u4E3A\u9879\u76EE\u660E\u786E\u7EA6\u5B9A\uFF0C\u8BA9\u6BCF\u6B21\u4EA4\u4ED8\u4FDD\u6301\u4E00\u81F4\u3002")), (0, import_react5.createElement)("div", { className: "te-actions" }, (0, import_react5.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "outline", onClick: () => {
5951
+ (0, import_react4.createElement)("div", { className: "te-section-heading" }, (0, import_react4.createElement)("div", null, (0, import_react4.createElement)("h2", null, `${noun}\u5E93`), (0, import_react4.createElement)("p", null, kind === "skill" ? "\u628A\u53EF\u590D\u7528\u7684\u5DE5\u4F5C\u65B9\u6CD5\u5E26\u5165\u9879\u76EE\u3002" : "\u4E3A\u9879\u76EE\u660E\u786E\u7EA6\u5B9A\uFF0C\u8BA9\u6BCF\u6B21\u4EA4\u4ED8\u4FDD\u6301\u4E00\u81F4\u3002")), (0, import_react4.createElement)("div", { className: "te-actions" }, (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "outline", onClick: () => {
5882
5952
  void edit("new");
5883
- } }, `\u65B0\u5EFA${noun}`), (0, import_react5.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "primary", onClick: choose }, `\u5B89\u88C5${noun}`))),
5884
- (0, import_react5.createElement)("div", { className: "te-toolbar" }, (0, import_react5.createElement)("input", { className: "te-input", placeholder: `\u641C\u7D22${noun}\u540D\u79F0${kind === "skill" ? "\u6216\u63CF\u8FF0" : ""}`, value: query, onChange: (e) => setQuery(e.target.value) }), (0, import_react5.createElement)("select", { className: "te-input", "aria-label": "\u7B5B\u9009\u6765\u6E90", value: filter, onChange: (e) => setFilter(e.target.value) }, (0, import_react5.createElement)("option", { value: "all" }, `\u5168\u90E8\u6765\u6E90 \xB7 ${rows.length}`), (0, import_react5.createElement)("option", { value: "bundled" }, "\u5185\u7F6E"), (0, import_react5.createElement)("option", { value: "project" }, "\u9879\u76EE"), (0, import_react5.createElement)("option", { value: "user" }, "\u4E2A\u4EBA")), (0, import_react5.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "ghost", onClick: () => refresh((n) => n + 1), disabled: loading }, "\u5237\u65B0")),
5885
- notice ? (0, import_react5.createElement)("div", { className: "te-success", role: "status" }, notice) : null,
5953
+ } }, `\u65B0\u5EFA${noun}`), (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "primary", onClick: choose }, `\u5B89\u88C5${noun}`))),
5954
+ (0, import_react4.createElement)("div", { className: "te-toolbar" }, (0, import_react4.createElement)("input", { className: "te-input", placeholder: `\u641C\u7D22${noun}\u540D\u79F0${kind === "skill" ? "\u6216\u63CF\u8FF0" : ""}`, value: query, onChange: (e) => setQuery(e.target.value) }), (0, import_react4.createElement)("select", { className: "te-input", "aria-label": "\u7B5B\u9009\u6765\u6E90", value: filter, onChange: (e) => setFilter(e.target.value) }, (0, import_react4.createElement)("option", { value: "all" }, `\u5168\u90E8\u6765\u6E90 \xB7 ${rows.length}`), (0, import_react4.createElement)("option", { value: "bundled" }, "\u5185\u7F6E"), (0, import_react4.createElement)("option", { value: "project" }, "\u9879\u76EE"), (0, import_react4.createElement)("option", { value: "user" }, "\u4E2A\u4EBA")), (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "ghost", onClick: () => refresh((n) => n + 1), disabled: loading }, "\u5237\u65B0")),
5955
+ notice ? (0, import_react4.createElement)("div", { className: "te-success", role: "status" }, notice) : null,
5886
5956
  !importing && !editing && !deleting ? status() : null,
5887
- loading ? (0, import_react5.createElement)("div", { className: "te-empty", role: "status" }, "\u6B63\u5728\u52A0\u8F7D\u2026") : visible.length === 0 ? (0, import_react5.createElement)("div", { className: "te-empty" }, (0, import_react5.createElement)("h3", null, query || filter !== "all" ? "\u6CA1\u6709\u5339\u914D\u7684\u7ED3\u679C" : `\u8FD8\u6CA1\u6709${noun}`), (0, import_react5.createElement)("p", null, "\u8C03\u6574\u7B5B\u9009\uFF0C\u6216\u4F7F\u7528\u53F3\u4E0A\u89D2\u6309\u94AE\u6DFB\u52A0\u3002")) : (0, import_react5.createElement)("div", { className: "te-resource-grid" }, ...visible.map((row) => (0, import_react5.createElement)(
5957
+ loading ? (0, import_react4.createElement)("div", { className: "te-empty", role: "status" }, "\u6B63\u5728\u52A0\u8F7D\u2026") : visible.length === 0 ? (0, import_react4.createElement)("div", { className: "te-empty" }, (0, import_react4.createElement)("h3", null, query || filter !== "all" ? "\u6CA1\u6709\u5339\u914D\u7684\u7ED3\u679C" : `\u8FD8\u6CA1\u6709${noun}`), (0, import_react4.createElement)("p", null, "\u8C03\u6574\u7B5B\u9009\uFF0C\u6216\u4F7F\u7528\u53F3\u4E0A\u89D2\u6309\u94AE\u6DFB\u52A0\u3002")) : (0, import_react4.createElement)("div", { className: "te-resource-grid" }, ...visible.map((row) => (0, import_react4.createElement)(
5888
5958
  "article",
5889
5959
  { className: "te-resource-card", key: row.source + "/" + row.name },
5890
- (0, import_react5.createElement)("div", { className: "te-card-top" }, (0, import_react5.createElement)("span", { className: "te-resource-icon", "aria-hidden": true }, kind === "skill" ? "\u25C7" : "\u2261"), (0, import_react5.createElement)("span", { className: "te-badge" }, sourceText2(row.source))),
5891
- (0, import_react5.createElement)("h3", null, row.name),
5892
- (0, import_react5.createElement)("p", null, row.description || "\u9879\u76EE\u7EA6\u5B9A\u4E0E\u6267\u884C\u89C4\u5219"),
5893
- (0, import_react5.createElement)("div", { className: "te-actions" }, (0, import_react5.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "outline", size: "sm", onClick: () => {
5960
+ (0, import_react4.createElement)("div", { className: "te-card-top" }, (0, import_react4.createElement)("span", { className: "te-resource-icon", "aria-hidden": true }, kind === "skill" ? "\u25C7" : "\u2261"), (0, import_react4.createElement)("span", { className: "te-badge" }, sourceText2(row.source))),
5961
+ (0, import_react4.createElement)("h3", null, row.name),
5962
+ (0, import_react4.createElement)("p", null, row.description || "\u9879\u76EE\u7EA6\u5B9A\u4E0E\u6267\u884C\u89C4\u5219"),
5963
+ (0, import_react4.createElement)("div", { className: "te-actions" }, (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "outline", size: "sm", onClick: () => {
5894
5964
  void edit(row, true);
5895
- } }, "\u67E5\u770B"), levelOf(row) !== "bundled" ? (0, import_react5.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "ghost", size: "sm", onClick: () => {
5965
+ } }, "\u67E5\u770B"), levelOf(row) !== "bundled" ? (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "ghost", size: "sm", onClick: () => {
5896
5966
  void edit(row);
5897
- } }, "\u7F16\u8F91") : null, levelOf(row) !== "bundled" ? (0, import_react5.createElement)("button", { className: "te-delete", onClick: () => {
5967
+ } }, "\u7F16\u8F91") : null, levelOf(row) !== "bundled" ? (0, import_react4.createElement)("button", { className: "te-delete", onClick: () => {
5898
5968
  setDeleting(row);
5899
5969
  setError("");
5900
5970
  } }, "\u5220\u9664") : null)
5901
5971
  ))),
5902
- kind === "skill" ? (0, import_react5.createElement)("button", { className: "te-link", onClick: () => {
5972
+ kind === "skill" ? (0, import_react4.createElement)("button", { className: "te-link", onClick: () => {
5903
5973
  setImporting(true);
5904
5974
  setManual(true);
5905
5975
  setError("");
5906
5976
  } }, "\u9AD8\u7EA7\uFF1A\u4ECE Harness \u4E3B\u673A\u8DEF\u5F84\u5B89\u88C5") : null,
5907
- importing ? (0, import_react5.createElement)(
5977
+ importing ? (0, import_react4.createElement)(
5908
5978
  ResourceModal,
5909
- { title: `\u5B89\u88C5${noun}`, description: "\u5148\u68C0\u67E5\u5185\u5BB9\u548C\u5B89\u88C5\u4F4D\u7F6E\uFF0C\u786E\u8BA4\u540E\u624D\u4F1A\u5199\u5165\u3002", onClose: close, footer: (0, import_react5.createElement)("div", { className: "te-actions" }, (0, import_react5.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "ghost", disabled: busy, onClick: close }, "\u53D6\u6D88"), (0, import_react5.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "primary", disabled: busy || !preview || preview.conflict, onClick: () => {
5979
+ { title: `\u5B89\u88C5${noun}`, description: "\u5148\u68C0\u67E5\u5185\u5BB9\u548C\u5B89\u88C5\u4F4D\u7F6E\uFF0C\u786E\u8BA4\u540E\u624D\u4F1A\u5199\u5165\u3002", onClose: close, footer: (0, import_react4.createElement)("div", { className: "te-actions" }, (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "ghost", disabled: busy, onClick: close }, "\u53D6\u6D88"), (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "primary", disabled: busy || !preview || preview.conflict, onClick: () => {
5910
5980
  void install();
5911
5981
  } }, busy ? "\u5904\u7406\u4E2D\u2026" : "\u786E\u8BA4\u5B89\u88C5")) },
5912
5982
  targets(),
5913
- (0, import_react5.createElement)("div", { className: "te-actions" }, (0, import_react5.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "outline", disabled: busy, onClick: choose }, "\u91CD\u65B0\u9009\u62E9"), kind === "skill" ? (0, import_react5.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "ghost", disabled: busy, onClick: () => setManual(!manual) }, manual ? "\u6536\u8D77\u9AD8\u7EA7\u65B9\u5F0F" : "\u4E3B\u673A\u8DEF\u5F84") : null),
5914
- manual ? (0, import_react5.createElement)("div", { className: "te-advanced" }, (0, import_react5.createElement)("p", null, "\u6B64\u8DEF\u5F84\u4F4D\u4E8E Harness \u4E3B\u673A\uFF1B\u6D4F\u89C8\u5668\u9009\u62E9\u5668\u8BFB\u53D6\u7684\u662F\u4F60\u5F53\u524D\u7535\u8111\u3002"), (0, import_react5.createElement)("div", { className: "te-toolbar" }, (0, import_react5.createElement)("input", { className: "te-input", "aria-label": "\u4E3B\u673A\u6280\u80FD\u76EE\u5F55", value: sourceDir, onChange: (e) => {
5983
+ (0, import_react4.createElement)("div", { className: "te-actions" }, (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "outline", disabled: busy, onClick: choose }, "\u91CD\u65B0\u9009\u62E9"), kind === "skill" ? (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "ghost", disabled: busy, onClick: () => setManual(!manual) }, manual ? "\u6536\u8D77\u9AD8\u7EA7\u65B9\u5F0F" : "\u4E3B\u673A\u8DEF\u5F84") : null),
5984
+ manual ? (0, import_react4.createElement)("div", { className: "te-advanced" }, (0, import_react4.createElement)("p", null, "\u6B64\u8DEF\u5F84\u4F4D\u4E8E Harness \u4E3B\u673A\uFF1B\u6D4F\u89C8\u5668\u9009\u62E9\u5668\u8BFB\u53D6\u7684\u662F\u4F60\u5F53\u524D\u7535\u8111\u3002"), (0, import_react4.createElement)("div", { className: "te-toolbar" }, (0, import_react4.createElement)("input", { className: "te-input", "aria-label": "\u4E3B\u673A\u6280\u80FD\u76EE\u5F55", value: sourceDir, onChange: (e) => {
5915
5985
  setSourceDir(e.target.value);
5916
5986
  setRequest(null);
5917
- } }), (0, import_react5.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "outline", onClick: () => {
5987
+ } }), (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "outline", onClick: () => {
5918
5988
  void browse(sourceDir);
5919
- } }, "\u6D4F\u89C8"), (0, import_react5.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "outline", disabled: busy || !sourceDir.trim(), onClick: () => setRequest({ kind, level, path: workspace, files: [], sourceDir }) }, "\u9884\u89C8\u76EE\u5F55")), (0, import_react5.createElement)("div", { className: "te-dir-list" }, browsePath ? (0, import_react5.createElement)("button", { onClick: () => {
5989
+ } }, "\u6D4F\u89C8"), (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "outline", disabled: busy || !sourceDir.trim(), onClick: () => setRequest({ kind, level, path: workspace, files: [], sourceDir }) }, "\u9884\u89C8\u76EE\u5F55")), (0, import_react4.createElement)("div", { className: "te-dir-list" }, browsePath ? (0, import_react4.createElement)("button", { onClick: () => {
5920
5990
  void browse(browsePath.replace(/[\\/][^\\/]+[\\/]?$/u, "") || "/");
5921
- } }, "\u2191 \u4E0A\u7EA7\u76EE\u5F55") : null, ...dirs.map((d) => (0, import_react5.createElement)("button", { key: d.name, onClick: () => {
5991
+ } }, "\u2191 \u4E0A\u7EA7\u76EE\u5F55") : null, ...dirs.map((d) => (0, import_react4.createElement)("button", { key: d.name, onClick: () => {
5922
5992
  setRequest(null);
5923
5993
  void browse(browsePath.replace(/[\\/]+$/u, "") + "/" + d.name);
5924
5994
  } }, d.name + (d.hasSkill ? " \xB7 SKILL.md" : ""))))) : null,
5925
- busy ? (0, import_react5.createElement)("p", { role: "status" }, "\u6B63\u5728\u6821\u9A8C\u6587\u4EF6\uFF0C\u8BF7\u7A0D\u5019\u2026") : null,
5995
+ busy ? (0, import_react4.createElement)("p", { role: "status" }, "\u6B63\u5728\u6821\u9A8C\u6587\u4EF6\uFF0C\u8BF7\u7A0D\u5019\u2026") : null,
5926
5996
  status(),
5927
- preview ? (0, import_react5.createElement)("div", { className: "te-preview" }, (0, import_react5.createElement)("h3", null, preview.name), (0, import_react5.createElement)("p", null, preview.description), (0, import_react5.createElement)("div", { className: "te-actions" }, (0, import_react5.createElement)("span", { className: "te-badge" }, `${preview.files} \u4E2A\u6587\u4EF6`), (0, import_react5.createElement)("span", { className: "te-badge" }, sizeText(preview.bytes))), (0, import_react5.createElement)("code", { className: "te-path" }, preview.target), preview.conflict ? (0, import_react5.createElement)("div", { className: "te-alert", role: "alert" }, "\u5DF2\u6709\u540C\u540D\u8D44\u6E90\u3002\u8BF7\u53D6\u6D88\u5E76\u68C0\u67E5\u73B0\u6709\u5185\u5BB9\uFF0C\u5B89\u88C5\u4E0D\u4F1A\u8986\u76D6\u5B83\u3002") : null, (0, import_react5.createElement)("div", { className: "te-markdown" }, (0, import_react5.createElement)(import_dsh_client_ui_primitives4.MarkdownText, { text: preview.content, labels }))) : null
5997
+ preview ? (0, import_react4.createElement)("div", { className: "te-preview" }, (0, import_react4.createElement)("h3", null, preview.name), (0, import_react4.createElement)("p", null, preview.description), (0, import_react4.createElement)("div", { className: "te-actions" }, (0, import_react4.createElement)("span", { className: "te-badge" }, `${preview.files} \u4E2A\u6587\u4EF6`), (0, import_react4.createElement)("span", { className: "te-badge" }, sizeText(preview.bytes))), (0, import_react4.createElement)("code", { className: "te-path" }, preview.target), preview.conflict ? (0, import_react4.createElement)("div", { className: "te-alert", role: "alert" }, "\u5DF2\u6709\u540C\u540D\u8D44\u6E90\u3002\u8BF7\u53D6\u6D88\u5E76\u68C0\u67E5\u73B0\u6709\u5185\u5BB9\uFF0C\u5B89\u88C5\u4E0D\u4F1A\u8986\u76D6\u5B83\u3002") : null, (0, import_react4.createElement)("div", { className: "te-markdown" }, (0, import_react4.createElement)(import_dsh_client_ui_primitives4.MarkdownText, { text: preview.content, labels }))) : null
5928
5998
  ) : null,
5929
- editing ? (0, import_react5.createElement)(
5999
+ editing ? (0, import_react4.createElement)(
5930
6000
  ResourceModal,
5931
- { title: editing === "new" ? `\u65B0\u5EFA${noun}` : `${viewing ? "\u67E5\u770B" : "\u7F16\u8F91"}${noun} \xB7 ${name}`, onClose: close, footer: (0, import_react5.createElement)("div", { className: "te-actions" }, (0, import_react5.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "ghost", disabled: busy, onClick: close }, "\u5173\u95ED"), !readonly ? (0, import_react5.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "outline", disabled: busy, onClick: () => setViewing(!viewing) }, viewing ? "\u7F16\u8F91\u5185\u5BB9" : "\u9884\u89C8") : null, !readonly ? (0, import_react5.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "primary", disabled: busy || !name.trim() || !body2.trim() || kind === "skill" && !description.trim(), onClick: () => {
6001
+ { title: editing === "new" ? `\u65B0\u5EFA${noun}` : `${viewing ? "\u67E5\u770B" : "\u7F16\u8F91"}${noun} \xB7 ${name}`, onClose: close, footer: (0, import_react4.createElement)("div", { className: "te-actions" }, (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "ghost", disabled: busy, onClick: close }, "\u5173\u95ED"), !readonly ? (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "outline", disabled: busy, onClick: () => setViewing(!viewing) }, viewing ? "\u7F16\u8F91\u5185\u5BB9" : "\u9884\u89C8") : null, !readonly ? (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "primary", disabled: busy || !name.trim() || !body2.trim() || kind === "skill" && !description.trim(), onClick: () => {
5932
6002
  void save2();
5933
6003
  } }, busy ? "\u5904\u7406\u4E2D\u2026" : "\u4FDD\u5B58") : null) },
5934
- !readonly ? targets() : (0, import_react5.createElement)("p", { className: "te-badge" }, "\u5185\u7F6E\u8D44\u6E90 \xB7 \u53EA\u8BFB"),
6004
+ !readonly ? targets() : (0, import_react4.createElement)("p", { className: "te-badge" }, "\u5185\u7F6E\u8D44\u6E90 \xB7 \u53EA\u8BFB"),
5935
6005
  status(),
5936
- viewing ? (0, import_react5.createElement)("div", { className: "te-markdown" }, (0, import_react5.createElement)(import_dsh_client_ui_primitives4.MarkdownText, { text: body2, labels })) : (0, import_react5.createElement)("div", { className: "te-form" }, (0, import_react5.createElement)("label", null, "\u540D\u79F0", (0, import_react5.createElement)("input", { className: "te-input", value: name, disabled: editing !== "new" || busy, onChange: (e) => setName(e.target.value), placeholder: "\u5C0F\u5199\u5B57\u6BCD\u3001\u6570\u5B57\u548C\u8FDE\u5B57\u7B26" })), kind === "skill" ? (0, import_react5.createElement)("label", null, "\u63CF\u8FF0", (0, import_react5.createElement)("input", { className: "te-input", value: description, disabled: busy, onChange: (e) => setDescription(e.target.value) })) : null, kind === "skill" ? (0, import_react5.createElement)("label", null, "\u4F7F\u7528\u65F6\u673A\uFF08\u53EF\u9009\uFF09", (0, import_react5.createElement)("input", { className: "te-input", value: whenToUse, disabled: busy, onChange: (e) => setWhenToUse(e.target.value) })) : null, (0, import_react5.createElement)("label", null, "Markdown \u6B63\u6587", (0, import_react5.createElement)("textarea", { className: "te-input te-editor", value: body2, disabled: busy, onChange: (e) => setBody(e.target.value) })))
6006
+ viewing ? (0, import_react4.createElement)("div", { className: "te-markdown" }, (0, import_react4.createElement)(import_dsh_client_ui_primitives4.MarkdownText, { text: body2, labels })) : (0, import_react4.createElement)("div", { className: "te-form" }, (0, import_react4.createElement)("label", null, "\u540D\u79F0", (0, import_react4.createElement)("input", { className: "te-input", value: name, disabled: editing !== "new" || busy, onChange: (e) => setName(e.target.value), placeholder: "\u5C0F\u5199\u5B57\u6BCD\u3001\u6570\u5B57\u548C\u8FDE\u5B57\u7B26" })), kind === "skill" ? (0, import_react4.createElement)("label", null, "\u63CF\u8FF0", (0, import_react4.createElement)("input", { className: "te-input", value: description, disabled: busy, onChange: (e) => setDescription(e.target.value) })) : null, kind === "skill" ? (0, import_react4.createElement)("label", null, "\u4F7F\u7528\u65F6\u673A\uFF08\u53EF\u9009\uFF09", (0, import_react4.createElement)("input", { className: "te-input", value: whenToUse, disabled: busy, onChange: (e) => setWhenToUse(e.target.value) })) : null, (0, import_react4.createElement)("label", null, "Markdown \u6B63\u6587", (0, import_react4.createElement)("textarea", { className: "te-input te-editor", value: body2, disabled: busy, onChange: (e) => setBody(e.target.value) })))
5937
6007
  ) : null,
5938
- deleting ? (0, import_react5.createElement)(ResourceModal, { title: `\u5220\u9664${noun}\u300C${deleting.name}\u300D\uFF1F`, description: levelOf(deleting) === "user" ? "\u8FD9\u662F\u4E2A\u4EBA\u5168\u5C40\u8D44\u6E90\uFF0C\u5220\u9664\u4F1A\u5F71\u54CD\u6B64\u4E3B\u673A\u4E0A\u7684\u6240\u6709\u9879\u76EE\u3002" : "\u5220\u9664\u5C06\u5F71\u54CD\u5F53\u524D\u9879\u76EE\u3002", onClose: close, footer: (0, import_react5.createElement)("div", { className: "te-actions" }, (0, import_react5.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "outline", disabled: busy, onClick: close }, "\u4FDD\u7559"), (0, import_react5.createElement)("button", { className: "te-danger-button", disabled: busy, onClick: () => {
6008
+ deleting ? (0, import_react4.createElement)(ResourceModal, { title: `\u5220\u9664${noun}\u300C${deleting.name}\u300D\uFF1F`, description: levelOf(deleting) === "user" ? "\u8FD9\u662F\u4E2A\u4EBA\u5168\u5C40\u8D44\u6E90\uFF0C\u5220\u9664\u4F1A\u5F71\u54CD\u6B64\u4E3B\u673A\u4E0A\u7684\u6240\u6709\u9879\u76EE\u3002" : "\u5220\u9664\u5C06\u5F71\u54CD\u5F53\u524D\u9879\u76EE\u3002", onClose: close, footer: (0, import_react4.createElement)("div", { className: "te-actions" }, (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "outline", disabled: busy, onClick: close }, "\u4FDD\u7559"), (0, import_react4.createElement)("button", { className: "te-danger-button", disabled: busy, onClick: () => {
5939
6009
  void remove();
5940
- } }, busy ? "\u5220\u9664\u4E2D\u2026" : "\u786E\u8BA4\u6C38\u4E45\u5220\u9664")) }, (0, import_react5.createElement)("code", { className: "te-path" }, `${roots?.[levelOf(deleting) === "user" ? "user" : "project"] ?? "\u8D44\u6E90\u76EE\u5F55"}/${deleting.name}${kind === "rule" ? ".md" : ""}`), (0, import_react5.createElement)("p", null, "\u6B64\u64CD\u4F5C\u4E0D\u4F1A\u8FDB\u5165\u56DE\u6536\u7AD9\uFF0C\u8BF7\u786E\u8BA4\u5DF2\u6709\u5907\u4EFD\u3002"), status()) : null
6010
+ } }, busy ? "\u5220\u9664\u4E2D\u2026" : "\u786E\u8BA4\u6C38\u4E45\u5220\u9664")) }, (0, import_react4.createElement)("code", { className: "te-path" }, `${roots?.[levelOf(deleting) === "user" ? "user" : "project"] ?? "\u8D44\u6E90\u76EE\u5F55"}/${deleting.name}${kind === "rule" ? ".md" : ""}`), (0, import_react4.createElement)("p", null, "\u6B64\u64CD\u4F5C\u4E0D\u4F1A\u8FDB\u5165\u56DE\u6536\u7AD9\uFF0C\u8BF7\u786E\u8BA4\u5DF2\u6709\u5907\u4EFD\u3002"), status()) : null
5941
6011
  );
5942
6012
  }
5943
6013
 
5944
6014
  // src/client/SkillManager.tsx
5945
6015
  function SkillManager(props) {
5946
- return (0, import_react6.createElement)(ResourceManager, { ...props, key: props.workspace, kind: "skill" });
6016
+ return (0, import_react5.createElement)(ResourceManager, { ...props, key: props.workspace, kind: "skill" });
5947
6017
  }
5948
6018
 
5949
6019
  // src/client/RuleManager.tsx
5950
- var import_react7 = require("react");
6020
+ var import_react6 = require("react");
5951
6021
  function RuleManager(props) {
5952
- return (0, import_react7.createElement)(ResourceManager, { ...props, key: props.workspace, kind: "rule" });
6022
+ return (0, import_react6.createElement)(ResourceManager, { ...props, key: props.workspace, kind: "rule" });
5953
6023
  }
5954
6024
 
5955
6025
  // src/client/TaskLedger.tsx
5956
- var import_react8 = require("react");
6026
+ var import_react7 = require("react");
5957
6027
  var import_dsh_client_ui_primitives5 = require("@deepseek-ai/dsh-client-ui-primitives");
5958
6028
  var card2 = {
5959
6029
  display: "flex",
@@ -5992,10 +6062,10 @@ var badge = {
5992
6062
  color: "var(--dsw-alias-label-secondary)"
5993
6063
  };
5994
6064
  function verdictDot(outcome) {
5995
- return (0, import_react8.createElement)(import_dsh_client_ui_primitives5.StateDot, { state: outcome === "pass" ? "done" : "error" });
6065
+ return (0, import_react7.createElement)(import_dsh_client_ui_primitives5.StateDot, { state: outcome === "pass" ? "done" : "error" });
5996
6066
  }
5997
6067
  function itemStatusDot(status) {
5998
- return (0, import_react8.createElement)(import_dsh_client_ui_primitives5.StateDot, { state: status === "done" ? "done" : "ongoing" });
6068
+ return (0, import_react7.createElement)(import_dsh_client_ui_primitives5.StateDot, { state: status === "done" ? "done" : "ongoing" });
5999
6069
  }
6000
6070
  function timeText(at) {
6001
6071
  return at.slice(0, 19).replace("T", " ");
@@ -6003,48 +6073,48 @@ function timeText(at) {
6003
6073
  function itemAudit(item) {
6004
6074
  const lines = [];
6005
6075
  if (item.dispatch !== void 0) {
6006
- lines.push((0, import_react8.createElement)(
6076
+ lines.push((0, import_react7.createElement)(
6007
6077
  "div",
6008
6078
  { key: "dispatch", style: metaLine },
6009
- (0, import_react8.createElement)("span", { style: badge }, "\u5DF2\u6D3E\u53D1"),
6010
- (0, import_react8.createElement)("span", null, item.dispatch.description === "" ? "\uFF08\u65E0\u63CF\u8FF0\uFF09" : item.dispatch.description),
6011
- (0, import_react8.createElement)("span", { style: badge }, timeText(item.dispatch.at))
6079
+ (0, import_react7.createElement)("span", { style: badge }, "\u5DF2\u6D3E\u53D1"),
6080
+ (0, import_react7.createElement)("span", null, item.dispatch.description === "" ? "\uFF08\u65E0\u63CF\u8FF0\uFF09" : item.dispatch.description),
6081
+ (0, import_react7.createElement)("span", { style: badge }, timeText(item.dispatch.at))
6012
6082
  ));
6013
6083
  }
6014
6084
  if (item.review !== void 0) {
6015
6085
  const spec = item.review.spec;
6016
6086
  const quality = item.review.quality;
6017
- lines.push((0, import_react8.createElement)(
6087
+ lines.push((0, import_react7.createElement)(
6018
6088
  "div",
6019
6089
  { key: "review", style: metaLine },
6020
6090
  verdictDot(spec.outcome),
6021
- (0, import_react8.createElement)("span", null, `\u89C4\u683C\u7B26\u5408 ${spec.outcome === "pass" ? "\u901A\u8FC7" : "\u4E0D\u901A\u8FC7"}`),
6022
- (0, import_react8.createElement)("span", null, "\xB7"),
6091
+ (0, import_react7.createElement)("span", null, `\u89C4\u683C\u7B26\u5408 ${spec.outcome === "pass" ? "\u901A\u8FC7" : "\u4E0D\u901A\u8FC7"}`),
6092
+ (0, import_react7.createElement)("span", null, "\xB7"),
6023
6093
  verdictDot(quality.outcome),
6024
- (0, import_react8.createElement)("span", null, `\u4EE3\u7801\u8D28\u91CF ${quality.outcome === "pass" ? "\u901A\u8FC7" : "\u4E0D\u901A\u8FC7"}`)
6094
+ (0, import_react7.createElement)("span", null, `\u4EE3\u7801\u8D28\u91CF ${quality.outcome === "pass" ? "\u901A\u8FC7" : "\u4E0D\u901A\u8FC7"}`)
6025
6095
  ));
6026
6096
  const failNotes = [spec, quality].flatMap((stage) => stage.outcome === "fail" ? stage.notes ?? [] : []);
6027
6097
  if (failNotes.length > 0) {
6028
- lines.push((0, import_react8.createElement)(
6098
+ lines.push((0, import_react7.createElement)(
6029
6099
  "div",
6030
6100
  { key: "notes", style: metaLine },
6031
- ...failNotes.map((note) => (0, import_react8.createElement)("span", { key: note, style: badge }, note))
6101
+ ...failNotes.map((note) => (0, import_react7.createElement)("span", { key: note, style: badge }, note))
6032
6102
  ));
6033
6103
  }
6034
6104
  }
6035
6105
  if (lines.length === 0) {
6036
- lines.push((0, import_react8.createElement)("div", { key: "none", style: metaLine }, (0, import_react8.createElement)("span", { style: badge }, "\u672A\u6D3E\u53D1 / \u672A\u5BA1\u67E5")));
6106
+ lines.push((0, import_react7.createElement)("div", { key: "none", style: metaLine }, (0, import_react7.createElement)("span", { style: badge }, "\u672A\u6D3E\u53D1 / \u672A\u5BA1\u67E5")));
6037
6107
  }
6038
- return (0, import_react8.createElement)("div", { style: { display: "flex", flexDirection: "column", gap: 4 } }, ...lines);
6108
+ return (0, import_react7.createElement)("div", { style: { display: "flex", flexDirection: "column", gap: 4 } }, ...lines);
6039
6109
  }
6040
6110
  function TaskLedger({ workspace, remote }) {
6041
- const [tasks, setTasks] = (0, import_react8.useState)([]);
6042
- const [error, setError] = (0, import_react8.useState)("");
6043
- const [loading, setLoading] = (0, import_react8.useState)(true);
6044
- const [query, setQuery] = (0, import_react8.useState)("");
6045
- const [risk, setRisk] = (0, import_react8.useState)("all");
6046
- const [stage, setStage] = (0, import_react8.useState)("all");
6047
- const refresh = (0, import_react8.useCallback)(() => {
6111
+ const [tasks, setTasks] = (0, import_react7.useState)([]);
6112
+ const [error, setError] = (0, import_react7.useState)("");
6113
+ const [loading, setLoading] = (0, import_react7.useState)(true);
6114
+ const [query, setQuery] = (0, import_react7.useState)("");
6115
+ const [risk, setRisk] = (0, import_react7.useState)("all");
6116
+ const [stage, setStage] = (0, import_react7.useState)("all");
6117
+ const refresh = (0, import_react7.useCallback)(() => {
6048
6118
  if (workspace === "") return;
6049
6119
  setError("");
6050
6120
  setLoading(true);
@@ -6057,57 +6127,57 @@ function TaskLedger({ workspace, remote }) {
6057
6127
  setError("\u8BFB\u53D6\u53F0\u8D26\u5931\u8D25\uFF1A" + describeError(reason));
6058
6128
  });
6059
6129
  }, [remote, workspace]);
6060
- (0, import_react8.useEffect)(() => {
6130
+ (0, import_react7.useEffect)(() => {
6061
6131
  refresh();
6062
6132
  }, [refresh]);
6063
6133
  const visible = tasks.filter((task) => `${task.task_id} ${task.title} ${task.branch}`.toLowerCase().includes(query.toLowerCase()) && (risk === "all" || task.risk_level === risk) && (stage === "all" || task.stage === stage));
6064
- return (0, import_react8.createElement)(
6134
+ return (0, import_react7.createElement)(
6065
6135
  "div",
6066
6136
  { style: styles.section },
6067
- (0, import_react8.createElement)(
6137
+ (0, import_react7.createElement)(
6068
6138
  "div",
6069
6139
  { className: "te-toolbar" },
6070
- (0, import_react8.createElement)("input", { className: "te-input", placeholder: "\u641C\u7D22\u4EFB\u52A1\u3001\u6807\u9898\u6216\u5206\u652F", value: query, onChange: (e) => setQuery(e.target.value) }),
6071
- (0, import_react8.createElement)("select", { className: "te-input", "aria-label": "\u98CE\u9669\u7B5B\u9009", value: risk, onChange: (e) => setRisk(e.target.value) }, (0, import_react8.createElement)("option", { value: "all" }, "\u5168\u90E8\u98CE\u9669"), (0, import_react8.createElement)("option", { value: "standard" }, "\u6807\u51C6"), (0, import_react8.createElement)("option", { value: "high_risk" }, "\u9AD8\u98CE\u9669")),
6072
- (0, import_react8.createElement)("select", { className: "te-input", "aria-label": "\u9636\u6BB5\u7B5B\u9009", value: stage, onChange: (e) => setStage(e.target.value) }, (0, import_react8.createElement)("option", { value: "all" }, "\u5168\u90E8\u9636\u6BB5"), ...Array.from(new Set(tasks.map((t) => t.stage))).map((value) => (0, import_react8.createElement)("option", { key: value, value }, value)))
6140
+ (0, import_react7.createElement)("input", { className: "te-input", placeholder: "\u641C\u7D22\u4EFB\u52A1\u3001\u6807\u9898\u6216\u5206\u652F", value: query, onChange: (e) => setQuery(e.target.value) }),
6141
+ (0, import_react7.createElement)("select", { className: "te-input", "aria-label": "\u98CE\u9669\u7B5B\u9009", value: risk, onChange: (e) => setRisk(e.target.value) }, (0, import_react7.createElement)("option", { value: "all" }, "\u5168\u90E8\u98CE\u9669"), (0, import_react7.createElement)("option", { value: "standard" }, "\u6807\u51C6"), (0, import_react7.createElement)("option", { value: "high_risk" }, "\u9AD8\u98CE\u9669")),
6142
+ (0, import_react7.createElement)("select", { className: "te-input", "aria-label": "\u9636\u6BB5\u7B5B\u9009", value: stage, onChange: (e) => setStage(e.target.value) }, (0, import_react7.createElement)("option", { value: "all" }, "\u5168\u90E8\u9636\u6BB5"), ...Array.from(new Set(tasks.map((t) => t.stage))).map((value) => (0, import_react7.createElement)("option", { key: value, value }, value)))
6073
6143
  ),
6074
- (0, import_react8.createElement)(
6144
+ (0, import_react7.createElement)(
6075
6145
  "div",
6076
6146
  { style: headerRow },
6077
- (0, import_react8.createElement)("span", { style: styles.bindingLabel }, "\u4EFB\u52A1\u53F0\u8D26"),
6078
- (0, import_react8.createElement)("span", { style: styles.sourceBadge }, "\u53EA\u8BFB \xB7 \u6765\u81EA .dsh/task-*.json"),
6079
- (0, import_react8.createElement)(import_dsh_client_ui_primitives5.Button, { variant: "outline", size: "sm", disabled: loading, onClick: refresh }, loading ? "\u8BFB\u53D6\u4E2D\u2026" : "\u5237\u65B0")
6147
+ (0, import_react7.createElement)("span", { style: styles.bindingLabel }, "\u4EFB\u52A1\u53F0\u8D26"),
6148
+ (0, import_react7.createElement)("span", { style: styles.sourceBadge }, "\u53EA\u8BFB \xB7 \u6765\u81EA .dsh/task-*.json"),
6149
+ (0, import_react7.createElement)(import_dsh_client_ui_primitives5.Button, { variant: "outline", size: "sm", disabled: loading, onClick: refresh }, loading ? "\u8BFB\u53D6\u4E2D\u2026" : "\u5237\u65B0")
6080
6150
  ),
6081
- loading ? (0, import_react8.createElement)("p", { role: "status" }, "\u6B63\u5728\u8BFB\u53D6\u4EFB\u52A1\u2026") : error !== "" ? (0, import_react8.createElement)("p", { style: styles.status }, error) : tasks.length === 0 ? (0, import_react8.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") : visible.length === 0 ? (0, import_react8.createElement)("div", { className: "te-empty" }, "\u6CA1\u6709\u5339\u914D\u7684\u4EFB\u52A1\uFF0C\u8BF7\u8C03\u6574\u7B5B\u9009\u3002") : (0, import_react8.createElement)(
6151
+ loading ? (0, import_react7.createElement)("p", { role: "status" }, "\u6B63\u5728\u8BFB\u53D6\u4EFB\u52A1\u2026") : error !== "" ? (0, import_react7.createElement)("p", { style: styles.status }, error) : tasks.length === 0 ? (0, import_react7.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") : visible.length === 0 ? (0, import_react7.createElement)("div", { className: "te-empty" }, "\u6CA1\u6709\u5339\u914D\u7684\u4EFB\u52A1\uFF0C\u8BF7\u8C03\u6574\u7B5B\u9009\u3002") : (0, import_react7.createElement)(
6082
6152
  "div",
6083
6153
  { style: { display: "flex", flexDirection: "column", gap: 12 } },
6084
- ...visible.map((task) => (0, import_react8.createElement)(
6154
+ ...visible.map((task) => (0, import_react7.createElement)(
6085
6155
  "div",
6086
6156
  { key: task.task_id, style: card2 },
6087
- (0, import_react8.createElement)(
6157
+ (0, import_react7.createElement)(
6088
6158
  "div",
6089
6159
  { style: headerRow },
6090
- (0, import_react8.createElement)("span", { style: { fontSize: 14, fontWeight: 600, color: "var(--dsw-alias-label-primary)" } }, task.task_id),
6091
- (0, import_react8.createElement)("span", { style: { fontSize: 13, color: "var(--dsw-alias-label-primary)" } }, task.title),
6092
- (0, import_react8.createElement)("span", { style: badge }, task.stage),
6093
- (0, import_react8.createElement)("span", { style: badge }, task.branch),
6094
- (0, import_react8.createElement)("span", { className: "te-badge", style: task.risk_level === "high_risk" ? { color: "var(--dsw-alias-state-error-primary)" } : {} }, task.risk_level === "high_risk" ? "\u9AD8\u98CE\u9669" : "\u6807\u51C6"),
6095
- (0, import_react8.createElement)("span", { className: "te-badge" }, task.verification_passed ? "\u9A8C\u8BC1\u901A\u8FC7" : "\u5F85\u9A8C\u8BC1"),
6096
- (0, import_react8.createElement)("span", { className: "te-badge" }, `\u5BA1\u6838\uFF1A${task.review_outcome ?? "pending"}`),
6097
- task.updated_at ? (0, import_react8.createElement)("span", { style: metaLine }, "\u66F4\u65B0\u4E8E " + timeText(task.updated_at)) : null
6160
+ (0, import_react7.createElement)("span", { style: { fontSize: 14, fontWeight: 600, color: "var(--dsw-alias-label-primary)" } }, task.task_id),
6161
+ (0, import_react7.createElement)("span", { style: { fontSize: 13, color: "var(--dsw-alias-label-primary)" } }, task.title),
6162
+ (0, import_react7.createElement)("span", { style: badge }, task.stage),
6163
+ (0, import_react7.createElement)("span", { style: badge }, task.branch),
6164
+ (0, import_react7.createElement)("span", { className: "te-badge", style: task.risk_level === "high_risk" ? { color: "var(--dsw-alias-state-error-primary)" } : {} }, task.risk_level === "high_risk" ? "\u9AD8\u98CE\u9669" : "\u6807\u51C6"),
6165
+ (0, import_react7.createElement)("span", { className: "te-badge" }, task.verification_passed ? "\u9A8C\u8BC1\u901A\u8FC7" : "\u5F85\u9A8C\u8BC1"),
6166
+ (0, import_react7.createElement)("span", { className: "te-badge" }, `\u5BA1\u6838\uFF1A${task.review_outcome ?? "pending"}`),
6167
+ task.updated_at ? (0, import_react7.createElement)("span", { style: metaLine }, "\u66F4\u65B0\u4E8E " + timeText(task.updated_at)) : null
6098
6168
  ),
6099
- (0, import_react8.createElement)(
6169
+ (0, import_react7.createElement)(
6100
6170
  "div",
6101
6171
  { style: { display: "flex", flexDirection: "column" } },
6102
- ...task.items.map((item) => (0, import_react8.createElement)(
6172
+ ...task.items.map((item) => (0, import_react7.createElement)(
6103
6173
  "div",
6104
6174
  { key: item.id, style: itemRow },
6105
- (0, import_react8.createElement)(
6175
+ (0, import_react7.createElement)(
6106
6176
  "div",
6107
6177
  { style: headerRow },
6108
6178
  itemStatusDot(item.status),
6109
- (0, import_react8.createElement)("span", { style: { fontSize: 13, color: "var(--dsw-alias-label-primary)" } }, item.id),
6110
- (0, import_react8.createElement)("span", { style: { fontSize: 12, color: "var(--dsw-alias-label-secondary)" } }, item.title)
6179
+ (0, import_react7.createElement)("span", { style: { fontSize: 13, color: "var(--dsw-alias-label-primary)" } }, item.id),
6180
+ (0, import_react7.createElement)("span", { style: { fontSize: 12, color: "var(--dsw-alias-label-secondary)" } }, item.title)
6111
6181
  ),
6112
6182
  itemAudit(item)
6113
6183
  ))
@@ -6181,29 +6251,29 @@ var TABS = [
6181
6251
  function Workbench({ useStore, actions, useWorkspaces, remote }) {
6182
6252
  const open = useStore((s) => s.open);
6183
6253
  const workspaces = useWorkspaces((s) => s.items);
6184
- const [tab, setTab] = (0, import_react9.useState)("init");
6185
- const [workspace, setWorkspace] = (0, import_react9.useState)("");
6254
+ const [tab, setTab] = (0, import_react8.useState)("init");
6255
+ const [workspace, setWorkspace] = (0, import_react8.useState)("");
6186
6256
  if (!open) return null;
6187
6257
  const current = workspaces.some((w) => w.path === workspace) ? workspace : workspaces[0]?.path ?? "";
6188
- return (0, import_react9.createElement)(
6258
+ return (0, import_react8.createElement)(
6189
6259
  "div",
6190
6260
  { style: overlay, className: "te-workbench" },
6191
- (0, import_react9.createElement)("style", null, workbenchTheme),
6192
- (0, import_react9.createElement)(
6261
+ (0, import_react8.createElement)("style", null, workbenchTheme),
6262
+ (0, import_react8.createElement)(
6193
6263
  "div",
6194
6264
  { style: header },
6195
- (0, import_react9.createElement)(
6265
+ (0, import_react8.createElement)(
6196
6266
  "div",
6197
6267
  { style: headerBrand },
6198
- (0, import_react9.createElement)(import_dsh_client_ui_primitives6.IconSettingsOutline16, { size: 18 }),
6199
- (0, import_react9.createElement)(
6268
+ (0, import_react8.createElement)(import_dsh_client_ui_primitives6.IconSettingsOutline16, { size: 18 }),
6269
+ (0, import_react8.createElement)(
6200
6270
  "div",
6201
6271
  { style: headerText },
6202
- (0, import_react9.createElement)("span", { style: headerTitle }, "\u5DE5\u7A0B\u6D41\u7A0B"),
6203
- (0, import_react9.createElement)("p", { style: headerSub }, "\u5DE5\u7A0B\u5316\u4EA4\u4ED8\u5DE5\u4F5C\u53F0 \xB7 \u9700\u6C42\u8BC4\u5BA1 \u2192 \u8BBE\u8BA1 \u2192 \u5F00\u53D1 \u2192 \u4EA4\u4ED8 \u2192 \u4EE3\u7801\u5BA1\u6838")
6272
+ (0, import_react8.createElement)("span", { style: headerTitle }, "\u5DE5\u7A0B\u6D41\u7A0B"),
6273
+ (0, import_react8.createElement)("p", { style: headerSub }, "\u5DE5\u7A0B\u5316\u4EA4\u4ED8\u5DE5\u4F5C\u53F0 \xB7 \u9700\u6C42\u8BC4\u5BA1 \u2192 \u8BBE\u8BA1 \u2192 \u5F00\u53D1 \u2192 \u4EA4\u4ED8 \u2192 \u4EE3\u7801\u5BA1\u6838")
6204
6274
  )
6205
6275
  ),
6206
- (0, import_react9.createElement)(
6276
+ (0, import_react8.createElement)(
6207
6277
  "button",
6208
6278
  {
6209
6279
  type: "button",
@@ -6219,44 +6289,44 @@ function Workbench({ useStore, actions, useWorkspaces, remote }) {
6219
6289
  event.currentTarget.style.background = "transparent";
6220
6290
  }
6221
6291
  },
6222
- (0, import_react9.createElement)(import_dsh_client_ui_primitives6.IconCloseOutline16, { size: 16 })
6292
+ (0, import_react8.createElement)(import_dsh_client_ui_primitives6.IconCloseOutline16, { size: 16 })
6223
6293
  )
6224
6294
  ),
6225
- (0, import_react9.createElement)(
6295
+ (0, import_react8.createElement)(
6226
6296
  "div",
6227
6297
  { style: tabbar },
6228
- ...TABS.map((t) => (0, import_react9.createElement)(import_dsh_client_ui_primitives6.Pill, { key: t.id, active: tab === t.id, onClick: () => {
6298
+ ...TABS.map((t) => (0, import_react8.createElement)(import_dsh_client_ui_primitives6.Pill, { key: t.id, active: tab === t.id, onClick: () => {
6229
6299
  setTab(t.id);
6230
6300
  } }, t.label)),
6231
- workspaces.length > 0 ? (0, import_react9.createElement)("select", {
6301
+ workspaces.length > 0 ? (0, import_react8.createElement)("select", {
6232
6302
  style: selectStyle,
6233
6303
  "aria-label": "\u5F53\u524D\u5DE5\u4F5C\u533A",
6234
6304
  value: current,
6235
6305
  onChange: (ev) => {
6236
6306
  setWorkspace(ev.target.value);
6237
6307
  }
6238
- }, ...workspaces.map((w) => (0, import_react9.createElement)("option", { key: w.path, value: w.path }, w.title || w.path))) : null
6308
+ }, ...workspaces.map((w) => (0, import_react8.createElement)("option", { key: w.path, value: w.path }, w.title || w.path))) : null
6239
6309
  ),
6240
- (0, import_react9.createElement)(
6310
+ (0, import_react8.createElement)(
6241
6311
  "div",
6242
6312
  { style: body },
6243
- (0, import_react9.createElement)(
6313
+ (0, import_react8.createElement)(
6244
6314
  "div",
6245
6315
  { className: "te-content", key: current },
6246
- (0, import_react9.createElement)("p", { style: { ...styles.hint, marginBottom: 20 }, title: current }, "\u5DE5\u4F5C\u533A \xB7 " + current),
6247
- current === "" ? (0, import_react9.createElement)("p", { style: styles.muted }, "\u5F53\u524D\u6CA1\u6709\u5DE5\u4F5C\u533A\uFF1A\u8BF7\u5148\u5728\u4FA7\u680F\u521B\u5EFA\u4E00\u4E2A\u5DE5\u4F5C\u533A\uFF0C\u518D\u56DE\u6765\u914D\u7F6E\u6D41\u7A0B\u3002") : tab === "init" ? (0, import_react9.createElement)(InitPanel, { workspace: current, remote }) : tab === "flow" ? (0, import_react9.createElement)(TaskEngineSection, { workspace: current, remote }) : tab === "tasks" ? (0, import_react9.createElement)(TaskLedger, { workspace: current, remote }) : tab === "skills" ? (0, import_react9.createElement)(SkillManager, { workspace: current, remote }) : (0, import_react9.createElement)(RuleManager, { workspace: current, remote })
6316
+ (0, import_react8.createElement)("p", { style: { ...styles.hint, marginBottom: 20 }, title: current }, "\u5DE5\u4F5C\u533A \xB7 " + current),
6317
+ current === "" ? (0, import_react8.createElement)("p", { style: styles.muted }, "\u5F53\u524D\u6CA1\u6709\u5DE5\u4F5C\u533A\uFF1A\u8BF7\u5148\u5728\u4FA7\u680F\u521B\u5EFA\u4E00\u4E2A\u5DE5\u4F5C\u533A\uFF0C\u518D\u56DE\u6765\u914D\u7F6E\u6D41\u7A0B\u3002") : tab === "init" ? (0, import_react8.createElement)(InitPanel, { workspace: current, remote }) : tab === "flow" ? (0, import_react8.createElement)(TaskEngineSection, { workspace: current, remote }) : tab === "tasks" ? (0, import_react8.createElement)(TaskLedger, { workspace: current, remote }) : tab === "skills" ? (0, import_react8.createElement)(SkillManager, { workspace: current, remote }) : (0, import_react8.createElement)(RuleManager, { workspace: current, remote })
6248
6318
  )
6249
6319
  )
6250
6320
  );
6251
6321
  }
6252
6322
 
6253
6323
  // src/client/TriggerButton.tsx
6254
- var import_react10 = require("react");
6324
+ var import_react9 = require("react");
6255
6325
  var import_dsh_client_ui_primitives7 = require("@deepseek-ai/dsh-client-ui-primitives");
6256
6326
  var hover = "var(--dsw-alias-bg-layer-2)";
6257
6327
  var label = "var(--dsw-alias-label-primary)";
6258
6328
  function TriggerButton({ wide, actions }) {
6259
- return (0, import_react10.createElement)(
6329
+ return (0, import_react9.createElement)(
6260
6330
  "button",
6261
6331
  {
6262
6332
  type: "button",
@@ -6296,8 +6366,8 @@ function TriggerButton({ wide, actions }) {
6296
6366
  transition: "background 120ms ease"
6297
6367
  }
6298
6368
  },
6299
- (0, import_react10.createElement)(import_dsh_client_ui_primitives7.IconSettingsOutline16, { size: wide ? 16 : 18 }),
6300
- wide ? (0, import_react10.createElement)("span", { style: { fontSize: 14, lineHeight: "22px" } }, "\u5DE5\u7A0B\u6D41\u7A0B") : null
6369
+ (0, import_react9.createElement)(import_dsh_client_ui_primitives7.IconSettingsOutline16, { size: wide ? 16 : 18 }),
6370
+ wide ? (0, import_react9.createElement)("span", { style: { fontSize: 14, lineHeight: "22px" } }, "\u5DE5\u7A0B\u6D41\u7A0B") : null
6301
6371
  );
6302
6372
  }
6303
6373