@godv61/dsh-task-engine 0.25.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 (56) hide show
  1. package/.acceptance.mjs +150 -150
  2. package/.assessment-batch1.mjs +20 -20
  3. package/.enforce-test.mjs +138 -138
  4. package/.evidence-test.mjs +118 -119
  5. package/.filter-test.mjs +92 -92
  6. package/.hook-test.mjs +195 -195
  7. package/.p0-test.mjs +59 -59
  8. package/.preset-test.mjs +160 -160
  9. package/.revision-test.mjs +30 -16
  10. package/.roundtrip-test.mjs +178 -63
  11. package/.workflow-test.mjs +86 -0
  12. package/README.md +7 -7
  13. package/cordis.patch.yml +10 -10
  14. package/defaults/eng.json +70 -22
  15. package/docs/BRIEF-FOR-REVIEW.md +162 -162
  16. package/docs/CHANGELOG.md +12 -0
  17. package/docs/README.md +40 -40
  18. package/docs/configuration.md +12 -9
  19. package/docs/development.md +1 -1
  20. package/docs/faq.md +4 -4
  21. package/docs/listing/godv61__dsh-task-engine.yml +5 -5
  22. package/docs/listing/submission.md +83 -83
  23. package/docs/manual.html +31 -26
  24. package/docs/releases/0.23.2.md +21 -21
  25. package/docs/roadmap.md +34 -34
  26. 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
  27. 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
  28. package/docs/testing/0.23.2//346/265/213/350/257/225/346/212/245/345/221/212.md +65 -65
  29. package/hooks/commit-msg +70 -1
  30. package/lib/client.js +825 -570
  31. package/lib/client.js.map +3 -3
  32. package/lib/controller.d.ts +2 -1
  33. package/lib/controller.js +6 -3
  34. package/lib/controller.js.map +1 -1
  35. package/lib/dev-task.js +79 -11
  36. package/lib/dev-task.js.map +1 -1
  37. package/lib/engine.d.ts +15 -0
  38. package/lib/engine.js +29 -5
  39. package/lib/engine.js.map +1 -1
  40. package/lib/hook.js +3 -0
  41. package/lib/hook.js.map +1 -1
  42. package/lib/skill-audit.js +3 -3
  43. package/lib/skill-audit.js.map +1 -1
  44. package/lib/workflows.d.ts +4 -1
  45. package/lib/workflows.js +90 -2
  46. package/lib/workflows.js.map +1 -1
  47. package/package.json +1 -1
  48. package/preset/agent.cordis.yml +21 -21
  49. package/preset/enable.mjs +87 -87
  50. package/preset/persona.md +4 -4
  51. package/preset/preset.yml +1 -1
  52. package/rules/coding-conventions.md +6 -6
  53. package/rules/commit-conventions.md +6 -6
  54. package/rules/security-redlines.md +5 -5
  55. package/scripts/verify-dsh-compat.mjs +144 -144
  56. 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 = `
@@ -4576,8 +4576,35 @@ var workbenchTheme = `
4576
4576
  .te-binding-name { font-size:13px; font-weight:600; overflow-wrap:anywhere; }
4577
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; }
4578
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); }
4579
4606
  .te-workbench p,.te-modal p { color:var(--dsw-alias-label-secondary); line-height:1.65; }
4580
- .te-content { max-width:1120px; margin:auto; width:100%; }
4607
+ .te-content { max-width:1600px; margin:auto; width:100%; }
4581
4608
  .te-resource { display:flex; flex-direction:column; gap:20px; }
4582
4609
  .te-section-heading { display:flex; justify-content:space-between; align-items:center; gap:16px; flex-wrap:wrap; }
4583
4610
  .te-section-heading p { margin:0; }
@@ -4585,7 +4612,7 @@ var workbenchTheme = `
4585
4612
  .te-toolbar { display:flex; flex-wrap:wrap; align-items:center; gap:12px; }
4586
4613
  .te-toolbar>input { flex:1; min-width:180px; }
4587
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; }
4588
- .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; }
4589
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; }
4590
4617
  .te-resource-card:hover { border-color:var(--dsw-alias-state-business-primary); }
4591
4618
  .te-resource-card p { margin:0; font-size:13px; flex:1; }
@@ -4616,7 +4643,8 @@ var workbenchTheme = `
4616
4643
  .te-form { display:flex; flex-direction:column; gap:16px; }
4617
4644
  .te-form label { display:flex; flex-direction:column; gap:8px; font-size:13px; }
4618
4645
  .te-editor { min-height:260px; resize:vertical; line-height:1.6; font-family:monospace; }
4619
- @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;} }
4620
4648
  `;
4621
4649
 
4622
4650
  // src/client/styles.ts
@@ -4630,8 +4658,8 @@ var success = "var(--dsw-alias-state-success-primary)";
4630
4658
  var warn = "var(--dsw-alias-state-warn-primary)";
4631
4659
  var brand = "var(--dsw-alias-state-business-primary)";
4632
4660
  var styles = {
4633
- wrap: { display: "flex", flexDirection: "column", gap: 16, padding: 20, maxWidth: 900 },
4634
- 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 },
4635
4663
  title: { margin: 0, color: text },
4636
4664
  muted: { margin: 0, color: textSecondary, fontSize: 13, lineHeight: 1.5 },
4637
4665
  sourceRow: { display: "flex", alignItems: "center", gap: 8 },
@@ -4702,7 +4730,7 @@ var styles = {
4702
4730
  borderTop: `1px solid ${border}`
4703
4731
  },
4704
4732
  // ── flow preset picker ────────────────────────────────────────────────────
4705
- 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 },
4706
4734
  // The adoption row is deliberately separated from the flow picker: choosing a
4707
4735
  // skeleton and adopting a recommended setup are different decisions, and the
4708
4736
  // button is the only thing that writes method into the user's config.
@@ -4748,8 +4776,8 @@ var styles = {
4748
4776
  };
4749
4777
 
4750
4778
  // src/client/TaskEngineSection.tsx
4751
- var import_react = require("react");
4752
- 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");
4753
4781
 
4754
4782
  // src/engine.ts
4755
4783
  function formatResourceRef(ref) {
@@ -4769,7 +4797,7 @@ var GUARD_NAMES = [
4769
4797
  "artifacts_present"
4770
4798
  ];
4771
4799
  function validateWorkflow(config) {
4772
- const problems = [];
4800
+ const problems = [...config.configuration_errors ?? []];
4773
4801
  if (config.stages.length === 0) problems.push("stages must not be empty");
4774
4802
  const seen = /* @__PURE__ */ new Set();
4775
4803
  for (const stage of config.stages) {
@@ -4816,6 +4844,7 @@ function validateWorkflow(config) {
4816
4844
  }
4817
4845
  });
4818
4846
  const bindings = config.stage_bindings ?? {};
4847
+ const skillMethods = /* @__PURE__ */ new Map();
4819
4848
  for (const [stage, binding] of Object.entries(bindings)) {
4820
4849
  if (!config.stages.includes(stage)) {
4821
4850
  problems.push(`stage_bindings: stage "${stage}" is not a stage`);
@@ -4828,6 +4857,19 @@ function validateWorkflow(config) {
4828
4857
  if (!["bundled", "project", "user"].includes(entry.skill.source)) {
4829
4858
  problems.push(`stage_bindings "${stage}": skill "${entry.skill.name}" has unknown source "${String(entry.skill.source)}"`);
4830
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
+ }
4831
4873
  for (const rule of entry.rules ?? []) {
4832
4874
  if (typeof rule?.name !== "string" || rule.name.trim() === "") {
4833
4875
  problems.push(`stage_bindings "${stage}": skill "${entry.skill.name}" has a rule with no name`);
@@ -5019,15 +5061,80 @@ function applyProjectConfig(base, project) {
5019
5061
  if (project === void 0) return base;
5020
5062
  const next = { ...base };
5021
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 = [];
5022
5067
  const bindings = {};
5023
5068
  for (const [stage, binding] of Object.entries(project.stage_bindings)) {
5024
5069
  const entry = {};
5025
- if ((binding.skills ?? []).length > 0) entry.skills = [...binding.skills];
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
+ }
5026
5129
  const legacy = dedupe(binding.legacy_rules ?? []);
5027
5130
  if (legacy.length > 0) entry.legacy_rules = legacy;
5028
5131
  bindings[stage] = entry;
5029
5132
  }
5030
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;
5031
5138
  }
5032
5139
  if (project.commit !== void 0) next.commit = project.commit;
5033
5140
  if (project.artifacts !== void 0) next.artifacts = project.artifacts;
@@ -5048,6 +5155,7 @@ function adoptRecommendation(presetId, current) {
5048
5155
  const config = {
5049
5156
  flow: presetId,
5050
5157
  stage_bindings: current?.stage_bindings ?? rec.stage_bindings ?? {},
5158
+ ...current?.skill_profiles !== void 0 ? { skill_profiles: current.skill_profiles } : {},
5051
5159
  commit,
5052
5160
  artifacts: current?.artifacts ?? rec.artifacts ?? preset2.config.artifacts,
5053
5161
  ...current?.review_depth !== void 0 ? { review_depth: current.review_depth } : rec.review_depth !== void 0 ? { review_depth: rec.review_depth } : {},
@@ -5055,6 +5163,19 @@ function adoptRecommendation(presetId, current) {
5055
5163
  };
5056
5164
  return config;
5057
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 };
5178
+ }
5058
5179
  function resolveFlow(flow, project) {
5059
5180
  const preset2 = FLOW_PRESETS[flow];
5060
5181
  if (preset2 === void 0) {
@@ -5071,33 +5192,296 @@ function describeError(error) {
5071
5192
  return "\u672A\u77E5\u9519\u8BEF";
5072
5193
  }
5073
5194
 
5074
- // 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
5075
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");
5076
5457
  function refFromText(text2) {
5077
5458
  return parseResourceRef(text2) ?? { source: "bundled", name: text2 };
5078
5459
  }
5079
- function resolvedConfig(flow, stageBindings) {
5080
- const resolved = resolveFlow(flow, { flow, stage_bindings: stageBindings });
5460
+ function resolvedConfig(flow, stageBindings, skillProfiles) {
5461
+ const resolved = resolveFlow(flow, { flow, stage_bindings: stageBindings, skill_profiles: skillProfiles });
5081
5462
  return resolved.ok ? resolved.config : FLOW_PRESETS.standard.config;
5082
5463
  }
5083
5464
  function TaskEngineSection(props) {
5084
5465
  const { remote, workspace } = props;
5085
- const [flow, setFlow] = (0, import_react.useState)("standard");
5086
- const [stageBindings, setStageBindings] = (0, import_react.useState)({});
5087
- const [commitRule, setCommitRule] = (0, import_react.useState)(void 0);
5088
- const [artifacts, setArtifacts] = (0, import_react.useState)(void 0);
5089
- const [reviewDepth, setReviewDepth] = (0, import_react.useState)(void 0);
5090
- const [source, setSource] = (0, import_react.useState)("default");
5091
- const [savedAt, setSavedAt] = (0, import_react.useState)("");
5092
- const [dirty, setDirty] = (0, import_react.useState)(false);
5093
- const [loadError, setLoadError] = (0, import_react.useState)("");
5094
- const [saving, setSaving] = (0, import_react.useState)(false);
5095
- const [loading, setLoading] = (0, import_react.useState)(true);
5096
- const [loadAttempt, setLoadAttempt] = (0, import_react.useState)(0);
5097
- const [configProblems, setConfigProblems] = (0, import_react.useState)([]);
5098
- const [skills, setSkills] = (0, import_react.useState)([]);
5099
- const [rules, setRules] = (0, import_react.useState)([]);
5100
- (0, import_react.useEffect)(() => {
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)(() => {
5101
5485
  if (workspace === "") return;
5102
5486
  let alive = true;
5103
5487
  setLoadError("");
@@ -5108,9 +5492,11 @@ function TaskEngineSection(props) {
5108
5492
  if (result.ok) {
5109
5493
  setFlow(result.value.flow);
5110
5494
  setStageBindings(result.value.config.stage_bindings ?? {});
5495
+ setSkillProfiles(result.value.config.skill_profiles ?? {});
5111
5496
  setCommitRule(result.value.config.commit);
5112
5497
  setArtifacts(result.value.config.artifacts);
5113
5498
  setReviewDepth(result.value.config.review_depth);
5499
+ setCommitRequired(result.value.config.commit_required);
5114
5500
  setSource(result.value.source);
5115
5501
  setConfigProblems(result.value.problems);
5116
5502
  setSavedAt("");
@@ -5127,7 +5513,7 @@ function TaskEngineSection(props) {
5127
5513
  alive = false;
5128
5514
  };
5129
5515
  }, [remote, workspace, loadAttempt]);
5130
- const refreshCatalogs = (0, import_react.useCallback)(() => {
5516
+ const refreshCatalogs = (0, import_react3.useCallback)(() => {
5131
5517
  if (workspace === "") return;
5132
5518
  void remote.listSkills(workspace).then((result) => {
5133
5519
  if (result.ok) setSkills(result.value.skills);
@@ -5138,13 +5524,13 @@ function TaskEngineSection(props) {
5138
5524
  }, () => {
5139
5525
  });
5140
5526
  }, [remote, workspace]);
5141
- (0, import_react.useEffect)(() => {
5527
+ (0, import_react3.useEffect)(() => {
5142
5528
  refreshCatalogs();
5143
5529
  }, [refreshCatalogs]);
5144
- const stages = (0, import_react.useMemo)(() => (FLOW_PRESETS[flow] ?? FLOW_PRESETS.standard).config.stages, [flow]);
5145
- const problems = (0, import_react.useMemo)(
5146
- () => validateWorkflow(resolvedConfig(flow, stageBindings)),
5147
- [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]
5148
5534
  );
5149
5535
  const selectFlow = (id) => {
5150
5536
  if (id === flow) return;
@@ -5158,53 +5544,68 @@ function TaskEngineSection(props) {
5158
5544
  if (adopted === void 0) return;
5159
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;
5160
5546
  setStageBindings({ ...adopted.stage_bindings ?? {} });
5547
+ const adoptedFlow = resolveFlow(flow, adopted);
5548
+ setSkillProfiles(adoptedFlow.ok ? adoptedFlow.config.skill_profiles ?? {} : {});
5161
5549
  setCommitRule(adopted.commit);
5162
5550
  setArtifacts(adopted.artifacts);
5163
5551
  setReviewDepth(adopted.review_depth);
5164
5552
  setDirty(true);
5165
5553
  setSavedAt("");
5166
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
+ };
5167
5568
  if (loadError !== "") {
5168
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.wrap, children: [
5169
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { style: styles.title, children: "\u5DE5\u7A0B\u6D41\u7A0B\u914D\u7F6E" }),
5170
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.problems, children: [
5171
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: styles.problemsTitle, children: [
5172
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.StateDot, { state: "error" }),
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" }),
5173
5574
  "\u8BFB\u53D6\u5931\u8D25"
5174
5575
  ] }),
5175
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.muted, children: loadError }),
5176
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { onClick: () => setLoadAttempt((n) => n + 1), children: "\u91CD\u8BD5" })
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" })
5177
5578
  ] })
5178
5579
  ] });
5179
5580
  }
5180
- if (loading) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { role: "status", children: "\u6B63\u5728\u8BFB\u53D6\u6D41\u7A0B\u914D\u7F6E\u2026" });
5181
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.wrap, children: [
5182
- configProblems.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { role: "alert", style: styles.problems, children: [
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: [
5183
5584
  "\u539F\u914D\u7F6E\u6709\u95EE\u9898\uFF1A",
5184
5585
  configProblems.join("\uFF1B"),
5185
5586
  "\u3002\u8BF7\u9009\u62E9\u6709\u6548\u9884\u8BBE\u5E76\u4FDD\u5B58\u4FEE\u590D\u3002"
5186
5587
  ] }),
5187
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.head, children: [
5188
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { style: styles.title, children: "\u5DE5\u7A0B\u6D41\u7A0B\u914D\u7F6E" }),
5189
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.muted, children: "\u6D41\u7A0B\u51B3\u5B9A\u5DE5\u4F5C\u600E\u4E48\u6D41\u8F6C\uFF08\u9636\u6BB5\u4E0E\u95E8\u7981\uFF09\uFF1B\u6280\u80FD\u3001\u89C4\u5219\u3001\u63D0\u4EA4\u683C\u5F0F\u548C\u4EA7\u7269\u5B57\u6BB5\u7531\u4F60\u81EA\u5DF1\u914D\u7F6E\u3002 \u9700\u8981\u4E00\u4EFD\u73B0\u6210\u7684\u8D77\u70B9\u65F6\uFF0C\u53EF\u4EE5\u300C\u91C7\u7528\u63A8\u8350\u914D\u7F6E\u300D\u2014\u2014\u91C7\u7528\u540E\u8FD9\u4E9B\u5C31\u5B8C\u5168\u5C5E\u4E8E\u4F60\uFF0C\u53EF\u968F\u610F\u4FEE\u6539\u6216\u5220\u9664\u3002" })
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" })
5190
5591
  ] }),
5191
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.adoptRow, children: [
5192
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_dsh_client_ui_primitives.Button, { size: "sm", onClick: adopt, children: [
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: [
5193
5594
  "\u91C7\u7528\u300C",
5194
5595
  FLOW_PRESETS[flow]?.label ?? flow,
5195
5596
  "\u300D\u7684\u63A8\u8350\u914D\u7F6E"
5196
5597
  ] }),
5197
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.muted, children: "\u5199\u5165\u63A8\u8350\u6280\u80FD\u3001\u63D0\u4EA4\u4FE1\u606F\u683C\u5F0F\u4E0E\u4EA7\u7269\u5B57\u6BB5\u3002\u4EC5\u5728\u4F60\u70B9\u51FB\u65F6\u53D1\u751F\u4E00\u6B21\uFF1B\u5220\u9664\u540E\u4E0D\u4F1A\u81EA\u52A8\u8865\u56DE\u3002" })
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" })
5198
5599
  ] }),
5199
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.sourceRow, children: [
5200
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.StateDot, { state: source === "project" ? "done" : source === "invalid" ? "warning" : "ongoing" }),
5201
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.sourceText, children: sourceText(source) })
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) })
5202
5603
  ] }),
5203
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.field, children: [
5204
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { children: "\u6D41\u7A0B\u9884\u8BBE" }),
5205
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.flowGrid, children: FLOW_OPTIONS.map((option) => {
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) => {
5206
5607
  const active = flow === option.id;
5207
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
5608
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
5208
5609
  "button",
5209
5610
  {
5210
5611
  type: "button",
@@ -5214,45 +5615,49 @@ function TaskEngineSection(props) {
5214
5615
  },
5215
5616
  style: { ...styles.flowOption, ...active ? styles.flowOptionActive : {} },
5216
5617
  children: [
5217
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: styles.flowOptionTitle, children: [
5218
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.StateDot, { state: active ? "done" : "ongoing", size: 8 }),
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 }),
5219
5620
  option.label
5220
5621
  ] }),
5221
- /* @__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 })
5222
5623
  ]
5223
5624
  },
5224
5625
  option.id
5225
5626
  );
5226
5627
  }) })
5227
5628
  ] }),
5228
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SectionCard, { icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconSettingsOutline16, { size: 16 }), title: "\u9636\u6BB5\u6280\u80FD / \u89C4\u5219", hint: "\u9009\u62E9\u8282\u70B9\uFF0C\u518D\u52FE\u9009\u9644\u52A0\u6280\u80FD\u4E0E\u89C4\u5219\u3002\u9884\u8BBE\u9ED8\u8BA4\u7ED1\u5B9A\u56FA\u5B9A\u4FDD\u7559\uFF1B\u65B0\u5EFA\u6216\u7F16\u8F91\u5185\u5BB9\u8BF7\u524D\u5F80\u4E0A\u65B9\u201C\u6280\u80FD\u201D\u6216\u201C\u89C4\u5219\u201D\u9875\u3002", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BindingEditor, { stages, defaults: (FLOW_PRESETS[flow] ?? FLOW_PRESETS.standard).config.stage_bindings ?? {}, stageBindings, setStageBindings: (next) => {
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) => {
5229
5630
  setStageBindings(next);
5230
5631
  setDirty(true);
5231
5632
  setSavedAt("");
5232
- }, skills, rules }) }),
5233
- problems.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.problems, children: [
5234
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: styles.problemsTitle, children: [
5235
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.StateDot, { state: "error" }),
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" }),
5236
5641
  "\u6709 ",
5237
5642
  problems.length,
5238
5643
  " \u4E2A\u95EE\u9898\uFF08\u4FDD\u5B58\u4F1A\u88AB\u62D2\u7EDD\uFF09"
5239
5644
  ] }),
5240
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { style: styles.problemsList, children: problems.map((p) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("li", { children: p }, p)) })
5241
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: styles.okText, children: [
5242
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.StateDot, { state: "done" }),
5243
- 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"
5244
5649
  ] }),
5245
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.actions, children: [
5246
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
5247
- 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,
5248
5653
  {
5249
5654
  variant: "primary",
5250
5655
  size: "md",
5251
- 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 }),
5252
5657
  disabled: problems.length > 0 || saving,
5253
5658
  onClick: () => {
5254
5659
  setSaving(true);
5255
- void save(remote, { flow, stage_bindings: stageBindings, ...commitRule !== void 0 ? { commit: commitRule } : {}, ...artifacts !== void 0 ? { artifacts } : {}, ...reviewDepth !== void 0 ? { review_depth: reviewDepth } : {} }, workspace, setSavedAt, setSource).then((ok) => {
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) => {
5256
5661
  if (ok) {
5257
5662
  setConfigProblems([]);
5258
5663
  setDirty(false);
@@ -5262,11 +5667,24 @@ function TaskEngineSection(props) {
5262
5667
  children: saving ? "\u6B63\u5728\u4FDD\u5B58\u2026" : dirty ? "\u4FDD\u5B58\u5230 .dsh/eng.json" : "\u5DF2\u4FDD\u5B58 \xB7 \u65E0\u9700\u4FDD\u5B58"
5263
5668
  }
5264
5669
  ),
5265
- savedAt !== "" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: styles.okText, children: [
5266
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.StateDot, { state: savedAt.startsWith("\u5DF2") ? "done" : "error" }),
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" }),
5267
5672
  savedAt
5268
5673
  ] }) : null
5269
- ] })
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
5270
5688
  ] });
5271
5689
  }
5272
5690
  function sourceText(source) {
@@ -5280,9 +5698,9 @@ function sourceText(source) {
5280
5698
  }
5281
5699
  }
5282
5700
  function SectionCard({ icon, title, hint, children }) {
5283
- const [open, setOpen] = (0, import_react.useState)(true);
5284
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.section, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
5285
- 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,
5286
5704
  {
5287
5705
  icon,
5288
5706
  title,
@@ -5294,187 +5712,115 @@ function SectionCard({ icon, title, hint, children }) {
5294
5712
  setOpen(!open);
5295
5713
  },
5296
5714
  keepContentWhenOpen: true,
5297
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.cardBody, children: [
5298
- hint !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.muted, children: hint }) : null,
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,
5299
5717
  children
5300
5718
  ] })
5301
5719
  }
5302
5720
  ) });
5303
5721
  }
5304
- function BindingEditor({ stages, defaults, stageBindings, setStageBindings, skills, rules }) {
5305
- const [stage, setStage] = (0, import_react.useState)(stages[0] ?? "");
5306
- const [expanded, setExpanded] = (0, import_react.useState)(null);
5307
- const [query, setQuery] = (0, import_react.useState)("");
5308
- const [onlySelected, setOnlySelected] = (0, import_react.useState)(false);
5309
- const [ruleQuery, setRuleQuery] = (0, import_react.useState)("");
5310
- const [ruleOnlySelected, setRuleOnlySelected] = (0, import_react.useState)(false);
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)("");
5311
5725
  const currentStage = stages.includes(stage) ? stage : stages[0] ?? "";
5312
5726
  const bindingFor = (name) => stageBindings[name] ?? {};
5313
- const presetSkills = (name) => defaults[name]?.skills ?? [];
5314
- const isPresetSkill = (name, raw) => presetSkills(name).some((entry) => formatResourceRef(entry.skill) === raw);
5315
- const visibleSkills = () => {
5316
- const bound = bindingFor(currentStage).skills ?? [];
5317
- const boundKeys = new Set(bound.map((entry) => formatResourceRef(entry.skill)));
5318
- const needle = query.trim().toLowerCase();
5319
- return skills.filter((entry) => {
5320
- const raw = formatResourceRef(entry.ref);
5321
- const inForce = boundKeys.has(raw) || isPresetSkill(currentStage, raw);
5322
- if (onlySelected && !inForce) return false;
5323
- if (needle === "") return true;
5324
- return inForce || entry.name.toLowerCase().includes(needle) || entry.description.toLowerCase().includes(needle) || entry.sourceLabel.toLowerCase().includes(needle);
5325
- });
5326
- };
5327
- const visibleRulesFor = (bound) => {
5328
- const chosen = new Set(bound.rules.map((rule) => formatResourceRef(rule)));
5329
- const needle = ruleQuery.trim().toLowerCase();
5330
- return rules.filter((rule) => {
5331
- const raw = formatResourceRef(rule.ref);
5332
- if (ruleOnlySelected && !chosen.has(raw)) return false;
5333
- if (needle === "") return true;
5334
- return chosen.has(raw) || rule.name.toLowerCase().includes(needle) || rule.sourceLabel.toLowerCase().includes(needle);
5335
- });
5336
- };
5337
5727
  const setSkills = (name, next) => {
5338
5728
  setStageBindings({ ...stageBindings, [name]: { ...bindingFor(name), skills: next } });
5339
5729
  };
5340
5730
  const toggleSkill = (raw) => {
5341
- if (currentStage === "" || isPresetSkill(currentStage, raw)) return;
5342
- const current = bindingFor(currentStage).skills ?? [];
5343
- const next = current.some((entry) => formatResourceRef(entry.skill) === raw) ? current.filter((entry) => formatResourceRef(entry.skill) !== raw) : [...current, { skill: refFromText(raw), rules: [] }].sort((a, b) => formatResourceRef(a.skill).localeCompare(formatResourceRef(b.skill)));
5344
- setSkills(currentStage, next);
5345
- };
5346
- const toggleRule = (skillRaw, ruleRaw) => {
5347
5731
  if (currentStage === "") return;
5348
5732
  const current = bindingFor(currentStage).skills ?? [];
5349
- setSkills(currentStage, current.map((entry) => {
5350
- if (formatResourceRef(entry.skill) !== skillRaw) return entry;
5351
- const has = entry.rules.some((rule) => formatResourceRef(rule) === ruleRaw);
5352
- const next = has ? entry.rules.filter((rule) => formatResourceRef(rule) !== ruleRaw) : [...entry.rules, refFromText(ruleRaw)].sort((a, b) => formatResourceRef(a).localeCompare(formatResourceRef(b)));
5353
- return { ...entry, rules: next };
5354
- }));
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);
5355
5738
  };
5356
5739
  if (currentStage === "") {
5357
- 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" });
5358
5741
  }
5359
5742
  const boundSkills = bindingFor(currentStage).skills ?? [];
5360
5743
  const unassigned = bindingFor(currentStage).legacy_rules ?? [];
5361
- const presetCount = presetSkills(currentStage).length;
5362
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.section, children: [
5363
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.hint, children: "\u8282\u70B9\u53EA\u9009\u62E9\u6280\u80FD\uFF1B\u89C4\u5219\u5C5E\u4E8E\u6280\u80FD\u2014\u2014\u70B9\u5F00\u4E00\u4E2A\u6280\u80FD\u5C31\u80FD\u770B\u5230\u5B83\u5B8C\u6574\u7684\u89C4\u5219\u5217\u8868\uFF0C\u6302\u5230\u4EFB\u4F55\u8282\u70B9\u90FD\u662F\u540C\u4E00\u5957\u89C4\u5219\u3002 \u9700\u8981\u540C\u4E00\u6280\u80FD\u7528\u4E0D\u540C\u89C4\u5219\u65F6\uFF0C\u590D\u5236\u6210\u53E6\u4E00\u4E2A\u6280\u80FD\u518D\u5206\u522B\u914D\u7F6E\u3002" }),
5364
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.field, children: [
5365
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.bindingLabel, children: "\u9009\u62E9\u8282\u70B9" }),
5366
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.chips, children: stages.map((s) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Pill, { active: s === currentStage, onClick: () => {
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: () => {
5367
5751
  setStage(s);
5368
5752
  }, children: s }, s)) })
5369
5753
  ] }),
5370
- 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: [
5371
5755
  "\u4EE5\u4E0B\u89C4\u5219\u5C5E\u4E8E",
5372
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: "\u8282\u70B9" }),
5756
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("strong", { children: "\u8282\u70B9" }),
5373
5757
  "\u800C\u4E0D\u662F\u4EFB\u4F55\u6280\u80FD\uFF08\u65E7\u914D\u7F6E\uFF09\uFF1A",
5374
5758
  unassigned.join("\u3001"),
5375
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"
5376
5760
  ] }) : null,
5377
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "te-binding-grid", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "te-binding-picker", "aria-label": "\u6280\u80FD\u7ED1\u5B9A", children: [
5378
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "te-binding-heading", children: [
5379
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h4", { children: "\u6280\u80FD" }),
5380
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "te-binding-count", children: [
5381
- "\u5DF2\u9009 ",
5382
- boundSkills.length,
5383
- presetCount > 0 ? `\uFF08\u542B ${presetCount} \u9879\u9884\u8BBE\uFF09` : "",
5384
- visibleSkills().length !== skills.length ? ` \xB7 \u663E\u793A ${visibleSkills().length}/${skills.length}` : ""
5385
- ] })
5386
- ] }),
5387
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "te-binding-controls", children: [
5388
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
5389
- "input",
5390
- {
5391
- className: "te-binding-search",
5392
- type: "search",
5393
- value: query,
5394
- placeholder: "\u641C\u7D22\u6280\u80FD\u540D\u6216\u8BF4\u660E\u2026",
5395
- "aria-label": "\u641C\u7D22\u6280\u80FD",
5396
- onChange: (event) => setQuery(event.target.value)
5397
- }
5398
- ),
5399
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "te-binding-filter", children: [
5400
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "checkbox", checked: onlySelected, onChange: () => setOnlySelected((value) => !value) }),
5401
- " ",
5402
- "\u4EC5\u770B\u5DF2\u9009"
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)))
5403
5784
  ] })
5404
5785
  ] }),
5405
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "te-binding-list", role: "group", "aria-label": "\u6280\u80FD\u5217\u8868", tabIndex: 0, children: [
5406
- skills.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "te-binding-empty", children: "\u6682\u65E0\u6280\u80FD\uFF0C\u8BF7\u5728\u4E0A\u65B9\u201C\u6280\u80FD\u201D\u9875\u6DFB\u52A0\u3002" }) : null,
5407
- skills.length > 0 && visibleSkills().length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "te-binding-empty", children: "\u6CA1\u6709\u5339\u914D\u7684\u6280\u80FD\u3002" }) : null,
5408
- visibleSkills().map((entry) => {
5409
- const raw = formatResourceRef(entry.ref);
5410
- const bound = boundSkills.find((candidate) => formatResourceRef(candidate.skill) === raw);
5411
- const preset2 = isPresetSkill(currentStage, raw);
5412
- const open = expanded === raw;
5413
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: `te-binding-option${bound !== void 0 ? " is-selected" : ""}`, children: [
5414
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
5415
- "input",
5416
- {
5417
- type: "checkbox",
5418
- "aria-label": raw,
5419
- checked: bound !== void 0,
5420
- disabled: preset2,
5421
- onChange: () => toggleSkill(raw)
5422
- }
5423
- ),
5424
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "te-binding-detail", children: [
5425
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "te-binding-name", children: [
5426
- entry.name,
5427
- preset2 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "te-source-badge", children: "\u9884\u8BBE" }) : null
5428
- ] }),
5429
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "te-binding-meta", children: [
5430
- entry.sourceLabel,
5431
- " \xB7 ",
5432
- bound === void 0 ? "\u672A\u7ED1\u5B9A" : `${bound.rules.length} \u6761\u89C4\u5219`
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
+ ] })
5433
5814
  ] }),
5434
- bound !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "te-link", onClick: () => setExpanded(open ? null : raw), children: open ? "\u6536\u8D77\u89C4\u5219" : "\u89C4\u5219\u8BBE\u7F6E" }) : null,
5435
- open && bound !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "te-rule-list", children: [
5436
- ruleQuery !== "" || ruleOnlySelected ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "te-binding-meta", children: [
5437
- rules.length,
5438
- " \u6761\u53EF\u7528\u89C4\u5219"
5439
- ] }),
5440
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
5441
- "input",
5442
- {
5443
- className: "te-binding-search",
5444
- type: "search",
5445
- value: ruleQuery,
5446
- placeholder: "\u8FC7\u6EE4\u89C4\u5219\u2026",
5447
- "aria-label": `\u8FC7\u6EE4 ${entry.name} \u7684\u89C4\u5219`,
5448
- onChange: (event) => setRuleQuery(event.target.value)
5449
- }
5450
- ),
5451
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "te-binding-filter", children: [
5452
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "checkbox", checked: ruleOnlySelected, onChange: () => setRuleOnlySelected((value) => !value) }),
5453
- " ",
5454
- "\u4EC5\u770B\u5DF2\u9009"
5455
- ] }),
5456
- rules.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "te-binding-meta", children: "\u89C4\u5219\u5E93\u4E3A\u7A7A\u3002" }) : null,
5457
- rules.length > 0 && visibleRulesFor(bound).length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "te-binding-meta", children: "\u6CA1\u6709\u5339\u914D\u7684\u89C4\u5219\u3002" }) : null,
5458
- visibleRulesFor(bound).map((rule) => {
5459
- const ruleRaw = formatResourceRef(rule.ref);
5460
- const on = bound.rules.some((candidate) => formatResourceRef(candidate) === ruleRaw);
5461
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "te-binding-filter", children: [
5462
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "checkbox", checked: on, onChange: () => toggleRule(raw, ruleRaw) }),
5463
- " ",
5464
- rule.name,
5465
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "te-binding-meta", children: [
5466
- "\uFF08",
5467
- rule.sourceLabel,
5468
- "\uFF09"
5469
- ] })
5470
- ] }, ruleRaw);
5471
- })
5472
- ] }) : null
5473
- ] })
5474
- ] }, raw);
5475
- })
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
+ ] })
5476
5822
  ] })
5477
- ] }) }, currentStage)
5823
+ ] }, currentStage)
5478
5824
  ] });
5479
5825
  }
5480
5826
  async function save(remote, config, workspace, setSavedAt, setSource) {
@@ -5498,8 +5844,8 @@ async function save(remote, config, workspace, setSavedAt, setSource) {
5498
5844
  }
5499
5845
 
5500
5846
  // src/client/InitPanel.tsx
5501
- var import_react2 = require("react");
5502
- 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");
5503
5849
  var MD_LABELS = { code: { copyLabel: "\u590D\u5236", copiedLabel: "\u5DF2\u590D\u5236" }, footnotes: "\u811A\u6CE8" };
5504
5850
  var INIT_TIMEOUT_S = 150;
5505
5851
  var card = {
@@ -5511,14 +5857,14 @@ var card = {
5511
5857
  padding: "12px 14px"
5512
5858
  };
5513
5859
  function InitPanel({ workspace, remote }) {
5514
- const [view, setView] = (0, import_react2.useState)(null);
5515
- const [generating, setGenerating] = (0, import_react2.useState)(false);
5516
- const [elapsed, setElapsed] = (0, import_react2.useState)(0);
5517
- const [draft, setDraft] = (0, import_react2.useState)(null);
5518
- const [editing, setEditing] = (0, import_react2.useState)(false);
5519
- const [body2, setBody] = (0, import_react2.useState)("");
5520
- const [msg, setMsg] = (0, import_react2.useState)("");
5521
- (0, import_react2.useEffect)(() => {
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)(() => {
5522
5868
  if (!generating) {
5523
5869
  setElapsed(0);
5524
5870
  return;
@@ -5532,13 +5878,13 @@ function InitPanel({ workspace, remote }) {
5532
5878
  clearInterval(timer);
5533
5879
  };
5534
5880
  }, [generating]);
5535
- const refresh = (0, import_react2.useCallback)(() => {
5881
+ const refresh = (0, import_react4.useCallback)(() => {
5536
5882
  void remote.readInit(workspace).then((r) => {
5537
5883
  if (r.ok) setView(r.value);
5538
5884
  }, () => {
5539
5885
  });
5540
5886
  }, [remote, workspace]);
5541
- (0, import_react2.useEffect)(() => {
5887
+ (0, import_react4.useEffect)(() => {
5542
5888
  refresh();
5543
5889
  }, [refresh]);
5544
5890
  const generate = async () => {
@@ -5581,45 +5927,45 @@ function InitPanel({ workspace, remote }) {
5581
5927
  setMsg("");
5582
5928
  };
5583
5929
  const exists = view?.exists === true;
5584
- return (0, import_react2.createElement)(
5930
+ return (0, import_react4.createElement)(
5585
5931
  "div",
5586
5932
  { style: styles.section },
5587
- (0, import_react2.createElement)(
5933
+ (0, import_react4.createElement)(
5588
5934
  "div",
5589
5935
  { style: card },
5590
- (0, import_react2.createElement)(
5936
+ (0, import_react4.createElement)(
5591
5937
  "div",
5592
5938
  { style: { display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap" } },
5593
- (0, import_react2.createElement)(import_dsh_client_ui_primitives2.StateDot, { state: exists ? "done" : "ongoing" }),
5594
- (0, import_react2.createElement)("span", { style: styles.bindingLabel }, exists ? `\u5DF2\u521D\u59CB\u5316 \xB7 ${view.lines} \u884C\uFF08\u4E0A\u9650 200\uFF09` : "\u672A\u521D\u59CB\u5316"),
5595
- view?.path !== void 0 ? (0, import_react2.createElement)("span", { style: styles.sourceBadge }, `\u5DF2\u5B9A\u4F4D\u5230 ${view.path}`) : null
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
5596
5942
  ),
5597
- (0, import_react2.createElement)(
5943
+ (0, import_react4.createElement)(
5598
5944
  "p",
5599
5945
  { style: styles.muted },
5600
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"
5601
5947
  ),
5602
- exists && !editing && draft === null ? (0, import_react2.createElement)(
5948
+ exists && !editing && draft === null ? (0, import_react4.createElement)(
5603
5949
  "div",
5604
5950
  { style: styles.mdPreview },
5605
- (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 })
5606
5952
  ) : null,
5607
- draft !== null ? (0, import_react2.createElement)(
5953
+ draft !== null ? (0, import_react4.createElement)(
5608
5954
  "div",
5609
5955
  { style: styles.section },
5610
- (0, import_react2.createElement)(
5956
+ (0, import_react4.createElement)(
5611
5957
  "div",
5612
5958
  { style: styles.sourceRow },
5613
- (0, import_react2.createElement)(import_dsh_client_ui_primitives2.StateDot, { state: "ongoing", size: 8 }),
5614
- (0, import_react2.createElement)("span", { style: styles.sourceBadge }, `AI \u8349\u7A3F \xB7 ${draft.lines} \u884C \xB7 \u5C1A\u672A\u5199\u5165`)
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`)
5615
5961
  ),
5616
- (0, import_react2.createElement)(
5962
+ (0, import_react4.createElement)(
5617
5963
  "div",
5618
5964
  { style: styles.mdPreview },
5619
- (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 })
5620
5966
  )
5621
5967
  ) : null,
5622
- editing ? (0, import_react2.createElement)("textarea", {
5968
+ editing ? (0, import_react4.createElement)("textarea", {
5623
5969
  style: { ...styles.textarea, minHeight: 300 },
5624
5970
  placeholder: "AGENTS.md \u6B63\u6587\uFF08Markdown\uFF0C\u2264200 \u884C\uFF09",
5625
5971
  value: body2,
@@ -5627,16 +5973,16 @@ function InitPanel({ workspace, remote }) {
5627
5973
  setBody(ev.target.value);
5628
5974
  }
5629
5975
  }) : null,
5630
- generating ? (0, import_react2.createElement)(
5976
+ generating ? (0, import_react4.createElement)(
5631
5977
  "p",
5632
5978
  { style: styles.status },
5633
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`
5634
5980
  ) : null,
5635
- msg !== "" ? (0, import_react2.createElement)("p", { style: styles.status }, msg) : null,
5636
- 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)(
5637
5983
  "div",
5638
5984
  { style: styles.row },
5639
- (0, import_react2.createElement)(import_dsh_client_ui_primitives2.Button, {
5985
+ (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, {
5640
5986
  variant: "primary",
5641
5987
  size: "md",
5642
5988
  disabled: draft.lines > 200,
@@ -5645,14 +5991,14 @@ function InitPanel({ workspace, remote }) {
5645
5991
  void write(draft.content, exists);
5646
5992
  }
5647
5993
  }, exists ? "\u4FDD\u5B58\u5E76\u8986\u76D6" : "\u4FDD\u5B58"),
5648
- draft.lines > 200 ? (0, import_react2.createElement)("span", { style: styles.sourceBadge }, `\u8349\u7A3F ${draft.lines} \u884C\u8D85\u9650\uFF0C\u8BF7\u70B9\u300C\u653E\u5F03\u300D\u540E\u91CD\u8BD5`) : null,
5649
- (0, import_react2.createElement)(import_dsh_client_ui_primitives2.Button, { variant: "ghost", size: "md", onClick: () => {
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: () => {
5650
5996
  setDraft(null);
5651
5997
  } }, "\u653E\u5F03")
5652
- ) : editing ? (0, import_react2.createElement)(
5998
+ ) : editing ? (0, import_react4.createElement)(
5653
5999
  "div",
5654
6000
  { style: styles.row },
5655
- (0, import_react2.createElement)(import_dsh_client_ui_primitives2.Button, {
6001
+ (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, {
5656
6002
  variant: "primary",
5657
6003
  size: "md",
5658
6004
  disabled: body2.trim() === "",
@@ -5661,13 +6007,13 @@ function InitPanel({ workspace, remote }) {
5661
6007
  void write(body2, exists);
5662
6008
  }
5663
6009
  }, exists ? "\u4FDD\u5B58\u5E76\u8986\u76D6" : "\u4FDD\u5B58"),
5664
- (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: () => {
5665
6011
  setEditing(false);
5666
6012
  } }, "\u53D6\u6D88")
5667
- ) : (0, import_react2.createElement)(
6013
+ ) : (0, import_react4.createElement)(
5668
6014
  "div",
5669
6015
  { style: styles.row },
5670
- (0, import_react2.createElement)(import_dsh_client_ui_primitives2.Button, {
6016
+ (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, {
5671
6017
  variant: "primary",
5672
6018
  size: "md",
5673
6019
  disabled: generating,
@@ -5676,203 +6022,54 @@ function InitPanel({ workspace, remote }) {
5676
6022
  void generate();
5677
6023
  }
5678
6024
  }, exists ? "\u91CD\u65B0\u521D\u59CB\u5316\uFF08AI \u626B\u63CF\u8986\u76D6\uFF09" : "\u8BA9 AI \u521D\u59CB\u5316"),
5679
- 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
5680
6026
  )
5681
6027
  )
5682
6028
  );
5683
6029
  }
5684
6030
 
5685
6031
  // src/client/SkillManager.tsx
5686
- var import_react5 = require("react");
5687
-
5688
- // src/client/ResourceManager.tsx
5689
- var import_react4 = require("react");
5690
- var import_dsh_client_ui_primitives4 = require("@deepseek-ai/dsh-client-ui-primitives");
5691
-
5692
- // src/client/ResourceModal.tsx
5693
- var import_react3 = require("react");
5694
- var import_react_dom = require("react-dom");
5695
- var import_dsh_client_ui_primitives3 = require("@deepseek-ai/dsh-client-ui-primitives");
5696
- var rootStyle = {
5697
- position: "fixed",
5698
- inset: 0,
5699
- zIndex: 1e3,
5700
- display: "flex",
5701
- alignItems: "center",
5702
- justifyContent: "center",
5703
- padding: 24
5704
- };
5705
- var maskStyle = {
5706
- position: "absolute",
5707
- inset: 0,
5708
- background: "var(--dsw-alias-bg-mask-1)",
5709
- backdropFilter: "var(--dsw-mask-blur)"
5710
- };
5711
- var dialogStyle = {
5712
- position: "relative",
5713
- zIndex: 1,
5714
- display: "flex",
5715
- flexDirection: "column",
5716
- width: "min(760px, 100%)",
5717
- maxHeight: "85vh",
5718
- borderRadius: 24,
5719
- background: "var(--dsw-alias-bg-layer-2)",
5720
- boxShadow: "var(--dsw-elevation-prominent)",
5721
- overflow: "hidden"
5722
- };
5723
- var headerStyle = {
5724
- display: "flex",
5725
- alignItems: "center",
5726
- justifyContent: "space-between",
5727
- gap: 8,
5728
- padding: "18px 18px 10px 24px",
5729
- flex: "none"
5730
- };
5731
- var titleStyle = {
5732
- margin: 0,
5733
- fontSize: 16,
5734
- lineHeight: "24px",
5735
- fontWeight: 500,
5736
- color: "var(--dsw-alias-label-primary)"
5737
- };
5738
- var closeBtnStyle = {
5739
- flex: "none",
5740
- display: "inline-flex",
5741
- alignItems: "center",
5742
- justifyContent: "center",
5743
- width: 28,
5744
- height: 28,
5745
- border: "none",
5746
- borderRadius: 8,
5747
- background: "transparent",
5748
- cursor: "pointer",
5749
- color: "var(--dsw-alias-label-secondary)",
5750
- padding: 0
5751
- };
5752
- var descStyle = {
5753
- margin: 0,
5754
- padding: "0 24px",
5755
- fontSize: 13,
5756
- lineHeight: "20px",
5757
- color: "var(--dsw-alias-label-secondary)",
5758
- flex: "none"
5759
- };
5760
- var bodyStyle = {
5761
- flex: "1 1 auto",
5762
- minHeight: 0,
5763
- overflowY: "auto",
5764
- padding: "16px 24px 4px",
5765
- display: "flex",
5766
- flexDirection: "column"
5767
- };
5768
- var footerStyle = {
5769
- display: "flex",
5770
- alignItems: "center",
5771
- justifyContent: "flex-end",
5772
- gap: 8,
5773
- padding: "12px 24px 20px",
5774
- flex: "none"
5775
- };
5776
- function ResourceModal({ title, description, onClose, footer, children }) {
5777
- const dialog = (0, import_react3.useRef)(null);
5778
- const closer = (0, import_react3.useRef)(onClose);
5779
- closer.current = onClose;
5780
- (0, import_react3.useEffect)(() => {
5781
- const previous = document.activeElement;
5782
- dialog.current?.focus();
5783
- const onKey = (e) => {
5784
- if (!dialog.current?.contains(document.activeElement)) return;
5785
- if (e.key === "Escape") {
5786
- e.preventDefault();
5787
- e.stopPropagation();
5788
- closer.current();
5789
- return;
5790
- }
5791
- if (e.key !== "Tab") return;
5792
- 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);
5793
- const first = nodes[0], last = nodes[nodes.length - 1];
5794
- if (!first || !last) {
5795
- e.preventDefault();
5796
- return;
5797
- }
5798
- if (e.shiftKey && (document.activeElement === first || document.activeElement === dialog.current)) {
5799
- e.preventDefault();
5800
- last.focus();
5801
- } else if (!e.shiftKey && (document.activeElement === last || document.activeElement === dialog.current)) {
5802
- e.preventDefault();
5803
- first.focus();
5804
- }
5805
- };
5806
- document.addEventListener("keydown", onKey);
5807
- return () => {
5808
- document.removeEventListener("keydown", onKey);
5809
- if (previous?.isConnected) previous.focus();
5810
- };
5811
- }, []);
5812
- return (0, import_react_dom.createPortal)(
5813
- (0, import_react3.createElement)(
5814
- "div",
5815
- { style: rootStyle, className: "te-modal", role: "presentation" },
5816
- (0, import_react3.createElement)("div", { style: maskStyle, "aria-hidden": true, onClick: onClose }),
5817
- (0, import_react3.createElement)(
5818
- "div",
5819
- { style: dialogStyle, ref: dialog, tabIndex: -1, role: "dialog", "aria-modal": true, "aria-label": title },
5820
- (0, import_react3.createElement)(
5821
- "div",
5822
- { style: headerStyle },
5823
- (0, import_react3.createElement)("h2", { style: titleStyle }, title),
5824
- (0, import_react3.createElement)(
5825
- "button",
5826
- { type: "button", style: closeBtnStyle, "aria-label": "\u5173\u95ED", onClick: onClose },
5827
- (0, import_react3.createElement)(import_dsh_client_ui_primitives3.IconCloseOutline16, { size: 14 })
5828
- )
5829
- ),
5830
- description !== void 0 && description !== "" ? (0, import_react3.createElement)("p", { style: descStyle }, description) : null,
5831
- (0, import_react3.createElement)("div", { style: bodyStyle }, children),
5832
- footer !== void 0 ? (0, import_react3.createElement)("div", { style: footerStyle }, footer) : null
5833
- )
5834
- ),
5835
- document.body
5836
- );
5837
- }
6032
+ var import_react6 = require("react");
5838
6033
 
5839
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");
5840
6037
  var labels = { code: { copyLabel: "\u590D\u5236", copiedLabel: "\u5DF2\u590D\u5236" }, footnotes: "\u811A\u6CE8" };
5841
6038
  var levelOf = (row) => row.source === "bundled" ? "bundled" : row.source.startsWith("user") ? "user" : "project";
5842
6039
  var sourceText2 = (source) => source === "bundled" ? "\u5185\u7F6E" : source.startsWith("user") ? "\u4E2A\u4EBA" : "\u9879\u76EE";
5843
6040
  var sizeText = (bytes) => bytes < 1024 ? `${bytes} B` : bytes < 1024 * 1024 ? `${(bytes / 1024).toFixed(1)} KB` : `${(bytes / 1024 / 1024).toFixed(1)} MB`;
5844
6041
  var fail = (r) => describeError(r.error ?? "\u64CD\u4F5C\u5931\u8D25");
5845
- function ResourceManager({ workspace, remote, kind }) {
6042
+ function ResourceManager({ workspace, remote, kind, onConfigureSkill }) {
5846
6043
  const noun = kind === "skill" ? "\u6280\u80FD" : "\u89C4\u5219";
5847
- const [rows, setRows] = (0, import_react4.useState)([]);
5848
- const [query, setQuery] = (0, import_react4.useState)("");
5849
- const [filter, setFilter] = (0, import_react4.useState)("all");
5850
- const [notice, setNotice] = (0, import_react4.useState)("");
5851
- const [error, setError] = (0, import_react4.useState)("");
5852
- const [loading, setLoading] = (0, import_react4.useState)(true);
5853
- const [revision, refresh] = (0, import_react4.useState)(0);
5854
- const [busy, setBusy] = (0, import_react4.useState)(false);
5855
- const [roots, setRoots] = (0, import_react4.useState)(null);
5856
- const [importing, setImporting] = (0, import_react4.useState)(false);
5857
- const [request, setRequest] = (0, import_react4.useState)(null);
5858
- const [preview, setPreview] = (0, import_react4.useState)(null);
5859
- const [level, setLevel] = (0, import_react4.useState)("project");
5860
- const [manual, setManual] = (0, import_react4.useState)(false);
5861
- const [sourceDir, setSourceDir] = (0, import_react4.useState)("");
5862
- const [dirs, setDirs] = (0, import_react4.useState)([]);
5863
- const [browsePath, setBrowsePath] = (0, import_react4.useState)("");
5864
- const [editing, setEditing] = (0, import_react4.useState)(null);
5865
- const [viewing, setViewing] = (0, import_react4.useState)(false);
5866
- const [name, setName] = (0, import_react4.useState)("");
5867
- const [description, setDescription] = (0, import_react4.useState)("");
5868
- const [whenToUse, setWhenToUse] = (0, import_react4.useState)("");
5869
- const [body2, setBody] = (0, import_react4.useState)("");
5870
- const [deleting, setDeleting] = (0, import_react4.useState)(null);
5871
- const input = (0, import_react4.useRef)(null);
5872
- const fileEpoch = (0, import_react4.useRef)(0);
5873
- const browseEpoch = (0, import_react4.useRef)(0);
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);
5874
6071
  const readonly = editing !== null && editing !== "new" && levelOf(editing) === "bundled";
5875
- (0, import_react4.useEffect)(() => {
6072
+ (0, import_react5.useEffect)(() => {
5876
6073
  let active = true;
5877
6074
  setLoading(true);
5878
6075
  setRows([]);
@@ -5899,7 +6096,7 @@ function ResourceManager({ workspace, remote, kind }) {
5899
6096
  fileEpoch.current++;
5900
6097
  };
5901
6098
  }, [workspace, remote, kind, revision]);
5902
- (0, import_react4.useEffect)(() => {
6099
+ (0, import_react5.useEffect)(() => {
5903
6100
  let active = true;
5904
6101
  setPreview(null);
5905
6102
  if (!request) return;
@@ -6063,105 +6260,163 @@ function ResourceManager({ workspace, remote, kind }) {
6063
6260
  setBusy(false);
6064
6261
  }
6065
6262
  };
6066
- const status = () => error ? (0, import_react4.createElement)("div", { className: "te-alert", role: "alert" }, error) : null;
6067
- 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)(
6068
6265
  "div",
6069
6266
  { className: "te-targets" },
6070
- ...["project", "user"].map((lvl) => (0, import_react4.createElement)(
6267
+ ...["project", "user"].map((lvl) => (0, import_react5.createElement)(
6071
6268
  "button",
6072
6269
  { type: "button", key: lvl, className: `te-target ${level === lvl ? "selected" : ""}`, "aria-pressed": level === lvl, disabled: busy || editing !== null && editing !== "new", onClick: () => {
6073
6270
  setPreview(null);
6074
6271
  setLevel(lvl);
6075
6272
  } },
6076
- (0, import_react4.createElement)("strong", null, lvl === "project" ? "\u9879\u76EE\u5171\u4EAB" : "\u4E2A\u4EBA\u5168\u5C40"),
6077
- (0, import_react4.createElement)("small", null, lvl === "project" ? "\u4EC5\u5F53\u524D\u5DE5\u4F5C\u533A\u4F7F\u7528" : "\u6B64\u4E3B\u673A\u4E0A\u7684\u6240\u6709\u9879\u76EE\u53EF\u7528")
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")
6078
6275
  )),
6079
- (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`))
6080
6277
  );
6081
6278
  const visible = rows.filter((r) => `${r.name} ${r.description ?? ""}`.toLowerCase().includes(query.toLowerCase()) && (filter === "all" || levelOf(r) === filter));
6082
- return (0, import_react4.createElement)(
6279
+ return (0, import_react5.createElement)(
6083
6280
  "section",
6084
6281
  { className: "te-resource" },
6085
- (0, import_react4.createElement)("input", { type: "file", ref: input, hidden: true, "aria-label": kind === "skill" ? "\u9009\u62E9\u6280\u80FD\u6587\u4EF6\u5939" : "\u9009\u62E9\u89C4\u5219\u6587\u4EF6", ...kind === "skill" ? { webkitdirectory: "", multiple: true } : { accept: ".md,text/markdown" }, onChange: (e) => {
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) => {
6086
6283
  void selected(Array.from(e.target.files ?? []));
6087
6284
  } }),
6088
- (0, import_react4.createElement)("div", { className: "te-section-heading" }, (0, import_react4.createElement)("div", null, (0, import_react4.createElement)("h2", null, `${noun}\u5E93`), (0, import_react4.createElement)("p", null, kind === "skill" ? "\u628A\u53EF\u590D\u7528\u7684\u5DE5\u4F5C\u65B9\u6CD5\u5E26\u5165\u9879\u76EE\u3002" : "\u4E3A\u9879\u76EE\u660E\u786E\u7EA6\u5B9A\uFF0C\u8BA9\u6BCF\u6B21\u4EA4\u4ED8\u4FDD\u6301\u4E00\u81F4\u3002")), (0, import_react4.createElement)("div", { className: "te-actions" }, (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "outline", onClick: () => {
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: () => {
6089
6286
  void edit("new");
6090
- } }, `\u65B0\u5EFA${noun}`), (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "primary", onClick: choose }, `\u5B89\u88C5${noun}`))),
6091
- (0, import_react4.createElement)("div", { className: "te-toolbar" }, (0, import_react4.createElement)("input", { className: "te-input", placeholder: `\u641C\u7D22${noun}\u540D\u79F0${kind === "skill" ? "\u6216\u63CF\u8FF0" : ""}`, value: query, onChange: (e) => setQuery(e.target.value) }), (0, import_react4.createElement)("select", { className: "te-input", "aria-label": "\u7B5B\u9009\u6765\u6E90", value: filter, onChange: (e) => setFilter(e.target.value) }, (0, import_react4.createElement)("option", { value: "all" }, `\u5168\u90E8\u6765\u6E90 \xB7 ${rows.length}`), (0, import_react4.createElement)("option", { value: "bundled" }, "\u5185\u7F6E"), (0, import_react4.createElement)("option", { value: "project" }, "\u9879\u76EE"), (0, import_react4.createElement)("option", { value: "user" }, "\u4E2A\u4EBA")), (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "ghost", onClick: () => refresh((n) => n + 1), disabled: loading }, "\u5237\u65B0")),
6092
- notice ? (0, import_react4.createElement)("div", { className: "te-success", role: "status" }, notice) : null,
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,
6093
6290
  !importing && !editing && !deleting ? status() : null,
6094
- loading ? (0, import_react4.createElement)("div", { className: "te-empty", role: "status" }, "\u6B63\u5728\u52A0\u8F7D\u2026") : visible.length === 0 ? (0, import_react4.createElement)("div", { className: "te-empty" }, (0, import_react4.createElement)("h3", null, query || filter !== "all" ? "\u6CA1\u6709\u5339\u914D\u7684\u7ED3\u679C" : `\u8FD8\u6CA1\u6709${noun}`), (0, import_react4.createElement)("p", null, "\u8C03\u6574\u7B5B\u9009\uFF0C\u6216\u4F7F\u7528\u53F3\u4E0A\u89D2\u6309\u94AE\u6DFB\u52A0\u3002")) : (0, import_react4.createElement)("div", { className: "te-resource-grid" }, ...visible.map((row) => (0, import_react4.createElement)(
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)(
6095
6292
  "article",
6096
6293
  { className: "te-resource-card", key: row.source + "/" + row.name },
6097
- (0, import_react4.createElement)("div", { className: "te-card-top" }, (0, import_react4.createElement)("span", { className: "te-resource-icon", "aria-hidden": true }, kind === "skill" ? "\u25C7" : "\u2261"), (0, import_react4.createElement)("span", { className: "te-badge" }, sourceText2(row.source))),
6098
- (0, import_react4.createElement)("h3", null, row.name),
6099
- (0, import_react4.createElement)("p", null, row.description || "\u9879\u76EE\u7EA6\u5B9A\u4E0E\u6267\u884C\u89C4\u5219"),
6100
- (0, import_react4.createElement)("div", { className: "te-actions" }, (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "outline", size: "sm", onClick: () => {
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: () => {
6101
6298
  void edit(row, true);
6102
- } }, "\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: () => {
6103
6300
  void edit(row);
6104
- } }, "\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: () => {
6105
6302
  setDeleting(row);
6106
6303
  setError("");
6107
6304
  } }, "\u5220\u9664") : null)
6108
6305
  ))),
6109
- kind === "skill" ? (0, import_react4.createElement)("button", { className: "te-link", onClick: () => {
6306
+ kind === "skill" ? (0, import_react5.createElement)("button", { className: "te-link", onClick: () => {
6110
6307
  setImporting(true);
6111
6308
  setManual(true);
6112
6309
  setError("");
6113
6310
  } }, "\u9AD8\u7EA7\uFF1A\u4ECE Harness \u4E3B\u673A\u8DEF\u5F84\u5B89\u88C5") : null,
6114
- importing ? (0, import_react4.createElement)(
6311
+ importing ? (0, import_react5.createElement)(
6115
6312
  ResourceModal,
6116
- { title: `\u5B89\u88C5${noun}`, description: "\u5148\u68C0\u67E5\u5185\u5BB9\u548C\u5B89\u88C5\u4F4D\u7F6E\uFF0C\u786E\u8BA4\u540E\u624D\u4F1A\u5199\u5165\u3002", onClose: close, footer: (0, import_react4.createElement)("div", { className: "te-actions" }, (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "ghost", disabled: busy, onClick: close }, "\u53D6\u6D88"), (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "primary", disabled: busy || !preview || preview.conflict, onClick: () => {
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: () => {
6117
6314
  void install();
6118
6315
  } }, busy ? "\u5904\u7406\u4E2D\u2026" : "\u786E\u8BA4\u5B89\u88C5")) },
6119
6316
  targets(),
6120
- (0, import_react4.createElement)("div", { className: "te-actions" }, (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "outline", disabled: busy, onClick: choose }, "\u91CD\u65B0\u9009\u62E9"), kind === "skill" ? (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "ghost", disabled: busy, onClick: () => setManual(!manual) }, manual ? "\u6536\u8D77\u9AD8\u7EA7\u65B9\u5F0F" : "\u4E3B\u673A\u8DEF\u5F84") : null),
6121
- manual ? (0, import_react4.createElement)("div", { className: "te-advanced" }, (0, import_react4.createElement)("p", null, "\u6B64\u8DEF\u5F84\u4F4D\u4E8E Harness \u4E3B\u673A\uFF1B\u6D4F\u89C8\u5668\u9009\u62E9\u5668\u8BFB\u53D6\u7684\u662F\u4F60\u5F53\u524D\u7535\u8111\u3002"), (0, import_react4.createElement)("div", { className: "te-toolbar" }, (0, import_react4.createElement)("input", { className: "te-input", "aria-label": "\u4E3B\u673A\u6280\u80FD\u76EE\u5F55", value: sourceDir, onChange: (e) => {
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) => {
6122
6319
  setSourceDir(e.target.value);
6123
6320
  setRequest(null);
6124
- } }), (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: () => {
6125
6322
  void browse(sourceDir);
6126
- } }, "\u6D4F\u89C8"), (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "outline", disabled: busy || !sourceDir.trim(), onClick: () => setRequest({ kind, level, path: workspace, files: [], sourceDir }) }, "\u9884\u89C8\u76EE\u5F55")), (0, import_react4.createElement)("div", { className: "te-dir-list" }, browsePath ? (0, import_react4.createElement)("button", { onClick: () => {
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: () => {
6127
6324
  void browse(browsePath.replace(/[\\/][^\\/]+[\\/]?$/u, "") || "/");
6128
- } }, "\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: () => {
6129
6326
  setRequest(null);
6130
6327
  void browse(browsePath.replace(/[\\/]+$/u, "") + "/" + d.name);
6131
6328
  } }, d.name + (d.hasSkill ? " \xB7 SKILL.md" : ""))))) : null,
6132
- 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,
6133
6330
  status(),
6134
- preview ? (0, import_react4.createElement)("div", { className: "te-preview" }, (0, import_react4.createElement)("h3", null, preview.name), (0, import_react4.createElement)("p", null, preview.description), (0, import_react4.createElement)("div", { className: "te-actions" }, (0, import_react4.createElement)("span", { className: "te-badge" }, `${preview.files} \u4E2A\u6587\u4EF6`), (0, import_react4.createElement)("span", { className: "te-badge" }, sizeText(preview.bytes))), (0, import_react4.createElement)("code", { className: "te-path" }, preview.target), preview.conflict ? (0, import_react4.createElement)("div", { className: "te-alert", role: "alert" }, "\u5DF2\u6709\u540C\u540D\u8D44\u6E90\u3002\u8BF7\u53D6\u6D88\u5E76\u68C0\u67E5\u73B0\u6709\u5185\u5BB9\uFF0C\u5B89\u88C5\u4E0D\u4F1A\u8986\u76D6\u5B83\u3002") : null, (0, import_react4.createElement)("div", { className: "te-markdown" }, (0, import_react4.createElement)(import_dsh_client_ui_primitives4.MarkdownText, { text: preview.content, labels }))) : null
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
6135
6332
  ) : null,
6136
- editing ? (0, import_react4.createElement)(
6333
+ editing ? (0, import_react5.createElement)(
6137
6334
  ResourceModal,
6138
- { title: editing === "new" ? `\u65B0\u5EFA${noun}` : `${viewing ? "\u67E5\u770B" : "\u7F16\u8F91"}${noun} \xB7 ${name}`, onClose: close, footer: (0, import_react4.createElement)("div", { className: "te-actions" }, (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "ghost", disabled: busy, onClick: close }, "\u5173\u95ED"), !readonly ? (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "outline", disabled: busy, onClick: () => setViewing(!viewing) }, viewing ? "\u7F16\u8F91\u5185\u5BB9" : "\u9884\u89C8") : null, !readonly ? (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "primary", disabled: busy || !name.trim() || !body2.trim() || kind === "skill" && !description.trim(), onClick: () => {
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: () => {
6139
6336
  void save2();
6140
6337
  } }, busy ? "\u5904\u7406\u4E2D\u2026" : "\u4FDD\u5B58") : null) },
6141
- !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"),
6142
6339
  status(),
6143
- viewing ? (0, import_react4.createElement)("div", { className: "te-markdown" }, (0, import_react4.createElement)(import_dsh_client_ui_primitives4.MarkdownText, { text: body2, labels })) : (0, import_react4.createElement)("div", { className: "te-form" }, (0, import_react4.createElement)("label", null, "\u540D\u79F0", (0, import_react4.createElement)("input", { className: "te-input", value: name, disabled: editing !== "new" || busy, onChange: (e) => setName(e.target.value), placeholder: "\u5C0F\u5199\u5B57\u6BCD\u3001\u6570\u5B57\u548C\u8FDE\u5B57\u7B26" })), kind === "skill" ? (0, import_react4.createElement)("label", null, "\u63CF\u8FF0", (0, import_react4.createElement)("input", { className: "te-input", value: description, disabled: busy, onChange: (e) => setDescription(e.target.value) })) : null, kind === "skill" ? (0, import_react4.createElement)("label", null, "\u4F7F\u7528\u65F6\u673A\uFF08\u53EF\u9009\uFF09", (0, import_react4.createElement)("input", { className: "te-input", value: whenToUse, disabled: busy, onChange: (e) => setWhenToUse(e.target.value) })) : null, (0, import_react4.createElement)("label", null, "Markdown \u6B63\u6587", (0, import_react4.createElement)("textarea", { className: "te-input te-editor", value: body2, disabled: busy, onChange: (e) => setBody(e.target.value) })))
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) })))
6144
6341
  ) : null,
6145
- deleting ? (0, import_react4.createElement)(ResourceModal, { title: `\u5220\u9664${noun}\u300C${deleting.name}\u300D\uFF1F`, description: levelOf(deleting) === "user" ? "\u8FD9\u662F\u4E2A\u4EBA\u5168\u5C40\u8D44\u6E90\uFF0C\u5220\u9664\u4F1A\u5F71\u54CD\u6B64\u4E3B\u673A\u4E0A\u7684\u6240\u6709\u9879\u76EE\u3002" : "\u5220\u9664\u5C06\u5F71\u54CD\u5F53\u524D\u9879\u76EE\u3002", onClose: close, footer: (0, import_react4.createElement)("div", { className: "te-actions" }, (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "outline", disabled: busy, onClick: close }, "\u4FDD\u7559"), (0, import_react4.createElement)("button", { className: "te-danger-button", disabled: busy, onClick: () => {
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: () => {
6146
6343
  void remove();
6147
- } }, busy ? "\u5220\u9664\u4E2D\u2026" : "\u786E\u8BA4\u6C38\u4E45\u5220\u9664")) }, (0, import_react4.createElement)("code", { className: "te-path" }, `${roots?.[levelOf(deleting) === "user" ? "user" : "project"] ?? "\u8D44\u6E90\u76EE\u5F55"}/${deleting.name}${kind === "rule" ? ".md" : ""}`), (0, import_react4.createElement)("p", null, "\u6B64\u64CD\u4F5C\u4E0D\u4F1A\u8FDB\u5165\u56DE\u6536\u7AD9\uFF0C\u8BF7\u786E\u8BA4\u5DF2\u6709\u5907\u4EFD\u3002"), status()) : null
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
6148
6345
  );
6149
6346
  }
6150
6347
 
6151
6348
  // src/client/SkillManager.tsx
6152
- function SkillManager(props) {
6153
- 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
+ ] });
6154
6409
  }
6155
6410
 
6156
6411
  // src/client/RuleManager.tsx
6157
- var import_react6 = require("react");
6412
+ var import_react7 = require("react");
6158
6413
  function RuleManager(props) {
6159
- 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" });
6160
6415
  }
6161
6416
 
6162
6417
  // src/client/TaskLedger.tsx
6163
- var import_react7 = require("react");
6164
- 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");
6165
6420
  var card2 = {
6166
6421
  display: "flex",
6167
6422
  flexDirection: "column",
@@ -6199,10 +6454,10 @@ var badge = {
6199
6454
  color: "var(--dsw-alias-label-secondary)"
6200
6455
  };
6201
6456
  function verdictDot(outcome) {
6202
- 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" });
6203
6458
  }
6204
6459
  function itemStatusDot(status) {
6205
- 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" });
6206
6461
  }
6207
6462
  function timeText(at) {
6208
6463
  return at.slice(0, 19).replace("T", " ");
@@ -6210,48 +6465,48 @@ function timeText(at) {
6210
6465
  function itemAudit(item) {
6211
6466
  const lines = [];
6212
6467
  if (item.dispatch !== void 0) {
6213
- lines.push((0, import_react7.createElement)(
6468
+ lines.push((0, import_react8.createElement)(
6214
6469
  "div",
6215
6470
  { key: "dispatch", style: metaLine },
6216
- (0, import_react7.createElement)("span", { style: badge }, "\u5DF2\u6D3E\u53D1"),
6217
- (0, import_react7.createElement)("span", null, item.dispatch.description === "" ? "\uFF08\u65E0\u63CF\u8FF0\uFF09" : item.dispatch.description),
6218
- (0, import_react7.createElement)("span", { style: badge }, timeText(item.dispatch.at))
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))
6219
6474
  ));
6220
6475
  }
6221
6476
  if (item.review !== void 0) {
6222
6477
  const spec = item.review.spec;
6223
6478
  const quality = item.review.quality;
6224
- lines.push((0, import_react7.createElement)(
6479
+ lines.push((0, import_react8.createElement)(
6225
6480
  "div",
6226
6481
  { key: "review", style: metaLine },
6227
6482
  verdictDot(spec.outcome),
6228
- (0, import_react7.createElement)("span", null, `\u89C4\u683C\u7B26\u5408 ${spec.outcome === "pass" ? "\u901A\u8FC7" : "\u4E0D\u901A\u8FC7"}`),
6229
- (0, import_react7.createElement)("span", null, "\xB7"),
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"),
6230
6485
  verdictDot(quality.outcome),
6231
- (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"}`)
6232
6487
  ));
6233
6488
  const failNotes = [spec, quality].flatMap((stage) => stage.outcome === "fail" ? stage.notes ?? [] : []);
6234
6489
  if (failNotes.length > 0) {
6235
- lines.push((0, import_react7.createElement)(
6490
+ lines.push((0, import_react8.createElement)(
6236
6491
  "div",
6237
6492
  { key: "notes", style: metaLine },
6238
- ...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))
6239
6494
  ));
6240
6495
  }
6241
6496
  }
6242
6497
  if (lines.length === 0) {
6243
- lines.push((0, import_react7.createElement)("div", { key: "none", style: metaLine }, (0, import_react7.createElement)("span", { style: badge }, "\u672A\u6D3E\u53D1 / \u672A\u5BA1\u67E5")));
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")));
6244
6499
  }
6245
- 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);
6246
6501
  }
6247
6502
  function TaskLedger({ workspace, remote }) {
6248
- const [tasks, setTasks] = (0, import_react7.useState)([]);
6249
- const [error, setError] = (0, import_react7.useState)("");
6250
- const [loading, setLoading] = (0, import_react7.useState)(true);
6251
- const [query, setQuery] = (0, import_react7.useState)("");
6252
- const [risk, setRisk] = (0, import_react7.useState)("all");
6253
- const [stage, setStage] = (0, import_react7.useState)("all");
6254
- const refresh = (0, import_react7.useCallback)(() => {
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)(() => {
6255
6510
  if (workspace === "") return;
6256
6511
  setError("");
6257
6512
  setLoading(true);
@@ -6264,57 +6519,57 @@ function TaskLedger({ workspace, remote }) {
6264
6519
  setError("\u8BFB\u53D6\u53F0\u8D26\u5931\u8D25\uFF1A" + describeError(reason));
6265
6520
  });
6266
6521
  }, [remote, workspace]);
6267
- (0, import_react7.useEffect)(() => {
6522
+ (0, import_react8.useEffect)(() => {
6268
6523
  refresh();
6269
6524
  }, [refresh]);
6270
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));
6271
- return (0, import_react7.createElement)(
6526
+ return (0, import_react8.createElement)(
6272
6527
  "div",
6273
6528
  { style: styles.section },
6274
- (0, import_react7.createElement)(
6529
+ (0, import_react8.createElement)(
6275
6530
  "div",
6276
6531
  { className: "te-toolbar" },
6277
- (0, import_react7.createElement)("input", { className: "te-input", placeholder: "\u641C\u7D22\u4EFB\u52A1\u3001\u6807\u9898\u6216\u5206\u652F", value: query, onChange: (e) => setQuery(e.target.value) }),
6278
- (0, import_react7.createElement)("select", { className: "te-input", "aria-label": "\u98CE\u9669\u7B5B\u9009", value: risk, onChange: (e) => setRisk(e.target.value) }, (0, import_react7.createElement)("option", { value: "all" }, "\u5168\u90E8\u98CE\u9669"), (0, import_react7.createElement)("option", { value: "standard" }, "\u6807\u51C6"), (0, import_react7.createElement)("option", { value: "high_risk" }, "\u9AD8\u98CE\u9669")),
6279
- (0, import_react7.createElement)("select", { className: "te-input", "aria-label": "\u9636\u6BB5\u7B5B\u9009", value: stage, onChange: (e) => setStage(e.target.value) }, (0, import_react7.createElement)("option", { value: "all" }, "\u5168\u90E8\u9636\u6BB5"), ...Array.from(new Set(tasks.map((t) => t.stage))).map((value) => (0, import_react7.createElement)("option", { key: value, value }, value)))
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)))
6280
6535
  ),
6281
- (0, import_react7.createElement)(
6536
+ (0, import_react8.createElement)(
6282
6537
  "div",
6283
6538
  { style: headerRow },
6284
- (0, import_react7.createElement)("span", { style: styles.bindingLabel }, "\u4EFB\u52A1\u53F0\u8D26"),
6285
- (0, import_react7.createElement)("span", { style: styles.sourceBadge }, "\u53EA\u8BFB \xB7 \u6765\u81EA .dsh/task-*.json"),
6286
- (0, import_react7.createElement)(import_dsh_client_ui_primitives5.Button, { variant: "outline", size: "sm", disabled: loading, onClick: refresh }, loading ? "\u8BFB\u53D6\u4E2D\u2026" : "\u5237\u65B0")
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")
6287
6542
  ),
6288
- loading ? (0, import_react7.createElement)("p", { role: "status" }, "\u6B63\u5728\u8BFB\u53D6\u4EFB\u52A1\u2026") : error !== "" ? (0, import_react7.createElement)("p", { style: styles.status }, error) : tasks.length === 0 ? (0, import_react7.createElement)("p", { style: styles.muted }, "\u5F53\u524D\u5DE5\u4F5C\u533A\u8FD8\u6CA1\u6709\u4EFB\u52A1\uFF1A\u5F00\u5DE5\u540E\uFF08dev_task create\uFF09\u4F1A\u5728\u8FD9\u91CC\u5217\u51FA\u6D3E\u53D1\u4E0E\u5BA1\u67E5\u7559\u75D5\u3002") : visible.length === 0 ? (0, import_react7.createElement)("div", { className: "te-empty" }, "\u6CA1\u6709\u5339\u914D\u7684\u4EFB\u52A1\uFF0C\u8BF7\u8C03\u6574\u7B5B\u9009\u3002") : (0, import_react7.createElement)(
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)(
6289
6544
  "div",
6290
6545
  { style: { display: "flex", flexDirection: "column", gap: 12 } },
6291
- ...visible.map((task) => (0, import_react7.createElement)(
6546
+ ...visible.map((task) => (0, import_react8.createElement)(
6292
6547
  "div",
6293
6548
  { key: task.task_id, style: card2 },
6294
- (0, import_react7.createElement)(
6549
+ (0, import_react8.createElement)(
6295
6550
  "div",
6296
6551
  { style: headerRow },
6297
- (0, import_react7.createElement)("span", { style: { fontSize: 14, fontWeight: 600, color: "var(--dsw-alias-label-primary)" } }, task.task_id),
6298
- (0, import_react7.createElement)("span", { style: { fontSize: 13, color: "var(--dsw-alias-label-primary)" } }, task.title),
6299
- (0, import_react7.createElement)("span", { style: badge }, task.stage),
6300
- (0, import_react7.createElement)("span", { style: badge }, task.branch),
6301
- (0, import_react7.createElement)("span", { className: "te-badge", style: task.risk_level === "high_risk" ? { color: "var(--dsw-alias-state-error-primary)" } : {} }, task.risk_level === "high_risk" ? "\u9AD8\u98CE\u9669" : "\u6807\u51C6"),
6302
- (0, import_react7.createElement)("span", { className: "te-badge" }, task.verification_passed ? "\u9A8C\u8BC1\u901A\u8FC7" : "\u5F85\u9A8C\u8BC1"),
6303
- (0, import_react7.createElement)("span", { className: "te-badge" }, `\u5BA1\u6838\uFF1A${task.review_outcome ?? "pending"}`),
6304
- task.updated_at ? (0, import_react7.createElement)("span", { style: metaLine }, "\u66F4\u65B0\u4E8E " + timeText(task.updated_at)) : null
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
6305
6560
  ),
6306
- (0, import_react7.createElement)(
6561
+ (0, import_react8.createElement)(
6307
6562
  "div",
6308
6563
  { style: { display: "flex", flexDirection: "column" } },
6309
- ...task.items.map((item) => (0, import_react7.createElement)(
6564
+ ...task.items.map((item) => (0, import_react8.createElement)(
6310
6565
  "div",
6311
6566
  { key: item.id, style: itemRow },
6312
- (0, import_react7.createElement)(
6567
+ (0, import_react8.createElement)(
6313
6568
  "div",
6314
6569
  { style: headerRow },
6315
6570
  itemStatusDot(item.status),
6316
- (0, import_react7.createElement)("span", { style: { fontSize: 13, color: "var(--dsw-alias-label-primary)" } }, item.id),
6317
- (0, import_react7.createElement)("span", { style: { fontSize: 12, color: "var(--dsw-alias-label-secondary)" } }, item.title)
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)
6318
6573
  ),
6319
6574
  itemAudit(item)
6320
6575
  ))
@@ -6355,7 +6610,7 @@ var tabbar = {
6355
6610
  var body = {
6356
6611
  flex: 1,
6357
6612
  overflowY: "auto",
6358
- padding: "24px clamp(12px, 3vw, 32px)"
6613
+ padding: "16px clamp(12px, 2vw, 28px)"
6359
6614
  };
6360
6615
  var selectStyle = {
6361
6616
  marginLeft: "auto",
@@ -6388,29 +6643,29 @@ var TABS = [
6388
6643
  function Workbench({ useStore, actions, useWorkspaces, remote }) {
6389
6644
  const open = useStore((s) => s.open);
6390
6645
  const workspaces = useWorkspaces((s) => s.items);
6391
- const [tab, setTab] = (0, import_react8.useState)("init");
6392
- const [workspace, setWorkspace] = (0, import_react8.useState)("");
6646
+ const [tab, setTab] = (0, import_react9.useState)("init");
6647
+ const [workspace, setWorkspace] = (0, import_react9.useState)("");
6393
6648
  if (!open) return null;
6394
6649
  const current = workspaces.some((w) => w.path === workspace) ? workspace : workspaces[0]?.path ?? "";
6395
- return (0, import_react8.createElement)(
6650
+ return (0, import_react9.createElement)(
6396
6651
  "div",
6397
6652
  { style: overlay, className: "te-workbench" },
6398
- (0, import_react8.createElement)("style", null, workbenchTheme),
6399
- (0, import_react8.createElement)(
6653
+ (0, import_react9.createElement)("style", null, workbenchTheme),
6654
+ (0, import_react9.createElement)(
6400
6655
  "div",
6401
6656
  { style: header },
6402
- (0, import_react8.createElement)(
6657
+ (0, import_react9.createElement)(
6403
6658
  "div",
6404
6659
  { style: headerBrand },
6405
- (0, import_react8.createElement)(import_dsh_client_ui_primitives6.IconSettingsOutline16, { size: 18 }),
6406
- (0, import_react8.createElement)(
6660
+ (0, import_react9.createElement)(import_dsh_client_ui_primitives7.IconSettingsOutline16, { size: 18 }),
6661
+ (0, import_react9.createElement)(
6407
6662
  "div",
6408
6663
  { style: headerText },
6409
- (0, import_react8.createElement)("span", { style: headerTitle }, "\u5DE5\u7A0B\u6D41\u7A0B"),
6410
- (0, import_react8.createElement)("p", { style: headerSub }, "\u5DE5\u7A0B\u5316\u4EA4\u4ED8\u5DE5\u4F5C\u53F0 \xB7 \u9700\u6C42\u8BC4\u5BA1 \u2192 \u8BBE\u8BA1 \u2192 \u5F00\u53D1 \u2192 \u4EA4\u4ED8 \u2192 \u4EE3\u7801\u5BA1\u6838")
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")
6411
6666
  )
6412
6667
  ),
6413
- (0, import_react8.createElement)(
6668
+ (0, import_react9.createElement)(
6414
6669
  "button",
6415
6670
  {
6416
6671
  type: "button",
@@ -6426,44 +6681,44 @@ function Workbench({ useStore, actions, useWorkspaces, remote }) {
6426
6681
  event.currentTarget.style.background = "transparent";
6427
6682
  }
6428
6683
  },
6429
- (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 })
6430
6685
  )
6431
6686
  ),
6432
- (0, import_react8.createElement)(
6687
+ (0, import_react9.createElement)(
6433
6688
  "div",
6434
6689
  { style: tabbar },
6435
- ...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: () => {
6436
6691
  setTab(t.id);
6437
6692
  } }, t.label)),
6438
- workspaces.length > 0 ? (0, import_react8.createElement)("select", {
6693
+ workspaces.length > 0 ? (0, import_react9.createElement)("select", {
6439
6694
  style: selectStyle,
6440
6695
  "aria-label": "\u5F53\u524D\u5DE5\u4F5C\u533A",
6441
6696
  value: current,
6442
6697
  onChange: (ev) => {
6443
6698
  setWorkspace(ev.target.value);
6444
6699
  }
6445
- }, ...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
6446
6701
  ),
6447
- (0, import_react8.createElement)(
6702
+ (0, import_react9.createElement)(
6448
6703
  "div",
6449
6704
  { style: body },
6450
- (0, import_react8.createElement)(
6705
+ (0, import_react9.createElement)(
6451
6706
  "div",
6452
6707
  { className: "te-content", key: current },
6453
- (0, import_react8.createElement)("p", { style: { ...styles.hint, marginBottom: 20 }, title: current }, "\u5DE5\u4F5C\u533A \xB7 " + current),
6454
- current === "" ? (0, import_react8.createElement)("p", { style: styles.muted }, "\u5F53\u524D\u6CA1\u6709\u5DE5\u4F5C\u533A\uFF1A\u8BF7\u5148\u5728\u4FA7\u680F\u521B\u5EFA\u4E00\u4E2A\u5DE5\u4F5C\u533A\uFF0C\u518D\u56DE\u6765\u914D\u7F6E\u6D41\u7A0B\u3002") : tab === "init" ? (0, import_react8.createElement)(InitPanel, { workspace: current, remote }) : tab === "flow" ? (0, import_react8.createElement)(TaskEngineSection, { workspace: current, remote }) : tab === "tasks" ? (0, import_react8.createElement)(TaskLedger, { workspace: current, remote }) : tab === "skills" ? (0, import_react8.createElement)(SkillManager, { workspace: current, remote }) : (0, import_react8.createElement)(RuleManager, { workspace: current, remote })
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 })
6455
6710
  )
6456
6711
  )
6457
6712
  );
6458
6713
  }
6459
6714
 
6460
6715
  // src/client/TriggerButton.tsx
6461
- var import_react9 = require("react");
6462
- 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");
6463
6718
  var hover = "var(--dsw-alias-bg-layer-2)";
6464
6719
  var label = "var(--dsw-alias-label-primary)";
6465
6720
  function TriggerButton({ wide, actions }) {
6466
- return (0, import_react9.createElement)(
6721
+ return (0, import_react10.createElement)(
6467
6722
  "button",
6468
6723
  {
6469
6724
  type: "button",
@@ -6503,8 +6758,8 @@ function TriggerButton({ wide, actions }) {
6503
6758
  transition: "background 120ms ease"
6504
6759
  }
6505
6760
  },
6506
- (0, import_react9.createElement)(import_dsh_client_ui_primitives7.IconSettingsOutline16, { size: wide ? 16 : 18 }),
6507
- wide ? (0, import_react9.createElement)("span", { style: { fontSize: 14, lineHeight: "22px" } }, "\u5DE5\u7A0B\u6D41\u7A0B") : null
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
6508
6763
  );
6509
6764
  }
6510
6765