@godv61/dsh-task-engine 0.6.1 → 0.8.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
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 }) }),
4861
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 }) }),
4862
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 }) }),
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", defaultOpen: false, 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 }) }),
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" }),
@@ -5255,143 +5312,511 @@ function BindingEditor({ config, setConfig, skills, rules }) {
5255
5312
  ] })
5256
5313
  ] });
5257
5314
  }
5258
- function ResourceCreator({ remote, workspace, onCreated }) {
5259
- const [skillName, setSkillName] = (0, import_react2.useState)("");
5260
- const [skillDesc, setSkillDesc] = (0, import_react2.useState)("");
5261
- const [skillWhen, setSkillWhen] = (0, import_react2.useState)("");
5262
- const [skillBody, setSkillBody] = (0, import_react2.useState)("");
5263
- const [ruleName, setRuleName] = (0, import_react2.useState)("");
5264
- const [ruleBody, setRuleBody] = (0, import_react2.useState)("");
5265
- const [level, setLevel] = (0, import_react2.useState)("project");
5266
- const [msg, setMsg] = (0, import_react2.useState)("");
5267
- const createSkill = async () => {
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);
5330
+ }
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("");
5268
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 () => {
5399
+ setMsg("");
5400
+ const target = editing ?? name;
5269
5401
  const result = await remote.writeSkill({
5270
- name: skillName,
5271
- description: skillDesc,
5272
- whenToUse: skillWhen === "" ? void 0 : skillWhen,
5273
- content: skillBody,
5402
+ name: target,
5403
+ description,
5404
+ whenToUse: whenToUse.trim() === "" ? void 0 : whenToUse,
5405
+ content: body2,
5274
5406
  level,
5275
- path: workspace
5407
+ path: level === "project" ? workspace : void 0
5276
5408
  });
5277
5409
  if (!result.ok) {
5278
- setMsg("\u65B0\u5EFA skill \u5931\u8D25\uFF1A" + describeError(result.error));
5410
+ setMsg("\u4FDD\u5B58\u5931\u8D25\uFF1A" + describeError(result.error));
5279
5411
  return;
5280
5412
  }
5281
5413
  if (!result.value.ok) {
5282
- 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"));
5283
5415
  return;
5284
5416
  }
5285
- const loc = level === "project" ? `.dsh/skills/${result.value.name}/SKILL.md` : `$DSH_HOME/skills/${result.value.name}/SKILL.md`;
5286
- setMsg(`\u5DF2\u65B0\u5EFA skill\u300C${result.value.name}\u300D\u2192 \u5199\u5165 ${loc}\uFF08\u5DF2\u51FA\u73B0\u5728\u4E0A\u65B9\u6302\u8F7D\u6E05\u5355\uFF09`);
5287
- setSkillName("");
5288
- setSkillDesc("");
5289
- setSkillWhen("");
5290
- setSkillBody("");
5291
- 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
+ });
5292
5573
  };
5293
- const createRule = async () => {
5574
+ const submit = async () => {
5294
5575
  setMsg("");
5295
- 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
+ });
5296
5582
  if (!result.ok) {
5297
- setMsg("\u65B0\u5EFA rule \u5931\u8D25\uFF1A" + describeError(result.error));
5583
+ setMsg("\u4FDD\u5B58\u5931\u8D25\uFF1A" + describeError(result.error));
5298
5584
  return;
5299
5585
  }
5300
5586
  if (!result.value.ok) {
5301
- 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"));
5302
5588
  return;
5303
5589
  }
5304
- const loc = level === "project" ? `.dsh/rules/${result.value.name}.md` : `$DSH_HOME/rules/${result.value.name}.md`;
5305
- setMsg(`\u5DF2\u65B0\u5EFA rule\u300C${result.value.name}\u300D\u2192 \u5199\u5165 ${loc}\uFF08\u5DF2\u51FA\u73B0\u5728\u4E0A\u65B9\u6302\u8F7D\u6E05\u5355\uFF09`);
5306
- setRuleName("");
5307
- setRuleBody("");
5308
- onCreated();
5590
+ setMsg(`\u5DF2\u4FDD\u5B58 rule\u300C${result.value.name}\u300D`);
5591
+ setEditing(null);
5592
+ refresh();
5309
5593
  };
5310
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.section, children: [
5311
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.row, children: [
5312
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.fieldLabel, children: "\u5199\u5165\u4F4D\u7F6E" }),
5313
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.chips, children: [
5314
- /* @__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: () => {
5315
5635
  setLevel("project");
5316
- }, title: "\u5199\u5230\u5DE5\u4F5C\u533A .dsh/\uFF0C\u56E2\u961F\u5171\u4EAB", children: "\u9879\u76EE\u7EA7" }),
5317
- /* @__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: () => {
5318
5638
  setLevel("user");
5319
- }, title: "\u5199\u5230 $DSH_HOME\uFF0C\u4E2A\u4EBA\u6240\u6709\u9879\u76EE\u53EF\u7528", children: "\u7528\u6237\u7EA7" })
5320
- ] })
5321
- ] }),
5322
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: cardV, children: [
5323
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.bindingLabel, children: "\u65B0\u5EFA Skill" }),
5324
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.row, children: [
5325
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { style: { ...control, flex: "1 1 140px" }, placeholder: "name\uFF08\u5982 my-skill\uFF09", value: skillName, onChange: (ev) => {
5326
- setSkillName(ev.target.value);
5327
- } }),
5328
- /* @__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) => {
5329
- setSkillDesc(ev.target.value);
5330
- } })
5331
- ] }),
5332
- /* @__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) => {
5333
- setSkillWhen(ev.target.value);
5334
- } }),
5335
- /* @__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) => {
5336
- setSkillBody(ev.target.value);
5337
- } }),
5338
- /* @__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: () => {
5339
- void createSkill();
5340
- }, children: "\u65B0\u5EFA skill" }) })
5341
- ] }),
5342
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: cardV, children: [
5343
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.bindingLabel, children: "\u65B0\u5EFA Rule" }),
5344
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { style: control, placeholder: "name\uFF08\u5982 my-redlines\uFF09", value: ruleName, onChange: (ev) => {
5345
- setRuleName(ev.target.value);
5346
- } }),
5347
- /* @__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) => {
5348
- 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);
5349
5646
  } }),
5350
- /* @__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: () => {
5351
- void createRule();
5352
- }, children: "\u65B0\u5EFA rule" }) })
5353
- ] }),
5354
- msg !== "" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.status, children: msg }) : null
5355
- ] });
5356
- }
5357
- function sourceLabel(source) {
5358
- switch (source) {
5359
- case "bundled":
5360
- return "\u5185\u7F6E";
5361
- case "project":
5362
- case "project-dsh":
5363
- case "project-agents":
5364
- return "\u9879\u76EE";
5365
- case "user":
5366
- case "user-dsh":
5367
- case "user-agents":
5368
- return "\u7528\u6237";
5369
- case "custom":
5370
- return "\u81EA\u5B9A\u4E49";
5371
- default:
5372
- return source;
5373
- }
5374
- }
5375
- function update(config, setConfig, fn) {
5376
- 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
+ );
5377
5672
  }
5378
- async function save(remote, config, workspace, setSavedAt, setSource, setLoadedProblems) {
5379
- const result = await remote.write({ path: workspace, config });
5380
- if (!result.ok) {
5381
- setSavedAt("\u4FDD\u5B58\u5931\u8D25\uFF1A" + describeError(result.error));
5382
- return;
5383
- }
5384
- setSource(result.value.source);
5385
- setLoadedProblems(result.value.source === "invalid" ? result.value.problems : []);
5386
- 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
+ );
5387
5770
  }
5388
- function splitList(textInput) {
5389
- 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
+ );
5390
5804
  }
5391
- function describeError(error) {
5392
- if (error instanceof Error) return error.message;
5393
- if (typeof error === "string") return error;
5394
- 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
+ });
5395
5820
  }
5396
5821
 
5397
5822
  // src/client/index.ts
@@ -5403,13 +5828,20 @@ async function apply(ctx) {
5403
5828
  await disposeRemote();
5404
5829
  throw new Error("task-engine: remote.task-engine namespace failed to mount");
5405
5830
  }
5406
- ctx.slots.inject("settings.section", () => ctx.slots.register({
5407
- name: "settings.section",
5831
+ const visibility = createVisibilityStore();
5832
+ ctx.slots.inject("shell.overlay", () => ctx.slots.register({
5833
+ name: "shell.overlay",
5408
5834
  id: "task-engine",
5409
5835
  order: 100,
5410
- label: "\u5DE5\u7A0B\u6D41\u7A0B\u914D\u7F6E",
5836
+ store: visibility,
5411
5837
  inject: () => ({ remote: taskEngine })
5412
- }, 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));
5413
5845
  return async () => {
5414
5846
  await disposeRemote();
5415
5847
  };