@godv61/dsh-task-engine 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/client.js CHANGED
@@ -1019,10 +1019,10 @@ function isValidJWT(jwt, alg) {
1019
1019
  if (!jwtRegex.test(jwt))
1020
1020
  return false;
1021
1021
  try {
1022
- const [header] = jwt.split(".");
1023
- if (!header)
1022
+ const [header2] = jwt.split(".");
1023
+ if (!header2)
1024
1024
  return false;
1025
- const base64 = header.replace(/-/g, "+").replace(/_/g, "/").padEnd(header.length + (4 - header.length % 4) % 4, "=");
1025
+ const base64 = header2.replace(/-/g, "+").replace(/_/g, "/").padEnd(header2.length + (4 - header2.length % 4) % 4, "=");
1026
1026
  const decoded = JSON.parse(atob(base64));
1027
1027
  if (typeof decoded !== "object" || decoded === null)
1028
1028
  return false;
@@ -4144,6 +4144,30 @@ var writeResourceResultSchema = external_exports.object({
4144
4144
  path: external_exports.string(),
4145
4145
  error: external_exports.string().optional()
4146
4146
  });
4147
+ var readSkillRequestSchema = external_exports.object({
4148
+ name: external_exports.string(),
4149
+ level: external_exports.enum(["project", "user"]),
4150
+ path: external_exports.string().optional()
4151
+ });
4152
+ var readSkillResultSchema = external_exports.object({
4153
+ ok: external_exports.boolean(),
4154
+ name: external_exports.string(),
4155
+ description: external_exports.string(),
4156
+ whenToUse: external_exports.string(),
4157
+ content: external_exports.string(),
4158
+ error: external_exports.string().optional()
4159
+ });
4160
+ var readRuleRequestSchema = external_exports.object({
4161
+ name: external_exports.string(),
4162
+ level: external_exports.enum(["project", "user"]),
4163
+ path: external_exports.string().optional()
4164
+ });
4165
+ var readRuleResultSchema = external_exports.object({
4166
+ ok: external_exports.boolean(),
4167
+ name: external_exports.string(),
4168
+ content: external_exports.string(),
4169
+ error: external_exports.string().optional()
4170
+ });
4147
4171
  var PACKAGE = "@godv61/dsh-task-engine";
4148
4172
  var TYPERT_REMOTE = {
4149
4173
  package: PACKAGE,
@@ -4243,11 +4267,123 @@ var TYPERT_REMOTE = {
4243
4267
  }
4244
4268
  ],
4245
4269
  result: { mode: "strict", typeSymbol: `${PACKAGE}/types#WriteResourceResult`, schema: writeResourceResultSchema }
4270
+ },
4271
+ {
4272
+ id: `${PACKAGE}#task-engine/readSkill`,
4273
+ service: "taskEngineController",
4274
+ namespace: "task-engine",
4275
+ method: "readSkill",
4276
+ invocation: { kind: "direct" },
4277
+ parameters: [
4278
+ {
4279
+ name: "request",
4280
+ wire: "request",
4281
+ source: "json",
4282
+ codec: { mode: "strict", typeSymbol: `${PACKAGE}/types#ReadSkillRequest`, schema: readSkillRequestSchema }
4283
+ }
4284
+ ],
4285
+ result: { mode: "strict", typeSymbol: `${PACKAGE}/types#ReadSkillResult`, schema: readSkillResultSchema }
4286
+ },
4287
+ {
4288
+ id: `${PACKAGE}#task-engine/readRule`,
4289
+ service: "taskEngineController",
4290
+ namespace: "task-engine",
4291
+ method: "readRule",
4292
+ invocation: { kind: "direct" },
4293
+ parameters: [
4294
+ {
4295
+ name: "request",
4296
+ wire: "request",
4297
+ source: "json",
4298
+ codec: { mode: "strict", typeSymbol: `${PACKAGE}/types#ReadRuleRequest`, schema: readRuleRequestSchema }
4299
+ }
4300
+ ],
4301
+ result: { mode: "strict", typeSymbol: `${PACKAGE}/types#ReadRuleResult`, schema: readRuleResultSchema }
4246
4302
  }
4247
4303
  ]
4248
4304
  };
4249
4305
  var remote_default = TYPERT_REMOTE;
4250
4306
 
4307
+ // src/client/Workbench.tsx
4308
+ var import_react5 = require("react");
4309
+ var import_dsh_client_ui_primitives4 = require("@deepseek-ai/dsh-client-ui-primitives");
4310
+
4311
+ // src/client/styles.ts
4312
+ var text = "var(--dsw-alias-label-primary)";
4313
+ var textSecondary = "var(--dsw-alias-label-secondary)";
4314
+ var textTertiary = "var(--dsw-alias-label-tertiary)";
4315
+ var border = "var(--dsw-alias-border-l2)";
4316
+ var surface = "var(--dsw-alias-bg-layer-2)";
4317
+ var danger = "var(--dsw-alias-state-error-primary)";
4318
+ var success = "var(--dsw-alias-state-success-primary)";
4319
+ var warn = "var(--dsw-alias-state-warn-primary)";
4320
+ var styles = {
4321
+ wrap: { display: "flex", flexDirection: "column", gap: 16, padding: 20, maxWidth: 900 },
4322
+ head: { display: "flex", flexDirection: "column", gap: 4 },
4323
+ title: { margin: 0, color: text },
4324
+ muted: { margin: 0, color: textSecondary, fontSize: 13, lineHeight: 1.5 },
4325
+ sourceRow: { display: "flex", alignItems: "center", gap: 8 },
4326
+ sourceText: { color: textTertiary, fontSize: 13 },
4327
+ workspaceRow: { display: "flex", alignItems: "center", gap: 8 },
4328
+ workspaceLabel: { color: textSecondary, fontSize: 13 },
4329
+ flowCard: { border: `1px solid ${border}`, borderRadius: 10, background: surface, padding: 12, overflowX: "auto" },
4330
+ section: { display: "flex", flexDirection: "column", gap: 12 },
4331
+ cardBody: { padding: "4px 0 8px", display: "flex", flexDirection: "column", gap: 12 },
4332
+ row: { display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap" },
4333
+ field: { display: "flex", flexDirection: "column", gap: 4, flex: "1 1 220px", minWidth: 180 },
4334
+ fieldLabel: { color: textSecondary, fontSize: 13 },
4335
+ hint: { color: textTertiary, fontSize: 12, margin: 0, lineHeight: 1.4 },
4336
+ chips: { display: "flex", flexWrap: "wrap", gap: 6, alignItems: "center" },
4337
+ cardRow: {
4338
+ display: "flex",
4339
+ alignItems: "center",
4340
+ gap: 8,
4341
+ flexWrap: "wrap",
4342
+ border: `1px solid ${border}`,
4343
+ borderRadius: 8,
4344
+ padding: "8px 10px"
4345
+ },
4346
+ inline: { display: "inline-flex", alignItems: "center", gap: 6, marginRight: 8 },
4347
+ textarea: {
4348
+ background: "var(--dsw-alias-bg-layer-1)",
4349
+ border: `1px solid ${border}`,
4350
+ borderRadius: 8,
4351
+ padding: "8px 10px",
4352
+ color: text,
4353
+ fontSize: 13,
4354
+ minHeight: 90,
4355
+ resize: "vertical",
4356
+ fontFamily: "inherit",
4357
+ width: "100%",
4358
+ boxSizing: "border-box"
4359
+ },
4360
+ sourceBadge: { color: textTertiary, fontSize: 11 },
4361
+ bindingStage: { display: "flex", flexDirection: "column", gap: 6 },
4362
+ bindingLabel: { color: text, fontSize: 13, fontWeight: 600 },
4363
+ problems: {
4364
+ display: "flex",
4365
+ flexDirection: "column",
4366
+ gap: 8,
4367
+ border: `1px solid ${danger}`,
4368
+ borderRadius: 8,
4369
+ padding: "10px 12px"
4370
+ },
4371
+ problemsTitle: { color: danger, fontSize: 13, fontWeight: 600, display: "flex", alignItems: "center", gap: 8 },
4372
+ problemsList: { margin: 0, paddingLeft: 20, color: text, fontSize: 13, display: "flex", flexDirection: "column", gap: 4 },
4373
+ noticeBox: {
4374
+ border: `1px solid ${warn}`,
4375
+ borderRadius: 8,
4376
+ padding: "10px 12px",
4377
+ display: "flex",
4378
+ flexDirection: "column",
4379
+ gap: 8
4380
+ },
4381
+ noticeTitle: { color: warn, fontSize: 13, fontWeight: 600, display: "flex", alignItems: "center", gap: 8 },
4382
+ okText: { color: success, fontSize: 13, display: "flex", alignItems: "center", gap: 6 },
4383
+ status: { color: textTertiary, fontSize: 13, display: "flex", alignItems: "center", gap: 6 },
4384
+ actions: { display: "flex", alignItems: "center", gap: 12, marginTop: 4 }
4385
+ };
4386
+
4251
4387
  // src/client/TaskEngineSection.tsx
4252
4388
  var import_react2 = require("react");
4253
4389
  var import_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
@@ -4350,12 +4486,12 @@ var stepX = nodeW + 56;
4350
4486
  var margin = 40;
4351
4487
  var nodeTop = 92;
4352
4488
  var nodeCenterY = nodeTop + nodeH / 2;
4353
- var textTertiary = "var(--dsw-alias-label-tertiary)";
4354
- var textSecondary = "var(--dsw-alias-label-secondary)";
4355
- var border = "var(--dsw-alias-border-l2)";
4356
- var surface = "var(--dsw-alias-bg-layer-2)";
4489
+ var textTertiary2 = "var(--dsw-alias-label-tertiary)";
4490
+ var textSecondary2 = "var(--dsw-alias-label-secondary)";
4491
+ var border2 = "var(--dsw-alias-border-l2)";
4492
+ var surface2 = "var(--dsw-alias-bg-layer-2)";
4357
4493
  var brand = "var(--dsw-alias-state-business-primary)";
4358
- var danger = "var(--dsw-alias-state-error-primary)";
4494
+ var danger2 = "var(--dsw-alias-state-error-primary)";
4359
4495
  function edgeList(config) {
4360
4496
  return config.transitions.map((t) => {
4361
4497
  const label = (t.requires ?? []).length > 0 ? (t.requires ?? []).join(" \xB7 ") : null;
@@ -4465,7 +4601,7 @@ function FlowDiagram({ config, onAddTransition, onRemoveTransition }) {
4465
4601
  ...edges.map((edge, i) => {
4466
4602
  const from = indexOf(edge.from);
4467
4603
  const to = indexOf(edge.to);
4468
- const stroke = edge.orphaned ? danger : textTertiary;
4604
+ const stroke = edge.orphaned ? danger2 : textTertiary2;
4469
4605
  const d = from < to ? forwardPath(from, to) : returnPath(from, to < 0 ? from : to);
4470
4606
  const labelY = from < to ? forwardLabelY(from, to) : returnLabelY(from, to < 0 ? from : to);
4471
4607
  const labelX = from < to ? (nodeX(from, stageCount) + nodeW + nodeX(to, stageCount)) / 2 : (nodeX(from, stageCount) + nodeX(to < 0 ? from : to, stageCount) + nodeW) / 2;
@@ -4487,7 +4623,7 @@ function FlowDiagram({ config, onAddTransition, onRemoveTransition }) {
4487
4623
  y: labelY,
4488
4624
  textAnchor: "middle",
4489
4625
  fontSize: 11,
4490
- fill: edge.orphaned ? danger : textSecondary
4626
+ fill: edge.orphaned ? danger2 : textSecondary2
4491
4627
  }, edge.label);
4492
4628
  return (0, import_react.createElement)(
4493
4629
  "g",
@@ -4529,8 +4665,8 @@ function FlowDiagram({ config, onAddTransition, onRemoveTransition }) {
4529
4665
  height: nodeH,
4530
4666
  rx: 20,
4531
4667
  ry: 20,
4532
- fill: surface,
4533
- stroke: isStart ? brand : border,
4668
+ fill: surface2,
4669
+ stroke: isStart ? brand : border2,
4534
4670
  strokeWidth: isStart ? 2 : 1.5
4535
4671
  }),
4536
4672
  (0, import_react.createElement)("text", {
@@ -4633,81 +4769,30 @@ var WORKFLOW_TEMPLATES = [
4633
4769
  { id: "minimal", label: "\u7EAF\u4EE3\u7801", description: "\u5F00\u53D1 \u2192 \u4EA4\u4ED8\uFF0C\u4E24\u9636\u6BB5\uFF0C\u53EA\u7559\u63D0\u4EA4\u95E8\u7981", config: MINIMAL }
4634
4770
  ];
4635
4771
 
4636
- // src/client/styles.ts
4637
- var text = "var(--dsw-alias-label-primary)";
4638
- var textSecondary2 = "var(--dsw-alias-label-secondary)";
4639
- var textTertiary2 = "var(--dsw-alias-label-tertiary)";
4640
- var border2 = "var(--dsw-alias-border-l2)";
4641
- var surface2 = "var(--dsw-alias-bg-layer-2)";
4642
- var danger2 = "var(--dsw-alias-state-error-primary)";
4643
- var success = "var(--dsw-alias-state-success-primary)";
4644
- var warn = "var(--dsw-alias-state-warn-primary)";
4645
- var styles = {
4646
- wrap: { display: "flex", flexDirection: "column", gap: 16, padding: 20, maxWidth: 900 },
4647
- head: { display: "flex", flexDirection: "column", gap: 4 },
4648
- title: { margin: 0, color: text },
4649
- muted: { margin: 0, color: textSecondary2, fontSize: 13, lineHeight: 1.5 },
4650
- sourceRow: { display: "flex", alignItems: "center", gap: 8 },
4651
- sourceText: { color: textTertiary2, fontSize: 13 },
4652
- workspaceRow: { display: "flex", alignItems: "center", gap: 8 },
4653
- workspaceLabel: { color: textSecondary2, fontSize: 13 },
4654
- flowCard: { border: `1px solid ${border2}`, borderRadius: 10, background: surface2, padding: 12, overflowX: "auto" },
4655
- section: { display: "flex", flexDirection: "column", gap: 12 },
4656
- cardBody: { padding: "4px 0 8px", display: "flex", flexDirection: "column", gap: 12 },
4657
- row: { display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap" },
4658
- field: { display: "flex", flexDirection: "column", gap: 4, flex: "1 1 220px", minWidth: 180 },
4659
- fieldLabel: { color: textSecondary2, fontSize: 13 },
4660
- hint: { color: textTertiary2, fontSize: 12, margin: 0, lineHeight: 1.4 },
4661
- chips: { display: "flex", flexWrap: "wrap", gap: 6, alignItems: "center" },
4662
- cardRow: {
4663
- display: "flex",
4664
- alignItems: "center",
4665
- gap: 8,
4666
- flexWrap: "wrap",
4667
- border: `1px solid ${border2}`,
4668
- borderRadius: 8,
4669
- padding: "8px 10px"
4670
- },
4671
- inline: { display: "inline-flex", alignItems: "center", gap: 6, marginRight: 8 },
4672
- textarea: {
4673
- background: "var(--dsw-alias-bg-layer-1)",
4674
- border: `1px solid ${border2}`,
4675
- borderRadius: 8,
4676
- padding: "8px 10px",
4677
- color: text,
4678
- fontSize: 13,
4679
- minHeight: 90,
4680
- resize: "vertical",
4681
- fontFamily: "inherit",
4682
- width: "100%",
4683
- boxSizing: "border-box"
4684
- },
4685
- sourceBadge: { color: textTertiary2, fontSize: 11 },
4686
- bindingStage: { display: "flex", flexDirection: "column", gap: 6 },
4687
- bindingLabel: { color: text, fontSize: 13, fontWeight: 600 },
4688
- problems: {
4689
- display: "flex",
4690
- flexDirection: "column",
4691
- gap: 8,
4692
- border: `1px solid ${danger2}`,
4693
- borderRadius: 8,
4694
- padding: "10px 12px"
4695
- },
4696
- problemsTitle: { color: danger2, fontSize: 13, fontWeight: 600, display: "flex", alignItems: "center", gap: 8 },
4697
- problemsList: { margin: 0, paddingLeft: 20, color: text, fontSize: 13, display: "flex", flexDirection: "column", gap: 4 },
4698
- noticeBox: {
4699
- border: `1px solid ${warn}`,
4700
- borderRadius: 8,
4701
- padding: "10px 12px",
4702
- display: "flex",
4703
- flexDirection: "column",
4704
- gap: 8
4705
- },
4706
- noticeTitle: { color: warn, fontSize: 13, fontWeight: 600, display: "flex", alignItems: "center", gap: 8 },
4707
- okText: { color: success, fontSize: 13, display: "flex", alignItems: "center", gap: 6 },
4708
- status: { color: textTertiary2, fontSize: 13, display: "flex", alignItems: "center", gap: 6 },
4709
- actions: { display: "flex", alignItems: "center", gap: 12, marginTop: 4 }
4710
- };
4772
+ // src/client/shared.ts
4773
+ function sourceLabel(source) {
4774
+ switch (source) {
4775
+ case "bundled":
4776
+ return "\u5185\u7F6E";
4777
+ case "project":
4778
+ case "project-dsh":
4779
+ case "project-agents":
4780
+ return "\u9879\u76EE";
4781
+ case "user":
4782
+ case "user-dsh":
4783
+ case "user-agents":
4784
+ return "\u7528\u6237";
4785
+ case "custom":
4786
+ return "\u81EA\u5B9A\u4E49";
4787
+ default:
4788
+ return source;
4789
+ }
4790
+ }
4791
+ function describeError(error) {
4792
+ if (error instanceof Error) return error.message;
4793
+ if (typeof error === "string") return error;
4794
+ return "\u672A\u77E5\u9519\u8BEF";
4795
+ }
4711
4796
 
4712
4797
  // src/client/TaskEngineSection.tsx
4713
4798
  var import_jsx_runtime = require("react/jsx-runtime");
@@ -4715,7 +4800,7 @@ var text2 = "var(--dsw-alias-label-primary)";
4715
4800
  var textTertiary3 = "var(--dsw-alias-label-tertiary)";
4716
4801
  var control = {
4717
4802
  background: "var(--dsw-alias-bg-layer-1)",
4718
- border: `1px solid ${border2}`,
4803
+ border: `1px solid ${border}`,
4719
4804
  borderRadius: 8,
4720
4805
  padding: "5px 8px",
4721
4806
  color: text2,
@@ -4726,7 +4811,7 @@ var cardV = {
4726
4811
  display: "flex",
4727
4812
  flexDirection: "column",
4728
4813
  gap: 8,
4729
- border: `1px solid ${border2}`,
4814
+ border: `1px solid ${border}`,
4730
4815
  borderRadius: 8,
4731
4816
  padding: "10px 12px"
4732
4817
  };
@@ -4744,9 +4829,7 @@ var POLICY_OPTIONS = [
4744
4829
  { value: "manual", label: "manual", hint: "\u4EBA\u5DE5\u6307\u793A" }
4745
4830
  ];
4746
4831
  function TaskEngineSection(props) {
4747
- const { remote, useWorkspaces } = props;
4748
- const workspaces = useWorkspaces((state) => state.items);
4749
- const [workspace, setWorkspace] = (0, import_react2.useState)("");
4832
+ const { remote, workspace } = props;
4750
4833
  const [config, setConfig] = (0, import_react2.useState)(null);
4751
4834
  const [source, setSource] = (0, import_react2.useState)("default");
4752
4835
  const [savedAt, setSavedAt] = (0, import_react2.useState)("");
@@ -4754,11 +4837,6 @@ function TaskEngineSection(props) {
4754
4837
  const [loadedProblems, setLoadedProblems] = (0, import_react2.useState)([]);
4755
4838
  const [skills, setSkills] = (0, import_react2.useState)([]);
4756
4839
  const [rules, setRules] = (0, import_react2.useState)([]);
4757
- (0, import_react2.useEffect)(() => {
4758
- if (workspaces.length > 0 && workspace === "") {
4759
- setWorkspace(workspaces[0].path);
4760
- }
4761
- }, [workspaces, workspace]);
4762
4840
  (0, import_react2.useEffect)(() => {
4763
4841
  if (workspace === "") return;
4764
4842
  let alive = true;
@@ -4807,12 +4885,6 @@ function TaskEngineSection(props) {
4807
4885
  if (config === null) return;
4808
4886
  update(config, setConfig, (c) => ({ ...c, transitions: c.transitions.filter((_, j) => j !== index) }));
4809
4887
  };
4810
- if (workspaces.length === 0) {
4811
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.wrap, children: [
4812
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { style: styles.title, children: "\u5DE5\u7A0B\u6D41\u7A0B\u914D\u7F6E" }),
4813
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.muted, children: "\u5F53\u524D\u6CA1\u6709\u4EFB\u4F55\u5DE5\u4F5C\u533A\uFF1A\u8BF7\u5148\u5728\u4FA7\u680F\u521B\u5EFA\u4E00\u4E2A\u5DE5\u4F5C\u533A\u3002" })
4814
- ] });
4815
- }
4816
4888
  if (loadError !== "") {
4817
4889
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.wrap, children: [
4818
4890
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { style: styles.title, children: "\u5DE5\u7A0B\u6D41\u7A0B\u914D\u7F6E" }),
@@ -4840,28 +4912,13 @@ function TaskEngineSection(props) {
4840
4912
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.StateDot, { state: source === "project" ? "done" : source === "invalid" ? "warning" : "ongoing" }),
4841
4913
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.sourceText, children: sourceText(source) })
4842
4914
  ] }),
4843
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.workspaceRow, children: [
4844
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.workspaceLabel, children: "\u5DE5\u4F5C\u533A" }),
4845
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
4846
- "select",
4847
- {
4848
- style: control,
4849
- value: workspace,
4850
- onChange: (ev) => {
4851
- setWorkspace(ev.target.value);
4852
- },
4853
- children: workspaces.map((w) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: w.path, children: w.title || w.path }, w.path))
4854
- }
4855
- )
4856
- ] }),
4857
4915
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TemplatePicker, { config, setConfig }),
4858
4916
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.flowCard, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FlowDiagram, { config, onAddTransition: addTransition, onRemoveTransition: removeTransition }) }),
4859
4917
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SectionCard, { icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconSettingsOutline16, { size: 16 }), title: "\u9636\u6BB5", hint: "\u6D41\u7A0B\u7531\u8FD9\u4E9B\u9636\u6BB5\u6309\u987A\u5E8F\u7EC4\u6210\u3002\u70B9\u4E00\u4E2A\u6807\u7B7E\u53EF\u5220\u9664\u5B83\uFF08\u8D77\u59CB\u9636\u6BB5\u9664\u5916\uFF09\uFF1B\u7528\u4E2D\u6587\u540D\u66F4\u6613\u61C2\uFF0C\u4F8B\u5982\u300C\u9700\u6C42\u8BC4\u5BA1\u300D\u300C\u5F00\u53D1\u300D\u3002", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StageEditor, { config, setConfig }) }),
4860
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SectionCard, { icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconBranchOutline16, { size: 16 }), title: "\u6D41\u8F6C\uFF08\u9636\u6BB5 \u2192 \u9636\u6BB5\uFF0C\u53EF\u5E26\u5B88\u536B\uFF09", hint: "\u6BCF\u6761\u6D41\u8F6C = \u4ECE\u300C\u4E0A\u4E00\u6B65\u300D\u5230\u300C\u4E0B\u4E00\u6B65\u300D\u5141\u8BB8\u8D70\u7684\u8DEF\uFF1B\u53EF\u9644\u52A0\u5B88\u536B\uFF0C\u6EE1\u8DB3\u5B88\u536B\u624D\u653E\u884C\u3002\u4E5F\u53EF\u5728\u6D41\u7A0B\u56FE\u91CC\u76F4\u63A5\u8FDE\u7EBF/\u70B9\u7BAD\u5934\u5220\u9664\u3002", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TransitionEditor, { config, setConfig }) }),
4861
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SectionCard, { icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconCheckOutline16, { size: 16 }), title: "\u4EA7\u7269\uFF08\u6BCF\u4E2A\u9636\u6BB5\u8981\u586B\u7684\u5B57\u6BB5\uFF09", hint: "\u7ED9\u67D0\u9636\u6BB5\u58F0\u660E\u8981\u4EA4\u7684\u4EA7\u7269\u548C\u5FC5\u586B\u5B57\u6BB5\uFF1B\u914D\u5408\u6D41\u8F6C\u91CC\u7684\u300C\u4EA7\u7269\u9F50\u5168\u300D\u5B88\u536B\uFF0C\u5B57\u6BB5\u6CA1\u586B\u5168\u5C31\u8FC7\u4E0D\u53BB\u3002", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ArtifactEditor, { config, setConfig }) }),
4862
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SectionCard, { icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconEditOutline16, { size: 16 }), title: "\u63D0\u4EA4\u89C4\u5219", hint: "\u63D0\u4EA4\u7B56\u7565\u3001\u6D88\u606F\u683C\u5F0F\u3001\u63D0\u4EA4\u68C0\u67E5\u70B9\u3001\u6587\u4EF6\u8303\u56F4\uFF0C\u4EE5\u53CA\u9AD8\u98CE\u9669\u662F\u5426\u5FC5\u987B\u9644\u9A8C\u8BC1\u8BC1\u636E\u3002", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CommitEditor, { config, setConfig }) }),
4863
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SectionCard, { icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconBranchOutline16, { size: 16 }), title: "\u8282\u70B9\u6302\u8F7D\uFF08skill / rule\uFF09", hint: "\u7ED9\u6BCF\u4E2A\u9636\u6BB5\u6302\u300C\u8FD9\u4E2A\u9636\u6BB5\u7528\u4EC0\u4E48 skill\u300D\u548C\u300C\u5B88\u54EA\u6761 rule\u300D\u3002\u5927\u6A21\u578B\u8D70\u5230\u8BE5\u9636\u6BB5\u65F6\uFF0Cdev_task \u53EA\u62AB\u9732\u8FD9\u9636\u6BB5\u6302\u8F7D\u7684\u5185\u5BB9\u3002", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BindingEditor, { config, setConfig, skills, rules }) }),
4864
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SectionCard, { icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconPlusOutline16, { size: 16 }), title: "\u65B0\u5EFA skill / rule", hint: "\u6E05\u5355\u91CC\u6CA1\u6709\u5408\u9002\u7684\u5C31\u5F53\u573A\u65B0\u5EFA\uFF0C\u5199\u5230\u9879\u76EE .dsh/ \u6216\u7528\u6237 $DSH_HOME\uFF1B\u5199\u597D\u540E\u81EA\u52A8\u51FA\u73B0\u5728\u4E0A\u9762\u7684\u6302\u8F7D\u6E05\u5355\u3002", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ResourceCreator, { remote, workspace, onCreated: refreshCatalogs }) }),
4918
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SectionCard, { icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconBranchOutline16, { size: 16 }), title: "\u6D41\u8F6C\uFF08\u9636\u6BB5 \u2192 \u9636\u6BB5\uFF0C\u53EF\u5E26\u5B88\u536B\uFF09", defaultOpen: false, hint: "\u6BCF\u6761\u6D41\u8F6C = \u4ECE\u300C\u4E0A\u4E00\u6B65\u300D\u5230\u300C\u4E0B\u4E00\u6B65\u300D\u5141\u8BB8\u8D70\u7684\u8DEF\uFF1B\u53EF\u9644\u52A0\u5B88\u536B\uFF0C\u6EE1\u8DB3\u5B88\u536B\u624D\u653E\u884C\u3002\u4E5F\u53EF\u5728\u6D41\u7A0B\u56FE\u91CC\u76F4\u63A5\u8FDE\u7EBF/\u70B9\u7BAD\u5934\u5220\u9664\u3002", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TransitionEditor, { config, setConfig }) }),
4919
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SectionCard, { icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconCheckOutline16, { size: 16 }), title: "\u4EA7\u7269\uFF08\u6BCF\u4E2A\u9636\u6BB5\u8981\u586B\u7684\u5B57\u6BB5\uFF09", defaultOpen: false, hint: "\u7ED9\u67D0\u9636\u6BB5\u58F0\u660E\u8981\u4EA4\u7684\u4EA7\u7269\u548C\u5FC5\u586B\u5B57\u6BB5\uFF1B\u914D\u5408\u6D41\u8F6C\u91CC\u7684\u300C\u4EA7\u7269\u9F50\u5168\u300D\u5B88\u536B\uFF0C\u5B57\u6BB5\u6CA1\u586B\u5168\u5C31\u8FC7\u4E0D\u53BB\u3002", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ArtifactEditor, { config, setConfig }) }),
4920
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SectionCard, { icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconEditOutline16, { size: 16 }), title: "\u63D0\u4EA4\u89C4\u5219", defaultOpen: false, hint: "\u63D0\u4EA4\u7B56\u7565\u3001\u6D88\u606F\u683C\u5F0F\u3001\u63D0\u4EA4\u68C0\u67E5\u70B9\u3001\u6587\u4EF6\u8303\u56F4\uFF0C\u4EE5\u53CA\u9AD8\u98CE\u9669\u662F\u5426\u5FC5\u987B\u9644\u9A8C\u8BC1\u8BC1\u636E\u3002", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CommitEditor, { config, setConfig }) }),
4921
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SectionCard, { icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconBranchOutline16, { size: 16 }), title: "\u8282\u70B9\u6302\u8F7D\uFF08skill / rule\uFF09", hint: "\u7ED9\u6BCF\u4E2A\u9636\u6BB5\u6302\u300C\u8FD9\u4E2A\u9636\u6BB5\u7528\u4EC0\u4E48 skill\u300D\u548C\u300C\u5B88\u54EA\u6761 rule\u300D\u3002\u5927\u6A21\u578B\u8D70\u5230\u8BE5\u9636\u6BB5\u65F6\uFF0Cdev_task \u53EA\u62AB\u9732\u8FD9\u9636\u6BB5\u6302\u8F7D\u7684\u5185\u5BB9\uFF1B\u8981\u65B0\u5EFA\u6216\u6539\u6B63\u6587\uFF0C\u8BF7\u5207\u5230\u4E0A\u65B9\u7684\u300C\u6280\u80FD / \u89C4\u5219\u300D\u6807\u7B7E\u9875\u3002", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BindingEditor, { config, setConfig, skills, rules }) }),
4865
4922
  problems.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.problems, children: [
4866
4923
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: styles.problemsTitle, children: [
4867
4924
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.StateDot, { state: "error" }),
@@ -4912,8 +4969,8 @@ function sourceText(source) {
4912
4969
  return "\u5185\u7F6E\u9ED8\u8BA4\u914D\u7F6E\uFF08\u5DE5\u4F5C\u533A\u5C1A\u65E0 .dsh/eng.json\uFF09";
4913
4970
  }
4914
4971
  }
4915
- function SectionCard({ icon, title, hint, children }) {
4916
- const [open, setOpen] = (0, import_react2.useState)(true);
4972
+ function SectionCard({ icon, title, hint, defaultOpen = true, children }) {
4973
+ const [open, setOpen] = (0, import_react2.useState)(defaultOpen);
4917
4974
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.section, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
4918
4975
  import_dsh_client_ui_primitives.DisclosureRow,
4919
4976
  {
@@ -5192,196 +5249,574 @@ function CommitEditor({ config, setConfig }) {
5192
5249
  ] });
5193
5250
  }
5194
5251
  function BindingEditor({ config, setConfig, skills, rules }) {
5195
- const toggleSkill = (stage, skill) => {
5252
+ const [stage, setStage] = (0, import_react2.useState)(config.stages[0] ?? "");
5253
+ const currentStage = config.stages.includes(stage) ? stage : config.stages[0] ?? "";
5254
+ const toggleSkill = (skill) => {
5255
+ if (currentStage === "") return;
5196
5256
  update(config, setConfig, (c) => {
5197
5257
  const bindings = c.stage_bindings ?? {};
5198
- const current = bindings[stage]?.skills ?? [];
5258
+ const current = bindings[currentStage]?.skills ?? [];
5199
5259
  const next = current.includes(skill) ? current.filter((s) => s !== skill) : [...current, skill].sort();
5200
- return { ...c, stage_bindings: { ...bindings, [stage]: { ...bindings[stage] ?? {}, skills: next } } };
5260
+ return { ...c, stage_bindings: { ...bindings, [currentStage]: { ...bindings[currentStage] ?? {}, skills: next } } };
5201
5261
  });
5202
5262
  };
5203
- const toggleRule = (stage, rule) => {
5263
+ const toggleRule = (rule) => {
5264
+ if (currentStage === "") return;
5204
5265
  update(config, setConfig, (c) => {
5205
5266
  const bindings = c.stage_bindings ?? {};
5206
- const current = bindings[stage]?.rules ?? [];
5267
+ const current = bindings[currentStage]?.rules ?? [];
5207
5268
  const next = current.includes(rule) ? current.filter((s) => s !== rule) : [...current, rule].sort();
5208
- return { ...c, stage_bindings: { ...bindings, [stage]: { ...bindings[stage] ?? {}, rules: next } } };
5269
+ return { ...c, stage_bindings: { ...bindings, [currentStage]: { ...bindings[currentStage] ?? {}, rules: next } } };
5209
5270
  });
5210
5271
  };
5211
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.section, children: config.stages.map((stage) => {
5212
- const binding = config.stage_bindings?.[stage];
5213
- const boundSkills = binding?.skills ?? [];
5214
- const boundRules = binding?.rules ?? [];
5215
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: cardV, children: [
5216
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.bindingLabel, children: stage }),
5272
+ if (currentStage === "") {
5273
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.muted, children: "\u5148\u5728\u300C\u9636\u6BB5\u300D\u91CC\u52A0\u4E00\u4E2A\u9636\u6BB5\uFF0C\u518D\u56DE\u6765\u6302 skill / rule\u3002" });
5274
+ }
5275
+ const boundSkills = config.stage_bindings?.[currentStage]?.skills ?? [];
5276
+ const boundRules = config.stage_bindings?.[currentStage]?.rules ?? [];
5277
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.section, children: [
5278
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.field, children: [
5279
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.fieldLabel, children: "\u9009\u62E9\u9636\u6BB5\uFF08\u6539\u54EA\u4E2A\u9636\u6BB5\u7684\u6302\u8F7D\uFF09" }),
5280
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.chips, children: config.stages.map((s) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Pill, { active: s === currentStage, onClick: () => {
5281
+ setStage(s);
5282
+ }, children: s }, s)) })
5283
+ ] }),
5284
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: cardV, children: [
5217
5285
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.bindingStage, children: [
5218
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.fieldLabel, children: "skill\uFF08\u505A\u4EC0\u4E48\uFF09" }),
5219
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.chips, children: skills.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.sourceBadge, children: "\u6682\u65E0\u53EF\u7528 skill\uFF0C\u53EF\u5728\u4E0B\u65B9\u65B0\u5EFA" }) : skills.map((sk) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
5220
- import_dsh_client_ui_primitives.Pill,
5221
- {
5222
- active: boundSkills.includes(sk.name),
5223
- onClick: () => {
5224
- toggleSkill(stage, sk.name);
5225
- },
5226
- title: `${sk.description}\uFF08${sourceLabel(sk.source)}\uFF09`,
5227
- children: sk.name
5228
- },
5229
- sk.name
5230
- )) })
5286
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.fieldLabel, children: "skill\uFF08\u8FD9\u4E2A\u9636\u6BB5\u505A\u4EC0\u4E48\uFF09" }),
5287
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.chips, children: skills.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.sourceBadge, children: "\u6682\u65E0\u53EF\u7528 skill\uFF0C\u53EF\u5728\u300C\u65B0\u5EFA skill / rule\u300D\u91CC\u5EFA" }) : skills.map((sk) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_dsh_client_ui_primitives.Pill, { active: boundSkills.includes(sk.name), onClick: () => {
5288
+ toggleSkill(sk.name);
5289
+ }, title: `${sk.description}\uFF08${sourceLabel(sk.source)}\uFF09`, children: [
5290
+ sk.name,
5291
+ sk.source !== "bundled" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: styles.sourceBadge, children: [
5292
+ "\uFF08",
5293
+ sourceLabel(sk.source),
5294
+ "\uFF09"
5295
+ ] }) : null
5296
+ ] }, sk.name)) })
5231
5297
  ] }),
5232
5298
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.bindingStage, children: [
5233
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.fieldLabel, children: "rule\uFF08\u5B88\u4EC0\u4E48\uFF09" }),
5234
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.chips, children: rules.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.sourceBadge, children: "\u6682\u65E0\u53EF\u7528 rule\uFF0C\u53EF\u5728\u4E0B\u65B9\u65B0\u5EFA" }) : rules.map((rule) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
5235
- import_dsh_client_ui_primitives.Pill,
5236
- {
5237
- active: boundRules.includes(rule.name),
5238
- onClick: () => {
5239
- toggleRule(stage, rule.name);
5240
- },
5241
- title: `\u6765\u6E90\uFF1A${sourceLabel(rule.source)}`,
5242
- children: rule.name
5243
- },
5244
- rule.name
5245
- )) })
5246
- ] })
5247
- ] }, stage);
5248
- }) });
5299
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.fieldLabel, children: "rule\uFF08\u8FD9\u4E2A\u9636\u6BB5\u5B88\u4EC0\u4E48\uFF09" }),
5300
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.chips, children: rules.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.sourceBadge, children: "\u6682\u65E0\u53EF\u7528 rule\uFF0C\u53EF\u5728\u300C\u65B0\u5EFA skill / rule\u300D\u91CC\u5EFA" }) : rules.map((rule) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_dsh_client_ui_primitives.Pill, { active: boundRules.includes(rule.name), onClick: () => {
5301
+ toggleRule(rule.name);
5302
+ }, title: `\u6765\u6E90\uFF1A${sourceLabel(rule.source)}`, children: [
5303
+ rule.name,
5304
+ rule.source !== "bundled" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: styles.sourceBadge, children: [
5305
+ "\uFF08",
5306
+ sourceLabel(rule.source),
5307
+ "\uFF09"
5308
+ ] }) : null
5309
+ ] }, rule.name)) })
5310
+ ] }),
5311
+ boundSkills.length === 0 && boundRules.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.hint, children: "\u8FD9\u4E2A\u9636\u6BB5\u8FD8\u6CA1\u6302\u4EFB\u4F55 skill / rule \u2014\u2014 \u70B9\u4E0A\u9762\u7684\u540D\u79F0\u52FE\u9009\u3002" }) : null
5312
+ ] })
5313
+ ] });
5314
+ }
5315
+ function update(config, setConfig, fn) {
5316
+ setConfig(fn(config));
5317
+ }
5318
+ async function save(remote, config, workspace, setSavedAt, setSource, setLoadedProblems) {
5319
+ const result = await remote.write({ path: workspace, config });
5320
+ if (!result.ok) {
5321
+ setSavedAt("\u4FDD\u5B58\u5931\u8D25\uFF1A" + describeError(result.error));
5322
+ return;
5323
+ }
5324
+ setSource(result.value.source);
5325
+ setLoadedProblems(result.value.source === "invalid" ? result.value.problems : []);
5326
+ setSavedAt(result.value.ok ? "\u5DF2\u4FDD\u5B58" : "");
5327
+ }
5328
+ function splitList(textInput) {
5329
+ return textInput.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
5249
5330
  }
5250
- function ResourceCreator({ remote, workspace, onCreated }) {
5251
- const [skillName, setSkillName] = (0, import_react2.useState)("");
5252
- const [skillDesc, setSkillDesc] = (0, import_react2.useState)("");
5253
- const [skillWhen, setSkillWhen] = (0, import_react2.useState)("");
5254
- const [skillBody, setSkillBody] = (0, import_react2.useState)("");
5255
- const [ruleName, setRuleName] = (0, import_react2.useState)("");
5256
- const [ruleBody, setRuleBody] = (0, import_react2.useState)("");
5257
- const [level, setLevel] = (0, import_react2.useState)("project");
5258
- const [msg, setMsg] = (0, import_react2.useState)("");
5259
- const createSkill = async () => {
5331
+
5332
+ // src/client/SkillManager.tsx
5333
+ var import_react3 = require("react");
5334
+ var import_dsh_client_ui_primitives2 = require("@deepseek-ai/dsh-client-ui-primitives");
5335
+ var control2 = {
5336
+ background: "var(--dsw-alias-bg-layer-1)",
5337
+ border: "1px solid var(--dsw-alias-border-l2)",
5338
+ borderRadius: 8,
5339
+ padding: "5px 8px",
5340
+ color: "var(--dsw-alias-label-primary)",
5341
+ fontSize: 13,
5342
+ minWidth: 0
5343
+ };
5344
+ var card = {
5345
+ display: "flex",
5346
+ flexDirection: "column",
5347
+ gap: 8,
5348
+ border: "1px solid var(--dsw-alias-border-l2)",
5349
+ borderRadius: 8,
5350
+ padding: "10px 12px"
5351
+ };
5352
+ function levelOf(source) {
5353
+ return source.startsWith("user") ? "user" : "project";
5354
+ }
5355
+ function SkillManager({ workspace, remote }) {
5356
+ const [skills, setSkills] = (0, import_react3.useState)([]);
5357
+ const [level, setLevel] = (0, import_react3.useState)("project");
5358
+ const [editing, setEditing] = (0, import_react3.useState)(null);
5359
+ const [name, setName] = (0, import_react3.useState)("");
5360
+ const [description, setDescription] = (0, import_react3.useState)("");
5361
+ const [whenToUse, setWhenToUse] = (0, import_react3.useState)("");
5362
+ const [body2, setBody] = (0, import_react3.useState)("");
5363
+ const [msg, setMsg] = (0, import_react3.useState)("");
5364
+ const refresh = (0, import_react3.useCallback)(() => {
5365
+ void remote.listSkills(workspace).then((r) => {
5366
+ if (r.ok) setSkills(r.value.skills);
5367
+ }, () => {
5368
+ });
5369
+ }, [remote, workspace]);
5370
+ (0, import_react3.useEffect)(() => {
5371
+ refresh();
5372
+ }, [refresh]);
5373
+ const startCreate = () => {
5374
+ setEditing(null);
5375
+ setLevel("project");
5376
+ setName("");
5377
+ setDescription("");
5378
+ setWhenToUse("");
5379
+ setBody("");
5380
+ setMsg("");
5381
+ };
5382
+ const startEdit = (sk) => {
5383
+ const lvl = levelOf(sk.source);
5384
+ setEditing(sk.name);
5385
+ setLevel(lvl);
5386
+ setMsg("");
5387
+ void remote.readSkill({ name: sk.name, level: lvl, path: workspace }).then((r) => {
5388
+ if (r.ok && r.value.ok) {
5389
+ setName(r.value.name);
5390
+ setDescription(r.value.description);
5391
+ setWhenToUse(r.value.whenToUse);
5392
+ setBody(r.value.content);
5393
+ } else {
5394
+ setMsg("\u8BFB\u53D6\u5931\u8D25\uFF1A" + (r.ok ? r.value.error ?? "\u672A\u77E5\u9519\u8BEF" : describeError(r.error)));
5395
+ }
5396
+ });
5397
+ };
5398
+ const submit = async () => {
5260
5399
  setMsg("");
5400
+ const target = editing ?? name;
5261
5401
  const result = await remote.writeSkill({
5262
- name: skillName,
5263
- description: skillDesc,
5264
- whenToUse: skillWhen === "" ? void 0 : skillWhen,
5265
- content: skillBody,
5402
+ name: target,
5403
+ description,
5404
+ whenToUse: whenToUse.trim() === "" ? void 0 : whenToUse,
5405
+ content: body2,
5266
5406
  level,
5267
- path: workspace
5407
+ path: level === "project" ? workspace : void 0
5268
5408
  });
5269
5409
  if (!result.ok) {
5270
- setMsg("\u65B0\u5EFA skill \u5931\u8D25\uFF1A" + describeError(result.error));
5410
+ setMsg("\u4FDD\u5B58\u5931\u8D25\uFF1A" + describeError(result.error));
5271
5411
  return;
5272
5412
  }
5273
5413
  if (!result.value.ok) {
5274
- setMsg("\u65B0\u5EFA skill \u5931\u8D25\uFF1A" + (result.value.error ?? "\u672A\u77E5\u9519\u8BEF"));
5414
+ setMsg("\u4FDD\u5B58\u5931\u8D25\uFF1A" + (result.value.error ?? "\u672A\u77E5\u9519\u8BEF"));
5275
5415
  return;
5276
5416
  }
5277
- setMsg(`\u5DF2\u65B0\u5EFA skill\u300C${result.value.name}\u300D`);
5278
- setSkillName("");
5279
- setSkillDesc("");
5280
- setSkillWhen("");
5281
- setSkillBody("");
5282
- onCreated();
5417
+ setMsg(`\u5DF2\u4FDD\u5B58 skill\u300C${result.value.name}\u300D`);
5418
+ setEditing(null);
5419
+ refresh();
5420
+ };
5421
+ const formOpen = editing !== null || name !== "" || description !== "" || body2 !== "";
5422
+ return (0, import_react3.createElement)(
5423
+ "div",
5424
+ { style: styles.section },
5425
+ (0, import_react3.createElement)(
5426
+ "div",
5427
+ { style: card },
5428
+ (0, import_react3.createElement)(
5429
+ "div",
5430
+ { style: styles.bindingStage },
5431
+ (0, import_react3.createElement)("span", { style: styles.bindingLabel }, "\u5DF2\u5B89\u88C5\u7684 skill"),
5432
+ skills.length === 0 ? (0, import_react3.createElement)("p", { style: styles.muted }, "\u6682\u65E0 skill\uFF0C\u70B9\u4E0B\u65B9\u300C\u65B0\u5EFA skill\u300D\u521B\u5EFA\u4E00\u4E2A\u3002") : (0, import_react3.createElement)(
5433
+ "div",
5434
+ { style: styles.section },
5435
+ ...skills.map((sk) => (0, import_react3.createElement)(
5436
+ "div",
5437
+ {
5438
+ key: sk.name,
5439
+ style: { display: "flex", alignItems: "center", gap: 8, justifyContent: "space-between", padding: "6px 0", borderBottom: "1px solid var(--dsw-alias-border-l2)" }
5440
+ },
5441
+ (0, import_react3.createElement)(
5442
+ "div",
5443
+ { style: { display: "flex", flexDirection: "column", gap: 2, minWidth: 0 } },
5444
+ (0, import_react3.createElement)(
5445
+ "span",
5446
+ { style: { fontSize: 13, color: "var(--dsw-alias-label-primary)" } },
5447
+ sk.name,
5448
+ sk.source !== "bundled" ? (0, import_react3.createElement)("span", { style: styles.sourceBadge }, `\uFF08${sourceLabel(sk.source)}\uFF09`) : null
5449
+ ),
5450
+ (0, import_react3.createElement)("span", { style: styles.sourceBadge }, sk.description)
5451
+ ),
5452
+ sk.source === "bundled" ? (0, import_react3.createElement)("span", { style: styles.sourceBadge }, "\u5185\u7F6E \xB7 \u53EA\u8BFB") : (0, import_react3.createElement)(import_dsh_client_ui_primitives2.Button, { variant: "outline", size: "sm", onClick: () => {
5453
+ startEdit(sk);
5454
+ } }, "\u7F16\u8F91")
5455
+ ))
5456
+ )
5457
+ )
5458
+ ),
5459
+ formOpen ? (0, import_react3.createElement)(
5460
+ "div",
5461
+ { style: card },
5462
+ (0, import_react3.createElement)("span", { style: styles.bindingLabel }, editing === null ? "\u65B0\u5EFA skill" : `\u7F16\u8F91 skill\u300C${editing}\u300D`),
5463
+ (0, import_react3.createElement)(
5464
+ "div",
5465
+ { style: styles.chips },
5466
+ (0, import_react3.createElement)(import_dsh_client_ui_primitives2.Pill, { active: level === "project", onClick: () => {
5467
+ setLevel("project");
5468
+ }, title: "\u5199\u5230\u5DE5\u4F5C\u533A .dsh/skills\uFF0C\u56E2\u961F\u5171\u4EAB" }, "\u9879\u76EE\u7EA7"),
5469
+ (0, import_react3.createElement)(import_dsh_client_ui_primitives2.Pill, { active: level === "user", onClick: () => {
5470
+ setLevel("user");
5471
+ }, title: "\u5199\u5230 $DSH_HOME/skills\uFF0C\u4E2A\u4EBA\u6240\u6709\u9879\u76EE\u53EF\u7528" }, "\u7528\u6237\u7EA7")
5472
+ ),
5473
+ editing === null ? (0, import_react3.createElement)("input", { style: control2, placeholder: "name\uFF08\u5982 my-skill\uFF0C\u53EA\u542B\u5C0F\u5199\u5B57\u6BCD\u6570\u5B57\u548C -\uFF09", value: name, onChange: (ev) => {
5474
+ setName(ev.target.value);
5475
+ } }) : (0, import_react3.createElement)("span", { style: styles.sourceBadge }, `name \u56FA\u5B9A\u4E3A ${name}\uFF08\u6539\u540D\u8BF7\u5220\u9664\u540E\u91CD\u5EFA\uFF09`),
5476
+ (0, import_react3.createElement)("input", { style: control2, placeholder: "description\uFF08\u4E00\u53E5\u8BDD\u8BF4\u660E\u5B83\u505A\u4EC0\u4E48\uFF09", value: description, onChange: (ev) => {
5477
+ setDescription(ev.target.value);
5478
+ } }),
5479
+ (0, import_react3.createElement)("input", { style: control2, placeholder: "whenToUse\uFF08\u53EF\u9009\uFF1A\u4EC0\u4E48\u60C5\u51B5\u8BE5\u7528\uFF09", value: whenToUse, onChange: (ev) => {
5480
+ setWhenToUse(ev.target.value);
5481
+ } }),
5482
+ (0, import_react3.createElement)("textarea", { style: { ...styles.textarea, minHeight: 220 }, placeholder: "\u6B63\u6587\uFF08\u544A\u8BC9\u5927\u6A21\u578B\u8FD9\u4E2A\u9636\u6BB5\u600E\u4E48\u5E72\uFF09", value: body2, onChange: (ev) => {
5483
+ setBody(ev.target.value);
5484
+ } }),
5485
+ (0, import_react3.createElement)(
5486
+ "div",
5487
+ { style: styles.row },
5488
+ (0, import_react3.createElement)(import_dsh_client_ui_primitives2.Button, {
5489
+ variant: "primary",
5490
+ size: "sm",
5491
+ disabled: editing === null && name.trim() === "" || description.trim() === "" || body2.trim() === "",
5492
+ onClick: () => {
5493
+ void submit();
5494
+ }
5495
+ }, "\u4FDD\u5B58"),
5496
+ (0, import_react3.createElement)(import_dsh_client_ui_primitives2.Button, { variant: "ghost", size: "sm", onClick: () => {
5497
+ setEditing(null);
5498
+ setName("");
5499
+ setDescription("");
5500
+ setWhenToUse("");
5501
+ setBody("");
5502
+ setMsg("");
5503
+ } }, "\u53D6\u6D88")
5504
+ ),
5505
+ msg !== "" ? (0, import_react3.createElement)("p", { style: styles.status }, msg) : null
5506
+ ) : (0, import_react3.createElement)(
5507
+ "div",
5508
+ null,
5509
+ (0, import_react3.createElement)(import_dsh_client_ui_primitives2.Button, { variant: "outline", size: "md", onClick: startCreate }, "\u65B0\u5EFA skill")
5510
+ )
5511
+ );
5512
+ }
5513
+
5514
+ // src/client/RuleManager.tsx
5515
+ var import_react4 = require("react");
5516
+ var import_dsh_client_ui_primitives3 = require("@deepseek-ai/dsh-client-ui-primitives");
5517
+ var control3 = {
5518
+ background: "var(--dsw-alias-bg-layer-1)",
5519
+ border: "1px solid var(--dsw-alias-border-l2)",
5520
+ borderRadius: 8,
5521
+ padding: "5px 8px",
5522
+ color: "var(--dsw-alias-label-primary)",
5523
+ fontSize: 13,
5524
+ minWidth: 0
5525
+ };
5526
+ var card2 = {
5527
+ display: "flex",
5528
+ flexDirection: "column",
5529
+ gap: 8,
5530
+ border: "1px solid var(--dsw-alias-border-l2)",
5531
+ borderRadius: 8,
5532
+ padding: "10px 12px"
5533
+ };
5534
+ function levelOf2(source) {
5535
+ return source.startsWith("user") ? "user" : "project";
5536
+ }
5537
+ function RuleManager({ workspace, remote }) {
5538
+ const [rules, setRules] = (0, import_react4.useState)([]);
5539
+ const [level, setLevel] = (0, import_react4.useState)("project");
5540
+ const [editing, setEditing] = (0, import_react4.useState)(null);
5541
+ const [name, setName] = (0, import_react4.useState)("");
5542
+ const [body2, setBody] = (0, import_react4.useState)("");
5543
+ const [msg, setMsg] = (0, import_react4.useState)("");
5544
+ const refresh = (0, import_react4.useCallback)(() => {
5545
+ void remote.listRules(workspace).then((r) => {
5546
+ if (r.ok) setRules(r.value.rules);
5547
+ }, () => {
5548
+ });
5549
+ }, [remote, workspace]);
5550
+ (0, import_react4.useEffect)(() => {
5551
+ refresh();
5552
+ }, [refresh]);
5553
+ const startCreate = () => {
5554
+ setEditing(null);
5555
+ setLevel("project");
5556
+ setName("");
5557
+ setBody("");
5558
+ setMsg("");
5559
+ };
5560
+ const startEdit = (rule) => {
5561
+ const lvl = levelOf2(rule.source);
5562
+ setEditing(rule.name);
5563
+ setLevel(lvl);
5564
+ setMsg("");
5565
+ void remote.readRule({ name: rule.name, level: lvl, path: workspace }).then((r) => {
5566
+ if (r.ok && r.value.ok) {
5567
+ setName(r.value.name);
5568
+ setBody(r.value.content);
5569
+ } else {
5570
+ setMsg("\u8BFB\u53D6\u5931\u8D25\uFF1A" + (r.ok ? r.value.error ?? "\u672A\u77E5\u9519\u8BEF" : describeError(r.error)));
5571
+ }
5572
+ });
5283
5573
  };
5284
- const createRule = async () => {
5574
+ const submit = async () => {
5285
5575
  setMsg("");
5286
- const result = await remote.writeRule({ name: ruleName, content: ruleBody, level, path: workspace });
5576
+ const result = await remote.writeRule({
5577
+ name: editing ?? name,
5578
+ content: body2,
5579
+ level,
5580
+ path: level === "project" ? workspace : void 0
5581
+ });
5287
5582
  if (!result.ok) {
5288
- setMsg("\u65B0\u5EFA rule \u5931\u8D25\uFF1A" + describeError(result.error));
5583
+ setMsg("\u4FDD\u5B58\u5931\u8D25\uFF1A" + describeError(result.error));
5289
5584
  return;
5290
5585
  }
5291
5586
  if (!result.value.ok) {
5292
- setMsg("\u65B0\u5EFA rule \u5931\u8D25\uFF1A" + (result.value.error ?? "\u672A\u77E5\u9519\u8BEF"));
5587
+ setMsg("\u4FDD\u5B58\u5931\u8D25\uFF1A" + (result.value.error ?? "\u672A\u77E5\u9519\u8BEF"));
5293
5588
  return;
5294
5589
  }
5295
- setMsg(`\u5DF2\u65B0\u5EFA rule\u300C${result.value.name}\u300D`);
5296
- setRuleName("");
5297
- setRuleBody("");
5298
- onCreated();
5590
+ setMsg(`\u5DF2\u4FDD\u5B58 rule\u300C${result.value.name}\u300D`);
5591
+ setEditing(null);
5592
+ refresh();
5299
5593
  };
5300
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.section, children: [
5301
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.row, children: [
5302
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.fieldLabel, children: "\u5199\u5165\u4F4D\u7F6E" }),
5303
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.chips, children: [
5304
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Pill, { active: level === "project", onClick: () => {
5594
+ const formOpen = editing !== null || name !== "" || body2 !== "";
5595
+ return (0, import_react4.createElement)(
5596
+ "div",
5597
+ { style: styles.section },
5598
+ (0, import_react4.createElement)(
5599
+ "div",
5600
+ { style: card2 },
5601
+ (0, import_react4.createElement)(
5602
+ "div",
5603
+ { style: styles.bindingStage },
5604
+ (0, import_react4.createElement)("span", { style: styles.bindingLabel }, "\u5DF2\u5B89\u88C5\u7684 rule"),
5605
+ rules.length === 0 ? (0, import_react4.createElement)("p", { style: styles.muted }, "\u6682\u65E0 rule\uFF0C\u70B9\u4E0B\u65B9\u300C\u65B0\u5EFA rule\u300D\u521B\u5EFA\u4E00\u4E2A\u3002") : (0, import_react4.createElement)(
5606
+ "div",
5607
+ { style: styles.section },
5608
+ ...rules.map((rule) => (0, import_react4.createElement)(
5609
+ "div",
5610
+ {
5611
+ key: rule.name,
5612
+ style: { display: "flex", alignItems: "center", gap: 8, justifyContent: "space-between", padding: "6px 0", borderBottom: "1px solid var(--dsw-alias-border-l2)" }
5613
+ },
5614
+ (0, import_react4.createElement)(
5615
+ "span",
5616
+ { style: { fontSize: 13, color: "var(--dsw-alias-label-primary)" } },
5617
+ rule.name,
5618
+ rule.source !== "bundled" ? (0, import_react4.createElement)("span", { style: styles.sourceBadge }, `\uFF08${sourceLabel(rule.source)}\uFF09`) : null
5619
+ ),
5620
+ rule.source === "bundled" ? (0, import_react4.createElement)("span", { style: styles.sourceBadge }, "\u5185\u7F6E \xB7 \u53EA\u8BFB") : (0, import_react4.createElement)(import_dsh_client_ui_primitives3.Button, { variant: "outline", size: "sm", onClick: () => {
5621
+ startEdit(rule);
5622
+ } }, "\u7F16\u8F91")
5623
+ ))
5624
+ )
5625
+ )
5626
+ ),
5627
+ formOpen ? (0, import_react4.createElement)(
5628
+ "div",
5629
+ { style: card2 },
5630
+ (0, import_react4.createElement)("span", { style: styles.bindingLabel }, editing === null ? "\u65B0\u5EFA rule" : `\u7F16\u8F91 rule\u300C${editing}\u300D`),
5631
+ (0, import_react4.createElement)(
5632
+ "div",
5633
+ { style: styles.chips },
5634
+ (0, import_react4.createElement)(import_dsh_client_ui_primitives3.Pill, { active: level === "project", onClick: () => {
5305
5635
  setLevel("project");
5306
- }, title: "\u5199\u5230\u5DE5\u4F5C\u533A .dsh/\uFF0C\u56E2\u961F\u5171\u4EAB", children: "\u9879\u76EE\u7EA7" }),
5307
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Pill, { active: level === "user", onClick: () => {
5636
+ }, title: "\u5199\u5230\u5DE5\u4F5C\u533A .dsh/rules\uFF0C\u56E2\u961F\u5171\u4EAB" }, "\u9879\u76EE\u7EA7"),
5637
+ (0, import_react4.createElement)(import_dsh_client_ui_primitives3.Pill, { active: level === "user", onClick: () => {
5308
5638
  setLevel("user");
5309
- }, title: "\u5199\u5230 $DSH_HOME\uFF0C\u4E2A\u4EBA\u6240\u6709\u9879\u76EE\u53EF\u7528", children: "\u7528\u6237\u7EA7" })
5310
- ] })
5311
- ] }),
5312
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: cardV, children: [
5313
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.bindingLabel, children: "\u65B0\u5EFA Skill" }),
5314
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.row, children: [
5315
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { style: { ...control, flex: "1 1 140px" }, placeholder: "name\uFF08\u5982 my-skill\uFF09", value: skillName, onChange: (ev) => {
5316
- setSkillName(ev.target.value);
5317
- } }),
5318
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { style: { ...control, flex: "1 1 240px" }, placeholder: "description\uFF08\u4E00\u53E5\u8BDD\u8BF4\u660E\u5B83\u505A\u4EC0\u4E48\uFF09", value: skillDesc, onChange: (ev) => {
5319
- setSkillDesc(ev.target.value);
5320
- } })
5321
- ] }),
5322
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { style: control, placeholder: "whenToUse\uFF08\u53EF\u9009\uFF1A\u4EC0\u4E48\u60C5\u51B5\u8BE5\u7528\uFF09", value: skillWhen, onChange: (ev) => {
5323
- setSkillWhen(ev.target.value);
5324
- } }),
5325
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("textarea", { style: styles.textarea, placeholder: "skill \u6B63\u6587\uFF08\u544A\u8BC9\u5927\u6A21\u578B\u8FD9\u4E2A\u9636\u6BB5\u600E\u4E48\u5E72\uFF09", value: skillBody, onChange: (ev) => {
5326
- setSkillBody(ev.target.value);
5327
- } }),
5328
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { variant: "outline", size: "sm", icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconPlusOutline16, { size: 14 }), disabled: skillName.trim() === "" || skillDesc.trim() === "" || skillBody.trim() === "", onClick: () => {
5329
- void createSkill();
5330
- }, children: "\u65B0\u5EFA skill" }) })
5331
- ] }),
5332
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: cardV, children: [
5333
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.bindingLabel, children: "\u65B0\u5EFA Rule" }),
5334
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { style: control, placeholder: "name\uFF08\u5982 my-redlines\uFF09", value: ruleName, onChange: (ev) => {
5335
- setRuleName(ev.target.value);
5336
- } }),
5337
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("textarea", { style: styles.textarea, placeholder: "rule \u6B63\u6587\uFF08\u8FD9\u6761\u89C4\u5219\u7EA6\u675F\u5927\u6A21\u578B\u9075\u5B88\u4EC0\u4E48\uFF09", value: ruleBody, onChange: (ev) => {
5338
- setRuleBody(ev.target.value);
5639
+ }, title: "\u5199\u5230 $DSH_HOME/rules\uFF0C\u4E2A\u4EBA\u6240\u6709\u9879\u76EE\u53EF\u7528" }, "\u7528\u6237\u7EA7")
5640
+ ),
5641
+ editing === null ? (0, import_react4.createElement)("input", { style: control3, placeholder: "name\uFF08\u5982 my-redlines\uFF0C\u53EA\u542B\u5C0F\u5199\u5B57\u6BCD\u6570\u5B57\u548C -\uFF09", value: name, onChange: (ev) => {
5642
+ setName(ev.target.value);
5643
+ } }) : (0, import_react4.createElement)("span", { style: styles.sourceBadge }, `name \u56FA\u5B9A\u4E3A ${name}\uFF08\u6539\u540D\u8BF7\u5220\u9664\u540E\u91CD\u5EFA\uFF09`),
5644
+ (0, import_react4.createElement)("textarea", { style: { ...styles.textarea, minHeight: 240 }, placeholder: "\u6B63\u6587\uFF08\u8FD9\u6761\u89C4\u5219\u7EA6\u675F\u5927\u6A21\u578B\u9075\u5B88\u4EC0\u4E48\uFF09", value: body2, onChange: (ev) => {
5645
+ setBody(ev.target.value);
5339
5646
  } }),
5340
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { variant: "outline", size: "sm", icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconPlusOutline16, { size: 14 }), disabled: ruleName.trim() === "" || ruleBody.trim() === "", onClick: () => {
5341
- void createRule();
5342
- }, children: "\u65B0\u5EFA rule" }) })
5343
- ] }),
5344
- msg !== "" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.status, children: msg }) : null
5345
- ] });
5346
- }
5347
- function sourceLabel(source) {
5348
- switch (source) {
5349
- case "bundled":
5350
- return "\u5185\u7F6E";
5351
- case "project":
5352
- case "project-dsh":
5353
- case "project-agents":
5354
- return "\u9879\u76EE";
5355
- case "user":
5356
- case "user-dsh":
5357
- case "user-agents":
5358
- return "\u7528\u6237";
5359
- case "custom":
5360
- return "\u81EA\u5B9A\u4E49";
5361
- default:
5362
- return source;
5363
- }
5364
- }
5365
- function update(config, setConfig, fn) {
5366
- setConfig(fn(config));
5647
+ (0, import_react4.createElement)(
5648
+ "div",
5649
+ { style: styles.row },
5650
+ (0, import_react4.createElement)(import_dsh_client_ui_primitives3.Button, {
5651
+ variant: "primary",
5652
+ size: "sm",
5653
+ disabled: editing === null && name.trim() === "" || body2.trim() === "",
5654
+ onClick: () => {
5655
+ void submit();
5656
+ }
5657
+ }, "\u4FDD\u5B58"),
5658
+ (0, import_react4.createElement)(import_dsh_client_ui_primitives3.Button, { variant: "ghost", size: "sm", onClick: () => {
5659
+ setEditing(null);
5660
+ setName("");
5661
+ setBody("");
5662
+ setMsg("");
5663
+ } }, "\u53D6\u6D88")
5664
+ ),
5665
+ msg !== "" ? (0, import_react4.createElement)("p", { style: styles.status }, msg) : null
5666
+ ) : (0, import_react4.createElement)(
5667
+ "div",
5668
+ null,
5669
+ (0, import_react4.createElement)(import_dsh_client_ui_primitives3.Button, { variant: "outline", size: "md", onClick: startCreate }, "\u65B0\u5EFA rule")
5670
+ )
5671
+ );
5367
5672
  }
5368
- async function save(remote, config, workspace, setSavedAt, setSource, setLoadedProblems) {
5369
- const result = await remote.write({ path: workspace, config });
5370
- if (!result.ok) {
5371
- setSavedAt("\u4FDD\u5B58\u5931\u8D25\uFF1A" + describeError(result.error));
5372
- return;
5373
- }
5374
- setSource(result.value.source);
5375
- setLoadedProblems(result.value.source === "invalid" ? result.value.problems : []);
5376
- setSavedAt(result.value.ok ? "\u5DF2\u4FDD\u5B58" : "");
5673
+
5674
+ // src/client/Workbench.tsx
5675
+ var overlay = {
5676
+ position: "absolute",
5677
+ inset: 0,
5678
+ display: "flex",
5679
+ flexDirection: "column",
5680
+ background: "var(--dsw-alias-bg-base)",
5681
+ zIndex: 20
5682
+ };
5683
+ var header = {
5684
+ display: "flex",
5685
+ alignItems: "center",
5686
+ justifyContent: "space-between",
5687
+ padding: "12px 20px",
5688
+ borderBottom: "1px solid var(--dsw-alias-border-l2)"
5689
+ };
5690
+ var tabbar = {
5691
+ display: "flex",
5692
+ alignItems: "center",
5693
+ gap: 8,
5694
+ padding: "10px 20px",
5695
+ borderBottom: "1px solid var(--dsw-alias-border-l2)"
5696
+ };
5697
+ var body = {
5698
+ flex: 1,
5699
+ overflowY: "auto",
5700
+ padding: 20
5701
+ };
5702
+ var selectStyle = {
5703
+ marginLeft: "auto",
5704
+ background: "var(--dsw-alias-bg-layer-1)",
5705
+ border: "1px solid var(--dsw-alias-border-l2)",
5706
+ borderRadius: 8,
5707
+ padding: "5px 8px",
5708
+ color: "var(--dsw-alias-label-primary)",
5709
+ fontSize: 13
5710
+ };
5711
+ var closeStyle = {
5712
+ display: "flex",
5713
+ alignItems: "center",
5714
+ justifyContent: "center",
5715
+ width: 28,
5716
+ height: 28,
5717
+ border: "none",
5718
+ background: "transparent",
5719
+ cursor: "pointer",
5720
+ borderRadius: 6,
5721
+ color: "var(--dsw-alias-label-secondary)"
5722
+ };
5723
+ var TABS = [
5724
+ { id: "flow", label: "\u6D41\u7A0B\u914D\u7F6E" },
5725
+ { id: "skills", label: "\u6280\u80FD skill" },
5726
+ { id: "rules", label: "\u89C4\u5219 rule" }
5727
+ ];
5728
+ function Workbench({ useStore, actions, useWorkspaces, remote }) {
5729
+ const open = useStore((s) => s.open);
5730
+ const workspaces = useWorkspaces((s) => s.items);
5731
+ const [tab, setTab] = (0, import_react5.useState)("flow");
5732
+ const [workspace, setWorkspace] = (0, import_react5.useState)("");
5733
+ if (!open) return null;
5734
+ const current = workspaces.some((w) => w.path === workspace) ? workspace : workspaces[0]?.path ?? "";
5735
+ return (0, import_react5.createElement)(
5736
+ "div",
5737
+ { style: overlay },
5738
+ (0, import_react5.createElement)(
5739
+ "div",
5740
+ { style: header },
5741
+ (0, import_react5.createElement)("span", { style: { fontSize: 15, fontWeight: 600, color: "var(--dsw-alias-label-primary)" } }, "\u5DE5\u7A0B\u6D41\u7A0B"),
5742
+ (0, import_react5.createElement)(
5743
+ "button",
5744
+ { type: "button", title: "\u5173\u95ED", onClick: () => {
5745
+ actions.close();
5746
+ }, style: closeStyle },
5747
+ (0, import_react5.createElement)(import_dsh_client_ui_primitives4.IconCloseOutline16, { size: 16 })
5748
+ )
5749
+ ),
5750
+ (0, import_react5.createElement)(
5751
+ "div",
5752
+ { style: tabbar },
5753
+ ...TABS.map((t) => (0, import_react5.createElement)(import_dsh_client_ui_primitives4.Pill, { key: t.id, active: tab === t.id, onClick: () => {
5754
+ setTab(t.id);
5755
+ } }, t.label)),
5756
+ workspaces.length > 0 ? (0, import_react5.createElement)("select", {
5757
+ style: selectStyle,
5758
+ value: current,
5759
+ onChange: (ev) => {
5760
+ setWorkspace(ev.target.value);
5761
+ }
5762
+ }, ...workspaces.map((w) => (0, import_react5.createElement)("option", { key: w.path, value: w.path }, w.title || w.path))) : null
5763
+ ),
5764
+ (0, import_react5.createElement)(
5765
+ "div",
5766
+ { style: body },
5767
+ current === "" ? (0, import_react5.createElement)("p", { style: styles.muted }, "\u5F53\u524D\u6CA1\u6709\u5DE5\u4F5C\u533A\uFF1A\u8BF7\u5148\u5728\u4FA7\u680F\u521B\u5EFA\u4E00\u4E2A\u5DE5\u4F5C\u533A\uFF0C\u518D\u56DE\u6765\u914D\u7F6E\u6D41\u7A0B\u3002") : tab === "flow" ? (0, import_react5.createElement)(TaskEngineSection, { workspace: current, remote }) : tab === "skills" ? (0, import_react5.createElement)(SkillManager, { workspace: current, remote }) : (0, import_react5.createElement)(RuleManager, { workspace: current, remote })
5768
+ )
5769
+ );
5377
5770
  }
5378
- function splitList(textInput) {
5379
- return textInput.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
5771
+
5772
+ // src/client/TriggerButton.tsx
5773
+ var import_react6 = require("react");
5774
+ var import_dsh_client_ui_primitives5 = require("@deepseek-ai/dsh-client-ui-primitives");
5775
+ function TriggerButton({ wide, actions }) {
5776
+ return (0, import_react6.createElement)(
5777
+ "button",
5778
+ {
5779
+ type: "button",
5780
+ title: "\u5DE5\u7A0B\u6D41\u7A0B",
5781
+ "aria-haspopup": "dialog",
5782
+ onClick: () => {
5783
+ actions.open();
5784
+ },
5785
+ style: {
5786
+ display: "flex",
5787
+ alignItems: "center",
5788
+ justifyContent: wide ? "flex-start" : "center",
5789
+ gap: wide ? 8 : 0,
5790
+ width: "100%",
5791
+ height: 32,
5792
+ border: "none",
5793
+ background: "transparent",
5794
+ cursor: "pointer",
5795
+ color: "var(--dsw-alias-label-secondary)",
5796
+ borderRadius: 6,
5797
+ padding: wide ? "0 10px" : 0,
5798
+ boxSizing: "border-box"
5799
+ }
5800
+ },
5801
+ (0, import_react6.createElement)(import_dsh_client_ui_primitives5.IconSettingsOutline16, { size: wide ? 16 : 18 }),
5802
+ wide ? (0, import_react6.createElement)("span", { style: { fontSize: 13 } }, "\u5DE5\u7A0B\u6D41\u7A0B") : null
5803
+ );
5380
5804
  }
5381
- function describeError(error) {
5382
- if (error instanceof Error) return error.message;
5383
- if (typeof error === "string") return error;
5384
- return "\u672A\u77E5\u9519\u8BEF";
5805
+
5806
+ // src/client/visibility.ts
5807
+ var import_dsh_client_store = require("@deepseek-ai/dsh-client-store");
5808
+ function createVisibilityStore() {
5809
+ return (0, import_dsh_client_store.defineStore)({
5810
+ init: () => ({ open: false }),
5811
+ actions: {
5812
+ open: (d) => {
5813
+ d.open = true;
5814
+ },
5815
+ close: (d) => {
5816
+ d.open = false;
5817
+ }
5818
+ }
5819
+ });
5385
5820
  }
5386
5821
 
5387
5822
  // src/client/index.ts
@@ -5393,13 +5828,20 @@ async function apply(ctx) {
5393
5828
  await disposeRemote();
5394
5829
  throw new Error("task-engine: remote.task-engine namespace failed to mount");
5395
5830
  }
5396
- ctx.slots.inject("settings.section", () => ctx.slots.register({
5397
- name: "settings.section",
5831
+ const visibility = createVisibilityStore();
5832
+ ctx.slots.inject("shell.overlay", () => ctx.slots.register({
5833
+ name: "shell.overlay",
5398
5834
  id: "task-engine",
5399
5835
  order: 100,
5400
- label: "\u5DE5\u7A0B\u6D41\u7A0B\u914D\u7F6E",
5836
+ store: visibility,
5401
5837
  inject: () => ({ remote: taskEngine })
5402
- }, TaskEngineSection));
5838
+ }, Workbench));
5839
+ ctx.slots.inject("sidebar.footer.action", () => ctx.slots.register({
5840
+ name: "sidebar.footer.action",
5841
+ id: "task-engine",
5842
+ order: 100,
5843
+ store: visibility
5844
+ }, TriggerButton));
5403
5845
  return async () => {
5404
5846
  await disposeRemote();
5405
5847
  };