@godv61/dsh-task-engine 0.22.6 → 0.23.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
@@ -4139,6 +4139,15 @@ var installSkillRequestSchema = external_exports.object({
4139
4139
  level: external_exports.enum(["project", "user"]),
4140
4140
  path: external_exports.string().optional()
4141
4141
  });
4142
+ var listDirsRequestSchema = external_exports.object({ path: external_exports.string() });
4143
+ var listDirsViewSchema = external_exports.object({
4144
+ ok: external_exports.boolean(),
4145
+ path: external_exports.string(),
4146
+ entries: external_exports.array(external_exports.object({ name: external_exports.string(), hasSkill: external_exports.boolean() })),
4147
+ roots: external_exports.array(external_exports.string()),
4148
+ currentHasSkill: external_exports.boolean(),
4149
+ error: external_exports.string().optional()
4150
+ });
4142
4151
  var writeRuleRequestSchema = external_exports.object({
4143
4152
  name: external_exports.string(),
4144
4153
  content: external_exports.string(),
@@ -4197,6 +4206,10 @@ var taskLedgerItemSchema = external_exports.object({
4197
4206
  });
4198
4207
  var taskLedgerViewSchema = external_exports.object({
4199
4208
  tasks: external_exports.array(external_exports.object({
4209
+ risk_level: external_exports.string().optional(),
4210
+ updated_at: external_exports.string().optional(),
4211
+ verification_passed: external_exports.boolean().optional(),
4212
+ review_outcome: external_exports.string().optional(),
4200
4213
  task_id: external_exports.string(),
4201
4214
  title: external_exports.string(),
4202
4215
  stage: external_exports.string(),
@@ -4229,10 +4242,37 @@ var initDraftSchema = external_exports.object({
4229
4242
  lines: external_exports.number(),
4230
4243
  error: external_exports.string().optional()
4231
4244
  });
4245
+ var resourceRequestSchema = external_exports.object({
4246
+ kind: external_exports.enum(["skill", "rule"]),
4247
+ level: external_exports.enum(["project", "user"]),
4248
+ path: external_exports.string(),
4249
+ files: external_exports.array(external_exports.object({ path: external_exports.string(), base64: external_exports.string() })).max(1e3),
4250
+ sourceDir: external_exports.string().optional(),
4251
+ expectedHash: external_exports.string().optional()
4252
+ });
4253
+ var resourcePreviewSchema = external_exports.object({ ok: external_exports.boolean(), name: external_exports.string(), description: external_exports.string(), content: external_exports.string(), target: external_exports.string(), files: external_exports.number(), bytes: external_exports.number(), hash: external_exports.string(), conflict: external_exports.boolean(), error: external_exports.string().optional() });
4232
4254
  var PACKAGE = "@godv61/dsh-task-engine";
4233
4255
  var TYPERT_REMOTE = {
4234
4256
  package: PACKAGE,
4235
4257
  descriptors: [
4258
+ ...["previewResource", "importResource"].map((method) => ({
4259
+ id: `${PACKAGE}#task-engine/${method}`,
4260
+ service: "taskEngineController",
4261
+ namespace: "task-engine",
4262
+ method,
4263
+ invocation: { kind: "direct" },
4264
+ parameters: [{ name: "request", wire: "request", source: "json", codec: { mode: "strict", typeSymbol: `${PACKAGE}/types#ResourceImportRequest`, schema: resourceRequestSchema } }],
4265
+ result: { mode: "strict", typeSymbol: `${PACKAGE}/types#ResourcePreview`, schema: resourcePreviewSchema }
4266
+ })),
4267
+ {
4268
+ id: `${PACKAGE}#task-engine/resourceRoots`,
4269
+ service: "taskEngineController",
4270
+ namespace: "task-engine",
4271
+ method: "resourceRoots",
4272
+ invocation: { kind: "direct" },
4273
+ parameters: [{ name: "request", wire: "request", source: "json", codec: { mode: "strict", typeSymbol: `${PACKAGE}/types#ResourceRootsRequest`, schema: external_exports.object({ kind: external_exports.enum(["skill", "rule"]), path: external_exports.string() }) } }],
4274
+ result: { mode: "strict", typeSymbol: `${PACKAGE}/types#ResourceRoots`, schema: external_exports.object({ project: external_exports.string(), user: external_exports.string() }) }
4275
+ },
4236
4276
  {
4237
4277
  id: `${PACKAGE}#task-engine/read`,
4238
4278
  service: "taskEngineController",
@@ -4329,6 +4369,22 @@ var TYPERT_REMOTE = {
4329
4369
  ],
4330
4370
  result: { mode: "strict", typeSymbol: `${PACKAGE}/types#WriteResourceResult`, schema: writeResourceResultSchema }
4331
4371
  },
4372
+ {
4373
+ id: `${PACKAGE}#task-engine/listDirs`,
4374
+ service: "taskEngineController",
4375
+ namespace: "task-engine",
4376
+ method: "listDirs",
4377
+ invocation: { kind: "direct" },
4378
+ parameters: [
4379
+ {
4380
+ name: "request",
4381
+ wire: "request",
4382
+ source: "json",
4383
+ codec: { mode: "strict", typeSymbol: `${PACKAGE}/types#ListDirsRequest`, schema: listDirsRequestSchema }
4384
+ }
4385
+ ],
4386
+ result: { mode: "strict", typeSymbol: `${PACKAGE}/types#ListDirsView`, schema: listDirsViewSchema }
4387
+ },
4332
4388
  {
4333
4389
  id: `${PACKAGE}#task-engine/writeRule`,
4334
4390
  service: "taskEngineController",
@@ -4478,8 +4534,59 @@ var TYPERT_REMOTE = {
4478
4534
  var remote_default = TYPERT_REMOTE;
4479
4535
 
4480
4536
  // src/client/Workbench.tsx
4481
- var import_react7 = require("react");
4482
- var import_dsh_client_ui_primitives7 = require("@deepseek-ai/dsh-client-ui-primitives");
4537
+ var import_react8 = require("react");
4538
+ var import_dsh_client_ui_primitives6 = require("@deepseek-ai/dsh-client-ui-primitives");
4539
+
4540
+ // src/client/workbench-theme.ts
4541
+ var workbenchTheme = `
4542
+ .te-workbench { color:var(--dsw-alias-label-primary); font-size:14px; }
4543
+ .te-workbench *,.te-modal * { box-sizing:border-box; }
4544
+ .te-workbench button,.te-modal button { font-family:inherit; }
4545
+ .te-workbench button:focus-visible,.te-modal button:focus-visible,.te-input:focus-visible { outline:2px solid var(--dsw-alias-state-business-primary); outline-offset:3px; }
4546
+ .te-workbench h2 { margin:0 0 6px; font-size:24px; letter-spacing:-.5px; }
4547
+ .te-workbench h3,.te-modal h3 { margin:0; font-size:16px; overflow-wrap:anywhere; }
4548
+ .te-workbench p,.te-modal p { color:var(--dsw-alias-label-secondary); line-height:1.65; }
4549
+ .te-content { max-width:1120px; margin:auto; width:100%; }
4550
+ .te-resource { display:flex; flex-direction:column; gap:20px; }
4551
+ .te-section-heading { display:flex; justify-content:space-between; align-items:center; gap:16px; flex-wrap:wrap; }
4552
+ .te-section-heading p { margin:0; }
4553
+ .te-actions { display:flex; align-items:center; flex-wrap:wrap; gap:10px; }
4554
+ .te-toolbar { display:flex; flex-wrap:wrap; align-items:center; gap:12px; }
4555
+ .te-toolbar>input { flex:1; min-width:180px; }
4556
+ .te-input { background:var(--dsw-alias-bg-layer-1); border:1px solid var(--dsw-alias-border-l2); border-radius:10px; padding:10px 12px; font:inherit; color:var(--dsw-alias-label-primary); min-width:0; }
4557
+ .te-resource-grid { display:grid; grid-template-columns:repeat(auto-fill,minmax(min(100%,280px),1fr)); gap:16px; }
4558
+ .te-resource-card { display:flex; flex-direction:column; gap:14px; background:var(--dsw-alias-bg-layer-1); border:1px solid var(--dsw-alias-border-l2); border-radius:16px; padding:20px; transition:border-color .15s; }
4559
+ .te-resource-card:hover { border-color:var(--dsw-alias-state-business-primary); }
4560
+ .te-resource-card p { margin:0; font-size:13px; flex:1; }
4561
+ .te-card-top { display:flex; justify-content:space-between; align-items:center; }
4562
+ .te-resource-icon { display:grid; place-items:center; width:36px; height:36px; border-radius:10px; background:var(--dsw-alias-bg-layer-2); color:var(--dsw-alias-state-business-primary); font-size:25px; }
4563
+ .te-badge { display:inline-flex; border-radius:20px; background:var(--dsw-alias-bg-layer-2); color:var(--dsw-alias-label-secondary); padding:4px 10px; font-size:12px; }
4564
+ .te-delete,.te-link { border:none; background:transparent; cursor:pointer; padding:8px; color:var(--dsw-alias-label-secondary); }
4565
+ .te-delete { margin-left:auto; }
4566
+ .te-delete:hover { color:var(--dsw-alias-state-error-primary); }
4567
+ .te-link { text-align:left; align-self:flex-start; text-decoration:underline; }
4568
+ .te-danger-button { border:0; border-radius:9px; padding:10px 16px; background:var(--dsw-alias-state-error-primary); color:white; cursor:pointer; }
4569
+ .te-danger-button:disabled { opacity:.5; cursor:wait; }
4570
+ .te-alert,.te-success { padding:12px 16px; border-radius:10px; border:1px solid currentColor; overflow-wrap:anywhere; font-size:13px; }
4571
+ .te-alert { color:var(--dsw-alias-state-error-primary); }
4572
+ .te-success { color:var(--dsw-alias-state-success-primary); }
4573
+ .te-empty { text-align:center; padding:56px 24px; border:1px dashed var(--dsw-alias-border-l2); border-radius:16px; color:var(--dsw-alias-label-secondary); }
4574
+ .te-targets { display:grid; grid-template-columns:1fr 1fr; gap:12px; margin:4px 0 16px; }
4575
+ .te-target { display:flex; flex-direction:column; align-items:flex-start; gap:6px; padding:16px; border-radius:12px; border:1px solid var(--dsw-alias-border-l2); background:var(--dsw-alias-bg-layer-1); color:var(--dsw-alias-label-primary); cursor:pointer; }
4576
+ .te-target small { color:var(--dsw-alias-label-secondary); text-align:left; }
4577
+ .te-target.selected { border-color:var(--dsw-alias-state-business-primary); box-shadow:0 0 0 1px var(--dsw-alias-state-business-primary); }
4578
+ .te-path { display:block; grid-column:1/-1; padding:10px 12px; font-size:12px; border-radius:8px; background:var(--dsw-alias-bg-layer-1); color:var(--dsw-alias-label-secondary); overflow-wrap:anywhere; white-space:pre-wrap; }
4579
+ .te-preview { display:flex; flex-direction:column; gap:12px; margin-top:16px; }
4580
+ .te-markdown { max-height:360px; overflow:auto; padding:16px; border:1px solid var(--dsw-alias-border-l2); border-radius:12px; }
4581
+ .te-advanced { margin-top:16px; padding:12px; border:1px dashed var(--dsw-alias-border-l2); border-radius:12px; }
4582
+ .te-dir-list { max-height:160px; overflow:auto; display:flex; flex-direction:column; gap:4px; }
4583
+ .te-dir-list button { text-align:left; border:0; background:transparent; color:var(--dsw-alias-label-primary); padding:8px; cursor:pointer; }
4584
+ .te-dir-list button:hover { background:var(--dsw-alias-bg-layer-1); }
4585
+ .te-form { display:flex; flex-direction:column; gap:16px; }
4586
+ .te-form label { display:flex; flex-direction:column; gap:8px; font-size:13px; }
4587
+ .te-editor { min-height:260px; resize:vertical; line-height:1.6; font-family:monospace; }
4588
+ @media(max-width:640px) { .te-targets {grid-template-columns:1fr;} .te-resource {gap:14px;} .te-section-heading h2 {font-size:21px;} .te-modal {padding:10px !important;} }
4589
+ `;
4483
4590
 
4484
4591
  // src/client/styles.ts
4485
4592
  var text = "var(--dsw-alias-label-primary)";
@@ -4873,29 +4980,39 @@ function TaskEngineSection(props) {
4873
4980
  const [source, setSource] = (0, import_react.useState)("default");
4874
4981
  const [savedAt, setSavedAt] = (0, import_react.useState)("");
4875
4982
  const [loadError, setLoadError] = (0, import_react.useState)("");
4983
+ const [saving, setSaving] = (0, import_react.useState)(false);
4984
+ const [loading, setLoading] = (0, import_react.useState)(true);
4985
+ const [loadAttempt, setLoadAttempt] = (0, import_react.useState)(0);
4986
+ const [configProblems, setConfigProblems] = (0, import_react.useState)([]);
4876
4987
  const [skills, setSkills] = (0, import_react.useState)([]);
4877
4988
  const [rules, setRules] = (0, import_react.useState)([]);
4878
4989
  (0, import_react.useEffect)(() => {
4879
4990
  if (workspace === "") return;
4880
4991
  let alive = true;
4881
4992
  setLoadError("");
4993
+ setLoading(true);
4882
4994
  void remote.read(workspace).then((result) => {
4883
4995
  if (!alive) return;
4996
+ setLoading(false);
4884
4997
  if (result.ok) {
4885
4998
  setFlow(result.value.flow);
4886
4999
  setStageBindings(result.value.config.stage_bindings ?? {});
4887
5000
  setSource(result.value.source);
5001
+ setConfigProblems(result.value.problems);
4888
5002
  setSavedAt("");
4889
5003
  } else {
4890
5004
  setLoadError("\u8BFB\u53D6\u914D\u7F6E\u5931\u8D25\uFF1A" + describeError(result.error));
4891
5005
  }
4892
5006
  }, (error) => {
4893
- if (alive) setLoadError("\u8BFB\u53D6\u914D\u7F6E\u5931\u8D25\uFF1A" + describeError(error));
5007
+ if (alive) {
5008
+ setLoading(false);
5009
+ setLoadError("\u8BFB\u53D6\u914D\u7F6E\u5931\u8D25\uFF1A" + describeError(error));
5010
+ }
4894
5011
  });
4895
5012
  return () => {
4896
5013
  alive = false;
4897
5014
  };
4898
- }, [remote, workspace]);
5015
+ }, [remote, workspace, loadAttempt]);
4899
5016
  const refreshCatalogs = (0, import_react.useCallback)(() => {
4900
5017
  if (workspace === "") return;
4901
5018
  void remote.listSkills(workspace).then((result) => {
@@ -4927,11 +5044,18 @@ function TaskEngineSection(props) {
4927
5044
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.StateDot, { state: "error" }),
4928
5045
  "\u8BFB\u53D6\u5931\u8D25"
4929
5046
  ] }),
4930
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.muted, children: loadError })
5047
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.muted, children: loadError }),
5048
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { onClick: () => setLoadAttempt((n) => n + 1), children: "\u91CD\u8BD5" })
4931
5049
  ] })
4932
5050
  ] });
4933
5051
  }
5052
+ if (loading) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { role: "status", children: "\u6B63\u5728\u8BFB\u53D6\u6D41\u7A0B\u914D\u7F6E\u2026" });
4934
5053
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.wrap, children: [
5054
+ configProblems.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { role: "alert", style: styles.problems, children: [
5055
+ "\u539F\u914D\u7F6E\u6709\u95EE\u9898\uFF1A",
5056
+ configProblems.join("\uFF1B"),
5057
+ "\u3002\u8BF7\u9009\u62E9\u6709\u6548\u9884\u8BBE\u5E76\u4FDD\u5B58\u4FEE\u590D\u3002"
5058
+ ] }),
4935
5059
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.head, children: [
4936
5060
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { style: styles.title, children: "\u5DE5\u7A0B\u6D41\u7A0B\u914D\u7F6E" }),
4937
5061
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.muted, children: "\u9009\u4E00\u5957\u6D41\u7A0B\uFF0C\u518D\u7ED9\u6BCF\u4E2A\u8282\u70B9\u6302\u4E0A skill / rule\u3002\u9636\u6BB5\u6D41\u8F6C\u3001\u5B88\u536B\u3001\u63D0\u4EA4\u89C4\u5219\u90FD\u7531\u6D41\u7A0B\u9884\u8BBE\u56FA\u5316\uFF0C\u65E0\u9700\u624B\u5DE5\u914D\u7F6E\u3002" })
@@ -4987,11 +5111,14 @@ function TaskEngineSection(props) {
4987
5111
  variant: "primary",
4988
5112
  size: "md",
4989
5113
  icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconCheckOutline16, { size: 16 }),
4990
- disabled: problems.length > 0,
5114
+ disabled: problems.length > 0 || saving,
4991
5115
  onClick: () => {
4992
- void save(remote, flow, stageBindings, workspace, setSavedAt, setSource);
5116
+ setSaving(true);
5117
+ void save(remote, flow, stageBindings, workspace, setSavedAt, setSource).then((ok) => {
5118
+ if (ok) setConfigProblems([]);
5119
+ }).finally(() => setSaving(false));
4993
5120
  },
4994
- children: "\u4FDD\u5B58\u5230 .dsh/eng.json"
5121
+ children: saving ? "\u6B63\u5728\u4FDD\u5B58\u2026" : "\u4FDD\u5B58\u5230 .dsh/eng.json"
4995
5122
  }
4996
5123
  ),
4997
5124
  savedAt !== "" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: styles.okText, children: [
@@ -5090,13 +5217,23 @@ function BindingEditor({ stages, stageBindings, setStageBindings, skills, rules
5090
5217
  ] });
5091
5218
  }
5092
5219
  async function save(remote, flow, stageBindings, workspace, setSavedAt, setSource) {
5093
- const result = await remote.write({ path: workspace, flow, stage_bindings: stageBindings });
5094
- if (!result.ok) {
5095
- setSavedAt("\u4FDD\u5B58\u5931\u8D25\uFF1A" + describeError(result.error));
5096
- return;
5220
+ try {
5221
+ const result = await remote.write({ path: workspace, flow, stage_bindings: stageBindings });
5222
+ if (!result.ok) {
5223
+ setSavedAt("\u4FDD\u5B58\u5931\u8D25\uFF1A" + describeError(result.error));
5224
+ return false;
5225
+ }
5226
+ if (!result.value.ok) {
5227
+ setSavedAt("\u4FDD\u5B58\u5931\u8D25\uFF1A" + result.value.problems.join("\uFF1B"));
5228
+ return false;
5229
+ }
5230
+ setSource(result.value.source);
5231
+ setSavedAt("\u5DF2\u4FDD\u5B58");
5232
+ return true;
5233
+ } catch (error) {
5234
+ setSavedAt("\u4FDD\u5B58\u5931\u8D25\uFF1A" + describeError(error));
5235
+ return false;
5097
5236
  }
5098
- setSource(result.value.source);
5099
- setSavedAt(result.value.ok ? "\u5DF2\u4FDD\u5B58" : "");
5100
5237
  }
5101
5238
 
5102
5239
  // src/client/InitPanel.tsx
@@ -5285,6 +5422,9 @@ function InitPanel({ workspace, remote }) {
5285
5422
  }
5286
5423
 
5287
5424
  // src/client/SkillManager.tsx
5425
+ var import_react5 = require("react");
5426
+
5427
+ // src/client/ResourceManager.tsx
5288
5428
  var import_react4 = require("react");
5289
5429
  var import_dsh_client_ui_primitives4 = require("@deepseek-ai/dsh-client-ui-primitives");
5290
5430
 
@@ -5373,23 +5513,49 @@ var footerStyle = {
5373
5513
  flex: "none"
5374
5514
  };
5375
5515
  function ResourceModal({ title, description, onClose, footer, children }) {
5516
+ const dialog = (0, import_react3.useRef)(null);
5517
+ const closer = (0, import_react3.useRef)(onClose);
5518
+ closer.current = onClose;
5376
5519
  (0, import_react3.useEffect)(() => {
5520
+ const previous = document.activeElement;
5521
+ dialog.current?.focus();
5377
5522
  const onKey = (e) => {
5378
- if (e.key === "Escape") onClose();
5523
+ if (!dialog.current?.contains(document.activeElement)) return;
5524
+ if (e.key === "Escape") {
5525
+ e.preventDefault();
5526
+ e.stopPropagation();
5527
+ closer.current();
5528
+ return;
5529
+ }
5530
+ if (e.key !== "Tab") return;
5531
+ const nodes = Array.from(dialog.current.querySelectorAll('button:not(:disabled),input:not(:disabled):not([hidden]),select:not(:disabled),textarea:not(:disabled),[tabindex="0"]')).filter((el) => el.getClientRects().length);
5532
+ const first = nodes[0], last = nodes[nodes.length - 1];
5533
+ if (!first || !last) {
5534
+ e.preventDefault();
5535
+ return;
5536
+ }
5537
+ if (e.shiftKey && (document.activeElement === first || document.activeElement === dialog.current)) {
5538
+ e.preventDefault();
5539
+ last.focus();
5540
+ } else if (!e.shiftKey && (document.activeElement === last || document.activeElement === dialog.current)) {
5541
+ e.preventDefault();
5542
+ first.focus();
5543
+ }
5379
5544
  };
5380
5545
  document.addEventListener("keydown", onKey);
5381
5546
  return () => {
5382
5547
  document.removeEventListener("keydown", onKey);
5548
+ if (previous?.isConnected) previous.focus();
5383
5549
  };
5384
- }, [onClose]);
5550
+ }, []);
5385
5551
  return (0, import_react_dom.createPortal)(
5386
5552
  (0, import_react3.createElement)(
5387
5553
  "div",
5388
- { style: rootStyle, role: "presentation" },
5554
+ { style: rootStyle, className: "te-modal", role: "presentation" },
5389
5555
  (0, import_react3.createElement)("div", { style: maskStyle, "aria-hidden": true, onClick: onClose }),
5390
5556
  (0, import_react3.createElement)(
5391
5557
  "div",
5392
- { style: dialogStyle, role: "dialog", "aria-modal": true, "aria-label": title },
5558
+ { style: dialogStyle, ref: dialog, tabIndex: -1, role: "dialog", "aria-modal": true, "aria-label": title },
5393
5559
  (0, import_react3.createElement)(
5394
5560
  "div",
5395
5561
  { style: headerStyle },
@@ -5409,571 +5575,333 @@ function ResourceModal({ title, description, onClose, footer, children }) {
5409
5575
  );
5410
5576
  }
5411
5577
 
5412
- // src/client/SkillManager.tsx
5413
- var MD_LABELS2 = { code: { copyLabel: "\u590D\u5236", copiedLabel: "\u5DF2\u590D\u5236" }, footnotes: "\u811A\u6CE8" };
5414
- var control = {
5415
- background: "var(--dsw-alias-bg-layer-1)",
5416
- border: "1px solid var(--dsw-alias-border-l2)",
5417
- borderRadius: 8,
5418
- padding: "5px 8px",
5419
- color: "var(--dsw-alias-label-primary)",
5420
- fontSize: 13,
5421
- minWidth: 0
5422
- };
5423
- var card2 = {
5424
- display: "flex",
5425
- flexDirection: "column",
5426
- gap: 8,
5427
- border: "1px solid var(--dsw-alias-border-l2)",
5428
- borderRadius: 8,
5429
- padding: "10px 12px"
5430
- };
5431
- function levelOf(source) {
5432
- if (source === "bundled") return "bundled";
5433
- return source.startsWith("user") ? "user" : "project";
5434
- }
5435
- function SkillManager({ workspace, remote }) {
5436
- const [skills, setSkills] = (0, import_react4.useState)([]);
5578
+ // src/client/ResourceManager.tsx
5579
+ var labels = { code: { copyLabel: "\u590D\u5236", copiedLabel: "\u5DF2\u590D\u5236" }, footnotes: "\u811A\u6CE8" };
5580
+ var levelOf = (row) => row.source === "bundled" ? "bundled" : row.source.startsWith("user") ? "user" : "project";
5581
+ var sourceText2 = (source) => source === "bundled" ? "\u5185\u7F6E" : source.startsWith("user") ? "\u4E2A\u4EBA" : "\u9879\u76EE";
5582
+ var sizeText = (bytes) => bytes < 1024 ? `${bytes} B` : bytes < 1024 * 1024 ? `${(bytes / 1024).toFixed(1)} KB` : `${(bytes / 1024 / 1024).toFixed(1)} MB`;
5583
+ var fail = (r) => describeError(r.error ?? "\u64CD\u4F5C\u5931\u8D25");
5584
+ function ResourceManager({ workspace, remote, kind }) {
5585
+ const noun = kind === "skill" ? "\u6280\u80FD" : "\u89C4\u5219";
5586
+ const [rows, setRows] = (0, import_react4.useState)([]);
5587
+ const [query, setQuery] = (0, import_react4.useState)("");
5588
+ const [filter, setFilter] = (0, import_react4.useState)("all");
5589
+ const [notice, setNotice] = (0, import_react4.useState)("");
5590
+ const [error, setError] = (0, import_react4.useState)("");
5591
+ const [loading, setLoading] = (0, import_react4.useState)(true);
5592
+ const [revision, refresh] = (0, import_react4.useState)(0);
5593
+ const [busy, setBusy] = (0, import_react4.useState)(false);
5594
+ const [roots, setRoots] = (0, import_react4.useState)(null);
5595
+ const [importing, setImporting] = (0, import_react4.useState)(false);
5596
+ const [request, setRequest] = (0, import_react4.useState)(null);
5597
+ const [preview, setPreview] = (0, import_react4.useState)(null);
5437
5598
  const [level, setLevel] = (0, import_react4.useState)("project");
5599
+ const [manual, setManual] = (0, import_react4.useState)(false);
5600
+ const [sourceDir, setSourceDir] = (0, import_react4.useState)("");
5601
+ const [dirs, setDirs] = (0, import_react4.useState)([]);
5602
+ const [browsePath, setBrowsePath] = (0, import_react4.useState)("");
5438
5603
  const [editing, setEditing] = (0, import_react4.useState)(null);
5439
- const [creating, setCreating] = (0, import_react4.useState)(false);
5440
5604
  const [viewing, setViewing] = (0, import_react4.useState)(false);
5441
- const [confirming, setConfirming] = (0, import_react4.useState)(null);
5442
5605
  const [name, setName] = (0, import_react4.useState)("");
5443
5606
  const [description, setDescription] = (0, import_react4.useState)("");
5444
5607
  const [whenToUse, setWhenToUse] = (0, import_react4.useState)("");
5445
5608
  const [body2, setBody] = (0, import_react4.useState)("");
5446
- const [msg, setMsg] = (0, import_react4.useState)("");
5447
- const [installing, setInstalling] = (0, import_react4.useState)(false);
5448
- const [installDir, setInstallDir] = (0, import_react4.useState)("");
5449
- const [installLevel, setInstallLevel] = (0, import_react4.useState)("project");
5450
- const refresh = (0, import_react4.useCallback)(() => {
5451
- void remote.listSkills(workspace).then((r) => {
5452
- if (r.ok) setSkills(r.value.skills);
5609
+ const [deleting, setDeleting] = (0, import_react4.useState)(null);
5610
+ const input = (0, import_react4.useRef)(null);
5611
+ const fileEpoch = (0, import_react4.useRef)(0);
5612
+ const browseEpoch = (0, import_react4.useRef)(0);
5613
+ const readonly = editing !== null && editing !== "new" && levelOf(editing) === "bundled";
5614
+ (0, import_react4.useEffect)(() => {
5615
+ let active = true;
5616
+ setLoading(true);
5617
+ setRows([]);
5618
+ setError("");
5619
+ const run = async () => {
5620
+ try {
5621
+ const r = kind === "skill" ? await remote.listSkills(workspace) : await remote.listRules(workspace);
5622
+ if (!active) return;
5623
+ if (!r.ok) throw new Error(fail(r));
5624
+ setRows("skills" in r.value ? r.value.skills : r.value.rules);
5625
+ } catch (e) {
5626
+ if (active) setError("\u52A0\u8F7D\u5931\u8D25\uFF1A" + describeError(e));
5627
+ } finally {
5628
+ if (active) setLoading(false);
5629
+ }
5630
+ };
5631
+ void run();
5632
+ void remote.resourceRoots({ kind, path: workspace }).then((r) => {
5633
+ if (active && r.ok) setRoots(r.value);
5453
5634
  }, () => {
5454
5635
  });
5455
- }, [remote, workspace]);
5636
+ return () => {
5637
+ active = false;
5638
+ fileEpoch.current++;
5639
+ };
5640
+ }, [workspace, remote, kind, revision]);
5456
5641
  (0, import_react4.useEffect)(() => {
5457
- refresh();
5458
- }, [refresh]);
5459
- const closeForm = () => {
5460
- setEditing(null);
5461
- setCreating(false);
5462
- setViewing(false);
5463
- setName("");
5464
- setDescription("");
5465
- setWhenToUse("");
5466
- setBody("");
5467
- setMsg("");
5468
- };
5469
- const startCreate = () => {
5470
- setEditing(null);
5471
- setCreating(true);
5472
- setViewing(false);
5473
- setInstalling(false);
5474
- setLevel("project");
5475
- setName("");
5476
- setDescription("");
5477
- setWhenToUse("");
5478
- setBody("");
5479
- setMsg("");
5480
- };
5481
- const startInstall = () => {
5642
+ let active = true;
5643
+ setPreview(null);
5644
+ if (!request) return;
5645
+ setBusy(true);
5646
+ setError("");
5647
+ void remote.previewResource({ ...request, level, path: workspace }).then((r) => {
5648
+ if (!active) return;
5649
+ if (!r.ok) setError(fail(r));
5650
+ else if (!r.value.ok) setError(r.value.error ?? "\u9884\u89C8\u5931\u8D25");
5651
+ else setPreview(r.value);
5652
+ }, (e) => {
5653
+ if (active) setError(describeError(e));
5654
+ }).finally(() => {
5655
+ if (active) setBusy(false);
5656
+ });
5657
+ return () => {
5658
+ active = false;
5659
+ };
5660
+ }, [request, level, workspace, remote]);
5661
+ const close = () => {
5662
+ if (busy) return;
5663
+ fileEpoch.current++;
5664
+ setImporting(false);
5482
5665
  setEditing(null);
5483
- setCreating(false);
5484
- setViewing(false);
5485
- setInstalling(true);
5486
- setInstallDir("");
5487
- setInstallLevel("project");
5488
- setMsg("");
5666
+ setDeleting(null);
5667
+ setRequest(null);
5668
+ setError("");
5489
5669
  };
5490
- const submitInstall = async () => {
5491
- setMsg("");
5492
- const result = await remote.installSkill({
5493
- sourceDir: installDir,
5494
- level: installLevel,
5495
- path: installLevel === "project" ? workspace : void 0
5496
- });
5497
- if (!result.ok) {
5498
- setMsg("\u5B89\u88C5\u5931\u8D25\uFF1A" + describeError(result.error));
5499
- return;
5500
- }
5501
- if (!result.value.ok) {
5502
- setMsg("\u5B89\u88C5\u5931\u8D25\uFF1A" + (result.value.error ?? "\u672A\u77E5\u9519\u8BEF"));
5503
- return;
5670
+ const choose = () => {
5671
+ setError("");
5672
+ if (input.current) {
5673
+ input.current.value = "";
5674
+ input.current.click();
5504
5675
  }
5505
- setMsg(`\u5DF2\u5B89\u88C5 skill\u300C${result.value.name}\u300D\u2192 ${result.value.path}`);
5506
- setInstalling(false);
5507
- refresh();
5508
5676
  };
5509
- const loadSkill = (skillName, lvl) => {
5510
- setMsg("");
5511
- void remote.readSkill({ name: skillName, level: lvl, path: workspace }).then((r) => {
5512
- if (r.ok && r.value.ok) {
5513
- setName(r.value.name);
5514
- setDescription(r.value.description);
5515
- setWhenToUse(r.value.whenToUse);
5516
- setBody(r.value.content);
5517
- } else {
5518
- setMsg("\u8BFB\u53D6\u5931\u8D25\uFF1A" + (r.ok ? r.value.error ?? "\u672A\u77E5\u9519\u8BEF" : describeError(r.error)));
5677
+ const selected = async (files) => {
5678
+ if (!files.length) return;
5679
+ const epoch = ++fileEpoch.current;
5680
+ setImporting(true);
5681
+ setManual(false);
5682
+ setRequest(null);
5683
+ setPreview(null);
5684
+ setBusy(true);
5685
+ setError("");
5686
+ setNotice("");
5687
+ try {
5688
+ files = files.filter((f) => !(f.webkitRelativePath || f.name).split("/").some((p) => ["node_modules", ".git", "__pycache__", ".venv", "venv", ".cache", ".DS_Store"].includes(p)));
5689
+ if (!files.length || files.length > 1e3 || files.reduce((n, f) => n + f.size, 0) > 100 * 1024 * 1024 || files.some((f) => f.size > 20 * 1024 * 1024)) throw new Error("\u8BF7\u9009\u62E9\u4E0D\u8D85\u8FC7 1000 \u4E2A\u6587\u4EF6 / 100 MB \u7684\u6280\u80FD\u5305\uFF0C\u5355\u6587\u4EF6\u4E0D\u8D85\u8FC7 20 MB");
5690
+ const entries = [];
5691
+ for (const file of files) {
5692
+ const data = new Uint8Array(await file.arrayBuffer());
5693
+ let binary = "";
5694
+ for (let i = 0; i < data.length; i += 32768) binary += String.fromCharCode(...data.subarray(i, i + 32768));
5695
+ entries.push({ path: file.webkitRelativePath || file.name, base64: btoa(binary) });
5519
5696
  }
5520
- });
5521
- };
5522
- const startEdit = (sk) => {
5523
- const lvl = levelOf(sk.source);
5524
- setEditing(sk.name);
5525
- setCreating(false);
5526
- setViewing(false);
5527
- setLevel(lvl === "user" ? "user" : "project");
5528
- loadSkill(sk.name, lvl);
5529
- };
5530
- const startView = (sk) => {
5531
- setEditing(sk.name);
5532
- setCreating(false);
5533
- setViewing(true);
5534
- loadSkill(sk.name, "bundled");
5535
- };
5536
- const submit = async () => {
5537
- setMsg("");
5538
- const target = editing ?? name;
5539
- const result = await remote.writeSkill({
5540
- name: target,
5541
- description,
5542
- whenToUse: whenToUse.trim() === "" ? void 0 : whenToUse,
5543
- content: body2,
5544
- level,
5545
- path: level === "project" ? workspace : void 0
5546
- });
5547
- if (!result.ok) {
5548
- setMsg("\u4FDD\u5B58\u5931\u8D25\uFF1A" + describeError(result.error));
5549
- return;
5550
- }
5551
- if (!result.value.ok) {
5552
- setMsg("\u4FDD\u5B58\u5931\u8D25\uFF1A" + (result.value.error ?? "\u672A\u77E5\u9519\u8BEF"));
5553
- return;
5697
+ if (epoch === fileEpoch.current) setRequest({ kind, level, path: workspace, files: entries });
5698
+ } catch (e) {
5699
+ if (epoch === fileEpoch.current) setError(describeError(e));
5700
+ } finally {
5701
+ if (epoch === fileEpoch.current) setBusy(false);
5554
5702
  }
5555
- setMsg(`\u5DF2\u4FDD\u5B58 skill\u300C${result.value.name}\u300D`);
5556
- setEditing(null);
5557
- setCreating(false);
5558
- refresh();
5559
5703
  };
5560
- const remove = async (sk) => {
5561
- setMsg("");
5562
- const lvl = levelOf(sk.source);
5563
- if (lvl === "bundled") return;
5564
- const result = await remote.deleteSkill({ name: sk.name, level: lvl, path: workspace });
5565
- if (!result.ok) {
5566
- setMsg("\u5220\u9664\u5931\u8D25\uFF1A" + describeError(result.error));
5567
- setConfirming(null);
5568
- return;
5569
- }
5570
- if (!result.value.ok) {
5571
- setMsg("\u5220\u9664\u5931\u8D25\uFF1A" + (result.value.error ?? "\u672A\u77E5\u9519\u8BEF"));
5572
- setConfirming(null);
5573
- return;
5704
+ const install = async () => {
5705
+ if (!request || !preview || preview.conflict || busy) return;
5706
+ setBusy(true);
5707
+ setError("");
5708
+ try {
5709
+ const r = await remote.importResource({ ...request, level, path: workspace, expectedHash: preview.hash });
5710
+ if (!r.ok) throw new Error(fail(r));
5711
+ if (!r.value.ok) throw new Error(r.value.error ?? "\u5B89\u88C5\u5931\u8D25");
5712
+ setNotice(`\u5DF2\u5B89\u88C5${noun}\u300C${r.value.name}\u300D \xB7 ${r.value.target}`);
5713
+ setImporting(false);
5714
+ setRequest(null);
5715
+ refresh((n) => n + 1);
5716
+ } catch (e) {
5717
+ setError(describeError(e));
5718
+ } finally {
5719
+ setBusy(false);
5574
5720
  }
5575
- setMsg(`\u5DF2\u5220\u9664 skill\u300C${result.value.name}\u300D`);
5576
- if (editing === sk.name) setEditing(null);
5577
- setConfirming(null);
5578
- refresh();
5579
5721
  };
5580
- const formOpen = editing !== null || creating || installing;
5581
- const renderRow = (sk) => (0, import_react4.createElement)(
5582
- "div",
5583
- {
5584
- key: sk.name,
5585
- style: { display: "flex", alignItems: "center", gap: 8, justifyContent: "space-between", padding: "6px 0", borderBottom: "1px solid var(--dsw-alias-border-l2)" }
5586
- },
5587
- (0, import_react4.createElement)(
5588
- "div",
5589
- { style: { display: "flex", flexDirection: "column", gap: 2, minWidth: 0 } },
5590
- (0, import_react4.createElement)(
5591
- "span",
5592
- { style: { fontSize: 13, color: "var(--dsw-alias-label-primary)" } },
5593
- sk.name,
5594
- sk.source !== "bundled" ? (0, import_react4.createElement)("span", { style: styles.sourceBadge }, `\uFF08${sourceLabel(sk.source)}\uFF09`) : null
5595
- ),
5596
- (0, import_react4.createElement)("span", { style: styles.sourceBadge }, sk.description)
5597
- ),
5598
- sk.source === "bundled" ? (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "outline", size: "sm", onClick: () => {
5599
- startView(sk);
5600
- } }, "\u67E5\u770B") : (0, import_react4.createElement)(
5601
- "div",
5602
- { style: { display: "flex", gap: 6 } },
5603
- (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "outline", size: "sm", onClick: () => {
5604
- startEdit(sk);
5605
- } }, "\u7F16\u8F91"),
5606
- confirming === sk.name ? (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "primary", size: "sm", onClick: () => {
5607
- void remove(sk);
5608
- } }, "\u786E\u8BA4\u5220\u9664") : (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "ghost", size: "sm", onClick: () => {
5609
- setConfirming(sk.name);
5610
- } }, "\u5220\u9664")
5611
- )
5612
- );
5613
- const renderForm = () => {
5614
- if (viewing) {
5615
- return (0, import_react4.createElement)(
5616
- ResourceModal,
5617
- {
5618
- title: `\u67E5\u770B skill\u300C${editing ?? ""}\u300D`,
5619
- description: "\u5185\u7F6E \xB7 \u53EA\u8BFB" + (whenToUse !== "" && whenToUse !== void 0 ? ` \xB7 \u4F7F\u7528\u65F6\u673A\uFF1A${whenToUse}` : ""),
5620
- onClose: closeForm,
5621
- footer: (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "ghost", size: "sm", onClick: closeForm }, "\u5173\u95ED")
5622
- },
5623
- (0, import_react4.createElement)(import_dsh_client_ui_primitives4.MarkdownText, { text: body2, labels: MD_LABELS2 })
5624
- );
5722
+ const browse = async (path) => {
5723
+ const epoch = ++browseEpoch.current;
5724
+ setError("");
5725
+ try {
5726
+ const r = await remote.listDirs({ path });
5727
+ if (epoch !== browseEpoch.current) return;
5728
+ if (!r.ok) throw new Error(fail(r));
5729
+ if (!r.value.ok) throw new Error(r.value.error ?? "\u76EE\u5F55\u8BFB\u53D6\u5931\u8D25");
5730
+ setBrowsePath(r.value.path);
5731
+ setSourceDir(r.value.path);
5732
+ setDirs(r.value.entries);
5733
+ } catch (e) {
5734
+ if (epoch === browseEpoch.current) setError(describeError(e));
5625
5735
  }
5626
- return (0, import_react4.createElement)(
5627
- ResourceModal,
5628
- {
5629
- title: editing === null ? "\u65B0\u5EFA skill" : `\u7F16\u8F91 skill\u300C${editing ?? ""}\u300D`,
5630
- onClose: closeForm,
5631
- footer: (0, import_react4.createElement)(
5632
- "div",
5633
- { style: styles.row },
5634
- (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, {
5635
- variant: "primary",
5636
- size: "sm",
5637
- disabled: editing === null && name.trim() === "" || description.trim() === "" || body2.trim() === "",
5638
- onClick: () => {
5639
- void submit();
5640
- }
5641
- }, "\u4FDD\u5B58"),
5642
- (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "ghost", size: "sm", onClick: closeForm }, "\u53D6\u6D88")
5643
- )
5644
- },
5645
- (0, import_react4.createElement)(
5646
- "div",
5647
- { style: styles.chips },
5648
- (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Pill, { active: level === "project", onClick: () => {
5649
- setLevel("project");
5650
- }, title: "\u5199\u5230\u5DE5\u4F5C\u533A .dsh/skills\uFF0C\u56E2\u961F\u5171\u4EAB" }, "\u9879\u76EE\u7EA7"),
5651
- (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Pill, { active: level === "user", onClick: () => {
5652
- setLevel("user");
5653
- }, title: "\u5199\u5230 $DSH_HOME/skills\uFF0C\u4E2A\u4EBA\u6240\u6709\u9879\u76EE\u53EF\u7528" }, "\u7528\u6237\u7EA7")
5654
- ),
5655
- editing === null ? (0, import_react4.createElement)("input", { style: control, placeholder: "name\uFF08\u5982 my-skill\uFF0C\u53EA\u542B\u5C0F\u5199\u5B57\u6BCD\u6570\u5B57\u548C -\uFF09", value: name, onChange: (ev) => {
5656
- setName(ev.target.value);
5657
- } }) : (0, import_react4.createElement)("span", { style: styles.sourceBadge }, `name \u56FA\u5B9A\u4E3A ${name}\uFF08\u6539\u540D\u8BF7\u5220\u9664\u540E\u91CD\u5EFA\uFF09`),
5658
- (0, import_react4.createElement)("input", { style: control, placeholder: "description\uFF08\u4E00\u53E5\u8BDD\u8BF4\u660E\u5B83\u505A\u4EC0\u4E48\uFF09", value: description, onChange: (ev) => {
5659
- setDescription(ev.target.value);
5660
- } }),
5661
- (0, import_react4.createElement)("input", { style: control, placeholder: "whenToUse\uFF08\u53EF\u9009\uFF1A\u4EC0\u4E48\u60C5\u51B5\u8BE5\u7528\uFF09", value: whenToUse, onChange: (ev) => {
5662
- setWhenToUse(ev.target.value);
5663
- } }),
5664
- (0, import_react4.createElement)("textarea", { style: { ...styles.textarea, minHeight: 300 }, placeholder: "\u6B63\u6587\uFF08\u544A\u8BC9\u5927\u6A21\u578B\u8FD9\u4E2A\u9636\u6BB5\u600E\u4E48\u5E72\uFF09", value: body2, onChange: (ev) => {
5665
- setBody(ev.target.value);
5666
- } }),
5667
- msg !== "" ? (0, import_react4.createElement)("p", { style: styles.status }, msg) : null
5668
- );
5669
- };
5670
- const renderInstallForm = () => (0, import_react4.createElement)(
5671
- ResourceModal,
5672
- {
5673
- title: "\u5B89\u88C5\u73B0\u6709 skill\uFF08\u76EE\u5F55\u578B\uFF09",
5674
- description: "\u628A\u4E00\u4E2A\u672C\u673A\u5DF2\u6709\u7684 skill \u76EE\u5F55\uFF08\u542B SKILL.md\uFF0C\u53EF\u5E26 references / scripts \u7B49\u6587\u4EF6\uFF09\u5B89\u88C5\u5230\u9879\u76EE\u7EA7\u6216\u7528\u6237\u7EA7\u3002",
5675
- onClose: () => {
5676
- setInstalling(false);
5677
- setMsg("");
5678
- },
5679
- footer: (0, import_react4.createElement)(
5680
- "div",
5681
- { style: styles.row },
5682
- (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, {
5683
- variant: "primary",
5684
- size: "sm",
5685
- disabled: installDir.trim() === "",
5686
- onClick: () => {
5687
- void submitInstall();
5688
- }
5689
- }, "\u5B89\u88C5"),
5690
- (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "ghost", size: "sm", onClick: () => {
5691
- setInstalling(false);
5692
- setMsg("");
5693
- } }, "\u53D6\u6D88")
5694
- )
5695
- },
5696
- (0, import_react4.createElement)(
5697
- "div",
5698
- { style: styles.chips },
5699
- (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Pill, { active: installLevel === "project", onClick: () => {
5700
- setInstallLevel("project");
5701
- }, title: "\u88C5\u5230\u5DE5\u4F5C\u533A .dsh/skills\uFF0C\u56E2\u961F\u5171\u4EAB" }, "\u9879\u76EE\u7EA7"),
5702
- (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Pill, { active: installLevel === "user", onClick: () => {
5703
- setInstallLevel("user");
5704
- }, title: "\u88C5\u5230 $DSH_HOME/skills\uFF0C\u4E2A\u4EBA\u6240\u6709\u9879\u76EE\u53EF\u7528" }, "\u7528\u6237\u7EA7")
5705
- ),
5706
- (0, import_react4.createElement)("input", {
5707
- style: control,
5708
- placeholder: "\u6E90\u76EE\u5F55\u7EDD\u5BF9\u8DEF\u5F84\uFF08\u672C\u673A skill \u76EE\u5F55\uFF0C\u9700\u542B SKILL.md\uFF09",
5709
- value: installDir,
5710
- onChange: (ev) => {
5711
- setInstallDir(ev.target.value);
5712
- }
5713
- }),
5714
- (0, import_react4.createElement)("p", { style: styles.hint }, "\u8981\u6C42\uFF1A\u76EE\u5F55\u5185\u6709 SKILL.md\uFF08frontmatter \u542B name + description\uFF09\u3002\u5B89\u88C5\u4F1A\u590D\u5236\u6574\u4E2A\u76EE\u5F55\uFF08\u81EA\u52A8\u6392\u9664 node_modules / .git \u7B49\u7F13\u5B58\uFF09\uFF0C\u540C\u540D\u5185\u7F6E\u6280\u80FD\u62D2\u7EDD\u8986\u76D6\uFF0C\u540C\u540D\u5DF2\u88C5\u6280\u80FD\u9700\u5148\u5220\u9664\u3002"),
5715
- msg !== "" ? (0, import_react4.createElement)("p", { style: styles.status }, msg) : null
5716
- );
5717
- return (0, import_react4.createElement)(
5718
- "div",
5719
- { style: styles.section },
5720
- (0, import_react4.createElement)(
5721
- "div",
5722
- { style: card2 },
5723
- (0, import_react4.createElement)(
5724
- "div",
5725
- { style: styles.bindingStage },
5726
- (0, import_react4.createElement)("span", { style: styles.bindingLabel }, "\u5DF2\u5B89\u88C5\u7684 skill"),
5727
- skills.length === 0 ? (0, import_react4.createElement)("p", { style: styles.muted }, "\u6682\u65E0 skill\uFF0C\u70B9\u4E0B\u65B9\u300C\u65B0\u5EFA skill\u300D\u521B\u5EFA\uFF0C\u6216\u300C\u5B89\u88C5 skill\u300D\u5BFC\u5165\u672C\u673A\u5DF2\u6709\u7684 skill \u76EE\u5F55\u3002") : (0, import_react4.createElement)(
5728
- "div",
5729
- { style: styles.section },
5730
- ...skills.map(renderRow)
5731
- )
5732
- ),
5733
- (0, import_react4.createElement)(
5734
- "div",
5735
- { style: styles.row },
5736
- (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "outline", size: "md", onClick: startCreate }, "\u65B0\u5EFA skill"),
5737
- (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "outline", size: "md", onClick: startInstall }, "\u5B89\u88C5 skill")
5738
- )
5739
- ),
5740
- installing ? renderInstallForm() : null,
5741
- formOpen && !installing ? renderForm() : null
5742
- );
5743
- }
5744
-
5745
- // src/client/RuleManager.tsx
5746
- var import_react5 = require("react");
5747
- var import_dsh_client_ui_primitives5 = require("@deepseek-ai/dsh-client-ui-primitives");
5748
- var MD_LABELS3 = { code: { copyLabel: "\u590D\u5236", copiedLabel: "\u5DF2\u590D\u5236" }, footnotes: "\u811A\u6CE8" };
5749
- var control2 = {
5750
- background: "var(--dsw-alias-bg-layer-1)",
5751
- border: "1px solid var(--dsw-alias-border-l2)",
5752
- borderRadius: 8,
5753
- padding: "5px 8px",
5754
- color: "var(--dsw-alias-label-primary)",
5755
- fontSize: 13,
5756
- minWidth: 0
5757
- };
5758
- var card3 = {
5759
- display: "flex",
5760
- flexDirection: "column",
5761
- gap: 8,
5762
- border: "1px solid var(--dsw-alias-border-l2)",
5763
- borderRadius: 8,
5764
- padding: "10px 12px"
5765
- };
5766
- function levelOf2(source) {
5767
- if (source === "bundled") return "bundled";
5768
- return source.startsWith("user") ? "user" : "project";
5769
- }
5770
- function RuleManager({ workspace, remote }) {
5771
- const [rules, setRules] = (0, import_react5.useState)([]);
5772
- const [level, setLevel] = (0, import_react5.useState)("project");
5773
- const [editing, setEditing] = (0, import_react5.useState)(null);
5774
- const [creating, setCreating] = (0, import_react5.useState)(false);
5775
- const [viewing, setViewing] = (0, import_react5.useState)(false);
5776
- const [confirming, setConfirming] = (0, import_react5.useState)(null);
5777
- const [name, setName] = (0, import_react5.useState)("");
5778
- const [body2, setBody] = (0, import_react5.useState)("");
5779
- const [msg, setMsg] = (0, import_react5.useState)("");
5780
- const refresh = (0, import_react5.useCallback)(() => {
5781
- void remote.listRules(workspace).then((r) => {
5782
- if (r.ok) setRules(r.value.rules);
5783
- }, () => {
5784
- });
5785
- }, [remote, workspace]);
5786
- (0, import_react5.useEffect)(() => {
5787
- refresh();
5788
- }, [refresh]);
5789
- const closeForm = () => {
5790
- setEditing(null);
5791
- setCreating(false);
5792
- setViewing(false);
5793
- setName("");
5794
- setBody("");
5795
- setMsg("");
5796
5736
  };
5797
- const startCreate = () => {
5798
- setEditing(null);
5799
- setCreating(true);
5800
- setViewing(false);
5801
- setLevel("project");
5802
- setName("");
5737
+ const edit = async (row, view = false) => {
5738
+ setEditing(row);
5739
+ setViewing(view);
5740
+ setName(row === "new" ? "" : row.name);
5741
+ setDescription("");
5742
+ setWhenToUse("");
5803
5743
  setBody("");
5804
- setMsg("");
5805
- };
5806
- const loadRule = (ruleName, lvl) => {
5807
- setMsg("");
5808
- void remote.readRule({ name: ruleName, level: lvl, path: workspace }).then((r) => {
5809
- if (r.ok && r.value.ok) {
5810
- setName(r.value.name);
5811
- setBody(r.value.content);
5812
- } else {
5813
- setMsg("\u8BFB\u53D6\u5931\u8D25\uFF1A" + (r.ok ? r.value.error ?? "\u672A\u77E5\u9519\u8BEF" : describeError(r.error)));
5814
- }
5815
- });
5816
- };
5817
- const startEdit = (rule) => {
5818
- const lvl = levelOf2(rule.source);
5819
- setEditing(rule.name);
5820
- setCreating(false);
5821
- setViewing(false);
5822
- setLevel(lvl === "user" ? "user" : "project");
5823
- loadRule(rule.name, lvl);
5824
- };
5825
- const startView = (rule) => {
5826
- setEditing(rule.name);
5827
- setCreating(false);
5828
- setViewing(true);
5829
- loadRule(rule.name, "bundled");
5830
- };
5831
- const submit = async () => {
5832
- setMsg("");
5833
- const result = await remote.writeRule({
5834
- name: editing ?? name,
5835
- content: body2,
5836
- level,
5837
- path: level === "project" ? workspace : void 0
5838
- });
5839
- if (!result.ok) {
5840
- setMsg("\u4FDD\u5B58\u5931\u8D25\uFF1A" + describeError(result.error));
5744
+ setError("");
5745
+ if (row === "new") {
5746
+ setLevel("project");
5841
5747
  return;
5842
5748
  }
5843
- if (!result.value.ok) {
5844
- setMsg("\u4FDD\u5B58\u5931\u8D25\uFF1A" + (result.value.error ?? "\u672A\u77E5\u9519\u8BEF"));
5845
- return;
5749
+ const lvl = levelOf(row);
5750
+ setLevel(lvl === "user" ? "user" : "project");
5751
+ setBusy(true);
5752
+ try {
5753
+ const r = kind === "skill" ? await remote.readSkill({ name: row.name, level: lvl, path: workspace }) : await remote.readRule({ name: row.name, level: lvl, path: workspace });
5754
+ if (!r.ok) throw new Error(fail(r));
5755
+ if (!r.value.ok) throw new Error(r.value.error ?? "\u8BFB\u53D6\u5931\u8D25");
5756
+ setBody(r.value.content);
5757
+ if (kind === "skill") {
5758
+ const skill = r.value;
5759
+ setDescription(skill.description);
5760
+ setWhenToUse(skill.whenToUse);
5761
+ }
5762
+ } catch (e) {
5763
+ setError(describeError(e));
5764
+ } finally {
5765
+ setBusy(false);
5846
5766
  }
5847
- setMsg(`\u5DF2\u4FDD\u5B58 rule\u300C${result.value.name}\u300D`);
5848
- setEditing(null);
5849
- setCreating(false);
5850
- refresh();
5851
5767
  };
5852
- const remove = async (rule) => {
5853
- setMsg("");
5854
- const lvl = levelOf2(rule.source);
5855
- if (lvl === "bundled") return;
5856
- const result = await remote.deleteRule({ name: rule.name, level: lvl, path: workspace });
5857
- if (!result.ok) {
5858
- setMsg("\u5220\u9664\u5931\u8D25\uFF1A" + describeError(result.error));
5859
- setConfirming(null);
5860
- return;
5768
+ const save2 = async () => {
5769
+ if (busy) return;
5770
+ setBusy(true);
5771
+ setError("");
5772
+ try {
5773
+ if (editing === "new" && rows.some((r2) => r2.name === name && (levelOf(r2) === level || levelOf(r2) === "bundled"))) throw new Error("\u540C\u540D\u8D44\u6E90\u5DF2\u5B58\u5728\uFF0C\u8BF7\u6362\u540D\u6216\u7F16\u8F91\u73B0\u6709\u8D44\u6E90");
5774
+ const r = kind === "skill" ? await remote.writeSkill({ name, description, whenToUse, content: body2, level, path: workspace }) : await remote.writeRule({ name, content: body2, level, path: workspace });
5775
+ if (!r.ok) throw new Error(fail(r));
5776
+ if (!r.value.ok) throw new Error(r.value.error ?? "\u4FDD\u5B58\u5931\u8D25");
5777
+ setNotice(`\u5DF2\u4FDD\u5B58${noun} \xB7 ${r.value.path}`);
5778
+ setEditing(null);
5779
+ refresh((n) => n + 1);
5780
+ } catch (e) {
5781
+ setError(describeError(e));
5782
+ } finally {
5783
+ setBusy(false);
5861
5784
  }
5862
- if (!result.value.ok) {
5863
- setMsg("\u5220\u9664\u5931\u8D25\uFF1A" + (result.value.error ?? "\u672A\u77E5\u9519\u8BEF"));
5864
- setConfirming(null);
5865
- return;
5785
+ };
5786
+ const remove = async () => {
5787
+ if (!deleting || busy) return;
5788
+ const lvl = levelOf(deleting);
5789
+ if (lvl === "bundled") return;
5790
+ setBusy(true);
5791
+ setError("");
5792
+ try {
5793
+ const r = kind === "skill" ? await remote.deleteSkill({ name: deleting.name, level: lvl, path: workspace }) : await remote.deleteRule({ name: deleting.name, level: lvl, path: workspace });
5794
+ if (!r.ok) throw new Error(fail(r));
5795
+ if (!r.value.ok) throw new Error(r.value.error ?? "\u5220\u9664\u5931\u8D25");
5796
+ setNotice(`\u5DF2\u5220\u9664${noun}\u300C${deleting.name}\u300D`);
5797
+ setDeleting(null);
5798
+ refresh((n) => n + 1);
5799
+ } catch (e) {
5800
+ setError(describeError(e));
5801
+ } finally {
5802
+ setBusy(false);
5866
5803
  }
5867
- setMsg(`\u5DF2\u5220\u9664 rule\u300C${result.value.name}\u300D`);
5868
- if (editing === rule.name) setEditing(null);
5869
- setConfirming(null);
5870
- refresh();
5871
5804
  };
5872
- const formOpen = editing !== null || creating;
5873
- const renderRow = (rule) => (0, import_react5.createElement)(
5805
+ const status = () => error ? (0, import_react4.createElement)("div", { className: "te-alert", role: "alert" }, error) : null;
5806
+ const targets = () => (0, import_react4.createElement)(
5874
5807
  "div",
5875
- {
5876
- key: rule.name,
5877
- style: { display: "flex", alignItems: "center", gap: 8, justifyContent: "space-between", padding: "6px 0", borderBottom: "1px solid var(--dsw-alias-border-l2)" }
5878
- },
5879
- (0, import_react5.createElement)(
5880
- "span",
5881
- { style: { fontSize: 13, color: "var(--dsw-alias-label-primary)" } },
5882
- rule.name,
5883
- rule.source !== "bundled" ? (0, import_react5.createElement)("span", { style: styles.sourceBadge }, `\uFF08${sourceLabel(rule.source)}\uFF09`) : null
5884
- ),
5885
- rule.source === "bundled" ? (0, import_react5.createElement)(import_dsh_client_ui_primitives5.Button, { variant: "outline", size: "sm", onClick: () => {
5886
- startView(rule);
5887
- } }, "\u67E5\u770B") : (0, import_react5.createElement)(
5888
- "div",
5889
- { style: { display: "flex", gap: 6 } },
5890
- (0, import_react5.createElement)(import_dsh_client_ui_primitives5.Button, { variant: "outline", size: "sm", onClick: () => {
5891
- startEdit(rule);
5892
- } }, "\u7F16\u8F91"),
5893
- confirming === rule.name ? (0, import_react5.createElement)(import_dsh_client_ui_primitives5.Button, { variant: "primary", size: "sm", onClick: () => {
5894
- void remove(rule);
5895
- } }, "\u786E\u8BA4\u5220\u9664") : (0, import_react5.createElement)(import_dsh_client_ui_primitives5.Button, { variant: "ghost", size: "sm", onClick: () => {
5896
- setConfirming(rule.name);
5897
- } }, "\u5220\u9664")
5898
- )
5808
+ { className: "te-targets" },
5809
+ ...["project", "user"].map((lvl) => (0, import_react4.createElement)(
5810
+ "button",
5811
+ { type: "button", key: lvl, className: `te-target ${level === lvl ? "selected" : ""}`, "aria-pressed": level === lvl, disabled: busy || editing !== null && editing !== "new", onClick: () => {
5812
+ setPreview(null);
5813
+ setLevel(lvl);
5814
+ } },
5815
+ (0, import_react4.createElement)("strong", null, lvl === "project" ? "\u9879\u76EE\u5171\u4EAB" : "\u4E2A\u4EBA\u5168\u5C40"),
5816
+ (0, import_react4.createElement)("small", null, lvl === "project" ? "\u4EC5\u5F53\u524D\u5DE5\u4F5C\u533A\u4F7F\u7528" : "\u6B64\u4E3B\u673A\u4E0A\u7684\u6240\u6709\u9879\u76EE\u53EF\u7528")
5817
+ )),
5818
+ (0, import_react4.createElement)("code", { className: "te-path" }, roots?.[level] ?? (level === "project" ? `${workspace}/.dsh/${kind}s` : `DSH_HOME/${kind}s`))
5899
5819
  );
5900
- const renderForm = () => {
5901
- if (viewing) {
5902
- return (0, import_react5.createElement)(
5903
- ResourceModal,
5904
- {
5905
- title: `\u67E5\u770B rule\u300C${editing ?? ""}\u300D`,
5906
- description: "\u5185\u7F6E \xB7 \u53EA\u8BFB",
5907
- onClose: closeForm,
5908
- footer: (0, import_react5.createElement)(import_dsh_client_ui_primitives5.Button, { variant: "ghost", size: "sm", onClick: closeForm }, "\u5173\u95ED")
5909
- },
5910
- (0, import_react5.createElement)(import_dsh_client_ui_primitives5.MarkdownText, { text: body2, labels: MD_LABELS3 })
5911
- );
5912
- }
5913
- return (0, import_react5.createElement)(
5820
+ const visible = rows.filter((r) => `${r.name} ${r.description ?? ""}`.toLowerCase().includes(query.toLowerCase()) && (filter === "all" || levelOf(r) === filter));
5821
+ return (0, import_react4.createElement)(
5822
+ "section",
5823
+ { className: "te-resource" },
5824
+ (0, import_react4.createElement)("input", { type: "file", ref: input, hidden: true, "aria-label": kind === "skill" ? "\u9009\u62E9\u6280\u80FD\u6587\u4EF6\u5939" : "\u9009\u62E9\u89C4\u5219\u6587\u4EF6", ...kind === "skill" ? { webkitdirectory: "", multiple: true } : { accept: ".md,text/markdown" }, onChange: (e) => {
5825
+ void selected(Array.from(e.target.files ?? []));
5826
+ } }),
5827
+ (0, import_react4.createElement)("div", { className: "te-section-heading" }, (0, import_react4.createElement)("div", null, (0, import_react4.createElement)("h2", null, `${noun}\u5E93`), (0, import_react4.createElement)("p", null, kind === "skill" ? "\u628A\u53EF\u590D\u7528\u7684\u5DE5\u4F5C\u65B9\u6CD5\u5E26\u5165\u9879\u76EE\u3002" : "\u4E3A\u9879\u76EE\u660E\u786E\u7EA6\u5B9A\uFF0C\u8BA9\u6BCF\u6B21\u4EA4\u4ED8\u4FDD\u6301\u4E00\u81F4\u3002")), (0, import_react4.createElement)("div", { className: "te-actions" }, (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "outline", onClick: () => {
5828
+ void edit("new");
5829
+ } }, `\u65B0\u5EFA${noun}`), (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "primary", onClick: choose }, `\u5B89\u88C5${noun}`))),
5830
+ (0, import_react4.createElement)("div", { className: "te-toolbar" }, (0, import_react4.createElement)("input", { className: "te-input", placeholder: `\u641C\u7D22${noun}\u540D\u79F0${kind === "skill" ? "\u6216\u63CF\u8FF0" : ""}`, value: query, onChange: (e) => setQuery(e.target.value) }), (0, import_react4.createElement)("select", { className: "te-input", "aria-label": "\u7B5B\u9009\u6765\u6E90", value: filter, onChange: (e) => setFilter(e.target.value) }, (0, import_react4.createElement)("option", { value: "all" }, `\u5168\u90E8\u6765\u6E90 \xB7 ${rows.length}`), (0, import_react4.createElement)("option", { value: "bundled" }, "\u5185\u7F6E"), (0, import_react4.createElement)("option", { value: "project" }, "\u9879\u76EE"), (0, import_react4.createElement)("option", { value: "user" }, "\u4E2A\u4EBA")), (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "ghost", onClick: () => refresh((n) => n + 1), disabled: loading }, "\u5237\u65B0")),
5831
+ notice ? (0, import_react4.createElement)("div", { className: "te-success", role: "status" }, notice) : null,
5832
+ !importing && !editing && !deleting ? status() : null,
5833
+ loading ? (0, import_react4.createElement)("div", { className: "te-empty", role: "status" }, "\u6B63\u5728\u52A0\u8F7D\u2026") : visible.length === 0 ? (0, import_react4.createElement)("div", { className: "te-empty" }, (0, import_react4.createElement)("h3", null, query || filter !== "all" ? "\u6CA1\u6709\u5339\u914D\u7684\u7ED3\u679C" : `\u8FD8\u6CA1\u6709${noun}`), (0, import_react4.createElement)("p", null, "\u8C03\u6574\u7B5B\u9009\uFF0C\u6216\u4F7F\u7528\u53F3\u4E0A\u89D2\u6309\u94AE\u6DFB\u52A0\u3002")) : (0, import_react4.createElement)("div", { className: "te-resource-grid" }, ...visible.map((row) => (0, import_react4.createElement)(
5834
+ "article",
5835
+ { className: "te-resource-card", key: row.source + "/" + row.name },
5836
+ (0, import_react4.createElement)("div", { className: "te-card-top" }, (0, import_react4.createElement)("span", { className: "te-resource-icon", "aria-hidden": true }, kind === "skill" ? "\u25C7" : "\u2261"), (0, import_react4.createElement)("span", { className: "te-badge" }, sourceText2(row.source))),
5837
+ (0, import_react4.createElement)("h3", null, row.name),
5838
+ (0, import_react4.createElement)("p", null, row.description || "\u9879\u76EE\u7EA6\u5B9A\u4E0E\u6267\u884C\u89C4\u5219"),
5839
+ (0, import_react4.createElement)("div", { className: "te-actions" }, (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "outline", size: "sm", onClick: () => {
5840
+ void edit(row, true);
5841
+ } }, "\u67E5\u770B"), levelOf(row) !== "bundled" ? (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "ghost", size: "sm", onClick: () => {
5842
+ void edit(row);
5843
+ } }, "\u7F16\u8F91") : null, levelOf(row) !== "bundled" ? (0, import_react4.createElement)("button", { className: "te-delete", onClick: () => {
5844
+ setDeleting(row);
5845
+ setError("");
5846
+ } }, "\u5220\u9664") : null)
5847
+ ))),
5848
+ kind === "skill" ? (0, import_react4.createElement)("button", { className: "te-link", onClick: () => {
5849
+ setImporting(true);
5850
+ setManual(true);
5851
+ setError("");
5852
+ } }, "\u9AD8\u7EA7\uFF1A\u4ECE Harness \u4E3B\u673A\u8DEF\u5F84\u5B89\u88C5") : null,
5853
+ importing ? (0, import_react4.createElement)(
5914
5854
  ResourceModal,
5915
- {
5916
- title: editing === null ? "\u65B0\u5EFA rule" : `\u7F16\u8F91 rule\u300C${editing ?? ""}\u300D`,
5917
- onClose: closeForm,
5918
- footer: (0, import_react5.createElement)(
5919
- "div",
5920
- { style: styles.row },
5921
- (0, import_react5.createElement)(import_dsh_client_ui_primitives5.Button, {
5922
- variant: "primary",
5923
- size: "sm",
5924
- disabled: editing === null && name.trim() === "" || body2.trim() === "",
5925
- onClick: () => {
5926
- void submit();
5927
- }
5928
- }, "\u4FDD\u5B58"),
5929
- (0, import_react5.createElement)(import_dsh_client_ui_primitives5.Button, { variant: "ghost", size: "sm", onClick: closeForm }, "\u53D6\u6D88")
5930
- )
5931
- },
5932
- (0, import_react5.createElement)(
5933
- "div",
5934
- { style: styles.chips },
5935
- (0, import_react5.createElement)(import_dsh_client_ui_primitives5.Pill, { active: level === "project", onClick: () => {
5936
- setLevel("project");
5937
- }, title: "\u5199\u5230\u5DE5\u4F5C\u533A .dsh/rules\uFF0C\u56E2\u961F\u5171\u4EAB" }, "\u9879\u76EE\u7EA7"),
5938
- (0, import_react5.createElement)(import_dsh_client_ui_primitives5.Pill, { active: level === "user", onClick: () => {
5939
- setLevel("user");
5940
- }, title: "\u5199\u5230 $DSH_HOME/rules\uFF0C\u4E2A\u4EBA\u6240\u6709\u9879\u76EE\u53EF\u7528" }, "\u7528\u6237\u7EA7")
5941
- ),
5942
- editing === null ? (0, import_react5.createElement)("input", { style: control2, placeholder: "name\uFF08\u5982 my-redlines\uFF0C\u53EA\u542B\u5C0F\u5199\u5B57\u6BCD\u6570\u5B57\u548C -\uFF09", value: name, onChange: (ev) => {
5943
- setName(ev.target.value);
5944
- } }) : (0, import_react5.createElement)("span", { style: styles.sourceBadge }, `name \u56FA\u5B9A\u4E3A ${name}\uFF08\u6539\u540D\u8BF7\u5220\u9664\u540E\u91CD\u5EFA\uFF09`),
5945
- (0, import_react5.createElement)("textarea", { style: { ...styles.textarea, minHeight: 260 }, placeholder: "\u6B63\u6587\uFF08\u8FD9\u6761\u89C4\u5219\u7EA6\u675F\u5927\u6A21\u578B\u9075\u5B88\u4EC0\u4E48\uFF09", value: body2, onChange: (ev) => {
5946
- setBody(ev.target.value);
5947
- } }),
5948
- msg !== "" ? (0, import_react5.createElement)("p", { style: styles.status }, msg) : null
5949
- );
5950
- };
5951
- return (0, import_react5.createElement)(
5952
- "div",
5953
- { style: styles.section },
5954
- (0, import_react5.createElement)(
5955
- "div",
5956
- { style: card3 },
5957
- (0, import_react5.createElement)(
5958
- "div",
5959
- { style: styles.bindingStage },
5960
- (0, import_react5.createElement)("span", { style: styles.bindingLabel }, "\u5DF2\u5B89\u88C5\u7684 rule"),
5961
- rules.length === 0 ? (0, import_react5.createElement)("p", { style: styles.muted }, "\u6682\u65E0 rule\uFF0C\u70B9\u4E0B\u65B9\u300C\u65B0\u5EFA rule\u300D\u521B\u5EFA\u4E00\u4E2A\u3002") : (0, import_react5.createElement)(
5962
- "div",
5963
- { style: styles.section },
5964
- ...rules.map(renderRow)
5965
- )
5966
- ),
5967
- (0, import_react5.createElement)(import_dsh_client_ui_primitives5.Button, { variant: "outline", size: "md", onClick: startCreate }, "\u65B0\u5EFA rule")
5968
- ),
5969
- formOpen ? renderForm() : null
5855
+ { title: `\u5B89\u88C5${noun}`, description: "\u5148\u68C0\u67E5\u5185\u5BB9\u548C\u5B89\u88C5\u4F4D\u7F6E\uFF0C\u786E\u8BA4\u540E\u624D\u4F1A\u5199\u5165\u3002", onClose: close, footer: (0, import_react4.createElement)("div", { className: "te-actions" }, (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "ghost", disabled: busy, onClick: close }, "\u53D6\u6D88"), (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "primary", disabled: busy || !preview || preview.conflict, onClick: () => {
5856
+ void install();
5857
+ } }, busy ? "\u5904\u7406\u4E2D\u2026" : "\u786E\u8BA4\u5B89\u88C5")) },
5858
+ targets(),
5859
+ (0, import_react4.createElement)("div", { className: "te-actions" }, (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "outline", disabled: busy, onClick: choose }, "\u91CD\u65B0\u9009\u62E9"), kind === "skill" ? (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "ghost", disabled: busy, onClick: () => setManual(!manual) }, manual ? "\u6536\u8D77\u9AD8\u7EA7\u65B9\u5F0F" : "\u4E3B\u673A\u8DEF\u5F84") : null),
5860
+ manual ? (0, import_react4.createElement)("div", { className: "te-advanced" }, (0, import_react4.createElement)("p", null, "\u6B64\u8DEF\u5F84\u4F4D\u4E8E Harness \u4E3B\u673A\uFF1B\u6D4F\u89C8\u5668\u9009\u62E9\u5668\u8BFB\u53D6\u7684\u662F\u4F60\u5F53\u524D\u7535\u8111\u3002"), (0, import_react4.createElement)("div", { className: "te-toolbar" }, (0, import_react4.createElement)("input", { className: "te-input", "aria-label": "\u4E3B\u673A\u6280\u80FD\u76EE\u5F55", value: sourceDir, onChange: (e) => {
5861
+ setSourceDir(e.target.value);
5862
+ setRequest(null);
5863
+ } }), (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "outline", onClick: () => {
5864
+ void browse(sourceDir);
5865
+ } }, "\u6D4F\u89C8"), (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "outline", disabled: busy || !sourceDir.trim(), onClick: () => setRequest({ kind, level, path: workspace, files: [], sourceDir }) }, "\u9884\u89C8\u76EE\u5F55")), (0, import_react4.createElement)("div", { className: "te-dir-list" }, browsePath ? (0, import_react4.createElement)("button", { onClick: () => {
5866
+ void browse(browsePath.replace(/[\\/][^\\/]+[\\/]?$/u, "") || "/");
5867
+ } }, "\u2191 \u4E0A\u7EA7\u76EE\u5F55") : null, ...dirs.map((d) => (0, import_react4.createElement)("button", { key: d.name, onClick: () => {
5868
+ setRequest(null);
5869
+ void browse(browsePath.replace(/[\\/]+$/u, "") + "/" + d.name);
5870
+ } }, d.name + (d.hasSkill ? " \xB7 SKILL.md" : ""))))) : null,
5871
+ busy ? (0, import_react4.createElement)("p", { role: "status" }, "\u6B63\u5728\u6821\u9A8C\u6587\u4EF6\uFF0C\u8BF7\u7A0D\u5019\u2026") : null,
5872
+ status(),
5873
+ preview ? (0, import_react4.createElement)("div", { className: "te-preview" }, (0, import_react4.createElement)("h3", null, preview.name), (0, import_react4.createElement)("p", null, preview.description), (0, import_react4.createElement)("div", { className: "te-actions" }, (0, import_react4.createElement)("span", { className: "te-badge" }, `${preview.files} \u4E2A\u6587\u4EF6`), (0, import_react4.createElement)("span", { className: "te-badge" }, sizeText(preview.bytes))), (0, import_react4.createElement)("code", { className: "te-path" }, preview.target), preview.conflict ? (0, import_react4.createElement)("div", { className: "te-alert", role: "alert" }, "\u5DF2\u6709\u540C\u540D\u8D44\u6E90\u3002\u8BF7\u53D6\u6D88\u5E76\u68C0\u67E5\u73B0\u6709\u5185\u5BB9\uFF0C\u5B89\u88C5\u4E0D\u4F1A\u8986\u76D6\u5B83\u3002") : null, (0, import_react4.createElement)("div", { className: "te-markdown" }, (0, import_react4.createElement)(import_dsh_client_ui_primitives4.MarkdownText, { text: preview.content, labels }))) : null
5874
+ ) : null,
5875
+ editing ? (0, import_react4.createElement)(
5876
+ ResourceModal,
5877
+ { title: editing === "new" ? `\u65B0\u5EFA${noun}` : `${viewing ? "\u67E5\u770B" : "\u7F16\u8F91"}${noun} \xB7 ${name}`, onClose: close, footer: (0, import_react4.createElement)("div", { className: "te-actions" }, (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "ghost", disabled: busy, onClick: close }, "\u5173\u95ED"), !readonly ? (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "outline", disabled: busy, onClick: () => setViewing(!viewing) }, viewing ? "\u7F16\u8F91\u5185\u5BB9" : "\u9884\u89C8") : null, !readonly ? (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "primary", disabled: busy || !name.trim() || !body2.trim() || kind === "skill" && !description.trim(), onClick: () => {
5878
+ void save2();
5879
+ } }, busy ? "\u5904\u7406\u4E2D\u2026" : "\u4FDD\u5B58") : null) },
5880
+ !readonly ? targets() : (0, import_react4.createElement)("p", { className: "te-badge" }, "\u5185\u7F6E\u8D44\u6E90 \xB7 \u53EA\u8BFB"),
5881
+ status(),
5882
+ viewing ? (0, import_react4.createElement)("div", { className: "te-markdown" }, (0, import_react4.createElement)(import_dsh_client_ui_primitives4.MarkdownText, { text: body2, labels })) : (0, import_react4.createElement)("div", { className: "te-form" }, (0, import_react4.createElement)("label", null, "\u540D\u79F0", (0, import_react4.createElement)("input", { className: "te-input", value: name, disabled: editing !== "new" || busy, onChange: (e) => setName(e.target.value), placeholder: "\u5C0F\u5199\u5B57\u6BCD\u3001\u6570\u5B57\u548C\u8FDE\u5B57\u7B26" })), kind === "skill" ? (0, import_react4.createElement)("label", null, "\u63CF\u8FF0", (0, import_react4.createElement)("input", { className: "te-input", value: description, disabled: busy, onChange: (e) => setDescription(e.target.value) })) : null, kind === "skill" ? (0, import_react4.createElement)("label", null, "\u4F7F\u7528\u65F6\u673A\uFF08\u53EF\u9009\uFF09", (0, import_react4.createElement)("input", { className: "te-input", value: whenToUse, disabled: busy, onChange: (e) => setWhenToUse(e.target.value) })) : null, (0, import_react4.createElement)("label", null, "Markdown \u6B63\u6587", (0, import_react4.createElement)("textarea", { className: "te-input te-editor", value: body2, disabled: busy, onChange: (e) => setBody(e.target.value) })))
5883
+ ) : null,
5884
+ deleting ? (0, import_react4.createElement)(ResourceModal, { title: `\u5220\u9664${noun}\u300C${deleting.name}\u300D\uFF1F`, description: levelOf(deleting) === "user" ? "\u8FD9\u662F\u4E2A\u4EBA\u5168\u5C40\u8D44\u6E90\uFF0C\u5220\u9664\u4F1A\u5F71\u54CD\u6B64\u4E3B\u673A\u4E0A\u7684\u6240\u6709\u9879\u76EE\u3002" : "\u5220\u9664\u5C06\u5F71\u54CD\u5F53\u524D\u9879\u76EE\u3002", onClose: close, footer: (0, import_react4.createElement)("div", { className: "te-actions" }, (0, import_react4.createElement)(import_dsh_client_ui_primitives4.Button, { variant: "outline", disabled: busy, onClick: close }, "\u4FDD\u7559"), (0, import_react4.createElement)("button", { className: "te-danger-button", disabled: busy, onClick: () => {
5885
+ void remove();
5886
+ } }, busy ? "\u5220\u9664\u4E2D\u2026" : "\u786E\u8BA4\u6C38\u4E45\u5220\u9664")) }, (0, import_react4.createElement)("code", { className: "te-path" }, `${roots?.[levelOf(deleting) === "user" ? "user" : "project"] ?? "\u8D44\u6E90\u76EE\u5F55"}/${deleting.name}${kind === "rule" ? ".md" : ""}`), (0, import_react4.createElement)("p", null, "\u6B64\u64CD\u4F5C\u4E0D\u4F1A\u8FDB\u5165\u56DE\u6536\u7AD9\uFF0C\u8BF7\u786E\u8BA4\u5DF2\u6709\u5907\u4EFD\u3002"), status()) : null
5970
5887
  );
5971
5888
  }
5972
5889
 
5973
- // src/client/TaskLedger.tsx
5890
+ // src/client/SkillManager.tsx
5891
+ function SkillManager(props) {
5892
+ return (0, import_react5.createElement)(ResourceManager, { ...props, key: props.workspace, kind: "skill" });
5893
+ }
5894
+
5895
+ // src/client/RuleManager.tsx
5974
5896
  var import_react6 = require("react");
5975
- var import_dsh_client_ui_primitives6 = require("@deepseek-ai/dsh-client-ui-primitives");
5976
- var card4 = {
5897
+ function RuleManager(props) {
5898
+ return (0, import_react6.createElement)(ResourceManager, { ...props, key: props.workspace, kind: "rule" });
5899
+ }
5900
+
5901
+ // src/client/TaskLedger.tsx
5902
+ var import_react7 = require("react");
5903
+ var import_dsh_client_ui_primitives5 = require("@deepseek-ai/dsh-client-ui-primitives");
5904
+ var card2 = {
5977
5905
  display: "flex",
5978
5906
  flexDirection: "column",
5979
5907
  gap: 10,
@@ -6010,10 +5938,10 @@ var badge = {
6010
5938
  color: "var(--dsw-alias-label-secondary)"
6011
5939
  };
6012
5940
  function verdictDot(outcome) {
6013
- return (0, import_react6.createElement)(import_dsh_client_ui_primitives6.StateDot, { state: outcome === "pass" ? "done" : "error" });
5941
+ return (0, import_react7.createElement)(import_dsh_client_ui_primitives5.StateDot, { state: outcome === "pass" ? "done" : "error" });
6014
5942
  }
6015
5943
  function itemStatusDot(status) {
6016
- return (0, import_react6.createElement)(import_dsh_client_ui_primitives6.StateDot, { state: status === "done" ? "done" : "ongoing" });
5944
+ return (0, import_react7.createElement)(import_dsh_client_ui_primitives5.StateDot, { state: status === "done" ? "done" : "ongoing" });
6017
5945
  }
6018
5946
  function timeText(at) {
6019
5947
  return at.slice(0, 19).replace("T", " ");
@@ -6021,92 +5949,111 @@ function timeText(at) {
6021
5949
  function itemAudit(item) {
6022
5950
  const lines = [];
6023
5951
  if (item.dispatch !== void 0) {
6024
- lines.push((0, import_react6.createElement)(
5952
+ lines.push((0, import_react7.createElement)(
6025
5953
  "div",
6026
5954
  { key: "dispatch", style: metaLine },
6027
- (0, import_react6.createElement)("span", { style: badge }, "\u5DF2\u6D3E\u53D1"),
6028
- (0, import_react6.createElement)("span", null, item.dispatch.description === "" ? "\uFF08\u65E0\u63CF\u8FF0\uFF09" : item.dispatch.description),
6029
- (0, import_react6.createElement)("span", { style: badge }, timeText(item.dispatch.at))
5955
+ (0, import_react7.createElement)("span", { style: badge }, "\u5DF2\u6D3E\u53D1"),
5956
+ (0, import_react7.createElement)("span", null, item.dispatch.description === "" ? "\uFF08\u65E0\u63CF\u8FF0\uFF09" : item.dispatch.description),
5957
+ (0, import_react7.createElement)("span", { style: badge }, timeText(item.dispatch.at))
6030
5958
  ));
6031
5959
  }
6032
5960
  if (item.review !== void 0) {
6033
5961
  const spec = item.review.spec;
6034
5962
  const quality = item.review.quality;
6035
- lines.push((0, import_react6.createElement)(
5963
+ lines.push((0, import_react7.createElement)(
6036
5964
  "div",
6037
5965
  { key: "review", style: metaLine },
6038
5966
  verdictDot(spec.outcome),
6039
- (0, import_react6.createElement)("span", null, `\u89C4\u683C\u7B26\u5408 ${spec.outcome === "pass" ? "\u901A\u8FC7" : "\u4E0D\u901A\u8FC7"}`),
6040
- (0, import_react6.createElement)("span", null, "\xB7"),
5967
+ (0, import_react7.createElement)("span", null, `\u89C4\u683C\u7B26\u5408 ${spec.outcome === "pass" ? "\u901A\u8FC7" : "\u4E0D\u901A\u8FC7"}`),
5968
+ (0, import_react7.createElement)("span", null, "\xB7"),
6041
5969
  verdictDot(quality.outcome),
6042
- (0, import_react6.createElement)("span", null, `\u4EE3\u7801\u8D28\u91CF ${quality.outcome === "pass" ? "\u901A\u8FC7" : "\u4E0D\u901A\u8FC7"}`)
5970
+ (0, import_react7.createElement)("span", null, `\u4EE3\u7801\u8D28\u91CF ${quality.outcome === "pass" ? "\u901A\u8FC7" : "\u4E0D\u901A\u8FC7"}`)
6043
5971
  ));
6044
5972
  const failNotes = [spec, quality].flatMap((stage) => stage.outcome === "fail" ? stage.notes ?? [] : []);
6045
5973
  if (failNotes.length > 0) {
6046
- lines.push((0, import_react6.createElement)(
5974
+ lines.push((0, import_react7.createElement)(
6047
5975
  "div",
6048
5976
  { key: "notes", style: metaLine },
6049
- ...failNotes.map((note) => (0, import_react6.createElement)("span", { key: note, style: badge }, note))
5977
+ ...failNotes.map((note) => (0, import_react7.createElement)("span", { key: note, style: badge }, note))
6050
5978
  ));
6051
5979
  }
6052
5980
  }
6053
5981
  if (lines.length === 0) {
6054
- lines.push((0, import_react6.createElement)("div", { key: "none", style: metaLine }, (0, import_react6.createElement)("span", { style: badge }, "\u672A\u6D3E\u53D1 / \u672A\u5BA1\u67E5")));
5982
+ lines.push((0, import_react7.createElement)("div", { key: "none", style: metaLine }, (0, import_react7.createElement)("span", { style: badge }, "\u672A\u6D3E\u53D1 / \u672A\u5BA1\u67E5")));
6055
5983
  }
6056
- return (0, import_react6.createElement)("div", { style: { display: "flex", flexDirection: "column", gap: 4 } }, ...lines);
5984
+ return (0, import_react7.createElement)("div", { style: { display: "flex", flexDirection: "column", gap: 4 } }, ...lines);
6057
5985
  }
6058
5986
  function TaskLedger({ workspace, remote }) {
6059
- const [tasks, setTasks] = (0, import_react6.useState)([]);
6060
- const [error, setError] = (0, import_react6.useState)("");
6061
- const refresh = (0, import_react6.useCallback)(() => {
5987
+ const [tasks, setTasks] = (0, import_react7.useState)([]);
5988
+ const [error, setError] = (0, import_react7.useState)("");
5989
+ const [loading, setLoading] = (0, import_react7.useState)(true);
5990
+ const [query, setQuery] = (0, import_react7.useState)("");
5991
+ const [risk, setRisk] = (0, import_react7.useState)("all");
5992
+ const [stage, setStage] = (0, import_react7.useState)("all");
5993
+ const refresh = (0, import_react7.useCallback)(() => {
6062
5994
  if (workspace === "") return;
6063
5995
  setError("");
5996
+ setLoading(true);
6064
5997
  void remote.readTasks(workspace).then((result) => {
5998
+ setLoading(false);
6065
5999
  if (result.ok) setTasks(result.value.tasks);
6066
6000
  else setError("\u8BFB\u53D6\u53F0\u8D26\u5931\u8D25\uFF1A" + describeError(result.error));
6067
6001
  }, (reason) => {
6002
+ setLoading(false);
6068
6003
  setError("\u8BFB\u53D6\u53F0\u8D26\u5931\u8D25\uFF1A" + describeError(reason));
6069
6004
  });
6070
6005
  }, [remote, workspace]);
6071
- (0, import_react6.useEffect)(() => {
6006
+ (0, import_react7.useEffect)(() => {
6072
6007
  refresh();
6073
6008
  }, [refresh]);
6074
- return (0, import_react6.createElement)(
6009
+ const visible = tasks.filter((task) => `${task.task_id} ${task.title} ${task.branch}`.toLowerCase().includes(query.toLowerCase()) && (risk === "all" || task.risk_level === risk) && (stage === "all" || task.stage === stage));
6010
+ return (0, import_react7.createElement)(
6075
6011
  "div",
6076
6012
  { style: styles.section },
6077
- (0, import_react6.createElement)(
6013
+ (0, import_react7.createElement)(
6014
+ "div",
6015
+ { className: "te-toolbar" },
6016
+ (0, import_react7.createElement)("input", { className: "te-input", placeholder: "\u641C\u7D22\u4EFB\u52A1\u3001\u6807\u9898\u6216\u5206\u652F", value: query, onChange: (e) => setQuery(e.target.value) }),
6017
+ (0, import_react7.createElement)("select", { className: "te-input", "aria-label": "\u98CE\u9669\u7B5B\u9009", value: risk, onChange: (e) => setRisk(e.target.value) }, (0, import_react7.createElement)("option", { value: "all" }, "\u5168\u90E8\u98CE\u9669"), (0, import_react7.createElement)("option", { value: "standard" }, "\u6807\u51C6"), (0, import_react7.createElement)("option", { value: "high_risk" }, "\u9AD8\u98CE\u9669")),
6018
+ (0, import_react7.createElement)("select", { className: "te-input", "aria-label": "\u9636\u6BB5\u7B5B\u9009", value: stage, onChange: (e) => setStage(e.target.value) }, (0, import_react7.createElement)("option", { value: "all" }, "\u5168\u90E8\u9636\u6BB5"), ...Array.from(new Set(tasks.map((t) => t.stage))).map((value) => (0, import_react7.createElement)("option", { key: value, value }, value)))
6019
+ ),
6020
+ (0, import_react7.createElement)(
6078
6021
  "div",
6079
6022
  { style: headerRow },
6080
- (0, import_react6.createElement)("span", { style: styles.bindingLabel }, "\u4EFB\u52A1\u53F0\u8D26"),
6081
- (0, import_react6.createElement)("span", { style: styles.sourceBadge }, "\u53EA\u8BFB \xB7 \u6765\u81EA .dsh/task-*.json"),
6082
- (0, import_react6.createElement)(import_dsh_client_ui_primitives6.Button, { variant: "outline", size: "sm", onClick: refresh }, "\u5237\u65B0")
6023
+ (0, import_react7.createElement)("span", { style: styles.bindingLabel }, "\u4EFB\u52A1\u53F0\u8D26"),
6024
+ (0, import_react7.createElement)("span", { style: styles.sourceBadge }, "\u53EA\u8BFB \xB7 \u6765\u81EA .dsh/task-*.json"),
6025
+ (0, import_react7.createElement)(import_dsh_client_ui_primitives5.Button, { variant: "outline", size: "sm", disabled: loading, onClick: refresh }, loading ? "\u8BFB\u53D6\u4E2D\u2026" : "\u5237\u65B0")
6083
6026
  ),
6084
- error !== "" ? (0, import_react6.createElement)("p", { style: styles.status }, error) : tasks.length === 0 ? (0, import_react6.createElement)("p", { style: styles.muted }, "\u5F53\u524D\u5DE5\u4F5C\u533A\u8FD8\u6CA1\u6709\u4EFB\u52A1\uFF1A\u5F00\u5DE5\u540E\uFF08dev_task create\uFF09\u4F1A\u5728\u8FD9\u91CC\u5217\u51FA\u6D3E\u53D1\u4E0E\u5BA1\u67E5\u7559\u75D5\u3002") : (0, import_react6.createElement)(
6027
+ loading ? (0, import_react7.createElement)("p", { role: "status" }, "\u6B63\u5728\u8BFB\u53D6\u4EFB\u52A1\u2026") : error !== "" ? (0, import_react7.createElement)("p", { style: styles.status }, error) : tasks.length === 0 ? (0, import_react7.createElement)("p", { style: styles.muted }, "\u5F53\u524D\u5DE5\u4F5C\u533A\u8FD8\u6CA1\u6709\u4EFB\u52A1\uFF1A\u5F00\u5DE5\u540E\uFF08dev_task create\uFF09\u4F1A\u5728\u8FD9\u91CC\u5217\u51FA\u6D3E\u53D1\u4E0E\u5BA1\u67E5\u7559\u75D5\u3002") : visible.length === 0 ? (0, import_react7.createElement)("div", { className: "te-empty" }, "\u6CA1\u6709\u5339\u914D\u7684\u4EFB\u52A1\uFF0C\u8BF7\u8C03\u6574\u7B5B\u9009\u3002") : (0, import_react7.createElement)(
6085
6028
  "div",
6086
6029
  { style: { display: "flex", flexDirection: "column", gap: 12 } },
6087
- ...tasks.map((task) => (0, import_react6.createElement)(
6030
+ ...visible.map((task) => (0, import_react7.createElement)(
6088
6031
  "div",
6089
- { key: task.task_id, style: card4 },
6090
- (0, import_react6.createElement)(
6032
+ { key: task.task_id, style: card2 },
6033
+ (0, import_react7.createElement)(
6091
6034
  "div",
6092
6035
  { style: headerRow },
6093
- (0, import_react6.createElement)("span", { style: { fontSize: 14, fontWeight: 600, color: "var(--dsw-alias-label-primary)" } }, task.task_id),
6094
- (0, import_react6.createElement)("span", { style: { fontSize: 13, color: "var(--dsw-alias-label-primary)" } }, task.title),
6095
- (0, import_react6.createElement)("span", { style: badge }, task.stage),
6096
- (0, import_react6.createElement)("span", { style: badge }, task.branch)
6036
+ (0, import_react7.createElement)("span", { style: { fontSize: 14, fontWeight: 600, color: "var(--dsw-alias-label-primary)" } }, task.task_id),
6037
+ (0, import_react7.createElement)("span", { style: { fontSize: 13, color: "var(--dsw-alias-label-primary)" } }, task.title),
6038
+ (0, import_react7.createElement)("span", { style: badge }, task.stage),
6039
+ (0, import_react7.createElement)("span", { style: badge }, task.branch),
6040
+ (0, import_react7.createElement)("span", { className: "te-badge", style: task.risk_level === "high_risk" ? { color: "var(--dsw-alias-state-error-primary)" } : {} }, task.risk_level === "high_risk" ? "\u9AD8\u98CE\u9669" : "\u6807\u51C6"),
6041
+ (0, import_react7.createElement)("span", { className: "te-badge" }, task.verification_passed ? "\u9A8C\u8BC1\u901A\u8FC7" : "\u5F85\u9A8C\u8BC1"),
6042
+ (0, import_react7.createElement)("span", { className: "te-badge" }, `\u5BA1\u6838\uFF1A${task.review_outcome ?? "pending"}`),
6043
+ task.updated_at ? (0, import_react7.createElement)("span", { style: metaLine }, "\u66F4\u65B0\u4E8E " + timeText(task.updated_at)) : null
6097
6044
  ),
6098
- (0, import_react6.createElement)(
6045
+ (0, import_react7.createElement)(
6099
6046
  "div",
6100
6047
  { style: { display: "flex", flexDirection: "column" } },
6101
- ...task.items.map((item) => (0, import_react6.createElement)(
6048
+ ...task.items.map((item) => (0, import_react7.createElement)(
6102
6049
  "div",
6103
6050
  { key: item.id, style: itemRow },
6104
- (0, import_react6.createElement)(
6051
+ (0, import_react7.createElement)(
6105
6052
  "div",
6106
6053
  { style: headerRow },
6107
6054
  itemStatusDot(item.status),
6108
- (0, import_react6.createElement)("span", { style: { fontSize: 13, color: "var(--dsw-alias-label-primary)" } }, item.id),
6109
- (0, import_react6.createElement)("span", { style: { fontSize: 12, color: "var(--dsw-alias-label-secondary)" } }, item.title)
6055
+ (0, import_react7.createElement)("span", { style: { fontSize: 13, color: "var(--dsw-alias-label-primary)" } }, item.id),
6056
+ (0, import_react7.createElement)("span", { style: { fontSize: 12, color: "var(--dsw-alias-label-secondary)" } }, item.title)
6110
6057
  ),
6111
6058
  itemAudit(item)
6112
6059
  ))
@@ -6129,24 +6076,25 @@ var header = {
6129
6076
  display: "flex",
6130
6077
  alignItems: "center",
6131
6078
  justifyContent: "space-between",
6132
- padding: "12px 20px",
6079
+ padding: "20px 28px",
6133
6080
  borderBottom: "1px solid var(--dsw-alias-border-l2)"
6134
6081
  };
6135
6082
  var headerBrand = { display: "flex", alignItems: "center", gap: 10, minWidth: 0 };
6136
6083
  var headerText = { display: "flex", flexDirection: "column", gap: 1, minWidth: 0 };
6137
- var headerTitle = { fontSize: 15, fontWeight: 600, color: "var(--dsw-alias-label-primary)" };
6084
+ var headerTitle = { fontSize: 20, fontWeight: 650, color: "var(--dsw-alias-label-primary)" };
6138
6085
  var headerSub = { fontSize: 12, color: "var(--dsw-alias-label-tertiary)", margin: 0 };
6139
6086
  var tabbar = {
6140
6087
  display: "flex",
6141
6088
  alignItems: "center",
6142
6089
  gap: 8,
6143
- padding: "10px 20px",
6090
+ padding: "12px 28px",
6091
+ flexWrap: "wrap",
6144
6092
  borderBottom: "1px solid var(--dsw-alias-border-l2)"
6145
6093
  };
6146
6094
  var body = {
6147
6095
  flex: 1,
6148
6096
  overflowY: "auto",
6149
- padding: 20
6097
+ padding: "24px clamp(12px, 3vw, 32px)"
6150
6098
  };
6151
6099
  var selectStyle = {
6152
6100
  marginLeft: "auto",
@@ -6173,34 +6121,35 @@ var TABS = [
6173
6121
  { id: "init", label: "\u9879\u76EE\u521D\u59CB\u5316" },
6174
6122
  { id: "flow", label: "\u6D41\u7A0B\u914D\u7F6E" },
6175
6123
  { id: "tasks", label: "\u4EFB\u52A1\u53F0\u8D26" },
6176
- { id: "skills", label: "\u6280\u80FD skill" },
6177
- { id: "rules", label: "\u89C4\u5219 rule" }
6124
+ { id: "skills", label: "\u6280\u80FD" },
6125
+ { id: "rules", label: "\u89C4\u5219" }
6178
6126
  ];
6179
6127
  function Workbench({ useStore, actions, useWorkspaces, remote }) {
6180
6128
  const open = useStore((s) => s.open);
6181
6129
  const workspaces = useWorkspaces((s) => s.items);
6182
- const [tab, setTab] = (0, import_react7.useState)("init");
6183
- const [workspace, setWorkspace] = (0, import_react7.useState)("");
6130
+ const [tab, setTab] = (0, import_react8.useState)("init");
6131
+ const [workspace, setWorkspace] = (0, import_react8.useState)("");
6184
6132
  if (!open) return null;
6185
6133
  const current = workspaces.some((w) => w.path === workspace) ? workspace : workspaces[0]?.path ?? "";
6186
- return (0, import_react7.createElement)(
6134
+ return (0, import_react8.createElement)(
6187
6135
  "div",
6188
- { style: overlay },
6189
- (0, import_react7.createElement)(
6136
+ { style: overlay, className: "te-workbench" },
6137
+ (0, import_react8.createElement)("style", null, workbenchTheme),
6138
+ (0, import_react8.createElement)(
6190
6139
  "div",
6191
6140
  { style: header },
6192
- (0, import_react7.createElement)(
6141
+ (0, import_react8.createElement)(
6193
6142
  "div",
6194
6143
  { style: headerBrand },
6195
- (0, import_react7.createElement)(import_dsh_client_ui_primitives7.IconSettingsOutline16, { size: 18 }),
6196
- (0, import_react7.createElement)(
6144
+ (0, import_react8.createElement)(import_dsh_client_ui_primitives6.IconSettingsOutline16, { size: 18 }),
6145
+ (0, import_react8.createElement)(
6197
6146
  "div",
6198
6147
  { style: headerText },
6199
- (0, import_react7.createElement)("span", { style: headerTitle }, "\u5DE5\u7A0B\u6D41\u7A0B"),
6200
- (0, import_react7.createElement)("p", { style: headerSub }, "\u5DE5\u7A0B\u5316\u4EA4\u4ED8\u5DE5\u4F5C\u53F0 \xB7 \u9700\u6C42\u8BC4\u5BA1 \u2192 \u8BBE\u8BA1 \u2192 \u5F00\u53D1 \u2192 \u4EA4\u4ED8 \u2192 \u4EE3\u7801\u5BA1\u6838")
6148
+ (0, import_react8.createElement)("span", { style: headerTitle }, "\u5DE5\u7A0B\u6D41\u7A0B"),
6149
+ (0, import_react8.createElement)("p", { style: headerSub }, "\u5DE5\u7A0B\u5316\u4EA4\u4ED8\u5DE5\u4F5C\u53F0 \xB7 \u9700\u6C42\u8BC4\u5BA1 \u2192 \u8BBE\u8BA1 \u2192 \u5F00\u53D1 \u2192 \u4EA4\u4ED8 \u2192 \u4EE3\u7801\u5BA1\u6838")
6201
6150
  )
6202
6151
  ),
6203
- (0, import_react7.createElement)(
6152
+ (0, import_react8.createElement)(
6204
6153
  "button",
6205
6154
  {
6206
6155
  type: "button",
@@ -6216,38 +6165,44 @@ function Workbench({ useStore, actions, useWorkspaces, remote }) {
6216
6165
  event.currentTarget.style.background = "transparent";
6217
6166
  }
6218
6167
  },
6219
- (0, import_react7.createElement)(import_dsh_client_ui_primitives7.IconCloseOutline16, { size: 16 })
6168
+ (0, import_react8.createElement)(import_dsh_client_ui_primitives6.IconCloseOutline16, { size: 16 })
6220
6169
  )
6221
6170
  ),
6222
- (0, import_react7.createElement)(
6171
+ (0, import_react8.createElement)(
6223
6172
  "div",
6224
6173
  { style: tabbar },
6225
- ...TABS.map((t) => (0, import_react7.createElement)(import_dsh_client_ui_primitives7.Pill, { key: t.id, active: tab === t.id, onClick: () => {
6174
+ ...TABS.map((t) => (0, import_react8.createElement)(import_dsh_client_ui_primitives6.Pill, { key: t.id, active: tab === t.id, onClick: () => {
6226
6175
  setTab(t.id);
6227
6176
  } }, t.label)),
6228
- workspaces.length > 0 ? (0, import_react7.createElement)("select", {
6177
+ workspaces.length > 0 ? (0, import_react8.createElement)("select", {
6229
6178
  style: selectStyle,
6179
+ "aria-label": "\u5F53\u524D\u5DE5\u4F5C\u533A",
6230
6180
  value: current,
6231
6181
  onChange: (ev) => {
6232
6182
  setWorkspace(ev.target.value);
6233
6183
  }
6234
- }, ...workspaces.map((w) => (0, import_react7.createElement)("option", { key: w.path, value: w.path }, w.title || w.path))) : null
6184
+ }, ...workspaces.map((w) => (0, import_react8.createElement)("option", { key: w.path, value: w.path }, w.title || w.path))) : null
6235
6185
  ),
6236
- (0, import_react7.createElement)(
6186
+ (0, import_react8.createElement)(
6237
6187
  "div",
6238
6188
  { style: body },
6239
- current === "" ? (0, import_react7.createElement)("p", { style: styles.muted }, "\u5F53\u524D\u6CA1\u6709\u5DE5\u4F5C\u533A\uFF1A\u8BF7\u5148\u5728\u4FA7\u680F\u521B\u5EFA\u4E00\u4E2A\u5DE5\u4F5C\u533A\uFF0C\u518D\u56DE\u6765\u914D\u7F6E\u6D41\u7A0B\u3002") : tab === "init" ? (0, import_react7.createElement)(InitPanel, { workspace: current, remote }) : tab === "flow" ? (0, import_react7.createElement)(TaskEngineSection, { workspace: current, remote }) : tab === "tasks" ? (0, import_react7.createElement)(TaskLedger, { workspace: current, remote }) : tab === "skills" ? (0, import_react7.createElement)(SkillManager, { workspace: current, remote }) : (0, import_react7.createElement)(RuleManager, { workspace: current, remote })
6189
+ (0, import_react8.createElement)(
6190
+ "div",
6191
+ { className: "te-content", key: current },
6192
+ (0, import_react8.createElement)("p", { style: { ...styles.hint, marginBottom: 20 }, title: current }, "\u5DE5\u4F5C\u533A \xB7 " + current),
6193
+ current === "" ? (0, import_react8.createElement)("p", { style: styles.muted }, "\u5F53\u524D\u6CA1\u6709\u5DE5\u4F5C\u533A\uFF1A\u8BF7\u5148\u5728\u4FA7\u680F\u521B\u5EFA\u4E00\u4E2A\u5DE5\u4F5C\u533A\uFF0C\u518D\u56DE\u6765\u914D\u7F6E\u6D41\u7A0B\u3002") : tab === "init" ? (0, import_react8.createElement)(InitPanel, { workspace: current, remote }) : tab === "flow" ? (0, import_react8.createElement)(TaskEngineSection, { workspace: current, remote }) : tab === "tasks" ? (0, import_react8.createElement)(TaskLedger, { workspace: current, remote }) : tab === "skills" ? (0, import_react8.createElement)(SkillManager, { workspace: current, remote }) : (0, import_react8.createElement)(RuleManager, { workspace: current, remote })
6194
+ )
6240
6195
  )
6241
6196
  );
6242
6197
  }
6243
6198
 
6244
6199
  // src/client/TriggerButton.tsx
6245
- var import_react8 = require("react");
6246
- var import_dsh_client_ui_primitives8 = require("@deepseek-ai/dsh-client-ui-primitives");
6200
+ var import_react9 = require("react");
6201
+ var import_dsh_client_ui_primitives7 = require("@deepseek-ai/dsh-client-ui-primitives");
6247
6202
  var hover = "var(--dsw-alias-bg-layer-2)";
6248
6203
  var label = "var(--dsw-alias-label-primary)";
6249
6204
  function TriggerButton({ wide, actions }) {
6250
- return (0, import_react8.createElement)(
6205
+ return (0, import_react9.createElement)(
6251
6206
  "button",
6252
6207
  {
6253
6208
  type: "button",
@@ -6287,8 +6242,8 @@ function TriggerButton({ wide, actions }) {
6287
6242
  transition: "background 120ms ease"
6288
6243
  }
6289
6244
  },
6290
- (0, import_react8.createElement)(import_dsh_client_ui_primitives8.IconSettingsOutline16, { size: wide ? 16 : 18 }),
6291
- wide ? (0, import_react8.createElement)("span", { style: { fontSize: 14, lineHeight: "22px" } }, "\u5DE5\u7A0B\u6D41\u7A0B") : null
6245
+ (0, import_react9.createElement)(import_dsh_client_ui_primitives7.IconSettingsOutline16, { size: wide ? 16 : 18 }),
6246
+ wide ? (0, import_react9.createElement)("span", { style: { fontSize: 14, lineHeight: "22px" } }, "\u5DE5\u7A0B\u6D41\u7A0B") : null
6292
6247
  );
6293
6248
  }
6294
6249