@shgroup/dsh-serenity-hooks 1.23.1 → 1.23.3

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/dsh.plugin.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "id": "dsh-serenity-hooks",
3
- "version": "1.23.1",
3
+ "version": "1.23.3",
4
4
  "main": "lib/index.js",
5
5
  "description": "宁静号 ACC harness(Native Cordis 插件):真实 DSH 工具 cc_fs/session/acc_msm/eap/neat/cce/loop/session_rebuild + 拦截缝机械约束(safe-mode/路径守卫)+ 高级设定面板(双端口网关/账号管理)。适配 DSH 公开版(0.1.0-rc,deepseek-ai/deepseek-harness)。",
6
6
  "engines": {
package/lib/client.js CHANGED
@@ -9,9 +9,9 @@ window.__ModuleLoader__.load({
9
9
  let react_jsx_runtime = require("react/jsx-runtime");
10
10
  //#region \0sp-css:/home/yh/home/home-serenity/AI_LAB/dsh-serenity-plugin/hooks/dsh-serenity-hooks/src/client/SafeModePanel
11
11
  const css$3 = "/* SafeModePanel — 会话头部 Serenity 状态卡片(v1.22 UX 重构)\n * 卡片 → 点击 → 官方 Modal(body portal 遮罩 + 居中)\n * 模态内:tab 栏 + 分组(groupTitle 标题 + rowCard 行卡)——看齐官方 settings 设计语言\n * 遵循 web-styling.md:颜色只用 --dsw-alias-* 语义 token(明暗自适应);\n * 前缀 sp- 防冲突。 */\n\n/* ── 头部状态卡片(可点击) ── */\n\n.sp-card {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n height: 26px;\n padding: 0 10px;\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 8px;\n background: var(--dsw-alias-bg-module-platform);\n color: inherit;\n font-size: 12px;\n cursor: pointer;\n transition: background var(--ds-transition-duration-fast, 0.1s) var(--ds-ease-in-out, ease),\n border-color var(--ds-transition-duration-fast, 0.1s) var(--ds-ease-in-out, ease);\n}\n\n.sp-card:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n border-color: var(--dsw-alias-border-l2);\n}\n\n.sp-card:focus-visible {\n outline: 2px solid var(--dsw-alias-button-ghost-active-border);\n outline-offset: 1px;\n}\n\n.sp-card:disabled {\n opacity: 0.6;\n cursor: default;\n}\n\n.sp-dot {\n flex: none;\n width: 7px;\n height: 7px;\n border-radius: 50%;\n}\n\n.sp-dotOn {\n background: var(--dsw-alias-state-success-primary);\n}\n\n.sp-dotOff {\n background: var(--dsw-alias-label-dimmed);\n}\n\n.sp-brand {\n color: var(--dsw-alias-label-primary);\n font-weight: 500;\n}\n\n.sp-chev {\n color: var(--dsw-alias-label-dimmed);\n}\n\n/* safe-mode 徽标(卡片本体直接可见;ON 红 / OFF 灰) */\n.sp-sm {\n display: inline-flex;\n align-items: center;\n gap: 3px;\n height: 18px;\n padding: 0 7px;\n border-radius: 9px;\n font-size: 11px;\n font-weight: 600;\n line-height: 1;\n}\n\n.sp-smOn {\n background: var(--dsw-alias-state-warning-bg, rgba(245, 158, 11, 0.18));\n color: var(--dsw-alias-state-warning-fg, #f59e0b);\n border: 1px solid var(--dsw-alias-state-warning-border, rgba(245, 158, 11, 0.4));\n}\n\n.sp-smOff {\n background: var(--dsw-alias-interactive-bg-active, rgba(128, 128, 128, 0.16));\n color: var(--dsw-alias-label-dimmed);\n border: 1px solid var(--dsw-alias-border-l1);\n}\n\n.sp-smIcon {\n flex: none;\n}\n\n/* ── 官方 Modal 定制(宽度 + 内容紧凑) ── */\n\n.sp-modal {\n width: 520px;\n max-width: calc(100vw - 48px);\n}\n\n/* ── tab 栏 ── */\n\n.sp-tabs {\n display: flex;\n gap: 6px;\n padding: 0 2px 12px;\n border-bottom: 1px solid var(--dsw-alias-border-l1);\n}\n\n.sp-tab {\n flex: 1;\n padding: 8px 0;\n border: none;\n border-radius: 8px;\n background: transparent;\n color: var(--dsw-alias-label-secondary);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: background var(--ds-transition-duration-fast, 0.1s) var(--ds-ease-in-out, ease);\n}\n\n.sp-tab:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.sp-tabOn {\n background: var(--dsw-alias-interactive-bg-active, rgba(128, 128, 128, 0.2));\n color: var(--dsw-alias-label-primary);\n font-weight: 600;\n}\n\n/* ── 模态内容 ── */\n\n.sp-modalBody {\n display: flex;\n flex-direction: column;\n gap: 16px;\n padding-top: 14px;\n /* 内容超出视口时 body 区滚动(兜底——不再截断);整卡不滚动 */\n overflow-y: auto;\n max-height: calc(100vh - 200px);\n}\n\n/* ── 分组(官方 settings 语言:groupTitle + rows) ── */\n\n.sp-group {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.sp-groupHead {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n}\n\n.sp-groupTitle {\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n font-weight: 600;\n letter-spacing: 0.02em;\n text-transform: uppercase;\n color: var(--dsw-alias-label-secondary);\n}\n\n.sp-rows {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n/* 行卡(rowCard:border + radius + padding;值与 label 分离、长内容可换行) */\n.sp-row {\n display: flex;\n align-items: baseline;\n gap: 12px;\n min-width: 0;\n padding: 8px 12px;\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 10px;\n background: var(--dsw-alias-bg-module);\n}\n\n.sp-label {\n flex: none;\n width: 76px;\n font-size: 12px;\n font-weight: 500;\n color: var(--dsw-alias-label-secondary);\n white-space: nowrap;\n}\n\n.sp-value {\n flex: 1;\n min-width: 0;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-primary);\n font-family: var(--ds-font-family-code, monospace);\n word-break: break-all;\n overflow-wrap: anywhere;\n}\n\n/* 安全模式动作区 */\n.sp-actions {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 8px 12px;\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 10px;\n background: var(--dsw-alias-bg-module);\n}\n\n.sp-toggle {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n height: 24px;\n padding: 0 10px;\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 6px;\n font-size: 12px;\n cursor: pointer;\n transition: background var(--ds-transition-duration-fast, 0.1s) var(--ds-ease-in-out, ease);\n}\n\n.sp-toggleLg {\n height: 30px;\n padding: 0 16px;\n font-size: 13px;\n}\n\n.sp-toggleOn {\n background: var(--dsw-alias-state-warning-bg, rgba(245, 158, 11, 0.15));\n color: var(--dsw-alias-state-warning-fg, #f59e0b);\n border-color: var(--dsw-alias-state-warning-border, rgba(245, 158, 11, 0.4));\n}\n\n.sp-toggleOff {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-secondary);\n}\n\n.sp-toggleIcon {\n flex: none;\n}\n\n.sp-toggleDesc {\n flex: 1;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-tertiary);\n}\n\n/* loop 运行状态区块 */\n\n.sp-loopsToggle {\n flex: none;\n padding: 2px 10px;\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 6px;\n background: transparent;\n color: var(--dsw-alias-label-secondary);\n font-size: 11px;\n cursor: pointer;\n}\n\n.sp-loopsToggle:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.sp-loopsList {\n display: flex;\n flex-direction: column;\n gap: 4px;\n margin-top: 2px;\n}\n\n.sp-loopItem {\n display: flex;\n flex-direction: column;\n gap: 2px;\n padding: 8px 12px;\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 8px;\n min-width: 0;\n}\n\n.sp-loopHead {\n display: flex;\n align-items: baseline;\n gap: 8px;\n min-width: 0;\n}\n\n.sp-loopLabel {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: 12px;\n font-weight: 500;\n color: var(--dsw-alias-label-primary);\n}\n\n.sp-loopRound {\n flex: none;\n font-size: 11px;\n color: var(--dsw-alias-label-dimmed);\n}\n\n.sp-loopTime {\n flex: none;\n font-size: 11px;\n color: var(--dsw-alias-label-dimmed);\n}\n\n.sp-loopResp {\n font-size: 11px;\n line-height: 16px;\n color: var(--dsw-alias-label-secondary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.sp-loopsMore {\n font-size: 11px;\n color: var(--dsw-alias-label-dimmed);\n padding: 4px 12px;\n}\n\n/* 底部提示(配置入口引导) */\n.sp-hint {\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-tertiary);\n word-break: break-word;\n overflow-wrap: anywhere;\n padding: 8px 12px;\n border: 1px dashed var(--dsw-alias-border-l2);\n border-radius: 10px;\n}\n";
12
- if (typeof document !== "undefined" && document.querySelector("style[data-sp-css]") === null) {
12
+ if (typeof document !== "undefined" && document.querySelector("style[data-sp-css=\"SafeModePanel\"]") === null) {
13
13
  const tag = document.createElement("style");
14
- tag.setAttribute("data-sp-css", "1");
14
+ tag.setAttribute("data-sp-css", "SafeModePanel");
15
15
  tag.textContent = css$3;
16
16
  document.head.appendChild(tag);
17
17
  }
@@ -547,9 +547,9 @@ window.__ModuleLoader__.load({
547
547
  //#endregion
548
548
  //#region \0sp-css:/home/yh/home/home-serenity/AI_LAB/dsh-serenity-plugin/hooks/dsh-serenity-hooks/src/client/AccountsEditor
549
549
  const css$2 = "/* AccountsEditor — DSH 设置面板「外部访问」区块(v1.22)\n * 与 SettingsSection ss-* 同设计语言:--dsw-alias-* 语义 token,明暗自适应。 */\n\n.ae-root {\n display: flex;\n flex-direction: column;\n gap: 16px;\n padding: 12px 14px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 12px;\n font-size: 13px;\n}\n\n.ae-warn {\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-state-warning-fg, #f59e0b);\n word-break: break-word;\n}\n\n.ae-block {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.ae-title {\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n font-weight: 600;\n letter-spacing: 0.02em;\n text-transform: uppercase;\n color: var(--dsw-alias-label-secondary);\n}\n\n.ae-desc {\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-tertiary);\n word-break: break-word;\n overflow-wrap: anywhere;\n}\n\n.ae-note {\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-tertiary);\n}\n\n/* ── 监听设置 / 白名单输入行 ── */\n\n.ae-row {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.ae-label {\n flex: none;\n font-size: 12px;\n font-weight: 500;\n color: var(--dsw-alias-label-secondary);\n white-space: nowrap;\n}\n\n.ae-input {\n flex: 1;\n min-width: 0;\n padding: 6px 10px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 8px;\n background: var(--dsw-alias-bg-module);\n color: var(--dsw-alias-label-primary);\n font-size: 13px;\n outline: none;\n}\n\n.ae-input:focus {\n border-color: var(--dsw-alias-button-primary-bg, var(--dsw-alias-accent, #3b82f6));\n}\n\n.ae-input::placeholder {\n color: var(--dsw-alias-label-dimmed);\n}\n\n.ae-input.ae-port {\n flex: none;\n width: 76px;\n}\n\n/* ── 账号列表 ── */\n\n.ae-list {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.ae-head {\n display: flex;\n gap: 8px;\n font-size: 11px;\n font-weight: 500;\n color: var(--dsw-alias-label-dimmed);\n padding: 0 2px;\n text-transform: uppercase;\n letter-spacing: 0.02em;\n}\n\n.ae-item {\n display: flex;\n gap: 8px;\n align-items: center;\n padding: 6px 2px;\n}\n\n.ae-colUser { flex: 1.2; }\n.ae-colPass { flex: 1.6; }\n.ae-colTotp { flex: 2.2; min-width: 0; }\n.ae-colOp { flex: none; width: 48px; }\n\n/* ── v1.22.4 TOTP 第二因素 ── */\n\n.ae-totpBtn {\n flex: none;\n padding: 4px 10px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 6px;\n background: transparent;\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n cursor: pointer;\n white-space: nowrap;\n}\n\n.ae-totpBtn:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.ae-totpPending {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n align-items: center;\n min-width: 0;\n}\n\n.ae-totpSecret {\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n font-size: 11px;\n background: var(--dsw-alias-surface-raised, rgba(0, 0, 0, 0.25));\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 4px;\n padding: 2px 6px;\n color: var(--dsw-alias-label-secondary);\n word-break: break-all;\n}\n\n.ae-totpUri {\n font-size: 11px;\n color: var(--dsw-alias-accent, #3b82f6);\n text-decoration: none;\n}\n\n.ae-totpUri:hover {\n text-decoration: underline;\n}\n\n.ae-totpConfirm {\n max-width: 120px;\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n letter-spacing: 0.2em;\n}\n\n.ae-totpBadge {\n font-size: 12px;\n color: var(--dsw-alias-state-warning-fg, #f59e0b);\n}\n\n.ae-totpClear {\n display: flex;\n gap: 6px;\n align-items: center;\n}\n\n.ae-check {\n display: flex;\n gap: 8px;\n align-items: center;\n font-size: 12px;\n color: var(--dsw-alias-label-secondary);\n margin-top: 10px;\n cursor: pointer;\n}\n\n.ae-check input {\n accent-color: var(--dsw-alias-accent, #3b82f6);\n}\n\n.ae-del {\n flex: none;\n padding: 4px 10px;\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 6px;\n background: transparent;\n color: var(--dsw-alias-state-danger-fg, #f87171);\n font-size: 12px;\n cursor: pointer;\n}\n\n.ae-del:hover {\n background: var(--dsw-alias-state-danger-bg, rgba(248, 113, 113, 0.12));\n}\n\n.ae-add {\n align-self: flex-start;\n padding: 5px 12px;\n border: 1px dashed var(--dsw-alias-border-l2);\n border-radius: 8px;\n background: transparent;\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n cursor: pointer;\n}\n\n.ae-add:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.ae-wsSelect {\n margin-top: 8px;\n max-width: 100%;\n cursor: pointer;\n}\n\n/* ── 工作区白名单 chips ── */\n\n.ae-wsList {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n}\n\n.ae-wsChip {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 3px 8px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 8px;\n background: var(--dsw-alias-interactive-bg-active, rgba(128, 128, 128, 0.14));\n}\n\n.ae-wsPath {\n font-size: 12px;\n color: var(--dsw-alias-label-primary);\n font-family: var(--ds-font-family-code, monospace);\n word-break: break-all;\n}\n\n.ae-wsDel {\n flex: none;\n width: 18px;\n height: 18px;\n border: none;\n border-radius: 50%;\n background: transparent;\n color: var(--dsw-alias-label-dimmed);\n font-size: 13px;\n line-height: 1;\n cursor: pointer;\n}\n\n.ae-wsDel:hover {\n background: var(--dsw-alias-state-danger-bg, rgba(248, 113, 113, 0.18));\n color: var(--dsw-alias-state-danger-fg, #f87171);\n}\n\n/* ── 错误 / 操作区 ── */\n\n.ae-error {\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-state-danger-fg, #f87171);\n word-break: break-word;\n}\n\n.ae-actions {\n display: flex;\n justify-content: flex-end;\n padding-top: 4px;\n border-top: 1px solid var(--dsw-alias-border-l1);\n}\n\n.ae-save {\n padding: 7px 24px;\n border: 0;\n border-radius: 8px;\n background: var(--dsw-alias-button-primary-bg, var(--dsw-alias-accent, #3b82f6));\n color: var(--dsw-alias-button-primary-fg, #fff);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n}\n\n.ae-save:hover:not(:disabled) {\n filter: brightness(1.08);\n}\n\n.ae-save:disabled {\n opacity: 0.6;\n cursor: default;\n}\n";
550
- if (typeof document !== "undefined" && document.querySelector("style[data-sp-css]") === null) {
550
+ if (typeof document !== "undefined" && document.querySelector("style[data-sp-css=\"AccountsEditor\"]") === null) {
551
551
  const tag = document.createElement("style");
552
- tag.setAttribute("data-sp-css", "1");
552
+ tag.setAttribute("data-sp-css", "AccountsEditor");
553
553
  tag.textContent = css$2;
554
554
  document.head.appendChild(tag);
555
555
  }
@@ -949,9 +949,9 @@ window.__ModuleLoader__.load({
949
949
  //#endregion
950
950
  //#region \0sp-css:/home/yh/home/home-serenity/AI_LAB/dsh-serenity-plugin/hooks/dsh-serenity-hooks/src/client/PersonaEditor
951
951
  const css$1 = "/* PersonaEditor.css — 彩蛋模式区块(v1.23.1,官方 settings 设计语言:rowCard 内分组) */\n\n.pe-wrap {\n display: flex;\n flex-direction: column;\n gap: 10px;\n width: 100%;\n padding: 2px 0 6px;\n}\n\n.pe-row {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.pe-label {\n font-size: 12px;\n color: var(--dsw-alias-text-secondary, #8a8f98);\n user-select: none;\n}\n\n.pe-input,\n.pe-textarea {\n width: 100%;\n box-sizing: border-box;\n background: var(--dsw-alias-bg-secondary, rgba(128, 128, 128, 0.08));\n color: var(--dsw-alias-text-primary, #e6e6e6);\n border: 1px solid var(--dsw-alias-border, rgba(128, 128, 128, 0.25));\n border-radius: 8px;\n font-size: 13px;\n padding: 8px 10px;\n outline: none;\n}\n\n.pe-input:focus,\n.pe-textarea:focus {\n border-color: var(--dsw-alias-accent, #4f8cff);\n}\n\n.pe-textarea {\n resize: vertical;\n min-height: 120px;\n line-height: 1.5;\n font-family: var(--dsw-alias-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);\n font-size: 12px;\n}\n\n.pe-actions {\n display: flex;\n gap: 8px;\n align-items: center;\n flex-wrap: wrap;\n}\n\n.pe-btn {\n border-radius: 6px;\n padding: 5px 12px;\n font-size: 12px;\n cursor: pointer;\n border: 1px solid var(--dsw-alias-border, rgba(128, 128, 128, 0.25));\n background: transparent;\n color: var(--dsw-alias-text-primary, #e6e6e6);\n transition: opacity 0.15s;\n}\n\n.pe-btn:hover:not(:disabled) {\n opacity: 0.85;\n}\n\n.pe-btn:disabled {\n opacity: 0.4;\n cursor: default;\n}\n\n.pe-btnGhost {\n border-color: var(--dsw-alias-border, rgba(128, 128, 128, 0.25));\n}\n\n.pe-btnPrimary {\n background: var(--dsw-alias-accent, #4f8cff);\n border-color: transparent;\n color: #fff;\n}\n\n.pe-hint {\n font-size: 12px;\n margin: 0;\n}\n\n.pe-hintOk {\n color: var(--dsw-alias-state-success, #4caf50);\n}\n\n.pe-hintErr {\n color: var(--dsw-alias-state-error, #e5484d);\n}\n";
952
- if (typeof document !== "undefined" && document.querySelector("style[data-sp-css]") === null) {
952
+ if (typeof document !== "undefined" && document.querySelector("style[data-sp-css=\"PersonaEditor\"]") === null) {
953
953
  const tag = document.createElement("style");
954
- tag.setAttribute("data-sp-css", "1");
954
+ tag.setAttribute("data-sp-css", "PersonaEditor");
955
955
  tag.textContent = css$1;
956
956
  document.head.appendChild(tag);
957
957
  }
@@ -1107,9 +1107,9 @@ Instruction-following style:
1107
1107
  //#endregion
1108
1108
  //#region \0sp-css:/home/yh/home/home-serenity/AI_LAB/dsh-serenity-plugin/hooks/dsh-serenity-hooks/src/client/SettingsSection
1109
1109
  const css = "/* SettingsSection — dsh 原生设置面板 serenity-hooks 简单配置页\n v1.21.1 看齐 dsh 自身:官方 settings 设计语言——\n section > title + intro + group(groupTitle) + rowCard 行卡;\n 全部 --dsw-alias-* token(与 ui-settings-models 同词汇表)。 */\n\n/* 页面容器(官方 .section:flex column gap 12) */\n.ss-section {\n display: flex;\n flex-direction: column;\n gap: 14px;\n max-width: 720px;\n color: var(--dsw-alias-label-primary);\n}\n\n/* 页面标题(官方 .title:16px/24 500) */\n.ss-title {\n margin: 0;\n font-size: 16px;\n line-height: 24px;\n font-weight: 500;\n color: var(--dsw-alias-label-primary);\n}\n\n/* 页面说明(官方 .intro:14px/22 tertiary) */\n.ss-intro {\n margin: 0;\n font-size: 14px;\n line-height: 22px;\n color: var(--dsw-alias-label-tertiary);\n word-break: break-word;\n overflow-wrap: anywhere;\n}\n\n/* 分组(多级标题:分组标题 + 行卡列表) */\n.ss-group {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n/* 分组标题(二级:12px/18 500 secondary——官方 fieldLabel 风格) */\n.ss-groupTitle {\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n font-weight: 600;\n letter-spacing: 0.02em;\n text-transform: uppercase;\n color: var(--dsw-alias-label-secondary);\n}\n\n/* 行卡列表(官方 .rows:无 marker,gap 8) */\n.ss-rows {\n list-style: none;\n margin: 0;\n padding: 0;\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n/* 行卡(官方 .rowCard:border-l2 r12 padding 12/14) */\n.ss-rowCard {\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 12px;\n padding: 12px 14px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 16px;\n}\n\n/* 行卡文本(标题 + 说明 左列) */\n.ss-rowText {\n display: flex;\n flex-direction: column;\n gap: 3px;\n min-width: 0;\n flex: 1;\n}\n\n/* 行卡标题(官方 .rowName:14px/22 500) */\n.ss-rowName {\n font-size: 14px;\n line-height: 22px;\n font-weight: 500;\n color: var(--dsw-alias-label-primary);\n}\n\n/* 行卡说明(12px/18 tertiary) */\n.ss-rowDesc {\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-tertiary);\n word-break: break-word;\n overflow-wrap: anywhere;\n}\n\n/* 行卡控件(右置) */\n.ss-rowControl {\n flex: none;\n display: flex;\n align-items: center;\n}\n\n/* 开关(官方 token 的自绘 toggle:track 22px,thumb 16px) */\n.ss-switch {\n position: relative;\n flex: none;\n width: 40px;\n height: 22px;\n cursor: pointer;\n}\n\n.ss-switch input {\n position: absolute;\n opacity: 0;\n width: 100%;\n height: 100%;\n margin: 0;\n cursor: pointer;\n}\n\n.ss-switchTrack {\n position: absolute;\n inset: 0;\n border-radius: 11px;\n background: var(--dsw-alias-interactive-bg-active, rgba(128, 128, 128, 0.3));\n transition: background var(--ds-transition-duration-fast, 0.15s) var(--ds-ease-in-out, ease);\n}\n\n.ss-switchTrack::after {\n content: '';\n position: absolute;\n top: 3px;\n left: 3px;\n width: 16px;\n height: 16px;\n border-radius: 50%;\n background: var(--dsw-alias-label-primary, #eee);\n transition: transform var(--ds-transition-duration-fast, 0.15s) var(--ds-ease-in-out, ease);\n}\n\n.ss-switch input:checked + .ss-switchTrack {\n background: var(--dsw-alias-state-success-primary, #22c55e);\n}\n\n.ss-switch input:checked + .ss-switchTrack::after {\n transform: translateX(18px);\n}\n\n.ss-switch input:disabled + .ss-switchTrack {\n opacity: 0.4;\n cursor: default;\n}\n\n/* 阈值行(滑块 + 值) */\n.ss-threshold {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.ss-threshold input[type='range'] {\n width: 160px;\n}\n\n.ss-value {\n min-width: 40px;\n font-variant-numeric: tabular-nums;\n font-size: 13px;\n font-weight: 600;\n color: var(--dsw-alias-label-primary);\n text-align: right;\n}\n\n/* 底部帮助行 */\n.ss-hint {\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-tertiary);\n word-break: break-word;\n overflow-wrap: anywhere;\n}\n\n/* 降级提示 */\n.ss-degrade {\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-state-warn-label);\n word-break: break-word;\n overflow-wrap: anywhere;\n}\n";
1110
- if (typeof document !== "undefined" && document.querySelector("style[data-sp-css]") === null) {
1110
+ if (typeof document !== "undefined" && document.querySelector("style[data-sp-css=\"SettingsSection\"]") === null) {
1111
1111
  const tag = document.createElement("style");
1112
- tag.setAttribute("data-sp-css", "1");
1112
+ tag.setAttribute("data-sp-css", "SettingsSection");
1113
1113
  tag.textContent = css;
1114
1114
  document.head.appendChild(tag);
1115
1115
  }
package/lib/index.js CHANGED
@@ -5417,11 +5417,18 @@ function namingTitleFor(active) {
5417
5417
  }
5418
5418
  /**
5419
5419
  * use 激活宁静号会话后,把当前 dsh 会话重命名为命名标题(`S###-日期`)。
5420
- * 门控:naming.enabled + sessionTitle 服务存在;失败不静默——返回 null 且输出
5421
- * 失败原因(调用方 console.warn),保证可观测性(v1.22.9)。
5422
- * @returns { title, ok } 或 { ok:false, reason }(未执行/失败均返回对象,非 null 歧义)
5420
+ * 门控:naming.enabled + sessionTitle 服务存在;失败不静默——返回结果对象
5421
+ * 而非 null(v1.22.9),调用方决定可见性。
5422
+ *
5423
+ * v1.23.2 修复(this 绑定):第三参从**解构的裸 rename 函数**改为**整个
5424
+ * sessionTitle 服务对象**——内部以 `titles.rename(session, title)` **方法调用**
5425
+ * (this = titles 服务实例)。旧实现调用点 `const rename = titles.rename` 解构
5426
+ * 后传入,方法内部读 `this.assertServiceActive` → this=undefined 抛错
5427
+ * (日志实证:`Cannot read properties of undefined (reading 'assertServiceActive')`;
5428
+ * 与 v1.20.2/1.20.3 图片落盘同款解构丢 this bug)。
5429
+ * @returns { title, ok } 或 { ok:false, reason }(未执行/失败均返回对象)
5423
5430
  */
5424
- function renameDshSessionOnUse(deps, session, rename, active) {
5431
+ function renameDshSessionOnUse(deps, session, titles, active) {
5425
5432
  if (!deps.namingEnabled) return {
5426
5433
  ok: false,
5427
5434
  reason: "naming.enabled=false"
@@ -5430,9 +5437,13 @@ function renameDshSessionOnUse(deps, session, rename, active) {
5430
5437
  ok: false,
5431
5438
  reason: "sessionTitle service unavailable"
5432
5439
  };
5440
+ if (!titles || typeof titles.rename !== "function") return {
5441
+ ok: false,
5442
+ reason: "sessionTitle service unavailable"
5443
+ };
5433
5444
  const title = namingTitleFor(active);
5434
5445
  try {
5435
- rename(session, title);
5446
+ titles.rename(session, title);
5436
5447
  return {
5437
5448
  ok: true,
5438
5449
  title
@@ -5622,16 +5633,16 @@ function createSessionTool(ctx) {
5622
5633
  try {
5623
5634
  const info = getActiveSessionInfo(scope);
5624
5635
  if (info) {
5625
- const rename = (ctx.get?.("sessionTitle"))?.rename;
5636
+ const titles = ctx.get?.("sessionTitle");
5626
5637
  const dshSession = exec.agent?.session;
5627
- if (dshSession && typeof rename === "function") {
5638
+ if (dshSession) {
5628
5639
  const result = renameDshSessionOnUse({
5629
5640
  namingEnabled: readSimpleSettings().namingEnabled,
5630
5641
  sessionTitleAvailable: true
5631
- }, dshSession, rename, info);
5642
+ }, dshSession, titles, info);
5632
5643
  if (result.ok) console.log(`[serenity-hooks] dsh 会话已重命名: ${String(dshSession.id ?? "?")} → ${result.title}`);
5633
5644
  else console.warn(`[serenity-hooks] dsh 会话重命名未执行: ${result.reason}`);
5634
- } else console.warn(`[serenity-hooks] dsh 会话重命名未执行: sessionTitle 服务不可用或缺少 agent session`);
5645
+ } else console.warn(`[serenity-hooks] dsh 会话重命名未执行: 缺少 agent session`);
5635
5646
  }
5636
5647
  } catch (err) {
5637
5648
  console.warn(`[serenity-hooks] dsh 会话重命名异常: ${String(err?.message ?? err)}`);
@@ -6254,11 +6265,20 @@ var KeeperTracker = class {
6254
6265
  function reminderText(code, score) {
6255
6266
  return `[TRAJECTORY-STEWARD] Score threshold reached (${score}). Please acknowledge with [TRAJECTORY-STEWARD-recorded-${code}] once progress is synced to the working session (acc-session show). No need to interrupt your work — just acknowledge inline and keep going.`;
6256
6267
  }
6257
- /** F2 rebuild 提示(v1.21;v1.22.1 对齐"轨迹跟踪器"概念;v1.23.0 英化 + 载体关系):
6258
- * SESSION.md = trajectory 持久身体,自身会话 = 可重建载体(工作副本)。
6259
- * 上下文接近上限时引导 LLM 主动触发 session_rebuild。 */
6260
- function rebuildReminderText(ratio) {
6261
- return `[TRAJECTORY] Context usage at ${(ratio * 100).toFixed(0)}% (trajectory-tracker threshold). This session is the rebuildable carrier of the trajectory: SESSION.md is the persistent body, this conversation is only a temporary work copy — no compaction needed. Call session_rebuild at a natural pause to rebuild the carrier (this copy is discarded; identity continues from SESSION.md).`;
6268
+ /**
6269
+ * F2 rebuild 提示(v1.21;v1.22.1 对齐"轨迹跟踪器"概念;v1.23.0 英化 + 载体关系;
6270
+ * v1.23.3 行动指令化——用户反馈"一直在触发为啥没执行":旧文案是状态播报式
6271
+ * ("[TRAJECTORY] Context usage at N%..."),模型当成系统状态而非行动请求,可一直忽略。
6272
+ * 新文案 = 明确的行动指令(ACT NOW + 何时执行 + 必须执行),对齐 steward ACK 协议风格。
6273
+ *
6274
+ * escalated=true(v1.23.3):连续多轮超阈值仍未 rebuild → 升级强制语气
6275
+ * (STOP and rebuild now,持续注入直到调用 session_rebuild)。
6276
+ */
6277
+ function rebuildReminderText(ratio, threshold, escalated = false) {
6278
+ const pct = (ratio * 100).toFixed(0);
6279
+ const thr = (threshold * 100).toFixed(0);
6280
+ if (escalated) return `[TRAJECTORY-ESCALATED] Context usage at ${pct}% (threshold ${thr}%) — you have been reminded repeatedly and have NOT called session_rebuild. This is now mandatory: STOP at the current task step and call the session_rebuild tool immediately. The conversation will be cleared and rebuilt in place; SESSION.md is the persistent trajectory and stays in place — identity continues from it. Do not continue working without rebuilding; this reminder persists until you call session_rebuild.`;
6281
+ return `[TRAJECTORY] Context usage at ${pct}% (threshold ${thr}%). This session is the rebuildable carrier of the trajectory: SESSION.md is the persistent body, this conversation is only a temporary work copy. ACT NOW: at the next natural pause (end of the current task step), call the session_rebuild tool to clear and rebuild this conversation — the current copy is discarded, identity continues from SESSION.md. If you are in the middle of an unbreakable step, continue it, then rebuild at its end. Do not ignore this; rebuild is the expected action, not an option.`;
6262
6282
  }
6263
6283
  /** 读取会话 contextPressure 投影(sessionProjections 可选服务;未装配返回 null) */
6264
6284
  function readContextPressure(ctx, session) {
@@ -6281,6 +6301,9 @@ const PLUGIN_SOURCE$1 = {
6281
6301
  };
6282
6302
  /** 每 agent 一个跟踪器(进程内存态,agent token 维度) */
6283
6303
  const trackers = /* @__PURE__ */ new Map();
6304
+ /** 连续超阈值轮数达此值 → 升级为 [TRAJECTORY-ESCALATED] 强制语气(此后持续升级催,直到 rebuild) */
6305
+ const REBUILD_ESCALATE_AFTER = 3;
6306
+ const rebuildReminderStates = /* @__PURE__ */ new Map();
6284
6307
  function registerKeeper(ctx, opts = {}) {
6285
6308
  const defaultThreshold = opts.defaultThreshold ?? 150;
6286
6309
  const trackerFor = (exec) => {
@@ -6313,10 +6336,18 @@ function registerKeeper(ctx, opts = {}) {
6313
6336
  const pressure = readContextPressure(ctx, session);
6314
6337
  if (pressure && pressure.contextWindow && pressure.contextWindow > 0) {
6315
6338
  const ratio = pressure.projectedTokens / pressure.contextWindow;
6316
- if (ratio >= readSimpleSettings().rebuildThreshold) blocks.push({
6317
- type: "text",
6318
- text: rebuildReminderText(ratio)
6319
- });
6339
+ const threshold = readSimpleSettings().rebuildThreshold;
6340
+ if (ratio >= threshold) {
6341
+ const key = exec.agent?.session?.id ?? "global";
6342
+ const st = rebuildReminderStates.get(key) ?? { consecutive: 0 };
6343
+ st.consecutive += 1;
6344
+ const escalated = st.consecutive >= REBUILD_ESCALATE_AFTER;
6345
+ blocks.push({
6346
+ type: "text",
6347
+ text: rebuildReminderText(ratio, threshold, escalated)
6348
+ });
6349
+ rebuildReminderStates.set(key, st);
6350
+ }
6320
6351
  }
6321
6352
  }
6322
6353
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shgroup/dsh-serenity-hooks",
3
- "version": "1.23.1",
3
+ "version": "1.23.3",
4
4
  "description": "宁静号 ACC harness — Native Cordis 插件(DeepSeek Harness 运行时)。真实 DSH 工具注册(cc_fs/session/acc_msm 等 9 工具)+ 拦截缝机械约束(safe-mode/路径守卫/会话落盘)+ 系统提示词注入(ACC/CCE/Constraints/SKILL/Session 五块)。适配 DSH 公开版(deepseek-ai/deepseek-harness 0.1.0-rc)。",
5
5
  "license": "MIT",
6
6
  "repository": {