@joekytc/dsh-swarm 0.3.2 → 0.3.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/README.md +14 -7
  2. package/README.zh-CN.md +10 -5
  3. package/client/KanbanBoard.tsx +3 -1
  4. package/client/TaskDrawer.tsx +74 -2
  5. package/client/WorkflowRail.tsx +84 -1
  6. package/client/config-store.ts +3 -1
  7. package/client/kanban.css +28 -0
  8. package/client/timeline-model.ts +4 -0
  9. package/client/workflow-model.ts +20 -11
  10. package/lib/client.js +1100 -22
  11. package/lib/config.d.ts +5 -1
  12. package/lib/config.js +2 -1
  13. package/lib/dispatcher/agent-runner.js +25 -9
  14. package/lib/dispatcher/event-waker.js +4 -1
  15. package/lib/dispatcher/v-orchestrator.d.ts +2 -0
  16. package/lib/dispatcher/v-orchestrator.js +58 -9
  17. package/lib/domain/config-override.d.ts +6 -0
  18. package/lib/domain/config-override.js +16 -1
  19. package/lib/domain/im-message.d.ts +21 -2
  20. package/lib/domain/im-message.js +84 -4
  21. package/lib/domain/kanban-service.d.ts +8 -1
  22. package/lib/domain/kanban-service.js +67 -1
  23. package/lib/domain/permissions.d.ts +1 -1
  24. package/lib/domain/permissions.js +4 -0
  25. package/lib/domain/projection.js +8 -3
  26. package/lib/domain/review-evidence.js +9 -0
  27. package/lib/domain/review-target.d.ts +10 -0
  28. package/lib/domain/review-target.js +24 -0
  29. package/lib/domain/state-machine.js +1 -1
  30. package/lib/domain/types.d.ts +16 -3
  31. package/lib/routes/kanban-http.js +52 -2
  32. package/lib/services/config-provider.js +2 -0
  33. package/lib/services/im-bot-probe.d.ts +36 -0
  34. package/lib/services/im-bot-probe.js +128 -0
  35. package/lib/services/im-delivery.d.ts +69 -7
  36. package/lib/services/im-delivery.js +220 -34
  37. package/lib/tools/kanban-tools.js +38 -1
  38. package/lib/tools/main-session-tools.js +34 -9
  39. package/package.json +1 -1
  40. package/personas/kanban-p/agent.cordis.yml +16 -0
  41. package/personas/kanban-pt/agent.cordis.yml +19 -1
  42. package/personas/kanban-w/agent.cordis.yml +15 -0
  43. package/personas/persona-p.md +4 -0
  44. package/personas/persona-pt.md +4 -1
  45. package/personas/persona-w.md +1 -0
  46. package/personas/swarm/agent.cordis.yml +11 -0
package/lib/client.js CHANGED
@@ -49,7 +49,8 @@ window.__ModuleLoader__.load({
49
49
  var CHAIN_TRANSITIONS = {
50
50
  planning: { "chain/executing": "executing" },
51
51
  executing: { "chain/completed": "completed", "chain/aborted": "aborted", "chain/blocked": "blocked" },
52
- blocked: {},
52
+ blocked: { "chain/reopened": "executing" },
53
+ // 人工恢复唯一出边(其余事件对 blocked 仍非法)
53
54
  completed: {},
54
55
  aborted: {}
55
56
  };
@@ -78,7 +79,8 @@ window.__ModuleLoader__.load({
78
79
  case "chain/executing":
79
80
  case "chain/completed":
80
81
  case "chain/aborted":
81
- case "chain/blocked": {
82
+ case "chain/blocked":
83
+ case "chain/reopened": {
82
84
  const c = state.chains.get(ev.chainId);
83
85
  if (!c) throw new Error("projection: unknown chain " + ev.chainId);
84
86
  next.chains = new Map(state.chains).set(ev.chainId, { ...c, status: transitionChain(c.status, ev.kind) });
@@ -177,11 +179,12 @@ window.__ModuleLoader__.load({
177
179
  // 评审事件(交付质量链):非状态转换——按 payload.targetTaskId 更新被评审任务 reviewStatus
178
180
  case "review/passed":
179
181
  case "review/failed":
180
- case "review/gave-up": {
182
+ case "review/gave-up":
183
+ case "review/waived": {
181
184
  const targetId = String(ev.payload["targetTaskId"] ?? "");
182
185
  const t = state.tasks.get(targetId);
183
186
  if (!t) throw new Error("projection: unknown review target " + targetId);
184
- const status = ev.kind === "review/passed" ? "passed" : ev.kind === "review/failed" ? "failed" : "gave-up";
187
+ const status = ev.kind === "review/passed" ? "passed" : ev.kind === "review/failed" ? "failed" : ev.kind === "review/waived" ? "waived" : "gave-up";
185
188
  next.tasks = new Map(state.tasks).set(targetId, { ...t, reviewStatus: status });
186
189
  break;
187
190
  }
@@ -429,18 +432,16 @@ window.__ModuleLoader__.load({
429
432
  return `${Math.floor(diff / 864e5)}d`;
430
433
  }
431
434
  function blockedSummary(chainId, state) {
432
- let latest = null;
433
- let latestSeq = -1;
434
- for (const ev of state.events) {
435
- if (ev.chainId !== chainId) continue;
436
- if (ev.kind === "task/blocked" || ev.kind === "task/failed") {
437
- if (ev.seq > latestSeq) {
438
- latestSeq = ev.seq;
439
- latest = String(ev.payload["reason"] ?? "");
440
- }
441
- }
435
+ if (state.chains.get(chainId)?.status === "blocked") {
436
+ const ev2 = [...state.events].reverse().find((e) => e.chainId === chainId && e.kind === "chain/blocked");
437
+ return String(ev2?.payload["reason"] ?? "") || "\u94FE\u7EA7\u963B\u585E\uFF08\u539F\u56E0\u672A\u8BB0\u5F55\uFF09";
442
438
  }
443
- return latest;
439
+ const blockedIds = new Set(
440
+ [...state.tasks.values()].filter((t) => t.chainId === chainId && (t.status === "blocked" || t.status === "failed")).map((t) => t.id)
441
+ );
442
+ if (blockedIds.size === 0) return null;
443
+ const ev = [...state.events].reverse().find((e) => e.chainId === chainId && e.taskId !== null && blockedIds.has(e.taskId) && (e.kind === "task/blocked" || e.kind === "task/failed"));
444
+ return ev ? String(ev.payload["reason"] ?? "") : null;
444
445
  }
445
446
  function relatedIds(state, chainId, selectedTaskId) {
446
447
  const set = /* @__PURE__ */ new Set();
@@ -689,6 +690,36 @@ window.__ModuleLoader__.load({
689
690
  const renamingChain = renamingChainId ? props.chains.find((v) => v.chain.id === renamingChainId)?.chain : void 0;
690
691
  const [deletingChainId, setDeletingChainId] = (0, import_react4.useState)(null);
691
692
  const [deleteError, setDeleteError] = (0, import_react4.useState)(null);
693
+ const [reopeningChainId, setReopeningChainId] = (0, import_react4.useState)(null);
694
+ const [reopenReason, setReopenReason] = (0, import_react4.useState)("");
695
+ const [reopenError, setReopenError] = (0, import_react4.useState)(null);
696
+ const [reopenBusy, setReopenBusy] = (0, import_react4.useState)(false);
697
+ const [reopenOk, setReopenOk] = (0, import_react4.useState)(false);
698
+ const reopeningView = reopeningChainId ? props.chains.find((v) => v.chain.id === reopeningChainId) : void 0;
699
+ const closeReopen = () => {
700
+ setReopeningChainId(null);
701
+ setReopenReason("");
702
+ setReopenError(null);
703
+ setReopenOk(false);
704
+ };
705
+ const confirmReopen = async () => {
706
+ if (!reopeningChainId) return;
707
+ if (!reopenReason.trim()) {
708
+ setReopenError("\u8BF7\u586B\u5199\u6062\u590D\u7406\u7531\uFF08\u5FC5\u586B\uFF0C\u7528\u4E8E\u5BA1\u8BA1\u7559\u75D5\uFF09");
709
+ return;
710
+ }
711
+ setReopenError(null);
712
+ setReopenBusy(true);
713
+ try {
714
+ await props.onReopenChain?.(reopeningChainId, reopenReason.trim());
715
+ setReopenOk(true);
716
+ window.setTimeout(() => closeReopen(), 800);
717
+ } catch (err) {
718
+ setReopenError("\u6062\u590D\u5931\u8D25\uFF1A" + String(err));
719
+ } finally {
720
+ setReopenBusy(false);
721
+ }
722
+ };
692
723
  const deletingView = deletingChainId ? props.chains.find((v) => v.chain.id === deletingChainId) : void 0;
693
724
  const confirmDelete = async () => {
694
725
  if (!deletingChainId) return;
@@ -750,6 +781,7 @@ window.__ModuleLoader__.load({
750
781
  type: "button",
751
782
  className: "dsh-kb-chain__delete",
752
783
  "aria-label": "\u5220\u9664\u9700\u6C42",
784
+ title: "\u5220\u9664\u9700\u6C42\uFF08\u6574\u94FE\u786C\u5220\u9664\uFF0C\u4E0D\u53EF\u6062\u590D\uFF09",
753
785
  onClick: (e) => {
754
786
  e.stopPropagation();
755
787
  setDeleteError(null);
@@ -770,6 +802,7 @@ window.__ModuleLoader__.load({
770
802
  type: "button",
771
803
  className: "dsh-kb-chain__rename",
772
804
  "aria-label": "\u6539\u94FE\u6807\u9898",
805
+ title: "\u4FEE\u6539\u94FE\u8DEF\u6807\u9898",
773
806
  onClick: (e) => {
774
807
  e.stopPropagation();
775
808
  setRenamingChainId(view.chain.id);
@@ -779,11 +812,30 @@ window.__ModuleLoader__.load({
779
812
  },
780
813
  children: "\u270E"
781
814
  }
815
+ ),
816
+ props.onReopenChain && view.chain.status === "blocked" && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
817
+ "button",
818
+ {
819
+ type: "button",
820
+ className: "dsh-kb-chain__reopen",
821
+ "aria-label": "\u4EBA\u5DE5\u6062\u590D\u94FE\u8DEF",
822
+ title: "\u5C06 blocked \u94FE\u6062\u590D\u4E3A executing\uFF0C\u7F16\u6392\u5668\u7EE7\u7EED\u63A8\u8FDB\u540E\u7EED\u9636\u6BB5",
823
+ onClick: (e) => {
824
+ e.stopPropagation();
825
+ setReopenError(null);
826
+ setReopenReason("");
827
+ setReopeningChainId(view.chain.id);
828
+ },
829
+ onKeyDown: (e) => {
830
+ e.stopPropagation();
831
+ },
832
+ children: "\u6062\u590D"
833
+ }
782
834
  )
783
835
  ]
784
836
  }
785
837
  ),
786
- (blocked || view.blockedSummary) && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dsh-kb-chain__warning", children: summary }),
838
+ (blocked || view.blockedSummary) && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dsh-kb-chain__warning", title: summary, children: summary }),
787
839
  view.audit && !view.audit.confirmed && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dsh-kb-chain__warning dsh-kb-chain__audit", children: [
788
840
  /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { children: [
789
841
  "\u26A0 \u4E3B agent \u7591\u4F3C\u8D8A\u6743\u5199\u5DE5\u4F5C\u533A\u4EA7\u7269\uFF08",
@@ -807,6 +859,51 @@ window.__ModuleLoader__.load({
807
859
  onCancel: () => setRenamingChainId(null)
808
860
  }
809
861
  ),
862
+ reopeningView && props.onReopenChain && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dsh-kb-rename-overlay", onClick: (e) => {
863
+ e.stopPropagation();
864
+ closeReopen();
865
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
866
+ "div",
867
+ {
868
+ className: "dsh-kb-rename-modal",
869
+ role: "dialog",
870
+ "aria-modal": "true",
871
+ "aria-label": "\u4EBA\u5DE5\u6062\u590D\u94FE\u8DEF",
872
+ onClick: (e) => e.stopPropagation(),
873
+ children: [
874
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dsh-kb-rename-modal__label", children: "\u4EBA\u5DE5\u6062\u590D\u94FE\u8DEF" }),
875
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dsh-kb-delete-modal__text", children: [
876
+ "\u5C06\u300C",
877
+ reopeningView.chain.title || "\u672A\u547D\u540D\u9700\u6C42",
878
+ "\u300D\u4ECE blocked \u6062\u590D\u4E3A executing\uFF0C\u7F16\u6392\u5668\u7EE7\u7EED\u63A8\u8FDB\u540E\u7EED\u9636\u6BB5\u3002"
879
+ ] }),
880
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
881
+ "input",
882
+ {
883
+ className: "dsh-kb-comment-input",
884
+ "aria-label": "\u6062\u590D\u7406\u7531",
885
+ placeholder: "\u6062\u590D\u7406\u7531\uFF08\u5FC5\u586B\uFF09",
886
+ autoFocus: true,
887
+ value: reopenReason,
888
+ onChange: (e) => {
889
+ setReopenReason(e.target.value);
890
+ if (reopenError) setReopenError(null);
891
+ },
892
+ onKeyDown: (e) => {
893
+ if (e.key === "Enter") void confirmReopen();
894
+ }
895
+ }
896
+ ),
897
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dsh-kb-rename-modal__hint", children: "\u6062\u590D\u7406\u7531\u5FC5\u586B\uFF08\u5BA1\u8BA1\u7559\u75D5\uFF09\uFF1B\u586B\u5199\u540E\u70B9\u300C\u786E\u8BA4\u6062\u590D\u300D\u3002" }),
898
+ reopenError && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dsh-kb-delete-modal__error", role: "alert", children: reopenError }),
899
+ reopenOk && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dsh-kb-rename-modal__success", role: "status", children: "\u2713 \u5DF2\u6062\u590D\uFF0C\u7F16\u6392\u5668\u5C06\u7EE7\u7EED\u63A8\u8FDB\u540E\u7EED\u9636\u6BB5" }),
900
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dsh-kb-rename-modal__actions", children: [
901
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "dsh-kb-rename-cancel", disabled: reopenBusy, onClick: closeReopen, children: "\u53D6\u6D88" }),
902
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "dsh-kb-rename-save", disabled: reopenBusy || reopenOk, onClick: () => void confirmReopen(), children: reopenOk ? "\u5DF2\u6062\u590D" : reopenBusy ? "\u6062\u590D\u4E2D\u2026" : "\u786E\u8BA4\u6062\u590D" })
903
+ ] })
904
+ ]
905
+ }
906
+ ) }),
810
907
  deletingView && props.onDeleteChain && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dsh-kb-rename-overlay", onClick: (e) => {
811
908
  e.stopPropagation();
812
909
  setDeletingChainId(null);
@@ -866,6 +963,10 @@ window.__ModuleLoader__.load({
866
963
  "chain/title-updated": "neutral",
867
964
  "chain/im-delivery-failed": "exception",
868
965
  // IM 投递失败留痕(非状态转换注记)
966
+ "chain/reopened": "running",
967
+ // 人工恢复(blocked → executing)
968
+ "review/waived": "success",
969
+ // 人工评审豁免(放行)
869
970
  "spec-card/created": "neutral",
870
971
  "spec-card/edited": "neutral",
871
972
  "spec-card/approved": "success",
@@ -900,6 +1001,7 @@ window.__ModuleLoader__.load({
900
1001
  "chain/audit-confirmed": "\u8D8A\u6743\u5DF2\u786E\u8BA4",
901
1002
  "chain/title-updated": "\u94FE\u8DEF\u6539\u540D",
902
1003
  "chain/im-delivery-failed": "IM \u6295\u9012\u5931\u8D25",
1004
+ "chain/reopened": "\u4EBA\u5DE5\u6062\u590D\u94FE\u8DEF",
903
1005
  "spec-card/created": "\u89C4\u683C\u5361\u521B\u5EFA",
904
1006
  "spec-card/edited": "\u89C4\u683C\u5361\u7F16\u8F91",
905
1007
  "spec-card/approved": "\u89C4\u683C\u5361\u6279\u51C6",
@@ -918,7 +1020,8 @@ window.__ModuleLoader__.load({
918
1020
  "task/renamed": "\u4EFB\u52A1\u6539\u540D",
919
1021
  "review/passed": "\u8BC4\u5BA1\u901A\u8FC7",
920
1022
  "review/failed": "\u8BC4\u5BA1\u9A73\u56DE",
921
- "review/gave-up": "\u8BC4\u5BA1\u8D85\u9650\u653E\u5F03"
1023
+ "review/gave-up": "\u8BC4\u5BA1\u8D85\u9650\u653E\u5F03",
1024
+ "review/waived": "\u8BC4\u5BA1\u8C41\u514D"
922
1025
  };
923
1026
  var AUTHOR_NAME = {
924
1027
  v: "orchestrator",
@@ -1055,8 +1158,13 @@ window.__ModuleLoader__.load({
1055
1158
  const { task, events, handoff, specCard, chain } = props;
1056
1159
  const [tab, setTab] = (0, import_react5.useState)("overview");
1057
1160
  const [pending, setPending] = (0, import_react5.useState)(null);
1161
+ const [waiveError, setWaiveError] = (0, import_react5.useState)(null);
1162
+ const [waiveBusy, setWaiveBusy] = (0, import_react5.useState)(false);
1163
+ const [waiveOk, setWaiveOk] = (0, import_react5.useState)(false);
1058
1164
  const timeline = events.filter((e) => e.taskId === task.id).toSorted((a, b) => a.seq - b.seq);
1059
1165
  const comments = timeline.filter((e) => e.kind === "task/commented");
1166
+ const reviewOutcome = task.mode === "review-plan" || task.mode === "review-impl" ? events.filter((e) => e.taskId === task.id && e.kind.startsWith("review/")).at(-1)?.kind ?? null : null;
1167
+ const canWaive = reviewOutcome === "review/failed" || reviewOutcome === "review/gave-up";
1060
1168
  const submitComment = (el) => {
1061
1169
  const value = el.value.trim();
1062
1170
  if (!value) return;
@@ -1074,6 +1182,28 @@ window.__ModuleLoader__.load({
1074
1182
  setPending(null);
1075
1183
  props.onAction({ type: "archive", taskId: task.id });
1076
1184
  };
1185
+ const submitWaive = async () => {
1186
+ if (pending?.kind !== "waive") return;
1187
+ const reason = pending.value.trim();
1188
+ if (!reason) {
1189
+ setWaiveError("\u8BF7\u586B\u5199\u8C41\u514D\u7406\u7531\uFF08\u5FC5\u586B\uFF0C\u7528\u4E8E\u5BA1\u8BA1\u7559\u75D5\uFF09");
1190
+ return;
1191
+ }
1192
+ setWaiveError(null);
1193
+ setWaiveBusy(true);
1194
+ try {
1195
+ await props.onAction({ type: "waive-review", taskId: task.id, reason });
1196
+ setWaiveOk(true);
1197
+ window.setTimeout(() => {
1198
+ setPending(null);
1199
+ setWaiveOk(false);
1200
+ }, 800);
1201
+ } catch (err) {
1202
+ setWaiveError("\u8C41\u514D\u5931\u8D25\uFF1A" + String(err));
1203
+ } finally {
1204
+ setWaiveBusy(false);
1205
+ }
1206
+ };
1077
1207
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dsh-kb-detail", children: [
1078
1208
  /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("header", { className: "dsh-kb-detail__header", children: [
1079
1209
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", "aria-label": "\u8FD4\u56DE\u4EFB\u52A1\u5217\u8868", onClick: props.onClose, children: "\u2190" }),
@@ -1095,7 +1225,19 @@ window.__ModuleLoader__.load({
1095
1225
  !props.readOnly && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dsh-kb-detail__actions", children: [
1096
1226
  task.status === "blocked" && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", onClick: () => props.onAction({ type: "unblock", taskId: task.id }), children: "\u89E3\u9664\u963B\u585E" }),
1097
1227
  task.status === "failed" && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", onClick: () => props.onAction({ type: "retry", taskId: task.id }), children: "\u91CD\u8BD5" }),
1098
- ["done", "failed", "blocked"].includes(task.status) && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", "data-confirming": pending?.kind === "archive" || void 0, onClick: pending?.kind === "archive" ? submitArchive : () => arm("archive"), children: pending?.kind === "archive" ? "\u786E\u8BA4\u5F52\u6863" : "\u5F52\u6863" })
1228
+ ["done", "failed", "blocked"].includes(task.status) && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", "data-confirming": pending?.kind === "archive" || void 0, onClick: pending?.kind === "archive" ? submitArchive : () => arm("archive"), children: pending?.kind === "archive" ? "\u786E\u8BA4\u5F52\u6863" : "\u5F52\u6863" }),
1229
+ canWaive && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1230
+ "button",
1231
+ {
1232
+ type: "button",
1233
+ onClick: () => {
1234
+ setPending({ kind: "waive", value: "" });
1235
+ setWaiveError(null);
1236
+ setWaiveOk(false);
1237
+ },
1238
+ children: "\u8C41\u514D\u8BC4\u5BA1"
1239
+ }
1240
+ )
1099
1241
  ] })
1100
1242
  ] }),
1101
1243
  props.actionError?.taskId === task.id && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dsh-kb-action-error", role: "alert", children: [
@@ -1227,7 +1369,60 @@ window.__ModuleLoader__.load({
1227
1369
  }
1228
1370
  }
1229
1371
  )
1230
- ] })
1372
+ ] }),
1373
+ !props.readOnly && pending?.kind === "waive" && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dsh-kb-rename-overlay", onClick: (e) => {
1374
+ e.stopPropagation();
1375
+ if (!waiveBusy) {
1376
+ setPending(null);
1377
+ setWaiveError(null);
1378
+ }
1379
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
1380
+ "div",
1381
+ {
1382
+ className: "dsh-kb-rename-modal",
1383
+ role: "dialog",
1384
+ "aria-modal": "true",
1385
+ "aria-label": "\u8C41\u514D\u8BC4\u5BA1",
1386
+ onClick: (e) => e.stopPropagation(),
1387
+ children: [
1388
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dsh-kb-rename-modal__label", children: "\u8C41\u514D\u8BC4\u5BA1" }),
1389
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dsh-kb-delete-modal__text", children: [
1390
+ "\u8C41\u514D\u300C",
1391
+ task.title,
1392
+ "\u300D\uFF08",
1393
+ task.id,
1394
+ "\uFF09\u7684\u8BC4\u5BA1\u7ED3\u8BBA\uFF1A\u88AB\u8BC4\u5BA1\u5361\u7F6E\u4E3A waived\uFF0C\u94FE\u8DEF\u6309\u8BC4\u5BA1\u901A\u8FC7\u7EE7\u7EED\u63A8\u8FDB\uFF08\u8BE5\u8BC4\u5BA1\u7684\u9057\u7559\u95EE\u9898\u4ECD\u4F5C\u4E3A\u975E\u963B\u585E\u5EFA\u8BAE\u4F20\u4E0B\u6E38\uFF09\u3002\u8BF7\u586B\u5199\u8C41\u514D\u7406\u7531\u3002"
1395
+ ] }),
1396
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1397
+ "input",
1398
+ {
1399
+ className: "dsh-kb-comment-input",
1400
+ "aria-label": "\u8C41\u514D\u7406\u7531",
1401
+ placeholder: "\u8C41\u514D\u7406\u7531\uFF08\u5FC5\u586B\uFF09",
1402
+ autoFocus: true,
1403
+ value: pending.value,
1404
+ onChange: (e) => {
1405
+ setPending({ kind: "waive", value: e.target.value });
1406
+ if (waiveError) setWaiveError(null);
1407
+ },
1408
+ onKeyDown: (e) => {
1409
+ if (e.key === "Enter") void submitWaive();
1410
+ }
1411
+ }
1412
+ ),
1413
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dsh-kb-rename-modal__hint", children: "\u8C41\u514D\u7406\u7531\u5FC5\u586B\uFF08\u5BA1\u8BA1\u7559\u75D5\uFF09\uFF1B\u586B\u5199\u540E\u70B9\u300C\u786E\u8BA4\u8C41\u514D\u300D\u3002" }),
1414
+ waiveError && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dsh-kb-delete-modal__error", role: "alert", children: waiveError }),
1415
+ waiveOk && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dsh-kb-rename-modal__success", role: "status", children: "\u2713 \u5DF2\u8C41\u514D\uFF0C\u94FE\u8DEF\u5C06\u7EE7\u7EED\u63A8\u8FDB" }),
1416
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dsh-kb-rename-modal__actions", children: [
1417
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: "dsh-kb-rename-cancel", disabled: waiveBusy, onClick: () => {
1418
+ setPending(null);
1419
+ setWaiveError(null);
1420
+ }, children: "\u53D6\u6D88" }),
1421
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: "dsh-kb-rename-save", disabled: waiveBusy || waiveOk, onClick: () => void submitWaive(), children: waiveOk ? "\u5DF2\u8C41\u514D" : waiveBusy ? "\u8C41\u514D\u4E2D\u2026" : "\u786E\u8BA4\u8C41\u514D" })
1422
+ ] })
1423
+ ]
1424
+ }
1425
+ ) })
1231
1426
  ] });
1232
1427
  }
1233
1428
 
@@ -1332,7 +1527,7 @@ window.__ModuleLoader__.load({
1332
1527
  readOnly: task.status === "archived",
1333
1528
  onRetry: failedAction && failedAction.taskId === task.id ? () => void runAction(failedAction.action) : void 0,
1334
1529
  onComment: (body) => void runAction({ type: "comment", taskId: task.id, body }),
1335
- onAction: (action) => void runAction(action),
1530
+ onAction: (action) => runAction(action),
1336
1531
  onClose: () => history.back()
1337
1532
  }
1338
1533
  );
@@ -1366,6 +1561,7 @@ window.__ModuleLoader__.load({
1366
1561
  onOpenView: props.onOpenView,
1367
1562
  onConfirmAudit: (chainId) => void runAction({ type: "confirm-audit", chainId }),
1368
1563
  onRenameChain: (chainId, title) => void runAction({ type: "rename", chainId, title }),
1564
+ onReopenChain: (chainId, reason) => props.postAction({ type: "reopen-chain", chainId, reason }).then(() => void 0),
1369
1565
  onDeleteChain: async (chainId) => {
1370
1566
  await props.postAction({ type: "delete", chainId });
1371
1567
  await props.onResync?.();
@@ -1411,7 +1607,7 @@ window.__ModuleLoader__.load({
1411
1607
  // client/config-store.ts
1412
1608
  var SWARM_CONFIG_NS = "swarm-config";
1413
1609
  function createConfigStore(fetchImpl) {
1414
- let state = { effective: { wikiVault: { baseUrl: "", pagePrefix: "" }, roles: { models: {} }, reviewEngine: { mode: "delegate", managed: { provider: "", model: "" } } }, sources: {}, catalog: { providers: [], models: {} }, ocrStatus: null, install: { phase: "idle", log: "" }, saving: false, error: null };
1610
+ let state = { effective: { wikiVault: { baseUrl: "", pagePrefix: "" }, roles: { models: {} }, reviewEngine: { mode: "delegate", managed: { provider: "", model: "" } }, imDelivery: { fallbackBotId: "" } }, sources: {}, catalog: { providers: [], models: {} }, ocrStatus: null, install: { phase: "idle", log: "" }, saving: false, error: null };
1415
1611
  const listeners = /* @__PURE__ */ new Set();
1416
1612
  const setState = (patch) => {
1417
1613
  state = { ...state, ...patch };
@@ -1794,7 +1990,889 @@ window.__ModuleLoader__.load({
1794
1990
  }
1795
1991
 
1796
1992
  // client/kanban.css
1797
- var kanban_default = "/* T32\uFF1A\u5361\u7247/\u8FDE\u63A5\u7EBF\u7B49\u5C40\u90E8\u8FC7\u6E21\u4FDD\u6301 120-180ms\uFF1Bprefers-reduced-motion \u5168\u5C40\u5173\u95ED */\n.dsh-kb-tab {\n /* DSH \u8BBE\u8BA1\u4EE4\u724C\uFF08\u6D45/\u6DF1\u8272\u968F body[data-ds-dark-theme] \u81EA\u52A8\u5207\u6362\uFF09\u2014\u2014\u7981\u6B62\u786C\u7F16\u7801\u989C\u8272 */\n --dsh-kb-surface: var(--dsw-alias-bg-layer-1);\n --dsh-kb-surface-elev: var(--dsw-alias-bg-layer-3);\n --dsh-kb-text-primary: var(--dsw-alias-label-primary);\n --dsh-kb-text-secondary: var(--dsw-alias-label-secondary);\n --dsh-kb-text-tertiary: var(--dsw-alias-label-tertiary);\n --dsh-kb-border: var(--dsw-alias-border-l2);\n --dsh-kb-hover: var(--dsw-alias-interactive-bg-hover);\n --dsh-kb-mask: var(--dsw-alias-bg-mask-3);\n --dsh-kb-input: var(--dsw-specific-input-major);\n --dsh-kb-inline-code: var(--dsw-alias-markdown-inline-code);\n /* \u5927\u5706\u89D2\u5951\u7EA6\uFF08\u5BF9\u9F50 DSH \u5361\u7247 16px\uFF09\uFF0C\u540E\u7EED UI \u4E00\u5F8B\u590D\u7528 */\n --dsh-kb-radius-lg: 16px;\n --dsh-kb-radius-md: 10px;\n --dsh-kb-radius-sm: 8px;\n /* \u72B6\u6001\u8272 \u2192 DSH \u8BED\u4E49\u4EE4\u724C */\n --dsh-kb-complete: var(--dsw-alias-state-success-primary);\n --dsh-kb-active: var(--dsw-alias-state-business-primary);\n --dsh-kb-blocked: var(--dsw-alias-state-error-primary);\n --dsh-kb-pending: currentColor;\n /* \u89D2\u8272\u8272\uFF1ADSH \u6709\u7B49\u4EF7\u4EE4\u724C\u5219\u590D\u7528\uFF1Bp/pt/dt \u65E0 DSH \u7B49\u4EF7\u8272\uFF0C\u4FDD\u7559\u539F\u503C */\n --dsh-kb-v: var(--dsw-alias-state-business-primary);\n --dsh-kb-p: #a855f7;\n --dsh-kb-w: var(--dsw-alias-state-success-primary);\n --dsh-kb-d: var(--dsw-alias-state-warn-primary);\n --dsh-kb-pt: #6366f1; /* \u8BA1\u5212\u8BC4\u5BA1\uFF1A\u975B/\u6D45\u84DD */\n --dsh-kb-dt: #ec4899; /* \u5B9E\u73B0\u8BC4\u5BA1\uFF1A\u73AB\u7EA2 */\n height: 100%;\n width: 100%;\n /* \u63A5\u5165\u5BBF\u4E3B\u4F1A\u8BDD\u6D41\u5BBD\u5EA6\u7CFB\u7EDF\uFF1A\u81EA\u9002\u5E94 clamp + \u62D6\u62FD\u504F\u597D\uFF08--dsh-chat-content-width \u7531\n \u5BBF\u4E3B ConversationRoot \u5B9A\u4E49\uFF0C\u62D6\u62FD\u624B\u67C4\u5B98\u65B9\u5DF2\u5B9E\u73B0\uFF09\uFF1B780px \u4EC5\u4E3A\u53D8\u91CF\u7F3A\u5931\u65F6\u7684\u515C\u5E95 */\n min-width: 0;\n max-width: var(--dsh-chat-content-width, 780px);\n margin-inline: auto;\n display: flex;\n flex-direction: column;\n color: inherit;\n background: var(--dsw-alias-bg-base);\n pointer-events: auto;\n font-size: 13px;\n line-height: 1.45;\n overflow: hidden;\n}\n\n.dsh-kb-banner {\n flex: 0 0 auto;\n padding: 6px 12px;\n font-size: 12px;\n border-bottom: 1px solid var(--dsh-kb-border);\n}\n.dsh-kb-banner--reconnecting,\n.dsh-kb-banner--loading {\n color: var(--dsh-kb-active);\n}\n.dsh-kb-banner--error {\n color: var(--dsh-kb-blocked);\n}\n\n.dsh-kb-tab-body {\n flex: 1 1 auto;\n min-height: 0;\n overflow: auto;\n padding: 8px;\n}\n\n.dsh-kb-loading {\n flex: 1 1 auto;\n display: flex;\n align-items: center;\n justify-content: center;\n color: currentColor;\n opacity: 0.7;\n}\n\n.dsh-kb-toolbar {\n position: sticky;\n top: 0;\n z-index: 1;\n padding-bottom: 8px;\n}\n.dsh-kb-toolbar input {\n width: 100%;\n box-sizing: border-box;\n padding: 6px 10px;\n border: 1px solid var(--dsh-kb-border);\n border-radius: var(--dsh-kb-radius-md);\n background: var(--dsh-kb-input);\n color: var(--dsh-kb-text-primary);\n}\n\n.dsh-kb-rail {\n display: flex;\n flex-direction: column;\n}\n/* \u72B6\u6001\u7B5B\u9009 chip \u7EC4\uFF1A\u6267\u884C\u4E2D/\u963B\u585E/\u5931\u8D25/\u5DF2\u5B8C\u6210\uFF08\u591A\u9009\u5E76\u96C6\uFF1B\u7A7A=\u9ED8\u8BA4\u89C6\u56FE\uFF09 */\n.dsh-kb-filters {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n padding: 0 0 8px;\n}\n.dsh-kb-filter {\n display: inline-flex;\n align-items: center;\n padding: 2px 10px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 999px;\n background: transparent;\n color: currentColor;\n font: inherit;\n cursor: pointer;\n user-select: none;\n transition: background-color 150ms ease, border-color 150ms ease, color 150ms ease;\n}\n.dsh-kb-filter:hover {\n background: var(--dsh-kb-hover);\n}\n.dsh-kb-filter--active {\n border-color: var(--dsh-kb-active);\n color: var(--dsh-kb-active);\n background: color-mix(in srgb, var(--dsh-kb-active) 10%, transparent);\n}\n\n.dsh-kb-chain {\n margin-bottom: 10px;\n}\n.dsh-kb-chain__title {\n display: flex;\n align-items: center;\n gap: 8px;\n box-sizing: border-box;\n width: 100%;\n padding: 6px 8px;\n border: 0;\n border-radius: var(--dsh-kb-radius-sm);\n background: transparent;\n color: var(--dsh-kb-text-primary);\n font: inherit;\n text-align: left;\n cursor: pointer;\n transition: background-color 150ms ease;\n}\n.dsh-kb-chain__title:hover {\n background: var(--dsh-kb-hover);\n}\n/* \u6BCF\u6761\u94FE\u8DEF\u524D\u7684\u6298\u53E0\u7BAD\u5934\uFF08\u4E0E DSH \u6298\u53E0\u4EA4\u4E92\u4E00\u81F4\uFF1A\u7EC6 chevron\uFF0C\u5C55\u5F00\u65F6\u65CB\u8F6C\uFF0C150ms \u8FC7\u6E21\uFF09 */\n.dsh-kb-chain__chevron {\n flex: 0 0 auto;\n width: 7px;\n height: 7px;\n border-top: 1.5px solid currentColor;\n border-right: 1.5px solid currentColor;\n transform: rotate(45deg);\n opacity: 0.7;\n transition: transform 150ms ease;\n}\n.dsh-kb-chain__title[aria-expanded='true'] .dsh-kb-chain__chevron {\n transform: rotate(135deg);\n}\n.dsh-kb-chain__name {\n flex: 1 1 auto;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.dsh-kb-chain__meta {\n flex: 0 0 auto;\n white-space: nowrap;\n opacity: 0.7;\n}\n.dsh-kb-chain__warning {\n padding: 4px 8px;\n margin: 2px 0 6px;\n border-left: 3px solid var(--dsh-kb-blocked);\n color: var(--dsh-kb-blocked);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n/* D23\uFF1A\u94FE\u5B8C\u6210\u9A8C\u6536\u6838\u5BF9\u8B66\u544A\u884C\uFF08completed \u94FE\u672A\u786E\u8BA4\u524D\u963B\u585E\u6700\u7EC8\u6C47\u62A5\uFF09 */\n.dsh-kb-chain__audit {\n display: flex;\n align-items: center;\n gap: 8px;\n white-space: normal;\n}\n.dsh-kb-chain__audit span {\n flex: 1 1 auto;\n overflow: hidden;\n}\n.dsh-kb-audit-confirm {\n flex: 0 0 auto;\n border: 1px solid var(--dsh-kb-blocked);\n border-radius: var(--dsh-kb-radius-sm);\n background: transparent;\n color: var(--dsh-kb-blocked);\n padding: 2px 10px;\n cursor: pointer;\n font: inherit;\n transition: background-color 150ms ease, color 150ms ease;\n}\n.dsh-kb-audit-confirm:hover {\n background: var(--dsh-kb-blocked);\n color: #fff;\n}\n\n.dsh-kb-nodes {\n list-style: none;\n margin: 0;\n padding: 0 0 0 12px;\n display: flex;\n flex-direction: column;\n gap: 0;\n}\n.dsh-kb-node {\n position: relative;\n padding-left: 12px;\n}\n.dsh-kb-node::before {\n content: '';\n position: absolute;\n left: 0;\n top: 0;\n bottom: 0;\n width: 2px;\n background: var(--dsh-kb-pending);\n transition: background-color 150ms ease;\n}\n.dsh-kb-node--complete::before { background: var(--dsh-kb-complete); }\n.dsh-kb-node--active::before { background: var(--dsh-kb-active); }\n.dsh-kb-node--pending::before {\n background: repeating-linear-gradient(to bottom, currentColor 0 3px, transparent 3px 6px);\n}\n.dsh-kb-node--blocked::before {\n background: repeating-linear-gradient(to bottom, var(--dsh-kb-blocked) 0 4px, transparent 4px 8px);\n}\n\n.dsh-kb-task {\n display: grid;\n grid-template-columns: 22px 1fr auto;\n grid-template-rows: auto auto;\n gap: 2px 8px;\n width: 100%;\n box-sizing: border-box;\n padding: 6px 8px;\n margin: 4px 0;\n border: 1px solid transparent;\n border-radius: var(--dsh-kb-radius-lg);\n background: transparent;\n color: var(--dsh-kb-text-primary);\n font: inherit;\n text-align: left;\n cursor: pointer;\n transition: border-color 150ms ease, background-color 150ms ease, opacity 150ms ease;\n}\n.dsh-kb-task:hover {\n background: var(--dsh-kb-hover);\n}\n.dsh-kb-task[data-selected],\n.dsh-kb-task--active {\n border-color: var(--dsh-kb-active);\n}\n/* T32\uFF1A\u5B8C\u6210\u4EFB\u52A1\u4FDD\u7559\u5728\u8F68\u9053\u4F46\u89C6\u89C9\u964D\u6743\uFF1B\u72B6\u6001\u8272\u4E0D\u53D8\u3001\u4E0D\u6574\u5361\u67D3\u8272 */\n.dsh-kb-task--complete {\n opacity: 0.72;\n}\n.dsh-kb-task__title {\n grid-column: 2;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.dsh-kb-task__status {\n grid-column: 3;\n color: currentColor;\n opacity: 0.75;\n}\n.dsh-kb-task__meta {\n grid-column: 2 / 4;\n opacity: 0.6;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.dsh-kb-task__warn {\n grid-column: 2 / 4;\n display: inline-flex;\n align-items: center;\n gap: 4px;\n color: var(--dsh-kb-blocked);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.dsh-kb-task__warn svg {\n flex: 0 0 auto;\n}\n.dsh-kb-task__warn span {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.dsh-kb-task--complete .dsh-kb-task__status { color: var(--dsh-kb-complete); }\n.dsh-kb-task--blocked .dsh-kb-task__status { color: var(--dsh-kb-blocked); }\n/* D17\uFF1A\u9009\u4E2D\u4EFB\u52A1\u6240\u5728\u94FE\u8DEF\u7684\u4E0A\u6E38/\u5F53\u524D/\u4E0B\u6E38\u8DEF\u5F84\u5361\u9AD8\u4EAE\uFF1B\u4E0D\u6539\u53D8\u8FDE\u63A5\u7EBF\u8BED\u4E49\uFF0C\u9009\u4E2D\u5361\u4FDD\u6301\u5F3A\u8FB9\u6846 */\n.dsh-kb-task--related:not(.dsh-kb-task--active) {\n border-color: color-mix(in srgb, var(--dsh-kb-active) 35%, transparent);\n background: color-mix(in srgb, var(--dsh-kb-active) 6%, transparent);\n}\n\n.dsh-kb-empty {\n padding: 24px 12px;\n text-align: center;\n color: var(--dsh-kb-text-secondary);\n border: 1px dashed var(--dsh-kb-border);\n border-radius: var(--dsh-kb-radius-lg);\n}\n\n.dsh-kb-profile {\n grid-row: 1 / 3;\n align-self: start;\n width: 20px;\n height: 20px;\n border-radius: var(--dsh-kb-radius-sm);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n font-size: 11px;\n font-weight: 700;\n color: #fff;\n}\n.dsh-kb-profile--v { background: var(--dsh-kb-v); }\n.dsh-kb-profile--p { background: var(--dsh-kb-p); }\n.dsh-kb-profile--w { background: var(--dsh-kb-w); }\n.dsh-kb-profile--d { background: var(--dsh-kb-d); }\n.dsh-kb-profile--pt { background: var(--dsh-kb-pt); }\n.dsh-kb-profile--dt { background: var(--dsh-kb-dt); }\n\n/* T27\uFF1A\u4EFB\u52A1\u5361\u5F39\u7A97\uFF08\u539F\u4F4D\u8BE6\u60C5\uFF09\u2014\u2014DSH \u9762\u677F\u98CE\u683C\uFF1A\u5927\u5706\u89D2 + \u62AC\u5347\u8868\u9762 + \u6D45/\u6DF1\u8272\u4EE4\u724C */\n.dsh-kb-detail {\n display: flex;\n flex-direction: column;\n min-height: calc(100% - 16px);\n margin: 8px;\n padding: 12px 16px;\n box-sizing: border-box;\n border: 1px solid var(--dsh-kb-border);\n border-radius: var(--dsh-kb-radius-lg);\n background: var(--dsh-kb-surface);\n color: var(--dsh-kb-text-primary);\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);\n}\n.dsh-kb-detail__header {\n display: flex;\n align-items: center;\n gap: 8px;\n padding-bottom: 8px;\n border-bottom: 1px solid var(--dsh-kb-border);\n}\n.dsh-kb-detail__header > button:not(.dsh-kb-unread) {\n flex: 0 0 auto;\n width: 28px;\n height: 28px;\n border: 1px solid var(--dsh-kb-border);\n border-radius: var(--dsh-kb-radius-md);\n background: transparent;\n color: var(--dsh-kb-text-primary);\n cursor: pointer;\n font: inherit;\n line-height: 1;\n transition: background-color 150ms ease;\n}\n.dsh-kb-detail__header > button:not(.dsh-kb-unread):hover {\n background: var(--dsh-kb-hover);\n}\n.dsh-kb-detail__identity {\n flex: 1 1 auto;\n min-width: 0;\n}\n.dsh-kb-detail__identity strong,\n.dsh-kb-detail__identity span {\n display: block;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.dsh-kb-detail__actions {\n display: flex;\n gap: 4px;\n flex: 0 0 auto;\n}\n.dsh-kb-detail__actions button {\n border: 1px solid var(--dsh-kb-border);\n border-radius: var(--dsh-kb-radius-md);\n background: transparent;\n color: var(--dsh-kb-text-primary);\n padding: 4px 10px;\n cursor: pointer;\n font: inherit;\n transition: border-color 150ms ease, color 150ms ease, background-color 150ms ease;\n}\n.dsh-kb-detail__actions button:hover {\n background: var(--dsh-kb-hover);\n}\n.dsh-kb-detail__actions button[data-confirming='true'] {\n border-color: var(--dsh-kb-blocked);\n color: var(--dsh-kb-blocked);\n}\n.dsh-kb-detail__actions button:disabled {\n opacity: 0.5;\n cursor: default;\n}\n.dsh-kb-action-form {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n}\n.dsh-kb-action-form input {\n width: 140px;\n padding: 3px 8px;\n border: 1px solid var(--dsh-kb-border);\n border-radius: var(--dsh-kb-radius-sm);\n background: var(--dsh-kb-input);\n color: var(--dsh-kb-text-primary);\n font: inherit;\n font-size: 12px;\n}\n/* \u8BC4\u8BBA\u8F93\u5165\uFF1A\u6309 DSH \u53D1\u9001\u6D88\u606F\u6846\u98CE\u683C\u7EDF\u4E00\uFF08\u5927\u5706\u89D2\u590D\u7528 16px \u5951\u7EA6\u4EE4\u724C\uFF09 */\n.dsh-kb-comment-input {\n display: block;\n width: 100%;\n box-sizing: border-box;\n margin-top: 8px;\n padding: 10px 14px;\n border: 1px solid var(--dsh-kb-border);\n border-radius: var(--dsh-kb-radius-lg); /* \u5927\u5706\u89D2\u53D1\u9001\u6846\uFF1A\u590D\u7528 16px \u5951\u7EA6 */\n background: var(--dsh-kb-input);\n color: var(--dsh-kb-text-primary);\n font: inherit;\n}\n.dsh-kb-comment-input:focus {\n outline: none;\n border-color: var(--dsh-kb-active);\n}\n.dsh-kb-comment-input::placeholder {\n color: var(--dsh-kb-text-tertiary);\n}\n.dsh-kb-unread {\n flex: 0 0 auto;\n border: 1px solid var(--dsh-kb-active);\n border-radius: 999px;\n background: color-mix(in srgb, var(--dsh-kb-active) 12%, transparent);\n color: var(--dsh-kb-active);\n padding: 2px 8px;\n font: inherit;\n font-size: 12px;\n white-space: nowrap;\n cursor: pointer;\n}\n.dsh-kb-action-error {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 8px;\n margin: 4px 0;\n border-left: 3px solid var(--dsh-kb-blocked);\n color: var(--dsh-kb-blocked);\n font-size: 12px;\n}\n.dsh-kb-action-error span {\n flex: 1 1 auto;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.dsh-kb-action-error button {\n flex: 0 0 auto;\n border: 1px solid currentColor;\n border-radius: var(--dsh-kb-radius-sm);\n background: transparent;\n color: inherit;\n padding: 1px 6px;\n cursor: pointer;\n font: inherit;\n}\n.dsh-kb-detail [role='tablist'] {\n display: flex;\n gap: 4px;\n padding: 8px 0;\n border-bottom: 1px solid var(--dsh-kb-border);\n}\n.dsh-kb-detail [role='tab'] {\n border: 0;\n border-radius: var(--dsh-kb-radius-sm);\n background: transparent;\n color: var(--dsh-kb-text-secondary);\n padding: 4px 10px;\n cursor: pointer;\n transition: background-color 150ms ease, color 150ms ease;\n}\n.dsh-kb-detail [role='tab']:hover {\n color: var(--dsh-kb-text-primary);\n background: var(--dsh-kb-hover);\n}\n.dsh-kb-detail [role='tab'][aria-selected='true'] {\n background: var(--dsh-kb-hover);\n color: var(--dsh-kb-text-primary);\n}\n.dsh-kb-detail [role='tabpanel'] {\n padding: 8px 0;\n overflow: auto;\n}\n.dsh-kb-detail h4 {\n margin: 8px 0 4px;\n font-size: 12px;\n text-transform: none;\n color: var(--dsh-kb-text-secondary);\n}\n.dsh-kb-detail code {\n background: var(--dsh-kb-inline-code);\n border-radius: var(--dsh-kb-radius-sm);\n padding: 1px 4px;\n}\n.dsh-kb-detail dl {\n display: grid;\n grid-template-columns: auto 1fr;\n gap: 4px 8px;\n margin: 8px 0;\n}\n.dsh-kb-detail dt { opacity: 0.7; color: var(--dsh-kb-text-tertiary); }\n.dsh-kb-detail dd { margin: 0; }\n.dsh-kb-detail time { opacity: 0.6; font-size: 12px; margin-inline-end: 4px; }\n\n/* \u8F68\u8FF9 tab \u53EF\u8BFB\u5316\uFF1A\u7269\u6D41\u5F0F\u7EB5\u5411\u65F6\u95F4\u8F74\uFF08\u56DB\u6001\u914D\u8272 + \u6700\u65B0\u8282\u70B9\u9AD8\u4EAE\uFF1B\u5F02\u5E38\u6574\u884C\u6807\u7EA2\uFF09 */\n.dsh-kb-timeline {\n list-style: none;\n margin: 0;\n padding: 0;\n display: flex;\n flex-direction: column;\n}\n.dsh-kb-timeline__item {\n position: relative;\n display: grid;\n grid-template-columns: 16px 1fr;\n gap: 8px;\n padding: 0 0 14px;\n}\n.dsh-kb-timeline__item:last-child {\n padding-bottom: 0;\n}\n/* \u7EB5\u5411\u65F6\u95F4\u7EBF\uFF1A\u8D2F\u7A7F\u8282\u70B9\uFF08\u6700\u65B0\u8282\u70B9\u4E0A\u65B9\u7EBF\u4E0D\u5EF6\u4F38\uFF0C\u6A21\u62DF\u7269\u6D41\u5934\u8282\u70B9\uFF09 */\n.dsh-kb-timeline__axis {\n position: relative;\n}\n.dsh-kb-timeline__item:not(:last-child) .dsh-kb-timeline__axis::after {\n content: '';\n position: absolute;\n left: 50%;\n top: 14px;\n bottom: -4px;\n width: 2px;\n transform: translateX(-50%);\n background: var(--dsh-kb-border);\n}\n.dsh-kb-timeline__dot {\n position: relative;\n z-index: 1;\n display: block;\n width: 10px;\n height: 10px;\n /* \u6C34\u5E73\u5C45\u4E2D\u4E8E 16px \u8F74\u5217\uFF08\u4E2D\u5FC3=8px\uFF09\uFF0C\u4E0E left:50% \u8FDE\u63A5\u7EBF\u5BF9\u9F50 */\n margin: 2px auto 0;\n border-radius: 50%;\n border: 2px solid var(--dsh-kb-surface);\n box-sizing: border-box;\n background: var(--dsh-kb-text-tertiary);\n}\n/* \u56DB\u6001\u914D\u8272\uFF1Aneutral \u7070 / running \u84DD / success \u7EFF / exception \u7EA2 */\n.dsh-kb-timeline__item--running .dsh-kb-timeline__dot {\n background: var(--dsh-kb-active);\n}\n.dsh-kb-timeline__item--success .dsh-kb-timeline__dot {\n background: var(--dsh-kb-complete);\n}\n.dsh-kb-timeline__item--exception .dsh-kb-timeline__dot {\n background: var(--dsh-kb-blocked);\n}\n/* \u6700\u65B0\u8282\u70B9\u9AD8\u4EAE\uFF1A\u4E3B\u8272\u5706\u70B9\u653E\u5927 + \u67D4\u548C\u8F89\u5149 */\n.dsh-kb-timeline__item--latest .dsh-kb-timeline__dot {\n width: 12px;\n height: 12px;\n margin-top: 0;\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--dsh-kb-active) 22%, transparent);\n}\n.dsh-kb-timeline__item--latest.dsh-kb-timeline__item--success .dsh-kb-timeline__dot {\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--dsh-kb-complete) 22%, transparent);\n}\n.dsh-kb-timeline__item--latest.dsh-kb-timeline__item--exception .dsh-kb-timeline__dot {\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--dsh-kb-blocked) 22%, transparent);\n}\n/* \u5F02\u5E38\u884C\uFF1A\u6D45\u7EA2\u5E95 + \u5DE6\u4FA7\u7EA2\u6761\uFF0C\u6458\u8981\u7EA2\u52A0\u7C97 */\n.dsh-kb-timeline__item--exception .dsh-kb-timeline__body {\n background: color-mix(in srgb, var(--dsh-kb-blocked) 8%, transparent);\n border-left: 3px solid var(--dsh-kb-blocked);\n border-radius: var(--dsh-kb-radius-sm);\n padding: 6px 8px;\n}\n.dsh-kb-timeline__body {\n min-width: 0;\n}\n.dsh-kb-timeline__row {\n display: flex;\n align-items: baseline;\n gap: 8px;\n flex-wrap: wrap;\n}\n.dsh-kb-timeline__label {\n font-size: 13px;\n font-weight: 600;\n color: var(--dsh-kb-text-primary);\n}\n.dsh-kb-timeline__item--success .dsh-kb-timeline__label {\n color: var(--dsh-kb-complete);\n}\n.dsh-kb-timeline__item--exception .dsh-kb-timeline__label {\n color: var(--dsh-kb-blocked);\n}\n.dsh-kb-timeline__summary {\n margin: 2px 0 0;\n font-size: 12px;\n color: var(--dsh-kb-text-secondary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.dsh-kb-timeline__item--exception .dsh-kb-timeline__summary {\n color: var(--dsh-kb-blocked);\n font-weight: 600;\n}\n.dsh-kb-timeline__author {\n display: block;\n margin-top: 2px;\n font-size: 11px;\n opacity: 0.7;\n color: var(--dsh-kb-text-tertiary);\n}\n\n.dsh-kb-spec-attachments {\n list-style: none;\n margin: 4px 0;\n padding: 0;\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n.dsh-kb-spec-attachments li {\n display: flex;\n align-items: baseline;\n gap: 6px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.dsh-kb-spec-attachment__kind {\n font-size: 11px;\n border: 1px solid var(--dsh-kb-border);\n border-radius: var(--dsh-kb-radius-sm);\n padding: 0 4px;\n opacity: 0.8;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .dsh-kb-tab * {\n transition-duration: 0ms !important;\n }\n}\n\n/* \u6574\u94FE\u5220\u9664\u6309\u94AE\uFF1A\u9ED8\u8BA4\u9690\u85CF\uFF0Chover \u9700\u6C42\u6807\u9898\u884C\u65F6\u51FA\u73B0\uFF08GUI \u4EC5 human\uFF0C\u4E8C\u6B21\u786E\u8BA4\uFF09 */\n.dsh-kb-chain__delete {\n flex: 0 0 auto;\n border: 0;\n background: transparent;\n color: currentColor;\n opacity: 0;\n font: inherit;\n line-height: 1;\n padding: 2px 4px;\n cursor: pointer;\n transition: opacity 150ms ease, color 150ms ease;\n}\n.dsh-kb-chain__title:hover .dsh-kb-chain__delete,\n.dsh-kb-chain__delete:focus-visible { opacity: 0.7; }\n.dsh-kb-chain__delete:hover { opacity: 1; color: var(--dsh-kb-blocked); }\n/* \u5220\u9664\u4E8C\u6B21\u786E\u8BA4\u5F39\u7A97\uFF08\u590D\u7528 rename \u5F39\u7A97\u5916\u58F3/\u5706\u89D2\u5951\u7EA6\uFF09 */\n.dsh-kb-delete-modal__text {\n color: var(--dsh-kb-text-secondary);\n font-size: 13px;\n line-height: 1.5;\n}\n.dsh-kb-delete-modal__error {\n color: var(--dsh-kb-blocked);\n font-size: 12px;\n}\n.dsh-kb-rename-modal__actions .dsh-kb-delete-confirm {\n border-color: transparent;\n background: var(--dsw-alias-state-error-primary);\n color: #fff;\n}\n/* T7\uFF1A\u94FE\u6807\u9898\u6539\u540D\u94C5\u7B14\u6309\u94AE + \u8F7B\u91CF\u5F39\u7A97\uFF08GUI \u4EC5 human\uFF1B\u89D2\u8272\u5361\u4E0D\u53EF\u6539\u540D\uFF09 */\n.dsh-kb-chain__rename {\n flex: 0 0 auto;\n border: 0;\n background: transparent;\n color: currentColor;\n opacity: 0.55;\n font: inherit;\n line-height: 1;\n padding: 2px 4px;\n cursor: pointer;\n}\n.dsh-kb-chain__rename:hover { opacity: 1; }\n.dsh-kb-task__status-row {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n.dsh-kb-task__session {\n flex: none;\n padding: 0 6px;\n font-size: 11px;\n line-height: 18px;\n border: 1px solid color-mix(in srgb, currentColor 40%, transparent);\n border-radius: 4px;\n background: transparent;\n color: inherit;\n cursor: pointer;\n opacity: 0.85;\n}\n.dsh-kb-task__session:hover {\n opacity: 1;\n}\n.dsh-kb-rename-overlay {\n position: fixed;\n inset: 0;\n z-index: 1000;\n background: var(--dsh-kb-mask);\n display: flex;\n align-items: center;\n justify-content: center;\n}\n.dsh-kb-rename-modal {\n display: flex;\n flex-direction: column;\n gap: 8px;\n min-width: 280px;\n padding: 16px;\n border: 1px solid var(--dsh-kb-border);\n border-radius: var(--dsh-kb-radius-lg);\n background: var(--dsh-kb-surface-elev);\n color: var(--dsh-kb-text-primary);\n box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);\n}\n.dsh-kb-rename-modal__label {\n color: var(--dsh-kb-text-primary);\n font-size: 13px;\n font-weight: 600;\n}\n.dsh-kb-rename-modal__input {\n padding: 6px 10px;\n border: 1px solid var(--dsh-kb-border);\n border-radius: var(--dsh-kb-radius-md);\n background: var(--dsh-kb-input);\n color: var(--dsh-kb-text-primary);\n font: inherit;\n}\n.dsh-kb-rename-modal__input:focus {\n outline: none;\n border-color: var(--dsh-kb-active);\n}\n.dsh-kb-rename-modal__actions {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n}\n.dsh-kb-rename-modal__actions button {\n border: 1px solid var(--dsh-kb-border);\n border-radius: var(--dsh-kb-radius-md);\n background: transparent;\n color: var(--dsh-kb-text-primary);\n font: inherit;\n padding: 4px 14px;\n cursor: pointer;\n transition: background-color 150ms ease;\n}\n.dsh-kb-rename-modal__actions button:hover {\n background: var(--dsh-kb-hover);\n}\n.dsh-kb-rename-modal__actions .dsh-kb-rename-save {\n border-color: transparent;\n background: var(--dsw-alias-button-primary-fill);\n color: var(--dsw-alias-label-primary-foreground);\n}\n\n/* Swarm \u914D\u7F6E\u9762\u677F\u300C\u8BC4\u5BA1\u5F15\u64CE\uFF08ocr\uFF09\u300D\u5361\uFF1A\u5B89\u88C5\u4E2D spinner \u884C\u4E0E\u72B6\u6001\u884C\uFF08\u6210\u529F\u7EFF / \u8B66\u793A\u9EC4\uFF09 */\n.dsh-kb-config__installing {\n display: flex;\n align-items: center;\n gap: 10px;\n margin: 8px 0;\n}\n.dsh-kb-config__installing button {\n margin-left: auto;\n padding: 4px 12px;\n border: 1px solid var(--dsh-kb-config-border, #333);\n border-radius: 10px;\n background: transparent;\n color: inherit;\n font: inherit;\n cursor: pointer;\n}\n.dsh-kb-config__installing-spinner {\n flex: 0 0 auto;\n width: 14px;\n height: 14px;\n border: 2px solid var(--dsw-alias-border-l2, #666);\n border-top-color: transparent;\n border-radius: 50%;\n animation: dsh-kb-ocr-spin 0.9s linear infinite;\n}\n@keyframes dsh-kb-ocr-spin {\n to { transform: rotate(360deg); }\n}\n.dsh-kb-config__ocr-ok { color: var(--dsw-alias-state-success-primary, #2e9e5b); margin: 6px 0; }\n.dsh-kb-config__ocr-warn { color: var(--dsw-alias-state-warning-primary, #b8860b); margin: 6px 0; }\n.dsh-kb-config__installing button,\n.dsh-kb-config__card > button {\n margin-top: 8px;\n}\n.dsh-kb-config__card > button {\n padding: 6px 16px;\n border: 1px solid var(--dsh-kb-config-border, #333);\n border-radius: 10px;\n background: transparent;\n color: inherit;\n font: inherit;\n cursor: pointer;\n transition: background-color 150ms ease;\n}\n.dsh-kb-config__card > button:hover:not([disabled]) { background: var(--dsw-alias-interactive-bg-hover, rgba(127, 127, 127, 0.12)); }\n.dsh-kb-config__card > button[disabled] { opacity: 0.5; cursor: not-allowed; }\n.dsh-kb-config__select-trigger:disabled { opacity: 0.5; cursor: not-allowed; }\n";
1993
+ var kanban_default = `/* T32\uFF1A\u5361\u7247/\u8FDE\u63A5\u7EBF\u7B49\u5C40\u90E8\u8FC7\u6E21\u4FDD\u6301 120-180ms\uFF1Bprefers-reduced-motion \u5168\u5C40\u5173\u95ED */
1994
+ .dsh-kb-tab {
1995
+ /* DSH \u8BBE\u8BA1\u4EE4\u724C\uFF08\u6D45/\u6DF1\u8272\u968F body[data-ds-dark-theme] \u81EA\u52A8\u5207\u6362\uFF09\u2014\u2014\u7981\u6B62\u786C\u7F16\u7801\u989C\u8272 */
1996
+ --dsh-kb-surface: var(--dsw-alias-bg-layer-1);
1997
+ --dsh-kb-surface-elev: var(--dsw-alias-bg-layer-3);
1998
+ --dsh-kb-text-primary: var(--dsw-alias-label-primary);
1999
+ --dsh-kb-text-secondary: var(--dsw-alias-label-secondary);
2000
+ --dsh-kb-text-tertiary: var(--dsw-alias-label-tertiary);
2001
+ --dsh-kb-border: var(--dsw-alias-border-l2);
2002
+ --dsh-kb-hover: var(--dsw-alias-interactive-bg-hover);
2003
+ --dsh-kb-mask: var(--dsw-alias-bg-mask-3);
2004
+ --dsh-kb-input: var(--dsw-specific-input-major);
2005
+ --dsh-kb-inline-code: var(--dsw-alias-markdown-inline-code);
2006
+ /* \u5927\u5706\u89D2\u5951\u7EA6\uFF08\u5BF9\u9F50 DSH \u5361\u7247 16px\uFF09\uFF0C\u540E\u7EED UI \u4E00\u5F8B\u590D\u7528 */
2007
+ --dsh-kb-radius-lg: 16px;
2008
+ --dsh-kb-radius-md: 10px;
2009
+ --dsh-kb-radius-sm: 8px;
2010
+ /* \u72B6\u6001\u8272 \u2192 DSH \u8BED\u4E49\u4EE4\u724C */
2011
+ --dsh-kb-complete: var(--dsw-alias-state-success-primary);
2012
+ --dsh-kb-active: var(--dsw-alias-state-business-primary);
2013
+ --dsh-kb-blocked: var(--dsw-alias-state-error-primary);
2014
+ --dsh-kb-pending: currentColor;
2015
+ /* \u89D2\u8272\u8272\uFF1ADSH \u6709\u7B49\u4EF7\u4EE4\u724C\u5219\u590D\u7528\uFF1Bp/pt/dt \u65E0 DSH \u7B49\u4EF7\u8272\uFF0C\u4FDD\u7559\u539F\u503C */
2016
+ --dsh-kb-v: var(--dsw-alias-state-business-primary);
2017
+ --dsh-kb-p: #a855f7;
2018
+ --dsh-kb-w: var(--dsw-alias-state-success-primary);
2019
+ --dsh-kb-d: var(--dsw-alias-state-warn-primary);
2020
+ --dsh-kb-pt: #6366f1; /* \u8BA1\u5212\u8BC4\u5BA1\uFF1A\u975B/\u6D45\u84DD */
2021
+ --dsh-kb-dt: #ec4899; /* \u5B9E\u73B0\u8BC4\u5BA1\uFF1A\u73AB\u7EA2 */
2022
+ height: 100%;
2023
+ width: 100%;
2024
+ /* \u63A5\u5165\u5BBF\u4E3B\u4F1A\u8BDD\u6D41\u5BBD\u5EA6\u7CFB\u7EDF\uFF1A\u81EA\u9002\u5E94 clamp + \u62D6\u62FD\u504F\u597D\uFF08--dsh-chat-content-width \u7531
2025
+ \u5BBF\u4E3B ConversationRoot \u5B9A\u4E49\uFF0C\u62D6\u62FD\u624B\u67C4\u5B98\u65B9\u5DF2\u5B9E\u73B0\uFF09\uFF1B780px \u4EC5\u4E3A\u53D8\u91CF\u7F3A\u5931\u65F6\u7684\u515C\u5E95 */
2026
+ min-width: 0;
2027
+ max-width: var(--dsh-chat-content-width, 780px);
2028
+ margin-inline: auto;
2029
+ display: flex;
2030
+ flex-direction: column;
2031
+ color: inherit;
2032
+ background: var(--dsw-alias-bg-base);
2033
+ pointer-events: auto;
2034
+ font-size: 13px;
2035
+ line-height: 1.45;
2036
+ overflow: hidden;
2037
+ }
2038
+
2039
+ .dsh-kb-banner {
2040
+ flex: 0 0 auto;
2041
+ padding: 6px 12px;
2042
+ font-size: 12px;
2043
+ border-bottom: 1px solid var(--dsh-kb-border);
2044
+ }
2045
+ .dsh-kb-banner--reconnecting,
2046
+ .dsh-kb-banner--loading {
2047
+ color: var(--dsh-kb-active);
2048
+ }
2049
+ .dsh-kb-banner--error {
2050
+ color: var(--dsh-kb-blocked);
2051
+ }
2052
+
2053
+ .dsh-kb-tab-body {
2054
+ flex: 1 1 auto;
2055
+ min-height: 0;
2056
+ overflow: auto;
2057
+ padding: 8px;
2058
+ }
2059
+
2060
+ .dsh-kb-loading {
2061
+ flex: 1 1 auto;
2062
+ display: flex;
2063
+ align-items: center;
2064
+ justify-content: center;
2065
+ color: currentColor;
2066
+ opacity: 0.7;
2067
+ }
2068
+
2069
+ .dsh-kb-toolbar {
2070
+ position: sticky;
2071
+ top: 0;
2072
+ z-index: 1;
2073
+ padding-bottom: 8px;
2074
+ }
2075
+ .dsh-kb-toolbar input {
2076
+ width: 100%;
2077
+ box-sizing: border-box;
2078
+ padding: 6px 10px;
2079
+ border: 1px solid var(--dsh-kb-border);
2080
+ border-radius: var(--dsh-kb-radius-md);
2081
+ background: var(--dsh-kb-input);
2082
+ color: var(--dsh-kb-text-primary);
2083
+ }
2084
+
2085
+ .dsh-kb-rail {
2086
+ display: flex;
2087
+ flex-direction: column;
2088
+ }
2089
+ /* \u72B6\u6001\u7B5B\u9009 chip \u7EC4\uFF1A\u6267\u884C\u4E2D/\u963B\u585E/\u5931\u8D25/\u5DF2\u5B8C\u6210\uFF08\u591A\u9009\u5E76\u96C6\uFF1B\u7A7A=\u9ED8\u8BA4\u89C6\u56FE\uFF09 */
2090
+ .dsh-kb-filters {
2091
+ display: flex;
2092
+ flex-wrap: wrap;
2093
+ gap: 6px;
2094
+ padding: 0 0 8px;
2095
+ }
2096
+ .dsh-kb-filter {
2097
+ display: inline-flex;
2098
+ align-items: center;
2099
+ padding: 2px 10px;
2100
+ border: 1px solid var(--dsw-alias-border-l2);
2101
+ border-radius: 999px;
2102
+ background: transparent;
2103
+ color: currentColor;
2104
+ font: inherit;
2105
+ cursor: pointer;
2106
+ user-select: none;
2107
+ transition: background-color 150ms ease, border-color 150ms ease, color 150ms ease;
2108
+ }
2109
+ .dsh-kb-filter:hover {
2110
+ background: var(--dsh-kb-hover);
2111
+ }
2112
+ .dsh-kb-filter--active {
2113
+ border-color: var(--dsh-kb-active);
2114
+ color: var(--dsh-kb-active);
2115
+ background: color-mix(in srgb, var(--dsh-kb-active) 10%, transparent);
2116
+ }
2117
+
2118
+ .dsh-kb-chain {
2119
+ margin-bottom: 10px;
2120
+ }
2121
+ .dsh-kb-chain__title {
2122
+ display: flex;
2123
+ align-items: center;
2124
+ gap: 8px;
2125
+ box-sizing: border-box;
2126
+ width: 100%;
2127
+ padding: 6px 8px;
2128
+ border: 0;
2129
+ border-radius: var(--dsh-kb-radius-sm);
2130
+ background: transparent;
2131
+ color: var(--dsh-kb-text-primary);
2132
+ font: inherit;
2133
+ text-align: left;
2134
+ cursor: pointer;
2135
+ transition: background-color 150ms ease;
2136
+ }
2137
+ .dsh-kb-chain__title:hover {
2138
+ background: var(--dsh-kb-hover);
2139
+ }
2140
+ /* \u6BCF\u6761\u94FE\u8DEF\u524D\u7684\u6298\u53E0\u7BAD\u5934\uFF08\u4E0E DSH \u6298\u53E0\u4EA4\u4E92\u4E00\u81F4\uFF1A\u7EC6 chevron\uFF0C\u5C55\u5F00\u65F6\u65CB\u8F6C\uFF0C150ms \u8FC7\u6E21\uFF09 */
2141
+ .dsh-kb-chain__chevron {
2142
+ flex: 0 0 auto;
2143
+ width: 7px;
2144
+ height: 7px;
2145
+ border-top: 1.5px solid currentColor;
2146
+ border-right: 1.5px solid currentColor;
2147
+ transform: rotate(45deg);
2148
+ opacity: 0.7;
2149
+ transition: transform 150ms ease;
2150
+ }
2151
+ .dsh-kb-chain__title[aria-expanded='true'] .dsh-kb-chain__chevron {
2152
+ transform: rotate(135deg);
2153
+ }
2154
+ .dsh-kb-chain__name {
2155
+ flex: 1 1 auto;
2156
+ overflow: hidden;
2157
+ text-overflow: ellipsis;
2158
+ white-space: nowrap;
2159
+ }
2160
+ .dsh-kb-chain__meta {
2161
+ flex: 0 0 auto;
2162
+ white-space: nowrap;
2163
+ opacity: 0.7;
2164
+ }
2165
+ .dsh-kb-chain__warning {
2166
+ padding: 4px 8px;
2167
+ margin: 2px 0 6px;
2168
+ border-left: 3px solid var(--dsh-kb-blocked);
2169
+ color: var(--dsh-kb-blocked);
2170
+ overflow: hidden;
2171
+ text-overflow: ellipsis;
2172
+ white-space: nowrap;
2173
+ }
2174
+ /* D23\uFF1A\u94FE\u5B8C\u6210\u9A8C\u6536\u6838\u5BF9\u8B66\u544A\u884C\uFF08completed \u94FE\u672A\u786E\u8BA4\u524D\u963B\u585E\u6700\u7EC8\u6C47\u62A5\uFF09 */
2175
+ .dsh-kb-chain__audit {
2176
+ display: flex;
2177
+ align-items: center;
2178
+ gap: 8px;
2179
+ white-space: normal;
2180
+ }
2181
+ .dsh-kb-chain__audit span {
2182
+ flex: 1 1 auto;
2183
+ overflow: hidden;
2184
+ }
2185
+ .dsh-kb-audit-confirm {
2186
+ flex: 0 0 auto;
2187
+ border: 1px solid var(--dsh-kb-blocked);
2188
+ border-radius: var(--dsh-kb-radius-sm);
2189
+ background: transparent;
2190
+ color: var(--dsh-kb-blocked);
2191
+ padding: 2px 10px;
2192
+ cursor: pointer;
2193
+ font: inherit;
2194
+ transition: background-color 150ms ease, color 150ms ease;
2195
+ }
2196
+ .dsh-kb-audit-confirm:hover {
2197
+ background: var(--dsh-kb-blocked);
2198
+ color: #fff;
2199
+ }
2200
+
2201
+ .dsh-kb-nodes {
2202
+ list-style: none;
2203
+ margin: 0;
2204
+ padding: 0 0 0 12px;
2205
+ display: flex;
2206
+ flex-direction: column;
2207
+ gap: 0;
2208
+ }
2209
+ .dsh-kb-node {
2210
+ position: relative;
2211
+ padding-left: 12px;
2212
+ }
2213
+ .dsh-kb-node::before {
2214
+ content: '';
2215
+ position: absolute;
2216
+ left: 0;
2217
+ top: 0;
2218
+ bottom: 0;
2219
+ width: 2px;
2220
+ background: var(--dsh-kb-pending);
2221
+ transition: background-color 150ms ease;
2222
+ }
2223
+ .dsh-kb-node--complete::before { background: var(--dsh-kb-complete); }
2224
+ .dsh-kb-node--active::before { background: var(--dsh-kb-active); }
2225
+ .dsh-kb-node--pending::before {
2226
+ background: repeating-linear-gradient(to bottom, currentColor 0 3px, transparent 3px 6px);
2227
+ }
2228
+ .dsh-kb-node--blocked::before {
2229
+ background: repeating-linear-gradient(to bottom, var(--dsh-kb-blocked) 0 4px, transparent 4px 8px);
2230
+ }
2231
+
2232
+ .dsh-kb-task {
2233
+ display: grid;
2234
+ grid-template-columns: 22px 1fr auto;
2235
+ grid-template-rows: auto auto;
2236
+ gap: 2px 8px;
2237
+ width: 100%;
2238
+ box-sizing: border-box;
2239
+ padding: 6px 8px;
2240
+ margin: 4px 0;
2241
+ border: 1px solid transparent;
2242
+ border-radius: var(--dsh-kb-radius-lg);
2243
+ background: transparent;
2244
+ color: var(--dsh-kb-text-primary);
2245
+ font: inherit;
2246
+ text-align: left;
2247
+ cursor: pointer;
2248
+ transition: border-color 150ms ease, background-color 150ms ease, opacity 150ms ease;
2249
+ }
2250
+ .dsh-kb-task:hover {
2251
+ background: var(--dsh-kb-hover);
2252
+ }
2253
+ .dsh-kb-task[data-selected],
2254
+ .dsh-kb-task--active {
2255
+ border-color: var(--dsh-kb-active);
2256
+ }
2257
+ /* T32\uFF1A\u5B8C\u6210\u4EFB\u52A1\u4FDD\u7559\u5728\u8F68\u9053\u4F46\u89C6\u89C9\u964D\u6743\uFF1B\u72B6\u6001\u8272\u4E0D\u53D8\u3001\u4E0D\u6574\u5361\u67D3\u8272 */
2258
+ .dsh-kb-task--complete {
2259
+ opacity: 0.72;
2260
+ }
2261
+ .dsh-kb-task__title {
2262
+ grid-column: 2;
2263
+ overflow: hidden;
2264
+ text-overflow: ellipsis;
2265
+ white-space: nowrap;
2266
+ }
2267
+ .dsh-kb-task__status {
2268
+ grid-column: 3;
2269
+ color: currentColor;
2270
+ opacity: 0.75;
2271
+ }
2272
+ .dsh-kb-task__meta {
2273
+ grid-column: 2 / 4;
2274
+ opacity: 0.6;
2275
+ overflow: hidden;
2276
+ text-overflow: ellipsis;
2277
+ white-space: nowrap;
2278
+ }
2279
+ .dsh-kb-task__warn {
2280
+ grid-column: 2 / 4;
2281
+ display: inline-flex;
2282
+ align-items: center;
2283
+ gap: 4px;
2284
+ color: var(--dsh-kb-blocked);
2285
+ overflow: hidden;
2286
+ text-overflow: ellipsis;
2287
+ white-space: nowrap;
2288
+ }
2289
+ .dsh-kb-task__warn svg {
2290
+ flex: 0 0 auto;
2291
+ }
2292
+ .dsh-kb-task__warn span {
2293
+ overflow: hidden;
2294
+ text-overflow: ellipsis;
2295
+ white-space: nowrap;
2296
+ }
2297
+ .dsh-kb-task--complete .dsh-kb-task__status { color: var(--dsh-kb-complete); }
2298
+ .dsh-kb-task--blocked .dsh-kb-task__status { color: var(--dsh-kb-blocked); }
2299
+ /* D17\uFF1A\u9009\u4E2D\u4EFB\u52A1\u6240\u5728\u94FE\u8DEF\u7684\u4E0A\u6E38/\u5F53\u524D/\u4E0B\u6E38\u8DEF\u5F84\u5361\u9AD8\u4EAE\uFF1B\u4E0D\u6539\u53D8\u8FDE\u63A5\u7EBF\u8BED\u4E49\uFF0C\u9009\u4E2D\u5361\u4FDD\u6301\u5F3A\u8FB9\u6846 */
2300
+ .dsh-kb-task--related:not(.dsh-kb-task--active) {
2301
+ border-color: color-mix(in srgb, var(--dsh-kb-active) 35%, transparent);
2302
+ background: color-mix(in srgb, var(--dsh-kb-active) 6%, transparent);
2303
+ }
2304
+
2305
+ .dsh-kb-empty {
2306
+ padding: 24px 12px;
2307
+ text-align: center;
2308
+ color: var(--dsh-kb-text-secondary);
2309
+ border: 1px dashed var(--dsh-kb-border);
2310
+ border-radius: var(--dsh-kb-radius-lg);
2311
+ }
2312
+
2313
+ .dsh-kb-profile {
2314
+ grid-row: 1 / 3;
2315
+ align-self: start;
2316
+ width: 20px;
2317
+ height: 20px;
2318
+ border-radius: var(--dsh-kb-radius-sm);
2319
+ display: inline-flex;
2320
+ align-items: center;
2321
+ justify-content: center;
2322
+ font-size: 11px;
2323
+ font-weight: 700;
2324
+ color: #fff;
2325
+ }
2326
+ .dsh-kb-profile--v { background: var(--dsh-kb-v); }
2327
+ .dsh-kb-profile--p { background: var(--dsh-kb-p); }
2328
+ .dsh-kb-profile--w { background: var(--dsh-kb-w); }
2329
+ .dsh-kb-profile--d { background: var(--dsh-kb-d); }
2330
+ .dsh-kb-profile--pt { background: var(--dsh-kb-pt); }
2331
+ .dsh-kb-profile--dt { background: var(--dsh-kb-dt); }
2332
+
2333
+ /* T27\uFF1A\u4EFB\u52A1\u5361\u5F39\u7A97\uFF08\u539F\u4F4D\u8BE6\u60C5\uFF09\u2014\u2014DSH \u9762\u677F\u98CE\u683C\uFF1A\u5927\u5706\u89D2 + \u62AC\u5347\u8868\u9762 + \u6D45/\u6DF1\u8272\u4EE4\u724C */
2334
+ .dsh-kb-detail {
2335
+ display: flex;
2336
+ flex-direction: column;
2337
+ min-height: calc(100% - 16px);
2338
+ margin: 8px;
2339
+ padding: 12px 16px;
2340
+ box-sizing: border-box;
2341
+ border: 1px solid var(--dsh-kb-border);
2342
+ border-radius: var(--dsh-kb-radius-lg);
2343
+ background: var(--dsh-kb-surface);
2344
+ color: var(--dsh-kb-text-primary);
2345
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
2346
+ }
2347
+ .dsh-kb-detail__header {
2348
+ display: flex;
2349
+ align-items: center;
2350
+ gap: 8px;
2351
+ padding-bottom: 8px;
2352
+ border-bottom: 1px solid var(--dsh-kb-border);
2353
+ }
2354
+ .dsh-kb-detail__header > button:not(.dsh-kb-unread) {
2355
+ flex: 0 0 auto;
2356
+ width: 28px;
2357
+ height: 28px;
2358
+ border: 1px solid var(--dsh-kb-border);
2359
+ border-radius: var(--dsh-kb-radius-md);
2360
+ background: transparent;
2361
+ color: var(--dsh-kb-text-primary);
2362
+ cursor: pointer;
2363
+ font: inherit;
2364
+ line-height: 1;
2365
+ transition: background-color 150ms ease;
2366
+ }
2367
+ .dsh-kb-detail__header > button:not(.dsh-kb-unread):hover {
2368
+ background: var(--dsh-kb-hover);
2369
+ }
2370
+ .dsh-kb-detail__identity {
2371
+ flex: 1 1 auto;
2372
+ min-width: 0;
2373
+ }
2374
+ .dsh-kb-detail__identity strong,
2375
+ .dsh-kb-detail__identity span {
2376
+ display: block;
2377
+ overflow: hidden;
2378
+ text-overflow: ellipsis;
2379
+ white-space: nowrap;
2380
+ }
2381
+ .dsh-kb-detail__actions {
2382
+ display: flex;
2383
+ gap: 4px;
2384
+ flex: 0 0 auto;
2385
+ }
2386
+ .dsh-kb-detail__actions button {
2387
+ border: 1px solid var(--dsh-kb-border);
2388
+ border-radius: var(--dsh-kb-radius-md);
2389
+ background: transparent;
2390
+ color: var(--dsh-kb-text-primary);
2391
+ padding: 4px 10px;
2392
+ cursor: pointer;
2393
+ font: inherit;
2394
+ white-space: nowrap; /* 2026-09-15\uFF1A\u6A2A\u5411\u7A7A\u95F4\u4E0D\u8DB3\u65F6\u6309\u94AE\u6587\u5B57\u66FE\u88AB\u9010\u5B57\u7AD6\u6392 */
2395
+ transition: border-color 150ms ease, color 150ms ease, background-color 150ms ease;
2396
+ }
2397
+ .dsh-kb-detail__actions button:hover {
2398
+ background: var(--dsh-kb-hover);
2399
+ }
2400
+ .dsh-kb-detail__actions button[data-confirming='true'] {
2401
+ border-color: var(--dsh-kb-blocked);
2402
+ color: var(--dsh-kb-blocked);
2403
+ }
2404
+ .dsh-kb-detail__actions button:disabled {
2405
+ opacity: 0.5;
2406
+ cursor: default;
2407
+ }
2408
+ .dsh-kb-action-form {
2409
+ display: inline-flex;
2410
+ align-items: center;
2411
+ gap: 4px;
2412
+ }
2413
+ .dsh-kb-action-form input {
2414
+ width: 140px;
2415
+ padding: 3px 8px;
2416
+ border: 1px solid var(--dsh-kb-border);
2417
+ border-radius: var(--dsh-kb-radius-sm);
2418
+ background: var(--dsh-kb-input);
2419
+ color: var(--dsh-kb-text-primary);
2420
+ font: inherit;
2421
+ font-size: 12px;
2422
+ }
2423
+ /* \u8BC4\u8BBA\u8F93\u5165\uFF1A\u6309 DSH \u53D1\u9001\u6D88\u606F\u6846\u98CE\u683C\u7EDF\u4E00\uFF08\u5927\u5706\u89D2\u590D\u7528 16px \u5951\u7EA6\u4EE4\u724C\uFF09 */
2424
+ .dsh-kb-comment-input {
2425
+ display: block;
2426
+ width: 100%;
2427
+ box-sizing: border-box;
2428
+ margin-top: 8px;
2429
+ padding: 10px 14px;
2430
+ border: 1px solid var(--dsh-kb-border);
2431
+ border-radius: var(--dsh-kb-radius-lg); /* \u5927\u5706\u89D2\u53D1\u9001\u6846\uFF1A\u590D\u7528 16px \u5951\u7EA6 */
2432
+ background: var(--dsh-kb-input);
2433
+ color: var(--dsh-kb-text-primary);
2434
+ font: inherit;
2435
+ }
2436
+ .dsh-kb-comment-input:focus {
2437
+ outline: none;
2438
+ border-color: var(--dsh-kb-active);
2439
+ }
2440
+ .dsh-kb-comment-input::placeholder {
2441
+ color: var(--dsh-kb-text-tertiary);
2442
+ }
2443
+ .dsh-kb-unread {
2444
+ flex: 0 0 auto;
2445
+ border: 1px solid var(--dsh-kb-active);
2446
+ border-radius: 999px;
2447
+ background: color-mix(in srgb, var(--dsh-kb-active) 12%, transparent);
2448
+ color: var(--dsh-kb-active);
2449
+ padding: 2px 8px;
2450
+ font: inherit;
2451
+ font-size: 12px;
2452
+ white-space: nowrap;
2453
+ cursor: pointer;
2454
+ }
2455
+ .dsh-kb-action-error {
2456
+ display: flex;
2457
+ align-items: center;
2458
+ gap: 8px;
2459
+ padding: 6px 8px;
2460
+ margin: 4px 0;
2461
+ border-left: 3px solid var(--dsh-kb-blocked);
2462
+ color: var(--dsh-kb-blocked);
2463
+ font-size: 12px;
2464
+ }
2465
+ .dsh-kb-action-error span {
2466
+ flex: 1 1 auto;
2467
+ overflow: hidden;
2468
+ text-overflow: ellipsis;
2469
+ white-space: nowrap;
2470
+ }
2471
+ .dsh-kb-action-error button {
2472
+ flex: 0 0 auto;
2473
+ border: 1px solid currentColor;
2474
+ border-radius: var(--dsh-kb-radius-sm);
2475
+ background: transparent;
2476
+ color: inherit;
2477
+ padding: 1px 6px;
2478
+ cursor: pointer;
2479
+ font: inherit;
2480
+ }
2481
+ .dsh-kb-detail [role='tablist'] {
2482
+ display: flex;
2483
+ gap: 4px;
2484
+ padding: 8px 0;
2485
+ border-bottom: 1px solid var(--dsh-kb-border);
2486
+ }
2487
+ .dsh-kb-detail [role='tab'] {
2488
+ border: 0;
2489
+ border-radius: var(--dsh-kb-radius-sm);
2490
+ background: transparent;
2491
+ color: var(--dsh-kb-text-secondary);
2492
+ padding: 4px 10px;
2493
+ cursor: pointer;
2494
+ transition: background-color 150ms ease, color 150ms ease;
2495
+ }
2496
+ .dsh-kb-detail [role='tab']:hover {
2497
+ color: var(--dsh-kb-text-primary);
2498
+ background: var(--dsh-kb-hover);
2499
+ }
2500
+ .dsh-kb-detail [role='tab'][aria-selected='true'] {
2501
+ background: var(--dsh-kb-hover);
2502
+ color: var(--dsh-kb-text-primary);
2503
+ }
2504
+ .dsh-kb-detail [role='tabpanel'] {
2505
+ padding: 8px 0;
2506
+ overflow: auto;
2507
+ }
2508
+ .dsh-kb-detail h4 {
2509
+ margin: 8px 0 4px;
2510
+ font-size: 12px;
2511
+ text-transform: none;
2512
+ color: var(--dsh-kb-text-secondary);
2513
+ }
2514
+ .dsh-kb-detail code {
2515
+ background: var(--dsh-kb-inline-code);
2516
+ border-radius: var(--dsh-kb-radius-sm);
2517
+ padding: 1px 4px;
2518
+ }
2519
+ .dsh-kb-detail dl {
2520
+ display: grid;
2521
+ grid-template-columns: auto 1fr;
2522
+ gap: 4px 8px;
2523
+ margin: 8px 0;
2524
+ }
2525
+ .dsh-kb-detail dt { opacity: 0.7; color: var(--dsh-kb-text-tertiary); }
2526
+ .dsh-kb-detail dd { margin: 0; }
2527
+ .dsh-kb-detail time { opacity: 0.6; font-size: 12px; margin-inline-end: 4px; }
2528
+
2529
+ /* \u8F68\u8FF9 tab \u53EF\u8BFB\u5316\uFF1A\u7269\u6D41\u5F0F\u7EB5\u5411\u65F6\u95F4\u8F74\uFF08\u56DB\u6001\u914D\u8272 + \u6700\u65B0\u8282\u70B9\u9AD8\u4EAE\uFF1B\u5F02\u5E38\u6574\u884C\u6807\u7EA2\uFF09 */
2530
+ .dsh-kb-timeline {
2531
+ list-style: none;
2532
+ margin: 0;
2533
+ padding: 0;
2534
+ display: flex;
2535
+ flex-direction: column;
2536
+ }
2537
+ .dsh-kb-timeline__item {
2538
+ position: relative;
2539
+ display: grid;
2540
+ grid-template-columns: 16px 1fr;
2541
+ gap: 8px;
2542
+ padding: 0 0 14px;
2543
+ }
2544
+ .dsh-kb-timeline__item:last-child {
2545
+ padding-bottom: 0;
2546
+ }
2547
+ /* \u7EB5\u5411\u65F6\u95F4\u7EBF\uFF1A\u8D2F\u7A7F\u8282\u70B9\uFF08\u6700\u65B0\u8282\u70B9\u4E0A\u65B9\u7EBF\u4E0D\u5EF6\u4F38\uFF0C\u6A21\u62DF\u7269\u6D41\u5934\u8282\u70B9\uFF09 */
2548
+ .dsh-kb-timeline__axis {
2549
+ position: relative;
2550
+ }
2551
+ .dsh-kb-timeline__item:not(:last-child) .dsh-kb-timeline__axis::after {
2552
+ content: '';
2553
+ position: absolute;
2554
+ left: 50%;
2555
+ top: 14px;
2556
+ bottom: -4px;
2557
+ width: 2px;
2558
+ transform: translateX(-50%);
2559
+ background: var(--dsh-kb-border);
2560
+ }
2561
+ .dsh-kb-timeline__dot {
2562
+ position: relative;
2563
+ z-index: 1;
2564
+ display: block;
2565
+ width: 10px;
2566
+ height: 10px;
2567
+ /* \u6C34\u5E73\u5C45\u4E2D\u4E8E 16px \u8F74\u5217\uFF08\u4E2D\u5FC3=8px\uFF09\uFF0C\u4E0E left:50% \u8FDE\u63A5\u7EBF\u5BF9\u9F50 */
2568
+ margin: 2px auto 0;
2569
+ border-radius: 50%;
2570
+ border: 2px solid var(--dsh-kb-surface);
2571
+ box-sizing: border-box;
2572
+ background: var(--dsh-kb-text-tertiary);
2573
+ }
2574
+ /* \u56DB\u6001\u914D\u8272\uFF1Aneutral \u7070 / running \u84DD / success \u7EFF / exception \u7EA2 */
2575
+ .dsh-kb-timeline__item--running .dsh-kb-timeline__dot {
2576
+ background: var(--dsh-kb-active);
2577
+ }
2578
+ .dsh-kb-timeline__item--success .dsh-kb-timeline__dot {
2579
+ background: var(--dsh-kb-complete);
2580
+ }
2581
+ .dsh-kb-timeline__item--exception .dsh-kb-timeline__dot {
2582
+ background: var(--dsh-kb-blocked);
2583
+ }
2584
+ /* \u6700\u65B0\u8282\u70B9\u9AD8\u4EAE\uFF1A\u4E3B\u8272\u5706\u70B9\u653E\u5927 + \u67D4\u548C\u8F89\u5149 */
2585
+ .dsh-kb-timeline__item--latest .dsh-kb-timeline__dot {
2586
+ width: 12px;
2587
+ height: 12px;
2588
+ margin-top: 0;
2589
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--dsh-kb-active) 22%, transparent);
2590
+ }
2591
+ .dsh-kb-timeline__item--latest.dsh-kb-timeline__item--success .dsh-kb-timeline__dot {
2592
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--dsh-kb-complete) 22%, transparent);
2593
+ }
2594
+ .dsh-kb-timeline__item--latest.dsh-kb-timeline__item--exception .dsh-kb-timeline__dot {
2595
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--dsh-kb-blocked) 22%, transparent);
2596
+ }
2597
+ /* \u5F02\u5E38\u884C\uFF1A\u6D45\u7EA2\u5E95 + \u5DE6\u4FA7\u7EA2\u6761\uFF0C\u6458\u8981\u7EA2\u52A0\u7C97 */
2598
+ .dsh-kb-timeline__item--exception .dsh-kb-timeline__body {
2599
+ background: color-mix(in srgb, var(--dsh-kb-blocked) 8%, transparent);
2600
+ border-left: 3px solid var(--dsh-kb-blocked);
2601
+ border-radius: var(--dsh-kb-radius-sm);
2602
+ padding: 6px 8px;
2603
+ }
2604
+ .dsh-kb-timeline__body {
2605
+ min-width: 0;
2606
+ }
2607
+ .dsh-kb-timeline__row {
2608
+ display: flex;
2609
+ align-items: baseline;
2610
+ gap: 8px;
2611
+ flex-wrap: wrap;
2612
+ }
2613
+ .dsh-kb-timeline__label {
2614
+ font-size: 13px;
2615
+ font-weight: 600;
2616
+ color: var(--dsh-kb-text-primary);
2617
+ }
2618
+ .dsh-kb-timeline__item--success .dsh-kb-timeline__label {
2619
+ color: var(--dsh-kb-complete);
2620
+ }
2621
+ .dsh-kb-timeline__item--exception .dsh-kb-timeline__label {
2622
+ color: var(--dsh-kb-blocked);
2623
+ }
2624
+ .dsh-kb-timeline__summary {
2625
+ margin: 2px 0 0;
2626
+ font-size: 12px;
2627
+ color: var(--dsh-kb-text-secondary);
2628
+ overflow: hidden;
2629
+ text-overflow: ellipsis;
2630
+ white-space: nowrap;
2631
+ }
2632
+ .dsh-kb-timeline__item--exception .dsh-kb-timeline__summary {
2633
+ color: var(--dsh-kb-blocked);
2634
+ font-weight: 600;
2635
+ }
2636
+ .dsh-kb-timeline__author {
2637
+ display: block;
2638
+ margin-top: 2px;
2639
+ font-size: 11px;
2640
+ opacity: 0.7;
2641
+ color: var(--dsh-kb-text-tertiary);
2642
+ }
2643
+
2644
+ .dsh-kb-spec-attachments {
2645
+ list-style: none;
2646
+ margin: 4px 0;
2647
+ padding: 0;
2648
+ display: flex;
2649
+ flex-direction: column;
2650
+ gap: 4px;
2651
+ }
2652
+ .dsh-kb-spec-attachments li {
2653
+ display: flex;
2654
+ align-items: baseline;
2655
+ gap: 6px;
2656
+ overflow: hidden;
2657
+ text-overflow: ellipsis;
2658
+ white-space: nowrap;
2659
+ }
2660
+ .dsh-kb-spec-attachment__kind {
2661
+ font-size: 11px;
2662
+ border: 1px solid var(--dsh-kb-border);
2663
+ border-radius: var(--dsh-kb-radius-sm);
2664
+ padding: 0 4px;
2665
+ opacity: 0.8;
2666
+ }
2667
+
2668
+ @media (prefers-reduced-motion: reduce) {
2669
+ .dsh-kb-tab * {
2670
+ transition-duration: 0ms !important;
2671
+ }
2672
+ }
2673
+
2674
+ /* \u6574\u94FE\u5220\u9664\u6309\u94AE\uFF1A\u9ED8\u8BA4\u9690\u85CF\uFF0Chover \u9700\u6C42\u6807\u9898\u884C\u65F6\u51FA\u73B0\uFF08GUI \u4EC5 human\uFF0C\u4E8C\u6B21\u786E\u8BA4\uFF09 */
2675
+ .dsh-kb-chain__delete {
2676
+ flex: 0 0 auto;
2677
+ border: 0;
2678
+ background: transparent;
2679
+ color: currentColor;
2680
+ opacity: 0;
2681
+ font: inherit;
2682
+ line-height: 1;
2683
+ padding: 2px 4px;
2684
+ cursor: pointer;
2685
+ transition: opacity 150ms ease, color 150ms ease;
2686
+ }
2687
+ .dsh-kb-chain__title:hover .dsh-kb-chain__delete,
2688
+ .dsh-kb-chain__delete:focus-visible { opacity: 0.7; }
2689
+ .dsh-kb-chain__delete:hover { opacity: 1; color: var(--dsh-kb-blocked); }
2690
+ /* \u5220\u9664\u4E8C\u6B21\u786E\u8BA4\u5F39\u7A97\uFF08\u590D\u7528 rename \u5F39\u7A97\u5916\u58F3/\u5706\u89D2\u5951\u7EA6\uFF09 */
2691
+ .dsh-kb-delete-modal__text {
2692
+ color: var(--dsh-kb-text-secondary);
2693
+ font-size: 13px;
2694
+ line-height: 1.5;
2695
+ }
2696
+ .dsh-kb-delete-modal__error {
2697
+ color: var(--dsh-kb-blocked);
2698
+ font-size: 12px;
2699
+ }
2700
+ .dsh-kb-rename-modal__actions .dsh-kb-delete-confirm {
2701
+ border-color: transparent;
2702
+ background: var(--dsw-alias-state-error-primary);
2703
+ color: #fff;
2704
+ }
2705
+ /* T7\uFF1A\u94FE\u6807\u9898\u6539\u540D\u94C5\u7B14\u6309\u94AE + \u8F7B\u91CF\u5F39\u7A97\uFF08GUI \u4EC5 human\uFF1B\u89D2\u8272\u5361\u4E0D\u53EF\u6539\u540D\uFF09 */
2706
+ .dsh-kb-chain__rename {
2707
+ flex: 0 0 auto;
2708
+ border: 0;
2709
+ background: transparent;
2710
+ color: currentColor;
2711
+ opacity: 0.55;
2712
+ font: inherit;
2713
+ line-height: 1;
2714
+ padding: 2px 4px;
2715
+ cursor: pointer;
2716
+ }
2717
+ .dsh-kb-chain__rename:hover { opacity: 1; }
2718
+ /* \u4EBA\u5DE5\u6062\u590D\u6309\u94AE\uFF082026-09-15\uFF09\uFF1A\u4EC5 blocked \u94FE\u663E\u793A\uFF0C\u5E38\u663E\uFF08\u4F4E\u9891\u9AD8\u4EF7\u503C\u573A\u666F\uFF0C\u660E\u786E\u6027\u4F18\u5148\u4E8E\u7D27\u51D1\u6027\uFF09 */
2719
+ .dsh-kb-chain__reopen {
2720
+ flex: 0 0 auto;
2721
+ border: 0;
2722
+ background: transparent;
2723
+ color: currentColor;
2724
+ font: inherit;
2725
+ font-size: 12px;
2726
+ line-height: 1;
2727
+ padding: 2px 6px;
2728
+ border-radius: 4px;
2729
+ cursor: pointer;
2730
+ transition: background 150ms ease;
2731
+ }
2732
+ .dsh-kb-chain__reopen:hover { background: rgba(255, 255, 255, 0.12); }
2733
+ .dsh-kb-task__status-row {
2734
+ display: flex;
2735
+ align-items: center;
2736
+ gap: 4px;
2737
+ }
2738
+ .dsh-kb-task__session {
2739
+ flex: none;
2740
+ padding: 0 6px;
2741
+ font-size: 11px;
2742
+ line-height: 18px;
2743
+ border: 1px solid color-mix(in srgb, currentColor 40%, transparent);
2744
+ border-radius: 4px;
2745
+ background: transparent;
2746
+ color: inherit;
2747
+ cursor: pointer;
2748
+ opacity: 0.85;
2749
+ }
2750
+ .dsh-kb-task__session:hover {
2751
+ opacity: 1;
2752
+ }
2753
+ .dsh-kb-rename-overlay {
2754
+ position: fixed;
2755
+ inset: 0;
2756
+ z-index: 1000;
2757
+ background: var(--dsh-kb-mask);
2758
+ display: flex;
2759
+ align-items: center;
2760
+ justify-content: center;
2761
+ }
2762
+ .dsh-kb-rename-modal {
2763
+ display: flex;
2764
+ flex-direction: column;
2765
+ gap: 8px;
2766
+ min-width: 280px;
2767
+ padding: 16px;
2768
+ border: 1px solid var(--dsh-kb-border);
2769
+ border-radius: var(--dsh-kb-radius-lg);
2770
+ background: var(--dsh-kb-surface-elev);
2771
+ color: var(--dsh-kb-text-primary);
2772
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
2773
+ }
2774
+ .dsh-kb-rename-modal__label {
2775
+ color: var(--dsh-kb-text-primary);
2776
+ font-size: 13px;
2777
+ font-weight: 600;
2778
+ }
2779
+ .dsh-kb-rename-modal__input {
2780
+ padding: 6px 10px;
2781
+ border: 1px solid var(--dsh-kb-border);
2782
+ border-radius: var(--dsh-kb-radius-md);
2783
+ background: var(--dsh-kb-input);
2784
+ color: var(--dsh-kb-text-primary);
2785
+ font: inherit;
2786
+ }
2787
+ .dsh-kb-rename-modal__input:focus {
2788
+ outline: none;
2789
+ border-color: var(--dsh-kb-active);
2790
+ }
2791
+ .dsh-kb-rename-modal__actions {
2792
+ display: flex;
2793
+ justify-content: flex-end;
2794
+ gap: 8px;
2795
+ }
2796
+ .dsh-kb-rename-modal__actions button {
2797
+ border: 1px solid var(--dsh-kb-border);
2798
+ border-radius: var(--dsh-kb-radius-md);
2799
+ background: transparent;
2800
+ color: var(--dsh-kb-text-primary);
2801
+ font: inherit;
2802
+ padding: 4px 14px;
2803
+ cursor: pointer;
2804
+ transition: background-color 150ms ease;
2805
+ }
2806
+ .dsh-kb-rename-modal__actions button:hover {
2807
+ background: var(--dsh-kb-hover);
2808
+ }
2809
+ .dsh-kb-rename-modal__actions .dsh-kb-rename-save {
2810
+ border-color: transparent;
2811
+ background: var(--dsw-alias-button-primary-fill);
2812
+ color: var(--dsw-alias-label-primary-foreground);
2813
+ }
2814
+ /* 2026-09-15\uFF1A\u5F39\u7A97\u64CD\u4F5C\u6309\u94AE\u7684\u7981\u7528/\u5728\u9014\u89C6\u89C9\uFF08\u6B64\u524D\u5B8C\u5168\u7F3A\u5931\u2014\u2014disabled \u65E0\u89C6\u89C9\u5DEE\u5F02\uFF0C\u70B9\u51FB\u50CF"\u6CA1\u53CD\u5E94"\uFF09 */
2815
+ .dsh-kb-rename-modal__actions button:disabled { opacity: 0.5; cursor: not-allowed; }
2816
+ .dsh-kb-rename-modal__hint {
2817
+ color: var(--dsh-kb-text-secondary);
2818
+ font-size: 12px;
2819
+ line-height: 1.4;
2820
+ }
2821
+ .dsh-kb-rename-modal__success {
2822
+ color: #2ea043;
2823
+ font-size: 12px;
2824
+ line-height: 1.4;
2825
+ }
2826
+
2827
+ /* Swarm \u914D\u7F6E\u9762\u677F\u300C\u8BC4\u5BA1\u5F15\u64CE\uFF08ocr\uFF09\u300D\u5361\uFF1A\u5B89\u88C5\u4E2D spinner \u884C\u4E0E\u72B6\u6001\u884C\uFF08\u6210\u529F\u7EFF / \u8B66\u793A\u9EC4\uFF09 */
2828
+ .dsh-kb-config__installing {
2829
+ display: flex;
2830
+ align-items: center;
2831
+ gap: 10px;
2832
+ margin: 8px 0;
2833
+ }
2834
+ .dsh-kb-config__installing button {
2835
+ margin-left: auto;
2836
+ padding: 4px 12px;
2837
+ border: 1px solid var(--dsh-kb-config-border, #333);
2838
+ border-radius: 10px;
2839
+ background: transparent;
2840
+ color: inherit;
2841
+ font: inherit;
2842
+ cursor: pointer;
2843
+ }
2844
+ .dsh-kb-config__installing-spinner {
2845
+ flex: 0 0 auto;
2846
+ width: 14px;
2847
+ height: 14px;
2848
+ border: 2px solid var(--dsw-alias-border-l2, #666);
2849
+ border-top-color: transparent;
2850
+ border-radius: 50%;
2851
+ animation: dsh-kb-ocr-spin 0.9s linear infinite;
2852
+ }
2853
+ @keyframes dsh-kb-ocr-spin {
2854
+ to { transform: rotate(360deg); }
2855
+ }
2856
+ .dsh-kb-config__ocr-ok { color: var(--dsw-alias-state-success-primary, #2e9e5b); margin: 6px 0; }
2857
+ .dsh-kb-config__ocr-warn { color: var(--dsw-alias-state-warning-primary, #b8860b); margin: 6px 0; }
2858
+ .dsh-kb-config__installing button,
2859
+ .dsh-kb-config__card > button {
2860
+ margin-top: 8px;
2861
+ }
2862
+ .dsh-kb-config__card > button {
2863
+ padding: 6px 16px;
2864
+ border: 1px solid var(--dsh-kb-config-border, #333);
2865
+ border-radius: 10px;
2866
+ background: transparent;
2867
+ color: inherit;
2868
+ font: inherit;
2869
+ cursor: pointer;
2870
+ transition: background-color 150ms ease;
2871
+ }
2872
+ .dsh-kb-config__card > button:hover:not([disabled]) { background: var(--dsw-alias-interactive-bg-hover, rgba(127, 127, 127, 0.12)); }
2873
+ .dsh-kb-config__card > button[disabled] { opacity: 0.5; cursor: not-allowed; }
2874
+ .dsh-kb-config__select-trigger:disabled { opacity: 0.5; cursor: not-allowed; }
2875
+ `;
1798
2876
 
1799
2877
  // client/config.css
1800
2878
  var config_default = ".dsh-kb-config {\n /* \u4E0E kanban.css \u5927\u5706\u89D2\u5951\u7EA6\u5BF9\u9F50\uFF08DSH \u5361\u7247 16px\uFF09 */\n --dsh-kb-config-border: var(--dsw-alias-border-l2, #333);\n --dsh-kb-config-radius-lg: 16px;\n --dsh-kb-config-radius-md: 10px;\n --dsh-kb-config-input: var(--dsw-specific-input-major, rgba(127, 127, 127, 0.12));\n padding: 16px;\n font-size: 13px;\n}\n.dsh-kb-config__card { border: 1px solid var(--dsh-kb-config-border); border-radius: var(--dsh-kb-config-radius-lg); padding: 20px; margin-bottom: 16px; }\n.dsh-kb-config__card h3 { margin: 0 0 14px; }\n\n.dsh-kb-config input,\n.dsh-kb-config select {\n box-sizing: border-box;\n width: 100%;\n padding: 8px 12px;\n border: 1px solid var(--dsh-kb-config-border);\n border-radius: var(--dsh-kb-config-radius-md);\n background: var(--dsh-kb-config-input);\n color: var(--dsw-alias-label-primary, inherit);\n font: inherit;\n transition: border-color 150ms ease, background-color 150ms ease;\n}\n.dsh-kb-config input:focus,\n.dsh-kb-config select:focus {\n outline: none;\n /* \u7126\u70B9/\u9009\u4E2D\u5F3A\u8C03\u8272\u8DDF\u968F\u4E3B\u9898\u524D\u666F\uFF08\u6D45\u8272=\u6697\u3001\u6697\u8272=\u767D\uFF09\uFF0C\u4E0E dsh settings \u8272\u7CFB\u4E00\u81F4 */\n border-color: var(--dsw-alias-label-primary, currentColor);\n}\n\n/* DSH \u98CE\u683C\u4E0B\u62C9\uFF1Atrigger \u884C\uFF08\u503C + \u203A chevron\uFF09+ \u5F39\u51FA\u83DC\u5355\uFF08\u9009\u4E2D\u6253\u52FE\u3001hover \u9AD8\u4EAE\uFF09 */\n.dsh-kb-config__select { position: relative; min-width: 0; }\n.dsh-kb-config__select-trigger {\n box-sizing: border-box;\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n width: 100%;\n padding: 8px 12px;\n border: 1px solid var(--dsh-kb-config-border);\n border-radius: var(--dsh-kb-config-radius-md);\n background: var(--dsh-kb-config-input);\n color: var(--dsw-alias-label-primary, inherit);\n font: inherit;\n text-align: left;\n cursor: pointer;\n transition: border-color 150ms ease, background-color 150ms ease;\n}\n.dsh-kb-config__select-trigger:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(127, 127, 127, 0.12)); }\n.dsh-kb-config__select-trigger[aria-expanded='true'] { border-color: var(--dsw-alias-label-primary, currentColor); }\n.dsh-kb-config__select-placeholder { color: var(--dsw-alias-label-tertiary, #999); }\n.dsh-kb-config__select-trigger > span:first-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.dsh-kb-config__select-chevron { flex: 0 0 auto; display: inline-flex; color: var(--dsw-alias-label-tertiary, #999); }\n.dsh-kb-config__menu {\n position: absolute;\n z-index: 30;\n top: calc(100% + 6px);\n left: 0;\n right: 0;\n margin: 0;\n padding: 6px;\n list-style: none;\n border: 1px solid var(--dsh-kb-config-border);\n border-radius: var(--dsh-kb-config-radius-lg);\n background: var(--dsw-alias-bg-layer-3, #222);\n color: var(--dsw-alias-label-primary, inherit);\n box-shadow: 0 8px 24px rgba(0, 0, 0, 0.24);\n max-height: 260px;\n overflow: auto;\n}\n.dsh-kb-config__option {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n width: 100%;\n padding: 8px 10px;\n border: none;\n border-radius: var(--dsh-kb-config-radius-md);\n background: transparent;\n color: inherit;\n font: inherit;\n text-align: left;\n cursor: pointer;\n transition: background-color 150ms ease;\n}\n.dsh-kb-config__option:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(127, 127, 127, 0.12)); }\n.dsh-kb-config__option[data-selected='true'] { color: var(--dsw-alias-state-business-primary, #4b7bff); }\n.dsh-kb-config__option > span:first-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.dsh-kb-config__option-check { flex: 0 0 auto; display: inline-flex; }\n\n.dsh-kb-config__label { display: block; margin: 12px 0 6px; font-weight: 600; }\n.dsh-kb-config__help { color: var(--dsw-alias-label-secondary, #888); font-size: 12px; display: block; margin: 6px 0 0; }\n.dsh-kb-config__role { display: grid; grid-template-columns: 32px 1fr 1fr 1fr auto; gap: 10px; margin-bottom: 12px; align-items: center; }\n.dsh-kb-config__src { color: var(--dsw-alias-label-secondary, #888); font-size: 12px; white-space: nowrap; padding-left: 4px; }\n.dsh-kb-config__footer { display: flex; justify-content: flex-end; margin-top: 4px; }\n.dsh-kb-config__footer button {\n padding: 6px 16px;\n border: 1px solid var(--dsh-kb-config-border);\n border-radius: var(--dsh-kb-config-radius-md);\n background: transparent;\n color: inherit;\n font: inherit;\n cursor: pointer;\n transition: background-color 150ms ease;\n}\n.dsh-kb-config__footer button:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(127, 127, 127, 0.12)); }\n.dsh-kb-config__error { color: var(--dsw-alias-state-error-primary, #e5484d); }\n";