dsh-daoing-memory 0.1.4 → 0.1.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.
package/lib/client.js CHANGED
@@ -4,10 +4,8 @@ window.__ModuleLoader__.load({
4
4
  var module = { exports: {} };
5
5
  var exports = module.exports;
6
6
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
7
- let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
8
7
  let react_jsx_runtime = require("react/jsx-runtime");
9
8
  let react = require("react");
10
- let _deepseek_ai_dsh_client_runtime_client = require("@deepseek-ai/dsh-client-runtime/client");
11
9
  //#region ../../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/core.js
12
10
  var _a$1;
13
11
  function $constructor(name, initializer, params) {
@@ -7724,44 +7722,37 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7724
7722
  ]
7725
7723
  };
7726
7724
  //#endregion
7727
- //#region \0dsh-css:D:\DSH 插件项目\项目源码\deepseek-harness-master\packages\memory\dsh-daoing-memory\src\client\MemoryFooterAction.module.css.mjs
7728
- const css$1 = ".O-5X5a_action{cursor:pointer;height:36px;color:var(--dsw-alias-label-secondary);background:0 0;border:none;border-radius:8px;flex:none;justify-content:center;align-items:center;gap:6px;padding:0 10px;display:flex}.O-5X5a_action:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.O-5X5a_label{white-space:nowrap;font-size:14px;line-height:20px}";
7729
- const tagId$1 = "dsh-daoing-memory/MemoryFooterAction.module.css";
7730
- if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
7725
+ //#region \0dsh-css:D:\DSH 插件项目\项目源码\deepseek-harness-master\packages\memory\dsh-daoing-memory\src\client\MemoryHeaderAction.module.css.mjs
7726
+ const css$2 = ".S16TIG_memoryButton{border:1px solid var(--dsw-alias-border-l2);height:32px;color:var(--dsw-alias-label-primary);font-family:var(--dsw-font-family);cursor:pointer;white-space:nowrap;background:0 0;border-radius:18px;justify-content:center;align-items:center;padding:6px 12px;font-size:13px;font-weight:400;line-height:20px;display:inline-flex}.S16TIG_memoryButton:hover{background:var(--dsw-alias-interactive-bg-hover)}";
7727
+ const tagId$2 = "dsh-daoing-memory/MemoryHeaderAction.module.css";
7728
+ if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$2) + "]") === null) {
7731
7729
  const tag = document.createElement("style");
7732
7730
  tag.dataset.plugin = "dsh-daoing-memory";
7733
- tag.dataset.pluginCss = tagId$1;
7734
- tag.textContent = css$1;
7731
+ tag.dataset.pluginCss = tagId$2;
7732
+ tag.textContent = css$2;
7735
7733
  document.head.appendChild(tag);
7736
7734
  }
7737
- var MemoryFooterAction_module_css_default = {
7738
- "action": "O-5X5a_action",
7739
- "label": "O-5X5a_label"
7740
- };
7735
+ var MemoryHeaderAction_module_css_default = { "memoryButton": "S16TIG_memoryButton" };
7741
7736
  //#endregion
7742
- //#region src/client/MemoryFooterAction.tsx
7737
+ //#region src/client/MemoryHeaderAction.tsx
7743
7738
  /**
7744
- * Render the footer entry. The wide variant shows an icon + label button;
7745
- * the rail variant is a single icon. Clicking selects the first monitoring
7746
- * page, which opens the workbench overlay.
7739
+ * Render the header entry. Clicking selects the first monitoring page, which
7740
+ * opens the workbench overlay. The button carries `data-memory-nav` so the
7741
+ * workbench's click-outside dismissal treats it as part of the monitoring
7742
+ * surface.
7747
7743
  * @param props - composed slot props.
7748
- * @returns the action button.
7744
+ * @returns the capsule button.
7749
7745
  */
7750
- function MemoryFooterAction(props) {
7751
- const { wide } = props;
7752
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
7746
+ function MemoryHeaderAction(props) {
7747
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
7753
7748
  type: "button",
7754
- className: MemoryFooterAction_module_css_default.action,
7749
+ className: MemoryHeaderAction_module_css_default.memoryButton,
7755
7750
  "data-memory-nav": true,
7756
7751
  "aria-label": "记忆监控",
7757
- title: "记忆监控",
7758
7752
  onClick: () => {
7759
- props.actions.select("experience");
7753
+ props.selectPage("experience");
7760
7754
  },
7761
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconDataOutline16, { size: 18 }), wide && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
7762
- className: MemoryFooterAction_module_css_default.label,
7763
- children: "记忆"
7764
- })]
7755
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "记忆" })
7765
7756
  });
7766
7757
  }
7767
7758
  //#endregion
@@ -7822,12 +7813,18 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7822
7813
  //#endregion
7823
7814
  //#region src/client/navStore.ts
7824
7815
  /**
7825
- * Memory monitoring nav store: shared viewing state between the left-sidebar
7826
- * footer entry (sidebar.footer.action) and the right-pane takeover (shell.overlay).
7827
- * One factory handle is created in apply and passed to both registrations so
7828
- * selecting a menu in the sidebar and rendering the matching page read the
7829
- * same state. Module level exports the factory only — a module-level handle
7830
- * would pin the store's identity across plugin reloads.
7816
+ * Memory monitoring nav state: shared viewing state between the session header
7817
+ * entry (conversation.session.header.utilities, scope "session") and the
7818
+ * right-pane takeover (shell.overlay, scope "root").
7819
+ *
7820
+ * IMPORTANT: DSH's slot system enforces "one handle, one scope" — a single
7821
+ * store handle cannot be mounted under two different scopes. Since the header
7822
+ * slot is scope "session" and the overlay slot is scope "root", we CANNOT
7823
+ * share a DSH EngineStoreHandle between them.
7824
+ *
7825
+ * Instead, page selection lives in a module-level observable that both
7826
+ * components subscribe to via the useCurrentPage() React hook. Neither slot
7827
+ * registration passes a `store` option, so no scope pinning occurs.
7831
7828
  */
7832
7829
  /** The four fixed monitoring pages. */
7833
7830
  const MEMORY_NAV_ITEMS = [
@@ -7848,99 +7845,105 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7848
7845
  label: "人工管理"
7849
7846
  }
7850
7847
  ];
7848
+ let _currentPage = null;
7849
+ const _listeners = /* @__PURE__ */ new Set();
7850
+ function notify() {
7851
+ for (const fn of _listeners) fn();
7852
+ }
7853
+ /** Select a monitoring page (opens the overlay on that page). */
7854
+ function selectPage(page) {
7855
+ _currentPage = page;
7856
+ notify();
7857
+ }
7858
+ /** Clear the selection (hides the overlay, returns to conversation view). */
7859
+ function clearPage() {
7860
+ _currentPage = null;
7861
+ notify();
7862
+ }
7851
7863
  /**
7852
- * Create the memory nav store handle. `select` both chooses the page and
7853
- * expands the group; `clear` hides the takeover overlay (used when the user
7854
- * opens a session row, returning to the native conversation view).
7855
- * @returns the store handle (spec + type + identity + factory in one).
7864
+ * React hook: subscribe to page changes and re-render on update.
7865
+ * Returns the current page key, or null when the overlay is hidden.
7856
7866
  */
7857
- function createMemoryNavStore() {
7858
- return (0, _deepseek_ai_dsh_client_runtime_client.defineStore)({
7859
- init: () => ({
7860
- page: null,
7861
- collapsed: false
7862
- }),
7863
- actions: {
7864
- select: (d, page) => {
7865
- d.page = page;
7866
- d.collapsed = false;
7867
- },
7868
- clear: (d) => {
7869
- d.page = null;
7870
- },
7871
- toggleCollapsed: (d) => {
7872
- d.collapsed = !d.collapsed;
7873
- }
7874
- }
7875
- });
7867
+ function useCurrentPage() {
7868
+ const [, force] = (0, react.useState)(0);
7869
+ (0, react.useEffect)(() => {
7870
+ const fn = () => {
7871
+ force((n) => n + 1);
7872
+ };
7873
+ _listeners.add(fn);
7874
+ return () => {
7875
+ _listeners.delete(fn);
7876
+ };
7877
+ }, []);
7878
+ return _currentPage;
7876
7879
  }
7877
7880
  //#endregion
7878
7881
  //#region \0dsh-css:D:\DSH 插件项目\项目源码\deepseek-harness-master\packages\memory\dsh-daoing-memory\src\client\Workbench.module.css.mjs
7879
- const css = ".KAfEAG_panel{background:var(--dsw-alias-bg-base);border-left:1px solid var(--dsw-alias-border-l2);flex-direction:column;display:flex;position:absolute;top:0;bottom:0;right:0;overflow:hidden}.KAfEAG_header{border-bottom:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-module-platform);flex-wrap:wrap;align-items:center;gap:16px;padding:10px 16px;display:flex}.KAfEAG_titleBlock{flex-direction:column;gap:2px;min-width:180px;display:flex}.KAfEAG_title{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600}.KAfEAG_subtitle{color:var(--dsw-alias-label-caption);font-size:11px}.KAfEAG_statline{color:var(--dsw-alias-label-tertiary);margin-left:auto;font-size:11px}.KAfEAG_body{flex:1;padding:12px 16px 24px;overflow:auto}.KAfEAG_workbenchTabs{border-bottom:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-module-platform);align-items:center;gap:2px;padding:0 16px;display:flex}.KAfEAG_workbenchTab{color:var(--dsw-alias-label-secondary);cursor:pointer;white-space:nowrap;background:0 0;border:none;padding:10px 14px;font-size:13px;line-height:20px;position:relative}.KAfEAG_workbenchTab:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-hover)}.KAfEAG_workbenchTabActive{color:var(--dsw-alias-label-primary);font-weight:600}.KAfEAG_workbenchTabActive:after{content:\"\";background:var(--ds-color-accent,#4c8dff);border-radius:2px 2px 0 0;height:2px;position:absolute;bottom:-1px;left:14px;right:14px}.KAfEAG_page{flex-direction:column;gap:10px;display:flex}.KAfEAG_toolbar{flex-wrap:wrap;align-items:center;gap:10px;display:flex}.KAfEAG_tabs{border-bottom:1px solid var(--dsw-alias-border-l2);flex-wrap:wrap;align-items:center;gap:6px;margin-bottom:12px;padding-bottom:8px;display:flex}.KAfEAG_tab{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);cursor:pointer;white-space:nowrap;border-radius:999px;padding:6px 12px;font-size:12px}.KAfEAG_tab:hover{background:var(--dsw-alias-interactive-bg-hover)}.KAfEAG_tabActive{background:var(--dsw-alias-interactive-bg-active,var(--dsw-alias-bg-module-platform));color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-border-l3,var(--dsw-alias-border-l2));font-weight:600}.KAfEAG_field{color:var(--dsw-alias-label-caption);flex-direction:column;gap:3px;font-size:11px;display:flex}.KAfEAG_field input,.KAfEAG_field select,.KAfEAG_field textarea{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-base);color:var(--dsw-alias-label-primary);border-radius:6px;min-width:140px;padding:5px 8px;font-size:12px}.KAfEAG_field textarea{resize:vertical}.KAfEAG_check{color:var(--dsw-alias-label-secondary);align-items:center;gap:5px;font-size:12px;display:flex}.KAfEAG_btn{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-primary);cursor:pointer;white-space:nowrap;border-radius:6px;padding:5px 10px;font-size:12px}.KAfEAG_btn:hover{background:var(--dsw-alias-interactive-bg-hover)}.KAfEAG_btn:disabled{opacity:.5;cursor:default}.KAfEAG_btnDanger{color:var(--dsw-alias-state-error-primary)}.KAfEAG_btnDanger:hover{background:var(--dsw-alias-interactive-bg-hover-danger)}.KAfEAG_error{color:var(--dsw-alias-state-error-primary);font-size:12px}.KAfEAG_okLine{color:var(--dsw-alias-state-success-primary);font-size:12px}.KAfEAG_warnLine{color:var(--dsw-alias-state-warn-label);margin-bottom:6px;font-size:12px}.KAfEAG_empty{color:var(--dsw-alias-label-caption);padding:14px 4px;font-size:12px}.KAfEAG_list{flex-direction:column;gap:8px;display:flex}.KAfEAG_card{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-module-platform);border-radius:8px;padding:8px 12px}.KAfEAG_cardHead{cursor:pointer;flex-wrap:wrap;align-items:center;gap:8px;display:flex}.KAfEAG_cardTitle{color:var(--dsw-alias-label-primary);font-size:13px;font-weight:500}.KAfEAG_cardMeta{color:var(--dsw-alias-label-caption);font-size:11px}.KAfEAG_cardSub{align-items:center;gap:12px;margin-top:4px;display:flex}.KAfEAG_concernBg{color:var(--dsw-alias-label-caption);margin-top:3px;font-size:11px;line-height:1.5}.KAfEAG_cardDetail{border-top:1px solid var(--dsw-alias-border-l2);flex-direction:column;gap:5px;margin-top:8px;padding-top:8px;display:flex}.KAfEAG_detailRow{color:var(--dsw-alias-label-secondary);font-size:12px}.KAfEAG_detailLabel{min-width:64px;color:var(--dsw-alias-label-caption);display:inline-block}.KAfEAG_actions{flex-wrap:wrap;gap:6px;margin-top:4px;display:flex}.KAfEAG_historyTitle{color:var(--dsw-alias-label-secondary);margin-top:10px;font-size:12px;font-weight:600}.KAfEAG_table{border-collapse:collapse;width:100%;color:var(--dsw-alias-label-secondary);font-size:12px}.KAfEAG_table th{text-align:left;color:var(--dsw-alias-label-caption);border-bottom:1px solid var(--dsw-alias-border-l2);padding:5px 8px;font-weight:500}.KAfEAG_table td{border-bottom:1px solid var(--dsw-alias-border-l2);vertical-align:top;padding:5px 8px}.KAfEAG_valueCell{text-overflow:ellipsis;white-space:nowrap;max-width:320px;overflow:hidden}.KAfEAG_payloadFull{white-space:pre-wrap;word-break:break-all;max-width:480px}.KAfEAG_payloadToggle{cursor:pointer;color:var(--ds-color-accent,#4c8dff);user-select:none;margin-left:6px;font-size:12px}.KAfEAG_payloadToggle:hover{text-decoration:underline}.KAfEAG_cellActions{flex-wrap:wrap;gap:4px;display:flex}.KAfEAG_badge{white-space:nowrap;border-radius:9px;padding:1px 7px;font-size:11px}.KAfEAG_badgePositive{background:var(--dsw-alias-state-success-tertiary);color:var(--dsw-alias-state-success-primary)}.KAfEAG_badgeNegative{background:var(--dsw-alias-state-warn-tertiary);color:var(--dsw-alias-state-warn-label)}.KAfEAG_badgePinned{background:var(--dsw-alias-state-business-tertiary);color:var(--dsw-alias-state-business-primary)}.KAfEAG_badgeConflict{background:var(--dsw-alias-state-warn-tertiary);color:var(--dsw-alias-state-warn-label)}.KAfEAG_statusLive{background:var(--dsw-alias-state-success-tertiary);color:var(--dsw-alias-state-success-primary)}.KAfEAG_statusCandidate{background:var(--dsw-alias-interactive-bg-active);color:var(--dsw-alias-label-secondary)}.KAfEAG_statusChallenged{background:var(--dsw-alias-interactive-bg-hover-danger);color:var(--dsw-alias-state-error-primary)}.KAfEAG_statusOther{background:var(--dsw-alias-bg-skeleton);color:var(--dsw-alias-label-caption)}.KAfEAG_trust{color:var(--dsw-alias-label-tertiary);font-size:11px}.KAfEAG_columns{grid-template-columns:minmax(0,3fr) minmax(0,2fr);align-items:start;gap:16px;display:grid}.KAfEAG_column{flex-direction:column;gap:8px;min-width:0;display:flex}.KAfEAG_sectionTitle{color:var(--dsw-alias-label-primary);margin-top:6px;font-size:13px;font-weight:600}.KAfEAG_form{border:1px solid var(--dsw-alias-border-l2);border-radius:8px;flex-direction:column;gap:8px;padding:12px;display:flex}.KAfEAG_form .KAfEAG_btn{align-self:flex-start}.KAfEAG_rules{color:var(--dsw-alias-label-secondary);flex-direction:column;gap:4px;margin:0;padding-left:18px;font-size:12px;display:flex}";
7880
- const tagId = "dsh-daoing-memory/Workbench.module.css";
7881
- if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
7882
+ const css$1 = ".KAfEAG_panel{background:var(--dsw-alias-bg-base);border-left:1px solid var(--dsw-alias-border-l2);flex-direction:column;display:flex;position:absolute;top:0;bottom:0;right:0;overflow:hidden}.KAfEAG_header{border-bottom:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-module-platform);flex-wrap:wrap;align-items:center;gap:16px;padding:10px 16px;display:flex}.KAfEAG_titleBlock{flex-direction:column;gap:2px;min-width:180px;display:flex}.KAfEAG_title{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600}.KAfEAG_subtitle{color:var(--dsw-alias-label-caption);font-size:11px}.KAfEAG_statline{color:var(--dsw-alias-label-tertiary);margin-left:auto;font-size:11px}.KAfEAG_body{flex:1;padding:12px 16px 24px;overflow:auto}.KAfEAG_workbenchTabs{border-bottom:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-module-platform);align-items:center;gap:2px;padding:0 16px;display:flex}.KAfEAG_workbenchTab{color:var(--dsw-alias-label-secondary);cursor:pointer;white-space:nowrap;background:0 0;border:none;padding:10px 14px;font-size:13px;line-height:20px;position:relative}.KAfEAG_workbenchTab:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-hover)}.KAfEAG_workbenchTabActive{color:var(--dsw-alias-label-primary);font-weight:600}.KAfEAG_workbenchTabActive:after{content:\"\";background:var(--ds-color-accent,#4c8dff);border-radius:2px 2px 0 0;height:2px;position:absolute;bottom:-1px;left:14px;right:14px}.KAfEAG_page{flex-direction:column;gap:10px;display:flex}.KAfEAG_toolbar{flex-wrap:wrap;align-items:center;gap:10px;display:flex}.KAfEAG_tabs{border-bottom:1px solid var(--dsw-alias-border-l2);flex-wrap:wrap;align-items:center;gap:6px;margin-bottom:12px;padding-bottom:8px;display:flex}.KAfEAG_tab{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);cursor:pointer;white-space:nowrap;border-radius:999px;padding:6px 12px;font-size:12px}.KAfEAG_tab:hover{background:var(--dsw-alias-interactive-bg-hover)}.KAfEAG_tabActive{background:var(--dsw-alias-interactive-bg-active,var(--dsw-alias-bg-module-platform));color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-border-l3,var(--dsw-alias-border-l2));font-weight:600}.KAfEAG_field{color:var(--dsw-alias-label-caption);flex-direction:column;gap:3px;font-size:11px;display:flex}.KAfEAG_field input,.KAfEAG_field select,.KAfEAG_field textarea{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-base);color:var(--dsw-alias-label-primary);border-radius:6px;min-width:140px;padding:5px 8px;font-size:12px}.KAfEAG_field textarea{resize:vertical}.KAfEAG_check{color:var(--dsw-alias-label-secondary);align-items:center;gap:5px;font-size:12px;display:flex}.KAfEAG_btn{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-primary);cursor:pointer;white-space:nowrap;border-radius:6px;padding:5px 10px;font-size:12px}.KAfEAG_btn:hover{background:var(--dsw-alias-interactive-bg-hover)}.KAfEAG_btn:disabled{opacity:.5;cursor:default}.KAfEAG_btnDanger{color:var(--dsw-alias-state-error-primary)}.KAfEAG_btnDanger:hover{background:var(--dsw-alias-interactive-bg-hover-danger)}.KAfEAG_error{color:var(--dsw-alias-state-error-primary);font-size:12px}.KAfEAG_okLine{color:var(--dsw-alias-state-success-primary);font-size:12px}.KAfEAG_warnLine{color:var(--dsw-alias-state-warn-label);margin-bottom:6px;font-size:12px}.KAfEAG_empty{color:var(--dsw-alias-label-caption);padding:14px 4px;font-size:12px}.KAfEAG_list{flex-direction:column;gap:8px;display:flex}.KAfEAG_card{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-module-platform);border-radius:8px;padding:8px 12px}.KAfEAG_cardHead{cursor:pointer;flex-wrap:wrap;align-items:center;gap:8px;display:flex}.KAfEAG_cardTitle{color:var(--dsw-alias-label-primary);font-size:13px;font-weight:500}.KAfEAG_cardMeta{color:var(--dsw-alias-label-caption);font-size:11px}.KAfEAG_cardSub{align-items:center;gap:12px;margin-top:4px;display:flex}.KAfEAG_concernBg{color:var(--dsw-alias-label-caption);margin-top:3px;font-size:11px;line-height:1.5}.KAfEAG_cardDetail{border-top:1px solid var(--dsw-alias-border-l2);flex-direction:column;gap:5px;margin-top:8px;padding-top:8px;display:flex}.KAfEAG_detailRow{color:var(--dsw-alias-label-secondary);font-size:12px}.KAfEAG_detailLabel{min-width:64px;color:var(--dsw-alias-label-caption);display:inline-block}.KAfEAG_actions{flex-wrap:wrap;gap:6px;margin-top:4px;display:flex}.KAfEAG_historyTitle{color:var(--dsw-alias-label-secondary);margin-top:10px;font-size:12px;font-weight:600}.KAfEAG_table{border-collapse:collapse;width:100%;color:var(--dsw-alias-label-secondary);font-size:12px}.KAfEAG_table th{text-align:left;color:var(--dsw-alias-label-caption);border-bottom:1px solid var(--dsw-alias-border-l2);padding:5px 8px;font-weight:500}.KAfEAG_table td{border-bottom:1px solid var(--dsw-alias-border-l2);vertical-align:top;padding:5px 8px}.KAfEAG_valueCell{text-overflow:ellipsis;white-space:nowrap;max-width:320px;overflow:hidden}.KAfEAG_payloadFull{white-space:pre-wrap;word-break:break-all;max-width:480px}.KAfEAG_payloadToggle{cursor:pointer;color:var(--ds-color-accent,#4c8dff);user-select:none;margin-left:6px;font-size:12px}.KAfEAG_payloadToggle:hover{text-decoration:underline}.KAfEAG_cellActions{flex-wrap:wrap;gap:4px;display:flex}.KAfEAG_badge{white-space:nowrap;border-radius:9px;padding:1px 7px;font-size:11px}.KAfEAG_badgePositive{background:var(--dsw-alias-state-success-tertiary);color:var(--dsw-alias-state-success-primary)}.KAfEAG_badgeNegative{background:var(--dsw-alias-state-warn-tertiary);color:var(--dsw-alias-state-warn-label)}.KAfEAG_badgePinned{background:var(--dsw-alias-state-business-tertiary);color:var(--dsw-alias-state-business-primary)}.KAfEAG_badgeConflict{background:var(--dsw-alias-state-warn-tertiary);color:var(--dsw-alias-state-warn-label)}.KAfEAG_statusLive{background:var(--dsw-alias-state-success-tertiary);color:var(--dsw-alias-state-success-primary)}.KAfEAG_statusCandidate{background:var(--dsw-alias-interactive-bg-active);color:var(--dsw-alias-label-secondary)}.KAfEAG_statusChallenged{background:var(--dsw-alias-interactive-bg-hover-danger);color:var(--dsw-alias-state-error-primary)}.KAfEAG_statusOther{background:var(--dsw-alias-bg-skeleton);color:var(--dsw-alias-label-caption)}.KAfEAG_trust{color:var(--dsw-alias-label-tertiary);font-size:11px}.KAfEAG_columns{grid-template-columns:minmax(0,3fr) minmax(0,2fr);align-items:start;gap:16px;display:grid}.KAfEAG_column{flex-direction:column;gap:8px;min-width:0;display:flex}.KAfEAG_sectionTitle{color:var(--dsw-alias-label-primary);margin-top:6px;font-size:13px;font-weight:600}.KAfEAG_form{border:1px solid var(--dsw-alias-border-l2);border-radius:8px;flex-direction:column;gap:8px;padding:12px;display:flex}.KAfEAG_form .KAfEAG_btn{align-self:flex-start}.KAfEAG_rules{color:var(--dsw-alias-label-secondary);flex-direction:column;gap:4px;margin:0;padding-left:18px;font-size:12px;display:flex}";
7883
+ const tagId$1 = "dsh-daoing-memory/Workbench.module.css";
7884
+ if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
7882
7885
  const tag = document.createElement("style");
7883
7886
  tag.dataset.plugin = "dsh-daoing-memory";
7884
- tag.dataset.pluginCss = tagId;
7885
- tag.textContent = css;
7887
+ tag.dataset.pluginCss = tagId$1;
7888
+ tag.textContent = css$1;
7886
7889
  document.head.appendChild(tag);
7887
7890
  }
7888
7891
  var Workbench_module_css_default = {
7889
- "statusCandidate": "KAfEAG_statusCandidate",
7892
+ "toolbar": "KAfEAG_toolbar",
7890
7893
  "trust": "KAfEAG_trust",
7891
- "concernBg": "KAfEAG_concernBg",
7892
- "column": "KAfEAG_column",
7893
- "sectionTitle": "KAfEAG_sectionTitle",
7894
- "tabs": "KAfEAG_tabs",
7895
- "title": "KAfEAG_title",
7896
- "btnDanger": "KAfEAG_btnDanger",
7897
- "cardDetail": "KAfEAG_cardDetail",
7898
- "table": "KAfEAG_table",
7899
- "tabActive": "KAfEAG_tabActive",
7900
- "statusChallenged": "KAfEAG_statusChallenged",
7901
- "statline": "KAfEAG_statline",
7902
- "body": "KAfEAG_body",
7894
+ "columns": "KAfEAG_columns",
7895
+ "cardMeta": "KAfEAG_cardMeta",
7903
7896
  "statusOther": "KAfEAG_statusOther",
7897
+ "cardTitle": "KAfEAG_cardTitle",
7898
+ "badgePositive": "KAfEAG_badgePositive",
7904
7899
  "badgeNegative": "KAfEAG_badgeNegative",
7905
- "btn": "KAfEAG_btn",
7906
- "badgeConflict": "KAfEAG_badgeConflict",
7907
- "columns": "KAfEAG_columns",
7908
- "titleBlock": "KAfEAG_titleBlock",
7909
- "cardHead": "KAfEAG_cardHead",
7910
- "header": "KAfEAG_header",
7911
- "historyTitle": "KAfEAG_historyTitle",
7912
- "workbenchTab": "KAfEAG_workbenchTab",
7913
- "rules": "KAfEAG_rules",
7914
- "detailRow": "KAfEAG_detailRow",
7900
+ "cardSub": "KAfEAG_cardSub",
7915
7901
  "payloadToggle": "KAfEAG_payloadToggle",
7916
- "cellActions": "KAfEAG_cellActions",
7917
- "payloadFull": "KAfEAG_payloadFull",
7918
- "form": "KAfEAG_form",
7902
+ "okLine": "KAfEAG_okLine",
7919
7903
  "panel": "KAfEAG_panel",
7920
- "actions": "KAfEAG_actions",
7921
- "badgePositive": "KAfEAG_badgePositive",
7922
- "badge": "KAfEAG_badge",
7923
- "subtitle": "KAfEAG_subtitle",
7924
- "card": "KAfEAG_card",
7925
- "cardSub": "KAfEAG_cardSub",
7926
- "workbenchTabActive": "KAfEAG_workbenchTabActive",
7904
+ "title": "KAfEAG_title",
7905
+ "concernBg": "KAfEAG_concernBg",
7906
+ "error": "KAfEAG_error",
7907
+ "valueCell": "KAfEAG_valueCell",
7908
+ "statusChallenged": "KAfEAG_statusChallenged",
7927
7909
  "list": "KAfEAG_list",
7928
7910
  "statusLive": "KAfEAG_statusLive",
7929
- "okLine": "KAfEAG_okLine",
7911
+ "cellActions": "KAfEAG_cellActions",
7912
+ "badge": "KAfEAG_badge",
7913
+ "tabActive": "KAfEAG_tabActive",
7914
+ "detailLabel": "KAfEAG_detailLabel",
7915
+ "btnDanger": "KAfEAG_btnDanger",
7916
+ "workbenchTab": "KAfEAG_workbenchTab",
7917
+ "btn": "KAfEAG_btn",
7918
+ "cardHead": "KAfEAG_cardHead",
7919
+ "detailRow": "KAfEAG_detailRow",
7920
+ "page": "KAfEAG_page",
7921
+ "subtitle": "KAfEAG_subtitle",
7922
+ "historyTitle": "KAfEAG_historyTitle",
7923
+ "sectionTitle": "KAfEAG_sectionTitle",
7924
+ "table": "KAfEAG_table",
7930
7925
  "tab": "KAfEAG_tab",
7926
+ "body": "KAfEAG_body",
7931
7927
  "workbenchTabs": "KAfEAG_workbenchTabs",
7932
- "cardTitle": "KAfEAG_cardTitle",
7933
- "toolbar": "KAfEAG_toolbar",
7934
- "check": "KAfEAG_check",
7935
- "field": "KAfEAG_field",
7936
- "warnLine": "KAfEAG_warnLine",
7937
- "page": "KAfEAG_page",
7938
- "valueCell": "KAfEAG_valueCell",
7939
- "cardMeta": "KAfEAG_cardMeta",
7940
- "error": "KAfEAG_error",
7928
+ "titleBlock": "KAfEAG_titleBlock",
7929
+ "header": "KAfEAG_header",
7930
+ "card": "KAfEAG_card",
7941
7931
  "badgePinned": "KAfEAG_badgePinned",
7932
+ "statusCandidate": "KAfEAG_statusCandidate",
7933
+ "form": "KAfEAG_form",
7934
+ "check": "KAfEAG_check",
7935
+ "cardDetail": "KAfEAG_cardDetail",
7936
+ "payloadFull": "KAfEAG_payloadFull",
7937
+ "rules": "KAfEAG_rules",
7942
7938
  "empty": "KAfEAG_empty",
7943
- "detailLabel": "KAfEAG_detailLabel"
7939
+ "workbenchTabActive": "KAfEAG_workbenchTabActive",
7940
+ "badgeConflict": "KAfEAG_badgeConflict",
7941
+ "column": "KAfEAG_column",
7942
+ "warnLine": "KAfEAG_warnLine",
7943
+ "statline": "KAfEAG_statline",
7944
+ "actions": "KAfEAG_actions",
7945
+ "field": "KAfEAG_field",
7946
+ "tabs": "KAfEAG_tabs"
7944
7947
  };
7945
7948
  //#endregion
7946
7949
  //#region src/client/ExperiencePage.tsx
@@ -8028,7 +8031,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8028
8031
  });
8029
8032
  }, [actions, expanded]);
8030
8033
  const runPin = (0, react.useCallback)(async (item) => {
8031
- const reason = promptReason(item.pinned ? "取消永久标记" : "永久标记(置顶信任,豁免预算)");
8034
+ const reason = await promptReason(item.pinned ? "取消永久标记" : "永久标记(置顶信任,豁免预算)");
8032
8035
  if (reason === void 0) return;
8033
8036
  await actions.humanPin({
8034
8037
  id: item.id,
@@ -8043,7 +8046,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8043
8046
  refresh
8044
8047
  ]);
8045
8048
  const runPromote = (0, react.useCallback)(async (item) => {
8046
- const reason = promptReason("人工转正(候选 → 生效,V2 人工权威)");
8049
+ const reason = await promptReason("人工转正(候选 → 生效,V2 人工权威)");
8047
8050
  if (reason === void 0) return;
8048
8051
  await actions.humanPromote(item.id, reason);
8049
8052
  refresh();
@@ -8054,7 +8057,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8054
8057
  refresh
8055
8058
  ]);
8056
8059
  const runReleaseCold = (0, react.useCallback)(async (item) => {
8057
- const reason = promptReason("从冷宫放回候选(可再次被试探验证)");
8060
+ const reason = await promptReason("从冷宫放回候选(可再次被试探验证)");
8058
8061
  if (reason === void 0) return;
8059
8062
  await actions.humanReleaseCold({
8060
8063
  id: item.id,
@@ -8068,7 +8071,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8068
8071
  refresh
8069
8072
  ]);
8070
8073
  const runDelete = (0, react.useCallback)(async (item) => {
8071
- const reason = promptReason(`删除经验「${item.gist.slice(0, 24)}」(指纹保留在账本)`);
8074
+ const reason = await promptReason(`删除经验「${item.gist.slice(0, 24)}」(指纹保留在账本)`);
8072
8075
  if (reason === void 0) return;
8073
8076
  await actions.humanDeleteExperience({
8074
8077
  id: item.id,
@@ -8082,7 +8085,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8082
8085
  refresh
8083
8086
  ]);
8084
8087
  const runRollback = (0, react.useCallback)(async (item, toRevision) => {
8085
- const reason = promptReason(`回滚到 v${String(toRevision)}`);
8088
+ const reason = await promptReason(`回滚到 v${String(toRevision)}`);
8086
8089
  if (reason === void 0) return;
8087
8090
  await actions.humanRollback({
8088
8091
  id: item.id,
@@ -8392,6 +8395,183 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8392
8395
  });
8393
8396
  }
8394
8397
  //#endregion
8398
+ //#region \0dsh-css:D:\DSH 插件项目\项目源码\deepseek-harness-master\packages\memory\dsh-daoing-memory\src\client\ReasonDialog.module.css.mjs
8399
+ const css = ".L4KK8a_overlay{z-index:10000;backdrop-filter:blur(2px);background:#0006;justify-content:center;align-items:center;display:flex;position:fixed;inset:0}.L4KK8a_dialog{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-base);border-radius:12px;flex-direction:column;gap:12px;width:480px;max-width:90vw;max-height:80vh;padding:20px 24px;display:flex;box-shadow:0 8px 32px #00000026}.L4KK8a_header{flex-direction:column;gap:4px;display:flex}.L4KK8a_title{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600}.L4KK8a_subtitle{color:var(--dsw-alias-label-caption);font-size:12px}.L4KK8a_textarea{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-module-platform);width:100%;min-height:80px;color:var(--dsw-alias-label-primary);font-family:var(--dsw-font-family);resize:vertical;box-sizing:border-box;border-radius:8px;outline:none;padding:10px 12px;font-size:13px;line-height:20px}.L4KK8a_textarea:focus{border-color:var(--ds-color-accent,#4c8dff);box-shadow:0 0 0 2px #4c8dff26}.L4KK8a_textarea::placeholder{color:var(--dsw-alias-label-dimmed)}.L4KK8a_footer{justify-content:space-between;align-items:center;display:flex}.L4KK8a_hint{color:var(--dsw-alias-label-dimmed);font-size:11px}.L4KK8a_buttons{gap:8px;display:flex}.L4KK8a_btnCancel,.L4KK8a_btnConfirm{height:32px;font-family:var(--dsw-font-family);cursor:pointer;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;padding:0 16px;font-size:13px;font-weight:500}.L4KK8a_btnCancel{color:var(--dsw-alias-label-secondary);background:0 0}.L4KK8a_btnCancel:hover{background:var(--dsw-alias-interactive-bg-hover)}.L4KK8a_btnConfirm{background:var(--ds-color-accent,#4c8dff);color:#fff;border-color:#0000}.L4KK8a_btnConfirm:hover{opacity:.9}";
8400
+ const tagId = "dsh-daoing-memory/ReasonDialog.module.css";
8401
+ if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
8402
+ const tag = document.createElement("style");
8403
+ tag.dataset.plugin = "dsh-daoing-memory";
8404
+ tag.dataset.pluginCss = tagId;
8405
+ tag.textContent = css;
8406
+ document.head.appendChild(tag);
8407
+ }
8408
+ var ReasonDialog_module_css_default = {
8409
+ "buttons": "L4KK8a_buttons",
8410
+ "btnConfirm": "L4KK8a_btnConfirm",
8411
+ "footer": "L4KK8a_footer",
8412
+ "textarea": "L4KK8a_textarea",
8413
+ "hint": "L4KK8a_hint",
8414
+ "btnCancel": "L4KK8a_btnCancel",
8415
+ "title": "L4KK8a_title",
8416
+ "overlay": "L4KK8a_overlay",
8417
+ "subtitle": "L4KK8a_subtitle",
8418
+ "dialog": "L4KK8a_dialog",
8419
+ "header": "L4KK8a_header"
8420
+ };
8421
+ //#endregion
8422
+ //#region src/client/ReasonDialog.tsx
8423
+ /**
8424
+ * Custom modal dialogs: replaces the browser's native window.prompt for
8425
+ * audited human operations (delete, rollback, etc.) and value editing.
8426
+ * A modal overlay with a textarea, confirm/cancel buttons, and DSH theme tokens.
8427
+ *
8428
+ * Usage:
8429
+ * showReasonDialog(action) → Promise<string | undefined> (reason required)
8430
+ * showInputDialog(title, defaultValue?) → Promise<string | undefined> (value optional)
8431
+ *
8432
+ * The dialog is rendered as a fixed overlay (DSH slots don't provide a modal
8433
+ * seat; a fixed-position element is the standard pattern).
8434
+ */
8435
+ let pendingRequest = null;
8436
+ let renderCallback = null;
8437
+ function showDialog(request) {
8438
+ return new Promise((resolve) => {
8439
+ pendingRequest = {
8440
+ ...request,
8441
+ resolve
8442
+ };
8443
+ renderCallback?.();
8444
+ });
8445
+ }
8446
+ /**
8447
+ * Show the reason dialog and wait for the user's response.
8448
+ * @param action - human-readable action name shown in the title.
8449
+ * @returns the trimmed reason on confirm, or undefined on cancel/empty.
8450
+ */
8451
+ function showReasonDialog(action) {
8452
+ return showDialog({
8453
+ title: `「${action}」需要填写原因`,
8454
+ subtitle: "此操作将写入审计账本,原因必填",
8455
+ placeholder: "请填写原因…",
8456
+ defaultValue: "",
8457
+ requireNonEmpty: true
8458
+ });
8459
+ }
8460
+ /**
8461
+ * Show a generic input dialog and wait for the user's response.
8462
+ * @param title - dialog title.
8463
+ * @param defaultValue - pre-filled value (optional).
8464
+ * @returns the trimmed value on confirm, or undefined on cancel. Empty string is allowed.
8465
+ */
8466
+ function showInputDialog(title, defaultValue = "") {
8467
+ return showDialog({
8468
+ title,
8469
+ subtitle: "",
8470
+ placeholder: "请输入…",
8471
+ defaultValue,
8472
+ requireNonEmpty: false
8473
+ });
8474
+ }
8475
+ /**
8476
+ * The dialog component. Mount once at the workbench root; it stays invisible
8477
+ * until showReasonDialog or showInputDialog is called.
8478
+ */
8479
+ function ReasonDialogHost() {
8480
+ const [, forceRender] = (0, react.useState)(0);
8481
+ const textareaRef = (0, react.useRef)(null);
8482
+ (0, react.useEffect)(() => {
8483
+ renderCallback = () => {
8484
+ forceRender((n) => n + 1);
8485
+ };
8486
+ return () => {
8487
+ renderCallback = null;
8488
+ };
8489
+ }, []);
8490
+ (0, react.useEffect)(() => {
8491
+ if (pendingRequest) requestAnimationFrame(() => {
8492
+ const el = textareaRef.current;
8493
+ if (el) {
8494
+ el.focus();
8495
+ el.select();
8496
+ }
8497
+ });
8498
+ }, [pendingRequest?.title]);
8499
+ if (!pendingRequest) return null;
8500
+ const { title, subtitle, placeholder, defaultValue, requireNonEmpty, resolve } = pendingRequest;
8501
+ const handleConfirm = () => {
8502
+ const value = textareaRef.current?.value?.trim() ?? "";
8503
+ if (requireNonEmpty && value === "") return;
8504
+ pendingRequest = null;
8505
+ resolve(value);
8506
+ forceRender((n) => n + 1);
8507
+ };
8508
+ const handleCancel = () => {
8509
+ pendingRequest = null;
8510
+ resolve(void 0);
8511
+ forceRender((n) => n + 1);
8512
+ };
8513
+ const handleKeyDown = (e) => {
8514
+ if (e.key === "Escape") {
8515
+ e.preventDefault();
8516
+ handleCancel();
8517
+ }
8518
+ if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) {
8519
+ e.preventDefault();
8520
+ handleConfirm();
8521
+ }
8522
+ };
8523
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8524
+ className: ReasonDialog_module_css_default.overlay,
8525
+ onClick: handleCancel,
8526
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8527
+ className: ReasonDialog_module_css_default.dialog,
8528
+ onClick: (e) => {
8529
+ e.stopPropagation();
8530
+ },
8531
+ onKeyDown: handleKeyDown,
8532
+ children: [
8533
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8534
+ className: ReasonDialog_module_css_default.header,
8535
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
8536
+ className: ReasonDialog_module_css_default.title,
8537
+ children: title
8538
+ }), subtitle && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
8539
+ className: ReasonDialog_module_css_default.subtitle,
8540
+ children: subtitle
8541
+ })]
8542
+ }),
8543
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
8544
+ ref: textareaRef,
8545
+ className: ReasonDialog_module_css_default.textarea,
8546
+ placeholder,
8547
+ defaultValue,
8548
+ rows: 4
8549
+ }),
8550
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8551
+ className: ReasonDialog_module_css_default.footer,
8552
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
8553
+ className: ReasonDialog_module_css_default.hint,
8554
+ children: "Ctrl+Enter 确认 · Esc 取消"
8555
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8556
+ className: ReasonDialog_module_css_default.buttons,
8557
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
8558
+ type: "button",
8559
+ className: ReasonDialog_module_css_default.btnCancel,
8560
+ onClick: handleCancel,
8561
+ children: "取消"
8562
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
8563
+ type: "button",
8564
+ className: ReasonDialog_module_css_default.btnConfirm,
8565
+ onClick: handleConfirm,
8566
+ children: "确认"
8567
+ })]
8568
+ })]
8569
+ })
8570
+ ]
8571
+ })
8572
+ });
8573
+ }
8574
+ //#endregion
8395
8575
  //#region src/client/FactDiaryPage.tsx
8396
8576
  /**
8397
8577
  * Profile·concerns page, split into two sub-pages: 关心事项 (open-loop memos) /
@@ -8548,7 +8728,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8548
8728
  refresh();
8549
8729
  }, [refresh]);
8550
8730
  const runConfirm = (0, react.useCallback)(async (fact) => {
8551
- const reason = promptReason(fact.locked ? "解除人工确认" : "人工确认(锁定,禁止自动取代)");
8731
+ const reason = await promptReason(fact.locked ? "解除人工确认" : "人工确认(锁定,禁止自动取代)");
8552
8732
  if (reason === void 0) return;
8553
8733
  await actions.humanConfirmFact({
8554
8734
  factId: fact.id,
@@ -8563,9 +8743,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8563
8743
  refresh
8564
8744
  ]);
8565
8745
  const runEditFact = (0, react.useCallback)(async (fact) => {
8566
- const value = window.prompt(`编辑画像「${fact.category}/${fact.factKey}」的新值:`, fact.value);
8567
- if (value === null || value.trim() === "") return;
8568
- const reason = promptReason("人工编辑画像");
8746
+ const value = await showInputDialog(`编辑画像「${fact.category}/${fact.factKey}」的新值`, fact.value);
8747
+ if (value === void 0 || value.trim() === "") return;
8748
+ const reason = await promptReason("人工编辑画像");
8569
8749
  if (reason === void 0) return;
8570
8750
  await actions.humanEditFact({
8571
8751
  factId: fact.id,
@@ -8580,7 +8760,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8580
8760
  refresh
8581
8761
  ]);
8582
8762
  const runDeleteFact = (0, react.useCallback)(async (fact) => {
8583
- const reason = promptReason(`删除画像「${fact.category}/${fact.factKey}」(墓碑保留)`);
8763
+ const reason = await promptReason(`删除画像「${fact.category}/${fact.factKey}」(墓碑保留)`);
8584
8764
  if (reason === void 0) return;
8585
8765
  await actions.humanDeleteFact({
8586
8766
  factId: fact.id,
@@ -8622,7 +8802,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8622
8802
  factSources
8623
8803
  ]);
8624
8804
  const runSetConcernStatus = (0, react.useCallback)(async (tree, status) => {
8625
- const reason = promptReason(`把关心事项「${tree.concern.title}」改为 ${CONCERN_STATUS_LABELS[status] ?? status}`);
8805
+ const reason = await promptReason(`把关心事项「${tree.concern.title}」改为 ${CONCERN_STATUS_LABELS[status] ?? status}`);
8626
8806
  if (reason === void 0) return;
8627
8807
  await actions.humanSetConcernStatus({
8628
8808
  id: tree.concern.id,
@@ -8637,7 +8817,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8637
8817
  refresh
8638
8818
  ]);
8639
8819
  const runDeleteConcern = (0, react.useCallback)(async (tree) => {
8640
- const reason = promptReason(`删除关心事项「${tree.concern.title}」及其更新(墓碑保留)`);
8820
+ const reason = await promptReason(`删除关心事项「${tree.concern.title}」及其更新(墓碑保留)`);
8641
8821
  if (reason === void 0) return;
8642
8822
  await actions.humanDeleteConcern({
8643
8823
  id: tree.concern.id,
@@ -9466,7 +9646,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9466
9646
  setNotice(null);
9467
9647
  };
9468
9648
  const submitExperience = async () => {
9469
- const reason = promptReason("人工注入经验(固定格式)");
9649
+ const reason = await promptReason("人工注入经验(固定格式)");
9470
9650
  if (reason === void 0) return;
9471
9651
  if (gist.trim() === "" || family.trim() === "" || situation.trim() === "" || path.trim() === "" || reasoning.trim() === "") {
9472
9652
  setError("固定格式不完整:任务族、摘要、情境、路径、判断背景均为必填。");
@@ -9517,7 +9697,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9517
9697
  setError("负经验必须填写确认的失败原因。");
9518
9698
  return;
9519
9699
  }
9520
- const reason = promptReason("人工摄取(固定格式 + 出处,产出候选待验证)");
9700
+ const reason = await promptReason("人工摄取(固定格式 + 出处,产出候选待验证)");
9521
9701
  if (reason === void 0) return;
9522
9702
  try {
9523
9703
  const result = await actions.ingest({
@@ -9557,7 +9737,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9557
9737
  setError("编辑需要先填写经验 id。");
9558
9738
  return;
9559
9739
  }
9560
- const reason = promptReason("人工编辑经验");
9740
+ const reason = await promptReason("人工编辑经验");
9561
9741
  if (reason === void 0) return;
9562
9742
  try {
9563
9743
  const snapshot = await actions.humanEditExperience({
@@ -9578,7 +9758,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9578
9758
  }
9579
9759
  };
9580
9760
  const submitFact = async () => {
9581
- const reason = promptReason("人工添加画像");
9761
+ const reason = await promptReason("人工添加画像");
9582
9762
  if (reason === void 0) return;
9583
9763
  if (factKey.trim() === "" || factValue.trim() === "") {
9584
9764
  setError("画像的键与值均为必填。");
@@ -10047,34 +10227,35 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10047
10227
  /**
10048
10228
  * Memory workbench takeover: covers the frame area to the right of the
10049
10229
  * sidebar while a monitoring page is selected. The entry point is the
10050
- * sidebar.footer.action button (MemoryFooterAction); page switching lives
10051
- * inside this panel as a tab bar so all four pages remain reachable without
10052
- * relying on a sidebar nav group. Opening a session row clears the selection
10230
+ * conversation.session.header.utilities button (MemoryHeaderAction, left of
10231
+ * Session log); page switching lives inside this panel as a tab bar so all
10232
+ * four pages remain reachable. Opening a session row clears the selection
10053
10233
  * and returns to the native conversation view. All human mutations go through
10054
10234
  * the audited Remote callbacks.
10235
+ *
10236
+ * IMPORTANT: No DSH store handle is used here. The overlay slot has scope
10237
+ * "root" while the header slot has scope "session" — sharing a handle would
10238
+ * violate DSH's "one handle, one scope" rule. Page state comes from the
10239
+ * module-level observable in navStore.ts via useCurrentPage().
10055
10240
  */
10056
10241
  /** Format an epoch-ms timestamp as a compact local string. */
10057
10242
  function formatTs(ts) {
10058
10243
  return new Date(ts).toLocaleString("zh-CN", { hour12: false });
10059
10244
  }
10060
- /** Confirmation prompt with an audited reason; resolves undefined when cancelled. */
10061
- function promptReason(action) {
10062
- const reason = window.prompt(`「${action}」将写入审计账本。请填写原因(必填):`);
10063
- if (reason === null) return void 0;
10064
- const trimmed = reason.trim();
10065
- if (trimmed === "") {
10066
- window.alert("原因是必填项:人工操作必须可审计。");
10067
- return;
10068
- }
10069
- return trimmed;
10245
+ /**
10246
+ * Confirmation prompt with an audited reason; resolves undefined when cancelled.
10247
+ * Uses the custom ReasonDialog instead of the browser's native window.prompt.
10248
+ */
10249
+ async function promptReason(action) {
10250
+ return showReasonDialog(action);
10070
10251
  }
10071
10252
  /**
10072
10253
  * The workbench entry component. Renders nothing unless a monitoring page is
10073
- * selected in the nav store and a current session exists (the Remote face is
10074
- * session-bound).
10254
+ * selected in the module-level nav state and a current session exists (the
10255
+ * Remote face is session-bound).
10075
10256
  */
10076
10257
  function MemoryWorkbench(props) {
10077
- const nav = props.useStore((s) => s);
10258
+ const page = useCurrentPage();
10078
10259
  const sessionId = props.useSessions((s) => s).current;
10079
10260
  const [info, setInfo] = (0, react.useState)(null);
10080
10261
  const [stats, setStats] = (0, react.useState)(null);
@@ -10106,9 +10287,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10106
10287
  }, [
10107
10288
  info,
10108
10289
  refreshStats,
10109
- nav.page
10290
+ page
10110
10291
  ]);
10111
- const active = nav.page !== null && info !== null && sessionId !== void 0;
10292
+ const active = page !== null && info !== null && sessionId !== void 0;
10112
10293
  (0, react.useEffect)(() => {
10113
10294
  if (!active) return;
10114
10295
  const onPointerDown = (event) => {
@@ -10116,19 +10297,19 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10116
10297
  if (!(target instanceof Element)) return;
10117
10298
  if (target.closest("[data-memory-workbench]") !== null) return;
10118
10299
  if (target.closest("[data-memory-nav]") !== null) return;
10119
- props.actions.clear();
10300
+ clearPage();
10120
10301
  };
10121
10302
  window.addEventListener("pointerdown", onPointerDown, true);
10122
10303
  return () => {
10123
10304
  window.removeEventListener("pointerdown", onPointerDown, true);
10124
10305
  };
10125
- }, [active, props.actions]);
10306
+ }, [active]);
10126
10307
  const prevSession = (0, react.useRef)(sessionId);
10127
10308
  (0, react.useEffect)(() => {
10128
10309
  if (prevSession.current === sessionId) return;
10129
10310
  prevSession.current = sessionId;
10130
- props.actions.clear();
10131
- }, [sessionId, props.actions]);
10311
+ clearPage();
10312
+ }, [sessionId]);
10132
10313
  (0, react.useEffect)(() => {
10133
10314
  if (!active) return;
10134
10315
  const root = rootRef.current;
@@ -10147,7 +10328,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10147
10328
  }, [active]);
10148
10329
  const bound = (0, react.useMemo)(() => sessionId === void 0 ? null : bindMemoryActions(props, sessionId), [sessionId]);
10149
10330
  if (!active || info === null || bound === null) return null;
10150
- const title = MEMORY_NAV_ITEMS.find((item) => item.key === nav.page)?.label ?? info.workspaceTitle;
10331
+ const title = MEMORY_NAV_ITEMS.find((item) => item.key === page)?.label ?? info.workspaceTitle;
10151
10332
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
10152
10333
  ref: rootRef,
10153
10334
  className: Workbench_module_css_default.panel,
@@ -10175,10 +10356,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10175
10356
  "aria-label": "记忆监控页面",
10176
10357
  children: MEMORY_NAV_ITEMS.map((item) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
10177
10358
  type: "button",
10178
- className: clsx(Workbench_module_css_default.workbenchTab, nav.page === item.key && Workbench_module_css_default.workbenchTabActive),
10179
- "aria-current": nav.page === item.key ? "page" : void 0,
10359
+ className: clsx(Workbench_module_css_default.workbenchTab, page === item.key && Workbench_module_css_default.workbenchTabActive),
10360
+ "aria-current": page === item.key ? "page" : void 0,
10180
10361
  onClick: () => {
10181
- props.actions.select(item.key);
10362
+ selectPage(item.key);
10182
10363
  },
10183
10364
  children: item.label
10184
10365
  }, item.key))
@@ -10186,21 +10367,22 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10186
10367
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("main", {
10187
10368
  className: Workbench_module_css_default.body,
10188
10369
  children: [
10189
- nav.page === "experience" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ExperiencePage, {
10370
+ page === "experience" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ExperiencePage, {
10190
10371
  actions: bound,
10191
10372
  onChanged: refreshStats
10192
10373
  }),
10193
- nav.page === "fact" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FactDiaryPage, {
10374
+ page === "fact" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FactDiaryPage, {
10194
10375
  actions: bound,
10195
10376
  onChanged: refreshStats
10196
10377
  }),
10197
- nav.page === "ledger" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LedgerPage, { actions: bound }),
10198
- nav.page === "human" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(HumanOpsPage, {
10378
+ page === "ledger" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LedgerPage, { actions: bound }),
10379
+ page === "human" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(HumanOpsPage, {
10199
10380
  actions: bound,
10200
10381
  onChanged: refreshStats
10201
10382
  })
10202
10383
  ]
10203
- })
10384
+ }),
10385
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ReasonDialogHost, {})
10204
10386
  ]
10205
10387
  });
10206
10388
  }
@@ -10224,7 +10406,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10224
10406
  }
10225
10407
  /**
10226
10408
  * Client plugin body: mount the memory Remote contribution, then register the
10227
- * nav group and the overlay takeover sharing one nav store handle.
10409
+ * header entry and the overlay takeover. Page selection is shared through the
10410
+ * module-level observable in navStore.ts (not a DSH store handle) to avoid
10411
+ * the "one handle, one scope" conflict between the session-scoped header slot
10412
+ * and the root-scoped overlay slot.
10228
10413
  * @param ctx - client root context.
10229
10414
  * @returns disposer after both entries and the Remote namespace unregister.
10230
10415
  */
@@ -10275,18 +10460,16 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10275
10460
  humanReleaseCold: async (session, request) => unwrap(await memory.humanReleaseCold(session, request)),
10276
10461
  ingest: async (session, request) => unwrap(await memory.ingest(session, request))
10277
10462
  };
10278
- const navStore = createMemoryNavStore();
10279
- const disposeNav = ctx.slots.inject("sidebar.footer.action", () => ctx.slots.register({
10280
- name: "sidebar.footer.action",
10463
+ const disposeNav = ctx.slots.inject("conversation.session.header.utilities", () => ctx.slots.register({
10464
+ name: "conversation.session.header.utilities",
10281
10465
  id: "memory-nav",
10282
- order: 100,
10283
- store: navStore
10284
- }, MemoryFooterAction));
10466
+ order: -10,
10467
+ inject: () => ({ selectPage })
10468
+ }, MemoryHeaderAction));
10285
10469
  const disposeOverlay = ctx.slots.inject("shell.overlay", () => ctx.slots.register({
10286
10470
  name: "shell.overlay",
10287
10471
  id: "memory-workbench",
10288
10472
  order: 100,
10289
- store: navStore,
10290
10473
  inject: () => actions
10291
10474
  }, MemoryWorkbench));
10292
10475
  return async () => {