@shgroup/dsh-serenity-hooks 1.28.2 → 1.29.1

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.28.2",
3
+ "version": "1.29.1",
4
4
  "main": "lib/index.js",
5
5
  "description": "宁静号 ACC harness(Native Cordis 插件):真实 DSH 工具 cc_fs/session/acc_msm/eap/neat/cce/handyman/session_rebuild/skiff_admin + 拦截缝机械约束(safe-mode/路径守卫)+ 高级设定面板(双端口网关/账号管理)+ Skiff 认知子集角色(实验性)。适配 DSH 公开版(0.1.0-rc,deepseek-ai/deepseek-harness)。",
6
6
  "engines": {
package/lib/client.js CHANGED
@@ -4587,7 +4587,7 @@ Instruction-following style:
4587
4587
  }
4588
4588
  //#endregion
4589
4589
  //#region \0sp-css:/home/yh/home/home-serenity/AI_LAB/dsh-serenity-plugin/hooks/dsh-serenity-hooks/src/client/SettingsSection
4590
- 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;v1.27.5 紧凑化:默认单行截断,hover title 看全文) */\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 display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\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-border-l3);\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-foreground);\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-brand-primary);\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/* Skiff 调试端口输入(number;关闭时跟随 disabled 半透明) */\n.ss-portInput {\n width: 96px;\n padding: 6px 8px;\n border-radius: 8px;\n border: 1px solid var(--dsw-alias-border-l2);\n background: var(--dsw-alias-bg-layer-2);\n color: var(--dsw-alias-label-primary);\n font-size: 13px;\n font-variant-numeric: tabular-nums;\n text-align: right;\n}\n\n.ss-portInput:disabled {\n opacity: 0.4;\n cursor: default;\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/* 自主轨迹「立即唤起」按钮(v1.26.14 调试语义;官方 button 语言:primary 弱化) */\n.ss-wakeBtn {\n flex: none;\n padding: 5px 12px;\n border-radius: 8px;\n border: 1px solid var(--dsw-alias-border-l2);\n background: var(--dsw-alias-interactive-bg-active, rgba(128, 128, 128, 0.12));\n color: var(--dsw-alias-label-primary);\n font-size: 12px;\n line-height: 18px;\n font-weight: 500;\n cursor: pointer;\n transition: opacity var(--ds-transition-duration-fast, 0.15s) ease;\n}\n\n.ss-wakeBtn:hover:not(:disabled) {\n border-color: var(--dsw-alias-state-success-primary, #22c55e);\n color: var(--dsw-alias-state-success-primary, #22c55e);\n}\n\n.ss-wakeBtn:disabled {\n opacity: 0.4;\n cursor: default;\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\n/* ── v1.27.5 紧凑化:折叠组(details/summary)── */\n.ss-collapse {\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 12px;\n overflow: hidden;\n}\n\n.ss-collapseHead {\n display: flex;\n align-items: baseline;\n gap: 10px;\n padding: 10px 14px;\n cursor: pointer;\n list-style: none;\n user-select: none;\n}\n\n.ss-collapseHead::-webkit-details-marker {\n display: none;\n}\n\n.ss-collapseHead::before {\n content: '▸';\n flex: none;\n font-size: 11px;\n color: var(--dsw-alias-label-tertiary);\n transition: transform 0.15s ease;\n}\n\n.ss-collapse[open] > .ss-collapseHead::before {\n transform: rotate(90deg);\n}\n\n.ss-collapseHead:hover {\n background: var(--dsw-alias-interactive-bg-hover, rgba(128, 128, 128, 0.06));\n}\n\n.ss-collapseTitle {\n font-size: 13px;\n font-weight: 500;\n color: var(--dsw-alias-label-primary);\n}\n\n.ss-collapseDesc {\n font-size: 12px;\n color: var(--dsw-alias-label-tertiary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n min-width: 0;\n}\n\n.ss-collapseBody {\n padding: 10px 14px 14px;\n border-top: 1px solid var(--dsw-alias-border-l1);\n}\n\n/* ── v1.27.5 紧凑化:只读定义列表(dl/dt/dd 2 列网格)── */\n.ss-defList {\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 6px 20px;\n margin: 0;\n width: 100%;\n min-width: 0;\n}\n\n.ss-defItem {\n display: flex;\n flex-direction: column;\n gap: 1px;\n min-width: 0;\n}\n\n.ss-defTerm {\n font-size: 11px;\n line-height: 16px;\n font-weight: 500;\n letter-spacing: 0.02em;\n text-transform: uppercase;\n color: var(--dsw-alias-label-tertiary);\n}\n\n.ss-defValue {\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-primary);\n word-break: break-word;\n overflow-wrap: anywhere;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n\n/* ── v1.27.5 紧凑化:开关 + 端口内联行 ── */\n.ss-switchRow {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n/* ── v1.27.6 「?」帮助浮层(hover/焦点显示三行以上严谨说明)── */\n.ss-help {\n position: relative;\n display: inline-flex;\n align-items: center;\n margin-top: 2px;\n}\n\n.ss-helpMark {\n flex: none;\n width: 16px;\n height: 16px;\n padding: 0;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 50%;\n background: var(--dsw-alias-interactive-bg-active, rgba(128, 128, 128, 0.12));\n color: var(--dsw-alias-label-tertiary);\n font-size: 10px;\n line-height: 1;\n font-weight: 600;\n cursor: help;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n transition: border-color 0.15s ease, color 0.15s ease;\n}\n\n.ss-helpMark:hover,\n.ss-helpMark:focus-visible {\n border-color: var(--dsw-alias-state-success-primary, #22c55e);\n color: var(--dsw-alias-state-success-primary, #22c55e);\n outline: none;\n}\n\n.ss-helpTip {\n position: absolute;\n left: 0;\n top: calc(100% + 6px);\n z-index: 30;\n width: 300px;\n max-width: 60vw;\n padding: 10px 12px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 10px;\n background: var(--dsw-alias-bg-overlay);\n box-shadow: 0 6px 24px rgba(0, 0, 0, 0.28);\n font-size: 12px;\n line-height: 19px;\n font-weight: 400;\n color: var(--dsw-alias-label-primary);\n white-space: pre-line;\n word-break: break-word;\n opacity: 0;\n pointer-events: none;\n transform: translateY(-4px);\n transition: opacity 0.15s ease, transform 0.15s ease;\n}\n\n.ss-help:hover .ss-helpTip,\n.ss-helpMark:focus-visible + .ss-helpTip {\n opacity: 1;\n pointer-events: auto;\n transform: translateY(0);\n}\n\n/* 折叠组内帮助浮层定位修正(左侧行卡不会溢出面板) */\n.ss-rowCard .ss-helpTip {\n left: 0;\n}\n\n/* ── 微信桥(F4c-3,v1.27.0 实验性)── */\n\n/* CCC 选择器(下拉) */\n.ss-select {\n max-width: 280px;\n padding: 6px 8px;\n border-radius: 8px;\n border: 1px solid var(--dsw-alias-border-l2);\n background: var(--dsw-alias-bg-layer-2);\n color: var(--dsw-alias-label-primary);\n font-size: 13px;\n}\n\n/* 扫码绑定按钮(复用 wakeBtn 语言) */\n.ss-loginBtn {\n flex: none;\n padding: 5px 12px;\n border-radius: 8px;\n border: 1px solid var(--dsw-alias-border-l2);\n background: var(--dsw-alias-interactive-bg-active, rgba(128, 128, 128, 0.12));\n color: var(--dsw-alias-label-primary);\n font-size: 12px;\n line-height: 18px;\n font-weight: 500;\n cursor: pointer;\n transition: opacity var(--ds-transition-duration-fast, 0.15s) ease;\n}\n\n.ss-loginBtn:hover:not(:disabled) {\n border-color: var(--dsw-alias-state-success-primary, #22c55e);\n color: var(--dsw-alias-state-success-primary, #22c55e);\n}\n\n.ss-loginBtn:disabled {\n opacity: 0.4;\n cursor: default;\n}\n\n/* 移除账号按钮(危险语义:红边框) */\n.ss-removeBtn {\n flex: none;\n padding: 5px 12px;\n border-radius: 8px;\n border: 1px solid var(--dsw-alias-border-l2);\n background: var(--dsw-alias-interactive-bg-active, rgba(128, 128, 128, 0.12));\n color: var(--dsw-alias-label-primary);\n font-size: 12px;\n line-height: 18px;\n font-weight: 500;\n cursor: pointer;\n transition: opacity var(--ds-transition-duration-fast, 0.15s) ease;\n}\n\n.ss-removeBtn:hover:not(:disabled) {\n border-color: var(--dsw-alias-state-error-primary, #ef4444);\n color: var(--dsw-alias-state-error-primary, #ef4444);\n}\n\n/* 二维码展示行 */\n.ss-qrRow {\n align-items: center;\n}\n\n.ss-qrSvg {\n flex: none;\n width: 120px; /* v1.27.5 紧凑化:160 → 120 */\n height: 120px;\n border-radius: 8px;\n border: 1px solid var(--dsw-alias-border-l2);\n background: #fff; /* 二维码需要白底才能被微信扫出 */\n padding: 6px;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.ss-qrSvg svg {\n width: 100%;\n height: 100%;\n}\n\n/* 路由表 JSON 编辑框 */\n.ss-routesEditor {\n width: 100%;\n box-sizing: border-box;\n margin-top: 6px;\n padding: 8px 10px;\n border-radius: 8px;\n border: 1px solid var(--dsw-alias-border-l2);\n background: var(--dsw-alias-bg-layer-2);\n color: var(--dsw-alias-label-primary);\n font-size: 12px;\n line-height: 18px;\n font-family: var(--ds-font-family-code);\n resize: vertical;\n}\n";
4590
+ 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/* ── v1.29 需求②:可展开行(整行点击 → 行内详设)── */\n.ss-expandable {\n flex-wrap: wrap; /* detail 换行占满整行 */\n cursor: default;\n}\n.ss-expandable .ss-rowText {\n cursor: pointer;\n}\n.ss-expandable .ss-rowText:hover .ss-rowName {\n color: var(--dsw-alias-state-success-primary, #22c55e);\n}\n.ss-expanded {\n border-color: var(--dsw-alias-state-success-primary, #22c55e);\n}\n.ss-expandMark {\n display: inline-block;\n margin-left: 6px;\n font-size: 10px;\n color: var(--dsw-alias-label-tertiary);\n transition: transform 0.15s ease;\n}\n.ss-expanded .ss-expandMark {\n transform: rotate(90deg);\n}\n.ss-rowDetail {\n flex-basis: 100%;\n width: 100%;\n border-top: 1px solid var(--dsw-alias-border-l2);\n margin-top: 10px;\n padding-top: 12px;\n display: flex;\n flex-direction: column;\n gap: 10px;\n min-width: 0;\n}\n.ss-detailStack {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n.ss-detailIntro {\n margin: 0;\n font-size: 12px;\n line-height: 19px;\n color: var(--dsw-alias-label-secondary);\n white-space: pre-line;\n word-break: break-word;\n overflow-wrap: anywhere;\n padding: 8px 10px;\n border-radius: 8px;\n background: var(--dsw-alias-interactive-bg-active, rgba(128, 128, 128, 0.06));\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;v1.27.5 紧凑化:默认单行截断,hover title 看全文) */\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 display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\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-border-l3);\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-foreground);\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-brand-primary);\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/* Skiff 调试端口输入(number;关闭时跟随 disabled 半透明) */\n.ss-portInput {\n width: 96px;\n padding: 6px 8px;\n border-radius: 8px;\n border: 1px solid var(--dsw-alias-border-l2);\n background: var(--dsw-alias-bg-layer-2);\n color: var(--dsw-alias-label-primary);\n font-size: 13px;\n font-variant-numeric: tabular-nums;\n text-align: right;\n}\n\n.ss-portInput:disabled {\n opacity: 0.4;\n cursor: default;\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/* 自主轨迹「立即唤起」按钮(v1.26.14 调试语义;官方 button 语言:primary 弱化) */\n.ss-wakeBtn {\n flex: none;\n padding: 5px 12px;\n border-radius: 8px;\n border: 1px solid var(--dsw-alias-border-l2);\n background: var(--dsw-alias-interactive-bg-active, rgba(128, 128, 128, 0.12));\n color: var(--dsw-alias-label-primary);\n font-size: 12px;\n line-height: 18px;\n font-weight: 500;\n cursor: pointer;\n transition: opacity var(--ds-transition-duration-fast, 0.15s) ease;\n}\n\n.ss-wakeBtn:hover:not(:disabled) {\n border-color: var(--dsw-alias-state-success-primary, #22c55e);\n color: var(--dsw-alias-state-success-primary, #22c55e);\n}\n\n.ss-wakeBtn:disabled {\n opacity: 0.4;\n cursor: default;\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\n/* 错误提示(v1.29 会话清理等) */\n.ss-error {\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-state-error-primary, #ef4444);\n background: rgba(239, 68, 68, 0.08);\n border-radius: 8px;\n padding: 8px 10px;\n white-space: pre-line;\n word-break: break-word;\n}\n\n/* ── v1.27.5 紧凑化:折叠组(details/summary)── */\n.ss-collapse {\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 12px;\n overflow: hidden;\n}\n\n.ss-collapseHead {\n display: flex;\n align-items: baseline;\n gap: 10px;\n padding: 10px 14px;\n cursor: pointer;\n list-style: none;\n user-select: none;\n}\n\n.ss-collapseHead::-webkit-details-marker {\n display: none;\n}\n\n.ss-collapseHead::before {\n content: '▸';\n flex: none;\n font-size: 11px;\n color: var(--dsw-alias-label-tertiary);\n transition: transform 0.15s ease;\n}\n\n.ss-collapse[open] > .ss-collapseHead::before {\n transform: rotate(90deg);\n}\n\n.ss-collapseHead:hover {\n background: var(--dsw-alias-interactive-bg-hover, rgba(128, 128, 128, 0.06));\n}\n\n.ss-collapseTitle {\n font-size: 13px;\n font-weight: 500;\n color: var(--dsw-alias-label-primary);\n}\n\n.ss-collapseDesc {\n font-size: 12px;\n color: var(--dsw-alias-label-tertiary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n min-width: 0;\n}\n\n.ss-collapseBody {\n padding: 10px 14px 14px;\n border-top: 1px solid var(--dsw-alias-border-l1);\n}\n\n/* ── v1.27.5 紧凑化:只读定义列表(dl/dt/dd 2 列网格)── */\n.ss-defList {\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 6px 20px;\n margin: 0;\n width: 100%;\n min-width: 0;\n}\n\n.ss-defItem {\n display: flex;\n flex-direction: column;\n gap: 1px;\n min-width: 0;\n}\n\n.ss-defTerm {\n font-size: 11px;\n line-height: 16px;\n font-weight: 500;\n letter-spacing: 0.02em;\n text-transform: uppercase;\n color: var(--dsw-alias-label-tertiary);\n}\n\n.ss-defValue {\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-primary);\n word-break: break-word;\n overflow-wrap: anywhere;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n\n/* ── v1.27.5 紧凑化:开关 + 端口内联行 ── */\n.ss-switchRow {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n/* ── v1.27.6 「?」帮助浮层(hover/焦点显示三行以上严谨说明)── */\n.ss-help {\n position: relative;\n display: inline-flex;\n align-items: center;\n margin-top: 2px;\n}\n\n.ss-helpMark {\n flex: none;\n width: 16px;\n height: 16px;\n padding: 0;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 50%;\n background: var(--dsw-alias-interactive-bg-active, rgba(128, 128, 128, 0.12));\n color: var(--dsw-alias-label-tertiary);\n font-size: 10px;\n line-height: 1;\n font-weight: 600;\n cursor: help;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n transition: border-color 0.15s ease, color 0.15s ease;\n}\n\n.ss-helpMark:hover,\n.ss-helpMark:focus-visible {\n border-color: var(--dsw-alias-state-success-primary, #22c55e);\n color: var(--dsw-alias-state-success-primary, #22c55e);\n outline: none;\n}\n\n.ss-helpTip {\n position: absolute;\n left: 0;\n top: calc(100% + 6px);\n z-index: 30;\n width: 300px;\n max-width: 60vw;\n padding: 10px 12px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 10px;\n background: var(--dsw-alias-bg-overlay);\n box-shadow: 0 6px 24px rgba(0, 0, 0, 0.28);\n font-size: 12px;\n line-height: 19px;\n font-weight: 400;\n color: var(--dsw-alias-label-primary);\n white-space: pre-line;\n word-break: break-word;\n opacity: 0;\n pointer-events: none;\n transform: translateY(-4px);\n transition: opacity 0.15s ease, transform 0.15s ease;\n}\n\n.ss-help:hover .ss-helpTip,\n.ss-helpMark:focus-visible + .ss-helpTip {\n opacity: 1;\n pointer-events: auto;\n transform: translateY(0);\n}\n\n/* 折叠组内帮助浮层定位修正(左侧行卡不会溢出面板) */\n.ss-rowCard .ss-helpTip {\n left: 0;\n}\n\n/* ── 微信桥(F4c-3,v1.27.0 实验性)── */\n\n/* CCC 选择器(下拉) */\n.ss-select {\n max-width: 280px;\n padding: 6px 8px;\n border-radius: 8px;\n border: 1px solid var(--dsw-alias-border-l2);\n background: var(--dsw-alias-bg-layer-2);\n color: var(--dsw-alias-label-primary);\n font-size: 13px;\n}\n\n/* 扫码绑定按钮(复用 wakeBtn 语言) */\n.ss-loginBtn {\n flex: none;\n padding: 5px 12px;\n border-radius: 8px;\n border: 1px solid var(--dsw-alias-border-l2);\n background: var(--dsw-alias-interactive-bg-active, rgba(128, 128, 128, 0.12));\n color: var(--dsw-alias-label-primary);\n font-size: 12px;\n line-height: 18px;\n font-weight: 500;\n cursor: pointer;\n transition: opacity var(--ds-transition-duration-fast, 0.15s) ease;\n}\n\n.ss-loginBtn:hover:not(:disabled) {\n border-color: var(--dsw-alias-state-success-primary, #22c55e);\n color: var(--dsw-alias-state-success-primary, #22c55e);\n}\n\n.ss-loginBtn:disabled {\n opacity: 0.4;\n cursor: default;\n}\n\n/* 移除账号按钮(危险语义:红边框) */\n.ss-removeBtn {\n flex: none;\n padding: 5px 12px;\n border-radius: 8px;\n border: 1px solid var(--dsw-alias-border-l2);\n background: var(--dsw-alias-interactive-bg-active, rgba(128, 128, 128, 0.12));\n color: var(--dsw-alias-label-primary);\n font-size: 12px;\n line-height: 18px;\n font-weight: 500;\n cursor: pointer;\n transition: opacity var(--ds-transition-duration-fast, 0.15s) ease;\n}\n\n.ss-removeBtn:hover:not(:disabled) {\n border-color: var(--dsw-alias-state-error-primary, #ef4444);\n color: var(--dsw-alias-state-error-primary, #ef4444);\n}\n\n/* 二维码展示行 */\n.ss-qrRow {\n align-items: center;\n}\n\n.ss-qrSvg {\n flex: none;\n width: 120px; /* v1.27.5 紧凑化:160 → 120 */\n height: 120px;\n border-radius: 8px;\n border: 1px solid var(--dsw-alias-border-l2);\n background: #fff; /* 二维码需要白底才能被微信扫出 */\n padding: 6px;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.ss-qrSvg svg {\n width: 100%;\n height: 100%;\n}\n\n/* 路由表 JSON 编辑框 */\n.ss-routesEditor {\n width: 100%;\n box-sizing: border-box;\n margin-top: 6px;\n padding: 8px 10px;\n border-radius: 8px;\n border: 1px solid var(--dsw-alias-border-l2);\n background: var(--dsw-alias-bg-layer-2);\n color: var(--dsw-alias-label-primary);\n font-size: 12px;\n line-height: 18px;\n font-family: var(--ds-font-family-code);\n resize: vertical;\n}\n";
4591
4591
  if (typeof document !== "undefined" && document.querySelector("style[data-sp-css=\"SettingsSection\"]") === null) {
4592
4592
  const tag = document.createElement("style");
4593
4593
  tag.setAttribute("data-sp-css", "SettingsSection");
@@ -4612,39 +4612,70 @@ Instruction-following style:
4612
4612
  });
4613
4613
  }
4614
4614
  /** 一个配置行卡(官方 rowCard:标题+说明 左列 / 控件右置)
4615
- * help:可选——desc 下方渲染「?」帮助浮层(hover/焦点显示三行以上严谨说明) */
4615
+ * help:可选——desc 下方渲染「?」帮助浮层(hover/焦点显示三行以上严谨说明)
4616
+ * expandable:可选——整行点击展开 detail 内联详设(需求②:开关与详设合一)。
4617
+ * 点击行(标题/desc 区)toggle 展开态;detail 渲染在行内下方(含 help 内容 +
4618
+ * 该功能全部配置项/重型编辑器)。展开时行头右置 ▾ 指示。 */
4616
4619
  function RowCard(props) {
4617
- const { title, desc, control, help } = props;
4620
+ const { title, desc, control, help, expandable, detail } = props;
4621
+ const isControlled = props.open !== void 0;
4622
+ const [selfOpen, setSelfOpen] = (0, react.useState)(false);
4623
+ const open = isControlled ? !!props.open : selfOpen;
4624
+ const toggle = () => {
4625
+ if (!expandable) return;
4626
+ if (isControlled) props.onToggle?.(!open);
4627
+ else setSelfOpen(!open);
4628
+ };
4618
4629
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4619
- className: "ss-rowCard",
4620
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4621
- className: "ss-rowText",
4622
- children: [
4623
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4624
- className: "ss-rowName",
4625
- children: title
4626
- }),
4627
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4628
- className: "ss-rowDesc",
4629
- children: desc
4630
- }),
4631
- help && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
4632
- className: "ss-help",
4633
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
4634
- type: "button",
4635
- className: "ss-helpMark",
4636
- "aria-label": `${title} 帮助`,
4637
- children: "?"
4638
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4639
- className: "ss-helpTip",
4640
- children: help
4641
- })]
4642
- })
4643
- ]
4644
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4645
- className: "ss-rowControl",
4646
- children: control
4647
- })]
4630
+ className: `ss-rowCard${expandable ? " ss-expandable" : ""}${expandable && open ? " ss-expanded" : ""}`,
4631
+ children: [
4632
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4633
+ className: "ss-rowText",
4634
+ role: expandable ? "button" : void 0,
4635
+ tabIndex: expandable ? 0 : void 0,
4636
+ onClick: toggle,
4637
+ onKeyDown: (e) => {
4638
+ if (expandable && (e.key === "Enter" || e.key === " ")) {
4639
+ e.preventDefault();
4640
+ toggle();
4641
+ }
4642
+ },
4643
+ children: [
4644
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
4645
+ className: "ss-rowName",
4646
+ children: [title, expandable && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4647
+ className: "ss-expandMark",
4648
+ "aria-hidden": true,
4649
+ children: open ? "▾" : "▸"
4650
+ })]
4651
+ }),
4652
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4653
+ className: "ss-rowDesc",
4654
+ children: desc
4655
+ }),
4656
+ help && !expandable && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
4657
+ className: "ss-help",
4658
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
4659
+ type: "button",
4660
+ className: "ss-helpMark",
4661
+ "aria-label": `${title} 帮助`,
4662
+ children: "?"
4663
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4664
+ className: "ss-helpTip",
4665
+ children: help
4666
+ })]
4667
+ })
4668
+ ]
4669
+ }),
4670
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4671
+ className: "ss-rowControl",
4672
+ children: control
4673
+ }),
4674
+ expandable && open && detail !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4675
+ className: "ss-rowDetail",
4676
+ children: detail
4677
+ })
4678
+ ]
4648
4679
  });
4649
4680
  }
4650
4681
  /** 分组(多级标题:分组标题 + 一组行卡) */
@@ -4736,6 +4767,12 @@ Instruction-following style:
4736
4767
  const acpPort = value?.acpHttpPort ?? 3100;
4737
4768
  const publicAskOn = value?.publicAskEnabled ?? false;
4738
4769
  const autopilotOn = value?.autopilotEnabled ?? false;
4770
+ const [openGateway, setOpenGateway] = (0, react.useState)(false);
4771
+ const [openRebuild, setOpenRebuild] = (0, react.useState)(false);
4772
+ const [openSkiff, setOpenSkiff] = (0, react.useState)(false);
4773
+ const [openAcp, setOpenAcp] = (0, react.useState)(false);
4774
+ const [openPublicAsk, setOpenPublicAsk] = (0, react.useState)(false);
4775
+ const [openAutopilot, setOpenAutopilot] = (0, react.useState)(false);
4739
4776
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4740
4777
  className: "ss-section",
4741
4778
  children: [
@@ -4745,46 +4782,66 @@ Instruction-following style:
4745
4782
  }),
4746
4783
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
4747
4784
  className: "ss-intro",
4748
- children: "宁静号的 plugin 级配置(全局生效,不依赖具体 CCC)。改动即时保存。"
4785
+ children: "宁静号的 plugin 级配置(全局生效,不依赖具体 CCC)。点击任一行展开该功能的详细设定;改动即时保存。"
4749
4786
  }),
4750
4787
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Group, {
4751
4788
  title: "访问",
4752
4789
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RowCard, {
4753
4790
  title: "双端口网关",
4754
4791
  desc: "额外监听端口 3081,登录后可从外部访问 Web UI",
4755
- help: "双端口网关(端口 3081)让外网/局域网用户经登录页访问本 DSH Web UI:\n· 适用范围:跨网络访问(本机默认端口 3080 仅监听本机)\n· 安全:登录账号 + 可选 TOTP 第二因素(见「外部访问」)\n· 工作区白名单:登录后仅白名单内工作区可见(可留空=全部)\n· 变更立即生效(热重建,无需重启)",
4792
+ expandable: true,
4793
+ open: openGateway,
4794
+ onToggle: setOpenGateway,
4795
+ expandHint: "配置",
4756
4796
  control: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Toggle, {
4757
4797
  checked: gatewayOn,
4758
4798
  onChange: (on) => toggle("gatewayEnabled", on)
4799
+ }),
4800
+ detail: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4801
+ className: "ss-detailStack",
4802
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
4803
+ className: "ss-detailIntro",
4804
+ children: "双端口网关(端口 3081)让外网/局域网用户经登录页访问本 DSH Web UI:\n· 适用范围:跨网络访问(本机默认端口 3080 仅监听本机)\n· 安全:登录账号 + 可选 TOTP 第二因素\n· 工作区白名单:登录后仅白名单内工作区可见(可留空=全部)\n· 变更立即生效(热重建,无需重启)"
4805
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AccountsEditor, { gatewayOn })]
4759
4806
  })
4760
4807
  }) })
4761
4808
  }),
4762
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Group, {
4809
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Group, {
4763
4810
  title: "上下文",
4764
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RowCard, {
4811
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RowCard, {
4765
4812
  title: "超限重建",
4766
4813
  desc: "上下文接近上限时提示调用 session_rebuild 清空重建",
4767
- help: "上下文超限自动重建(session_rebuild):\n· 机制:agent 上下文占用达到阈值时,由 LLM 主动调用重建工具\n· 语义:完全丢弃当前 dsh 会话 + 自动新建 + 注入「继续原 SESSION 的工作」\n· 效果:SESSION.md 原位不动,认知轨迹延续,上下文归零\n· 关闭后:上下文超限时不再提示,可能导致会话卡顿或丢失",
4814
+ expandable: true,
4815
+ open: openRebuild,
4816
+ onToggle: setOpenRebuild,
4817
+ expandHint: "配置",
4768
4818
  control: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Toggle, {
4769
4819
  checked: rebuildOn,
4770
4820
  onChange: (on) => toggle("rebuildEnabled", on)
4821
+ }),
4822
+ detail: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4823
+ className: "ss-detailStack",
4824
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
4825
+ className: "ss-detailIntro",
4826
+ children: "上下文超限自动重建(session_rebuild):\n· 机制:agent 上下文占用达到阈值时,由 LLM 主动调用重建工具\n· 语义:完全丢弃当前 dsh 会话 + 自动新建 + 注入「继续原 SESSION 的工作」\n· 效果:SESSION.md 原位不动,认知轨迹延续,上下文归零\n· 关闭后:上下文超限时不再提示,可能导致会话卡顿或丢失"
4827
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RowCard, {
4828
+ title: "重建阈值",
4829
+ desc: "上下文占用达到该 K 数值时提示(单位 K token,默认 400)",
4830
+ help: "重建触发阈值(需求①:K 数值,默认 400K,范围 50~4000K):\n· 含义:上下文 projected tokens 达到 thresholdK × 1000 时触发提醒\n· 纯绝对数值(不再依赖窗口比例)\n· 迁移:旧版 0~1 比例(settings.yaml rebuildThreshold)已废弃被忽略\n· 调低更早触发 / 调高更晚触发;仅「超限重建」开启时有意义",
4831
+ control: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
4832
+ className: "ss-portInput",
4833
+ type: "number",
4834
+ min: 50,
4835
+ max: 4e3,
4836
+ step: 50,
4837
+ value: thresholdK,
4838
+ disabled: !rebuildOn,
4839
+ title: "重建阈值(K token,默认 400)",
4840
+ onChange: (e) => setThreshold(Number(e.target.value))
4841
+ })
4842
+ })]
4771
4843
  })
4772
- }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RowCard, {
4773
- title: "重建阈值",
4774
- desc: "上下文占用达到该 K 数值时提示(单位 K token,默认 400)",
4775
- help: "重建触发阈值(需求①:K 数值,默认 400K,范围 50~4000K):\n· 含义:上下文 projected tokens 达到 thresholdK × 1000 时,轨迹跟踪器开始提醒重建\n· 纯绝对数值(不再依赖窗口比例)——配多大就多大,无窗口上限保护\n· 迁移:旧版 0~1 比例(settings.yaml rebuildThreshold,如 0.9)已废弃并被忽略——\n 请按 K 数值在此重设(如 0.9 → 900);若从未设置则默认 400K 生效\n· 调低:更早触发(适合长任务,避免上下文耗尽前措手不及)\n· 调高:更晚触发(适合短对话,减少不必要的重建提示)\n· 仅「超限重建」开启时有意义",
4776
- control: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
4777
- className: "ss-portInput",
4778
- type: "number",
4779
- min: 50,
4780
- max: 4e3,
4781
- step: 50,
4782
- value: thresholdK,
4783
- disabled: !rebuildOn,
4784
- title: "重建阈值(K token,默认 400)",
4785
- onChange: (e) => setThreshold(Number(e.target.value))
4786
- })
4787
- }) })]
4844
+ }) })
4788
4845
  }),
4789
4846
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Group, {
4790
4847
  title: "外部能力",
@@ -4792,7 +4849,9 @@ Instruction-following style:
4792
4849
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RowCard, {
4793
4850
  title: "Skiff 调试",
4794
4851
  desc: "Skiff 认知子集问答页(端口 3099,实验性,127.0.0.1)",
4795
- help: "Skiff 认知子集角色调试服务(端口 3099):\n· 概念:Skiff = 完整宁静号 trajectory 的任意子集(认知子集角色)\n· 服务:角色问答页(调试用),仅监听 127.0.0.1(本地)\n· 使用:配置 CCC 的 skiff.roles 角色后,可经此页以角色身份问答\n· 实验性:人工启停,默认关闭;对外问答请用「Skiff 问答页」",
4852
+ expandable: true,
4853
+ open: openSkiff,
4854
+ onToggle: setOpenSkiff,
4796
4855
  control: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
4797
4856
  className: "ss-switchRow",
4798
4857
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Toggle, {
@@ -4808,12 +4867,18 @@ Instruction-following style:
4808
4867
  title: "Skiff 调试端口(默认 3099)",
4809
4868
  onChange: (e) => setSkiffPort(Number(e.target.value))
4810
4869
  })]
4870
+ }),
4871
+ detail: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
4872
+ className: "ss-detailIntro",
4873
+ children: "Skiff 认知子集角色调试服务(端口 3099):\n· 概念:Skiff = 完整宁静号 trajectory 的任意子集(认知子集角色)\n· 服务:角色问答页(调试用),仅监听 127.0.0.1(本地)\n· 使用:配置 CCC 的 skiff.roles 角色后,可经此页以角色身份问答\n· 实验性:人工启停,默认关闭;对外问答请用「Skiff 问答页」"
4811
4874
  })
4812
4875
  }) }),
4813
4876
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RowCard, {
4814
4877
  title: "ACP JSON-RPC",
4815
4878
  desc: "程序化调用 Skiff 角色(端口 3100,实验性,127.0.0.1)",
4816
- help: "ACP(Agent Client Protocol)HTTP JSON-RPC 端点(端口 3100):\n· 作用:程序化调用 Skiff 角色(指定 CCC + 角色 + 会话)\n· 形态:HTTP JSON-RPC 服务,仅监听 127.0.0.1(本地)\n· 场景:IM 桥(如微信桥)、脚本、自动化接线\n· 实验性:人工启停,默认关闭;与「Skiff 问答页」共用端口",
4879
+ expandable: true,
4880
+ open: openAcp,
4881
+ onToggle: setOpenAcp,
4817
4882
  control: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
4818
4883
  className: "ss-switchRow",
4819
4884
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Toggle, {
@@ -4829,60 +4894,199 @@ Instruction-following style:
4829
4894
  title: "ACP + Skiff 问答共用端口(默认 3100)",
4830
4895
  onChange: (e) => setAcpPort(Number(e.target.value))
4831
4896
  })]
4897
+ }),
4898
+ detail: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
4899
+ className: "ss-detailIntro",
4900
+ children: "ACP(Agent Client Protocol)HTTP JSON-RPC 端点(端口 3100):\n· 作用:程序化调用 Skiff 角色(指定 CCC + 角色 + 会话)\n· 形态:HTTP JSON-RPC 服务,仅监听 127.0.0.1(本地)\n· 场景:IM 桥(如微信桥)、脚本、自动化接线\n· 实验性:人工启停,默认关闭;与「Skiff 问答页」共用端口"
4832
4901
  })
4833
4902
  }) }),
4834
4903
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RowCard, {
4835
4904
  title: "Skiff 问答页",
4836
4905
  desc: "按认知容器暴露问答页(端口 3100,需 key)",
4837
- help: "Skiff 问答页(对外问答,端口 3100,key 认证):\n· 作用:让外部用户在浏览器中与指定 CCC 的 Skiff 角色对话\n· 认证:访问 key(首次开启自动生成,见 ~/.dsh/serenity-hooks.json)\n· 授权:开放容器白名单(未选 = 全部开放;见「Skiff 问答页配置」)\n· 外部接入:需经部署方自选方案暴露(隧道/反代/端口映射)\n· 安全:key 可轮换(旧 key 立即失效)",
4906
+ expandable: true,
4907
+ open: openPublicAsk,
4908
+ onToggle: setOpenPublicAsk,
4838
4909
  control: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Toggle, {
4839
4910
  checked: publicAskOn,
4840
4911
  onChange: (on) => toggle("publicAskEnabled", on)
4912
+ }),
4913
+ detail: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4914
+ className: "ss-detailStack",
4915
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
4916
+ className: "ss-detailIntro",
4917
+ children: "Skiff 问答页(对外问答,端口 3100,key 认证):\n· 作用:让外部用户在浏览器中与指定 CCC 的 Skiff 角色对话\n· 认证:访问 key(首次开启自动生成)\n· 授权:开放容器白名单(未选 = 全部开放)\n· 外部接入:需经部署方自选方案暴露(隧道/反代/端口映射)\n· 安全:key 可轮换(旧 key 立即失效)"
4918
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PublicAskEditor, { publicAskOn })]
4841
4919
  })
4842
4920
  }) }),
4843
4921
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RowCard, {
4844
4922
  title: "Autopilot Trajectory",
4845
4923
  desc: "自动巡航轨迹(全局开关,默认关——只在指定电脑开启)",
4846
- help: "Autopilot Trajectory 全局总开关(v1.27.9):\n· 作用:控制本机(本 dsh 实例)是否运行自动巡航轨迹\n· 默认关:未开启即使 CCC 配置 enabled=true 也不启动定时器\n· 定位:多台电脑装 dsp 时,只在指定电脑开启(其余默认关)\n· 双重门控:全局开关 AND CCC 级 enabled 都满足才运行\n· CCC 级配置(interval/session/偏见脚本/焦点)不受影响",
4924
+ expandable: true,
4925
+ open: openAutopilot,
4926
+ onToggle: setOpenAutopilot,
4847
4927
  control: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Toggle, {
4848
4928
  checked: autopilotOn,
4849
4929
  onChange: (on) => toggle("autopilotEnabled", on)
4930
+ }),
4931
+ detail: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4932
+ className: "ss-detailStack",
4933
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
4934
+ className: "ss-detailIntro",
4935
+ children: "Autopilot Trajectory 全局总开关(v1.27.9):\n· 作用:控制本机(本 dsh 实例)是否运行自动巡航轨迹\n· 默认关:未开启即使 CCC 配置 enabled=true 也不启动定时器\n· 定位:多台电脑装 dsp 时,只在指定电脑开启(其余默认关)\n· 双重门控:全局开关 AND CCC 级 enabled 都满足才运行\n· CCC 级配置(interval/session/偏见脚本/焦点)不受影响"
4936
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AutopilotTrajectoryStatusBlock, { autopilotOn })]
4850
4937
  })
4851
4938
  }) })
4852
4939
  ]
4853
4940
  }),
4854
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Collapse, {
4855
- title: "Skiff 问答页配置",
4856
- desc: "开放容器白名单 · 访问 key 与地址",
4857
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PublicAskEditor, { publicAskOn })
4858
- }),
4859
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Collapse, {
4860
- title: "外部访问",
4861
- desc: "网关监听(端口 3081)· 登录账号 · 工作区白名单(plugin 全局)",
4862
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AccountsEditor, { gatewayOn })
4863
- }),
4864
4941
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Collapse, {
4865
4942
  title: "彩蛋模式",
4866
4943
  desc: "persona 输出风格(默认关闭)",
4867
4944
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PersonaEditor, {})
4868
4945
  }),
4869
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Collapse, {
4870
- title: "Autopilot Trajectory",
4871
- desc: autopilotOn ? "全局已开启" : "全局关闭(外部能力组开启)",
4872
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AutopilotTrajectoryStatusBlock, {})
4873
- }),
4874
4946
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Collapse, {
4875
4947
  title: "微信桥",
4876
- desc: "扫码绑定微信账号 · 路由到 skiff 角色",
4948
+ desc: "扫码绑定微信账号 · 路由到 skiff 角色(CCC 级配置)",
4877
4949
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(WeixinBridgeEditor, {})
4950
+ }),
4951
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Collapse, {
4952
+ title: "会话清理",
4953
+ desc: "删除指定天数前无活动的 DSH 会话(手动,物理删不可恢复)",
4954
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SessionCleanupBlock, {})
4955
+ })
4956
+ ]
4957
+ });
4958
+ }
4959
+ /** 「会话清理」块(v1.29 需求③,S142 用户拍板:lastActive + 手动按钮 + 直接物理删):
4960
+ * 天数输入 → GET 预览(dryRun 列表)→ 确认 → POST 执行。live 会话由服务端保护跳过。 */
4961
+ function SessionCleanupBlock() {
4962
+ const [days, setDays] = (0, react.useState)(30);
4963
+ const [preview, setPreview] = (0, react.useState)(null);
4964
+ const [done, setDone] = (0, react.useState)(null);
4965
+ const [busy, setBusy] = (0, react.useState)(false);
4966
+ const [confirming, setConfirming] = (0, react.useState)(false);
4967
+ const [error, setError] = (0, react.useState)(null);
4968
+ const previewNow = async () => {
4969
+ setBusy(true);
4970
+ setError(null);
4971
+ setDone(null);
4972
+ try {
4973
+ const res = await fetch(`/serenity/session-cleanup?olderThanDays=${days}`, { headers: {
4974
+ accept: "application/json",
4975
+ "x-serenity-ui": "1"
4976
+ } });
4977
+ if (!res.ok) {
4978
+ const body = await res.json().catch(() => null);
4979
+ setError(body?.error ?? `HTTP ${res.status}`);
4980
+ return;
4981
+ }
4982
+ setPreview(await res.json());
4983
+ setConfirming(false);
4984
+ } catch (err) {
4985
+ setError(err instanceof Error ? err.message : String(err));
4986
+ } finally {
4987
+ setBusy(false);
4988
+ }
4989
+ };
4990
+ const execute = async () => {
4991
+ if (!confirming) {
4992
+ setConfirming(true);
4993
+ return;
4994
+ }
4995
+ setBusy(true);
4996
+ setError(null);
4997
+ try {
4998
+ const res = await fetch(`/serenity/session-cleanup?olderThanDays=${days}`, {
4999
+ method: "POST",
5000
+ headers: {
5001
+ accept: "application/json",
5002
+ "x-serenity-ui": "1"
5003
+ }
5004
+ });
5005
+ if (!res.ok) {
5006
+ const body = await res.json().catch(() => null);
5007
+ setError(body?.error ?? `HTTP ${res.status}`);
5008
+ return;
5009
+ }
5010
+ setDone(await res.json());
5011
+ setPreview(null);
5012
+ setConfirming(false);
5013
+ } catch (err) {
5014
+ setError(err instanceof Error ? err.message : String(err));
5015
+ } finally {
5016
+ setBusy(false);
5017
+ }
5018
+ };
5019
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5020
+ className: "ss-detailStack",
5021
+ children: [
5022
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RowCard, {
5023
+ title: "删除前无活动天数",
5024
+ desc: "删除最后活动早于该天数的 DSH 会话(默认 30)",
5025
+ help: "会话清理阈值(v1.29,S142 用户拍板 lastActive 基准):\n· 含义:删除「最后活动早于 N 天前」的 DSH 平台会话(对话历史)\n· lastActive = 会话日志文件最后写入时间(日志只追加,mtime 可靠)\n· live 保护:正在运行的会话绝不删除(服务端强制跳过)\n· 物理删不可恢复——先「预览」确认列表再执行",
5026
+ control: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
5027
+ className: "ss-portInput",
5028
+ type: "number",
5029
+ min: 1,
5030
+ max: 3650,
5031
+ step: 1,
5032
+ value: days,
5033
+ title: "删除前无活动天数(默认 30)",
5034
+ onChange: (e) => {
5035
+ setDays(Math.min(3650, Math.max(1, Math.round(Number(e.target.value) || 30))));
5036
+ setPreview(null);
5037
+ setDone(null);
5038
+ setConfirming(false);
5039
+ }
5040
+ })
5041
+ }),
5042
+ error && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
5043
+ className: "ss-error",
5044
+ children: error
5045
+ }),
5046
+ preview && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
5047
+ className: "ss-detailIntro",
5048
+ children: preview.count === 0 ? `无早于 ${preview.olderThanDays} 天前无活动的会话可清理(root: ${preview.root})` : `将删除 ${preview.count} 个会话(root: ${preview.root}):\n` + preview.candidates.map((c) => ` · ${c.id}(${c.project},最后活动 ${new Date(c.lastActive).toLocaleDateString()})`).join("\n")
5049
+ }),
5050
+ done && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
5051
+ className: "ss-detailIntro",
5052
+ children: `已删除 ${done.deleted.length} 个会话${done.errors.length > 0 ? `;${done.errors.length} 个失败(${done.errors.map((e) => `${e.id}: ${e.reason}`).join("; ")})` : ""}`
5053
+ }),
5054
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5055
+ className: "ss-switchRow",
5056
+ children: [
5057
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
5058
+ type: "button",
5059
+ className: "ss-wakeBtn",
5060
+ disabled: busy,
5061
+ onClick: () => void previewNow(),
5062
+ children: busy ? "处理中…" : preview ? "刷新预览" : "预览将删会话"
5063
+ }),
5064
+ preview && preview.count > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
5065
+ type: "button",
5066
+ className: "ss-removeBtn",
5067
+ disabled: busy,
5068
+ onClick: () => void execute(),
5069
+ children: confirming ? "确认物理删除(不可恢复)" : "执行删除"
5070
+ }),
5071
+ done && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
5072
+ type: "button",
5073
+ className: "ss-wakeBtn",
5074
+ onClick: () => {
5075
+ setPreview(null);
5076
+ setDone(null);
5077
+ },
5078
+ children: "完成"
5079
+ })
5080
+ ]
4878
5081
  })
4879
5082
  ]
4880
5083
  });
4881
5084
  }
4882
5085
  /** 「Autopilot Trajectory」只读状态区块(v1.26.14;v1.27.4 多 CCC:显式 CCC 选择器——
4883
5086
  * GET/POST 带 ?ccc=/body.ccc——用户"两个 CCC 都设定了,但手工唤起只能唤起一个"修复):
4884
- * 展示所选 CCC 的状态(配置摘要 + 目标会话 + 窗口/可唤起判定 + 审计);配置改走 CCC 配置文件 */
4885
- function AutopilotTrajectoryStatusBlock() {
5087
+ * 展示所选 CCC 的状态(配置摘要 + 目标会话 + 窗口/可唤起判定 + 审计);配置改走 CCC 配置文件
5088
+ * v1.29:autopilotOn prop(需求②——原折叠块并入开关行 detail,全局门控状态由外部行显示) */
5089
+ function AutopilotTrajectoryStatusBlock(props) {
4886
5090
  const [cccs, setCccs] = (0, react.useState)([]);
4887
5091
  const [selectedRoot, setSelectedRoot] = (0, react.useState)("");
4888
5092
  const [status, setStatus] = (0, react.useState)(null);
@@ -4967,7 +5171,8 @@ Instruction-following style:
4967
5171
  }) })
4968
5172
  });
4969
5173
  const target = status.target;
4970
- const stateText = !status.configured ? "未配置(机制未开始)" : !status.enabled ? "已配置,未启用(enabled=false,零资源占用)" : "已启用 — 时钟唤起等待中";
5174
+ const { autopilotOn } = props;
5175
+ const stateText = !props.autopilotOn ? "全局开关关闭(在「外部能力」组开启后才运行)" : !status.configured ? "未配置(机制未开始)" : !status.enabled ? "已配置,未启用(enabled=false,零资源占用)" : "已启用 — 时钟唤起等待中";
4971
5176
  const targetText = target ? `${target.dirName}${target.autoFlag ? "(--auto ✓)" : "(无 --auto 标志)"} · 空闲 ${target.idleHours.toFixed(1)}h / 阈值 ${status.intervalHours}h` : status.session ? `会话 ${status.session} 未命中(AGENT_SESSIONS 无匹配)` : "未配置目标会话(不唤起)";
4972
5177
  const wakeReady = status.enabled && !!target && target.autoFlag;
4973
5178
  const lastWake = status.recentWakes[0];