@godv61/dsh-task-engine 0.26.1 → 0.27.1

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 (57) hide show
  1. package/.acceptance.mjs +11 -6
  2. package/.assessment-batch1.mjs +14 -11
  3. package/.codex-project-test.mjs +80 -0
  4. package/.enforce-test.mjs +12 -17
  5. package/.evidence-test.mjs +8 -8
  6. package/.filter-test.mjs +6 -8
  7. package/.freeze-test.mjs +44 -40
  8. package/.p0-test.mjs +21 -24
  9. package/.revision-test.mjs +16 -16
  10. package/.roundtrip-test.mjs +247 -120
  11. package/.workflow-test.mjs +119 -102
  12. package/README.md +14 -12
  13. package/defaults/eng.json +1 -97
  14. package/docs/CHANGELOG.md +33 -19
  15. package/docs/configuration.md +22 -21
  16. package/docs/development.md +1 -1
  17. package/docs/faq.md +5 -5
  18. package/docs/manual.html +41 -59
  19. package/docs/resource-install.md +5 -3
  20. package/docs/roadmap.md +2 -2
  21. package/hooks/commit-msg +4 -33
  22. package/lib/client.js +332 -226
  23. package/lib/client.js.map +3 -3
  24. package/lib/controller.d.ts +19 -3
  25. package/lib/controller.js +132 -28
  26. package/lib/controller.js.map +1 -1
  27. package/lib/dev-task.js +130 -79
  28. package/lib/dev-task.js.map +1 -1
  29. package/lib/engine.d.ts +10 -13
  30. package/lib/engine.js +3 -3
  31. package/lib/engine.js.map +1 -1
  32. package/lib/shipped-skills.d.ts +2 -4
  33. package/lib/shipped-skills.js +2 -4
  34. package/lib/shipped-skills.js.map +1 -1
  35. package/lib/skill-audit.d.ts +4 -4
  36. package/lib/skill-audit.js +19 -14
  37. package/lib/skill-audit.js.map +1 -1
  38. package/lib/user-skill-profiles.d.ts +7 -0
  39. package/lib/user-skill-profiles.js +69 -0
  40. package/lib/user-skill-profiles.js.map +1 -0
  41. package/lib/workflows.d.ts +24 -4
  42. package/lib/workflows.js +57 -41
  43. package/lib/workflows.js.map +1 -1
  44. package/package.json +4 -4
  45. package/preset/agent.cordis.yml +3 -3
  46. package/preset/persona.md +2 -2
  47. package/scripts/verify-package.mjs +3 -1
  48. package/skills/eng-delivery/SKILL.md +17 -17
  49. package/rules/coding-conventions.md +0 -7
  50. package/rules/commit-conventions.md +0 -6
  51. package/rules/security-redlines.md +0 -6
  52. package/skills/code-commit/SKILL.md +0 -13
  53. package/skills/code-implement/SKILL.md +0 -24
  54. package/skills/code-review/SKILL.md +0 -13
  55. package/skills/code-verify/SKILL.md +0 -20
  56. package/skills/requirement-analysis/SKILL.md +0 -16
  57. package/skills/solution-design/SKILL.md +0 -19
package/lib/client.js CHANGED
@@ -2,9 +2,11 @@ window.__ModuleLoader__.load({ id: "@godv61/dsh-task-engine", factory: (require)
2
2
  var module = { exports: {} }; var exports = module.exports;
3
3
 
4
4
  "use strict";
5
+ var __create = Object.create;
5
6
  var __defProp = Object.defineProperty;
6
7
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
7
8
  var __getOwnPropNames = Object.getOwnPropertyNames;
9
+ var __getProtoOf = Object.getPrototypeOf;
8
10
  var __hasOwnProp = Object.prototype.hasOwnProperty;
9
11
  var __export = (target, all) => {
10
12
  for (var name in all)
@@ -18,6 +20,14 @@ var __copyProps = (to, from, except, desc) => {
18
20
  }
19
21
  return to;
20
22
  };
23
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
24
+ // If the importer is in node compatibility mode or this is not an ESM
25
+ // file that has been converted to a CommonJS file using a Babel-
26
+ // compatible transform (i.e. "__esModule" has not been set), then set
27
+ // "default" to the CommonJS "module.exports" for node compatibility.
28
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
29
+ mod
30
+ ));
21
31
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
22
32
 
23
33
  // src/client/index.ts
@@ -4082,15 +4092,24 @@ var artifactSchema = external_exports.object({
4082
4092
  fields: external_exports.array(external_exports.string())
4083
4093
  });
4084
4094
  var commitSchema = external_exports.object({
4085
- policy: external_exports.string(),
4095
+ policy: external_exports.enum(["task", "item", "manual"]),
4086
4096
  message_pattern: external_exports.string(),
4087
4097
  message_hint: external_exports.string(),
4088
4098
  checkpoints: external_exports.array(external_exports.string()),
4089
4099
  file_scope: external_exports.boolean()
4090
4100
  });
4101
+ var resourceRefSchema = external_exports.object({ source: external_exports.enum(["bundled", "project", "codex-project", "user"]), name: external_exports.string() });
4102
+ var evidenceSchema = external_exports.enum(["command", "artifact", "review", "manual", "none"]);
4103
+ var skillProfileSchema = external_exports.object({ rules: external_exports.array(resourceRefSchema), evidence: evidenceSchema.optional() });
4104
+ var skillBindingSchema = external_exports.object({
4105
+ skill: resourceRefSchema,
4106
+ rules: external_exports.array(resourceRefSchema),
4107
+ evidence: evidenceSchema.optional()
4108
+ });
4091
4109
  var stageBindingSchema = external_exports.object({
4092
- skills: external_exports.array(external_exports.string()).optional(),
4093
- rules: external_exports.array(external_exports.string()).optional()
4110
+ skills: external_exports.array(skillBindingSchema).optional(),
4111
+ skill_refs: external_exports.array(resourceRefSchema).optional(),
4112
+ legacy_rules: external_exports.array(external_exports.string()).optional()
4094
4113
  });
4095
4114
  var configSchema = external_exports.object({
4096
4115
  stages: external_exports.array(external_exports.string()),
@@ -4099,31 +4118,47 @@ var configSchema = external_exports.object({
4099
4118
  artifacts: external_exports.array(artifactSchema),
4100
4119
  commit: commitSchema,
4101
4120
  high_risk_requires_verification: external_exports.boolean(),
4102
- stage_bindings: external_exports.record(external_exports.string(), stageBindingSchema).optional()
4121
+ stage_bindings: external_exports.record(external_exports.string(), stageBindingSchema).optional(),
4122
+ skill_profiles: external_exports.record(external_exports.string(), skillProfileSchema).optional(),
4123
+ configuration_errors: external_exports.array(external_exports.string()).optional(),
4124
+ review_depth: external_exports.enum(["two-stage", "single"]).optional(),
4125
+ commit_required: external_exports.boolean().optional(),
4126
+ completion_guards: external_exports.array(external_exports.string()).optional()
4103
4127
  });
4104
4128
  var viewSchema = external_exports.object({
4105
4129
  ok: external_exports.boolean(),
4106
4130
  source: external_exports.enum(["default", "project", "invalid"]),
4107
4131
  flow: external_exports.string(),
4108
4132
  config: configSchema,
4109
- problems: external_exports.array(external_exports.string())
4133
+ problems: external_exports.array(external_exports.string()),
4134
+ adoption: external_exports.object({ created: external_exports.array(external_exports.string()), reused: external_exports.array(external_exports.string()) }).optional()
4110
4135
  });
4111
4136
  var writeRequestSchema = external_exports.object({
4112
4137
  path: external_exports.string(),
4113
4138
  flow: external_exports.string(),
4114
- stage_bindings: external_exports.record(external_exports.string(), stageBindingSchema).optional()
4139
+ stage_bindings: external_exports.record(external_exports.string(), stageBindingSchema).optional(),
4140
+ skill_profiles: external_exports.record(external_exports.string(), skillProfileSchema).optional(),
4141
+ commit: commitSchema.optional(),
4142
+ artifacts: external_exports.array(artifactSchema).optional(),
4143
+ review_depth: external_exports.enum(["two-stage", "single"]).optional(),
4144
+ commit_required: external_exports.boolean().optional(),
4145
+ materialize_bundled: external_exports.enum(["project", "user"]).optional()
4115
4146
  });
4116
4147
  var skillCatalogSchema = external_exports.object({
4117
4148
  skills: external_exports.array(external_exports.object({
4118
4149
  name: external_exports.string(),
4119
4150
  description: external_exports.string(),
4120
- source: external_exports.string()
4151
+ source: external_exports.string(),
4152
+ ref: resourceRefSchema,
4153
+ sourceLabel: external_exports.string()
4121
4154
  }))
4122
4155
  });
4123
4156
  var ruleCatalogSchema = external_exports.object({
4124
4157
  rules: external_exports.array(external_exports.object({
4125
4158
  name: external_exports.string(),
4126
- source: external_exports.string()
4159
+ source: external_exports.string(),
4160
+ ref: resourceRefSchema,
4161
+ sourceLabel: external_exports.string()
4127
4162
  }))
4128
4163
  });
4129
4164
  var writeSkillRequestSchema = external_exports.object({
@@ -4154,6 +4189,8 @@ var writeRuleRequestSchema = external_exports.object({
4154
4189
  level: external_exports.enum(["project", "user"]),
4155
4190
  path: external_exports.string().optional()
4156
4191
  });
4192
+ var writeUserSkillProfileRequestSchema = external_exports.object({ name: external_exports.string(), profile: skillProfileSchema });
4193
+ var writeUserSkillProfileResultSchema = external_exports.object({ ok: external_exports.boolean(), error: external_exports.string().optional() });
4157
4194
  var writeResourceResultSchema = external_exports.object({
4158
4195
  ok: external_exports.boolean(),
4159
4196
  name: external_exports.string(),
@@ -4162,7 +4199,7 @@ var writeResourceResultSchema = external_exports.object({
4162
4199
  });
4163
4200
  var readSkillRequestSchema = external_exports.object({
4164
4201
  name: external_exports.string(),
4165
- level: external_exports.enum(["project", "user", "bundled"]),
4202
+ level: external_exports.enum(["project", "codex-project", "user", "bundled"]),
4166
4203
  path: external_exports.string().optional()
4167
4204
  });
4168
4205
  var readSkillResultSchema = external_exports.object({
@@ -4403,6 +4440,20 @@ var TYPERT_REMOTE = {
4403
4440
  ],
4404
4441
  result: { mode: "strict", typeSymbol: `${PACKAGE}/types#WriteResourceResult`, create: () => writeResourceResultSchema, schema: writeResourceResultSchema }
4405
4442
  },
4443
+ {
4444
+ id: `${PACKAGE}#task-engine/writeUserSkillProfile`,
4445
+ service: "taskEngineController",
4446
+ namespace: "task-engine",
4447
+ method: "writeUserSkillProfile",
4448
+ invocation: { kind: "direct" },
4449
+ parameters: [{
4450
+ name: "request",
4451
+ wire: "request",
4452
+ source: "json",
4453
+ codec: { mode: "strict", typeSymbol: `${PACKAGE}/types#WriteUserSkillProfileRequest`, create: () => writeUserSkillProfileRequestSchema, schema: writeUserSkillProfileRequestSchema }
4454
+ }],
4455
+ result: { mode: "strict", typeSymbol: `${PACKAGE}/types#WriteUserSkillProfileResult`, create: () => writeUserSkillProfileResultSchema, schema: writeUserSkillProfileResultSchema }
4456
+ },
4406
4457
  {
4407
4458
  id: `${PACKAGE}#task-engine/readSkill`,
4408
4459
  service: "taskEngineController",
@@ -4537,7 +4588,13 @@ var remote_default = TYPERT_REMOTE;
4537
4588
 
4538
4589
  // src/client/Workbench.tsx
4539
4590
  var import_react9 = require("react");
4540
- var import_dsh_client_ui_primitives7 = require("@deepseek-ai/dsh-client-ui-primitives");
4591
+ var import_dsh_client_ui_primitives6 = require("@deepseek-ai/dsh-client-ui-primitives");
4592
+
4593
+ // src/client/icons.ts
4594
+ var primitives = __toESM(require("@deepseek-ai/dsh-client-ui-primitives"), 1);
4595
+ var IconSettings = primitives.IconSettingsOutlineRegular ?? primitives.IconSettingsOutline16;
4596
+ var IconClose = primitives.IconCloseOutlineRegular ?? primitives.IconCloseOutline16;
4597
+ var IconCheck = primitives.IconCheckOutlineRegular ?? primitives.IconCheckOutline16;
4541
4598
 
4542
4599
  // src/client/workbench-theme.ts
4543
4600
  var workbenchTheme = `
@@ -4547,6 +4604,11 @@ var workbenchTheme = `
4547
4604
  .te-workbench button:focus-visible,.te-modal button:focus-visible,.te-input:focus-visible { outline:2px solid var(--dsw-alias-state-business-primary); outline-offset:3px; }
4548
4605
  .te-workbench h2 { margin:0 0 6px; font-size:24px; letter-spacing:-.5px; }
4549
4606
  .te-workbench h3,.te-modal h3 { margin:0; font-size:16px; overflow-wrap:anywhere; }
4607
+ .te-config-layout { display:grid; grid-template-columns:minmax(0,1fr); gap:16px; align-items:start; width:100%; }
4608
+ .te-config-layout.is-open { grid-template-columns:minmax(0,1fr) minmax(320px,420px); }
4609
+ .te-config-main { min-width:0; }
4610
+ .te-inline-panel { position:sticky !important; top:12px; min-width:0; }
4611
+ .te-flow-notice { margin:0; padding:10px 12px; border:1px solid var(--dsw-alias-state-warn-primary); border-radius:8px; font-size:13px; }
4550
4612
  .te-workbench .te-disclosure-title { font-size:16px; font-weight:700; color:var(--dsw-alias-label-primary); }
4551
4613
  .te-binding-grid { display:grid; grid-template-columns:repeat(auto-fit,minmax(min(100%,320px),1fr)); gap:14px; align-items:start; }
4552
4614
  .te-binding-picker { min-width:0; display:flex; flex-direction:column; gap:10px; border:1px solid var(--dsw-alias-border-l2); border-radius:12px; padding:14px; background:var(--dsw-alias-bg-layer-1); }
@@ -4644,6 +4706,7 @@ var workbenchTheme = `
4644
4706
  .te-form label { display:flex; flex-direction:column; gap:8px; font-size:13px; }
4645
4707
  .te-editor { min-height:260px; resize:vertical; line-height:1.6; font-family:monospace; }
4646
4708
  @media(max-width:760px) { .te-transfer {grid-template-columns:1fr;} .te-transfer-arrow {transform:rotate(90deg); height:20px;} .te-transfer-list {max-height:210px;} }
4709
+ @media(max-width:1000px) { .te-config-layout.is-open { grid-template-columns:minmax(0,1fr); } .te-inline-panel { position:static !important; height:min(600px,calc(100vh - 32px)) !important; } }
4647
4710
  @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;} }
4648
4711
  `;
4649
4712
 
@@ -4777,14 +4840,14 @@ var styles = {
4777
4840
 
4778
4841
  // src/client/TaskEngineSection.tsx
4779
4842
  var import_react3 = require("react");
4780
- var import_dsh_client_ui_primitives3 = require("@deepseek-ai/dsh-client-ui-primitives");
4843
+ var import_dsh_client_ui_primitives2 = require("@deepseek-ai/dsh-client-ui-primitives");
4781
4844
 
4782
4845
  // src/engine.ts
4783
4846
  function formatResourceRef(ref) {
4784
4847
  return `${ref.source}:${ref.name}`;
4785
4848
  }
4786
4849
  function parseResourceRef(text2) {
4787
- const match = /^(bundled|project|user):(.+)$/u.exec(text2);
4850
+ const match = /^(bundled|project|codex-project|user):(.+)$/u.exec(text2);
4788
4851
  if (match === null) return void 0;
4789
4852
  return { source: match[1], name: match[2] };
4790
4853
  }
@@ -4854,7 +4917,7 @@ function validateWorkflow(config) {
4854
4917
  problems.push(`stage_bindings "${stage}": skill ${index + 1} has no name`);
4855
4918
  continue;
4856
4919
  }
4857
- if (!["bundled", "project", "user"].includes(entry.skill.source)) {
4920
+ if (!["bundled", "project", "codex-project", "user"].includes(entry.skill.source)) {
4858
4921
  problems.push(`stage_bindings "${stage}": skill "${entry.skill.name}" has unknown source "${String(entry.skill.source)}"`);
4859
4922
  }
4860
4923
  const skillKey = formatResourceRef(entry.skill);
@@ -4906,10 +4969,6 @@ function validateWorkflow(config) {
4906
4969
  }
4907
4970
 
4908
4971
  // src/workflows.ts
4909
- function bundled(skill, ...rules) {
4910
- const ref = (name) => ({ source: "bundled", name });
4911
- return { skill: ref(skill), rules: rules.map(ref) };
4912
- }
4913
4972
  var FLOW_OPTIONS = [
4914
4973
  { id: "standard", label: "\u5B8C\u6574\u7814\u53D1", description: "\u65B0\u529F\u80FD\u3001\u67B6\u6784\u6216\u8DE8\u6A21\u5757\u6539\u52A8\u3001\u9AD8\u98CE\u9669\u4EFB\u52A1\uFF1A\u9700\u6C42\u786E\u8BA4 \u2192 \u65B9\u6848\u786E\u8BA4 \u2192 \u5B9E\u73B0 \u2192 \u9A8C\u8BC1 \u2192 \u5BA1\u6838 \u2192 \u63D0\u4EA4" },
4915
4974
  { id: "agile", label: "\u65E5\u5E38\u8FED\u4EE3", description: "\u76EE\u6807\u660E\u786E\u7684\u5E38\u89C4\u529F\u80FD\u4E0E\u7F3A\u9677\u4FEE\u590D\uFF1A\u76EE\u6807\u4E0E\u9A8C\u6536 \u2192 \u5B9E\u73B0 \u2192 \u9A8C\u6536\u4E0E\u5BA1\u67E5 \u2192 \u63D0\u4EA4" },
@@ -4941,19 +5000,7 @@ var STANDARD_RECOMMENDATION = {
4941
5000
  { stage: "\u9700\u6C42\u8BC4\u5BA1", id: "requirement", name: "\u9700\u6C42\u8BF4\u660E", fields: ["scope", "acceptance_criteria"] },
4942
5001
  { stage: "\u8BBE\u8BA1", id: "design", name: "\u8BBE\u8BA1\u6587\u6863", fields: ["approach", "risks", "impact"] },
4943
5002
  { stage: "\u4EE3\u7801\u5BA1\u6838", id: "review", name: "\u8BC4\u5BA1\u8BB0\u5F55", fields: ["conclusion", "issues"] }
4944
- ],
4945
- stage_bindings: {
4946
- "\u9700\u6C42\u8BC4\u5BA1": { skills: [bundled("requirement-analysis", "security-redlines")] },
4947
- "\u8BBE\u8BA1": { skills: [bundled("solution-design")] },
4948
- "\u5F00\u53D1": { skills: [bundled("code-implement", "coding-conventions", "security-redlines")] },
4949
- "\u4EA4\u4ED8": { skills: [bundled("code-verify")] },
4950
- "\u4EE3\u7801\u5BA1\u6838": {
4951
- skills: [
4952
- bundled("code-review", "coding-conventions", "security-redlines"),
4953
- bundled("code-commit", "commit-conventions")
4954
- ]
4955
- }
4956
- }
5003
+ ]
4957
5004
  };
4958
5005
  var AGILE = {
4959
5006
  stages: ["\u9700\u6C42", "\u5F00\u53D1", "\u4EA4\u4ED8", "\u5BA1\u67E5"],
@@ -4987,18 +5034,9 @@ var AGILE_RECOMMENDATION = {
4987
5034
  },
4988
5035
  artifacts: [
4989
5036
  { stage: "\u9700\u6C42", id: "requirement", name: "\u9700\u6C42\u8BF4\u660E", fields: ["scope"] },
4990
- // The 审查 stage binds code-review, whose instructions write this artifact with
4991
- // `record artifact=review`. Declaring it keeps that binding executable: the
4992
- // engine refuses an undeclared artifact, so a bound skill pointing at one would
4993
- // be a contract the recommendation made impossible to satisfy.
5037
+ // Optional review record; the flow's review gate itself does not require a skill.
4994
5038
  { stage: "\u5BA1\u67E5", id: "review", name: "\u8BC4\u5BA1\u8BB0\u5F55", fields: ["conclusion", "issues"] }
4995
- ],
4996
- stage_bindings: {
4997
- "\u9700\u6C42": { skills: [bundled("requirement-analysis", "security-redlines")] },
4998
- "\u5F00\u53D1": { skills: [bundled("code-implement", "coding-conventions", "security-redlines")] },
4999
- "\u4EA4\u4ED8": { skills: [bundled("code-verify"), bundled("code-commit", "commit-conventions")] },
5000
- "\u5BA1\u67E5": { skills: [bundled("code-review", "coding-conventions", "security-redlines")] }
5001
- }
5039
+ ]
5002
5040
  };
5003
5041
  var MINIMAL = {
5004
5042
  stages: ["\u5F00\u53D1", "\u4EA4\u4ED8"],
@@ -5014,11 +5052,7 @@ var MINIMAL_RECOMMENDATION = {
5014
5052
  // A fast-change flow checks each change once, not twice under two headings a
5015
5053
  // short change rarely distinguishes. The item still has to be reviewed — what
5016
5054
  // drops is the duplicated verdict, which is where the weight actually was.
5017
- review_depth: "single",
5018
- stage_bindings: {
5019
- "\u5F00\u53D1": { skills: [bundled("code-implement", "coding-conventions", "security-redlines")] },
5020
- "\u4EA4\u4ED8": { skills: [bundled("code-commit", "commit-conventions")] }
5021
- }
5055
+ review_depth: "single"
5022
5056
  };
5023
5057
  function deriveCapabilities(config) {
5024
5058
  const caps = [];
@@ -5054,6 +5088,16 @@ var FLOW_PRESETS = {
5054
5088
  agile: preset("agile", 4, "\u65E5\u5E38\u8FED\u4EE3", "\u76EE\u6807\u660E\u786E\u7684\u5E38\u89C4\u529F\u80FD\u4E0E\u7F3A\u9677\u4FEE\u590D\uFF1A\u76EE\u6807\u4E0E\u9A8C\u6536 \u2192 \u5B9E\u73B0 \u2192 \u9A8C\u6536\u4E0E\u5BA1\u67E5 \u2192 \u63D0\u4EA4", AGILE, AGILE_RECOMMENDATION),
5055
5089
  minimal: preset("minimal", 3, "\u5FEB\u901F\u4FEE\u6539", "\u5C40\u90E8\u3001\u4F4E\u98CE\u9669\u3001\u65B9\u6848\u660E\u786E\u7684\u6539\u52A8\uFF1A\u4FEE\u6539 \u2192 \u68C0\u67E5\u4E0E\u63D0\u4EA4\uFF0C\u6BCF\u9879\u4E00\u6B21\u68C0\u67E5", MINIMAL, MINIMAL_RECOMMENDATION)
5056
5090
  };
5091
+ function retainStageBindings(flow, bindings) {
5092
+ const stages = new Set(FLOW_PRESETS[flow]?.config.stages ?? []);
5093
+ const kept = {};
5094
+ const dropped = [];
5095
+ for (const [stage, binding] of Object.entries(bindings)) {
5096
+ if (stages.has(stage)) kept[stage] = binding;
5097
+ else dropped.push(stage);
5098
+ }
5099
+ return { bindings: kept, dropped };
5100
+ }
5057
5101
  function dedupe(names) {
5058
5102
  return [...new Set(names)];
5059
5103
  }
@@ -5194,12 +5238,11 @@ function describeError(error) {
5194
5238
 
5195
5239
  // src/client/SkillRuleDialog.tsx
5196
5240
  var import_react2 = require("react");
5197
- var import_dsh_client_ui_primitives2 = require("@deepseek-ai/dsh-client-ui-primitives");
5241
+ var import_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
5198
5242
 
5199
5243
  // src/client/ResourceModal.tsx
5200
5244
  var import_react = require("react");
5201
5245
  var import_react_dom = require("react-dom");
5202
- var import_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
5203
5246
  var rootStyle = {
5204
5247
  position: "fixed",
5205
5248
  inset: 0,
@@ -5234,6 +5277,15 @@ var drawerStyle = {
5234
5277
  maxHeight: "100%",
5235
5278
  borderRadius: "16px 0 0 16px"
5236
5279
  };
5280
+ var inlineStyle = {
5281
+ ...dialogStyle,
5282
+ width: "100%",
5283
+ height: "min(720px, calc(100vh - 32px))",
5284
+ maxHeight: "calc(100vh - 32px)",
5285
+ borderRadius: 12,
5286
+ border: "1px solid var(--dsw-alias-border-l2)",
5287
+ boxShadow: "none"
5288
+ };
5237
5289
  var headerStyle = {
5238
5290
  display: "flex",
5239
5291
  alignItems: "center",
@@ -5293,7 +5345,7 @@ function ResourceModal({ title, description, onClose, footer, children, placemen
5293
5345
  closer.current = onClose;
5294
5346
  (0, import_react.useEffect)(() => {
5295
5347
  const previous = document.activeElement;
5296
- dialog.current?.focus();
5348
+ if (placement !== "inline") dialog.current?.focus();
5297
5349
  const onKey = (e) => {
5298
5350
  if (!dialog.current?.contains(document.activeElement)) return;
5299
5351
  if (e.key === "Escape") {
@@ -5302,6 +5354,7 @@ function ResourceModal({ title, description, onClose, footer, children, placemen
5302
5354
  closer.current();
5303
5355
  return;
5304
5356
  }
5357
+ if (placement === "inline") return;
5305
5358
  if (e.key !== "Tab") return;
5306
5359
  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
5360
  const first = nodes[0], last = nodes[nodes.length - 1];
@@ -5322,29 +5375,39 @@ function ResourceModal({ title, description, onClose, footer, children, placemen
5322
5375
  document.removeEventListener("keydown", onKey);
5323
5376
  if (previous?.isConnected) previous.focus();
5324
5377
  };
5325
- }, []);
5378
+ }, [placement]);
5379
+ const panel = (0, import_react.createElement)(
5380
+ "div",
5381
+ {
5382
+ style: placement === "inline" ? inlineStyle : placement === "right" ? drawerStyle : dialogStyle,
5383
+ className: placement === "inline" ? "te-inline-panel" : void 0,
5384
+ ref: dialog,
5385
+ tabIndex: -1,
5386
+ role: placement === "inline" ? "complementary" : "dialog",
5387
+ ...placement === "inline" ? {} : { "aria-modal": true },
5388
+ "aria-label": title
5389
+ },
5390
+ (0, import_react.createElement)(
5391
+ "div",
5392
+ { style: headerStyle },
5393
+ (0, import_react.createElement)("h2", { style: titleStyle }, title),
5394
+ (0, import_react.createElement)(
5395
+ "button",
5396
+ { type: "button", style: closeBtnStyle, "aria-label": "\u5173\u95ED", onClick: onClose },
5397
+ (0, import_react.createElement)(IconClose, { size: 14 })
5398
+ )
5399
+ ),
5400
+ description !== void 0 && description !== "" ? (0, import_react.createElement)("p", { style: descStyle }, description) : null,
5401
+ (0, import_react.createElement)("div", { style: bodyStyle }, children),
5402
+ footer !== void 0 ? (0, import_react.createElement)("div", { style: footerStyle }, footer) : null
5403
+ );
5404
+ if (placement === "inline") return panel;
5326
5405
  return (0, import_react_dom.createPortal)(
5327
5406
  (0, import_react.createElement)(
5328
5407
  "div",
5329
5408
  { style: placement === "right" ? { ...rootStyle, justifyContent: "flex-end", padding: 0 } : rootStyle, className: `te-modal${placement === "right" ? " te-drawer" : ""}`, role: "presentation" },
5330
5409
  (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
- )
5410
+ panel
5348
5411
  ),
5349
5412
  document.body
5350
5413
  );
@@ -5392,14 +5455,14 @@ function SkillRuleDialog({ skill, profile, rules, description, saveLabel, onSave
5392
5455
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
5393
5456
  ResourceModal,
5394
5457
  {
5395
- placement: "right",
5458
+ placement: "inline",
5396
5459
  title: `\u914D\u7F6E\u89C4\u5219 \xB7 ${skill.name}`,
5397
5460
  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
5461
  onClose: close,
5399
5462
  footer: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
5400
5463
  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: () => {
5464
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { variant: "ghost", disabled: busy, onClick: close, children: "\u53D6\u6D88" }),
5465
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { variant: "primary", disabled: busy || !dirty, onClick: () => {
5403
5466
  void save2();
5404
5467
  }, children: busy ? "\u5904\u7406\u4E2D\u2026" : saveLabel ?? "\u4FDD\u5B58\u914D\u7F6E" })
5405
5468
  ] }),
@@ -5478,6 +5541,8 @@ function TaskEngineSection(props) {
5478
5541
  const [loading, setLoading] = (0, import_react3.useState)(true);
5479
5542
  const [loadAttempt, setLoadAttempt] = (0, import_react3.useState)(0);
5480
5543
  const [configProblems, setConfigProblems] = (0, import_react3.useState)([]);
5544
+ const [flowNotice, setFlowNotice] = (0, import_react3.useState)("");
5545
+ const [pendingAdoption, setPendingAdoption] = (0, import_react3.useState)(false);
5481
5546
  const [skills, setSkills] = (0, import_react3.useState)([]);
5482
5547
  const [rules, setRules] = (0, import_react3.useState)([]);
5483
5548
  const [configuringSkill, setConfiguringSkill] = (0, import_react3.useState)(null);
@@ -5499,6 +5564,8 @@ function TaskEngineSection(props) {
5499
5564
  setCommitRequired(result.value.config.commit_required);
5500
5565
  setSource(result.value.source);
5501
5566
  setConfigProblems(result.value.problems);
5567
+ setFlowNotice("");
5568
+ setPendingAdoption(false);
5502
5569
  setSavedAt("");
5503
5570
  } else {
5504
5571
  setLoadError("\u8BFB\u53D6\u914D\u7F6E\u5931\u8D25\uFF1A" + describeError(result.error));
@@ -5532,20 +5599,31 @@ function TaskEngineSection(props) {
5532
5599
  () => validateWorkflow(resolvedConfig(flow, stageBindings, skillProfiles)),
5533
5600
  [flow, stageBindings, skillProfiles]
5534
5601
  );
5602
+ const hasBundledReferences = (0, import_react3.useMemo)(
5603
+ () => Object.values(stageBindings).some((binding) => (binding.skills ?? []).some((entry) => entry.skill.source === "bundled" || entry.skill.source !== "user" && entry.rules.some((rule) => rule.source === "bundled")) || (binding.skill_refs ?? []).some((ref) => ref.source === "bundled")) || Object.entries(skillProfiles).some(([key, profile]) => key.startsWith("bundled:") || !key.startsWith("user:") && profile.rules.some((rule) => rule.source === "bundled")),
5604
+ [stageBindings, skillProfiles]
5605
+ );
5535
5606
  const selectFlow = (id) => {
5536
5607
  if (id === flow) return;
5537
- if (dirty && !window.confirm("\u5F53\u524D\u6D41\u7A0B\u914D\u7F6E\u6709\u672A\u4FDD\u5B58\u7684\u4FEE\u6539\uFF0C\u5207\u6362\u6D41\u7A0B\u4F1A\u4E22\u5F03\u5B83\u4EEC\u3002\u7EE7\u7EED\u5207\u6362\uFF1F")) return;
5608
+ const { bindings, dropped } = retainStageBindings(id, stageBindings);
5609
+ if (dirty && dropped.length > 0 && !window.confirm(`\u5207\u6362\u540E\u5C06\u79FB\u9664\u4E0D\u5C5E\u4E8E\u65B0\u6D41\u7A0B\u7684\u8282\u70B9\u7ED1\u5B9A\uFF1A${dropped.join("\u3001")}\u3002\u7EE7\u7EED\uFF1F`)) return;
5610
+ setStageBindings(bindings);
5611
+ setFlowNotice(dropped.length > 0 ? `\u5DF2\u79FB\u9664\u4E0D\u5C5E\u4E8E\u300C${FLOW_PRESETS[id]?.label ?? id}\u300D\u7684\u8282\u70B9\u7ED1\u5B9A\uFF1A${dropped.join("\u3001")}\u3002\u4FDD\u5B58\u540E\u624D\u4F1A\u5199\u5165\u9879\u76EE\u914D\u7F6E\u3002` : "");
5538
5612
  setFlow(id);
5613
+ setPendingAdoption(false);
5539
5614
  setDirty(true);
5540
5615
  setSavedAt("");
5541
5616
  };
5542
5617
  const adopt = () => {
5543
- const adopted = adoptRecommendation(flow);
5618
+ const adopted = adoptRecommendation(flow, {
5619
+ flow,
5620
+ stage_bindings: stageBindings,
5621
+ skill_profiles: skillProfiles,
5622
+ ...commitRequired !== void 0 ? { commit_required: commitRequired } : {}
5623
+ });
5544
5624
  if (adopted === void 0) return;
5545
- if (dirty && !window.confirm("\u91C7\u7528\u63A8\u8350\u914D\u7F6E\u4F1A\u66FF\u6362\u5F53\u524D\u7684\u6280\u80FD\u4E0E\u89C4\u5219\u8BBE\u7F6E\u3002\u7EE7\u7EED\uFF1F")) return;
5546
- setStageBindings({ ...adopted.stage_bindings ?? {} });
5547
- const adoptedFlow = resolveFlow(flow, adopted);
5548
- setSkillProfiles(adoptedFlow.ok ? adoptedFlow.config.skill_profiles ?? {} : {});
5625
+ if (dirty && !window.confirm("\u91C7\u7528\u63A8\u8350\u7684\u63D0\u4EA4\u6587\u672C\u3001\u4EA7\u7269\u5B57\u6BB5\u548C\u8BC4\u5BA1\u6DF1\u5EA6\uFF1F\u73B0\u6709\u6280\u80FD\u4E0E\u89C4\u5219\u4F1A\u4FDD\u7559\u3002")) return;
5626
+ setFlowNotice("");
5549
5627
  setCommitRule(adopted.commit);
5550
5628
  setArtifacts(adopted.artifacts);
5551
5629
  setReviewDepth(adopted.review_depth);
@@ -5554,6 +5632,10 @@ function TaskEngineSection(props) {
5554
5632
  };
5555
5633
  const updateSkillProfile = async (profile) => {
5556
5634
  if (!configuringSkill) return;
5635
+ if (configuringSkill.source === "user") {
5636
+ const result = await remote.writeUserSkillProfile({ name: configuringSkill.name, profile });
5637
+ if (!result.ok || !result.value.ok) throw new Error(result.ok ? result.value.error : "\u4FDD\u5B58\u7528\u6237\u7EA7\u6280\u80FD\u89C4\u5219\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u3002");
5638
+ }
5557
5639
  const key = formatResourceRef(configuringSkill);
5558
5640
  const bindings = {};
5559
5641
  for (const [name, binding] of Object.entries(stageBindings)) {
@@ -5570,116 +5652,132 @@ function TaskEngineSection(props) {
5570
5652
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h2", { style: styles.title, children: "\u5DE5\u7A0B\u6D41\u7A0B\u914D\u7F6E" }),
5571
5653
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles.problems, children: [
5572
5654
  /* @__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" }),
5655
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives2.StateDot, { state: "error" }),
5574
5656
  "\u8BFB\u53D6\u5931\u8D25"
5575
5657
  ] }),
5576
5658
  /* @__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" })
5659
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives2.Button, { onClick: () => setLoadAttempt((n) => n + 1), children: "\u91CD\u8BD5" })
5578
5660
  ] })
5579
5661
  ] });
5580
5662
  }
5581
5663
  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: [
5584
- "\u539F\u914D\u7F6E\u6709\u95EE\u9898\uFF1A",
5585
- configProblems.join("\uFF1B"),
5586
- "\u3002\u8BF7\u9009\u62E9\u6709\u6548\u9884\u8BBE\u5E76\u4FDD\u5B58\u4FEE\u590D\u3002"
5587
- ] }),
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" })
5591
- ] }),
5592
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles.adoptRow, children: [
5593
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_dsh_client_ui_primitives3.Button, { size: "sm", onClick: adopt, children: [
5594
- "\u91C7\u7528\u300C",
5595
- FLOW_PRESETS[flow]?.label ?? flow,
5596
- "\u300D\u7684\u63A8\u8350\u914D\u7F6E"
5664
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: `te-config-layout${configuringSkill ? " is-open" : ""}`, children: [
5665
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "te-config-main", style: styles.wrap, children: [
5666
+ configProblems.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("p", { role: "alert", style: styles.problems, children: [
5667
+ "\u539F\u914D\u7F6E\u6709\u95EE\u9898\uFF1A",
5668
+ configProblems.join("\uFF1B"),
5669
+ "\u3002\u8BF7\u9009\u62E9\u6709\u6548\u9884\u8BBE\u5E76\u4FDD\u5B58\u4FEE\u590D\u3002"
5597
5670
  ] }),
5598
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: styles.muted, children: "\u5199\u5165\u63A8\u8350\u6280\u80FD\u3001\u63D0\u4EA4\u4FE1\u606F\u683C\u5F0F\u4E0E\u4EA7\u7269\u5B57\u6BB5\u3002\u4EC5\u5728\u4F60\u70B9\u51FB\u65F6\u53D1\u751F\u4E00\u6B21\uFF1B\u5220\u9664\u540E\u4E0D\u4F1A\u81EA\u52A8\u8865\u56DE\u3002" })
5599
- ] }),
5600
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles.sourceRow, children: [
5601
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives3.StateDot, { state: source === "project" ? "done" : source === "invalid" ? "warning" : "ongoing" }),
5602
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: styles.sourceText, children: sourceText(source) })
5603
- ] }),
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) => {
5607
- const active = flow === option.id;
5608
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
5609
- "button",
5671
+ flowNotice && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { role: "status", className: "te-flow-notice", children: flowNotice }),
5672
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles.head, children: [
5673
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h2", { style: styles.title, children: "\u5DE5\u7A0B\u6D41\u7A0B\u914D\u7F6E" }),
5674
+ /* @__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\u63D0\u4EA4\u6587\u672C\u3001\u4EA7\u7269\u5B57\u6BB5\u548C\u8BC4\u5BA1\u6DF1\u5EA6\u7684\u8D77\u70B9\u65F6\uFF0C\u53EF\u4EE5\u300C\u91C7\u7528\u63A8\u8350\u914D\u7F6E\u300D\u3002\u6280\u80FD\u4E0E\u89C4\u5219\u8BF7\u6309\u9879\u76EE\u9700\u8981\u81EA\u884C\u521B\u5EFA\u5E76\u7ED1\u5B9A\u3002" })
5675
+ ] }),
5676
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles.adoptRow, children: [
5677
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_dsh_client_ui_primitives2.Button, { size: "sm", onClick: adopt, children: [
5678
+ "\u91C7\u7528\u300C",
5679
+ FLOW_PRESETS[flow]?.label ?? flow,
5680
+ "\u300D\u7684\u63A8\u8350\u914D\u7F6E"
5681
+ ] }),
5682
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: styles.muted, children: "\u4EC5\u5199\u5165\u53EF\u4FEE\u6539\u7684\u6587\u672C\u4E0E\u5B57\u6BB5\uFF0C\u4E0D\u589E\u5220\u73B0\u6709\u6280\u80FD\u548C\u89C4\u5219\u7ED1\u5B9A\u3002" })
5683
+ ] }),
5684
+ hasBundledReferences && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles.adoptRow, children: [
5685
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives2.Button, { size: "sm", onClick: () => {
5686
+ setPendingAdoption(true);
5687
+ setDirty(true);
5688
+ setSavedAt("");
5689
+ setFlowNotice("\u4FDD\u5B58\u540E\u4F1A\u628A\u5F53\u524D\u914D\u7F6E\u4E2D\u7684\u5185\u7F6E\u5F15\u7528\u590D\u5236\u5230\u9879\u76EE\uFF0C\u4FDD\u7559\u5DF2\u6709\u9879\u76EE\u526F\u672C\u53CA\u5176\u4ED6\u914D\u7F6E\u3002");
5690
+ }, children: "\u628A\u5F53\u524D\u5185\u7F6E\u5F15\u7528\u8FC1\u79FB\u5230\u9879\u76EE" }),
5691
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: styles.muted, children: "\u5C06\u5F53\u524D\u5185\u7F6E\u5F15\u7528\u590D\u5236\u4E3A\u9879\u76EE\u8D44\u6E90\u3002" })
5692
+ ] }),
5693
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles.sourceRow, children: [
5694
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives2.StateDot, { state: source === "project" ? "done" : source === "invalid" ? "warning" : "ongoing" }),
5695
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: styles.sourceText, children: sourceText(source) })
5696
+ ] }),
5697
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles.field, children: [
5698
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { children: "\u6D41\u7A0B\u9884\u8BBE" }),
5699
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: styles.flowGrid, children: FLOW_OPTIONS.map((option) => {
5700
+ const active = flow === option.id;
5701
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
5702
+ "button",
5703
+ {
5704
+ type: "button",
5705
+ "aria-pressed": active,
5706
+ onClick: () => {
5707
+ selectFlow(option.id);
5708
+ },
5709
+ style: { ...styles.flowOption, ...active ? styles.flowOptionActive : {} },
5710
+ children: [
5711
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { style: styles.flowOptionTitle, children: [
5712
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives2.StateDot, { state: active ? "done" : "ongoing", size: 8 }),
5713
+ option.label
5714
+ ] }),
5715
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { style: styles.flowOptionDesc, children: option.description })
5716
+ ]
5717
+ },
5718
+ option.id
5719
+ );
5720
+ }) })
5721
+ ] }),
5722
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(SectionCard, { icon: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(IconSettings, { size: 16 }), title: "\u9636\u6BB5\u6280\u80FD", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(BindingEditor, { stages, stageBindings, setStageBindings: (next) => {
5723
+ setStageBindings(next);
5724
+ setDirty(true);
5725
+ setSavedAt("");
5726
+ }, skillProfiles, setSkillProfiles: (next) => {
5727
+ setSkillProfiles(next);
5728
+ setDirty(true);
5729
+ setSavedAt("");
5730
+ }, skills, onConfigureSkill: setConfiguringSkill }) }),
5731
+ problems.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles.problems, children: [
5732
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { style: styles.problemsTitle, children: [
5733
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives2.StateDot, { state: "error" }),
5734
+ "\u6709 ",
5735
+ problems.length,
5736
+ " \u4E2A\u95EE\u9898\uFF08\u4FDD\u5B58\u4F1A\u88AB\u62D2\u7EDD\uFF09"
5737
+ ] }),
5738
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("ul", { style: styles.problemsList, children: problems.map((p) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("li", { children: p }, p)) })
5739
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { style: styles.okText, children: [
5740
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives2.StateDot, { state: "done" }),
5741
+ source === "project" ? "\u914D\u7F6E\u6709\u6548" : "\u4F7F\u7528\u7A7A\u767D\u6D41\u7A0B\u914D\u7F6E\uFF08\u5C1A\u672A\u4FDD\u5B58\uFF09"
5742
+ ] }),
5743
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles.actions, children: [
5744
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
5745
+ import_dsh_client_ui_primitives2.Button,
5610
5746
  {
5611
- type: "button",
5612
- "aria-pressed": active,
5747
+ variant: "primary",
5748
+ size: "md",
5749
+ icon: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(IconCheck, { size: 16 }),
5750
+ disabled: problems.length > 0 || saving,
5613
5751
  onClick: () => {
5614
- selectFlow(option.id);
5752
+ setSaving(true);
5753
+ 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 } : {}, ...pendingAdoption ? { materialize_bundled: "project" } : {} }, workspace, setSavedAt, setSource).then((view) => {
5754
+ if (view) {
5755
+ setConfigProblems([]);
5756
+ setDirty(false);
5757
+ setPendingAdoption(false);
5758
+ setStageBindings(view.config.stage_bindings ?? {});
5759
+ setSkillProfiles(view.config.skill_profiles ?? {});
5760
+ refreshCatalogs();
5761
+ }
5762
+ }).finally(() => setSaving(false));
5615
5763
  },
5616
- style: { ...styles.flowOption, ...active ? styles.flowOptionActive : {} },
5617
- children: [
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 }),
5620
- option.label
5621
- ] }),
5622
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { style: styles.flowOptionDesc, children: option.description })
5623
- ]
5624
- },
5625
- option.id
5626
- );
5627
- }) })
5628
- ] }),
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) => {
5630
- setStageBindings(next);
5631
- setDirty(true);
5632
- setSavedAt("");
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" }),
5641
- "\u6709 ",
5642
- problems.length,
5643
- " \u4E2A\u95EE\u9898\uFF08\u4FDD\u5B58\u4F1A\u88AB\u62D2\u7EDD\uFF09"
5644
- ] }),
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"
5649
- ] }),
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,
5653
- {
5654
- variant: "primary",
5655
- size: "md",
5656
- icon: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives3.IconCheckOutline16, { size: 16 }),
5657
- disabled: problems.length > 0 || saving,
5658
- onClick: () => {
5659
- setSaving(true);
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) => {
5661
- if (ok) {
5662
- setConfigProblems([]);
5663
- setDirty(false);
5664
- }
5665
- }).finally(() => setSaving(false));
5666
- },
5667
- children: saving ? "\u6B63\u5728\u4FDD\u5B58\u2026" : dirty ? "\u4FDD\u5B58\u5230 .dsh/eng.json" : "\u5DF2\u4FDD\u5B58 \xB7 \u65E0\u9700\u4FDD\u5B58"
5668
- }
5669
- ),
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" }),
5672
- savedAt
5673
- ] }) : null
5764
+ children: saving ? "\u6B63\u5728\u4FDD\u5B58\u2026" : dirty ? "\u4FDD\u5B58\u5230 .dsh/eng.json" : "\u5DF2\u4FDD\u5B58 \xB7 \u65E0\u9700\u4FDD\u5B58"
5765
+ }
5766
+ ),
5767
+ savedAt !== "" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { style: styles.okText, children: [
5768
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives2.StateDot, { state: savedAt.startsWith("\u5DF2") ? "done" : "error" }),
5769
+ savedAt
5770
+ ] }) : null
5771
+ ] })
5674
5772
  ] }),
5675
5773
  configuringSkill ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
5676
5774
  SkillRuleDialog,
5677
5775
  {
5678
5776
  skill: configuringSkill,
5679
5777
  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",
5778
+ rules: configuringSkill.source === "user" ? rules.filter((rule) => rule.ref.source !== "project") : rules,
5779
+ description: configuringSkill.source === "user" ? "\u7528\u6237\u7EA7\u6280\u80FD\u7684\u89C4\u5219\u914D\u7F6E\u7ACB\u5373\u4FDD\u5B58\u5230\u7528\u6237\u76EE\u5F55\uFF0C\u6240\u6709\u9879\u76EE\u4E0E\u4F1A\u8BDD\u5171\u7528\uFF1B\u8282\u70B9\u9009\u62E9\u4ECD\u9700\u5728\u9875\u9762\u5E95\u90E8\u4FDD\u5B58\u3002" : "\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",
5780
+ saveLabel: configuringSkill.source === "user" ? "\u4FDD\u5B58\u7528\u6237\u7EA7\u89C4\u5219" : "\u5E94\u7528\u5230\u5F53\u524D\u914D\u7F6E",
5683
5781
  onSave: updateSkillProfile,
5684
5782
  onClose: () => setConfiguringSkill(null)
5685
5783
  },
@@ -5700,7 +5798,7 @@ function sourceText(source) {
5700
5798
  function SectionCard({ icon, title, hint, children }) {
5701
5799
  const [open, setOpen] = (0, import_react3.useState)(true);
5702
5800
  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,
5801
+ import_dsh_client_ui_primitives2.DisclosureRow,
5704
5802
  {
5705
5803
  icon,
5706
5804
  title,
@@ -5747,7 +5845,7 @@ function BindingEditor({ stages, stageBindings, setStageBindings, skillProfiles,
5747
5845
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles.section, children: [
5748
5846
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles.field, children: [
5749
5847
  /* @__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: () => {
5848
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: styles.chips, children: stages.map((s) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives2.Pill, { active: s === currentStage, onClick: () => {
5751
5849
  setStage(s);
5752
5850
  }, children: s }, s)) })
5753
5851
  ] }),
@@ -5828,24 +5926,25 @@ async function save(remote, config, workspace, setSavedAt, setSource) {
5828
5926
  const result = await remote.write({ path: workspace, ...config });
5829
5927
  if (!result.ok) {
5830
5928
  setSavedAt("\u4FDD\u5B58\u5931\u8D25\uFF1A" + describeError(result.error));
5831
- return false;
5929
+ return void 0;
5832
5930
  }
5833
5931
  if (!result.value.ok) {
5834
5932
  setSavedAt("\u4FDD\u5B58\u5931\u8D25\uFF1A" + result.value.problems.join("\uFF1B"));
5835
- return false;
5933
+ return void 0;
5836
5934
  }
5837
5935
  setSource(result.value.source);
5838
- setSavedAt("\u5DF2\u4FDD\u5B58");
5839
- return true;
5936
+ const reused = result.value.adoption?.reused.length ?? 0;
5937
+ setSavedAt(reused > 0 ? `\u5DF2\u4FDD\u5B58\uFF1B\u4FDD\u7559\u4E86 ${reused} \u4EFD\u5DF2\u6709\u9879\u76EE\u8D44\u6E90` : "\u5DF2\u4FDD\u5B58");
5938
+ return result.value;
5840
5939
  } catch (error) {
5841
5940
  setSavedAt("\u4FDD\u5B58\u5931\u8D25\uFF1A" + describeError(error));
5842
- return false;
5941
+ return void 0;
5843
5942
  }
5844
5943
  }
5845
5944
 
5846
5945
  // src/client/InitPanel.tsx
5847
5946
  var import_react4 = require("react");
5848
- var import_dsh_client_ui_primitives4 = require("@deepseek-ai/dsh-client-ui-primitives");
5947
+ var import_dsh_client_ui_primitives3 = require("@deepseek-ai/dsh-client-ui-primitives");
5849
5948
  var MD_LABELS = { code: { copyLabel: "\u590D\u5236", copiedLabel: "\u5DF2\u590D\u5236" }, footnotes: "\u811A\u6CE8" };
5850
5949
  var INIT_TIMEOUT_S = 150;
5851
5950
  var card = {
@@ -5936,7 +6035,7 @@ function InitPanel({ workspace, remote }) {
5936
6035
  (0, import_react4.createElement)(
5937
6036
  "div",
5938
6037
  { style: { display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap" } },
5939
- (0, import_react4.createElement)(import_dsh_client_ui_primitives4.StateDot, { state: exists ? "done" : "ongoing" }),
6038
+ (0, import_react4.createElement)(import_dsh_client_ui_primitives3.StateDot, { state: exists ? "done" : "ongoing" }),
5940
6039
  (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
6040
  view?.path !== void 0 ? (0, import_react4.createElement)("span", { style: styles.sourceBadge }, `\u5DF2\u5B9A\u4F4D\u5230 ${view.path}`) : null
5942
6041
  ),
@@ -5948,7 +6047,7 @@ function InitPanel({ workspace, remote }) {
5948
6047
  exists && !editing && draft === null ? (0, import_react4.createElement)(
5949
6048
  "div",
5950
6049
  { style: styles.mdPreview },
5951
- (0, import_react4.createElement)(import_dsh_client_ui_primitives4.MarkdownText, { text: view.content, labels: MD_LABELS })
6050
+ (0, import_react4.createElement)(import_dsh_client_ui_primitives3.MarkdownText, { text: view.content, labels: MD_LABELS })
5952
6051
  ) : null,
5953
6052
  draft !== null ? (0, import_react4.createElement)(
5954
6053
  "div",
@@ -5956,13 +6055,13 @@ function InitPanel({ workspace, remote }) {
5956
6055
  (0, import_react4.createElement)(
5957
6056
  "div",
5958
6057
  { style: styles.sourceRow },
5959
- (0, import_react4.createElement)(import_dsh_client_ui_primitives4.StateDot, { state: "ongoing", size: 8 }),
6058
+ (0, import_react4.createElement)(import_dsh_client_ui_primitives3.StateDot, { state: "ongoing", size: 8 }),
5960
6059
  (0, import_react4.createElement)("span", { style: styles.sourceBadge }, `AI \u8349\u7A3F \xB7 ${draft.lines} \u884C \xB7 \u5C1A\u672A\u5199\u5165`)
5961
6060
  ),
5962
6061
  (0, import_react4.createElement)(
5963
6062
  "div",
5964
6063
  { style: styles.mdPreview },
5965
- (0, import_react4.createElement)(import_dsh_client_ui_primitives4.MarkdownText, { text: draft.content, labels: MD_LABELS })
6064
+ (0, import_react4.createElement)(import_dsh_client_ui_primitives3.MarkdownText, { text: draft.content, labels: MD_LABELS })
5966
6065
  )
5967
6066
  ) : null,
5968
6067
  editing ? (0, import_react4.createElement)("textarea", {
@@ -5982,7 +6081,7 @@ function InitPanel({ workspace, remote }) {
5982
6081
  draft !== null ? (0, import_react4.createElement)(
5983
6082
  "div",
5984
6083
  { style: styles.row },
5985
- (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, {
6084
+ (0, import_react4.createElement)(import_dsh_client_ui_primitives3.Button, {
5986
6085
  variant: "primary",
5987
6086
  size: "md",
5988
6087
  disabled: draft.lines > 200,
@@ -5992,13 +6091,13 @@ function InitPanel({ workspace, remote }) {
5992
6091
  }
5993
6092
  }, exists ? "\u4FDD\u5B58\u5E76\u8986\u76D6" : "\u4FDD\u5B58"),
5994
6093
  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: () => {
6094
+ (0, import_react4.createElement)(import_dsh_client_ui_primitives3.Button, { variant: "ghost", size: "md", onClick: () => {
5996
6095
  setDraft(null);
5997
6096
  } }, "\u653E\u5F03")
5998
6097
  ) : editing ? (0, import_react4.createElement)(
5999
6098
  "div",
6000
6099
  { style: styles.row },
6001
- (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, {
6100
+ (0, import_react4.createElement)(import_dsh_client_ui_primitives3.Button, {
6002
6101
  variant: "primary",
6003
6102
  size: "md",
6004
6103
  disabled: body2.trim() === "",
@@ -6007,13 +6106,13 @@ function InitPanel({ workspace, remote }) {
6007
6106
  void write(body2, exists);
6008
6107
  }
6009
6108
  }, exists ? "\u4FDD\u5B58\u5E76\u8986\u76D6" : "\u4FDD\u5B58"),
6010
- (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "ghost", size: "md", onClick: () => {
6109
+ (0, import_react4.createElement)(import_dsh_client_ui_primitives3.Button, { variant: "ghost", size: "md", onClick: () => {
6011
6110
  setEditing(false);
6012
6111
  } }, "\u53D6\u6D88")
6013
6112
  ) : (0, import_react4.createElement)(
6014
6113
  "div",
6015
6114
  { style: styles.row },
6016
- (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, {
6115
+ (0, import_react4.createElement)(import_dsh_client_ui_primitives3.Button, {
6017
6116
  variant: "primary",
6018
6117
  size: "md",
6019
6118
  disabled: generating,
@@ -6022,7 +6121,7 @@ function InitPanel({ workspace, remote }) {
6022
6121
  void generate();
6023
6122
  }
6024
6123
  }, exists ? "\u91CD\u65B0\u521D\u59CB\u5316\uFF08AI \u626B\u63CF\u8986\u76D6\uFF09" : "\u8BA9 AI \u521D\u59CB\u5316"),
6025
- exists ? (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "outline", size: "md", onClick: startEdit }, "\u624B\u52A8\u7F16\u8F91") : null
6124
+ exists ? (0, import_react4.createElement)(import_dsh_client_ui_primitives3.Button, { variant: "outline", size: "md", onClick: startEdit }, "\u624B\u52A8\u7F16\u8F91") : null
6026
6125
  )
6027
6126
  )
6028
6127
  );
@@ -6033,10 +6132,10 @@ var import_react6 = require("react");
6033
6132
 
6034
6133
  // src/client/ResourceManager.tsx
6035
6134
  var import_react5 = require("react");
6036
- var import_dsh_client_ui_primitives5 = require("@deepseek-ai/dsh-client-ui-primitives");
6135
+ var import_dsh_client_ui_primitives4 = require("@deepseek-ai/dsh-client-ui-primitives");
6037
6136
  var labels = { code: { copyLabel: "\u590D\u5236", copiedLabel: "\u5DF2\u590D\u5236" }, footnotes: "\u811A\u6CE8" };
6038
6137
  var levelOf = (row) => row.source === "bundled" ? "bundled" : row.source.startsWith("user") ? "user" : "project";
6039
- var sourceText2 = (source) => source === "bundled" ? "\u5185\u7F6E" : source.startsWith("user") ? "\u4E2A\u4EBA" : "\u9879\u76EE";
6138
+ var sourceText2 = (source) => source === "bundled" ? "\u5185\u7F6E" : source === "codex-project" ? "\u9879\u76EE \xB7 Codex" : source.startsWith("user") ? "\u4E2A\u4EBA" : "\u9879\u76EE";
6040
6139
  var sizeText = (bytes) => bytes < 1024 ? `${bytes} B` : bytes < 1024 * 1024 ? `${(bytes / 1024).toFixed(1)} KB` : `${(bytes / 1024 / 1024).toFixed(1)} MB`;
6041
6140
  var fail = (r) => describeError(r.error ?? "\u64CD\u4F5C\u5931\u8D25");
6042
6141
  function ResourceManager({ workspace, remote, kind, onConfigureSkill }) {
@@ -6069,7 +6168,7 @@ function ResourceManager({ workspace, remote, kind, onConfigureSkill }) {
6069
6168
  const input = (0, import_react5.useRef)(null);
6070
6169
  const fileEpoch = (0, import_react5.useRef)(0);
6071
6170
  const browseEpoch = (0, import_react5.useRef)(0);
6072
- const readonly = editing !== null && editing !== "new" && levelOf(editing) === "bundled";
6171
+ const readonly = editing !== null && editing !== "new" && (levelOf(editing) === "bundled" || editing.source === "codex-project");
6073
6172
  (0, import_react5.useEffect)(() => {
6074
6173
  let active = true;
6075
6174
  setLoading(true);
@@ -6211,7 +6310,7 @@ function ResourceManager({ workspace, remote, kind, onConfigureSkill }) {
6211
6310
  setLevel(lvl === "user" ? "user" : "project");
6212
6311
  setBusy(true);
6213
6312
  try {
6214
- const r = kind === "skill" ? await remote.readSkill({ name: row.name, level: lvl, path: workspace }) : await remote.readRule({ name: row.name, level: lvl, path: workspace });
6313
+ const r = kind === "skill" ? await remote.readSkill({ name: row.name, level: row.source === "codex-project" ? "codex-project" : lvl, path: workspace }) : await remote.readRule({ name: row.name, level: lvl, path: workspace });
6215
6314
  if (!r.ok) throw new Error(fail(r));
6216
6315
  if (!r.value.ok) throw new Error(r.value.error ?? "\u8BFB\u53D6\u5931\u8D25");
6217
6316
  setBody(r.value.content);
@@ -6321,10 +6420,10 @@ function ResourceManager({ workspace, remote, kind, onConfigureSkill }) {
6321
6420
  (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) => {
6322
6421
  void selected(Array.from(e.target.files ?? []));
6323
6422
  } }),
6324
- (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: () => {
6423
+ (0, import_react5.createElement)("div", { className: "te-section-heading" }, (0, import_react5.createElement)("div", null, (0, import_react5.createElement)("h2", null, `${noun}\u5E93`), (0, import_react5.createElement)("p", null, kind === "skill" ? "\u628A\u53EF\u590D\u7528\u7684\u5DE5\u4F5C\u65B9\u6CD5\u5E26\u5165\u9879\u76EE\u3002" : "\u4E3A\u9879\u76EE\u660E\u786E\u7EA6\u5B9A\uFF0C\u8BA9\u6BCF\u6B21\u4EA4\u4ED8\u4FDD\u6301\u4E00\u81F4\u3002")), (0, import_react5.createElement)("div", { className: "te-actions" }, (0, import_react5.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "outline", onClick: () => {
6325
6424
  void edit("new");
6326
- } }, `\u65B0\u5EFA${noun}`), (0, import_react5.createElement)(import_dsh_client_ui_primitives5.Button, { variant: "primary", onClick: choose }, `\u5B89\u88C5${noun}`))),
6327
- (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")),
6425
+ } }, `\u65B0\u5EFA${noun}`), (0, import_react5.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "primary", onClick: choose }, `\u5B89\u88C5${noun}`))),
6426
+ (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: "project" }, "\u9879\u76EE"), (0, import_react5.createElement)("option", { value: "user" }, "\u4E2A\u4EBA")), (0, import_react5.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "ghost", onClick: () => refresh((n) => n + 1), disabled: loading }, "\u5237\u65B0")),
6328
6427
  notice ? (0, import_react5.createElement)("div", { className: "te-success", role: "status" }, notice) : null,
6329
6428
  !importing && !editing && !deleting ? status() : null,
6330
6429
  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)(
@@ -6333,13 +6432,13 @@ function ResourceManager({ workspace, remote, kind, onConfigureSkill }) {
6333
6432
  (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))),
6334
6433
  (0, import_react5.createElement)("h3", null, row.name),
6335
6434
  (0, import_react5.createElement)("p", null, row.description || "\u9879\u76EE\u7EA6\u5B9A\u4E0E\u6267\u884C\u89C4\u5219"),
6336
- (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: () => {
6435
+ (0, import_react5.createElement)("div", { className: "te-actions" }, kind === "skill" && onConfigureSkill ? (0, import_react5.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "primary", size: "sm", onClick: () => onConfigureSkill({ source: row.source === "codex-project" ? "codex-project" : levelOf(row), name: row.name }) }, "\u914D\u7F6E\u89C4\u5219") : null, (0, import_react5.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "outline", size: "sm", onClick: () => {
6337
6436
  void edit(row, true);
6338
- } }, "\u67E5\u770B"), levelOf(row) === "bundled" ? (0, import_react5.createElement)(import_dsh_client_ui_primitives5.Button, { variant: "ghost", size: "sm", disabled: busy, onClick: () => {
6437
+ } }, "\u67E5\u770B"), levelOf(row) === "bundled" ? (0, import_react5.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "ghost", size: "sm", disabled: busy, onClick: () => {
6339
6438
  void copyTemplate(row);
6340
- } }, "\u4EE5\u6B64\u4E3A\u6A21\u677F\u65B0\u5EFA") : (0, import_react5.createElement)(import_dsh_client_ui_primitives5.Button, { variant: "ghost", size: "sm", onClick: () => {
6439
+ } }, "\u4EE5\u6B64\u4E3A\u6A21\u677F\u65B0\u5EFA") : row.source !== "codex-project" ? (0, import_react5.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "ghost", size: "sm", onClick: () => {
6341
6440
  void edit(row);
6342
- } }, "\u7F16\u8F91"), levelOf(row) !== "bundled" ? (0, import_react5.createElement)("button", { className: "te-delete", onClick: () => {
6441
+ } }, "\u7F16\u8F91") : null, levelOf(row) !== "bundled" && row.source !== "codex-project" ? (0, import_react5.createElement)("button", { className: "te-delete", onClick: () => {
6343
6442
  setDeleting(row);
6344
6443
  setError("");
6345
6444
  } }, "\u5220\u9664") : null)
@@ -6351,17 +6450,17 @@ function ResourceManager({ workspace, remote, kind, onConfigureSkill }) {
6351
6450
  } }, "\u9AD8\u7EA7\uFF1A\u4ECE Harness \u4E3B\u673A\u8DEF\u5F84\u5B89\u88C5") : null,
6352
6451
  importing ? (0, import_react5.createElement)(
6353
6452
  ResourceModal,
6354
- { 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: () => {
6453
+ { title: `\u5B89\u88C5${noun}`, description: "\u5148\u68C0\u67E5\u5185\u5BB9\u548C\u5B89\u88C5\u4F4D\u7F6E\uFF0C\u786E\u8BA4\u540E\u624D\u4F1A\u5199\u5165\u3002", onClose: close, footer: (0, import_react5.createElement)("div", { className: "te-actions" }, (0, import_react5.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "ghost", disabled: busy, onClick: close }, "\u53D6\u6D88"), (0, import_react5.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "primary", disabled: busy || !preview || preview.conflict, onClick: () => {
6355
6454
  void install();
6356
6455
  } }, busy ? "\u5904\u7406\u4E2D\u2026" : "\u786E\u8BA4\u5B89\u88C5")) },
6357
6456
  targets(),
6358
- (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),
6457
+ (0, import_react5.createElement)("div", { className: "te-actions" }, (0, import_react5.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "outline", disabled: busy, onClick: choose }, "\u91CD\u65B0\u9009\u62E9"), kind === "skill" ? (0, import_react5.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "ghost", disabled: busy, onClick: () => setManual(!manual) }, manual ? "\u6536\u8D77\u9AD8\u7EA7\u65B9\u5F0F" : "\u4E3B\u673A\u8DEF\u5F84") : null),
6359
6458
  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) => {
6360
6459
  setSourceDir(e.target.value);
6361
6460
  setRequest(null);
6362
- } }), (0, import_react5.createElement)(import_dsh_client_ui_primitives5.Button, { variant: "outline", onClick: () => {
6461
+ } }), (0, import_react5.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "outline", onClick: () => {
6363
6462
  void browse(sourceDir);
6364
- } }, "\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: () => {
6463
+ } }, "\u6D4F\u89C8"), (0, import_react5.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "outline", disabled: busy || !sourceDir.trim(), onClick: () => setRequest({ kind, level, path: workspace, files: [], sourceDir }) }, "\u9884\u89C8\u76EE\u5F55")), (0, import_react5.createElement)("div", { className: "te-dir-list" }, browsePath ? (0, import_react5.createElement)("button", { onClick: () => {
6365
6464
  void browse(browsePath.replace(/[\\/][^\\/]+[\\/]?$/u, "") || "/");
6366
6465
  } }, "\u2191 \u4E0A\u7EA7\u76EE\u5F55") : null, ...dirs.map((d) => (0, import_react5.createElement)("button", { key: d.name, onClick: () => {
6367
6466
  setRequest(null);
@@ -6369,21 +6468,21 @@ function ResourceManager({ workspace, remote, kind, onConfigureSkill }) {
6369
6468
  } }, d.name + (d.hasSkill ? " \xB7 SKILL.md" : ""))))) : null,
6370
6469
  busy ? (0, import_react5.createElement)("p", { role: "status" }, "\u6B63\u5728\u6821\u9A8C\u6587\u4EF6\uFF0C\u8BF7\u7A0D\u5019\u2026") : null,
6371
6470
  status(),
6372
- 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
6471
+ preview ? (0, import_react5.createElement)("div", { className: "te-preview" }, (0, import_react5.createElement)("h3", null, preview.name), (0, import_react5.createElement)("p", null, preview.description), (0, import_react5.createElement)("div", { className: "te-actions" }, (0, import_react5.createElement)("span", { className: "te-badge" }, `${preview.files} \u4E2A\u6587\u4EF6`), (0, import_react5.createElement)("span", { className: "te-badge" }, sizeText(preview.bytes))), (0, import_react5.createElement)("code", { className: "te-path" }, preview.target), preview.conflict ? (0, import_react5.createElement)("div", { className: "te-alert", role: "alert" }, "\u5DF2\u6709\u540C\u540D\u8D44\u6E90\u3002\u8BF7\u53D6\u6D88\u5E76\u68C0\u67E5\u73B0\u6709\u5185\u5BB9\uFF0C\u5B89\u88C5\u4E0D\u4F1A\u8986\u76D6\u5B83\u3002") : null, (0, import_react5.createElement)("div", { className: "te-markdown" }, (0, import_react5.createElement)(import_dsh_client_ui_primitives4.MarkdownText, { text: preview.content, labels }))) : null
6373
6472
  ) : null,
6374
6473
  editing ? (0, import_react5.createElement)(
6375
6474
  ResourceModal,
6376
- { 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: () => {
6475
+ { title: editing === "new" ? `\u65B0\u5EFA${noun}` : `${viewing ? "\u67E5\u770B" : "\u7F16\u8F91"}${noun} \xB7 ${name}`, onClose: close, footer: (0, import_react5.createElement)("div", { className: "te-actions" }, (0, import_react5.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "ghost", disabled: busy, onClick: close }, "\u5173\u95ED"), editing !== "new" && levelOf(editing) === "bundled" ? (0, import_react5.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "outline", disabled: busy, onClick: () => {
6377
6476
  void copyTemplate(editing);
6378
- } }, "\u4EE5\u6B64\u4E3A\u6A21\u677F\u65B0\u5EFA") : null, !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: () => {
6477
+ } }, "\u4EE5\u6B64\u4E3A\u6A21\u677F\u65B0\u5EFA") : null, !readonly ? (0, import_react5.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "outline", disabled: busy, onClick: () => setViewing(!viewing) }, viewing ? "\u7F16\u8F91\u5185\u5BB9" : "\u9884\u89C8") : null, !readonly ? (0, import_react5.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "primary", disabled: busy || !name.trim() || !body2.trim() || kind === "skill" && !description.trim(), onClick: () => {
6379
6478
  void save2();
6380
6479
  } }, busy ? "\u5904\u7406\u4E2D\u2026" : "\u4FDD\u5B58") : null) },
6381
- !readonly ? targets() : (0, import_react5.createElement)("p", { className: "te-badge" }, "\u5185\u7F6E\u6837\u672C \xB7 \u53EA\u8BFB"),
6480
+ !readonly ? targets() : (0, import_react5.createElement)("p", { className: "te-badge" }, editing.source === "codex-project" ? "Codex \u9879\u76EE\u6280\u80FD \xB7 \u6B63\u6587\u8BF7\u5728\u539F\u76EE\u5F55\u7F16\u8F91" : "\u5185\u7F6E\u6837\u672C \xB7 \u53EA\u8BFB"),
6382
6481
  templateSource ? (0, import_react5.createElement)("p", null, `\u4EE5\u300C${templateSource.name}\u300D\u4E3A\u6A21\u677F\u590D\u5236\u6B63\u6587\u3002\u65B0\u8D44\u6E90\u7684\u5B8C\u6210\u51ED\u8BC1\u3001\u89C4\u5219\u548C\u9636\u6BB5\u7ED1\u5B9A\u9700\u5355\u72EC\u914D\u7F6E\uFF0C\u4FDD\u5B58\u672C\u8EAB\u4E0D\u4F1A\u542F\u7528\u5B83\u3002`) : null,
6383
6482
  status(),
6384
- 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) })))
6483
+ viewing ? (0, import_react5.createElement)("div", { className: "te-markdown" }, (0, import_react5.createElement)(import_dsh_client_ui_primitives4.MarkdownText, { text: body2, labels })) : (0, import_react5.createElement)("div", { className: "te-form" }, (0, import_react5.createElement)("label", null, "\u540D\u79F0", (0, import_react5.createElement)("input", { className: "te-input", value: name, disabled: editing !== "new" || busy, onChange: (e) => setName(e.target.value), placeholder: "\u5C0F\u5199\u5B57\u6BCD\u3001\u6570\u5B57\u548C\u8FDE\u5B57\u7B26" })), kind === "skill" ? (0, import_react5.createElement)("label", null, "\u63CF\u8FF0", (0, import_react5.createElement)("input", { className: "te-input", value: description, disabled: busy, onChange: (e) => setDescription(e.target.value) })) : null, kind === "skill" ? (0, import_react5.createElement)("label", null, "\u4F7F\u7528\u65F6\u673A\uFF08\u53EF\u9009\uFF09", (0, import_react5.createElement)("input", { className: "te-input", value: whenToUse, disabled: busy, onChange: (e) => setWhenToUse(e.target.value) })) : null, (0, import_react5.createElement)("label", null, "Markdown \u6B63\u6587", (0, import_react5.createElement)("textarea", { className: "te-input te-editor", value: body2, disabled: busy, onChange: (e) => setBody(e.target.value) })))
6385
6484
  ) : null,
6386
- 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: () => {
6485
+ deleting ? (0, import_react5.createElement)(ResourceModal, { title: `\u5220\u9664${noun}\u300C${deleting.name}\u300D\uFF1F`, description: levelOf(deleting) === "user" ? "\u8FD9\u662F\u4E2A\u4EBA\u5168\u5C40\u8D44\u6E90\uFF0C\u5220\u9664\u4F1A\u5F71\u54CD\u6B64\u4E3B\u673A\u4E0A\u7684\u6240\u6709\u9879\u76EE\u3002" : "\u5220\u9664\u5C06\u5F71\u54CD\u5F53\u524D\u9879\u76EE\u3002", onClose: close, footer: (0, import_react5.createElement)("div", { className: "te-actions" }, (0, import_react5.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "outline", disabled: busy, onClick: close }, "\u4FDD\u7559"), (0, import_react5.createElement)("button", { className: "te-danger-button", disabled: busy, onClick: () => {
6387
6486
  void remove();
6388
6487
  } }, 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
6389
6488
  );
@@ -6426,24 +6525,32 @@ function SkillManager({ workspace, remote }) {
6426
6525
  if (!config || !selected) throw new Error("\u914D\u7F6E\u5C1A\u672A\u52A0\u8F7D\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002");
6427
6526
  const key = formatResourceRef(selected);
6428
6527
  const next = { ...config, skill_profiles: { ...config.skill_profiles, [key]: profile } };
6429
- const result = await remote.write({ path: workspace, ...next });
6430
- 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");
6528
+ if (selected.source === "user") {
6529
+ const result = await remote.writeUserSkillProfile({ name: selected.name, profile });
6530
+ if (!result.ok || !result.value.ok) throw new Error(result.ok ? result.value.error : "\u4FDD\u5B58\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u3002");
6531
+ } else {
6532
+ const result = await remote.write({ path: workspace, ...next });
6533
+ 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");
6534
+ }
6431
6535
  setConfig(next);
6432
6536
  setMessage(`\u5DF2\u4FDD\u5B58 ${selected.name} \u7684\u89C4\u5219\u914D\u7F6E\u3002`);
6433
6537
  setSelected(null);
6434
6538
  };
6435
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { children: [
6436
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ResourceManager, { workspace, remote, kind: "skill", onConfigureSkill: config ? (ref) => {
6437
- setMessage("");
6438
- setSelected(ref);
6439
- } : void 0 }),
6440
- selected === null && message ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { role: "status", className: "te-success", children: message }) : null,
6539
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: `te-config-layout${selected ? " is-open" : ""}`, children: [
6540
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "te-config-main", children: [
6541
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ResourceManager, { workspace, remote, kind: "skill", onConfigureSkill: config ? (ref) => {
6542
+ setMessage("");
6543
+ setSelected(ref);
6544
+ } : void 0 }),
6545
+ selected === null && message ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { role: "status", className: "te-success", children: message }) : null
6546
+ ] }),
6441
6547
  selected !== null ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
6442
6548
  SkillRuleDialog,
6443
6549
  {
6444
6550
  skill: selected,
6445
6551
  profile: config?.skill_profiles?.[formatResourceRef(selected)],
6446
- rules,
6552
+ rules: selected.source === "user" ? rules.filter((rule) => rule.ref.source !== "project") : rules,
6553
+ description: selected.source === "user" ? "\u7528\u6237\u7EA7\u6280\u80FD\u7684\u89C4\u5219\u914D\u7F6E\u4FDD\u5B58\u5728\u7528\u6237\u76EE\u5F55\uFF0C\u6240\u6709\u9879\u76EE\u4E0E\u4F1A\u8BDD\u5171\u7528\uFF1B\u53EA\u80FD\u9009\u62E9\u7528\u6237\u7EA7\u6216\u5185\u7F6E\u89C4\u5219\u3002" : "\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",
6447
6554
  onSave: saveProfile,
6448
6555
  onClose: () => setSelected(null)
6449
6556
  },
@@ -6460,7 +6567,7 @@ function RuleManager(props) {
6460
6567
 
6461
6568
  // src/client/TaskLedger.tsx
6462
6569
  var import_react8 = require("react");
6463
- var import_dsh_client_ui_primitives6 = require("@deepseek-ai/dsh-client-ui-primitives");
6570
+ var import_dsh_client_ui_primitives5 = require("@deepseek-ai/dsh-client-ui-primitives");
6464
6571
  var card2 = {
6465
6572
  display: "flex",
6466
6573
  flexDirection: "column",
@@ -6498,10 +6605,10 @@ var badge = {
6498
6605
  color: "var(--dsw-alias-label-secondary)"
6499
6606
  };
6500
6607
  function verdictDot(outcome) {
6501
- return (0, import_react8.createElement)(import_dsh_client_ui_primitives6.StateDot, { state: outcome === "pass" ? "done" : "error" });
6608
+ return (0, import_react8.createElement)(import_dsh_client_ui_primitives5.StateDot, { state: outcome === "pass" ? "done" : "error" });
6502
6609
  }
6503
6610
  function itemStatusDot(status) {
6504
- return (0, import_react8.createElement)(import_dsh_client_ui_primitives6.StateDot, { state: status === "done" ? "done" : "ongoing" });
6611
+ return (0, import_react8.createElement)(import_dsh_client_ui_primitives5.StateDot, { state: status === "done" ? "done" : "ongoing" });
6505
6612
  }
6506
6613
  function timeText(at) {
6507
6614
  return at.slice(0, 19).replace("T", " ");
@@ -6582,7 +6689,7 @@ function TaskLedger({ workspace, remote }) {
6582
6689
  { style: headerRow },
6583
6690
  (0, import_react8.createElement)("span", { style: styles.bindingLabel }, "\u4EFB\u52A1\u53F0\u8D26"),
6584
6691
  (0, import_react8.createElement)("span", { style: styles.sourceBadge }, "\u53EA\u8BFB \xB7 \u6765\u81EA .dsh/task-*.json"),
6585
- (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")
6692
+ (0, import_react8.createElement)(import_dsh_client_ui_primitives5.Button, { variant: "outline", size: "sm", disabled: loading, onClick: refresh }, loading ? "\u8BFB\u53D6\u4E2D\u2026" : "\u5237\u65B0")
6586
6693
  ),
6587
6694
  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)(
6588
6695
  "div",
@@ -6701,7 +6808,7 @@ function Workbench({ useStore, actions, useWorkspaces, remote }) {
6701
6808
  (0, import_react9.createElement)(
6702
6809
  "div",
6703
6810
  { style: headerBrand },
6704
- (0, import_react9.createElement)(import_dsh_client_ui_primitives7.IconSettingsOutline16, { size: 18 }),
6811
+ (0, import_react9.createElement)(IconSettings, { size: 18 }),
6705
6812
  (0, import_react9.createElement)(
6706
6813
  "div",
6707
6814
  { style: headerText },
@@ -6725,13 +6832,13 @@ function Workbench({ useStore, actions, useWorkspaces, remote }) {
6725
6832
  event.currentTarget.style.background = "transparent";
6726
6833
  }
6727
6834
  },
6728
- (0, import_react9.createElement)(import_dsh_client_ui_primitives7.IconCloseOutline16, { size: 16 })
6835
+ (0, import_react9.createElement)(IconClose, { size: 16 })
6729
6836
  )
6730
6837
  ),
6731
6838
  (0, import_react9.createElement)(
6732
6839
  "div",
6733
6840
  { style: tabbar },
6734
- ...TABS.map((t) => (0, import_react9.createElement)(import_dsh_client_ui_primitives7.Pill, { key: t.id, active: tab === t.id, onClick: () => {
6841
+ ...TABS.map((t) => (0, import_react9.createElement)(import_dsh_client_ui_primitives6.Pill, { key: t.id, active: tab === t.id, onClick: () => {
6735
6842
  setTab(t.id);
6736
6843
  } }, t.label)),
6737
6844
  workspaces.length > 0 ? (0, import_react9.createElement)("select", {
@@ -6758,7 +6865,6 @@ function Workbench({ useStore, actions, useWorkspaces, remote }) {
6758
6865
 
6759
6866
  // src/client/TriggerButton.tsx
6760
6867
  var import_react10 = require("react");
6761
- var import_dsh_client_ui_primitives8 = require("@deepseek-ai/dsh-client-ui-primitives");
6762
6868
  var hover = "var(--dsw-alias-bg-layer-2)";
6763
6869
  var label = "var(--dsw-alias-label-primary)";
6764
6870
  function TriggerButton({ wide, actions }) {
@@ -6802,7 +6908,7 @@ function TriggerButton({ wide, actions }) {
6802
6908
  transition: "background 120ms ease"
6803
6909
  }
6804
6910
  },
6805
- (0, import_react10.createElement)(import_dsh_client_ui_primitives8.IconSettingsOutline16, { size: wide ? 16 : 18 }),
6911
+ (0, import_react10.createElement)(IconSettings, { size: wide ? 16 : 18 }),
6806
6912
  wide ? (0, import_react10.createElement)("span", { style: { fontSize: 14, lineHeight: "22px" } }, "\u5DE5\u7A0B\u6D41\u7A0B") : null
6807
6913
  );
6808
6914
  }