@godv61/dsh-task-engine 0.24.0 → 0.26.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.
Files changed (60) hide show
  1. package/.acceptance.mjs +101 -39
  2. package/.assessment-batch1.mjs +32 -12
  3. package/.e2e-presets.mjs +40 -5
  4. package/.enforce-test.mjs +139 -0
  5. package/.evidence-test.mjs +118 -0
  6. package/.filter-test.mjs +93 -0
  7. package/.freeze-test.mjs +110 -1
  8. package/.hook-test.mjs +195 -190
  9. package/.p0-test.mjs +130 -46
  10. package/.preset-test.mjs +160 -160
  11. package/.revision-test.mjs +32 -3
  12. package/.roundtrip-test.mjs +178 -0
  13. package/.workflow-test.mjs +117 -4
  14. package/README.md +10 -8
  15. package/cordis.patch.yml +10 -10
  16. package/defaults/eng.json +70 -22
  17. package/docs/BRIEF-FOR-REVIEW.md +162 -162
  18. package/docs/CHANGELOG.md +49 -0
  19. package/docs/README.md +40 -40
  20. package/docs/configuration.md +14 -11
  21. package/docs/development.md +1 -1
  22. package/docs/faq.md +4 -4
  23. package/docs/listing/godv61__dsh-task-engine.yml +5 -5
  24. package/docs/listing/submission.md +83 -83
  25. package/docs/manual.html +31 -26
  26. package/docs/releases/0.23.2.md +21 -21
  27. package/docs/roadmap.md +34 -34
  28. package/docs/testing/0.23.2/R02/344/270/232/345/212/241/346/265/213/350/257/225/346/230/216/347/273/206.md +56 -56
  29. package/docs/testing/0.23.2/R03/344/270/232/345/212/241/346/265/213/350/257/225/346/230/216/347/273/206.md +38 -38
  30. package/docs/testing/0.23.2//346/265/213/350/257/225/346/212/245/345/221/212.md +65 -65
  31. package/hooks/commit-msg +159 -72
  32. package/lib/client.js +963 -571
  33. package/lib/client.js.map +3 -3
  34. package/lib/controller.d.ts +11 -2
  35. package/lib/controller.js +33 -5
  36. package/lib/controller.js.map +1 -1
  37. package/lib/dev-task.js +170 -28
  38. package/lib/dev-task.js.map +1 -1
  39. package/lib/engine.d.ts +105 -0
  40. package/lib/engine.js +93 -5
  41. package/lib/engine.js.map +1 -1
  42. package/lib/hook.js +17 -4
  43. package/lib/hook.js.map +1 -1
  44. package/lib/skill-audit.d.ts +14 -3
  45. package/lib/skill-audit.js +66 -3
  46. package/lib/skill-audit.js.map +1 -1
  47. package/lib/workflows.d.ts +78 -12
  48. package/lib/workflows.js +258 -94
  49. package/lib/workflows.js.map +1 -1
  50. package/package.json +9 -5
  51. package/preset/agent.cordis.yml +21 -21
  52. package/preset/enable.mjs +87 -87
  53. package/preset/persona.md +4 -4
  54. package/preset/preset.yml +1 -1
  55. package/rules/coding-conventions.md +6 -6
  56. package/rules/commit-conventions.md +6 -6
  57. package/rules/security-redlines.md +5 -5
  58. package/scripts/verify-dsh-compat.mjs +144 -144
  59. package/scripts/verify-package.mjs +1 -1
  60. package/skills/code-verify/SKILL.md +3 -3
package/lib/client.js CHANGED
@@ -4536,8 +4536,8 @@ var TYPERT_REMOTE = {
4536
4536
  var remote_default = TYPERT_REMOTE;
4537
4537
 
4538
4538
  // src/client/Workbench.tsx
4539
- var import_react8 = require("react");
4540
- var import_dsh_client_ui_primitives6 = require("@deepseek-ai/dsh-client-ui-primitives");
4539
+ var import_react9 = require("react");
4540
+ var import_dsh_client_ui_primitives7 = require("@deepseek-ai/dsh-client-ui-primitives");
4541
4541
 
4542
4542
  // src/client/workbench-theme.ts
4543
4543
  var workbenchTheme = `
@@ -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); }
@@ -4568,8 +4576,35 @@ var workbenchTheme = `
4568
4576
  .te-binding-name { font-size:13px; font-weight:600; overflow-wrap:anywhere; }
4569
4577
  .te-binding-description { color:var(--dsw-alias-label-secondary); font-size:12px; line-height:1.4; display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden; overflow-wrap:anywhere; }
4570
4578
  .te-binding-empty { margin:0; padding:18px 8px; font-size:13px; }
4579
+ .te-transfer { display:grid; grid-template-columns:minmax(0,1fr) 24px minmax(0,1fr); gap:12px; align-items:stretch; }
4580
+ .te-transfer-pane { display:flex; flex-direction:column; min-width:0; gap:10px; padding:14px; border:1px solid var(--dsw-alias-border-l2); border-radius:12px; background:var(--dsw-alias-bg-layer-1); }
4581
+ .te-transfer-pane h4 { margin:0; font-size:14px; }
4582
+ .te-transfer-arrow { display:grid; place-items:center; color:var(--dsw-alias-label-tertiary); font-size:20px; }
4583
+ .te-transfer-search,.te-transfer-caption { min-height:38px; width:100%; }
4584
+ .te-transfer-caption { display:flex; align-items:center; margin:0; color:var(--dsw-alias-label-secondary); font-size:12px; }
4585
+ .te-transfer-list { display:flex; flex-direction:column; gap:4px; min-height:180px; max-height:310px; overflow:auto; overscroll-behavior:contain; scrollbar-gutter:stable; }
4586
+ .te-transfer-row { width:100%; display:flex; align-items:center; justify-content:space-between; gap:12px; border:1px solid transparent; border-radius:8px; padding:9px 11px; background:var(--dsw-alias-bg-layer-2); color:var(--dsw-alias-label-primary); text-align:left; cursor:pointer; }
4587
+ .te-transfer-row:hover { border-color:var(--dsw-alias-state-business-primary); }
4588
+ .te-transfer-row.is-bound { background:var(--dsw-alias-bg-layer-1); border-color:var(--dsw-alias-border-l2); cursor:default; }
4589
+ .te-transfer-row-main { min-width:0; display:flex; flex-direction:column; gap:2px; }
4590
+ .te-transfer-row-main strong { font-size:13px; font-weight:600; overflow-wrap:anywhere; }
4591
+ .te-transfer-row-main small { color:var(--dsw-alias-label-secondary); font-size:11px; line-height:1.35; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
4592
+ .te-transfer-action { flex:none; display:grid; place-items:center; width:27px; height:27px; border-radius:7px; background:var(--dsw-alias-bg-layer-1); color:var(--dsw-alias-state-business-primary); font-size:18px; }
4593
+ .te-transfer-actions { flex:none; display:flex; align-items:center; gap:6px; }
4594
+ .te-transfer-config,.te-transfer-remove { border:0; border-radius:7px; padding:6px 8px; background:var(--dsw-alias-bg-layer-2); color:var(--dsw-alias-label-primary); cursor:pointer; font-size:12px; white-space:nowrap; }
4595
+ .te-transfer-config:hover,.te-transfer-remove:hover { color:var(--dsw-alias-state-business-primary); }
4596
+ .te-transfer-remove { width:27px; height:27px; padding:0; font-size:19px; line-height:1; }
4597
+ .te-dialog-error { color:var(--dsw-alias-state-error-primary); font-size:12px; margin-right:auto; }
4598
+ .te-skill-config { display:flex; flex:1; flex-direction:column; gap:12px; min-width:0; min-height:0; }
4599
+ .te-skill-evidence { display:flex; align-items:center; justify-content:space-between; gap:12px; font-size:13px; font-weight:600; }
4600
+ .te-skill-evidence .te-input { min-width:210px; }
4601
+ .te-skill-rule-list { display:flex; flex:1; flex-direction:column; gap:4px; min-height:0; overflow:auto; padding:4px; }
4602
+ .te-skill-rule-row { display:flex; align-items:center; gap:10px; padding:9px 10px; border:1px solid var(--dsw-alias-border-l2); border-radius:8px; cursor:pointer; }
4603
+ .te-skill-rule-row:hover { background:var(--dsw-alias-bg-layer-1); }
4604
+ .te-skill-rule-row span { flex:1; min-width:0; overflow-wrap:anywhere; }
4605
+ .te-skill-rule-row small { color:var(--dsw-alias-label-secondary); }
4571
4606
  .te-workbench p,.te-modal p { color:var(--dsw-alias-label-secondary); line-height:1.65; }
4572
- .te-content { max-width:1120px; margin:auto; width:100%; }
4607
+ .te-content { max-width:1600px; margin:auto; width:100%; }
4573
4608
  .te-resource { display:flex; flex-direction:column; gap:20px; }
4574
4609
  .te-section-heading { display:flex; justify-content:space-between; align-items:center; gap:16px; flex-wrap:wrap; }
4575
4610
  .te-section-heading p { margin:0; }
@@ -4577,7 +4612,7 @@ var workbenchTheme = `
4577
4612
  .te-toolbar { display:flex; flex-wrap:wrap; align-items:center; gap:12px; }
4578
4613
  .te-toolbar>input { flex:1; min-width:180px; }
4579
4614
  .te-input { background:var(--dsw-alias-bg-layer-1); border:1px solid var(--dsw-alias-border-l2); border-radius:10px; padding:10px 12px; font:inherit; color:var(--dsw-alias-label-primary); min-width:0; }
4580
- .te-resource-grid { display:grid; grid-template-columns:repeat(auto-fill,minmax(min(100%,280px),1fr)); gap:16px; }
4615
+ .te-resource-grid { display:grid; grid-template-columns:repeat(auto-fill,minmax(min(100%,320px),1fr)); gap:16px; }
4581
4616
  .te-resource-card { display:flex; flex-direction:column; gap:14px; background:var(--dsw-alias-bg-layer-1); border:1px solid var(--dsw-alias-border-l2); border-radius:16px; padding:20px; transition:border-color .15s; }
4582
4617
  .te-resource-card:hover { border-color:var(--dsw-alias-state-business-primary); }
4583
4618
  .te-resource-card p { margin:0; font-size:13px; flex:1; }
@@ -4608,7 +4643,8 @@ var workbenchTheme = `
4608
4643
  .te-form { display:flex; flex-direction:column; gap:16px; }
4609
4644
  .te-form label { display:flex; flex-direction:column; gap:8px; font-size:13px; }
4610
4645
  .te-editor { min-height:260px; resize:vertical; line-height:1.6; font-family:monospace; }
4611
- @media(max-width:640px) { .te-targets {grid-template-columns:1fr;} .te-resource {gap:14px;} .te-section-heading h2 {font-size:21px;} .te-modal {padding:10px !important;} }
4646
+ @media(max-width:760px) { .te-transfer {grid-template-columns:1fr;} .te-transfer-arrow {transform:rotate(90deg); height:20px;} .te-transfer-list {max-height:210px;} }
4647
+ @media(max-width:640px) { .te-targets {grid-template-columns:1fr;} .te-resource {gap:14px;} .te-section-heading h2 {font-size:21px;} .te-modal:not(.te-drawer) {padding:10px !important;} .te-drawer [role=dialog] {border-radius:0 !important;} .te-skill-evidence {align-items:stretch; flex-direction:column;} .te-skill-evidence .te-input {min-width:0;} }
4612
4648
  `;
4613
4649
 
4614
4650
  // src/client/styles.ts
@@ -4622,8 +4658,8 @@ var success = "var(--dsw-alias-state-success-primary)";
4622
4658
  var warn = "var(--dsw-alias-state-warn-primary)";
4623
4659
  var brand = "var(--dsw-alias-state-business-primary)";
4624
4660
  var styles = {
4625
- wrap: { display: "flex", flexDirection: "column", gap: 16, padding: 20, maxWidth: 900 },
4626
- head: { display: "flex", flexDirection: "column", gap: 4 },
4661
+ wrap: { display: "flex", flexDirection: "column", gap: 14, padding: "0 0 24px", width: "100%" },
4662
+ head: { display: "flex", flexDirection: "column", gap: 4, maxWidth: 1e3 },
4627
4663
  title: { margin: 0, color: text },
4628
4664
  muted: { margin: 0, color: textSecondary, fontSize: 13, lineHeight: 1.5 },
4629
4665
  sourceRow: { display: "flex", alignItems: "center", gap: 8 },
@@ -4694,7 +4730,11 @@ var styles = {
4694
4730
  borderTop: `1px solid ${border}`
4695
4731
  },
4696
4732
  // ── flow preset picker ────────────────────────────────────────────────────
4697
- flowGrid: { display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(230px, 1fr))", gap: 10 },
4733
+ flowGrid: { display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(230px, 1fr))", gap: 10, maxWidth: 1200 },
4734
+ // The adoption row is deliberately separated from the flow picker: choosing a
4735
+ // skeleton and adopting a recommended setup are different decisions, and the
4736
+ // button is the only thing that writes method into the user's config.
4737
+ adoptRow: { display: "flex", alignItems: "center", gap: 10, flexWrap: "wrap", marginBottom: 4 },
4698
4738
  flowOption: {
4699
4739
  display: "flex",
4700
4740
  flexDirection: "column",
@@ -4736,8 +4776,8 @@ var styles = {
4736
4776
  };
4737
4777
 
4738
4778
  // src/client/TaskEngineSection.tsx
4739
- var import_react = require("react");
4740
- var import_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
4779
+ var import_react3 = require("react");
4780
+ var import_dsh_client_ui_primitives3 = require("@deepseek-ai/dsh-client-ui-primitives");
4741
4781
 
4742
4782
  // src/engine.ts
4743
4783
  function formatResourceRef(ref) {
@@ -4757,7 +4797,7 @@ var GUARD_NAMES = [
4757
4797
  "artifacts_present"
4758
4798
  ];
4759
4799
  function validateWorkflow(config) {
4760
- const problems = [];
4800
+ const problems = [...config.configuration_errors ?? []];
4761
4801
  if (config.stages.length === 0) problems.push("stages must not be empty");
4762
4802
  const seen = /* @__PURE__ */ new Set();
4763
4803
  for (const stage of config.stages) {
@@ -4804,6 +4844,7 @@ function validateWorkflow(config) {
4804
4844
  }
4805
4845
  });
4806
4846
  const bindings = config.stage_bindings ?? {};
4847
+ const skillMethods = /* @__PURE__ */ new Map();
4807
4848
  for (const [stage, binding] of Object.entries(bindings)) {
4808
4849
  if (!config.stages.includes(stage)) {
4809
4850
  problems.push(`stage_bindings: stage "${stage}" is not a stage`);
@@ -4816,6 +4857,19 @@ function validateWorkflow(config) {
4816
4857
  if (!["bundled", "project", "user"].includes(entry.skill.source)) {
4817
4858
  problems.push(`stage_bindings "${stage}": skill "${entry.skill.name}" has unknown source "${String(entry.skill.source)}"`);
4818
4859
  }
4860
+ const skillKey = formatResourceRef(entry.skill);
4861
+ const method = JSON.stringify({ rules: entry.rules ?? [], evidence: entry.evidence });
4862
+ const existing = skillMethods.get(skillKey);
4863
+ if (existing !== void 0 && existing !== method) {
4864
+ problems.push(`skill "${skillKey}" has different rules or evidence in multiple stages; copy it as a distinct skill`);
4865
+ }
4866
+ skillMethods.set(skillKey, method);
4867
+ if (entry.evidence === "artifact" && !config.artifacts.some((artifact) => artifact.stage === stage)) {
4868
+ problems.push(`skill "${skillKey}" requires artifact evidence, but stage "${stage}" declares no artifact`);
4869
+ }
4870
+ if (entry.evidence !== void 0 && !["command", "artifact", "review", "manual", "none"].includes(entry.evidence)) {
4871
+ problems.push(`skill "${skillKey}" has unknown evidence type "${String(entry.evidence)}"`);
4872
+ }
4819
4873
  for (const rule of entry.rules ?? []) {
4820
4874
  if (typeof rule?.name !== "string" || rule.name.trim() === "") {
4821
4875
  problems.push(`stage_bindings "${stage}": skill "${entry.skill.name}" has a rule with no name`);
@@ -4871,19 +4925,23 @@ var STANDARD = {
4871
4925
  { from: "\u4EA4\u4ED8", to: "\u4EE3\u7801\u5BA1\u6838", requires: ["verified"] },
4872
4926
  { from: "\u4EE3\u7801\u5BA1\u6838", to: "\u5B8C\u6210", requires: ["review_passed", "artifacts_present"] }
4873
4927
  ],
4928
+ // No artifacts, no commit policy, no skills: the skeleton carries none of them.
4929
+ artifacts: [],
4930
+ commit: { policy: "task", message_pattern: "", message_hint: "\u65E0\u683C\u5F0F\u8981\u6C42", checkpoints: ["\u4EE3\u7801\u5BA1\u6838"], file_scope: true },
4931
+ high_risk_requires_verification: true
4932
+ };
4933
+ var STANDARD_RECOMMENDATION = {
4934
+ commit: {
4935
+ // Only the TEXT conventions. Policy, checkpoints and scope stay on the
4936
+ // skeleton: they decide when a gate fires, not how a message reads.
4937
+ message_pattern: "^\u3010(\\S+)\u3011\u3010(?:TASK|T\\d+)\u3011.+",
4938
+ 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"
4939
+ },
4874
4940
  artifacts: [
4875
4941
  { stage: "\u9700\u6C42\u8BC4\u5BA1", id: "requirement", name: "\u9700\u6C42\u8BF4\u660E", fields: ["scope", "acceptance_criteria"] },
4876
4942
  { stage: "\u8BBE\u8BA1", id: "design", name: "\u8BBE\u8BA1\u6587\u6863", fields: ["approach", "risks", "impact"] },
4877
4943
  { stage: "\u4EE3\u7801\u5BA1\u6838", id: "review", name: "\u8BC4\u5BA1\u8BB0\u5F55", fields: ["conclusion", "issues"] }
4878
4944
  ],
4879
- commit: {
4880
- policy: "task",
4881
- message_pattern: "^\u3010(\\S+)\u3011\u3010(?:TASK|T\\d+)\u3011.+",
4882
- 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",
4883
- checkpoints: ["\u4EE3\u7801\u5BA1\u6838"],
4884
- file_scope: true
4885
- },
4886
- high_risk_requires_verification: true,
4887
4945
  stage_bindings: {
4888
4946
  "\u9700\u6C42\u8BC4\u5BA1": { skills: [bundled("requirement-analysis", "security-redlines")] },
4889
4947
  "\u8BBE\u8BA1": { skills: [bundled("solution-design")] },
@@ -4903,30 +4961,38 @@ var AGILE = {
4903
4961
  transitions: [
4904
4962
  { from: "\u9700\u6C42", to: "\u5F00\u53D1", requires: ["requirement_confirmation"] },
4905
4963
  { from: "\u5F00\u53D1", to: "\u4EA4\u4ED8", requires: ["todos_done"] },
4964
+ // Entering 审查 is unconditional. A review guard on this edge would be
4965
+ // circular — it would demand the verdict BEFORE the stage that produces it —
4966
+ // and it would also block the commit at 交付, since a commit requires its
4967
+ // stage's outgoing guards. What 审查 requires is declared as completion_guards
4968
+ // instead, because a terminal stage has no outgoing edge to carry it.
4906
4969
  { from: "\u4EA4\u4ED8", to: "\u5BA1\u67E5", requires: [] }
4907
4970
  ],
4971
+ artifacts: [],
4972
+ commit: { policy: "item", message_pattern: "", message_hint: "\u65E0\u683C\u5F0F\u8981\u6C42", checkpoints: ["\u4EA4\u4ED8"], file_scope: true },
4973
+ high_risk_requires_verification: false,
4974
+ // 审查 is terminal and IS the review, so there is no outgoing edge to carry
4975
+ // the guard. Declaring it here is what makes a blocked review prevent
4976
+ // completion; without it the stage could be reached and finished with the
4977
+ // review failing, which is what the assessment found.
4978
+ completion_guards: ["review_passed"]
4979
+ };
4980
+ var AGILE_RECOMMENDATION = {
4981
+ commit: {
4982
+ // `item` policy emits two label shapes: `T<n>` mid-flow and `TASK` at the
4983
+ // closing checkpoint. The pattern accepts BOTH, so the label the engine hands
4984
+ // the model always satisfies the rule that validates it.
4985
+ message_pattern: "^\u3010(\\S+)\u3011\u3010(?:TASK|T\\d+)\u3011.+",
4986
+ 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"
4987
+ },
4908
4988
  artifacts: [
4909
4989
  { stage: "\u9700\u6C42", id: "requirement", name: "\u9700\u6C42\u8BF4\u660E", fields: ["scope"] },
4910
4990
  // The 审查 stage binds code-review, whose instructions write this artifact with
4911
- // `record artifact=review`. Declaring it here keeps that binding executable:
4912
- // the engine refuses an undeclared artifact, so a bound skill pointing at one
4913
- // would be a contract the preset itself made impossible to satisfy.
4991
+ // `record artifact=review`. Declaring it keeps that binding executable: the
4992
+ // engine refuses an undeclared artifact, so a bound skill pointing at one would
4993
+ // be a contract the recommendation made impossible to satisfy.
4914
4994
  { stage: "\u5BA1\u67E5", id: "review", name: "\u8BC4\u5BA1\u8BB0\u5F55", fields: ["conclusion", "issues"] }
4915
4995
  ],
4916
- commit: {
4917
- // `item` policy emits two label shapes: `T<n>` for a mid-flow item commit and
4918
- // `TASK` for the closing commit at the checkpoint. The pattern below accepts
4919
- // BOTH, so the label the engine hands the model always satisfies the preset's
4920
- // own rule. Previously it accepted only `T\d+` while the checkpoint stage
4921
- // returned `TASK`, which made the closing commit impossible to phrase: the
4922
- // status line and the validator disagreed about the contract.
4923
- policy: "item",
4924
- message_pattern: "^\u3010(\\S+)\u3011\u3010(?:TASK|T\\d+)\u3011.+",
4925
- message_hint: "\u3010<task_id>\u3011\u3010TASK/T1\u3011\u8BF4\u660E \u2014\u2014 \u7B2C\u4E00\u6BB5\u586B\u672C\u4EFB\u52A1 id\uFF1B\u5B9E\u65BD\u9879\u63D0\u4EA4\u7528 T1\u3001T2\uFF0C\u6536\u5C3E\u63D0\u4EA4\u7528 TASK",
4926
- checkpoints: ["\u4EA4\u4ED8"],
4927
- file_scope: true
4928
- },
4929
- high_risk_requires_verification: false,
4930
4996
  stage_bindings: {
4931
4997
  "\u9700\u6C42": { skills: [bundled("requirement-analysis", "security-redlines")] },
4932
4998
  "\u5F00\u53D1": { skills: [bundled("code-implement", "coding-conventions", "security-redlines")] },
@@ -4941,18 +5007,13 @@ var MINIMAL = {
4941
5007
  { from: "\u5F00\u53D1", to: "\u4EA4\u4ED8", requires: ["todos_done"] }
4942
5008
  ],
4943
5009
  artifacts: [],
4944
- commit: {
4945
- policy: "task",
4946
- message_pattern: "",
4947
- message_hint: "\u65E0\u683C\u5F0F\u8981\u6C42",
4948
- checkpoints: ["\u4EA4\u4ED8"],
4949
- file_scope: false
4950
- },
4951
- high_risk_requires_verification: false,
5010
+ commit: { policy: "task", message_pattern: "", message_hint: "\u65E0\u683C\u5F0F\u8981\u6C42", checkpoints: ["\u4EA4\u4ED8"], file_scope: false },
5011
+ high_risk_requires_verification: false
5012
+ };
5013
+ var MINIMAL_RECOMMENDATION = {
4952
5014
  // A fast-change flow checks each change once, not twice under two headings a
4953
5015
  // short change rarely distinguishes. The item still has to be reviewed — what
4954
- // drops is the duplicated verdict, which is where the weight actually was: this
4955
- // flow used to carry the same per-item audit burden as the full one.
5016
+ // drops is the duplicated verdict, which is where the weight actually was.
4956
5017
  review_depth: "single",
4957
5018
  stage_bindings: {
4958
5019
  "\u5F00\u53D1": { skills: [bundled("code-implement", "coding-conventions", "security-redlines")] },
@@ -4968,54 +5029,160 @@ function deriveCapabilities(config) {
4968
5029
  if (config.commit.file_scope) caps.push("file_scope");
4969
5030
  return caps;
4970
5031
  }
4971
- function preset(id, version, label2, description, config) {
4972
- return { id, version, label: label2, description, capabilities: deriveCapabilities(config), config };
5032
+ function preset(id, version, label2, description, config, recommendation) {
5033
+ return {
5034
+ id,
5035
+ version,
5036
+ label: label2,
5037
+ description,
5038
+ capabilities: deriveCapabilities(config),
5039
+ config,
5040
+ // exactOptionalPropertyTypes: omit rather than assign undefined.
5041
+ ...recommendation !== void 0 ? { recommendation } : {}
5042
+ };
4973
5043
  }
4974
5044
  var FLOW_PRESETS = {
4975
- standard: preset("standard", 2, "\u5B8C\u6574\u7814\u53D1", "\u65B0\u529F\u80FD\u3001\u67B6\u6784\u6216\u8DE8\u6A21\u5757\u6539\u52A8\u3001\u9AD8\u98CE\u9669\u4EFB\u52A1\uFF1A\u9700\u6C42\u786E\u8BA4 \u2192 \u65B9\u6848\u786E\u8BA4 \u2192 \u5B9E\u73B0 \u2192 \u9A8C\u8BC1 \u2192 \u5BA1\u6838 \u2192 \u63D0\u4EA4", STANDARD),
4976
- // Version 2: the closing-commit label shape was unified with the message pattern,
4977
- // and the `review` artifact the bound code-review skill writes was declared. Tasks
4978
- // created before this keep their frozen version 1 config and are unaffected.
4979
- agile: preset("agile", 2, "\u65E5\u5E38\u8FED\u4EE3", "\u76EE\u6807\u660E\u786E\u7684\u5E38\u89C4\u529F\u80FD\u4E0E\u7F3A\u9677\u4FEE\u590D\uFF1A\u76EE\u6807\u4E0E\u9A8C\u6536 \u2192 \u5B9E\u73B0 \u2192 \u9A8C\u6536\u4E0E\u5BA1\u67E5 \u2192 \u63D0\u4EA4", AGILE),
4980
- // Version 2: per-item review depth is declared as `single` instead of inheriting
4981
- // the full flow's two verdicts per item. Tasks created before this keep their
4982
- // frozen version 1 config, which has no `review_depth` and therefore reads as
4983
- // two-stage exactly as it behaved.
4984
- minimal: preset("minimal", 2, "\u5FEB\u901F\u4FEE\u6539", "\u5C40\u90E8\u3001\u4F4E\u98CE\u9669\u3001\u65B9\u6848\u660E\u786E\u7684\u6539\u52A8\uFF1A\u4FEE\u6539 \u2192 \u68C0\u67E5\u4E0E\u63D0\u4EA4\uFF0C\u6BCF\u9879\u4E00\u6B21\u68C0\u67E5", MINIMAL)
5045
+ 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),
5046
+ // Version 4 for agile: 交付 → 审查 now requires review_passed, where it previously
5047
+ // required nothing. That is a gate-semantics change, so a task created before it
5048
+ // keeps its frozen version 3 config and behaves exactly as it did.
5049
+ //
5050
+ // Version 3 across all three: the preset is now a bare skeleton and its former
5051
+ // built-in bindings, commit rule and artifacts are a separate recommendation a
5052
+ // user adopts explicitly. Tasks created before this keep their frozen config and
5053
+ // are unaffected; a project's existing config is likewise left exactly as it is.
5054
+ 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),
5055
+ 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)
4985
5056
  };
4986
5057
  function dedupe(names) {
4987
5058
  return [...new Set(names)];
4988
5059
  }
4989
- function mergeBindings(base, override) {
4990
- if (override === void 0) return base;
4991
- let changed = false;
4992
- const merged = { ...base.stage_bindings };
4993
- for (const [stage, addition] of Object.entries(override)) {
4994
- const existing = merged[stage];
4995
- const skills = [...existing?.skills ?? []];
4996
- const seen = new Set(skills.map((skill) => formatResourceRef(skill.skill)));
4997
- for (const skill of addition.skills ?? []) {
4998
- const key = formatResourceRef(skill.skill);
4999
- if (seen.has(key)) continue;
5000
- seen.add(key);
5001
- skills.push(skill);
5002
- }
5003
- const legacy = dedupe([...existing?.legacy_rules ?? [], ...addition.legacy_rules ?? []]);
5004
- const binding = {};
5005
- if (skills.length > 0) binding.skills = skills;
5006
- if (legacy.length > 0) binding.legacy_rules = legacy;
5007
- merged[stage] = binding;
5008
- changed = true;
5009
- }
5010
- if (!changed) return base;
5011
- return { ...base, stage_bindings: merged };
5060
+ function applyProjectConfig(base, project) {
5061
+ if (project === void 0) return base;
5062
+ const next = { ...base };
5063
+ if (project.stage_bindings !== void 0) {
5064
+ const profiles = { ...project.skill_profiles ?? {} };
5065
+ const explicitProfiles = new Set(Object.keys(project.skill_profiles ?? {}));
5066
+ const problems = [];
5067
+ const bindings = {};
5068
+ for (const [stage, binding] of Object.entries(project.stage_bindings)) {
5069
+ const entry = {};
5070
+ if (binding === null || typeof binding !== "object") {
5071
+ problems.push(`stage_bindings "${stage}" must be an object`);
5072
+ bindings[stage] = entry;
5073
+ continue;
5074
+ }
5075
+ if (binding.skill_refs !== void 0 && binding.skills !== void 0) {
5076
+ problems.push(`stage_bindings "${stage}" has both skill_refs and legacy skills`);
5077
+ }
5078
+ if (binding.skill_refs !== void 0) {
5079
+ if (!Array.isArray(binding.skill_refs)) {
5080
+ problems.push(`stage_bindings "${stage}" skill_refs must be an array`);
5081
+ }
5082
+ entry.skills = (Array.isArray(binding.skill_refs) ? binding.skill_refs : []).flatMap((ref) => {
5083
+ if (ref === null || typeof ref !== "object") {
5084
+ problems.push(`stage_bindings "${stage}" has an invalid skill reference`);
5085
+ return [];
5086
+ }
5087
+ const key = formatResourceRef(ref);
5088
+ const profile = profiles[key];
5089
+ if (profile === void 0) {
5090
+ problems.push(`skill profile "${key}" is missing`);
5091
+ return [];
5092
+ }
5093
+ if (profile === null || !Array.isArray(profile.rules)) {
5094
+ problems.push(`skill profile "${key}" must declare a rules array`);
5095
+ return [];
5096
+ }
5097
+ return [{ skill: ref, rules: profile.rules, ...profile.evidence !== void 0 ? { evidence: profile.evidence } : {} }];
5098
+ });
5099
+ } else if (binding.skills !== void 0) {
5100
+ if (!Array.isArray(binding.skills)) {
5101
+ problems.push(`stage_bindings "${stage}" skills must be an array`);
5102
+ }
5103
+ entry.skills = (Array.isArray(binding.skills) ? binding.skills : []).flatMap((skill) => {
5104
+ if (skill === null || typeof skill !== "object" || skill.skill === null || typeof skill.skill !== "object") {
5105
+ problems.push(`stage_bindings "${stage}" has an invalid skill binding`);
5106
+ return [];
5107
+ }
5108
+ const key = formatResourceRef(skill.skill);
5109
+ if (explicitProfiles.has(key)) {
5110
+ const profile = profiles[key];
5111
+ if (profile === null || !Array.isArray(profile?.rules)) {
5112
+ problems.push(`skill profile "${key}" must declare a rules array`);
5113
+ return [];
5114
+ }
5115
+ return [{
5116
+ skill: skill.skill,
5117
+ rules: profile.rules,
5118
+ ...profile.evidence !== void 0 ? { evidence: profile.evidence } : {}
5119
+ }];
5120
+ }
5121
+ const candidate = { rules: skill.rules ?? [], ...skill.evidence !== void 0 ? { evidence: skill.evidence } : {} };
5122
+ const existing = profiles[key];
5123
+ if (existing !== void 0 && JSON.stringify(existing) !== JSON.stringify(candidate)) {
5124
+ problems.push(`skill "${key}" has different rules or evidence in multiple stages; copy it as a distinct skill`);
5125
+ } else profiles[key] = candidate;
5126
+ return [skill];
5127
+ });
5128
+ }
5129
+ const legacy = dedupe(binding.legacy_rules ?? []);
5130
+ if (legacy.length > 0) entry.legacy_rules = legacy;
5131
+ bindings[stage] = entry;
5132
+ }
5133
+ next.stage_bindings = bindings;
5134
+ next.skill_profiles = profiles;
5135
+ if (problems.length > 0) next.configuration_errors = problems;
5136
+ } else if (project.skill_profiles !== void 0) {
5137
+ next.skill_profiles = project.skill_profiles;
5138
+ }
5139
+ if (project.commit !== void 0) next.commit = project.commit;
5140
+ if (project.artifacts !== void 0) next.artifacts = project.artifacts;
5141
+ if (project.review_depth !== void 0) next.review_depth = project.review_depth;
5142
+ if (project.commit_required !== void 0) next.commit_required = project.commit_required;
5143
+ return next;
5144
+ }
5145
+ function adoptRecommendation(presetId, current) {
5146
+ const preset2 = FLOW_PRESETS[presetId];
5147
+ if (preset2 === void 0) return void 0;
5148
+ const rec = preset2.recommendation;
5149
+ if (rec === void 0) return { flow: presetId, ...current };
5150
+ const commit = {
5151
+ ...preset2.config.commit,
5152
+ ...rec.commit ?? {},
5153
+ ...current?.commit ?? {}
5154
+ };
5155
+ const config = {
5156
+ flow: presetId,
5157
+ stage_bindings: current?.stage_bindings ?? rec.stage_bindings ?? {},
5158
+ ...current?.skill_profiles !== void 0 ? { skill_profiles: current.skill_profiles } : {},
5159
+ commit,
5160
+ artifacts: current?.artifacts ?? rec.artifacts ?? preset2.config.artifacts,
5161
+ ...current?.review_depth !== void 0 ? { review_depth: current.review_depth } : rec.review_depth !== void 0 ? { review_depth: rec.review_depth } : {},
5162
+ ...current?.commit_required !== void 0 ? { commit_required: current.commit_required } : {}
5163
+ };
5164
+ return config;
5165
+ }
5166
+ function compactProjectConfig(project) {
5167
+ const resolved = resolveFlow(project.flow, project);
5168
+ if (!resolved.ok) return project;
5169
+ const profiles = resolved.config.skill_profiles ?? {};
5170
+ const bindings = {};
5171
+ for (const [stage, binding] of Object.entries(resolved.config.stage_bindings ?? {})) {
5172
+ bindings[stage] = {
5173
+ skill_refs: (binding.skills ?? []).map((entry) => entry.skill),
5174
+ ...binding.legacy_rules?.length ? { legacy_rules: binding.legacy_rules } : {}
5175
+ };
5176
+ }
5177
+ return { ...project, stage_bindings: bindings, skill_profiles: profiles };
5012
5178
  }
5013
- function resolveFlow(flow, override) {
5179
+ function resolveFlow(flow, project) {
5014
5180
  const preset2 = FLOW_PRESETS[flow];
5015
5181
  if (preset2 === void 0) {
5016
5182
  return { ok: false, code: "UNKNOWN_FLOW", flow, knownFlows: Object.keys(FLOW_PRESETS) };
5017
5183
  }
5018
- return { ok: true, config: mergeBindings(preset2.config, override?.stage_bindings), preset: preset2 };
5184
+ const { flow: _ignored, ...rest } = project ?? { flow };
5185
+ return { ok: true, config: applyProjectConfig(preset2.config, { flow, ...rest }), preset: preset2 };
5019
5186
  }
5020
5187
 
5021
5188
  // src/client/shared.ts
@@ -5025,30 +5192,296 @@ function describeError(error) {
5025
5192
  return "\u672A\u77E5\u9519\u8BEF";
5026
5193
  }
5027
5194
 
5028
- // src/client/TaskEngineSection.tsx
5195
+ // src/client/SkillRuleDialog.tsx
5196
+ var import_react2 = require("react");
5197
+ var import_dsh_client_ui_primitives2 = require("@deepseek-ai/dsh-client-ui-primitives");
5198
+
5199
+ // src/client/ResourceModal.tsx
5200
+ var import_react = require("react");
5201
+ var import_react_dom = require("react-dom");
5202
+ var import_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
5203
+ var rootStyle = {
5204
+ position: "fixed",
5205
+ inset: 0,
5206
+ zIndex: 1e3,
5207
+ display: "flex",
5208
+ alignItems: "center",
5209
+ justifyContent: "center",
5210
+ padding: 24
5211
+ };
5212
+ var maskStyle = {
5213
+ position: "absolute",
5214
+ inset: 0,
5215
+ background: "var(--dsw-alias-bg-mask-1)",
5216
+ backdropFilter: "var(--dsw-mask-blur)"
5217
+ };
5218
+ var dialogStyle = {
5219
+ position: "relative",
5220
+ zIndex: 1,
5221
+ display: "flex",
5222
+ flexDirection: "column",
5223
+ width: "min(760px, 100%)",
5224
+ maxHeight: "85vh",
5225
+ borderRadius: 24,
5226
+ background: "var(--dsw-alias-bg-layer-2)",
5227
+ boxShadow: "var(--dsw-elevation-prominent)",
5228
+ overflow: "hidden"
5229
+ };
5230
+ var drawerStyle = {
5231
+ ...dialogStyle,
5232
+ width: "min(560px, 100%)",
5233
+ height: "100%",
5234
+ maxHeight: "100%",
5235
+ borderRadius: "16px 0 0 16px"
5236
+ };
5237
+ var headerStyle = {
5238
+ display: "flex",
5239
+ alignItems: "center",
5240
+ justifyContent: "space-between",
5241
+ gap: 8,
5242
+ padding: "18px 18px 10px 24px",
5243
+ flex: "none"
5244
+ };
5245
+ var titleStyle = {
5246
+ margin: 0,
5247
+ fontSize: 16,
5248
+ lineHeight: "24px",
5249
+ fontWeight: 500,
5250
+ color: "var(--dsw-alias-label-primary)"
5251
+ };
5252
+ var closeBtnStyle = {
5253
+ flex: "none",
5254
+ display: "inline-flex",
5255
+ alignItems: "center",
5256
+ justifyContent: "center",
5257
+ width: 28,
5258
+ height: 28,
5259
+ border: "none",
5260
+ borderRadius: 8,
5261
+ background: "transparent",
5262
+ cursor: "pointer",
5263
+ color: "var(--dsw-alias-label-secondary)",
5264
+ padding: 0
5265
+ };
5266
+ var descStyle = {
5267
+ margin: 0,
5268
+ padding: "0 24px",
5269
+ fontSize: 13,
5270
+ lineHeight: "20px",
5271
+ color: "var(--dsw-alias-label-secondary)",
5272
+ flex: "none"
5273
+ };
5274
+ var bodyStyle = {
5275
+ flex: "1 1 auto",
5276
+ minHeight: 0,
5277
+ overflowY: "auto",
5278
+ padding: "16px 24px 4px",
5279
+ display: "flex",
5280
+ flexDirection: "column"
5281
+ };
5282
+ var footerStyle = {
5283
+ display: "flex",
5284
+ alignItems: "center",
5285
+ justifyContent: "flex-end",
5286
+ gap: 8,
5287
+ padding: "12px 24px 20px",
5288
+ flex: "none"
5289
+ };
5290
+ function ResourceModal({ title, description, onClose, footer, children, placement = "center" }) {
5291
+ const dialog = (0, import_react.useRef)(null);
5292
+ const closer = (0, import_react.useRef)(onClose);
5293
+ closer.current = onClose;
5294
+ (0, import_react.useEffect)(() => {
5295
+ const previous = document.activeElement;
5296
+ dialog.current?.focus();
5297
+ const onKey = (e) => {
5298
+ if (!dialog.current?.contains(document.activeElement)) return;
5299
+ if (e.key === "Escape") {
5300
+ e.preventDefault();
5301
+ e.stopPropagation();
5302
+ closer.current();
5303
+ return;
5304
+ }
5305
+ if (e.key !== "Tab") return;
5306
+ const nodes = Array.from(dialog.current.querySelectorAll('button:not(:disabled),input:not(:disabled):not([hidden]),select:not(:disabled),textarea:not(:disabled),[tabindex="0"]')).filter((el) => el.getClientRects().length);
5307
+ const first = nodes[0], last = nodes[nodes.length - 1];
5308
+ if (!first || !last) {
5309
+ e.preventDefault();
5310
+ return;
5311
+ }
5312
+ if (e.shiftKey && (document.activeElement === first || document.activeElement === dialog.current)) {
5313
+ e.preventDefault();
5314
+ last.focus();
5315
+ } else if (!e.shiftKey && (document.activeElement === last || document.activeElement === dialog.current)) {
5316
+ e.preventDefault();
5317
+ first.focus();
5318
+ }
5319
+ };
5320
+ document.addEventListener("keydown", onKey);
5321
+ return () => {
5322
+ document.removeEventListener("keydown", onKey);
5323
+ if (previous?.isConnected) previous.focus();
5324
+ };
5325
+ }, []);
5326
+ return (0, import_react_dom.createPortal)(
5327
+ (0, import_react.createElement)(
5328
+ "div",
5329
+ { style: placement === "right" ? { ...rootStyle, justifyContent: "flex-end", padding: 0 } : rootStyle, className: `te-modal${placement === "right" ? " te-drawer" : ""}`, role: "presentation" },
5330
+ (0, import_react.createElement)("div", { style: placement === "right" ? { ...maskStyle, background: "rgba(0, 0, 0, 0.18)" } : maskStyle, "aria-hidden": true, onClick: onClose }),
5331
+ (0, import_react.createElement)(
5332
+ "div",
5333
+ { style: placement === "right" ? drawerStyle : dialogStyle, ref: dialog, tabIndex: -1, role: "dialog", "aria-modal": true, "aria-label": title },
5334
+ (0, import_react.createElement)(
5335
+ "div",
5336
+ { style: headerStyle },
5337
+ (0, import_react.createElement)("h2", { style: titleStyle }, title),
5338
+ (0, import_react.createElement)(
5339
+ "button",
5340
+ { type: "button", style: closeBtnStyle, "aria-label": "\u5173\u95ED", onClick: onClose },
5341
+ (0, import_react.createElement)(import_dsh_client_ui_primitives.IconCloseOutline16, { size: 14 })
5342
+ )
5343
+ ),
5344
+ description !== void 0 && description !== "" ? (0, import_react.createElement)("p", { style: descStyle }, description) : null,
5345
+ (0, import_react.createElement)("div", { style: bodyStyle }, children),
5346
+ footer !== void 0 ? (0, import_react.createElement)("div", { style: footerStyle }, footer) : null
5347
+ )
5348
+ ),
5349
+ document.body
5350
+ );
5351
+ }
5352
+
5353
+ // src/client/SkillRuleDialog.tsx
5029
5354
  var import_jsx_runtime = require("react/jsx-runtime");
5355
+ function SkillRuleDialog({ skill, profile, rules, description, saveLabel, onSave, onClose }) {
5356
+ const [draftRules, setDraftRules] = (0, import_react2.useState)(profile?.rules ?? []);
5357
+ const [evidence, setEvidence] = (0, import_react2.useState)(profile?.evidence ?? "");
5358
+ const [query, setQuery] = (0, import_react2.useState)("");
5359
+ const [dirty, setDirty] = (0, import_react2.useState)(false);
5360
+ const [busy, setBusy] = (0, import_react2.useState)(false);
5361
+ const [error, setError] = (0, import_react2.useState)("");
5362
+ const close = () => {
5363
+ if (busy) return;
5364
+ if (dirty && !window.confirm("\u6280\u80FD\u89C4\u5219\u914D\u7F6E\u5C1A\u672A\u4FDD\u5B58\uFF0C\u786E\u5B9A\u653E\u5F03\u4FEE\u6539\uFF1F")) return;
5365
+ onClose();
5366
+ };
5367
+ const toggle = (rule) => {
5368
+ const key = formatResourceRef(rule);
5369
+ setDraftRules((previous) => previous.some((item) => formatResourceRef(item) === key) ? previous.filter((item) => formatResourceRef(item) !== key) : [...previous, rule].sort((a, b) => formatResourceRef(a).localeCompare(formatResourceRef(b))));
5370
+ setDirty(true);
5371
+ setError("");
5372
+ };
5373
+ const save2 = async () => {
5374
+ if (busy || !dirty) return;
5375
+ setBusy(true);
5376
+ setError("");
5377
+ try {
5378
+ await onSave({ rules: draftRules, ...evidence ? { evidence } : {} });
5379
+ } catch (failure) {
5380
+ setError(failure instanceof Error ? failure.message : "\u4FDD\u5B58\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u3002");
5381
+ } finally {
5382
+ setBusy(false);
5383
+ }
5384
+ };
5385
+ const filtered = rules.filter((rule) => {
5386
+ const key = formatResourceRef(rule.ref);
5387
+ const chosen = draftRules.some((item) => formatResourceRef(item) === key);
5388
+ return chosen || `${rule.name} ${rule.sourceLabel}`.toLowerCase().includes(query.trim().toLowerCase());
5389
+ });
5390
+ const catalogKeys = new Set(rules.map((rule) => formatResourceRef(rule.ref)));
5391
+ const missingRules = draftRules.filter((rule) => !catalogKeys.has(formatResourceRef(rule)));
5392
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
5393
+ ResourceModal,
5394
+ {
5395
+ placement: "right",
5396
+ title: `\u914D\u7F6E\u89C4\u5219 \xB7 ${skill.name}`,
5397
+ description: description ?? "\u89C4\u5219\u5C5E\u4E8E\u6280\u80FD\uFF1B\u6B64\u5904\u7684\u914D\u7F6E\u4F1A\u7528\u4E8E\u6240\u6709\u7ED1\u5B9A\u8BE5\u6280\u80FD\u7684\u8282\u70B9\u3002",
5398
+ onClose: close,
5399
+ footer: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
5400
+ error ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { role: "alert", className: "te-dialog-error", children: error }) : null,
5401
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives2.Button, { variant: "ghost", disabled: busy, onClick: close, children: "\u53D6\u6D88" }),
5402
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives2.Button, { variant: "primary", disabled: busy || !dirty, onClick: () => {
5403
+ void save2();
5404
+ }, children: busy ? "\u5904\u7406\u4E2D\u2026" : saveLabel ?? "\u4FDD\u5B58\u914D\u7F6E" })
5405
+ ] }),
5406
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "te-skill-config", children: [
5407
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "te-skill-evidence", children: [
5408
+ "\u5B8C\u6210\u51ED\u8BC1",
5409
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("select", { className: "te-input", "aria-label": "\u6280\u80FD\u5B8C\u6210\u51ED\u8BC1", value: evidence, onChange: (event) => {
5410
+ setEvidence(event.target.value);
5411
+ setDirty(true);
5412
+ }, children: [
5413
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "", children: "\u6CBF\u7528\u65E7\u914D\u7F6E\u9ED8\u8BA4\u503C" }),
5414
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "command", children: "\u547D\u4EE4\u6267\u884C\u8BB0\u5F55" }),
5415
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "artifact", children: "\u4EA7\u7269\u5185\u5BB9" }),
5416
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "review", children: "\u5BA1\u6838\u7ED3\u679C" }),
5417
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "manual", children: "\u4EBA\u5DE5\u786E\u8BA4" }),
5418
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "none", children: "\u65E0\u9700\u51ED\u8BC1" })
5419
+ ] })
5420
+ ] }),
5421
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "te-binding-heading", children: [
5422
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: "\u9002\u7528\u89C4\u5219" }),
5423
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "te-binding-count", children: [
5424
+ "\u5DF2\u9009 ",
5425
+ draftRules.length
5426
+ ] })
5427
+ ] }),
5428
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { className: "te-input", type: "search", "aria-label": "\u641C\u7D22\u89C4\u5219", placeholder: "\u641C\u7D22\u89C4\u5219\u540D\u79F0\u6216\u6765\u6E90", value: query, onChange: (event) => setQuery(event.target.value) }),
5429
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "te-skill-rule-list", role: "group", "aria-label": "\u89C4\u5219\u5217\u8868", children: [
5430
+ rules.length === 0 && missingRules.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "te-binding-empty", children: "\u89C4\u5219\u5E93\u4E3A\u7A7A\uFF0C\u8BF7\u5148\u5230\u201C\u89C4\u5219\u201D\u9875\u521B\u5EFA\u6216\u5B89\u88C5\u3002" }) : null,
5431
+ rules.length > 0 && filtered.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "te-binding-empty", children: "\u6CA1\u6709\u5339\u914D\u7684\u89C4\u5219\u3002" }) : null,
5432
+ missingRules.map((rule) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "te-skill-rule-row", children: [
5433
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "checkbox", checked: true, onChange: () => toggle(rule) }),
5434
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: rule.name }),
5435
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("small", { children: [
5436
+ rule.source,
5437
+ " \xB7 \u89C4\u5219\u6587\u4EF6\u672A\u627E\u5230"
5438
+ ] })
5439
+ ] }, formatResourceRef(rule))),
5440
+ filtered.map((rule) => {
5441
+ const key = formatResourceRef(rule.ref);
5442
+ const checked = draftRules.some((item) => formatResourceRef(item) === key);
5443
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "te-skill-rule-row", children: [
5444
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "checkbox", checked, onChange: () => toggle(rule.ref) }),
5445
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: rule.name }),
5446
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("small", { children: rule.sourceLabel })
5447
+ ] }, key);
5448
+ })
5449
+ ] })
5450
+ ] })
5451
+ }
5452
+ );
5453
+ }
5454
+
5455
+ // src/client/TaskEngineSection.tsx
5456
+ var import_jsx_runtime2 = require("react/jsx-runtime");
5030
5457
  function refFromText(text2) {
5031
5458
  return parseResourceRef(text2) ?? { source: "bundled", name: text2 };
5032
5459
  }
5033
- function resolvedConfig(flow, stageBindings) {
5034
- const resolved = resolveFlow(flow, { stage_bindings: stageBindings });
5460
+ function resolvedConfig(flow, stageBindings, skillProfiles) {
5461
+ const resolved = resolveFlow(flow, { flow, stage_bindings: stageBindings, skill_profiles: skillProfiles });
5035
5462
  return resolved.ok ? resolved.config : FLOW_PRESETS.standard.config;
5036
5463
  }
5037
5464
  function TaskEngineSection(props) {
5038
5465
  const { remote, workspace } = props;
5039
- const [flow, setFlow] = (0, import_react.useState)("standard");
5040
- const [stageBindings, setStageBindings] = (0, import_react.useState)({});
5041
- const [source, setSource] = (0, import_react.useState)("default");
5042
- const [savedAt, setSavedAt] = (0, import_react.useState)("");
5043
- const [dirty, setDirty] = (0, import_react.useState)(false);
5044
- const [loadError, setLoadError] = (0, import_react.useState)("");
5045
- const [saving, setSaving] = (0, import_react.useState)(false);
5046
- const [loading, setLoading] = (0, import_react.useState)(true);
5047
- const [loadAttempt, setLoadAttempt] = (0, import_react.useState)(0);
5048
- const [configProblems, setConfigProblems] = (0, import_react.useState)([]);
5049
- const [skills, setSkills] = (0, import_react.useState)([]);
5050
- const [rules, setRules] = (0, import_react.useState)([]);
5051
- (0, import_react.useEffect)(() => {
5466
+ const [flow, setFlow] = (0, import_react3.useState)("standard");
5467
+ const [stageBindings, setStageBindings] = (0, import_react3.useState)({});
5468
+ const [skillProfiles, setSkillProfiles] = (0, import_react3.useState)({});
5469
+ const [commitRule, setCommitRule] = (0, import_react3.useState)(void 0);
5470
+ const [artifacts, setArtifacts] = (0, import_react3.useState)(void 0);
5471
+ const [reviewDepth, setReviewDepth] = (0, import_react3.useState)(void 0);
5472
+ const [commitRequired, setCommitRequired] = (0, import_react3.useState)(void 0);
5473
+ const [source, setSource] = (0, import_react3.useState)("default");
5474
+ const [savedAt, setSavedAt] = (0, import_react3.useState)("");
5475
+ const [dirty, setDirty] = (0, import_react3.useState)(false);
5476
+ const [loadError, setLoadError] = (0, import_react3.useState)("");
5477
+ const [saving, setSaving] = (0, import_react3.useState)(false);
5478
+ const [loading, setLoading] = (0, import_react3.useState)(true);
5479
+ const [loadAttempt, setLoadAttempt] = (0, import_react3.useState)(0);
5480
+ const [configProblems, setConfigProblems] = (0, import_react3.useState)([]);
5481
+ const [skills, setSkills] = (0, import_react3.useState)([]);
5482
+ const [rules, setRules] = (0, import_react3.useState)([]);
5483
+ const [configuringSkill, setConfiguringSkill] = (0, import_react3.useState)(null);
5484
+ (0, import_react3.useEffect)(() => {
5052
5485
  if (workspace === "") return;
5053
5486
  let alive = true;
5054
5487
  setLoadError("");
@@ -5059,6 +5492,11 @@ function TaskEngineSection(props) {
5059
5492
  if (result.ok) {
5060
5493
  setFlow(result.value.flow);
5061
5494
  setStageBindings(result.value.config.stage_bindings ?? {});
5495
+ setSkillProfiles(result.value.config.skill_profiles ?? {});
5496
+ setCommitRule(result.value.config.commit);
5497
+ setArtifacts(result.value.config.artifacts);
5498
+ setReviewDepth(result.value.config.review_depth);
5499
+ setCommitRequired(result.value.config.commit_required);
5062
5500
  setSource(result.value.source);
5063
5501
  setConfigProblems(result.value.problems);
5064
5502
  setSavedAt("");
@@ -5075,7 +5513,7 @@ function TaskEngineSection(props) {
5075
5513
  alive = false;
5076
5514
  };
5077
5515
  }, [remote, workspace, loadAttempt]);
5078
- const refreshCatalogs = (0, import_react.useCallback)(() => {
5516
+ const refreshCatalogs = (0, import_react3.useCallback)(() => {
5079
5517
  if (workspace === "") return;
5080
5518
  void remote.listSkills(workspace).then((result) => {
5081
5519
  if (result.ok) setSkills(result.value.skills);
@@ -5086,55 +5524,88 @@ function TaskEngineSection(props) {
5086
5524
  }, () => {
5087
5525
  });
5088
5526
  }, [remote, workspace]);
5089
- (0, import_react.useEffect)(() => {
5527
+ (0, import_react3.useEffect)(() => {
5090
5528
  refreshCatalogs();
5091
5529
  }, [refreshCatalogs]);
5092
- const stages = (0, import_react.useMemo)(() => (FLOW_PRESETS[flow] ?? FLOW_PRESETS.standard).config.stages, [flow]);
5093
- const problems = (0, import_react.useMemo)(
5094
- () => validateWorkflow(resolvedConfig(flow, stageBindings)),
5095
- [flow, stageBindings]
5530
+ const stages = (0, import_react3.useMemo)(() => (FLOW_PRESETS[flow] ?? FLOW_PRESETS.standard).config.stages, [flow]);
5531
+ const problems = (0, import_react3.useMemo)(
5532
+ () => validateWorkflow(resolvedConfig(flow, stageBindings, skillProfiles)),
5533
+ [flow, stageBindings, skillProfiles]
5096
5534
  );
5097
5535
  const selectFlow = (id) => {
5098
5536
  if (id === flow) return;
5099
5537
  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;
5100
5538
  setFlow(id);
5101
- setStageBindings({ ...FLOW_PRESETS[id]?.config.stage_bindings ?? {} });
5102
5539
  setDirty(true);
5103
5540
  setSavedAt("");
5104
5541
  };
5542
+ const adopt = () => {
5543
+ const adopted = adoptRecommendation(flow);
5544
+ if (adopted === void 0) return;
5545
+ 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;
5546
+ setStageBindings({ ...adopted.stage_bindings ?? {} });
5547
+ const adoptedFlow = resolveFlow(flow, adopted);
5548
+ setSkillProfiles(adoptedFlow.ok ? adoptedFlow.config.skill_profiles ?? {} : {});
5549
+ setCommitRule(adopted.commit);
5550
+ setArtifacts(adopted.artifacts);
5551
+ setReviewDepth(adopted.review_depth);
5552
+ setDirty(true);
5553
+ setSavedAt("");
5554
+ };
5555
+ const updateSkillProfile = async (profile) => {
5556
+ if (!configuringSkill) return;
5557
+ const key = formatResourceRef(configuringSkill);
5558
+ const bindings = {};
5559
+ for (const [name, binding] of Object.entries(stageBindings)) {
5560
+ bindings[name] = { ...binding, skills: binding.skills?.map((entry) => formatResourceRef(entry.skill) === key ? { skill: entry.skill, rules: profile.rules, ...profile.evidence ? { evidence: profile.evidence } : {} } : entry) };
5561
+ }
5562
+ setStageBindings(bindings);
5563
+ setSkillProfiles({ ...skillProfiles, [key]: profile });
5564
+ setDirty(true);
5565
+ setSavedAt("");
5566
+ setConfiguringSkill(null);
5567
+ };
5105
5568
  if (loadError !== "") {
5106
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.wrap, children: [
5107
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { style: styles.title, children: "\u5DE5\u7A0B\u6D41\u7A0B\u914D\u7F6E" }),
5108
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.problems, children: [
5109
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: styles.problemsTitle, children: [
5110
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.StateDot, { state: "error" }),
5569
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles.wrap, children: [
5570
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h2", { style: styles.title, children: "\u5DE5\u7A0B\u6D41\u7A0B\u914D\u7F6E" }),
5571
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles.problems, children: [
5572
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { style: styles.problemsTitle, children: [
5573
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives3.StateDot, { state: "error" }),
5111
5574
  "\u8BFB\u53D6\u5931\u8D25"
5112
5575
  ] }),
5113
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.muted, children: loadError }),
5114
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { onClick: () => setLoadAttempt((n) => n + 1), children: "\u91CD\u8BD5" })
5576
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { style: styles.muted, children: loadError }),
5577
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives3.Button, { onClick: () => setLoadAttempt((n) => n + 1), children: "\u91CD\u8BD5" })
5115
5578
  ] })
5116
5579
  ] });
5117
5580
  }
5118
- if (loading) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { role: "status", children: "\u6B63\u5728\u8BFB\u53D6\u6D41\u7A0B\u914D\u7F6E\u2026" });
5119
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.wrap, children: [
5120
- configProblems.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { role: "alert", style: styles.problems, children: [
5581
+ if (loading) return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { role: "status", children: "\u6B63\u5728\u8BFB\u53D6\u6D41\u7A0B\u914D\u7F6E\u2026" });
5582
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles.wrap, children: [
5583
+ configProblems.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("p", { role: "alert", style: styles.problems, children: [
5121
5584
  "\u539F\u914D\u7F6E\u6709\u95EE\u9898\uFF1A",
5122
5585
  configProblems.join("\uFF1B"),
5123
5586
  "\u3002\u8BF7\u9009\u62E9\u6709\u6548\u9884\u8BBE\u5E76\u4FDD\u5B58\u4FEE\u590D\u3002"
5124
5587
  ] }),
5125
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.head, children: [
5126
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { style: styles.title, children: "\u5DE5\u7A0B\u6D41\u7A0B\u914D\u7F6E" }),
5127
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.muted, children: "\u9009\u4E00\u5957\u6D41\u7A0B\uFF0C\u518D\u7ED9\u6BCF\u4E2A\u8282\u70B9\u6302\u4E0A skill / rule\u3002\u9636\u6BB5\u6D41\u8F6C\u3001\u5B88\u536B\u3001\u63D0\u4EA4\u89C4\u5219\u90FD\u7531\u6D41\u7A0B\u9884\u8BBE\u56FA\u5316\uFF0C\u65E0\u9700\u624B\u5DE5\u914D\u7F6E\u3002" })
5588
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles.head, children: [
5589
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h2", { style: styles.title, children: "\u5DE5\u7A0B\u6D41\u7A0B\u914D\u7F6E" }),
5590
+ /* @__PURE__ */ (0, import_jsx_runtime2.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" })
5128
5591
  ] }),
5129
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.sourceRow, children: [
5130
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.StateDot, { state: source === "project" ? "done" : source === "invalid" ? "warning" : "ongoing" }),
5131
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.sourceText, children: sourceText(source) })
5592
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles.adoptRow, children: [
5593
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_dsh_client_ui_primitives3.Button, { size: "sm", onClick: adopt, children: [
5594
+ "\u91C7\u7528\u300C",
5595
+ FLOW_PRESETS[flow]?.label ?? flow,
5596
+ "\u300D\u7684\u63A8\u8350\u914D\u7F6E"
5597
+ ] }),
5598
+ /* @__PURE__ */ (0, import_jsx_runtime2.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" })
5599
+ ] }),
5600
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles.sourceRow, children: [
5601
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives3.StateDot, { state: source === "project" ? "done" : source === "invalid" ? "warning" : "ongoing" }),
5602
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: styles.sourceText, children: sourceText(source) })
5132
5603
  ] }),
5133
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.field, children: [
5134
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { children: "\u6D41\u7A0B\u9884\u8BBE" }),
5135
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.flowGrid, children: FLOW_OPTIONS.map((option) => {
5604
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles.field, children: [
5605
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { children: "\u6D41\u7A0B\u9884\u8BBE" }),
5606
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: styles.flowGrid, children: FLOW_OPTIONS.map((option) => {
5136
5607
  const active = flow === option.id;
5137
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
5608
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
5138
5609
  "button",
5139
5610
  {
5140
5611
  type: "button",
@@ -5144,45 +5615,49 @@ function TaskEngineSection(props) {
5144
5615
  },
5145
5616
  style: { ...styles.flowOption, ...active ? styles.flowOptionActive : {} },
5146
5617
  children: [
5147
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: styles.flowOptionTitle, children: [
5148
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.StateDot, { state: active ? "done" : "ongoing", size: 8 }),
5618
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { style: styles.flowOptionTitle, children: [
5619
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives3.StateDot, { state: active ? "done" : "ongoing", size: 8 }),
5149
5620
  option.label
5150
5621
  ] }),
5151
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.flowOptionDesc, children: option.description })
5622
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { style: styles.flowOptionDesc, children: option.description })
5152
5623
  ]
5153
5624
  },
5154
5625
  option.id
5155
5626
  );
5156
5627
  }) })
5157
5628
  ] }),
5158
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SectionCard, { icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconSettingsOutline16, { size: 16 }), title: "\u9636\u6BB5\u6280\u80FD / \u89C4\u5219", hint: "\u9009\u62E9\u8282\u70B9\uFF0C\u518D\u52FE\u9009\u9644\u52A0\u6280\u80FD\u4E0E\u89C4\u5219\u3002\u9884\u8BBE\u9ED8\u8BA4\u7ED1\u5B9A\u56FA\u5B9A\u4FDD\u7559\uFF1B\u65B0\u5EFA\u6216\u7F16\u8F91\u5185\u5BB9\u8BF7\u524D\u5F80\u4E0A\u65B9\u201C\u6280\u80FD\u201D\u6216\u201C\u89C4\u5219\u201D\u9875\u3002", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BindingEditor, { stages, defaults: (FLOW_PRESETS[flow] ?? FLOW_PRESETS.standard).config.stage_bindings ?? {}, stageBindings, setStageBindings: (next) => {
5629
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(SectionCard, { icon: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives3.IconSettingsOutline16, { size: 16 }), title: "\u9636\u6BB5\u6280\u80FD", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(BindingEditor, { stages, stageBindings, setStageBindings: (next) => {
5159
5630
  setStageBindings(next);
5160
5631
  setDirty(true);
5161
5632
  setSavedAt("");
5162
- }, skills, rules }) }),
5163
- problems.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.problems, children: [
5164
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: styles.problemsTitle, children: [
5165
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.StateDot, { state: "error" }),
5633
+ }, skillProfiles, setSkillProfiles: (next) => {
5634
+ setSkillProfiles(next);
5635
+ setDirty(true);
5636
+ setSavedAt("");
5637
+ }, skills, onConfigureSkill: setConfiguringSkill }) }),
5638
+ problems.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles.problems, children: [
5639
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { style: styles.problemsTitle, children: [
5640
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives3.StateDot, { state: "error" }),
5166
5641
  "\u6709 ",
5167
5642
  problems.length,
5168
5643
  " \u4E2A\u95EE\u9898\uFF08\u4FDD\u5B58\u4F1A\u88AB\u62D2\u7EDD\uFF09"
5169
5644
  ] }),
5170
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { style: styles.problemsList, children: problems.map((p) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("li", { children: p }, p)) })
5171
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: styles.okText, children: [
5172
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.StateDot, { state: "done" }),
5173
- source === "project" ? "\u914D\u7F6E\u6709\u6548" : "\u4F7F\u7528\u6D41\u7A0B\u9884\u8BBE\u9ED8\u8BA4\u7ED1\u5B9A\uFF08\u5C1A\u672A\u4FDD\u5B58\uFF09"
5645
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("ul", { style: styles.problemsList, children: problems.map((p) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("li", { children: p }, p)) })
5646
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { style: styles.okText, children: [
5647
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives3.StateDot, { state: "done" }),
5648
+ source === "project" ? "\u914D\u7F6E\u6709\u6548" : "\u4F7F\u7528\u7A7A\u767D\u6D41\u7A0B\u914D\u7F6E\uFF08\u5C1A\u672A\u4FDD\u5B58\uFF09"
5174
5649
  ] }),
5175
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.actions, children: [
5176
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
5177
- import_dsh_client_ui_primitives.Button,
5650
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles.actions, children: [
5651
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
5652
+ import_dsh_client_ui_primitives3.Button,
5178
5653
  {
5179
5654
  variant: "primary",
5180
5655
  size: "md",
5181
- icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconCheckOutline16, { size: 16 }),
5656
+ icon: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives3.IconCheckOutline16, { size: 16 }),
5182
5657
  disabled: problems.length > 0 || saving,
5183
5658
  onClick: () => {
5184
5659
  setSaving(true);
5185
- void save(remote, flow, stageBindings, workspace, setSavedAt, setSource).then((ok) => {
5660
+ void save(remote, { flow, stage_bindings: stageBindings, skill_profiles: skillProfiles, ...commitRule !== void 0 ? { commit: commitRule } : {}, ...artifacts !== void 0 ? { artifacts } : {}, ...reviewDepth !== void 0 ? { review_depth: reviewDepth } : {}, ...commitRequired !== void 0 ? { commit_required: commitRequired } : {} }, workspace, setSavedAt, setSource).then((ok) => {
5186
5661
  if (ok) {
5187
5662
  setConfigProblems([]);
5188
5663
  setDirty(false);
@@ -5192,11 +5667,24 @@ function TaskEngineSection(props) {
5192
5667
  children: saving ? "\u6B63\u5728\u4FDD\u5B58\u2026" : dirty ? "\u4FDD\u5B58\u5230 .dsh/eng.json" : "\u5DF2\u4FDD\u5B58 \xB7 \u65E0\u9700\u4FDD\u5B58"
5193
5668
  }
5194
5669
  ),
5195
- savedAt !== "" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: styles.okText, children: [
5196
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.StateDot, { state: savedAt.startsWith("\u5DF2") ? "done" : "error" }),
5670
+ savedAt !== "" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { style: styles.okText, children: [
5671
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives3.StateDot, { state: savedAt.startsWith("\u5DF2") ? "done" : "error" }),
5197
5672
  savedAt
5198
5673
  ] }) : null
5199
- ] })
5674
+ ] }),
5675
+ configuringSkill ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
5676
+ SkillRuleDialog,
5677
+ {
5678
+ skill: configuringSkill,
5679
+ profile: skillProfiles[formatResourceRef(configuringSkill)],
5680
+ rules,
5681
+ description: "\u89C4\u5219\u5C5E\u4E8E\u6280\u80FD\uFF0C\u6240\u6709\u5F15\u7528\u6B64\u6280\u80FD\u7684\u8282\u70B9\u90FD\u4F1A\u540C\u6B65\u3002\u5E94\u7528\u540E\u8BF7\u70B9\u51FB\u9875\u9762\u5E95\u90E8\u4FDD\u5B58\u3002",
5682
+ saveLabel: "\u5E94\u7528\u5230\u5F53\u524D\u914D\u7F6E",
5683
+ onSave: updateSkillProfile,
5684
+ onClose: () => setConfiguringSkill(null)
5685
+ },
5686
+ formatResourceRef(configuringSkill)
5687
+ ) : null
5200
5688
  ] });
5201
5689
  }
5202
5690
  function sourceText(source) {
@@ -5210,9 +5698,9 @@ function sourceText(source) {
5210
5698
  }
5211
5699
  }
5212
5700
  function SectionCard({ icon, title, hint, children }) {
5213
- const [open, setOpen] = (0, import_react.useState)(true);
5214
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.section, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
5215
- import_dsh_client_ui_primitives.DisclosureRow,
5701
+ const [open, setOpen] = (0, import_react3.useState)(true);
5702
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: styles.section, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
5703
+ import_dsh_client_ui_primitives3.DisclosureRow,
5216
5704
  {
5217
5705
  icon,
5218
5706
  title,
@@ -5224,125 +5712,120 @@ function SectionCard({ icon, title, hint, children }) {
5224
5712
  setOpen(!open);
5225
5713
  },
5226
5714
  keepContentWhenOpen: true,
5227
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.cardBody, children: [
5228
- hint !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.muted, children: hint }) : null,
5715
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles.cardBody, children: [
5716
+ hint !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { style: styles.muted, children: hint }) : null,
5229
5717
  children
5230
5718
  ] })
5231
5719
  }
5232
5720
  ) });
5233
5721
  }
5234
- function BindingEditor({ stages, defaults, stageBindings, setStageBindings, skills, rules }) {
5235
- const [stage, setStage] = (0, import_react.useState)(stages[0] ?? "");
5236
- const [expanded, setExpanded] = (0, import_react.useState)(null);
5722
+ function BindingEditor({ stages, stageBindings, setStageBindings, skillProfiles, setSkillProfiles, skills, onConfigureSkill }) {
5723
+ const [stage, setStage] = (0, import_react3.useState)(stages[0] ?? "");
5724
+ const [query, setQuery] = (0, import_react3.useState)("");
5237
5725
  const currentStage = stages.includes(stage) ? stage : stages[0] ?? "";
5238
5726
  const bindingFor = (name) => stageBindings[name] ?? {};
5239
- const presetSkills = (name) => defaults[name]?.skills ?? [];
5240
- const isPresetSkill = (name, raw) => presetSkills(name).some((entry) => formatResourceRef(entry.skill) === raw);
5241
5727
  const setSkills = (name, next) => {
5242
5728
  setStageBindings({ ...stageBindings, [name]: { ...bindingFor(name), skills: next } });
5243
5729
  };
5244
5730
  const toggleSkill = (raw) => {
5245
- if (currentStage === "" || isPresetSkill(currentStage, raw)) return;
5246
- const current = bindingFor(currentStage).skills ?? [];
5247
- const next = current.some((entry) => formatResourceRef(entry.skill) === raw) ? current.filter((entry) => formatResourceRef(entry.skill) !== raw) : [...current, { skill: refFromText(raw), rules: [] }].sort((a, b) => formatResourceRef(a.skill).localeCompare(formatResourceRef(b.skill)));
5248
- setSkills(currentStage, next);
5249
- };
5250
- const toggleRule = (skillRaw, ruleRaw) => {
5251
5731
  if (currentStage === "") return;
5252
5732
  const current = bindingFor(currentStage).skills ?? [];
5253
- setSkills(currentStage, current.map((entry) => {
5254
- if (formatResourceRef(entry.skill) !== skillRaw) return entry;
5255
- const has = entry.rules.some((rule) => formatResourceRef(rule) === ruleRaw);
5256
- const next = has ? entry.rules.filter((rule) => formatResourceRef(rule) !== ruleRaw) : [...entry.rules, refFromText(ruleRaw)].sort((a, b) => formatResourceRef(a).localeCompare(formatResourceRef(b)));
5257
- return { ...entry, rules: next };
5258
- }));
5733
+ const profile = skillProfiles[raw];
5734
+ const alreadyBound = current.some((entry) => formatResourceRef(entry.skill) === raw);
5735
+ const next = alreadyBound ? current.filter((entry) => formatResourceRef(entry.skill) !== raw) : [...current, { skill: refFromText(raw), rules: profile?.rules ?? [], ...profile?.evidence !== void 0 ? { evidence: profile.evidence } : {} }].sort((a, b) => formatResourceRef(a.skill).localeCompare(formatResourceRef(b.skill)));
5736
+ if (!alreadyBound && profile === void 0) setSkillProfiles({ ...skillProfiles, [raw]: { rules: [] } });
5737
+ setSkills(currentStage, next);
5259
5738
  };
5260
5739
  if (currentStage === "") {
5261
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.muted, children: "\u5F53\u524D\u6D41\u7A0B\u6CA1\u6709\u8282\u70B9\u3002" });
5740
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { style: styles.muted, children: "\u5F53\u524D\u6D41\u7A0B\u6CA1\u6709\u8282\u70B9\u3002" });
5262
5741
  }
5263
5742
  const boundSkills = bindingFor(currentStage).skills ?? [];
5264
5743
  const unassigned = bindingFor(currentStage).legacy_rules ?? [];
5265
- const presetCount = presetSkills(currentStage).length;
5266
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.section, children: [
5267
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.hint, children: "\u8282\u70B9\u53EA\u9009\u62E9\u6280\u80FD\uFF1B\u89C4\u5219\u5C5E\u4E8E\u6280\u80FD\u2014\u2014\u70B9\u5F00\u4E00\u4E2A\u6280\u80FD\u5C31\u80FD\u770B\u5230\u5B83\u5B8C\u6574\u7684\u89C4\u5219\u5217\u8868\uFF0C\u6302\u5230\u4EFB\u4F55\u8282\u70B9\u90FD\u662F\u540C\u4E00\u5957\u89C4\u5219\u3002 \u9700\u8981\u540C\u4E00\u6280\u80FD\u7528\u4E0D\u540C\u89C4\u5219\u65F6\uFF0C\u590D\u5236\u6210\u53E6\u4E00\u4E2A\u6280\u80FD\u518D\u5206\u522B\u914D\u7F6E\u3002" }),
5268
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.field, children: [
5269
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.bindingLabel, children: "\u9009\u62E9\u8282\u70B9" }),
5270
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.chips, children: stages.map((s) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Pill, { active: s === currentStage, onClick: () => {
5744
+ const boundKeys = new Set(boundSkills.map((entry) => formatResourceRef(entry.skill)));
5745
+ const needle = query.trim().toLowerCase();
5746
+ const available = skills.filter((entry) => !boundKeys.has(formatResourceRef(entry.ref)) && `${entry.name} ${entry.description} ${entry.sourceLabel}`.toLowerCase().includes(needle));
5747
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles.section, children: [
5748
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles.field, children: [
5749
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: styles.bindingLabel, children: "\u9009\u62E9\u8282\u70B9" }),
5750
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: styles.chips, children: stages.map((s) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives3.Pill, { active: s === currentStage, onClick: () => {
5271
5751
  setStage(s);
5272
5752
  }, children: s }, s)) })
5273
5753
  ] }),
5274
- unassigned.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "te-alert", children: [
5754
+ unassigned.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "te-alert", children: [
5275
5755
  "\u4EE5\u4E0B\u89C4\u5219\u5C5E\u4E8E",
5276
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: "\u8282\u70B9" }),
5756
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("strong", { children: "\u8282\u70B9" }),
5277
5757
  "\u800C\u4E0D\u662F\u4EFB\u4F55\u6280\u80FD\uFF08\u65E7\u914D\u7F6E\uFF09\uFF1A",
5278
5758
  unassigned.join("\u3001"),
5279
5759
  "\u3002 \u5B83\u4EEC\u4ECD\u7136\u751F\u6548\uFF0C\u4F46\u9700\u8981\u6307\u5B9A\u5F52\u5C5E\u2014\u2014\u628A\u6BCF\u6761\u89C4\u5219\u52A0\u5230\u4F60\u5E0C\u671B\u627F\u8F7D\u5B83\u7684\u6280\u80FD\u4E0B\uFF0C\u7136\u540E\u4ECE\u8FD9\u91CC\u79FB\u9664\uFF1B \u82E5\u540C\u4E00\u6280\u80FD\u5728\u4E0D\u540C\u8282\u70B9\u9700\u8981\u4E0D\u540C\u89C4\u5219\uFF0C\u8BF7\u590D\u5236\u8BE5\u6280\u80FD\u518D\u5206\u522B\u914D\u7F6E\u3002"
5280
5760
  ] }) : null,
5281
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "te-binding-grid", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "te-binding-picker", "aria-label": "\u6280\u80FD\u7ED1\u5B9A", children: [
5282
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "te-binding-heading", children: [
5283
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h4", { children: "\u6280\u80FD" }),
5284
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "te-binding-count", children: [
5285
- "\u5DF2\u9009 ",
5286
- boundSkills.length,
5287
- presetCount > 0 ? `\uFF08\u542B ${presetCount} \u9879\u9884\u8BBE\uFF09` : ""
5761
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "te-transfer", children: [
5762
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("section", { className: "te-transfer-pane", "aria-label": "\u53EF\u7528\u6280\u80FD", children: [
5763
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "te-binding-heading", children: [
5764
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h4", { children: "\u53EF\u7528\u6280\u80FD" }),
5765
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "te-binding-count", children: [
5766
+ skills.filter((entry) => !boundKeys.has(formatResourceRef(entry.ref))).length,
5767
+ " \u9879"
5768
+ ] })
5769
+ ] }),
5770
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("input", { className: "te-input te-transfer-search", type: "search", value: query, placeholder: "\u641C\u7D22\u6280\u80FD\u540D\u79F0\u6216\u8BF4\u660E", "aria-label": "\u641C\u7D22\u53EF\u7528\u6280\u80FD", onChange: (event) => setQuery(event.target.value) }),
5771
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "te-transfer-list", role: "group", "aria-label": "\u53EF\u7528\u6280\u80FD\u5217\u8868", children: [
5772
+ skills.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "te-binding-empty", children: "\u6682\u65E0\u6280\u80FD\uFF0C\u8BF7\u5148\u5728\u201C\u6280\u80FD\u201D\u9875\u6DFB\u52A0\u3002" }) : null,
5773
+ skills.length > 0 && available.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "te-binding-empty", children: "\u6CA1\u6709\u53EF\u6DFB\u52A0\u7684\u6280\u80FD\u3002" }) : null,
5774
+ available.map((entry) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("button", { type: "button", className: "te-transfer-row", onClick: () => toggleSkill(formatResourceRef(entry.ref)), "aria-label": `\u6DFB\u52A0\u6280\u80FD ${entry.name}`, children: [
5775
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "te-transfer-row-main", children: [
5776
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("strong", { children: entry.name }),
5777
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("small", { children: [
5778
+ entry.sourceLabel,
5779
+ entry.description ? ` \xB7 ${entry.description}` : ""
5780
+ ] })
5781
+ ] }),
5782
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "te-transfer-action", "aria-hidden": "true", children: "\uFF0B" })
5783
+ ] }, formatResourceRef(entry.ref)))
5288
5784
  ] })
5289
5785
  ] }),
5290
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "te-binding-list", role: "group", "aria-label": "\u6280\u80FD\u5217\u8868", tabIndex: 0, children: [
5291
- skills.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "te-binding-empty", children: "\u6682\u65E0\u6280\u80FD\uFF0C\u8BF7\u5728\u4E0A\u65B9\u201C\u6280\u80FD\u201D\u9875\u6DFB\u52A0\u3002" }) : null,
5292
- skills.map((entry) => {
5293
- const raw = formatResourceRef(entry.ref);
5294
- const bound = boundSkills.find((candidate) => formatResourceRef(candidate.skill) === raw);
5295
- const preset2 = isPresetSkill(currentStage, raw);
5296
- const open = expanded === raw;
5297
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: `te-binding-option${bound !== void 0 ? " is-selected" : ""}`, children: [
5298
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
5299
- "input",
5300
- {
5301
- type: "checkbox",
5302
- "aria-label": raw,
5303
- checked: bound !== void 0,
5304
- disabled: preset2,
5305
- onChange: () => toggleSkill(raw)
5306
- }
5307
- ),
5308
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "te-binding-detail", children: [
5309
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "te-binding-name", children: [
5310
- entry.name,
5311
- preset2 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "te-source-badge", children: "\u9884\u8BBE" }) : null
5312
- ] }),
5313
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "te-binding-meta", children: [
5314
- entry.sourceLabel,
5315
- " \xB7 ",
5316
- bound === void 0 ? "\u672A\u7ED1\u5B9A" : `${bound.rules.length} \u6761\u89C4\u5219`
5786
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "te-transfer-arrow", "aria-hidden": "true", children: "\u2192" }),
5787
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("section", { className: "te-transfer-pane", "aria-label": "\u5F53\u524D\u8282\u70B9\u6280\u80FD", children: [
5788
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "te-binding-heading", children: [
5789
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("h4", { children: [
5790
+ currentStage,
5791
+ " \xB7 \u5DF2\u7ED1\u5B9A"
5792
+ ] }),
5793
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "te-binding-count", children: [
5794
+ boundSkills.length,
5795
+ " \u9879"
5796
+ ] })
5797
+ ] }),
5798
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "te-transfer-caption", children: "\u89C4\u5219\u5C5E\u4E8E\u6280\u80FD\uFF1B\u70B9\u201C\u914D\u7F6E\u89C4\u5219\u201D\u5373\u53EF\u7EDF\u4E00\u4FEE\u6539\u3002" }),
5799
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "te-transfer-list", role: "group", "aria-label": "\u5DF2\u7ED1\u5B9A\u6280\u80FD\u5217\u8868", children: [
5800
+ boundSkills.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "te-binding-empty", children: "\u6B64\u8282\u70B9\u5C1A\u672A\u7ED1\u5B9A\u6280\u80FD\u3002\u70B9\u51FB\u5DE6\u4FA7 \uFF0B \u6DFB\u52A0\u3002" }) : null,
5801
+ boundSkills.map((entry) => {
5802
+ const raw = formatResourceRef(entry.skill);
5803
+ const catalog = skills.find((skill) => formatResourceRef(skill.ref) === raw);
5804
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "te-transfer-row is-bound", children: [
5805
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "te-transfer-row-main", children: [
5806
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("strong", { children: entry.skill.name }),
5807
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("small", { children: [
5808
+ catalog?.sourceLabel ?? entry.skill.source,
5809
+ " \xB7 ",
5810
+ entry.rules.length,
5811
+ " \u6761\u89C4\u5219",
5812
+ catalog ? "" : " \xB7 \u8D44\u6E90\u672A\u627E\u5230"
5813
+ ] })
5317
5814
  ] }),
5318
- bound !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "te-link", onClick: () => setExpanded(open ? null : raw), children: open ? "\u6536\u8D77\u89C4\u5219" : "\u89C4\u5219\u8BBE\u7F6E" }) : null,
5319
- open && bound !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "te-rule-list", children: [
5320
- rules.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "te-binding-meta", children: "\u89C4\u5219\u5E93\u4E3A\u7A7A\u3002" }) : null,
5321
- rules.map((rule) => {
5322
- const ruleRaw = formatResourceRef(rule.ref);
5323
- const on = bound.rules.some((candidate) => formatResourceRef(candidate) === ruleRaw);
5324
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "te-binding-filter", children: [
5325
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "checkbox", checked: on, onChange: () => toggleRule(raw, ruleRaw) }),
5326
- " ",
5327
- rule.name,
5328
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "te-binding-meta", children: [
5329
- "\uFF08",
5330
- rule.sourceLabel,
5331
- "\uFF09"
5332
- ] })
5333
- ] }, ruleRaw);
5334
- })
5335
- ] }) : null
5336
- ] })
5337
- ] }, raw);
5338
- })
5815
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "te-transfer-actions", children: [
5816
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", className: "te-transfer-config", onClick: () => onConfigureSkill(entry.skill), children: "\u914D\u7F6E\u89C4\u5219" }),
5817
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", className: "te-transfer-remove", onClick: () => toggleSkill(raw), "aria-label": `\u79FB\u9664\u6280\u80FD ${entry.skill.name}`, children: "\xD7" })
5818
+ ] })
5819
+ ] }, raw);
5820
+ })
5821
+ ] })
5339
5822
  ] })
5340
- ] }) }, currentStage)
5823
+ ] }, currentStage)
5341
5824
  ] });
5342
5825
  }
5343
- async function save(remote, flow, stageBindings, workspace, setSavedAt, setSource) {
5826
+ async function save(remote, config, workspace, setSavedAt, setSource) {
5344
5827
  try {
5345
- const result = await remote.write({ path: workspace, flow, stage_bindings: stageBindings });
5828
+ const result = await remote.write({ path: workspace, ...config });
5346
5829
  if (!result.ok) {
5347
5830
  setSavedAt("\u4FDD\u5B58\u5931\u8D25\uFF1A" + describeError(result.error));
5348
5831
  return false;
@@ -5361,8 +5844,8 @@ async function save(remote, flow, stageBindings, workspace, setSavedAt, setSourc
5361
5844
  }
5362
5845
 
5363
5846
  // src/client/InitPanel.tsx
5364
- var import_react2 = require("react");
5365
- var import_dsh_client_ui_primitives2 = require("@deepseek-ai/dsh-client-ui-primitives");
5847
+ var import_react4 = require("react");
5848
+ var import_dsh_client_ui_primitives4 = require("@deepseek-ai/dsh-client-ui-primitives");
5366
5849
  var MD_LABELS = { code: { copyLabel: "\u590D\u5236", copiedLabel: "\u5DF2\u590D\u5236" }, footnotes: "\u811A\u6CE8" };
5367
5850
  var INIT_TIMEOUT_S = 150;
5368
5851
  var card = {
@@ -5374,14 +5857,14 @@ var card = {
5374
5857
  padding: "12px 14px"
5375
5858
  };
5376
5859
  function InitPanel({ workspace, remote }) {
5377
- const [view, setView] = (0, import_react2.useState)(null);
5378
- const [generating, setGenerating] = (0, import_react2.useState)(false);
5379
- const [elapsed, setElapsed] = (0, import_react2.useState)(0);
5380
- const [draft, setDraft] = (0, import_react2.useState)(null);
5381
- const [editing, setEditing] = (0, import_react2.useState)(false);
5382
- const [body2, setBody] = (0, import_react2.useState)("");
5383
- const [msg, setMsg] = (0, import_react2.useState)("");
5384
- (0, import_react2.useEffect)(() => {
5860
+ const [view, setView] = (0, import_react4.useState)(null);
5861
+ const [generating, setGenerating] = (0, import_react4.useState)(false);
5862
+ const [elapsed, setElapsed] = (0, import_react4.useState)(0);
5863
+ const [draft, setDraft] = (0, import_react4.useState)(null);
5864
+ const [editing, setEditing] = (0, import_react4.useState)(false);
5865
+ const [body2, setBody] = (0, import_react4.useState)("");
5866
+ const [msg, setMsg] = (0, import_react4.useState)("");
5867
+ (0, import_react4.useEffect)(() => {
5385
5868
  if (!generating) {
5386
5869
  setElapsed(0);
5387
5870
  return;
@@ -5395,13 +5878,13 @@ function InitPanel({ workspace, remote }) {
5395
5878
  clearInterval(timer);
5396
5879
  };
5397
5880
  }, [generating]);
5398
- const refresh = (0, import_react2.useCallback)(() => {
5881
+ const refresh = (0, import_react4.useCallback)(() => {
5399
5882
  void remote.readInit(workspace).then((r) => {
5400
5883
  if (r.ok) setView(r.value);
5401
5884
  }, () => {
5402
5885
  });
5403
5886
  }, [remote, workspace]);
5404
- (0, import_react2.useEffect)(() => {
5887
+ (0, import_react4.useEffect)(() => {
5405
5888
  refresh();
5406
5889
  }, [refresh]);
5407
5890
  const generate = async () => {
@@ -5444,45 +5927,45 @@ function InitPanel({ workspace, remote }) {
5444
5927
  setMsg("");
5445
5928
  };
5446
5929
  const exists = view?.exists === true;
5447
- return (0, import_react2.createElement)(
5930
+ return (0, import_react4.createElement)(
5448
5931
  "div",
5449
5932
  { style: styles.section },
5450
- (0, import_react2.createElement)(
5933
+ (0, import_react4.createElement)(
5451
5934
  "div",
5452
5935
  { style: card },
5453
- (0, import_react2.createElement)(
5936
+ (0, import_react4.createElement)(
5454
5937
  "div",
5455
5938
  { style: { display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap" } },
5456
- (0, import_react2.createElement)(import_dsh_client_ui_primitives2.StateDot, { state: exists ? "done" : "ongoing" }),
5457
- (0, import_react2.createElement)("span", { style: styles.bindingLabel }, exists ? `\u5DF2\u521D\u59CB\u5316 \xB7 ${view.lines} \u884C\uFF08\u4E0A\u9650 200\uFF09` : "\u672A\u521D\u59CB\u5316"),
5458
- view?.path !== void 0 ? (0, import_react2.createElement)("span", { style: styles.sourceBadge }, `\u5DF2\u5B9A\u4F4D\u5230 ${view.path}`) : null
5939
+ (0, import_react4.createElement)(import_dsh_client_ui_primitives4.StateDot, { state: exists ? "done" : "ongoing" }),
5940
+ (0, import_react4.createElement)("span", { style: styles.bindingLabel }, exists ? `\u5DF2\u521D\u59CB\u5316 \xB7 ${view.lines} \u884C\uFF08\u4E0A\u9650 200\uFF09` : "\u672A\u521D\u59CB\u5316"),
5941
+ view?.path !== void 0 ? (0, import_react4.createElement)("span", { style: styles.sourceBadge }, `\u5DF2\u5B9A\u4F4D\u5230 ${view.path}`) : null
5459
5942
  ),
5460
- (0, import_react2.createElement)(
5943
+ (0, import_react4.createElement)(
5461
5944
  "p",
5462
5945
  { style: styles.muted },
5463
5946
  "\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"
5464
5947
  ),
5465
- exists && !editing && draft === null ? (0, import_react2.createElement)(
5948
+ exists && !editing && draft === null ? (0, import_react4.createElement)(
5466
5949
  "div",
5467
5950
  { style: styles.mdPreview },
5468
- (0, import_react2.createElement)(import_dsh_client_ui_primitives2.MarkdownText, { text: view.content, labels: MD_LABELS })
5951
+ (0, import_react4.createElement)(import_dsh_client_ui_primitives4.MarkdownText, { text: view.content, labels: MD_LABELS })
5469
5952
  ) : null,
5470
- draft !== null ? (0, import_react2.createElement)(
5953
+ draft !== null ? (0, import_react4.createElement)(
5471
5954
  "div",
5472
5955
  { style: styles.section },
5473
- (0, import_react2.createElement)(
5956
+ (0, import_react4.createElement)(
5474
5957
  "div",
5475
5958
  { style: styles.sourceRow },
5476
- (0, import_react2.createElement)(import_dsh_client_ui_primitives2.StateDot, { state: "ongoing", size: 8 }),
5477
- (0, import_react2.createElement)("span", { style: styles.sourceBadge }, `AI \u8349\u7A3F \xB7 ${draft.lines} \u884C \xB7 \u5C1A\u672A\u5199\u5165`)
5959
+ (0, import_react4.createElement)(import_dsh_client_ui_primitives4.StateDot, { state: "ongoing", size: 8 }),
5960
+ (0, import_react4.createElement)("span", { style: styles.sourceBadge }, `AI \u8349\u7A3F \xB7 ${draft.lines} \u884C \xB7 \u5C1A\u672A\u5199\u5165`)
5478
5961
  ),
5479
- (0, import_react2.createElement)(
5962
+ (0, import_react4.createElement)(
5480
5963
  "div",
5481
5964
  { style: styles.mdPreview },
5482
- (0, import_react2.createElement)(import_dsh_client_ui_primitives2.MarkdownText, { text: draft.content, labels: MD_LABELS })
5965
+ (0, import_react4.createElement)(import_dsh_client_ui_primitives4.MarkdownText, { text: draft.content, labels: MD_LABELS })
5483
5966
  )
5484
5967
  ) : null,
5485
- editing ? (0, import_react2.createElement)("textarea", {
5968
+ editing ? (0, import_react4.createElement)("textarea", {
5486
5969
  style: { ...styles.textarea, minHeight: 300 },
5487
5970
  placeholder: "AGENTS.md \u6B63\u6587\uFF08Markdown\uFF0C\u2264200 \u884C\uFF09",
5488
5971
  value: body2,
@@ -5490,16 +5973,16 @@ function InitPanel({ workspace, remote }) {
5490
5973
  setBody(ev.target.value);
5491
5974
  }
5492
5975
  }) : null,
5493
- generating ? (0, import_react2.createElement)(
5976
+ generating ? (0, import_react4.createElement)(
5494
5977
  "p",
5495
5978
  { style: styles.status },
5496
5979
  `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`
5497
5980
  ) : null,
5498
- msg !== "" ? (0, import_react2.createElement)("p", { style: styles.status }, msg) : null,
5499
- draft !== null ? (0, import_react2.createElement)(
5981
+ msg !== "" ? (0, import_react4.createElement)("p", { style: styles.status }, msg) : null,
5982
+ draft !== null ? (0, import_react4.createElement)(
5500
5983
  "div",
5501
5984
  { style: styles.row },
5502
- (0, import_react2.createElement)(import_dsh_client_ui_primitives2.Button, {
5985
+ (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, {
5503
5986
  variant: "primary",
5504
5987
  size: "md",
5505
5988
  disabled: draft.lines > 200,
@@ -5508,14 +5991,14 @@ function InitPanel({ workspace, remote }) {
5508
5991
  void write(draft.content, exists);
5509
5992
  }
5510
5993
  }, exists ? "\u4FDD\u5B58\u5E76\u8986\u76D6" : "\u4FDD\u5B58"),
5511
- draft.lines > 200 ? (0, import_react2.createElement)("span", { style: styles.sourceBadge }, `\u8349\u7A3F ${draft.lines} \u884C\u8D85\u9650\uFF0C\u8BF7\u70B9\u300C\u653E\u5F03\u300D\u540E\u91CD\u8BD5`) : null,
5512
- (0, import_react2.createElement)(import_dsh_client_ui_primitives2.Button, { variant: "ghost", size: "md", onClick: () => {
5994
+ draft.lines > 200 ? (0, import_react4.createElement)("span", { style: styles.sourceBadge }, `\u8349\u7A3F ${draft.lines} \u884C\u8D85\u9650\uFF0C\u8BF7\u70B9\u300C\u653E\u5F03\u300D\u540E\u91CD\u8BD5`) : null,
5995
+ (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "ghost", size: "md", onClick: () => {
5513
5996
  setDraft(null);
5514
5997
  } }, "\u653E\u5F03")
5515
- ) : editing ? (0, import_react2.createElement)(
5998
+ ) : editing ? (0, import_react4.createElement)(
5516
5999
  "div",
5517
6000
  { style: styles.row },
5518
- (0, import_react2.createElement)(import_dsh_client_ui_primitives2.Button, {
6001
+ (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, {
5519
6002
  variant: "primary",
5520
6003
  size: "md",
5521
6004
  disabled: body2.trim() === "",
@@ -5524,13 +6007,13 @@ function InitPanel({ workspace, remote }) {
5524
6007
  void write(body2, exists);
5525
6008
  }
5526
6009
  }, exists ? "\u4FDD\u5B58\u5E76\u8986\u76D6" : "\u4FDD\u5B58"),
5527
- (0, import_react2.createElement)(import_dsh_client_ui_primitives2.Button, { variant: "ghost", size: "md", onClick: () => {
6010
+ (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "ghost", size: "md", onClick: () => {
5528
6011
  setEditing(false);
5529
6012
  } }, "\u53D6\u6D88")
5530
- ) : (0, import_react2.createElement)(
6013
+ ) : (0, import_react4.createElement)(
5531
6014
  "div",
5532
6015
  { style: styles.row },
5533
- (0, import_react2.createElement)(import_dsh_client_ui_primitives2.Button, {
6016
+ (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, {
5534
6017
  variant: "primary",
5535
6018
  size: "md",
5536
6019
  disabled: generating,
@@ -5539,203 +6022,54 @@ function InitPanel({ workspace, remote }) {
5539
6022
  void generate();
5540
6023
  }
5541
6024
  }, exists ? "\u91CD\u65B0\u521D\u59CB\u5316\uFF08AI \u626B\u63CF\u8986\u76D6\uFF09" : "\u8BA9 AI \u521D\u59CB\u5316"),
5542
- exists ? (0, import_react2.createElement)(import_dsh_client_ui_primitives2.Button, { variant: "outline", size: "md", onClick: startEdit }, "\u624B\u52A8\u7F16\u8F91") : null
6025
+ exists ? (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "outline", size: "md", onClick: startEdit }, "\u624B\u52A8\u7F16\u8F91") : null
5543
6026
  )
5544
6027
  )
5545
6028
  );
5546
6029
  }
5547
6030
 
5548
6031
  // src/client/SkillManager.tsx
5549
- var import_react5 = require("react");
5550
-
5551
- // src/client/ResourceManager.tsx
5552
- var import_react4 = require("react");
5553
- var import_dsh_client_ui_primitives4 = require("@deepseek-ai/dsh-client-ui-primitives");
5554
-
5555
- // src/client/ResourceModal.tsx
5556
- var import_react3 = require("react");
5557
- var import_react_dom = require("react-dom");
5558
- var import_dsh_client_ui_primitives3 = require("@deepseek-ai/dsh-client-ui-primitives");
5559
- var rootStyle = {
5560
- position: "fixed",
5561
- inset: 0,
5562
- zIndex: 1e3,
5563
- display: "flex",
5564
- alignItems: "center",
5565
- justifyContent: "center",
5566
- padding: 24
5567
- };
5568
- var maskStyle = {
5569
- position: "absolute",
5570
- inset: 0,
5571
- background: "var(--dsw-alias-bg-mask-1)",
5572
- backdropFilter: "var(--dsw-mask-blur)"
5573
- };
5574
- var dialogStyle = {
5575
- position: "relative",
5576
- zIndex: 1,
5577
- display: "flex",
5578
- flexDirection: "column",
5579
- width: "min(760px, 100%)",
5580
- maxHeight: "85vh",
5581
- borderRadius: 24,
5582
- background: "var(--dsw-alias-bg-layer-2)",
5583
- boxShadow: "var(--dsw-elevation-prominent)",
5584
- overflow: "hidden"
5585
- };
5586
- var headerStyle = {
5587
- display: "flex",
5588
- alignItems: "center",
5589
- justifyContent: "space-between",
5590
- gap: 8,
5591
- padding: "18px 18px 10px 24px",
5592
- flex: "none"
5593
- };
5594
- var titleStyle = {
5595
- margin: 0,
5596
- fontSize: 16,
5597
- lineHeight: "24px",
5598
- fontWeight: 500,
5599
- color: "var(--dsw-alias-label-primary)"
5600
- };
5601
- var closeBtnStyle = {
5602
- flex: "none",
5603
- display: "inline-flex",
5604
- alignItems: "center",
5605
- justifyContent: "center",
5606
- width: 28,
5607
- height: 28,
5608
- border: "none",
5609
- borderRadius: 8,
5610
- background: "transparent",
5611
- cursor: "pointer",
5612
- color: "var(--dsw-alias-label-secondary)",
5613
- padding: 0
5614
- };
5615
- var descStyle = {
5616
- margin: 0,
5617
- padding: "0 24px",
5618
- fontSize: 13,
5619
- lineHeight: "20px",
5620
- color: "var(--dsw-alias-label-secondary)",
5621
- flex: "none"
5622
- };
5623
- var bodyStyle = {
5624
- flex: "1 1 auto",
5625
- minHeight: 0,
5626
- overflowY: "auto",
5627
- padding: "16px 24px 4px",
5628
- display: "flex",
5629
- flexDirection: "column"
5630
- };
5631
- var footerStyle = {
5632
- display: "flex",
5633
- alignItems: "center",
5634
- justifyContent: "flex-end",
5635
- gap: 8,
5636
- padding: "12px 24px 20px",
5637
- flex: "none"
5638
- };
5639
- function ResourceModal({ title, description, onClose, footer, children }) {
5640
- const dialog = (0, import_react3.useRef)(null);
5641
- const closer = (0, import_react3.useRef)(onClose);
5642
- closer.current = onClose;
5643
- (0, import_react3.useEffect)(() => {
5644
- const previous = document.activeElement;
5645
- dialog.current?.focus();
5646
- const onKey = (e) => {
5647
- if (!dialog.current?.contains(document.activeElement)) return;
5648
- if (e.key === "Escape") {
5649
- e.preventDefault();
5650
- e.stopPropagation();
5651
- closer.current();
5652
- return;
5653
- }
5654
- if (e.key !== "Tab") return;
5655
- const nodes = Array.from(dialog.current.querySelectorAll('button:not(:disabled),input:not(:disabled):not([hidden]),select:not(:disabled),textarea:not(:disabled),[tabindex="0"]')).filter((el) => el.getClientRects().length);
5656
- const first = nodes[0], last = nodes[nodes.length - 1];
5657
- if (!first || !last) {
5658
- e.preventDefault();
5659
- return;
5660
- }
5661
- if (e.shiftKey && (document.activeElement === first || document.activeElement === dialog.current)) {
5662
- e.preventDefault();
5663
- last.focus();
5664
- } else if (!e.shiftKey && (document.activeElement === last || document.activeElement === dialog.current)) {
5665
- e.preventDefault();
5666
- first.focus();
5667
- }
5668
- };
5669
- document.addEventListener("keydown", onKey);
5670
- return () => {
5671
- document.removeEventListener("keydown", onKey);
5672
- if (previous?.isConnected) previous.focus();
5673
- };
5674
- }, []);
5675
- return (0, import_react_dom.createPortal)(
5676
- (0, import_react3.createElement)(
5677
- "div",
5678
- { style: rootStyle, className: "te-modal", role: "presentation" },
5679
- (0, import_react3.createElement)("div", { style: maskStyle, "aria-hidden": true, onClick: onClose }),
5680
- (0, import_react3.createElement)(
5681
- "div",
5682
- { style: dialogStyle, ref: dialog, tabIndex: -1, role: "dialog", "aria-modal": true, "aria-label": title },
5683
- (0, import_react3.createElement)(
5684
- "div",
5685
- { style: headerStyle },
5686
- (0, import_react3.createElement)("h2", { style: titleStyle }, title),
5687
- (0, import_react3.createElement)(
5688
- "button",
5689
- { type: "button", style: closeBtnStyle, "aria-label": "\u5173\u95ED", onClick: onClose },
5690
- (0, import_react3.createElement)(import_dsh_client_ui_primitives3.IconCloseOutline16, { size: 14 })
5691
- )
5692
- ),
5693
- description !== void 0 && description !== "" ? (0, import_react3.createElement)("p", { style: descStyle }, description) : null,
5694
- (0, import_react3.createElement)("div", { style: bodyStyle }, children),
5695
- footer !== void 0 ? (0, import_react3.createElement)("div", { style: footerStyle }, footer) : null
5696
- )
5697
- ),
5698
- document.body
5699
- );
5700
- }
6032
+ var import_react6 = require("react");
5701
6033
 
5702
6034
  // src/client/ResourceManager.tsx
6035
+ var import_react5 = require("react");
6036
+ var import_dsh_client_ui_primitives5 = require("@deepseek-ai/dsh-client-ui-primitives");
5703
6037
  var labels = { code: { copyLabel: "\u590D\u5236", copiedLabel: "\u5DF2\u590D\u5236" }, footnotes: "\u811A\u6CE8" };
5704
6038
  var levelOf = (row) => row.source === "bundled" ? "bundled" : row.source.startsWith("user") ? "user" : "project";
5705
6039
  var sourceText2 = (source) => source === "bundled" ? "\u5185\u7F6E" : source.startsWith("user") ? "\u4E2A\u4EBA" : "\u9879\u76EE";
5706
6040
  var sizeText = (bytes) => bytes < 1024 ? `${bytes} B` : bytes < 1024 * 1024 ? `${(bytes / 1024).toFixed(1)} KB` : `${(bytes / 1024 / 1024).toFixed(1)} MB`;
5707
6041
  var fail = (r) => describeError(r.error ?? "\u64CD\u4F5C\u5931\u8D25");
5708
- function ResourceManager({ workspace, remote, kind }) {
6042
+ function ResourceManager({ workspace, remote, kind, onConfigureSkill }) {
5709
6043
  const noun = kind === "skill" ? "\u6280\u80FD" : "\u89C4\u5219";
5710
- const [rows, setRows] = (0, import_react4.useState)([]);
5711
- const [query, setQuery] = (0, import_react4.useState)("");
5712
- const [filter, setFilter] = (0, import_react4.useState)("all");
5713
- const [notice, setNotice] = (0, import_react4.useState)("");
5714
- const [error, setError] = (0, import_react4.useState)("");
5715
- const [loading, setLoading] = (0, import_react4.useState)(true);
5716
- const [revision, refresh] = (0, import_react4.useState)(0);
5717
- const [busy, setBusy] = (0, import_react4.useState)(false);
5718
- const [roots, setRoots] = (0, import_react4.useState)(null);
5719
- const [importing, setImporting] = (0, import_react4.useState)(false);
5720
- const [request, setRequest] = (0, import_react4.useState)(null);
5721
- const [preview, setPreview] = (0, import_react4.useState)(null);
5722
- const [level, setLevel] = (0, import_react4.useState)("project");
5723
- const [manual, setManual] = (0, import_react4.useState)(false);
5724
- const [sourceDir, setSourceDir] = (0, import_react4.useState)("");
5725
- const [dirs, setDirs] = (0, import_react4.useState)([]);
5726
- const [browsePath, setBrowsePath] = (0, import_react4.useState)("");
5727
- const [editing, setEditing] = (0, import_react4.useState)(null);
5728
- const [viewing, setViewing] = (0, import_react4.useState)(false);
5729
- const [name, setName] = (0, import_react4.useState)("");
5730
- const [description, setDescription] = (0, import_react4.useState)("");
5731
- const [whenToUse, setWhenToUse] = (0, import_react4.useState)("");
5732
- const [body2, setBody] = (0, import_react4.useState)("");
5733
- const [deleting, setDeleting] = (0, import_react4.useState)(null);
5734
- const input = (0, import_react4.useRef)(null);
5735
- const fileEpoch = (0, import_react4.useRef)(0);
5736
- const browseEpoch = (0, import_react4.useRef)(0);
6044
+ const [rows, setRows] = (0, import_react5.useState)([]);
6045
+ const [query, setQuery] = (0, import_react5.useState)("");
6046
+ const [filter, setFilter] = (0, import_react5.useState)("all");
6047
+ const [notice, setNotice] = (0, import_react5.useState)("");
6048
+ const [error, setError] = (0, import_react5.useState)("");
6049
+ const [loading, setLoading] = (0, import_react5.useState)(true);
6050
+ const [revision, refresh] = (0, import_react5.useState)(0);
6051
+ const [busy, setBusy] = (0, import_react5.useState)(false);
6052
+ const [roots, setRoots] = (0, import_react5.useState)(null);
6053
+ const [importing, setImporting] = (0, import_react5.useState)(false);
6054
+ const [request, setRequest] = (0, import_react5.useState)(null);
6055
+ const [preview, setPreview] = (0, import_react5.useState)(null);
6056
+ const [level, setLevel] = (0, import_react5.useState)("project");
6057
+ const [manual, setManual] = (0, import_react5.useState)(false);
6058
+ const [sourceDir, setSourceDir] = (0, import_react5.useState)("");
6059
+ const [dirs, setDirs] = (0, import_react5.useState)([]);
6060
+ const [browsePath, setBrowsePath] = (0, import_react5.useState)("");
6061
+ const [editing, setEditing] = (0, import_react5.useState)(null);
6062
+ const [viewing, setViewing] = (0, import_react5.useState)(false);
6063
+ const [name, setName] = (0, import_react5.useState)("");
6064
+ const [description, setDescription] = (0, import_react5.useState)("");
6065
+ const [whenToUse, setWhenToUse] = (0, import_react5.useState)("");
6066
+ const [body2, setBody] = (0, import_react5.useState)("");
6067
+ const [deleting, setDeleting] = (0, import_react5.useState)(null);
6068
+ const input = (0, import_react5.useRef)(null);
6069
+ const fileEpoch = (0, import_react5.useRef)(0);
6070
+ const browseEpoch = (0, import_react5.useRef)(0);
5737
6071
  const readonly = editing !== null && editing !== "new" && levelOf(editing) === "bundled";
5738
- (0, import_react4.useEffect)(() => {
6072
+ (0, import_react5.useEffect)(() => {
5739
6073
  let active = true;
5740
6074
  setLoading(true);
5741
6075
  setRows([]);
@@ -5762,7 +6096,7 @@ function ResourceManager({ workspace, remote, kind }) {
5762
6096
  fileEpoch.current++;
5763
6097
  };
5764
6098
  }, [workspace, remote, kind, revision]);
5765
- (0, import_react4.useEffect)(() => {
6099
+ (0, import_react5.useEffect)(() => {
5766
6100
  let active = true;
5767
6101
  setPreview(null);
5768
6102
  if (!request) return;
@@ -5926,105 +6260,163 @@ function ResourceManager({ workspace, remote, kind }) {
5926
6260
  setBusy(false);
5927
6261
  }
5928
6262
  };
5929
- const status = () => error ? (0, import_react4.createElement)("div", { className: "te-alert", role: "alert" }, error) : null;
5930
- const targets = () => (0, import_react4.createElement)(
6263
+ const status = () => error ? (0, import_react5.createElement)("div", { className: "te-alert", role: "alert" }, error) : null;
6264
+ const targets = () => (0, import_react5.createElement)(
5931
6265
  "div",
5932
6266
  { className: "te-targets" },
5933
- ...["project", "user"].map((lvl) => (0, import_react4.createElement)(
6267
+ ...["project", "user"].map((lvl) => (0, import_react5.createElement)(
5934
6268
  "button",
5935
6269
  { type: "button", key: lvl, className: `te-target ${level === lvl ? "selected" : ""}`, "aria-pressed": level === lvl, disabled: busy || editing !== null && editing !== "new", onClick: () => {
5936
6270
  setPreview(null);
5937
6271
  setLevel(lvl);
5938
6272
  } },
5939
- (0, import_react4.createElement)("strong", null, lvl === "project" ? "\u9879\u76EE\u5171\u4EAB" : "\u4E2A\u4EBA\u5168\u5C40"),
5940
- (0, import_react4.createElement)("small", null, lvl === "project" ? "\u4EC5\u5F53\u524D\u5DE5\u4F5C\u533A\u4F7F\u7528" : "\u6B64\u4E3B\u673A\u4E0A\u7684\u6240\u6709\u9879\u76EE\u53EF\u7528")
6273
+ (0, import_react5.createElement)("strong", null, lvl === "project" ? "\u9879\u76EE\u5171\u4EAB" : "\u4E2A\u4EBA\u5168\u5C40"),
6274
+ (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")
5941
6275
  )),
5942
- (0, import_react4.createElement)("code", { className: "te-path" }, roots?.[level] ?? (level === "project" ? `${workspace}/.dsh/${kind}s` : `DSH_HOME/${kind}s`))
6276
+ (0, import_react5.createElement)("code", { className: "te-path" }, roots?.[level] ?? (level === "project" ? `${workspace}/.dsh/${kind}s` : `DSH_HOME/${kind}s`))
5943
6277
  );
5944
6278
  const visible = rows.filter((r) => `${r.name} ${r.description ?? ""}`.toLowerCase().includes(query.toLowerCase()) && (filter === "all" || levelOf(r) === filter));
5945
- return (0, import_react4.createElement)(
6279
+ return (0, import_react5.createElement)(
5946
6280
  "section",
5947
6281
  { className: "te-resource" },
5948
- (0, import_react4.createElement)("input", { type: "file", ref: input, hidden: true, "aria-label": kind === "skill" ? "\u9009\u62E9\u6280\u80FD\u6587\u4EF6\u5939" : "\u9009\u62E9\u89C4\u5219\u6587\u4EF6", ...kind === "skill" ? { webkitdirectory: "", multiple: true } : { accept: ".md,text/markdown" }, onChange: (e) => {
6282
+ (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) => {
5949
6283
  void selected(Array.from(e.target.files ?? []));
5950
6284
  } }),
5951
- (0, import_react4.createElement)("div", { className: "te-section-heading" }, (0, import_react4.createElement)("div", null, (0, import_react4.createElement)("h2", null, `${noun}\u5E93`), (0, import_react4.createElement)("p", null, kind === "skill" ? "\u628A\u53EF\u590D\u7528\u7684\u5DE5\u4F5C\u65B9\u6CD5\u5E26\u5165\u9879\u76EE\u3002" : "\u4E3A\u9879\u76EE\u660E\u786E\u7EA6\u5B9A\uFF0C\u8BA9\u6BCF\u6B21\u4EA4\u4ED8\u4FDD\u6301\u4E00\u81F4\u3002")), (0, import_react4.createElement)("div", { className: "te-actions" }, (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "outline", onClick: () => {
6285
+ (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_primitives5.Button, { variant: "outline", onClick: () => {
5952
6286
  void edit("new");
5953
- } }, `\u65B0\u5EFA${noun}`), (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "primary", onClick: choose }, `\u5B89\u88C5${noun}`))),
5954
- (0, import_react4.createElement)("div", { className: "te-toolbar" }, (0, import_react4.createElement)("input", { className: "te-input", placeholder: `\u641C\u7D22${noun}\u540D\u79F0${kind === "skill" ? "\u6216\u63CF\u8FF0" : ""}`, value: query, onChange: (e) => setQuery(e.target.value) }), (0, import_react4.createElement)("select", { className: "te-input", "aria-label": "\u7B5B\u9009\u6765\u6E90", value: filter, onChange: (e) => setFilter(e.target.value) }, (0, import_react4.createElement)("option", { value: "all" }, `\u5168\u90E8\u6765\u6E90 \xB7 ${rows.length}`), (0, import_react4.createElement)("option", { value: "bundled" }, "\u5185\u7F6E"), (0, import_react4.createElement)("option", { value: "project" }, "\u9879\u76EE"), (0, import_react4.createElement)("option", { value: "user" }, "\u4E2A\u4EBA")), (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "ghost", onClick: () => refresh((n) => n + 1), disabled: loading }, "\u5237\u65B0")),
5955
- notice ? (0, import_react4.createElement)("div", { className: "te-success", role: "status" }, notice) : null,
6287
+ } }, `\u65B0\u5EFA${noun}`), (0, import_react5.createElement)(import_dsh_client_ui_primitives5.Button, { variant: "primary", onClick: choose }, `\u5B89\u88C5${noun}`))),
6288
+ (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_primitives5.Button, { variant: "ghost", onClick: () => refresh((n) => n + 1), disabled: loading }, "\u5237\u65B0")),
6289
+ notice ? (0, import_react5.createElement)("div", { className: "te-success", role: "status" }, notice) : null,
5956
6290
  !importing && !editing && !deleting ? status() : null,
5957
- loading ? (0, import_react4.createElement)("div", { className: "te-empty", role: "status" }, "\u6B63\u5728\u52A0\u8F7D\u2026") : visible.length === 0 ? (0, import_react4.createElement)("div", { className: "te-empty" }, (0, import_react4.createElement)("h3", null, query || filter !== "all" ? "\u6CA1\u6709\u5339\u914D\u7684\u7ED3\u679C" : `\u8FD8\u6CA1\u6709${noun}`), (0, import_react4.createElement)("p", null, "\u8C03\u6574\u7B5B\u9009\uFF0C\u6216\u4F7F\u7528\u53F3\u4E0A\u89D2\u6309\u94AE\u6DFB\u52A0\u3002")) : (0, import_react4.createElement)("div", { className: "te-resource-grid" }, ...visible.map((row) => (0, import_react4.createElement)(
6291
+ 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)(
5958
6292
  "article",
5959
6293
  { className: "te-resource-card", key: row.source + "/" + row.name },
5960
- (0, import_react4.createElement)("div", { className: "te-card-top" }, (0, import_react4.createElement)("span", { className: "te-resource-icon", "aria-hidden": true }, kind === "skill" ? "\u25C7" : "\u2261"), (0, import_react4.createElement)("span", { className: "te-badge" }, sourceText2(row.source))),
5961
- (0, import_react4.createElement)("h3", null, row.name),
5962
- (0, import_react4.createElement)("p", null, row.description || "\u9879\u76EE\u7EA6\u5B9A\u4E0E\u6267\u884C\u89C4\u5219"),
5963
- (0, import_react4.createElement)("div", { className: "te-actions" }, (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "outline", size: "sm", onClick: () => {
6294
+ (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))),
6295
+ (0, import_react5.createElement)("h3", null, row.name),
6296
+ (0, import_react5.createElement)("p", null, row.description || "\u9879\u76EE\u7EA6\u5B9A\u4E0E\u6267\u884C\u89C4\u5219"),
6297
+ (0, import_react5.createElement)("div", { className: "te-actions" }, kind === "skill" && onConfigureSkill ? (0, import_react5.createElement)(import_dsh_client_ui_primitives5.Button, { variant: "primary", size: "sm", onClick: () => onConfigureSkill({ source: levelOf(row), name: row.name }) }, "\u914D\u7F6E\u89C4\u5219") : null, (0, import_react5.createElement)(import_dsh_client_ui_primitives5.Button, { variant: "outline", size: "sm", onClick: () => {
5964
6298
  void edit(row, true);
5965
- } }, "\u67E5\u770B"), levelOf(row) !== "bundled" ? (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "ghost", size: "sm", onClick: () => {
6299
+ } }, "\u67E5\u770B"), levelOf(row) !== "bundled" ? (0, import_react5.createElement)(import_dsh_client_ui_primitives5.Button, { variant: "ghost", size: "sm", onClick: () => {
5966
6300
  void edit(row);
5967
- } }, "\u7F16\u8F91") : null, levelOf(row) !== "bundled" ? (0, import_react4.createElement)("button", { className: "te-delete", onClick: () => {
6301
+ } }, "\u7F16\u8F91") : null, levelOf(row) !== "bundled" ? (0, import_react5.createElement)("button", { className: "te-delete", onClick: () => {
5968
6302
  setDeleting(row);
5969
6303
  setError("");
5970
6304
  } }, "\u5220\u9664") : null)
5971
6305
  ))),
5972
- kind === "skill" ? (0, import_react4.createElement)("button", { className: "te-link", onClick: () => {
6306
+ kind === "skill" ? (0, import_react5.createElement)("button", { className: "te-link", onClick: () => {
5973
6307
  setImporting(true);
5974
6308
  setManual(true);
5975
6309
  setError("");
5976
6310
  } }, "\u9AD8\u7EA7\uFF1A\u4ECE Harness \u4E3B\u673A\u8DEF\u5F84\u5B89\u88C5") : null,
5977
- importing ? (0, import_react4.createElement)(
6311
+ importing ? (0, import_react5.createElement)(
5978
6312
  ResourceModal,
5979
- { title: `\u5B89\u88C5${noun}`, description: "\u5148\u68C0\u67E5\u5185\u5BB9\u548C\u5B89\u88C5\u4F4D\u7F6E\uFF0C\u786E\u8BA4\u540E\u624D\u4F1A\u5199\u5165\u3002", onClose: close, footer: (0, import_react4.createElement)("div", { className: "te-actions" }, (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "ghost", disabled: busy, onClick: close }, "\u53D6\u6D88"), (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "primary", disabled: busy || !preview || preview.conflict, onClick: () => {
6313
+ { 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_primitives5.Button, { variant: "ghost", disabled: busy, onClick: close }, "\u53D6\u6D88"), (0, import_react5.createElement)(import_dsh_client_ui_primitives5.Button, { variant: "primary", disabled: busy || !preview || preview.conflict, onClick: () => {
5980
6314
  void install();
5981
6315
  } }, busy ? "\u5904\u7406\u4E2D\u2026" : "\u786E\u8BA4\u5B89\u88C5")) },
5982
6316
  targets(),
5983
- (0, import_react4.createElement)("div", { className: "te-actions" }, (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "outline", disabled: busy, onClick: choose }, "\u91CD\u65B0\u9009\u62E9"), kind === "skill" ? (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "ghost", disabled: busy, onClick: () => setManual(!manual) }, manual ? "\u6536\u8D77\u9AD8\u7EA7\u65B9\u5F0F" : "\u4E3B\u673A\u8DEF\u5F84") : null),
5984
- manual ? (0, import_react4.createElement)("div", { className: "te-advanced" }, (0, import_react4.createElement)("p", null, "\u6B64\u8DEF\u5F84\u4F4D\u4E8E Harness \u4E3B\u673A\uFF1B\u6D4F\u89C8\u5668\u9009\u62E9\u5668\u8BFB\u53D6\u7684\u662F\u4F60\u5F53\u524D\u7535\u8111\u3002"), (0, import_react4.createElement)("div", { className: "te-toolbar" }, (0, import_react4.createElement)("input", { className: "te-input", "aria-label": "\u4E3B\u673A\u6280\u80FD\u76EE\u5F55", value: sourceDir, onChange: (e) => {
6317
+ (0, import_react5.createElement)("div", { className: "te-actions" }, (0, import_react5.createElement)(import_dsh_client_ui_primitives5.Button, { variant: "outline", disabled: busy, onClick: choose }, "\u91CD\u65B0\u9009\u62E9"), kind === "skill" ? (0, import_react5.createElement)(import_dsh_client_ui_primitives5.Button, { variant: "ghost", disabled: busy, onClick: () => setManual(!manual) }, manual ? "\u6536\u8D77\u9AD8\u7EA7\u65B9\u5F0F" : "\u4E3B\u673A\u8DEF\u5F84") : null),
6318
+ 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) => {
5985
6319
  setSourceDir(e.target.value);
5986
6320
  setRequest(null);
5987
- } }), (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "outline", onClick: () => {
6321
+ } }), (0, import_react5.createElement)(import_dsh_client_ui_primitives5.Button, { variant: "outline", onClick: () => {
5988
6322
  void browse(sourceDir);
5989
- } }, "\u6D4F\u89C8"), (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "outline", disabled: busy || !sourceDir.trim(), onClick: () => setRequest({ kind, level, path: workspace, files: [], sourceDir }) }, "\u9884\u89C8\u76EE\u5F55")), (0, import_react4.createElement)("div", { className: "te-dir-list" }, browsePath ? (0, import_react4.createElement)("button", { onClick: () => {
6323
+ } }, "\u6D4F\u89C8"), (0, import_react5.createElement)(import_dsh_client_ui_primitives5.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: () => {
5990
6324
  void browse(browsePath.replace(/[\\/][^\\/]+[\\/]?$/u, "") || "/");
5991
- } }, "\u2191 \u4E0A\u7EA7\u76EE\u5F55") : null, ...dirs.map((d) => (0, import_react4.createElement)("button", { key: d.name, onClick: () => {
6325
+ } }, "\u2191 \u4E0A\u7EA7\u76EE\u5F55") : null, ...dirs.map((d) => (0, import_react5.createElement)("button", { key: d.name, onClick: () => {
5992
6326
  setRequest(null);
5993
6327
  void browse(browsePath.replace(/[\\/]+$/u, "") + "/" + d.name);
5994
6328
  } }, d.name + (d.hasSkill ? " \xB7 SKILL.md" : ""))))) : null,
5995
- busy ? (0, import_react4.createElement)("p", { role: "status" }, "\u6B63\u5728\u6821\u9A8C\u6587\u4EF6\uFF0C\u8BF7\u7A0D\u5019\u2026") : null,
6329
+ busy ? (0, import_react5.createElement)("p", { role: "status" }, "\u6B63\u5728\u6821\u9A8C\u6587\u4EF6\uFF0C\u8BF7\u7A0D\u5019\u2026") : null,
5996
6330
  status(),
5997
- preview ? (0, import_react4.createElement)("div", { className: "te-preview" }, (0, import_react4.createElement)("h3", null, preview.name), (0, import_react4.createElement)("p", null, preview.description), (0, import_react4.createElement)("div", { className: "te-actions" }, (0, import_react4.createElement)("span", { className: "te-badge" }, `${preview.files} \u4E2A\u6587\u4EF6`), (0, import_react4.createElement)("span", { className: "te-badge" }, sizeText(preview.bytes))), (0, import_react4.createElement)("code", { className: "te-path" }, preview.target), preview.conflict ? (0, import_react4.createElement)("div", { className: "te-alert", role: "alert" }, "\u5DF2\u6709\u540C\u540D\u8D44\u6E90\u3002\u8BF7\u53D6\u6D88\u5E76\u68C0\u67E5\u73B0\u6709\u5185\u5BB9\uFF0C\u5B89\u88C5\u4E0D\u4F1A\u8986\u76D6\u5B83\u3002") : null, (0, import_react4.createElement)("div", { className: "te-markdown" }, (0, import_react4.createElement)(import_dsh_client_ui_primitives4.MarkdownText, { text: preview.content, labels }))) : null
6331
+ 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_primitives5.MarkdownText, { text: preview.content, labels }))) : null
5998
6332
  ) : null,
5999
- editing ? (0, import_react4.createElement)(
6333
+ editing ? (0, import_react5.createElement)(
6000
6334
  ResourceModal,
6001
- { title: editing === "new" ? `\u65B0\u5EFA${noun}` : `${viewing ? "\u67E5\u770B" : "\u7F16\u8F91"}${noun} \xB7 ${name}`, onClose: close, footer: (0, import_react4.createElement)("div", { className: "te-actions" }, (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "ghost", disabled: busy, onClick: close }, "\u5173\u95ED"), !readonly ? (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "outline", disabled: busy, onClick: () => setViewing(!viewing) }, viewing ? "\u7F16\u8F91\u5185\u5BB9" : "\u9884\u89C8") : null, !readonly ? (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "primary", disabled: busy || !name.trim() || !body2.trim() || kind === "skill" && !description.trim(), onClick: () => {
6335
+ { 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_primitives5.Button, { variant: "ghost", disabled: busy, onClick: close }, "\u5173\u95ED"), !readonly ? (0, import_react5.createElement)(import_dsh_client_ui_primitives5.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_primitives5.Button, { variant: "primary", disabled: busy || !name.trim() || !body2.trim() || kind === "skill" && !description.trim(), onClick: () => {
6002
6336
  void save2();
6003
6337
  } }, busy ? "\u5904\u7406\u4E2D\u2026" : "\u4FDD\u5B58") : null) },
6004
- !readonly ? targets() : (0, import_react4.createElement)("p", { className: "te-badge" }, "\u5185\u7F6E\u8D44\u6E90 \xB7 \u53EA\u8BFB"),
6338
+ !readonly ? targets() : (0, import_react5.createElement)("p", { className: "te-badge" }, "\u5185\u7F6E\u8D44\u6E90 \xB7 \u53EA\u8BFB"),
6005
6339
  status(),
6006
- viewing ? (0, import_react4.createElement)("div", { className: "te-markdown" }, (0, import_react4.createElement)(import_dsh_client_ui_primitives4.MarkdownText, { text: body2, labels })) : (0, import_react4.createElement)("div", { className: "te-form" }, (0, import_react4.createElement)("label", null, "\u540D\u79F0", (0, import_react4.createElement)("input", { className: "te-input", value: name, disabled: editing !== "new" || busy, onChange: (e) => setName(e.target.value), placeholder: "\u5C0F\u5199\u5B57\u6BCD\u3001\u6570\u5B57\u548C\u8FDE\u5B57\u7B26" })), kind === "skill" ? (0, import_react4.createElement)("label", null, "\u63CF\u8FF0", (0, import_react4.createElement)("input", { className: "te-input", value: description, disabled: busy, onChange: (e) => setDescription(e.target.value) })) : null, kind === "skill" ? (0, import_react4.createElement)("label", null, "\u4F7F\u7528\u65F6\u673A\uFF08\u53EF\u9009\uFF09", (0, import_react4.createElement)("input", { className: "te-input", value: whenToUse, disabled: busy, onChange: (e) => setWhenToUse(e.target.value) })) : null, (0, import_react4.createElement)("label", null, "Markdown \u6B63\u6587", (0, import_react4.createElement)("textarea", { className: "te-input te-editor", value: body2, disabled: busy, onChange: (e) => setBody(e.target.value) })))
6340
+ viewing ? (0, import_react5.createElement)("div", { className: "te-markdown" }, (0, import_react5.createElement)(import_dsh_client_ui_primitives5.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) })))
6007
6341
  ) : null,
6008
- deleting ? (0, import_react4.createElement)(ResourceModal, { title: `\u5220\u9664${noun}\u300C${deleting.name}\u300D\uFF1F`, description: levelOf(deleting) === "user" ? "\u8FD9\u662F\u4E2A\u4EBA\u5168\u5C40\u8D44\u6E90\uFF0C\u5220\u9664\u4F1A\u5F71\u54CD\u6B64\u4E3B\u673A\u4E0A\u7684\u6240\u6709\u9879\u76EE\u3002" : "\u5220\u9664\u5C06\u5F71\u54CD\u5F53\u524D\u9879\u76EE\u3002", onClose: close, footer: (0, import_react4.createElement)("div", { className: "te-actions" }, (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "outline", disabled: busy, onClick: close }, "\u4FDD\u7559"), (0, import_react4.createElement)("button", { className: "te-danger-button", disabled: busy, onClick: () => {
6342
+ 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_primitives5.Button, { variant: "outline", disabled: busy, onClick: close }, "\u4FDD\u7559"), (0, import_react5.createElement)("button", { className: "te-danger-button", disabled: busy, onClick: () => {
6009
6343
  void remove();
6010
- } }, busy ? "\u5220\u9664\u4E2D\u2026" : "\u786E\u8BA4\u6C38\u4E45\u5220\u9664")) }, (0, import_react4.createElement)("code", { className: "te-path" }, `${roots?.[levelOf(deleting) === "user" ? "user" : "project"] ?? "\u8D44\u6E90\u76EE\u5F55"}/${deleting.name}${kind === "rule" ? ".md" : ""}`), (0, import_react4.createElement)("p", null, "\u6B64\u64CD\u4F5C\u4E0D\u4F1A\u8FDB\u5165\u56DE\u6536\u7AD9\uFF0C\u8BF7\u786E\u8BA4\u5DF2\u6709\u5907\u4EFD\u3002"), status()) : null
6344
+ } }, 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
6011
6345
  );
6012
6346
  }
6013
6347
 
6014
6348
  // src/client/SkillManager.tsx
6015
- function SkillManager(props) {
6016
- return (0, import_react5.createElement)(ResourceManager, { ...props, key: props.workspace, kind: "skill" });
6349
+ var import_jsx_runtime3 = require("react/jsx-runtime");
6350
+ function SkillManager({ workspace, remote }) {
6351
+ const [config, setConfig] = (0, import_react6.useState)(null);
6352
+ const [rules, setRules] = (0, import_react6.useState)([]);
6353
+ const [selected, setSelected] = (0, import_react6.useState)(null);
6354
+ const [message, setMessage] = (0, import_react6.useState)("");
6355
+ (0, import_react6.useEffect)(() => {
6356
+ let active = true;
6357
+ void Promise.all([remote.read(workspace), remote.listRules(workspace)]).then(([saved, availableRules]) => {
6358
+ if (!active) return;
6359
+ if (!saved.ok || !saved.value.ok || !availableRules.ok) {
6360
+ setMessage("\u8BFB\u53D6\u6280\u80FD\u89C4\u5219\u914D\u7F6E\u5931\u8D25\uFF0C\u8BF7\u91CD\u65B0\u6253\u5F00\u6280\u80FD\u9875\u3002");
6361
+ return;
6362
+ }
6363
+ const effective = saved.value.config;
6364
+ setConfig(compactProjectConfig({
6365
+ flow: saved.value.flow,
6366
+ stage_bindings: effective.stage_bindings,
6367
+ skill_profiles: effective.skill_profiles,
6368
+ commit: effective.commit,
6369
+ artifacts: effective.artifacts,
6370
+ review_depth: effective.review_depth,
6371
+ commit_required: effective.commit_required
6372
+ }));
6373
+ setRules(availableRules.value.rules);
6374
+ }).catch(() => {
6375
+ if (active) setMessage("\u8BFB\u53D6\u6280\u80FD\u89C4\u5219\u914D\u7F6E\u5931\u8D25\uFF0C\u8BF7\u91CD\u65B0\u6253\u5F00\u6280\u80FD\u9875\u3002");
6376
+ });
6377
+ return () => {
6378
+ active = false;
6379
+ };
6380
+ }, [remote, workspace]);
6381
+ const saveProfile = async (profile) => {
6382
+ if (!config || !selected) throw new Error("\u914D\u7F6E\u5C1A\u672A\u52A0\u8F7D\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002");
6383
+ const key = formatResourceRef(selected);
6384
+ const next = { ...config, skill_profiles: { ...config.skill_profiles, [key]: profile } };
6385
+ const result = await remote.write({ path: workspace, ...next });
6386
+ if (!result.ok || !result.value.ok) throw new Error(result.ok ? result.value.problems.join("\uFF1B") : "\u4FDD\u5B58\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u3002");
6387
+ setConfig(next);
6388
+ setMessage(`\u5DF2\u4FDD\u5B58 ${selected.name} \u7684\u89C4\u5219\u914D\u7F6E\u3002`);
6389
+ setSelected(null);
6390
+ };
6391
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { children: [
6392
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ResourceManager, { workspace, remote, kind: "skill", onConfigureSkill: config ? (ref) => {
6393
+ setMessage("");
6394
+ setSelected(ref);
6395
+ } : void 0 }),
6396
+ selected === null && message ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { role: "status", className: "te-success", children: message }) : null,
6397
+ selected !== null ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
6398
+ SkillRuleDialog,
6399
+ {
6400
+ skill: selected,
6401
+ profile: config?.skill_profiles?.[formatResourceRef(selected)],
6402
+ rules,
6403
+ onSave: saveProfile,
6404
+ onClose: () => setSelected(null)
6405
+ },
6406
+ formatResourceRef(selected)
6407
+ ) : null
6408
+ ] });
6017
6409
  }
6018
6410
 
6019
6411
  // src/client/RuleManager.tsx
6020
- var import_react6 = require("react");
6412
+ var import_react7 = require("react");
6021
6413
  function RuleManager(props) {
6022
- return (0, import_react6.createElement)(ResourceManager, { ...props, key: props.workspace, kind: "rule" });
6414
+ return (0, import_react7.createElement)(ResourceManager, { ...props, key: props.workspace, kind: "rule" });
6023
6415
  }
6024
6416
 
6025
6417
  // src/client/TaskLedger.tsx
6026
- var import_react7 = require("react");
6027
- var import_dsh_client_ui_primitives5 = require("@deepseek-ai/dsh-client-ui-primitives");
6418
+ var import_react8 = require("react");
6419
+ var import_dsh_client_ui_primitives6 = require("@deepseek-ai/dsh-client-ui-primitives");
6028
6420
  var card2 = {
6029
6421
  display: "flex",
6030
6422
  flexDirection: "column",
@@ -6062,10 +6454,10 @@ var badge = {
6062
6454
  color: "var(--dsw-alias-label-secondary)"
6063
6455
  };
6064
6456
  function verdictDot(outcome) {
6065
- return (0, import_react7.createElement)(import_dsh_client_ui_primitives5.StateDot, { state: outcome === "pass" ? "done" : "error" });
6457
+ return (0, import_react8.createElement)(import_dsh_client_ui_primitives6.StateDot, { state: outcome === "pass" ? "done" : "error" });
6066
6458
  }
6067
6459
  function itemStatusDot(status) {
6068
- return (0, import_react7.createElement)(import_dsh_client_ui_primitives5.StateDot, { state: status === "done" ? "done" : "ongoing" });
6460
+ return (0, import_react8.createElement)(import_dsh_client_ui_primitives6.StateDot, { state: status === "done" ? "done" : "ongoing" });
6069
6461
  }
6070
6462
  function timeText(at) {
6071
6463
  return at.slice(0, 19).replace("T", " ");
@@ -6073,48 +6465,48 @@ function timeText(at) {
6073
6465
  function itemAudit(item) {
6074
6466
  const lines = [];
6075
6467
  if (item.dispatch !== void 0) {
6076
- lines.push((0, import_react7.createElement)(
6468
+ lines.push((0, import_react8.createElement)(
6077
6469
  "div",
6078
6470
  { key: "dispatch", style: metaLine },
6079
- (0, import_react7.createElement)("span", { style: badge }, "\u5DF2\u6D3E\u53D1"),
6080
- (0, import_react7.createElement)("span", null, item.dispatch.description === "" ? "\uFF08\u65E0\u63CF\u8FF0\uFF09" : item.dispatch.description),
6081
- (0, import_react7.createElement)("span", { style: badge }, timeText(item.dispatch.at))
6471
+ (0, import_react8.createElement)("span", { style: badge }, "\u5DF2\u6D3E\u53D1"),
6472
+ (0, import_react8.createElement)("span", null, item.dispatch.description === "" ? "\uFF08\u65E0\u63CF\u8FF0\uFF09" : item.dispatch.description),
6473
+ (0, import_react8.createElement)("span", { style: badge }, timeText(item.dispatch.at))
6082
6474
  ));
6083
6475
  }
6084
6476
  if (item.review !== void 0) {
6085
6477
  const spec = item.review.spec;
6086
6478
  const quality = item.review.quality;
6087
- lines.push((0, import_react7.createElement)(
6479
+ lines.push((0, import_react8.createElement)(
6088
6480
  "div",
6089
6481
  { key: "review", style: metaLine },
6090
6482
  verdictDot(spec.outcome),
6091
- (0, import_react7.createElement)("span", null, `\u89C4\u683C\u7B26\u5408 ${spec.outcome === "pass" ? "\u901A\u8FC7" : "\u4E0D\u901A\u8FC7"}`),
6092
- (0, import_react7.createElement)("span", null, "\xB7"),
6483
+ (0, import_react8.createElement)("span", null, `\u89C4\u683C\u7B26\u5408 ${spec.outcome === "pass" ? "\u901A\u8FC7" : "\u4E0D\u901A\u8FC7"}`),
6484
+ (0, import_react8.createElement)("span", null, "\xB7"),
6093
6485
  verdictDot(quality.outcome),
6094
- (0, import_react7.createElement)("span", null, `\u4EE3\u7801\u8D28\u91CF ${quality.outcome === "pass" ? "\u901A\u8FC7" : "\u4E0D\u901A\u8FC7"}`)
6486
+ (0, import_react8.createElement)("span", null, `\u4EE3\u7801\u8D28\u91CF ${quality.outcome === "pass" ? "\u901A\u8FC7" : "\u4E0D\u901A\u8FC7"}`)
6095
6487
  ));
6096
6488
  const failNotes = [spec, quality].flatMap((stage) => stage.outcome === "fail" ? stage.notes ?? [] : []);
6097
6489
  if (failNotes.length > 0) {
6098
- lines.push((0, import_react7.createElement)(
6490
+ lines.push((0, import_react8.createElement)(
6099
6491
  "div",
6100
6492
  { key: "notes", style: metaLine },
6101
- ...failNotes.map((note) => (0, import_react7.createElement)("span", { key: note, style: badge }, note))
6493
+ ...failNotes.map((note) => (0, import_react8.createElement)("span", { key: note, style: badge }, note))
6102
6494
  ));
6103
6495
  }
6104
6496
  }
6105
6497
  if (lines.length === 0) {
6106
- lines.push((0, import_react7.createElement)("div", { key: "none", style: metaLine }, (0, import_react7.createElement)("span", { style: badge }, "\u672A\u6D3E\u53D1 / \u672A\u5BA1\u67E5")));
6498
+ lines.push((0, import_react8.createElement)("div", { key: "none", style: metaLine }, (0, import_react8.createElement)("span", { style: badge }, "\u672A\u6D3E\u53D1 / \u672A\u5BA1\u67E5")));
6107
6499
  }
6108
- return (0, import_react7.createElement)("div", { style: { display: "flex", flexDirection: "column", gap: 4 } }, ...lines);
6500
+ return (0, import_react8.createElement)("div", { style: { display: "flex", flexDirection: "column", gap: 4 } }, ...lines);
6109
6501
  }
6110
6502
  function TaskLedger({ workspace, remote }) {
6111
- const [tasks, setTasks] = (0, import_react7.useState)([]);
6112
- const [error, setError] = (0, import_react7.useState)("");
6113
- const [loading, setLoading] = (0, import_react7.useState)(true);
6114
- const [query, setQuery] = (0, import_react7.useState)("");
6115
- const [risk, setRisk] = (0, import_react7.useState)("all");
6116
- const [stage, setStage] = (0, import_react7.useState)("all");
6117
- const refresh = (0, import_react7.useCallback)(() => {
6503
+ const [tasks, setTasks] = (0, import_react8.useState)([]);
6504
+ const [error, setError] = (0, import_react8.useState)("");
6505
+ const [loading, setLoading] = (0, import_react8.useState)(true);
6506
+ const [query, setQuery] = (0, import_react8.useState)("");
6507
+ const [risk, setRisk] = (0, import_react8.useState)("all");
6508
+ const [stage, setStage] = (0, import_react8.useState)("all");
6509
+ const refresh = (0, import_react8.useCallback)(() => {
6118
6510
  if (workspace === "") return;
6119
6511
  setError("");
6120
6512
  setLoading(true);
@@ -6127,57 +6519,57 @@ function TaskLedger({ workspace, remote }) {
6127
6519
  setError("\u8BFB\u53D6\u53F0\u8D26\u5931\u8D25\uFF1A" + describeError(reason));
6128
6520
  });
6129
6521
  }, [remote, workspace]);
6130
- (0, import_react7.useEffect)(() => {
6522
+ (0, import_react8.useEffect)(() => {
6131
6523
  refresh();
6132
6524
  }, [refresh]);
6133
6525
  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));
6134
- return (0, import_react7.createElement)(
6526
+ return (0, import_react8.createElement)(
6135
6527
  "div",
6136
6528
  { style: styles.section },
6137
- (0, import_react7.createElement)(
6529
+ (0, import_react8.createElement)(
6138
6530
  "div",
6139
6531
  { className: "te-toolbar" },
6140
- (0, import_react7.createElement)("input", { className: "te-input", placeholder: "\u641C\u7D22\u4EFB\u52A1\u3001\u6807\u9898\u6216\u5206\u652F", value: query, onChange: (e) => setQuery(e.target.value) }),
6141
- (0, import_react7.createElement)("select", { className: "te-input", "aria-label": "\u98CE\u9669\u7B5B\u9009", value: risk, onChange: (e) => setRisk(e.target.value) }, (0, import_react7.createElement)("option", { value: "all" }, "\u5168\u90E8\u98CE\u9669"), (0, import_react7.createElement)("option", { value: "standard" }, "\u6807\u51C6"), (0, import_react7.createElement)("option", { value: "high_risk" }, "\u9AD8\u98CE\u9669")),
6142
- (0, import_react7.createElement)("select", { className: "te-input", "aria-label": "\u9636\u6BB5\u7B5B\u9009", value: stage, onChange: (e) => setStage(e.target.value) }, (0, import_react7.createElement)("option", { value: "all" }, "\u5168\u90E8\u9636\u6BB5"), ...Array.from(new Set(tasks.map((t) => t.stage))).map((value) => (0, import_react7.createElement)("option", { key: value, value }, value)))
6532
+ (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) }),
6533
+ (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")),
6534
+ (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)))
6143
6535
  ),
6144
- (0, import_react7.createElement)(
6536
+ (0, import_react8.createElement)(
6145
6537
  "div",
6146
6538
  { style: headerRow },
6147
- (0, import_react7.createElement)("span", { style: styles.bindingLabel }, "\u4EFB\u52A1\u53F0\u8D26"),
6148
- (0, import_react7.createElement)("span", { style: styles.sourceBadge }, "\u53EA\u8BFB \xB7 \u6765\u81EA .dsh/task-*.json"),
6149
- (0, import_react7.createElement)(import_dsh_client_ui_primitives5.Button, { variant: "outline", size: "sm", disabled: loading, onClick: refresh }, loading ? "\u8BFB\u53D6\u4E2D\u2026" : "\u5237\u65B0")
6539
+ (0, import_react8.createElement)("span", { style: styles.bindingLabel }, "\u4EFB\u52A1\u53F0\u8D26"),
6540
+ (0, import_react8.createElement)("span", { style: styles.sourceBadge }, "\u53EA\u8BFB \xB7 \u6765\u81EA .dsh/task-*.json"),
6541
+ (0, import_react8.createElement)(import_dsh_client_ui_primitives6.Button, { variant: "outline", size: "sm", disabled: loading, onClick: refresh }, loading ? "\u8BFB\u53D6\u4E2D\u2026" : "\u5237\u65B0")
6150
6542
  ),
6151
- loading ? (0, import_react7.createElement)("p", { role: "status" }, "\u6B63\u5728\u8BFB\u53D6\u4EFB\u52A1\u2026") : error !== "" ? (0, import_react7.createElement)("p", { style: styles.status }, error) : tasks.length === 0 ? (0, import_react7.createElement)("p", { style: styles.muted }, "\u5F53\u524D\u5DE5\u4F5C\u533A\u8FD8\u6CA1\u6709\u4EFB\u52A1\uFF1A\u5F00\u5DE5\u540E\uFF08dev_task create\uFF09\u4F1A\u5728\u8FD9\u91CC\u5217\u51FA\u6D3E\u53D1\u4E0E\u5BA1\u67E5\u7559\u75D5\u3002") : visible.length === 0 ? (0, import_react7.createElement)("div", { className: "te-empty" }, "\u6CA1\u6709\u5339\u914D\u7684\u4EFB\u52A1\uFF0C\u8BF7\u8C03\u6574\u7B5B\u9009\u3002") : (0, import_react7.createElement)(
6543
+ 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)(
6152
6544
  "div",
6153
6545
  { style: { display: "flex", flexDirection: "column", gap: 12 } },
6154
- ...visible.map((task) => (0, import_react7.createElement)(
6546
+ ...visible.map((task) => (0, import_react8.createElement)(
6155
6547
  "div",
6156
6548
  { key: task.task_id, style: card2 },
6157
- (0, import_react7.createElement)(
6549
+ (0, import_react8.createElement)(
6158
6550
  "div",
6159
6551
  { style: headerRow },
6160
- (0, import_react7.createElement)("span", { style: { fontSize: 14, fontWeight: 600, color: "var(--dsw-alias-label-primary)" } }, task.task_id),
6161
- (0, import_react7.createElement)("span", { style: { fontSize: 13, color: "var(--dsw-alias-label-primary)" } }, task.title),
6162
- (0, import_react7.createElement)("span", { style: badge }, task.stage),
6163
- (0, import_react7.createElement)("span", { style: badge }, task.branch),
6164
- (0, import_react7.createElement)("span", { className: "te-badge", style: task.risk_level === "high_risk" ? { color: "var(--dsw-alias-state-error-primary)" } : {} }, task.risk_level === "high_risk" ? "\u9AD8\u98CE\u9669" : "\u6807\u51C6"),
6165
- (0, import_react7.createElement)("span", { className: "te-badge" }, task.verification_passed ? "\u9A8C\u8BC1\u901A\u8FC7" : "\u5F85\u9A8C\u8BC1"),
6166
- (0, import_react7.createElement)("span", { className: "te-badge" }, `\u5BA1\u6838\uFF1A${task.review_outcome ?? "pending"}`),
6167
- task.updated_at ? (0, import_react7.createElement)("span", { style: metaLine }, "\u66F4\u65B0\u4E8E " + timeText(task.updated_at)) : null
6552
+ (0, import_react8.createElement)("span", { style: { fontSize: 14, fontWeight: 600, color: "var(--dsw-alias-label-primary)" } }, task.task_id),
6553
+ (0, import_react8.createElement)("span", { style: { fontSize: 13, color: "var(--dsw-alias-label-primary)" } }, task.title),
6554
+ (0, import_react8.createElement)("span", { style: badge }, task.stage),
6555
+ (0, import_react8.createElement)("span", { style: badge }, task.branch),
6556
+ (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"),
6557
+ (0, import_react8.createElement)("span", { className: "te-badge" }, task.verification_passed ? "\u9A8C\u8BC1\u901A\u8FC7" : "\u5F85\u9A8C\u8BC1"),
6558
+ (0, import_react8.createElement)("span", { className: "te-badge" }, `\u5BA1\u6838\uFF1A${task.review_outcome ?? "pending"}`),
6559
+ task.updated_at ? (0, import_react8.createElement)("span", { style: metaLine }, "\u66F4\u65B0\u4E8E " + timeText(task.updated_at)) : null
6168
6560
  ),
6169
- (0, import_react7.createElement)(
6561
+ (0, import_react8.createElement)(
6170
6562
  "div",
6171
6563
  { style: { display: "flex", flexDirection: "column" } },
6172
- ...task.items.map((item) => (0, import_react7.createElement)(
6564
+ ...task.items.map((item) => (0, import_react8.createElement)(
6173
6565
  "div",
6174
6566
  { key: item.id, style: itemRow },
6175
- (0, import_react7.createElement)(
6567
+ (0, import_react8.createElement)(
6176
6568
  "div",
6177
6569
  { style: headerRow },
6178
6570
  itemStatusDot(item.status),
6179
- (0, import_react7.createElement)("span", { style: { fontSize: 13, color: "var(--dsw-alias-label-primary)" } }, item.id),
6180
- (0, import_react7.createElement)("span", { style: { fontSize: 12, color: "var(--dsw-alias-label-secondary)" } }, item.title)
6571
+ (0, import_react8.createElement)("span", { style: { fontSize: 13, color: "var(--dsw-alias-label-primary)" } }, item.id),
6572
+ (0, import_react8.createElement)("span", { style: { fontSize: 12, color: "var(--dsw-alias-label-secondary)" } }, item.title)
6181
6573
  ),
6182
6574
  itemAudit(item)
6183
6575
  ))
@@ -6218,7 +6610,7 @@ var tabbar = {
6218
6610
  var body = {
6219
6611
  flex: 1,
6220
6612
  overflowY: "auto",
6221
- padding: "24px clamp(12px, 3vw, 32px)"
6613
+ padding: "16px clamp(12px, 2vw, 28px)"
6222
6614
  };
6223
6615
  var selectStyle = {
6224
6616
  marginLeft: "auto",
@@ -6251,29 +6643,29 @@ var TABS = [
6251
6643
  function Workbench({ useStore, actions, useWorkspaces, remote }) {
6252
6644
  const open = useStore((s) => s.open);
6253
6645
  const workspaces = useWorkspaces((s) => s.items);
6254
- const [tab, setTab] = (0, import_react8.useState)("init");
6255
- const [workspace, setWorkspace] = (0, import_react8.useState)("");
6646
+ const [tab, setTab] = (0, import_react9.useState)("init");
6647
+ const [workspace, setWorkspace] = (0, import_react9.useState)("");
6256
6648
  if (!open) return null;
6257
6649
  const current = workspaces.some((w) => w.path === workspace) ? workspace : workspaces[0]?.path ?? "";
6258
- return (0, import_react8.createElement)(
6650
+ return (0, import_react9.createElement)(
6259
6651
  "div",
6260
6652
  { style: overlay, className: "te-workbench" },
6261
- (0, import_react8.createElement)("style", null, workbenchTheme),
6262
- (0, import_react8.createElement)(
6653
+ (0, import_react9.createElement)("style", null, workbenchTheme),
6654
+ (0, import_react9.createElement)(
6263
6655
  "div",
6264
6656
  { style: header },
6265
- (0, import_react8.createElement)(
6657
+ (0, import_react9.createElement)(
6266
6658
  "div",
6267
6659
  { style: headerBrand },
6268
- (0, import_react8.createElement)(import_dsh_client_ui_primitives6.IconSettingsOutline16, { size: 18 }),
6269
- (0, import_react8.createElement)(
6660
+ (0, import_react9.createElement)(import_dsh_client_ui_primitives7.IconSettingsOutline16, { size: 18 }),
6661
+ (0, import_react9.createElement)(
6270
6662
  "div",
6271
6663
  { style: headerText },
6272
- (0, import_react8.createElement)("span", { style: headerTitle }, "\u5DE5\u7A0B\u6D41\u7A0B"),
6273
- (0, import_react8.createElement)("p", { style: headerSub }, "\u5DE5\u7A0B\u5316\u4EA4\u4ED8\u5DE5\u4F5C\u53F0 \xB7 \u9700\u6C42\u8BC4\u5BA1 \u2192 \u8BBE\u8BA1 \u2192 \u5F00\u53D1 \u2192 \u4EA4\u4ED8 \u2192 \u4EE3\u7801\u5BA1\u6838")
6664
+ (0, import_react9.createElement)("span", { style: headerTitle }, "\u5DE5\u7A0B\u6D41\u7A0B"),
6665
+ (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")
6274
6666
  )
6275
6667
  ),
6276
- (0, import_react8.createElement)(
6668
+ (0, import_react9.createElement)(
6277
6669
  "button",
6278
6670
  {
6279
6671
  type: "button",
@@ -6289,44 +6681,44 @@ function Workbench({ useStore, actions, useWorkspaces, remote }) {
6289
6681
  event.currentTarget.style.background = "transparent";
6290
6682
  }
6291
6683
  },
6292
- (0, import_react8.createElement)(import_dsh_client_ui_primitives6.IconCloseOutline16, { size: 16 })
6684
+ (0, import_react9.createElement)(import_dsh_client_ui_primitives7.IconCloseOutline16, { size: 16 })
6293
6685
  )
6294
6686
  ),
6295
- (0, import_react8.createElement)(
6687
+ (0, import_react9.createElement)(
6296
6688
  "div",
6297
6689
  { style: tabbar },
6298
- ...TABS.map((t) => (0, import_react8.createElement)(import_dsh_client_ui_primitives6.Pill, { key: t.id, active: tab === t.id, onClick: () => {
6690
+ ...TABS.map((t) => (0, import_react9.createElement)(import_dsh_client_ui_primitives7.Pill, { key: t.id, active: tab === t.id, onClick: () => {
6299
6691
  setTab(t.id);
6300
6692
  } }, t.label)),
6301
- workspaces.length > 0 ? (0, import_react8.createElement)("select", {
6693
+ workspaces.length > 0 ? (0, import_react9.createElement)("select", {
6302
6694
  style: selectStyle,
6303
6695
  "aria-label": "\u5F53\u524D\u5DE5\u4F5C\u533A",
6304
6696
  value: current,
6305
6697
  onChange: (ev) => {
6306
6698
  setWorkspace(ev.target.value);
6307
6699
  }
6308
- }, ...workspaces.map((w) => (0, import_react8.createElement)("option", { key: w.path, value: w.path }, w.title || w.path))) : null
6700
+ }, ...workspaces.map((w) => (0, import_react9.createElement)("option", { key: w.path, value: w.path }, w.title || w.path))) : null
6309
6701
  ),
6310
- (0, import_react8.createElement)(
6702
+ (0, import_react9.createElement)(
6311
6703
  "div",
6312
6704
  { style: body },
6313
- (0, import_react8.createElement)(
6705
+ (0, import_react9.createElement)(
6314
6706
  "div",
6315
6707
  { className: "te-content", key: current },
6316
- (0, import_react8.createElement)("p", { style: { ...styles.hint, marginBottom: 20 }, title: current }, "\u5DE5\u4F5C\u533A \xB7 " + current),
6317
- current === "" ? (0, import_react8.createElement)("p", { style: styles.muted }, "\u5F53\u524D\u6CA1\u6709\u5DE5\u4F5C\u533A\uFF1A\u8BF7\u5148\u5728\u4FA7\u680F\u521B\u5EFA\u4E00\u4E2A\u5DE5\u4F5C\u533A\uFF0C\u518D\u56DE\u6765\u914D\u7F6E\u6D41\u7A0B\u3002") : tab === "init" ? (0, import_react8.createElement)(InitPanel, { workspace: current, remote }) : tab === "flow" ? (0, import_react8.createElement)(TaskEngineSection, { workspace: current, remote }) : tab === "tasks" ? (0, import_react8.createElement)(TaskLedger, { workspace: current, remote }) : tab === "skills" ? (0, import_react8.createElement)(SkillManager, { workspace: current, remote }) : (0, import_react8.createElement)(RuleManager, { workspace: current, remote })
6708
+ (0, import_react9.createElement)("p", { style: { ...styles.hint, marginBottom: 10 }, title: current }, "\u5DE5\u4F5C\u533A \xB7 " + current),
6709
+ 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 })
6318
6710
  )
6319
6711
  )
6320
6712
  );
6321
6713
  }
6322
6714
 
6323
6715
  // src/client/TriggerButton.tsx
6324
- var import_react9 = require("react");
6325
- var import_dsh_client_ui_primitives7 = require("@deepseek-ai/dsh-client-ui-primitives");
6716
+ var import_react10 = require("react");
6717
+ var import_dsh_client_ui_primitives8 = require("@deepseek-ai/dsh-client-ui-primitives");
6326
6718
  var hover = "var(--dsw-alias-bg-layer-2)";
6327
6719
  var label = "var(--dsw-alias-label-primary)";
6328
6720
  function TriggerButton({ wide, actions }) {
6329
- return (0, import_react9.createElement)(
6721
+ return (0, import_react10.createElement)(
6330
6722
  "button",
6331
6723
  {
6332
6724
  type: "button",
@@ -6366,8 +6758,8 @@ function TriggerButton({ wide, actions }) {
6366
6758
  transition: "background 120ms ease"
6367
6759
  }
6368
6760
  },
6369
- (0, import_react9.createElement)(import_dsh_client_ui_primitives7.IconSettingsOutline16, { size: wide ? 16 : 18 }),
6370
- wide ? (0, import_react9.createElement)("span", { style: { fontSize: 14, lineHeight: "22px" } }, "\u5DE5\u7A0B\u6D41\u7A0B") : null
6761
+ (0, import_react10.createElement)(import_dsh_client_ui_primitives8.IconSettingsOutline16, { size: wide ? 16 : 18 }),
6762
+ wide ? (0, import_react10.createElement)("span", { style: { fontSize: 14, lineHeight: "22px" } }, "\u5DE5\u7A0B\u6D41\u7A0B") : null
6371
6763
  );
6372
6764
  }
6373
6765