@godv61/dsh-task-engine 0.23.9 → 0.25.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
@@ -4557,6 +4557,14 @@ var workbenchTheme = `
4557
4557
  .te-binding-tools .te-input { flex:1; width:100%; min-width:120px; padding:8px 10px; font-size:13px; }
4558
4558
  .te-binding-filter { display:flex; align-items:center; gap:5px; font-size:12px; white-space:nowrap; cursor:pointer; }
4559
4559
  .te-binding-list { max-height:280px; overflow-y:auto; overscroll-behavior:contain; display:flex; flex-direction:column; gap:4px; scrollbar-gutter:stable; }
4560
+ /* Search + filter row. The catalog grows with every install, so finding one skill
4561
+ has to be a lookup rather than a scroll. */
4562
+ .te-binding-controls { display:flex; gap:8px; align-items:center; flex-wrap:wrap; margin:0 0 6px; }
4563
+ .te-binding-search { flex:1; min-width:120px; padding:6px 9px; font-size:12px; color:var(--dsw-alias-label-primary); background:var(--dsw-alias-bg-layer-1); border:1px solid var(--dsw-alias-border-l2); border-radius:7px; }
4564
+ .te-binding-search:focus-visible { outline:2px solid var(--dsw-alias-state-business-primary); outline-offset:1px; }
4565
+ /* Only the open skill's rules render, and inside a bounded region: expanding a
4566
+ second skill must not push the first off screen or grow the page without limit. */
4567
+ .te-rule-list { display:flex; flex-direction:column; gap:4px; margin-top:6px; padding:8px; max-height:240px; overflow-y:auto; overscroll-behavior:contain; border:1px solid var(--dsw-alias-border-l2); border-radius:8px; background:var(--dsw-alias-bg-layer-1); scrollbar-gutter:stable; }
4560
4568
  .te-binding-option { display:flex; gap:9px; align-items:flex-start; padding:9px; border:1px solid transparent; border-radius:8px; cursor:pointer; }
4561
4569
  .te-binding-option:hover { background:var(--dsw-alias-bg-layer-2); }
4562
4570
  .te-binding-option.is-selected { background:var(--dsw-alias-bg-layer-2); border-color:var(--dsw-alias-border-l2); }
@@ -4695,6 +4703,10 @@ var styles = {
4695
4703
  },
4696
4704
  // ── flow preset picker ────────────────────────────────────────────────────
4697
4705
  flowGrid: { display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(230px, 1fr))", gap: 10 },
4706
+ // The adoption row is deliberately separated from the flow picker: choosing a
4707
+ // skeleton and adopting a recommended setup are different decisions, and the
4708
+ // button is the only thing that writes method into the user's config.
4709
+ adoptRow: { display: "flex", alignItems: "center", gap: 10, flexWrap: "wrap", marginBottom: 4 },
4698
4710
  flowOption: {
4699
4711
  display: "flex",
4700
4712
  flexDirection: "column",
@@ -4736,10 +4748,18 @@ var styles = {
4736
4748
  };
4737
4749
 
4738
4750
  // src/client/TaskEngineSection.tsx
4739
- var import_react2 = require("react");
4751
+ var import_react = require("react");
4740
4752
  var import_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
4741
4753
 
4742
4754
  // src/engine.ts
4755
+ function formatResourceRef(ref) {
4756
+ return `${ref.source}:${ref.name}`;
4757
+ }
4758
+ function parseResourceRef(text2) {
4759
+ const match = /^(bundled|project|user):(.+)$/u.exec(text2);
4760
+ if (match === null) return void 0;
4761
+ return { source: match[1], name: match[2] };
4762
+ }
4743
4763
  var GUARD_NAMES = [
4744
4764
  "requirement_confirmation",
4745
4765
  "solution_confirmation",
@@ -4800,16 +4820,27 @@ function validateWorkflow(config) {
4800
4820
  if (!config.stages.includes(stage)) {
4801
4821
  problems.push(`stage_bindings: stage "${stage}" is not a stage`);
4802
4822
  }
4803
- for (const skill of binding.skills ?? []) {
4804
- if (typeof skill !== "string" || skill.trim() === "") {
4805
- problems.push(`stage_bindings "${stage}": empty skill name`);
4823
+ for (const [index, entry] of (binding.skills ?? []).entries()) {
4824
+ if (typeof entry?.skill?.name !== "string" || entry.skill.name.trim() === "") {
4825
+ problems.push(`stage_bindings "${stage}": skill ${index + 1} has no name`);
4826
+ continue;
4806
4827
  }
4807
- }
4808
- for (const rule of binding.rules ?? []) {
4809
- if (typeof rule !== "string" || rule.trim() === "") {
4810
- problems.push(`stage_bindings "${stage}": empty rule name`);
4828
+ if (!["bundled", "project", "user"].includes(entry.skill.source)) {
4829
+ problems.push(`stage_bindings "${stage}": skill "${entry.skill.name}" has unknown source "${String(entry.skill.source)}"`);
4830
+ }
4831
+ for (const rule of entry.rules ?? []) {
4832
+ if (typeof rule?.name !== "string" || rule.name.trim() === "") {
4833
+ problems.push(`stage_bindings "${stage}": skill "${entry.skill.name}" has a rule with no name`);
4834
+ continue;
4835
+ }
4836
+ if (!["bundled", "project", "user"].includes(rule.source)) {
4837
+ problems.push(`stage_bindings "${stage}": skill "${entry.skill.name}" rule "${rule.name}" has unknown source "${String(rule.source)}"`);
4838
+ }
4811
4839
  }
4812
4840
  }
4841
+ if ((binding.legacy_rules ?? []).length > 0) {
4842
+ 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`);
4843
+ }
4813
4844
  }
4814
4845
  if (!["task", "item", "manual"].includes(config.commit.policy)) {
4815
4846
  problems.push(`commit.policy "${config.commit.policy}" is not task|item|manual`);
@@ -4826,14 +4857,21 @@ function validateWorkflow(config) {
4826
4857
  problems.push("commit.message_pattern is not a valid regular expression");
4827
4858
  }
4828
4859
  }
4860
+ if (config.review_depth !== void 0 && config.review_depth !== "two-stage" && config.review_depth !== "single") {
4861
+ problems.push(`review_depth "${String(config.review_depth)}" is not one of: two-stage, single`);
4862
+ }
4829
4863
  return problems;
4830
4864
  }
4831
4865
 
4832
4866
  // src/workflows.ts
4867
+ function bundled(skill, ...rules) {
4868
+ const ref = (name) => ({ source: "bundled", name });
4869
+ return { skill: ref(skill), rules: rules.map(ref) };
4870
+ }
4833
4871
  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" }
4872
+ { 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" },
4873
+ { 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" },
4874
+ { 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
4875
  ];
4838
4876
  var STANDARD = {
4839
4877
  stages: ["\u9700\u6C42\u8BC4\u5BA1", "\u8BBE\u8BA1", "\u5F00\u53D1", "\u4EA4\u4ED8", "\u4EE3\u7801\u5BA1\u6838", "\u5B8C\u6210"],
@@ -4845,25 +4883,34 @@ var STANDARD = {
4845
4883
  { from: "\u4EA4\u4ED8", to: "\u4EE3\u7801\u5BA1\u6838", requires: ["verified"] },
4846
4884
  { from: "\u4EE3\u7801\u5BA1\u6838", to: "\u5B8C\u6210", requires: ["review_passed", "artifacts_present"] }
4847
4885
  ],
4886
+ // No artifacts, no commit policy, no skills: the skeleton carries none of them.
4887
+ artifacts: [],
4888
+ commit: { policy: "task", message_pattern: "", message_hint: "\u65E0\u683C\u5F0F\u8981\u6C42", checkpoints: ["\u4EE3\u7801\u5BA1\u6838"], file_scope: true },
4889
+ high_risk_requires_verification: true
4890
+ };
4891
+ var STANDARD_RECOMMENDATION = {
4892
+ commit: {
4893
+ // Only the TEXT conventions. Policy, checkpoints and scope stay on the
4894
+ // skeleton: they decide when a gate fires, not how a message reads.
4895
+ message_pattern: "^\u3010(\\S+)\u3011\u3010(?:TASK|T\\d+)\u3011.+",
4896
+ message_hint: "\u3010<task_id>\u3011\u3010TASK/T1\u3011\u8BF4\u660E \u2014\u2014 \u7B2C\u4E00\u6BB5\u586B\u672C\u4EFB\u52A1 id\uFF08\u5982 GREET-001\uFF09\uFF0C\u5199\u7ED3\u679C\u4E0D\u5199\u7A7A\u6CDB\u52A8\u4F5C"
4897
+ },
4848
4898
  artifacts: [
4849
4899
  { stage: "\u9700\u6C42\u8BC4\u5BA1", id: "requirement", name: "\u9700\u6C42\u8BF4\u660E", fields: ["scope", "acceptance_criteria"] },
4850
4900
  { stage: "\u8BBE\u8BA1", id: "design", name: "\u8BBE\u8BA1\u6587\u6863", fields: ["approach", "risks", "impact"] },
4851
4901
  { stage: "\u4EE3\u7801\u5BA1\u6838", id: "review", name: "\u8BC4\u5BA1\u8BB0\u5F55", fields: ["conclusion", "issues"] }
4852
4902
  ],
4853
- commit: {
4854
- policy: "task",
4855
- message_pattern: "^\u3010(\\S+)\u3011\u3010(?:TASK|T\\d+)\u3011.+",
4856
- message_hint: "\u3010<task_id>\u3011\u3010TASK/T1\u3011\u8BF4\u660E \u2014\u2014 \u7B2C\u4E00\u6BB5\u586B\u672C\u4EFB\u52A1 id\uFF08\u5982 GREET-001\uFF09\uFF0C\u5199\u7ED3\u679C\u4E0D\u5199\u7A7A\u6CDB\u52A8\u4F5C",
4857
- checkpoints: ["\u4EE3\u7801\u5BA1\u6838"],
4858
- file_scope: true
4859
- },
4860
- high_risk_requires_verification: true,
4861
4903
  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"] }
4904
+ "\u9700\u6C42\u8BC4\u5BA1": { skills: [bundled("requirement-analysis", "security-redlines")] },
4905
+ "\u8BBE\u8BA1": { skills: [bundled("solution-design")] },
4906
+ "\u5F00\u53D1": { skills: [bundled("code-implement", "coding-conventions", "security-redlines")] },
4907
+ "\u4EA4\u4ED8": { skills: [bundled("code-verify")] },
4908
+ "\u4EE3\u7801\u5BA1\u6838": {
4909
+ skills: [
4910
+ bundled("code-review", "coding-conventions", "security-redlines"),
4911
+ bundled("code-commit", "commit-conventions")
4912
+ ]
4913
+ }
4867
4914
  }
4868
4915
  };
4869
4916
  var AGILE = {
@@ -4872,24 +4919,43 @@ var AGILE = {
4872
4919
  transitions: [
4873
4920
  { from: "\u9700\u6C42", to: "\u5F00\u53D1", requires: ["requirement_confirmation"] },
4874
4921
  { from: "\u5F00\u53D1", to: "\u4EA4\u4ED8", requires: ["todos_done"] },
4922
+ // Entering 审查 is unconditional. A review guard on this edge would be
4923
+ // circular — it would demand the verdict BEFORE the stage that produces it —
4924
+ // and it would also block the commit at 交付, since a commit requires its
4925
+ // stage's outgoing guards. What 审查 requires is declared as completion_guards
4926
+ // instead, because a terminal stage has no outgoing edge to carry it.
4875
4927
  { from: "\u4EA4\u4ED8", to: "\u5BA1\u67E5", requires: [] }
4876
4928
  ],
4877
- artifacts: [
4878
- { stage: "\u9700\u6C42", id: "requirement", name: "\u9700\u6C42\u8BF4\u660E", fields: ["scope"] }
4879
- ],
4929
+ artifacts: [],
4930
+ commit: { policy: "item", message_pattern: "", message_hint: "\u65E0\u683C\u5F0F\u8981\u6C42", checkpoints: ["\u4EA4\u4ED8"], file_scope: true },
4931
+ high_risk_requires_verification: false,
4932
+ // 审查 is terminal and IS the review, so there is no outgoing edge to carry
4933
+ // the guard. Declaring it here is what makes a blocked review prevent
4934
+ // completion; without it the stage could be reached and finished with the
4935
+ // review failing, which is what the assessment found.
4936
+ completion_guards: ["review_passed"]
4937
+ };
4938
+ var AGILE_RECOMMENDATION = {
4880
4939
  commit: {
4881
- 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",
4884
- checkpoints: ["\u4EA4\u4ED8"],
4885
- file_scope: true
4940
+ // `item` policy emits two label shapes: `T<n>` mid-flow and `TASK` at the
4941
+ // closing checkpoint. The pattern accepts BOTH, so the label the engine hands
4942
+ // the model always satisfies the rule that validates it.
4943
+ message_pattern: "^\u3010(\\S+)\u3011\u3010(?:TASK|T\\d+)\u3011.+",
4944
+ 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"
4886
4945
  },
4887
- high_risk_requires_verification: false,
4946
+ artifacts: [
4947
+ { stage: "\u9700\u6C42", id: "requirement", name: "\u9700\u6C42\u8BF4\u660E", fields: ["scope"] },
4948
+ // The 审查 stage binds code-review, whose instructions write this artifact with
4949
+ // `record artifact=review`. Declaring it keeps that binding executable: the
4950
+ // engine refuses an undeclared artifact, so a bound skill pointing at one would
4951
+ // be a contract the recommendation made impossible to satisfy.
4952
+ { stage: "\u5BA1\u67E5", id: "review", name: "\u8BC4\u5BA1\u8BB0\u5F55", fields: ["conclusion", "issues"] }
4953
+ ],
4888
4954
  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"] }
4955
+ "\u9700\u6C42": { skills: [bundled("requirement-analysis", "security-redlines")] },
4956
+ "\u5F00\u53D1": { skills: [bundled("code-implement", "coding-conventions", "security-redlines")] },
4957
+ "\u4EA4\u4ED8": { skills: [bundled("code-verify"), bundled("code-commit", "commit-conventions")] },
4958
+ "\u5BA1\u67E5": { skills: [bundled("code-review", "coding-conventions", "security-redlines")] }
4893
4959
  }
4894
4960
  };
4895
4961
  var MINIMAL = {
@@ -4899,17 +4965,17 @@ var MINIMAL = {
4899
4965
  { from: "\u5F00\u53D1", to: "\u4EA4\u4ED8", requires: ["todos_done"] }
4900
4966
  ],
4901
4967
  artifacts: [],
4902
- commit: {
4903
- policy: "task",
4904
- message_pattern: "",
4905
- message_hint: "\u65E0\u683C\u5F0F\u8981\u6C42",
4906
- checkpoints: ["\u4EA4\u4ED8"],
4907
- file_scope: false
4908
- },
4909
- high_risk_requires_verification: false,
4968
+ commit: { policy: "task", message_pattern: "", message_hint: "\u65E0\u683C\u5F0F\u8981\u6C42", checkpoints: ["\u4EA4\u4ED8"], file_scope: false },
4969
+ high_risk_requires_verification: false
4970
+ };
4971
+ var MINIMAL_RECOMMENDATION = {
4972
+ // A fast-change flow checks each change once, not twice under two headings a
4973
+ // short change rarely distinguishes. The item still has to be reviewed — what
4974
+ // drops is the duplicated verdict, which is where the weight actually was.
4975
+ review_depth: "single",
4910
4976
  stage_bindings: {
4911
- "\u5F00\u53D1": { skills: ["code-implement"] },
4912
- "\u4EA4\u4ED8": { skills: ["code-commit"], rules: ["commit-conventions"] }
4977
+ "\u5F00\u53D1": { skills: [bundled("code-implement", "coding-conventions", "security-redlines")] },
4978
+ "\u4EA4\u4ED8": { skills: [bundled("code-commit", "commit-conventions")] }
4913
4979
  }
4914
4980
  };
4915
4981
  function deriveCapabilities(config) {
@@ -4921,150 +4987,117 @@ function deriveCapabilities(config) {
4921
4987
  if (config.commit.file_scope) caps.push("file_scope");
4922
4988
  return caps;
4923
4989
  }
4924
- function preset(id, version, label2, description, config) {
4925
- return { id, version, label: label2, description, capabilities: deriveCapabilities(config), config };
4990
+ function preset(id, version, label2, description, config, recommendation) {
4991
+ return {
4992
+ id,
4993
+ version,
4994
+ label: label2,
4995
+ description,
4996
+ capabilities: deriveCapabilities(config),
4997
+ config,
4998
+ // exactOptionalPropertyTypes: omit rather than assign undefined.
4999
+ ...recommendation !== void 0 ? { recommendation } : {}
5000
+ };
4926
5001
  }
4927
5002
  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)
5003
+ standard: preset("standard", 3, "\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, STANDARD_RECOMMENDATION),
5004
+ // Version 4 for agile: 交付 → 审查 now requires review_passed, where it previously
5005
+ // required nothing. That is a gate-semantics change, so a task created before it
5006
+ // keeps its frozen version 3 config and behaves exactly as it did.
5007
+ //
5008
+ // Version 3 across all three: the preset is now a bare skeleton and its former
5009
+ // built-in bindings, commit rule and artifacts are a separate recommendation a
5010
+ // user adopts explicitly. Tasks created before this keep their frozen config and
5011
+ // are unaffected; a project's existing config is likewise left exactly as it is.
5012
+ agile: preset("agile", 4, "\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, AGILE_RECOMMENDATION),
5013
+ minimal: preset("minimal", 3, "\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, MINIMAL_RECOMMENDATION)
4931
5014
  };
4932
5015
  function dedupe(names) {
4933
5016
  return [...new Set(names)];
4934
5017
  }
4935
- function mergeBindings(base, override) {
4936
- if (override === void 0) return base;
4937
- let changed = false;
4938
- const merged = { ...base.stage_bindings };
4939
- for (const [stage, addition] of Object.entries(override)) {
4940
- const existing = merged[stage];
4941
- const skills = dedupe([...existing?.skills ?? [], ...addition.skills ?? []]);
4942
- const rules = dedupe([...existing?.rules ?? [], ...addition.rules ?? []]);
4943
- const binding = {};
4944
- if (skills.length > 0) binding.skills = skills;
4945
- if (rules.length > 0) binding.rules = rules;
4946
- merged[stage] = binding;
4947
- changed = true;
4948
- }
4949
- if (!changed) return base;
4950
- return { ...base, stage_bindings: merged };
5018
+ function applyProjectConfig(base, project) {
5019
+ if (project === void 0) return base;
5020
+ const next = { ...base };
5021
+ if (project.stage_bindings !== void 0) {
5022
+ const bindings = {};
5023
+ for (const [stage, binding] of Object.entries(project.stage_bindings)) {
5024
+ const entry = {};
5025
+ if ((binding.skills ?? []).length > 0) entry.skills = [...binding.skills];
5026
+ const legacy = dedupe(binding.legacy_rules ?? []);
5027
+ if (legacy.length > 0) entry.legacy_rules = legacy;
5028
+ bindings[stage] = entry;
5029
+ }
5030
+ next.stage_bindings = bindings;
5031
+ }
5032
+ if (project.commit !== void 0) next.commit = project.commit;
5033
+ if (project.artifacts !== void 0) next.artifacts = project.artifacts;
5034
+ if (project.review_depth !== void 0) next.review_depth = project.review_depth;
5035
+ if (project.commit_required !== void 0) next.commit_required = project.commit_required;
5036
+ return next;
5037
+ }
5038
+ function adoptRecommendation(presetId, current) {
5039
+ const preset2 = FLOW_PRESETS[presetId];
5040
+ if (preset2 === void 0) return void 0;
5041
+ const rec = preset2.recommendation;
5042
+ if (rec === void 0) return { flow: presetId, ...current };
5043
+ const commit = {
5044
+ ...preset2.config.commit,
5045
+ ...rec.commit ?? {},
5046
+ ...current?.commit ?? {}
5047
+ };
5048
+ const config = {
5049
+ flow: presetId,
5050
+ stage_bindings: current?.stage_bindings ?? rec.stage_bindings ?? {},
5051
+ commit,
5052
+ artifacts: current?.artifacts ?? rec.artifacts ?? preset2.config.artifacts,
5053
+ ...current?.review_depth !== void 0 ? { review_depth: current.review_depth } : rec.review_depth !== void 0 ? { review_depth: rec.review_depth } : {},
5054
+ ...current?.commit_required !== void 0 ? { commit_required: current.commit_required } : {}
5055
+ };
5056
+ return config;
4951
5057
  }
4952
- function resolveFlow(flow, override) {
5058
+ function resolveFlow(flow, project) {
4953
5059
  const preset2 = FLOW_PRESETS[flow];
4954
5060
  if (preset2 === void 0) {
4955
5061
  return { ok: false, code: "UNKNOWN_FLOW", flow, knownFlows: Object.keys(FLOW_PRESETS) };
4956
5062
  }
4957
- return { ok: true, config: mergeBindings(preset2.config, override?.stage_bindings), preset: preset2 };
5063
+ const { flow: _ignored, ...rest } = project ?? { flow };
5064
+ return { ok: true, config: applyProjectConfig(preset2.config, { flow, ...rest }), preset: preset2 };
4958
5065
  }
4959
5066
 
4960
5067
  // 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
5068
  function describeError(error) {
4980
5069
  if (error instanceof Error) return error.message;
4981
5070
  if (typeof error === "string") return error;
4982
5071
  return "\u672A\u77E5\u9519\u8BEF";
4983
5072
  }
4984
5073
 
4985
- // src/client/BindingPicker.tsx
4986
- var import_react = require("react");
5074
+ // src/client/TaskEngineSection.tsx
4987
5075
  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
- ] });
5076
+ function refFromText(text2) {
5077
+ return parseResourceRef(text2) ?? { source: "bundled", name: text2 };
5046
5078
  }
5047
-
5048
- // src/client/TaskEngineSection.tsx
5049
- var import_jsx_runtime2 = require("react/jsx-runtime");
5050
5079
  function resolvedConfig(flow, stageBindings) {
5051
- const resolved = resolveFlow(flow, { stage_bindings: stageBindings });
5080
+ const resolved = resolveFlow(flow, { flow, stage_bindings: stageBindings });
5052
5081
  return resolved.ok ? resolved.config : FLOW_PRESETS.standard.config;
5053
5082
  }
5054
5083
  function TaskEngineSection(props) {
5055
5084
  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)(() => {
5085
+ const [flow, setFlow] = (0, import_react.useState)("standard");
5086
+ const [stageBindings, setStageBindings] = (0, import_react.useState)({});
5087
+ const [commitRule, setCommitRule] = (0, import_react.useState)(void 0);
5088
+ const [artifacts, setArtifacts] = (0, import_react.useState)(void 0);
5089
+ const [reviewDepth, setReviewDepth] = (0, import_react.useState)(void 0);
5090
+ const [source, setSource] = (0, import_react.useState)("default");
5091
+ const [savedAt, setSavedAt] = (0, import_react.useState)("");
5092
+ const [dirty, setDirty] = (0, import_react.useState)(false);
5093
+ const [loadError, setLoadError] = (0, import_react.useState)("");
5094
+ const [saving, setSaving] = (0, import_react.useState)(false);
5095
+ const [loading, setLoading] = (0, import_react.useState)(true);
5096
+ const [loadAttempt, setLoadAttempt] = (0, import_react.useState)(0);
5097
+ const [configProblems, setConfigProblems] = (0, import_react.useState)([]);
5098
+ const [skills, setSkills] = (0, import_react.useState)([]);
5099
+ const [rules, setRules] = (0, import_react.useState)([]);
5100
+ (0, import_react.useEffect)(() => {
5068
5101
  if (workspace === "") return;
5069
5102
  let alive = true;
5070
5103
  setLoadError("");
@@ -5075,6 +5108,9 @@ function TaskEngineSection(props) {
5075
5108
  if (result.ok) {
5076
5109
  setFlow(result.value.flow);
5077
5110
  setStageBindings(result.value.config.stage_bindings ?? {});
5111
+ setCommitRule(result.value.config.commit);
5112
+ setArtifacts(result.value.config.artifacts);
5113
+ setReviewDepth(result.value.config.review_depth);
5078
5114
  setSource(result.value.source);
5079
5115
  setConfigProblems(result.value.problems);
5080
5116
  setSavedAt("");
@@ -5091,7 +5127,7 @@ function TaskEngineSection(props) {
5091
5127
  alive = false;
5092
5128
  };
5093
5129
  }, [remote, workspace, loadAttempt]);
5094
- const refreshCatalogs = (0, import_react2.useCallback)(() => {
5130
+ const refreshCatalogs = (0, import_react.useCallback)(() => {
5095
5131
  if (workspace === "") return;
5096
5132
  void remote.listSkills(workspace).then((result) => {
5097
5133
  if (result.ok) setSkills(result.value.skills);
@@ -5102,51 +5138,73 @@ function TaskEngineSection(props) {
5102
5138
  }, () => {
5103
5139
  });
5104
5140
  }, [remote, workspace]);
5105
- (0, import_react2.useEffect)(() => {
5141
+ (0, import_react.useEffect)(() => {
5106
5142
  refreshCatalogs();
5107
5143
  }, [refreshCatalogs]);
5108
- const stages = (0, import_react2.useMemo)(() => (FLOW_PRESETS[flow] ?? FLOW_PRESETS.standard).config.stages, [flow]);
5109
- const problems = (0, import_react2.useMemo)(
5144
+ const stages = (0, import_react.useMemo)(() => (FLOW_PRESETS[flow] ?? FLOW_PRESETS.standard).config.stages, [flow]);
5145
+ const problems = (0, import_react.useMemo)(
5110
5146
  () => validateWorkflow(resolvedConfig(flow, stageBindings)),
5111
5147
  [flow, stageBindings]
5112
5148
  );
5113
5149
  const selectFlow = (id) => {
5150
+ if (id === flow) return;
5151
+ 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
5152
  setFlow(id);
5115
- setStageBindings({ ...FLOW_PRESETS[id]?.config.stage_bindings ?? {} });
5153
+ setDirty(true);
5154
+ setSavedAt("");
5155
+ };
5156
+ const adopt = () => {
5157
+ const adopted = adoptRecommendation(flow);
5158
+ if (adopted === void 0) return;
5159
+ if (dirty && !window.confirm("\u91C7\u7528\u63A8\u8350\u914D\u7F6E\u4F1A\u66FF\u6362\u5F53\u524D\u7684\u6280\u80FD\u4E0E\u89C4\u5219\u8BBE\u7F6E\u3002\u7EE7\u7EED\uFF1F")) return;
5160
+ setStageBindings({ ...adopted.stage_bindings ?? {} });
5161
+ setCommitRule(adopted.commit);
5162
+ setArtifacts(adopted.artifacts);
5163
+ setReviewDepth(adopted.review_depth);
5164
+ setDirty(true);
5165
+ setSavedAt("");
5116
5166
  };
5117
5167
  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" }),
5168
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.wrap, children: [
5169
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { style: styles.title, children: "\u5DE5\u7A0B\u6D41\u7A0B\u914D\u7F6E" }),
5170
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.problems, children: [
5171
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: styles.problemsTitle, children: [
5172
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.StateDot, { state: "error" }),
5123
5173
  "\u8BFB\u53D6\u5931\u8D25"
5124
5174
  ] }),
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" })
5175
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.muted, children: loadError }),
5176
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { onClick: () => setLoadAttempt((n) => n + 1), children: "\u91CD\u8BD5" })
5127
5177
  ] })
5128
5178
  ] });
5129
5179
  }
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: [
5180
+ if (loading) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { role: "status", children: "\u6B63\u5728\u8BFB\u53D6\u6D41\u7A0B\u914D\u7F6E\u2026" });
5181
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.wrap, children: [
5182
+ configProblems.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { role: "alert", style: styles.problems, children: [
5133
5183
  "\u539F\u914D\u7F6E\u6709\u95EE\u9898\uFF1A",
5134
5184
  configProblems.join("\uFF1B"),
5135
5185
  "\u3002\u8BF7\u9009\u62E9\u6709\u6548\u9884\u8BBE\u5E76\u4FDD\u5B58\u4FEE\u590D\u3002"
5136
5186
  ] }),
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" })
5187
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.head, children: [
5188
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { style: styles.title, children: "\u5DE5\u7A0B\u6D41\u7A0B\u914D\u7F6E" }),
5189
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.muted, children: "\u6D41\u7A0B\u51B3\u5B9A\u5DE5\u4F5C\u600E\u4E48\u6D41\u8F6C\uFF08\u9636\u6BB5\u4E0E\u95E8\u7981\uFF09\uFF1B\u6280\u80FD\u3001\u89C4\u5219\u3001\u63D0\u4EA4\u683C\u5F0F\u548C\u4EA7\u7269\u5B57\u6BB5\u7531\u4F60\u81EA\u5DF1\u914D\u7F6E\u3002 \u9700\u8981\u4E00\u4EFD\u73B0\u6210\u7684\u8D77\u70B9\u65F6\uFF0C\u53EF\u4EE5\u300C\u91C7\u7528\u63A8\u8350\u914D\u7F6E\u300D\u2014\u2014\u91C7\u7528\u540E\u8FD9\u4E9B\u5C31\u5B8C\u5168\u5C5E\u4E8E\u4F60\uFF0C\u53EF\u968F\u610F\u4FEE\u6539\u6216\u5220\u9664\u3002" })
5140
5190
  ] }),
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) })
5191
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.adoptRow, children: [
5192
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_dsh_client_ui_primitives.Button, { size: "sm", onClick: adopt, children: [
5193
+ "\u91C7\u7528\u300C",
5194
+ FLOW_PRESETS[flow]?.label ?? flow,
5195
+ "\u300D\u7684\u63A8\u8350\u914D\u7F6E"
5196
+ ] }),
5197
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.muted, children: "\u5199\u5165\u63A8\u8350\u6280\u80FD\u3001\u63D0\u4EA4\u4FE1\u606F\u683C\u5F0F\u4E0E\u4EA7\u7269\u5B57\u6BB5\u3002\u4EC5\u5728\u4F60\u70B9\u51FB\u65F6\u53D1\u751F\u4E00\u6B21\uFF1B\u5220\u9664\u540E\u4E0D\u4F1A\u81EA\u52A8\u8865\u56DE\u3002" })
5198
+ ] }),
5199
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.sourceRow, children: [
5200
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.StateDot, { state: source === "project" ? "done" : source === "invalid" ? "warning" : "ongoing" }),
5201
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.sourceText, children: sourceText(source) })
5144
5202
  ] }),
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) => {
5203
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.field, children: [
5204
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { children: "\u6D41\u7A0B\u9884\u8BBE" }),
5205
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.flowGrid, children: FLOW_OPTIONS.map((option) => {
5148
5206
  const active = flow === option.id;
5149
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
5207
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
5150
5208
  "button",
5151
5209
  {
5152
5210
  type: "button",
@@ -5156,49 +5214,56 @@ function TaskEngineSection(props) {
5156
5214
  },
5157
5215
  style: { ...styles.flowOption, ...active ? styles.flowOptionActive : {} },
5158
5216
  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 }),
5217
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: styles.flowOptionTitle, children: [
5218
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.StateDot, { state: active ? "done" : "ongoing", size: 8 }),
5161
5219
  option.label
5162
5220
  ] }),
5163
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { style: styles.flowOptionDesc, children: option.description })
5221
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.flowOptionDesc, children: option.description })
5164
5222
  ]
5165
5223
  },
5166
5224
  option.id
5167
5225
  );
5168
5226
  }) })
5169
5227
  ] }),
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" }),
5228
+ /* @__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) => {
5229
+ setStageBindings(next);
5230
+ setDirty(true);
5231
+ setSavedAt("");
5232
+ }, skills, rules }) }),
5233
+ problems.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.problems, children: [
5234
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: styles.problemsTitle, children: [
5235
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.StateDot, { state: "error" }),
5174
5236
  "\u6709 ",
5175
5237
  problems.length,
5176
5238
  " \u4E2A\u95EE\u9898\uFF08\u4FDD\u5B58\u4F1A\u88AB\u62D2\u7EDD\uFF09"
5177
5239
  ] }),
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" }),
5240
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { style: styles.problemsList, children: problems.map((p) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("li", { children: p }, p)) })
5241
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: styles.okText, children: [
5242
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.StateDot, { state: "done" }),
5181
5243
  source === "project" ? "\u914D\u7F6E\u6709\u6548" : "\u4F7F\u7528\u6D41\u7A0B\u9884\u8BBE\u9ED8\u8BA4\u7ED1\u5B9A\uFF08\u5C1A\u672A\u4FDD\u5B58\uFF09"
5182
5244
  ] }),
5183
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles.actions, children: [
5184
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
5245
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.actions, children: [
5246
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
5185
5247
  import_dsh_client_ui_primitives.Button,
5186
5248
  {
5187
5249
  variant: "primary",
5188
5250
  size: "md",
5189
- icon: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives.IconCheckOutline16, { size: 16 }),
5251
+ icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconCheckOutline16, { size: 16 }),
5190
5252
  disabled: problems.length > 0 || saving,
5191
5253
  onClick: () => {
5192
5254
  setSaving(true);
5193
- void save(remote, flow, stageBindings, workspace, setSavedAt, setSource).then((ok) => {
5194
- if (ok) setConfigProblems([]);
5255
+ void save(remote, { flow, stage_bindings: stageBindings, ...commitRule !== void 0 ? { commit: commitRule } : {}, ...artifacts !== void 0 ? { artifacts } : {}, ...reviewDepth !== void 0 ? { review_depth: reviewDepth } : {} }, workspace, setSavedAt, setSource).then((ok) => {
5256
+ if (ok) {
5257
+ setConfigProblems([]);
5258
+ setDirty(false);
5259
+ }
5195
5260
  }).finally(() => setSaving(false));
5196
5261
  },
5197
- children: saving ? "\u6B63\u5728\u4FDD\u5B58\u2026" : "\u4FDD\u5B58\u5230 .dsh/eng.json"
5262
+ children: saving ? "\u6B63\u5728\u4FDD\u5B58\u2026" : dirty ? "\u4FDD\u5B58\u5230 .dsh/eng.json" : "\u5DF2\u4FDD\u5B58 \xB7 \u65E0\u9700\u4FDD\u5B58"
5198
5263
  }
5199
5264
  ),
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" }),
5265
+ savedAt !== "" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: styles.okText, children: [
5266
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.StateDot, { state: savedAt.startsWith("\u5DF2") ? "done" : "error" }),
5202
5267
  savedAt
5203
5268
  ] }) : null
5204
5269
  ] })
@@ -5215,8 +5280,8 @@ function sourceText(source) {
5215
5280
  }
5216
5281
  }
5217
5282
  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)(
5283
+ const [open, setOpen] = (0, import_react.useState)(true);
5284
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.section, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
5220
5285
  import_dsh_client_ui_primitives.DisclosureRow,
5221
5286
  {
5222
5287
  icon,
@@ -5229,50 +5294,192 @@ function SectionCard({ icon, title, hint, children }) {
5229
5294
  setOpen(!open);
5230
5295
  },
5231
5296
  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,
5297
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.cardBody, children: [
5298
+ hint !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.muted, children: hint }) : null,
5234
5299
  children
5235
5300
  ] })
5236
5301
  }
5237
5302
  ) });
5238
5303
  }
5239
5304
  function BindingEditor({ stages, defaults, stageBindings, setStageBindings, skills, rules }) {
5240
- const [stage, setStage] = (0, import_react2.useState)(stages[0] ?? "");
5305
+ const [stage, setStage] = (0, import_react.useState)(stages[0] ?? "");
5306
+ const [expanded, setExpanded] = (0, import_react.useState)(null);
5307
+ const [query, setQuery] = (0, import_react.useState)("");
5308
+ const [onlySelected, setOnlySelected] = (0, import_react.useState)(false);
5309
+ const [ruleQuery, setRuleQuery] = (0, import_react.useState)("");
5310
+ const [ruleOnlySelected, setRuleOnlySelected] = (0, import_react.useState)(false);
5241
5311
  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 } });
5312
+ const bindingFor = (name) => stageBindings[name] ?? {};
5313
+ const presetSkills = (name) => defaults[name]?.skills ?? [];
5314
+ const isPresetSkill = (name, raw) => presetSkills(name).some((entry) => formatResourceRef(entry.skill) === raw);
5315
+ const visibleSkills = () => {
5316
+ const bound = bindingFor(currentStage).skills ?? [];
5317
+ const boundKeys = new Set(bound.map((entry) => formatResourceRef(entry.skill)));
5318
+ const needle = query.trim().toLowerCase();
5319
+ return skills.filter((entry) => {
5320
+ const raw = formatResourceRef(entry.ref);
5321
+ const inForce = boundKeys.has(raw) || isPresetSkill(currentStage, raw);
5322
+ if (onlySelected && !inForce) return false;
5323
+ if (needle === "") return true;
5324
+ return inForce || entry.name.toLowerCase().includes(needle) || entry.description.toLowerCase().includes(needle) || entry.sourceLabel.toLowerCase().includes(needle);
5325
+ });
5326
+ };
5327
+ const visibleRulesFor = (bound) => {
5328
+ const chosen = new Set(bound.rules.map((rule) => formatResourceRef(rule)));
5329
+ const needle = ruleQuery.trim().toLowerCase();
5330
+ return rules.filter((rule) => {
5331
+ const raw = formatResourceRef(rule.ref);
5332
+ if (ruleOnlySelected && !chosen.has(raw)) return false;
5333
+ if (needle === "") return true;
5334
+ return chosen.has(raw) || rule.name.toLowerCase().includes(needle) || rule.sourceLabel.toLowerCase().includes(needle);
5335
+ });
5336
+ };
5337
+ const setSkills = (name, next) => {
5338
+ setStageBindings({ ...stageBindings, [name]: { ...bindingFor(name), skills: next } });
5247
5339
  };
5248
- const toggleRule = (rule) => {
5340
+ const toggleSkill = (raw) => {
5341
+ if (currentStage === "" || isPresetSkill(currentStage, raw)) return;
5342
+ const current = bindingFor(currentStage).skills ?? [];
5343
+ 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)));
5344
+ setSkills(currentStage, next);
5345
+ };
5346
+ const toggleRule = (skillRaw, ruleRaw) => {
5249
5347
  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 } });
5348
+ const current = bindingFor(currentStage).skills ?? [];
5349
+ setSkills(currentStage, current.map((entry) => {
5350
+ if (formatResourceRef(entry.skill) !== skillRaw) return entry;
5351
+ const has = entry.rules.some((rule) => formatResourceRef(rule) === ruleRaw);
5352
+ const next = has ? entry.rules.filter((rule) => formatResourceRef(rule) !== ruleRaw) : [...entry.rules, refFromText(ruleRaw)].sort((a, b) => formatResourceRef(a).localeCompare(formatResourceRef(b)));
5353
+ return { ...entry, rules: next };
5354
+ }));
5253
5355
  };
5254
5356
  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: () => {
5357
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.muted, children: "\u5F53\u524D\u6D41\u7A0B\u6CA1\u6709\u8282\u70B9\u3002" });
5358
+ }
5359
+ const boundSkills = bindingFor(currentStage).skills ?? [];
5360
+ const unassigned = bindingFor(currentStage).legacy_rules ?? [];
5361
+ const presetCount = presetSkills(currentStage).length;
5362
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.section, children: [
5363
+ /* @__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" }),
5364
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.field, children: [
5365
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.bindingLabel, children: "\u9009\u62E9\u8282\u70B9" }),
5366
+ /* @__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
5367
  setStage(s);
5265
5368
  }, children: s }, s)) })
5266
5369
  ] }),
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)
5370
+ unassigned.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "te-alert", children: [
5371
+ "\u4EE5\u4E0B\u89C4\u5219\u5C5E\u4E8E",
5372
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: "\u8282\u70B9" }),
5373
+ "\u800C\u4E0D\u662F\u4EFB\u4F55\u6280\u80FD\uFF08\u65E7\u914D\u7F6E\uFF09\uFF1A",
5374
+ unassigned.join("\u3001"),
5375
+ "\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"
5376
+ ] }) : null,
5377
+ /* @__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: [
5378
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "te-binding-heading", children: [
5379
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h4", { children: "\u6280\u80FD" }),
5380
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "te-binding-count", children: [
5381
+ "\u5DF2\u9009 ",
5382
+ boundSkills.length,
5383
+ presetCount > 0 ? `\uFF08\u542B ${presetCount} \u9879\u9884\u8BBE\uFF09` : "",
5384
+ visibleSkills().length !== skills.length ? ` \xB7 \u663E\u793A ${visibleSkills().length}/${skills.length}` : ""
5385
+ ] })
5386
+ ] }),
5387
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "te-binding-controls", children: [
5388
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
5389
+ "input",
5390
+ {
5391
+ className: "te-binding-search",
5392
+ type: "search",
5393
+ value: query,
5394
+ placeholder: "\u641C\u7D22\u6280\u80FD\u540D\u6216\u8BF4\u660E\u2026",
5395
+ "aria-label": "\u641C\u7D22\u6280\u80FD",
5396
+ onChange: (event) => setQuery(event.target.value)
5397
+ }
5398
+ ),
5399
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "te-binding-filter", children: [
5400
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "checkbox", checked: onlySelected, onChange: () => setOnlySelected((value) => !value) }),
5401
+ " ",
5402
+ "\u4EC5\u770B\u5DF2\u9009"
5403
+ ] })
5404
+ ] }),
5405
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "te-binding-list", role: "group", "aria-label": "\u6280\u80FD\u5217\u8868", tabIndex: 0, children: [
5406
+ 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,
5407
+ skills.length > 0 && visibleSkills().length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "te-binding-empty", children: "\u6CA1\u6709\u5339\u914D\u7684\u6280\u80FD\u3002" }) : null,
5408
+ visibleSkills().map((entry) => {
5409
+ const raw = formatResourceRef(entry.ref);
5410
+ const bound = boundSkills.find((candidate) => formatResourceRef(candidate.skill) === raw);
5411
+ const preset2 = isPresetSkill(currentStage, raw);
5412
+ const open = expanded === raw;
5413
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: `te-binding-option${bound !== void 0 ? " is-selected" : ""}`, children: [
5414
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
5415
+ "input",
5416
+ {
5417
+ type: "checkbox",
5418
+ "aria-label": raw,
5419
+ checked: bound !== void 0,
5420
+ disabled: preset2,
5421
+ onChange: () => toggleSkill(raw)
5422
+ }
5423
+ ),
5424
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "te-binding-detail", children: [
5425
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "te-binding-name", children: [
5426
+ entry.name,
5427
+ preset2 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "te-source-badge", children: "\u9884\u8BBE" }) : null
5428
+ ] }),
5429
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "te-binding-meta", children: [
5430
+ entry.sourceLabel,
5431
+ " \xB7 ",
5432
+ bound === void 0 ? "\u672A\u7ED1\u5B9A" : `${bound.rules.length} \u6761\u89C4\u5219`
5433
+ ] }),
5434
+ 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,
5435
+ open && bound !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "te-rule-list", children: [
5436
+ ruleQuery !== "" || ruleOnlySelected ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "te-binding-meta", children: [
5437
+ rules.length,
5438
+ " \u6761\u53EF\u7528\u89C4\u5219"
5439
+ ] }),
5440
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
5441
+ "input",
5442
+ {
5443
+ className: "te-binding-search",
5444
+ type: "search",
5445
+ value: ruleQuery,
5446
+ placeholder: "\u8FC7\u6EE4\u89C4\u5219\u2026",
5447
+ "aria-label": `\u8FC7\u6EE4 ${entry.name} \u7684\u89C4\u5219`,
5448
+ onChange: (event) => setRuleQuery(event.target.value)
5449
+ }
5450
+ ),
5451
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "te-binding-filter", children: [
5452
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "checkbox", checked: ruleOnlySelected, onChange: () => setRuleOnlySelected((value) => !value) }),
5453
+ " ",
5454
+ "\u4EC5\u770B\u5DF2\u9009"
5455
+ ] }),
5456
+ rules.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "te-binding-meta", children: "\u89C4\u5219\u5E93\u4E3A\u7A7A\u3002" }) : null,
5457
+ rules.length > 0 && visibleRulesFor(bound).length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "te-binding-meta", children: "\u6CA1\u6709\u5339\u914D\u7684\u89C4\u5219\u3002" }) : null,
5458
+ visibleRulesFor(bound).map((rule) => {
5459
+ const ruleRaw = formatResourceRef(rule.ref);
5460
+ const on = bound.rules.some((candidate) => formatResourceRef(candidate) === ruleRaw);
5461
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "te-binding-filter", children: [
5462
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "checkbox", checked: on, onChange: () => toggleRule(raw, ruleRaw) }),
5463
+ " ",
5464
+ rule.name,
5465
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "te-binding-meta", children: [
5466
+ "\uFF08",
5467
+ rule.sourceLabel,
5468
+ "\uFF09"
5469
+ ] })
5470
+ ] }, ruleRaw);
5471
+ })
5472
+ ] }) : null
5473
+ ] })
5474
+ ] }, raw);
5475
+ })
5476
+ ] })
5477
+ ] }) }, currentStage)
5271
5478
  ] });
5272
5479
  }
5273
- async function save(remote, flow, stageBindings, workspace, setSavedAt, setSource) {
5480
+ async function save(remote, config, workspace, setSavedAt, setSource) {
5274
5481
  try {
5275
- const result = await remote.write({ path: workspace, flow, stage_bindings: stageBindings });
5482
+ const result = await remote.write({ path: workspace, ...config });
5276
5483
  if (!result.ok) {
5277
5484
  setSavedAt("\u4FDD\u5B58\u5931\u8D25\uFF1A" + describeError(result.error));
5278
5485
  return false;
@@ -5291,7 +5498,7 @@ async function save(remote, flow, stageBindings, workspace, setSavedAt, setSourc
5291
5498
  }
5292
5499
 
5293
5500
  // src/client/InitPanel.tsx
5294
- var import_react3 = require("react");
5501
+ var import_react2 = require("react");
5295
5502
  var import_dsh_client_ui_primitives2 = require("@deepseek-ai/dsh-client-ui-primitives");
5296
5503
  var MD_LABELS = { code: { copyLabel: "\u590D\u5236", copiedLabel: "\u5DF2\u590D\u5236" }, footnotes: "\u811A\u6CE8" };
5297
5504
  var INIT_TIMEOUT_S = 150;
@@ -5304,14 +5511,14 @@ var card = {
5304
5511
  padding: "12px 14px"
5305
5512
  };
5306
5513
  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)(() => {
5514
+ const [view, setView] = (0, import_react2.useState)(null);
5515
+ const [generating, setGenerating] = (0, import_react2.useState)(false);
5516
+ const [elapsed, setElapsed] = (0, import_react2.useState)(0);
5517
+ const [draft, setDraft] = (0, import_react2.useState)(null);
5518
+ const [editing, setEditing] = (0, import_react2.useState)(false);
5519
+ const [body2, setBody] = (0, import_react2.useState)("");
5520
+ const [msg, setMsg] = (0, import_react2.useState)("");
5521
+ (0, import_react2.useEffect)(() => {
5315
5522
  if (!generating) {
5316
5523
  setElapsed(0);
5317
5524
  return;
@@ -5325,13 +5532,13 @@ function InitPanel({ workspace, remote }) {
5325
5532
  clearInterval(timer);
5326
5533
  };
5327
5534
  }, [generating]);
5328
- const refresh = (0, import_react3.useCallback)(() => {
5535
+ const refresh = (0, import_react2.useCallback)(() => {
5329
5536
  void remote.readInit(workspace).then((r) => {
5330
5537
  if (r.ok) setView(r.value);
5331
5538
  }, () => {
5332
5539
  });
5333
5540
  }, [remote, workspace]);
5334
- (0, import_react3.useEffect)(() => {
5541
+ (0, import_react2.useEffect)(() => {
5335
5542
  refresh();
5336
5543
  }, [refresh]);
5337
5544
  const generate = async () => {
@@ -5374,45 +5581,45 @@ function InitPanel({ workspace, remote }) {
5374
5581
  setMsg("");
5375
5582
  };
5376
5583
  const exists = view?.exists === true;
5377
- return (0, import_react3.createElement)(
5584
+ return (0, import_react2.createElement)(
5378
5585
  "div",
5379
5586
  { style: styles.section },
5380
- (0, import_react3.createElement)(
5587
+ (0, import_react2.createElement)(
5381
5588
  "div",
5382
5589
  { style: card },
5383
- (0, import_react3.createElement)(
5590
+ (0, import_react2.createElement)(
5384
5591
  "div",
5385
5592
  { 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
5593
+ (0, import_react2.createElement)(import_dsh_client_ui_primitives2.StateDot, { state: exists ? "done" : "ongoing" }),
5594
+ (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"),
5595
+ view?.path !== void 0 ? (0, import_react2.createElement)("span", { style: styles.sourceBadge }, `\u5DF2\u5B9A\u4F4D\u5230 ${view.path}`) : null
5389
5596
  ),
5390
- (0, import_react3.createElement)(
5597
+ (0, import_react2.createElement)(
5391
5598
  "p",
5392
5599
  { style: styles.muted },
5393
5600
  "\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
5601
  ),
5395
- exists && !editing && draft === null ? (0, import_react3.createElement)(
5602
+ exists && !editing && draft === null ? (0, import_react2.createElement)(
5396
5603
  "div",
5397
5604
  { style: styles.mdPreview },
5398
- (0, import_react3.createElement)(import_dsh_client_ui_primitives2.MarkdownText, { text: view.content, labels: MD_LABELS })
5605
+ (0, import_react2.createElement)(import_dsh_client_ui_primitives2.MarkdownText, { text: view.content, labels: MD_LABELS })
5399
5606
  ) : null,
5400
- draft !== null ? (0, import_react3.createElement)(
5607
+ draft !== null ? (0, import_react2.createElement)(
5401
5608
  "div",
5402
5609
  { style: styles.section },
5403
- (0, import_react3.createElement)(
5610
+ (0, import_react2.createElement)(
5404
5611
  "div",
5405
5612
  { 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`)
5613
+ (0, import_react2.createElement)(import_dsh_client_ui_primitives2.StateDot, { state: "ongoing", size: 8 }),
5614
+ (0, import_react2.createElement)("span", { style: styles.sourceBadge }, `AI \u8349\u7A3F \xB7 ${draft.lines} \u884C \xB7 \u5C1A\u672A\u5199\u5165`)
5408
5615
  ),
5409
- (0, import_react3.createElement)(
5616
+ (0, import_react2.createElement)(
5410
5617
  "div",
5411
5618
  { style: styles.mdPreview },
5412
- (0, import_react3.createElement)(import_dsh_client_ui_primitives2.MarkdownText, { text: draft.content, labels: MD_LABELS })
5619
+ (0, import_react2.createElement)(import_dsh_client_ui_primitives2.MarkdownText, { text: draft.content, labels: MD_LABELS })
5413
5620
  )
5414
5621
  ) : null,
5415
- editing ? (0, import_react3.createElement)("textarea", {
5622
+ editing ? (0, import_react2.createElement)("textarea", {
5416
5623
  style: { ...styles.textarea, minHeight: 300 },
5417
5624
  placeholder: "AGENTS.md \u6B63\u6587\uFF08Markdown\uFF0C\u2264200 \u884C\uFF09",
5418
5625
  value: body2,
@@ -5420,16 +5627,16 @@ function InitPanel({ workspace, remote }) {
5420
5627
  setBody(ev.target.value);
5421
5628
  }
5422
5629
  }) : null,
5423
- generating ? (0, import_react3.createElement)(
5630
+ generating ? (0, import_react2.createElement)(
5424
5631
  "p",
5425
5632
  { style: styles.status },
5426
5633
  `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
5634
  ) : null,
5428
- msg !== "" ? (0, import_react3.createElement)("p", { style: styles.status }, msg) : null,
5429
- draft !== null ? (0, import_react3.createElement)(
5635
+ msg !== "" ? (0, import_react2.createElement)("p", { style: styles.status }, msg) : null,
5636
+ draft !== null ? (0, import_react2.createElement)(
5430
5637
  "div",
5431
5638
  { style: styles.row },
5432
- (0, import_react3.createElement)(import_dsh_client_ui_primitives2.Button, {
5639
+ (0, import_react2.createElement)(import_dsh_client_ui_primitives2.Button, {
5433
5640
  variant: "primary",
5434
5641
  size: "md",
5435
5642
  disabled: draft.lines > 200,
@@ -5438,14 +5645,14 @@ function InitPanel({ workspace, remote }) {
5438
5645
  void write(draft.content, exists);
5439
5646
  }
5440
5647
  }, 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: () => {
5648
+ 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,
5649
+ (0, import_react2.createElement)(import_dsh_client_ui_primitives2.Button, { variant: "ghost", size: "md", onClick: () => {
5443
5650
  setDraft(null);
5444
5651
  } }, "\u653E\u5F03")
5445
- ) : editing ? (0, import_react3.createElement)(
5652
+ ) : editing ? (0, import_react2.createElement)(
5446
5653
  "div",
5447
5654
  { style: styles.row },
5448
- (0, import_react3.createElement)(import_dsh_client_ui_primitives2.Button, {
5655
+ (0, import_react2.createElement)(import_dsh_client_ui_primitives2.Button, {
5449
5656
  variant: "primary",
5450
5657
  size: "md",
5451
5658
  disabled: body2.trim() === "",
@@ -5454,13 +5661,13 @@ function InitPanel({ workspace, remote }) {
5454
5661
  void write(body2, exists);
5455
5662
  }
5456
5663
  }, exists ? "\u4FDD\u5B58\u5E76\u8986\u76D6" : "\u4FDD\u5B58"),
5457
- (0, import_react3.createElement)(import_dsh_client_ui_primitives2.Button, { variant: "ghost", size: "md", onClick: () => {
5664
+ (0, import_react2.createElement)(import_dsh_client_ui_primitives2.Button, { variant: "ghost", size: "md", onClick: () => {
5458
5665
  setEditing(false);
5459
5666
  } }, "\u53D6\u6D88")
5460
- ) : (0, import_react3.createElement)(
5667
+ ) : (0, import_react2.createElement)(
5461
5668
  "div",
5462
5669
  { style: styles.row },
5463
- (0, import_react3.createElement)(import_dsh_client_ui_primitives2.Button, {
5670
+ (0, import_react2.createElement)(import_dsh_client_ui_primitives2.Button, {
5464
5671
  variant: "primary",
5465
5672
  size: "md",
5466
5673
  disabled: generating,
@@ -5469,21 +5676,21 @@ function InitPanel({ workspace, remote }) {
5469
5676
  void generate();
5470
5677
  }
5471
5678
  }, 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
5679
+ exists ? (0, import_react2.createElement)(import_dsh_client_ui_primitives2.Button, { variant: "outline", size: "md", onClick: startEdit }, "\u624B\u52A8\u7F16\u8F91") : null
5473
5680
  )
5474
5681
  )
5475
5682
  );
5476
5683
  }
5477
5684
 
5478
5685
  // src/client/SkillManager.tsx
5479
- var import_react6 = require("react");
5686
+ var import_react5 = require("react");
5480
5687
 
5481
5688
  // src/client/ResourceManager.tsx
5482
- var import_react5 = require("react");
5689
+ var import_react4 = require("react");
5483
5690
  var import_dsh_client_ui_primitives4 = require("@deepseek-ai/dsh-client-ui-primitives");
5484
5691
 
5485
5692
  // src/client/ResourceModal.tsx
5486
- var import_react4 = require("react");
5693
+ var import_react3 = require("react");
5487
5694
  var import_react_dom = require("react-dom");
5488
5695
  var import_dsh_client_ui_primitives3 = require("@deepseek-ai/dsh-client-ui-primitives");
5489
5696
  var rootStyle = {
@@ -5567,10 +5774,10 @@ var footerStyle = {
5567
5774
  flex: "none"
5568
5775
  };
5569
5776
  function ResourceModal({ title, description, onClose, footer, children }) {
5570
- const dialog = (0, import_react4.useRef)(null);
5571
- const closer = (0, import_react4.useRef)(onClose);
5777
+ const dialog = (0, import_react3.useRef)(null);
5778
+ const closer = (0, import_react3.useRef)(onClose);
5572
5779
  closer.current = onClose;
5573
- (0, import_react4.useEffect)(() => {
5780
+ (0, import_react3.useEffect)(() => {
5574
5781
  const previous = document.activeElement;
5575
5782
  dialog.current?.focus();
5576
5783
  const onKey = (e) => {
@@ -5603,26 +5810,26 @@ function ResourceModal({ title, description, onClose, footer, children }) {
5603
5810
  };
5604
5811
  }, []);
5605
5812
  return (0, import_react_dom.createPortal)(
5606
- (0, import_react4.createElement)(
5813
+ (0, import_react3.createElement)(
5607
5814
  "div",
5608
5815
  { 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)(
5816
+ (0, import_react3.createElement)("div", { style: maskStyle, "aria-hidden": true, onClick: onClose }),
5817
+ (0, import_react3.createElement)(
5611
5818
  "div",
5612
5819
  { style: dialogStyle, ref: dialog, tabIndex: -1, role: "dialog", "aria-modal": true, "aria-label": title },
5613
- (0, import_react4.createElement)(
5820
+ (0, import_react3.createElement)(
5614
5821
  "div",
5615
5822
  { style: headerStyle },
5616
- (0, import_react4.createElement)("h2", { style: titleStyle }, title),
5617
- (0, import_react4.createElement)(
5823
+ (0, import_react3.createElement)("h2", { style: titleStyle }, title),
5824
+ (0, import_react3.createElement)(
5618
5825
  "button",
5619
5826
  { type: "button", style: closeBtnStyle, "aria-label": "\u5173\u95ED", onClick: onClose },
5620
- (0, import_react4.createElement)(import_dsh_client_ui_primitives3.IconCloseOutline16, { size: 14 })
5827
+ (0, import_react3.createElement)(import_dsh_client_ui_primitives3.IconCloseOutline16, { size: 14 })
5621
5828
  )
5622
5829
  ),
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
5830
+ description !== void 0 && description !== "" ? (0, import_react3.createElement)("p", { style: descStyle }, description) : null,
5831
+ (0, import_react3.createElement)("div", { style: bodyStyle }, children),
5832
+ footer !== void 0 ? (0, import_react3.createElement)("div", { style: footerStyle }, footer) : null
5626
5833
  )
5627
5834
  ),
5628
5835
  document.body
@@ -5637,35 +5844,35 @@ var sizeText = (bytes) => bytes < 1024 ? `${bytes} B` : bytes < 1024 * 1024 ? `$
5637
5844
  var fail = (r) => describeError(r.error ?? "\u64CD\u4F5C\u5931\u8D25");
5638
5845
  function ResourceManager({ workspace, remote, kind }) {
5639
5846
  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);
5847
+ const [rows, setRows] = (0, import_react4.useState)([]);
5848
+ const [query, setQuery] = (0, import_react4.useState)("");
5849
+ const [filter, setFilter] = (0, import_react4.useState)("all");
5850
+ const [notice, setNotice] = (0, import_react4.useState)("");
5851
+ const [error, setError] = (0, import_react4.useState)("");
5852
+ const [loading, setLoading] = (0, import_react4.useState)(true);
5853
+ const [revision, refresh] = (0, import_react4.useState)(0);
5854
+ const [busy, setBusy] = (0, import_react4.useState)(false);
5855
+ const [roots, setRoots] = (0, import_react4.useState)(null);
5856
+ const [importing, setImporting] = (0, import_react4.useState)(false);
5857
+ const [request, setRequest] = (0, import_react4.useState)(null);
5858
+ const [preview, setPreview] = (0, import_react4.useState)(null);
5859
+ const [level, setLevel] = (0, import_react4.useState)("project");
5860
+ const [manual, setManual] = (0, import_react4.useState)(false);
5861
+ const [sourceDir, setSourceDir] = (0, import_react4.useState)("");
5862
+ const [dirs, setDirs] = (0, import_react4.useState)([]);
5863
+ const [browsePath, setBrowsePath] = (0, import_react4.useState)("");
5864
+ const [editing, setEditing] = (0, import_react4.useState)(null);
5865
+ const [viewing, setViewing] = (0, import_react4.useState)(false);
5866
+ const [name, setName] = (0, import_react4.useState)("");
5867
+ const [description, setDescription] = (0, import_react4.useState)("");
5868
+ const [whenToUse, setWhenToUse] = (0, import_react4.useState)("");
5869
+ const [body2, setBody] = (0, import_react4.useState)("");
5870
+ const [deleting, setDeleting] = (0, import_react4.useState)(null);
5871
+ const input = (0, import_react4.useRef)(null);
5872
+ const fileEpoch = (0, import_react4.useRef)(0);
5873
+ const browseEpoch = (0, import_react4.useRef)(0);
5667
5874
  const readonly = editing !== null && editing !== "new" && levelOf(editing) === "bundled";
5668
- (0, import_react5.useEffect)(() => {
5875
+ (0, import_react4.useEffect)(() => {
5669
5876
  let active = true;
5670
5877
  setLoading(true);
5671
5878
  setRows([]);
@@ -5692,7 +5899,7 @@ function ResourceManager({ workspace, remote, kind }) {
5692
5899
  fileEpoch.current++;
5693
5900
  };
5694
5901
  }, [workspace, remote, kind, revision]);
5695
- (0, import_react5.useEffect)(() => {
5902
+ (0, import_react4.useEffect)(() => {
5696
5903
  let active = true;
5697
5904
  setPreview(null);
5698
5905
  if (!request) return;
@@ -5856,104 +6063,104 @@ function ResourceManager({ workspace, remote, kind }) {
5856
6063
  setBusy(false);
5857
6064
  }
5858
6065
  };
5859
- const status = () => error ? (0, import_react5.createElement)("div", { className: "te-alert", role: "alert" }, error) : null;
5860
- const targets = () => (0, import_react5.createElement)(
6066
+ const status = () => error ? (0, import_react4.createElement)("div", { className: "te-alert", role: "alert" }, error) : null;
6067
+ const targets = () => (0, import_react4.createElement)(
5861
6068
  "div",
5862
6069
  { className: "te-targets" },
5863
- ...["project", "user"].map((lvl) => (0, import_react5.createElement)(
6070
+ ...["project", "user"].map((lvl) => (0, import_react4.createElement)(
5864
6071
  "button",
5865
6072
  { type: "button", key: lvl, className: `te-target ${level === lvl ? "selected" : ""}`, "aria-pressed": level === lvl, disabled: busy || editing !== null && editing !== "new", onClick: () => {
5866
6073
  setPreview(null);
5867
6074
  setLevel(lvl);
5868
6075
  } },
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")
6076
+ (0, import_react4.createElement)("strong", null, lvl === "project" ? "\u9879\u76EE\u5171\u4EAB" : "\u4E2A\u4EBA\u5168\u5C40"),
6077
+ (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
6078
  )),
5872
- (0, import_react5.createElement)("code", { className: "te-path" }, roots?.[level] ?? (level === "project" ? `${workspace}/.dsh/${kind}s` : `DSH_HOME/${kind}s`))
6079
+ (0, import_react4.createElement)("code", { className: "te-path" }, roots?.[level] ?? (level === "project" ? `${workspace}/.dsh/${kind}s` : `DSH_HOME/${kind}s`))
5873
6080
  );
5874
6081
  const visible = rows.filter((r) => `${r.name} ${r.description ?? ""}`.toLowerCase().includes(query.toLowerCase()) && (filter === "all" || levelOf(r) === filter));
5875
- return (0, import_react5.createElement)(
6082
+ return (0, import_react4.createElement)(
5876
6083
  "section",
5877
6084
  { 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) => {
6085
+ (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
6086
  void selected(Array.from(e.target.files ?? []));
5880
6087
  } }),
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: () => {
6088
+ (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
6089
  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,
6090
+ } }, `\u65B0\u5EFA${noun}`), (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "primary", onClick: choose }, `\u5B89\u88C5${noun}`))),
6091
+ (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")),
6092
+ notice ? (0, import_react4.createElement)("div", { className: "te-success", role: "status" }, notice) : null,
5886
6093
  !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)(
6094
+ 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
6095
  "article",
5889
6096
  { 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: () => {
6097
+ (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))),
6098
+ (0, import_react4.createElement)("h3", null, row.name),
6099
+ (0, import_react4.createElement)("p", null, row.description || "\u9879\u76EE\u7EA6\u5B9A\u4E0E\u6267\u884C\u89C4\u5219"),
6100
+ (0, import_react4.createElement)("div", { className: "te-actions" }, (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "outline", size: "sm", onClick: () => {
5894
6101
  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: () => {
6102
+ } }, "\u67E5\u770B"), levelOf(row) !== "bundled" ? (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "ghost", size: "sm", onClick: () => {
5896
6103
  void edit(row);
5897
- } }, "\u7F16\u8F91") : null, levelOf(row) !== "bundled" ? (0, import_react5.createElement)("button", { className: "te-delete", onClick: () => {
6104
+ } }, "\u7F16\u8F91") : null, levelOf(row) !== "bundled" ? (0, import_react4.createElement)("button", { className: "te-delete", onClick: () => {
5898
6105
  setDeleting(row);
5899
6106
  setError("");
5900
6107
  } }, "\u5220\u9664") : null)
5901
6108
  ))),
5902
- kind === "skill" ? (0, import_react5.createElement)("button", { className: "te-link", onClick: () => {
6109
+ kind === "skill" ? (0, import_react4.createElement)("button", { className: "te-link", onClick: () => {
5903
6110
  setImporting(true);
5904
6111
  setManual(true);
5905
6112
  setError("");
5906
6113
  } }, "\u9AD8\u7EA7\uFF1A\u4ECE Harness \u4E3B\u673A\u8DEF\u5F84\u5B89\u88C5") : null,
5907
- importing ? (0, import_react5.createElement)(
6114
+ importing ? (0, import_react4.createElement)(
5908
6115
  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: () => {
6116
+ { 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
6117
  void install();
5911
6118
  } }, busy ? "\u5904\u7406\u4E2D\u2026" : "\u786E\u8BA4\u5B89\u88C5")) },
5912
6119
  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) => {
6120
+ (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),
6121
+ 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
6122
  setSourceDir(e.target.value);
5916
6123
  setRequest(null);
5917
- } }), (0, import_react5.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "outline", onClick: () => {
6124
+ } }), (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "outline", onClick: () => {
5918
6125
  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: () => {
6126
+ } }, "\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
6127
  void browse(browsePath.replace(/[\\/][^\\/]+[\\/]?$/u, "") || "/");
5921
- } }, "\u2191 \u4E0A\u7EA7\u76EE\u5F55") : null, ...dirs.map((d) => (0, import_react5.createElement)("button", { key: d.name, onClick: () => {
6128
+ } }, "\u2191 \u4E0A\u7EA7\u76EE\u5F55") : null, ...dirs.map((d) => (0, import_react4.createElement)("button", { key: d.name, onClick: () => {
5922
6129
  setRequest(null);
5923
6130
  void browse(browsePath.replace(/[\\/]+$/u, "") + "/" + d.name);
5924
6131
  } }, 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,
6132
+ busy ? (0, import_react4.createElement)("p", { role: "status" }, "\u6B63\u5728\u6821\u9A8C\u6587\u4EF6\uFF0C\u8BF7\u7A0D\u5019\u2026") : null,
5926
6133
  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
6134
+ 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
6135
  ) : null,
5929
- editing ? (0, import_react5.createElement)(
6136
+ editing ? (0, import_react4.createElement)(
5930
6137
  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: () => {
6138
+ { 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
6139
  void save2();
5933
6140
  } }, 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"),
6141
+ !readonly ? targets() : (0, import_react4.createElement)("p", { className: "te-badge" }, "\u5185\u7F6E\u8D44\u6E90 \xB7 \u53EA\u8BFB"),
5935
6142
  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) })))
6143
+ 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
6144
  ) : 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: () => {
6145
+ 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
6146
  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
6147
+ } }, 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
6148
  );
5942
6149
  }
5943
6150
 
5944
6151
  // src/client/SkillManager.tsx
5945
6152
  function SkillManager(props) {
5946
- return (0, import_react6.createElement)(ResourceManager, { ...props, key: props.workspace, kind: "skill" });
6153
+ return (0, import_react5.createElement)(ResourceManager, { ...props, key: props.workspace, kind: "skill" });
5947
6154
  }
5948
6155
 
5949
6156
  // src/client/RuleManager.tsx
5950
- var import_react7 = require("react");
6157
+ var import_react6 = require("react");
5951
6158
  function RuleManager(props) {
5952
- return (0, import_react7.createElement)(ResourceManager, { ...props, key: props.workspace, kind: "rule" });
6159
+ return (0, import_react6.createElement)(ResourceManager, { ...props, key: props.workspace, kind: "rule" });
5953
6160
  }
5954
6161
 
5955
6162
  // src/client/TaskLedger.tsx
5956
- var import_react8 = require("react");
6163
+ var import_react7 = require("react");
5957
6164
  var import_dsh_client_ui_primitives5 = require("@deepseek-ai/dsh-client-ui-primitives");
5958
6165
  var card2 = {
5959
6166
  display: "flex",
@@ -5992,10 +6199,10 @@ var badge = {
5992
6199
  color: "var(--dsw-alias-label-secondary)"
5993
6200
  };
5994
6201
  function verdictDot(outcome) {
5995
- return (0, import_react8.createElement)(import_dsh_client_ui_primitives5.StateDot, { state: outcome === "pass" ? "done" : "error" });
6202
+ return (0, import_react7.createElement)(import_dsh_client_ui_primitives5.StateDot, { state: outcome === "pass" ? "done" : "error" });
5996
6203
  }
5997
6204
  function itemStatusDot(status) {
5998
- return (0, import_react8.createElement)(import_dsh_client_ui_primitives5.StateDot, { state: status === "done" ? "done" : "ongoing" });
6205
+ return (0, import_react7.createElement)(import_dsh_client_ui_primitives5.StateDot, { state: status === "done" ? "done" : "ongoing" });
5999
6206
  }
6000
6207
  function timeText(at) {
6001
6208
  return at.slice(0, 19).replace("T", " ");
@@ -6003,48 +6210,48 @@ function timeText(at) {
6003
6210
  function itemAudit(item) {
6004
6211
  const lines = [];
6005
6212
  if (item.dispatch !== void 0) {
6006
- lines.push((0, import_react8.createElement)(
6213
+ lines.push((0, import_react7.createElement)(
6007
6214
  "div",
6008
6215
  { 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))
6216
+ (0, import_react7.createElement)("span", { style: badge }, "\u5DF2\u6D3E\u53D1"),
6217
+ (0, import_react7.createElement)("span", null, item.dispatch.description === "" ? "\uFF08\u65E0\u63CF\u8FF0\uFF09" : item.dispatch.description),
6218
+ (0, import_react7.createElement)("span", { style: badge }, timeText(item.dispatch.at))
6012
6219
  ));
6013
6220
  }
6014
6221
  if (item.review !== void 0) {
6015
6222
  const spec = item.review.spec;
6016
6223
  const quality = item.review.quality;
6017
- lines.push((0, import_react8.createElement)(
6224
+ lines.push((0, import_react7.createElement)(
6018
6225
  "div",
6019
6226
  { key: "review", style: metaLine },
6020
6227
  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"),
6228
+ (0, import_react7.createElement)("span", null, `\u89C4\u683C\u7B26\u5408 ${spec.outcome === "pass" ? "\u901A\u8FC7" : "\u4E0D\u901A\u8FC7"}`),
6229
+ (0, import_react7.createElement)("span", null, "\xB7"),
6023
6230
  verdictDot(quality.outcome),
6024
- (0, import_react8.createElement)("span", null, `\u4EE3\u7801\u8D28\u91CF ${quality.outcome === "pass" ? "\u901A\u8FC7" : "\u4E0D\u901A\u8FC7"}`)
6231
+ (0, import_react7.createElement)("span", null, `\u4EE3\u7801\u8D28\u91CF ${quality.outcome === "pass" ? "\u901A\u8FC7" : "\u4E0D\u901A\u8FC7"}`)
6025
6232
  ));
6026
6233
  const failNotes = [spec, quality].flatMap((stage) => stage.outcome === "fail" ? stage.notes ?? [] : []);
6027
6234
  if (failNotes.length > 0) {
6028
- lines.push((0, import_react8.createElement)(
6235
+ lines.push((0, import_react7.createElement)(
6029
6236
  "div",
6030
6237
  { key: "notes", style: metaLine },
6031
- ...failNotes.map((note) => (0, import_react8.createElement)("span", { key: note, style: badge }, note))
6238
+ ...failNotes.map((note) => (0, import_react7.createElement)("span", { key: note, style: badge }, note))
6032
6239
  ));
6033
6240
  }
6034
6241
  }
6035
6242
  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")));
6243
+ 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
6244
  }
6038
- return (0, import_react8.createElement)("div", { style: { display: "flex", flexDirection: "column", gap: 4 } }, ...lines);
6245
+ return (0, import_react7.createElement)("div", { style: { display: "flex", flexDirection: "column", gap: 4 } }, ...lines);
6039
6246
  }
6040
6247
  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)(() => {
6248
+ const [tasks, setTasks] = (0, import_react7.useState)([]);
6249
+ const [error, setError] = (0, import_react7.useState)("");
6250
+ const [loading, setLoading] = (0, import_react7.useState)(true);
6251
+ const [query, setQuery] = (0, import_react7.useState)("");
6252
+ const [risk, setRisk] = (0, import_react7.useState)("all");
6253
+ const [stage, setStage] = (0, import_react7.useState)("all");
6254
+ const refresh = (0, import_react7.useCallback)(() => {
6048
6255
  if (workspace === "") return;
6049
6256
  setError("");
6050
6257
  setLoading(true);
@@ -6057,57 +6264,57 @@ function TaskLedger({ workspace, remote }) {
6057
6264
  setError("\u8BFB\u53D6\u53F0\u8D26\u5931\u8D25\uFF1A" + describeError(reason));
6058
6265
  });
6059
6266
  }, [remote, workspace]);
6060
- (0, import_react8.useEffect)(() => {
6267
+ (0, import_react7.useEffect)(() => {
6061
6268
  refresh();
6062
6269
  }, [refresh]);
6063
6270
  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)(
6271
+ return (0, import_react7.createElement)(
6065
6272
  "div",
6066
6273
  { style: styles.section },
6067
- (0, import_react8.createElement)(
6274
+ (0, import_react7.createElement)(
6068
6275
  "div",
6069
6276
  { 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)))
6277
+ (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) }),
6278
+ (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")),
6279
+ (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
6280
  ),
6074
- (0, import_react8.createElement)(
6281
+ (0, import_react7.createElement)(
6075
6282
  "div",
6076
6283
  { 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")
6284
+ (0, import_react7.createElement)("span", { style: styles.bindingLabel }, "\u4EFB\u52A1\u53F0\u8D26"),
6285
+ (0, import_react7.createElement)("span", { style: styles.sourceBadge }, "\u53EA\u8BFB \xB7 \u6765\u81EA .dsh/task-*.json"),
6286
+ (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
6287
  ),
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)(
6288
+ 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
6289
  "div",
6083
6290
  { style: { display: "flex", flexDirection: "column", gap: 12 } },
6084
- ...visible.map((task) => (0, import_react8.createElement)(
6291
+ ...visible.map((task) => (0, import_react7.createElement)(
6085
6292
  "div",
6086
6293
  { key: task.task_id, style: card2 },
6087
- (0, import_react8.createElement)(
6294
+ (0, import_react7.createElement)(
6088
6295
  "div",
6089
6296
  { 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
6297
+ (0, import_react7.createElement)("span", { style: { fontSize: 14, fontWeight: 600, color: "var(--dsw-alias-label-primary)" } }, task.task_id),
6298
+ (0, import_react7.createElement)("span", { style: { fontSize: 13, color: "var(--dsw-alias-label-primary)" } }, task.title),
6299
+ (0, import_react7.createElement)("span", { style: badge }, task.stage),
6300
+ (0, import_react7.createElement)("span", { style: badge }, task.branch),
6301
+ (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"),
6302
+ (0, import_react7.createElement)("span", { className: "te-badge" }, task.verification_passed ? "\u9A8C\u8BC1\u901A\u8FC7" : "\u5F85\u9A8C\u8BC1"),
6303
+ (0, import_react7.createElement)("span", { className: "te-badge" }, `\u5BA1\u6838\uFF1A${task.review_outcome ?? "pending"}`),
6304
+ task.updated_at ? (0, import_react7.createElement)("span", { style: metaLine }, "\u66F4\u65B0\u4E8E " + timeText(task.updated_at)) : null
6098
6305
  ),
6099
- (0, import_react8.createElement)(
6306
+ (0, import_react7.createElement)(
6100
6307
  "div",
6101
6308
  { style: { display: "flex", flexDirection: "column" } },
6102
- ...task.items.map((item) => (0, import_react8.createElement)(
6309
+ ...task.items.map((item) => (0, import_react7.createElement)(
6103
6310
  "div",
6104
6311
  { key: item.id, style: itemRow },
6105
- (0, import_react8.createElement)(
6312
+ (0, import_react7.createElement)(
6106
6313
  "div",
6107
6314
  { style: headerRow },
6108
6315
  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)
6316
+ (0, import_react7.createElement)("span", { style: { fontSize: 13, color: "var(--dsw-alias-label-primary)" } }, item.id),
6317
+ (0, import_react7.createElement)("span", { style: { fontSize: 12, color: "var(--dsw-alias-label-secondary)" } }, item.title)
6111
6318
  ),
6112
6319
  itemAudit(item)
6113
6320
  ))
@@ -6181,29 +6388,29 @@ var TABS = [
6181
6388
  function Workbench({ useStore, actions, useWorkspaces, remote }) {
6182
6389
  const open = useStore((s) => s.open);
6183
6390
  const workspaces = useWorkspaces((s) => s.items);
6184
- const [tab, setTab] = (0, import_react9.useState)("init");
6185
- const [workspace, setWorkspace] = (0, import_react9.useState)("");
6391
+ const [tab, setTab] = (0, import_react8.useState)("init");
6392
+ const [workspace, setWorkspace] = (0, import_react8.useState)("");
6186
6393
  if (!open) return null;
6187
6394
  const current = workspaces.some((w) => w.path === workspace) ? workspace : workspaces[0]?.path ?? "";
6188
- return (0, import_react9.createElement)(
6395
+ return (0, import_react8.createElement)(
6189
6396
  "div",
6190
6397
  { style: overlay, className: "te-workbench" },
6191
- (0, import_react9.createElement)("style", null, workbenchTheme),
6192
- (0, import_react9.createElement)(
6398
+ (0, import_react8.createElement)("style", null, workbenchTheme),
6399
+ (0, import_react8.createElement)(
6193
6400
  "div",
6194
6401
  { style: header },
6195
- (0, import_react9.createElement)(
6402
+ (0, import_react8.createElement)(
6196
6403
  "div",
6197
6404
  { style: headerBrand },
6198
- (0, import_react9.createElement)(import_dsh_client_ui_primitives6.IconSettingsOutline16, { size: 18 }),
6199
- (0, import_react9.createElement)(
6405
+ (0, import_react8.createElement)(import_dsh_client_ui_primitives6.IconSettingsOutline16, { size: 18 }),
6406
+ (0, import_react8.createElement)(
6200
6407
  "div",
6201
6408
  { 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")
6409
+ (0, import_react8.createElement)("span", { style: headerTitle }, "\u5DE5\u7A0B\u6D41\u7A0B"),
6410
+ (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
6411
  )
6205
6412
  ),
6206
- (0, import_react9.createElement)(
6413
+ (0, import_react8.createElement)(
6207
6414
  "button",
6208
6415
  {
6209
6416
  type: "button",
@@ -6219,44 +6426,44 @@ function Workbench({ useStore, actions, useWorkspaces, remote }) {
6219
6426
  event.currentTarget.style.background = "transparent";
6220
6427
  }
6221
6428
  },
6222
- (0, import_react9.createElement)(import_dsh_client_ui_primitives6.IconCloseOutline16, { size: 16 })
6429
+ (0, import_react8.createElement)(import_dsh_client_ui_primitives6.IconCloseOutline16, { size: 16 })
6223
6430
  )
6224
6431
  ),
6225
- (0, import_react9.createElement)(
6432
+ (0, import_react8.createElement)(
6226
6433
  "div",
6227
6434
  { style: tabbar },
6228
- ...TABS.map((t) => (0, import_react9.createElement)(import_dsh_client_ui_primitives6.Pill, { key: t.id, active: tab === t.id, onClick: () => {
6435
+ ...TABS.map((t) => (0, import_react8.createElement)(import_dsh_client_ui_primitives6.Pill, { key: t.id, active: tab === t.id, onClick: () => {
6229
6436
  setTab(t.id);
6230
6437
  } }, t.label)),
6231
- workspaces.length > 0 ? (0, import_react9.createElement)("select", {
6438
+ workspaces.length > 0 ? (0, import_react8.createElement)("select", {
6232
6439
  style: selectStyle,
6233
6440
  "aria-label": "\u5F53\u524D\u5DE5\u4F5C\u533A",
6234
6441
  value: current,
6235
6442
  onChange: (ev) => {
6236
6443
  setWorkspace(ev.target.value);
6237
6444
  }
6238
- }, ...workspaces.map((w) => (0, import_react9.createElement)("option", { key: w.path, value: w.path }, w.title || w.path))) : null
6445
+ }, ...workspaces.map((w) => (0, import_react8.createElement)("option", { key: w.path, value: w.path }, w.title || w.path))) : null
6239
6446
  ),
6240
- (0, import_react9.createElement)(
6447
+ (0, import_react8.createElement)(
6241
6448
  "div",
6242
6449
  { style: body },
6243
- (0, import_react9.createElement)(
6450
+ (0, import_react8.createElement)(
6244
6451
  "div",
6245
6452
  { 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 })
6453
+ (0, import_react8.createElement)("p", { style: { ...styles.hint, marginBottom: 20 }, title: current }, "\u5DE5\u4F5C\u533A \xB7 " + current),
6454
+ 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
6455
  )
6249
6456
  )
6250
6457
  );
6251
6458
  }
6252
6459
 
6253
6460
  // src/client/TriggerButton.tsx
6254
- var import_react10 = require("react");
6461
+ var import_react9 = require("react");
6255
6462
  var import_dsh_client_ui_primitives7 = require("@deepseek-ai/dsh-client-ui-primitives");
6256
6463
  var hover = "var(--dsw-alias-bg-layer-2)";
6257
6464
  var label = "var(--dsw-alias-label-primary)";
6258
6465
  function TriggerButton({ wide, actions }) {
6259
- return (0, import_react10.createElement)(
6466
+ return (0, import_react9.createElement)(
6260
6467
  "button",
6261
6468
  {
6262
6469
  type: "button",
@@ -6296,8 +6503,8 @@ function TriggerButton({ wide, actions }) {
6296
6503
  transition: "background 120ms ease"
6297
6504
  }
6298
6505
  },
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
6506
+ (0, import_react9.createElement)(import_dsh_client_ui_primitives7.IconSettingsOutline16, { size: wide ? 16 : 18 }),
6507
+ wide ? (0, import_react9.createElement)("span", { style: { fontSize: 14, lineHeight: "22px" } }, "\u5DE5\u7A0B\u6D41\u7A0B") : null
6301
6508
  );
6302
6509
  }
6303
6510