@shgroup/dsh-serenity-hooks 1.27.2 → 1.27.4

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
@@ -3263,7 +3263,7 @@ window.__ModuleLoader__.load({
3263
3263
  }
3264
3264
  //#endregion
3265
3265
  //#region \0sp-css:/home/yh/home/home-serenity/AI_LAB/dsh-serenity-plugin/hooks/dsh-serenity-hooks/src/client/AccountsEditor
3266
- 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/* v1.24.6:TOTP 绑定二维码(扫码即录入;scalable SVG,白底保证扫码识别) */\n.ae-totpQr {\n flex-basis: 100%;\n display: inline-flex;\n justify-content: center;\n padding: 8px;\n background: #fff;\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 8px;\n}\n\n.ae-totpQr svg {\n width: 132px;\n height: 132px;\n display: block;\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/* v1.24.7:绑定提示(去确认码后——扫码或手动录入,保存即绑定) */\n.ae-totpHint {\n flex-basis: 100%;\n font-size: 11px;\n color: var(--dsw-alias-label-tertiary);\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\n/* ── v1.26.2 建议问答页配置(PublicAskEditor:开放容器白名单 chips + key/地址展示)── */\n\n.ae-chips {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n margin: 8px 0 4px;\n}\n\n.ae-chip {\n padding: 4px 12px;\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 999px;\n background: transparent;\n color: var(--dsw-alias-text-primary);\n font-size: 12px;\n cursor: pointer;\n transition: background 0.15s ease, border-color 0.15s ease;\n}\n\n.ae-chip:hover {\n border-color: var(--dsw-alias-accent, #0ba875);\n}\n\n.ae-chipOn {\n background: var(--dsw-alias-accent, #0ba875);\n border-color: var(--dsw-alias-accent, #0ba875);\n color: #fff;\n}\n\n.ae-saved {\n margin-left: 10px;\n font-size: 12px;\n color: var(--dsw-alias-state-success-fg, #4ade80);\n}\n\n.ae-err {\n margin-left: 10px;\n font-size: 12px;\n color: var(--dsw-alias-state-danger-fg, #f87171);\n}\n\n.ae-key {\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n font-size: 12px;\n padding: 2px 8px;\n border-radius: 6px;\n background: var(--dsw-alias-bg-l2);\n color: var(--dsw-alias-text-primary);\n word-break: break-all;\n user-select: all;\n}\n\n.ae-copy {\n flex: none;\n margin-left: 8px;\n padding: 3px 10px;\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 6px;\n background: transparent;\n color: var(--dsw-alias-text-primary);\n font-size: 12px;\n cursor: pointer;\n}\n\n.ae-copy:hover {\n border-color: var(--dsw-alias-accent, #0ba875);\n color: var(--dsw-alias-accent, #0ba875);\n}\n\n/* v1.26.5 轮换 key(警示色:旧 key 立即失效) */\n.ae-rotate {\n color: var(--dsw-alias-state-danger-fg, #f87171);\n border-color: rgba(248, 113, 113, 0.35);\n}\n\n.ae-rotate:hover {\n border-color: var(--dsw-alias-state-danger-fg, #f87171);\n color: var(--dsw-alias-state-danger-fg, #f87171);\n}\n\n.ae-rotate:disabled {\n opacity: 0.6;\n cursor: wait;\n}\n\n.ae-rows {\n display: flex;\n flex-direction: column;\n gap: 6px;\n margin-top: 8px;\n}\n\n.ae-labelDim {\n opacity: 0.65;\n min-width: 96px;\n}\n";
3266
+ 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: 10px;\n padding: 12px 14px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 12px;\n font-size: 13px;\n}\n\n/* ── v1.27.5 紧凑化:折叠块(details/summary)── */\n.ae-collapse {\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 8px;\n overflow: hidden;\n}\n\n.ae-collapseHead {\n display: flex;\n align-items: baseline;\n gap: 8px;\n padding: 8px 12px;\n cursor: pointer;\n list-style: none;\n user-select: none;\n}\n\n.ae-collapseHead::-webkit-details-marker {\n display: none;\n}\n\n.ae-collapseHead::before {\n content: '▸';\n flex: none;\n font-size: 11px;\n color: var(--dsw-alias-label-dimmed);\n transition: transform 0.15s ease;\n}\n\n.ae-collapse[open] > .ae-collapseHead::before {\n transform: rotate(90deg);\n}\n\n.ae-collapseHead:hover {\n background: var(--dsw-alias-interactive-bg-hover, rgba(128, 128, 128, 0.06));\n}\n\n.ae-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.ae-collapseBody {\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding: 8px 12px 10px;\n border-top: 1px solid var(--dsw-alias-border-l1);\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/* v1.24.6:TOTP 绑定二维码(扫码即录入;scalable SVG,白底保证扫码识别) */\n.ae-totpQr {\n flex-basis: 100%;\n display: inline-flex;\n justify-content: center;\n padding: 8px;\n background: #fff;\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 8px;\n}\n\n.ae-totpQr svg {\n width: 132px;\n height: 132px;\n display: block;\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/* v1.24.7:绑定提示(去确认码后——扫码或手动录入,保存即绑定) */\n.ae-totpHint {\n flex-basis: 100%;\n font-size: 11px;\n color: var(--dsw-alias-label-tertiary);\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\n/* ── v1.26.2 建议问答页配置(PublicAskEditor:开放容器白名单 chips + key/地址展示)── */\n\n.ae-chips {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n margin: 8px 0 4px;\n}\n\n.ae-chip {\n padding: 4px 12px;\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 999px;\n background: transparent;\n color: var(--dsw-alias-text-primary);\n font-size: 12px;\n cursor: pointer;\n transition: background 0.15s ease, border-color 0.15s ease;\n}\n\n.ae-chip:hover {\n border-color: var(--dsw-alias-accent, #0ba875);\n}\n\n.ae-chipOn {\n background: var(--dsw-alias-accent, #0ba875);\n border-color: var(--dsw-alias-accent, #0ba875);\n color: #fff;\n}\n\n.ae-saved {\n margin-left: 10px;\n font-size: 12px;\n color: var(--dsw-alias-state-success-fg, #4ade80);\n}\n\n.ae-err {\n margin-left: 10px;\n font-size: 12px;\n color: var(--dsw-alias-state-danger-fg, #f87171);\n}\n\n.ae-key {\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n font-size: 12px;\n padding: 2px 8px;\n border-radius: 6px;\n background: var(--dsw-alias-bg-l2);\n color: var(--dsw-alias-text-primary);\n word-break: break-all;\n user-select: all;\n}\n\n.ae-copy {\n flex: none;\n margin-left: 8px;\n padding: 3px 10px;\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 6px;\n background: transparent;\n color: var(--dsw-alias-text-primary);\n font-size: 12px;\n cursor: pointer;\n}\n\n.ae-copy:hover {\n border-color: var(--dsw-alias-accent, #0ba875);\n color: var(--dsw-alias-accent, #0ba875);\n}\n\n/* v1.26.5 轮换 key(警示色:旧 key 立即失效) */\n.ae-rotate {\n color: var(--dsw-alias-state-danger-fg, #f87171);\n border-color: rgba(248, 113, 113, 0.35);\n}\n\n.ae-rotate:hover {\n border-color: var(--dsw-alias-state-danger-fg, #f87171);\n color: var(--dsw-alias-state-danger-fg, #f87171);\n}\n\n.ae-rotate:disabled {\n opacity: 0.6;\n cursor: wait;\n}\n\n.ae-rows {\n display: flex;\n flex-direction: column;\n gap: 6px;\n margin-top: 8px;\n}\n\n.ae-labelDim {\n opacity: 0.65;\n min-width: 96px;\n}\n";
3267
3267
  if (typeof document !== "undefined" && document.querySelector("style[data-sp-css=\"AccountsEditor\"]") === null) {
3268
3268
  const tag = document.createElement("style");
3269
3269
  tag.setAttribute("data-sp-css", "AccountsEditor");
@@ -3412,14 +3412,20 @@ window.__ModuleLoader__.load({
3412
3412
  className: "ae-warn",
3413
3413
  children: "⚠️ 双端口网关当前关闭——先开启上方「双端口网关」开关,外部访问才生效。"
3414
3414
  }),
3415
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3416
- className: "ae-block",
3417
- children: [
3418
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h4", {
3415
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", {
3416
+ className: "ae-collapse",
3417
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("summary", {
3418
+ className: "ae-collapseHead",
3419
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3419
3420
  className: "ae-title",
3420
3421
  children: "监听设置"
3421
- }),
3422
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3422
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3423
+ className: "ae-collapseDesc",
3424
+ children: "地址 · 端口 · Secure Cookie"
3425
+ })]
3426
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3427
+ className: "ae-collapseBody",
3428
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3423
3429
  className: "ae-row",
3424
3430
  children: [
3425
3431
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
@@ -3445,41 +3451,45 @@ window.__ModuleLoader__.load({
3445
3451
  onChange: (e) => setPort(Number(e.target.value) || 0)
3446
3452
  })
3447
3453
  ]
3448
- }),
3449
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
3454
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
3450
3455
  className: "ae-check",
3451
3456
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
3452
3457
  type: "checkbox",
3453
3458
  checked: cookieSecure,
3454
3459
  onChange: (e) => setCookieSecure(e.target.checked)
3455
3460
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "Secure Cookie(仅 HTTPS 反代时开启;明文 HTTP 下关闭,否则登录态不生效)" })]
3456
- })
3457
- ]
3461
+ })]
3462
+ })]
3458
3463
  }),
3459
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3460
- className: "ae-block",
3461
- children: [
3462
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h4", {
3464
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", {
3465
+ className: "ae-collapse",
3466
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("summary", {
3467
+ className: "ae-collapseHead",
3468
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3463
3469
  className: "ae-title",
3464
3470
  children: "外部能力"
3465
- }),
3466
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
3471
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3472
+ className: "ae-collapseDesc",
3473
+ children: "允许新建工作区 · Authenticator 登录"
3474
+ })]
3475
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3476
+ className: "ae-collapseBody",
3477
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
3467
3478
  className: "ae-check",
3468
3479
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
3469
3480
  type: "checkbox",
3470
3481
  checked: allowWorkspaceCreate,
3471
3482
  onChange: (e) => setAllowWorkspaceCreate(e.target.checked)
3472
3483
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "允许外部新建工作区(关闭后经外部网关的 workspace.create 一律拒绝;仅使用已有工作区)" })]
3473
- }),
3474
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
3484
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
3475
3485
  className: "ae-check",
3476
3486
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
3477
3487
  type: "checkbox",
3478
3488
  checked: totpEnabled,
3479
3489
  onChange: (e) => setTotpEnabled(e.target.checked)
3480
3490
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "启用 Authenticator 登录(v1.24.6 二选一:开启后绑定验证器的账号可用密码 或 6 位验证码任一登录;关闭时 TOTP 完全禁用,仅密码)" })]
3481
- })
3482
- ]
3491
+ })]
3492
+ })]
3483
3493
  }),
3484
3494
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3485
3495
  className: "ae-block",
@@ -3592,55 +3602,63 @@ window.__ModuleLoader__.load({
3592
3602
  ]
3593
3603
  })]
3594
3604
  }),
3595
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3596
- className: "ae-block",
3597
- children: [
3598
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h4", {
3605
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", {
3606
+ className: "ae-collapse",
3607
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("summary", {
3608
+ className: "ae-collapseHead",
3609
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3599
3610
  className: "ae-title",
3600
3611
  children: "工作区白名单"
3601
- }),
3602
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
3603
- className: "ae-desc",
3604
- children: "允许外部访问的已有工作区;未选择 = 全部允许。登录后仅白名单内的工作区可见/可用。"
3605
- }),
3606
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3607
- className: "ae-wsList",
3608
- children: workspaces.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
3612
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3613
+ className: "ae-collapseDesc",
3614
+ children: "未选择 = 全部允许"
3615
+ })]
3616
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3617
+ className: "ae-collapseBody",
3618
+ children: [
3619
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
3620
+ className: "ae-desc",
3621
+ children: "允许外部访问的已有工作区;未选择 = 全部允许。登录后仅白名单内的工作区可见/可用。"
3622
+ }),
3623
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3624
+ className: "ae-wsList",
3625
+ children: workspaces.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
3626
+ className: "ae-note",
3627
+ children: "(全部允许)"
3628
+ }) : workspaces.map((w) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
3629
+ className: "ae-wsChip",
3630
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", {
3631
+ className: "ae-wsPath",
3632
+ children: w
3633
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3634
+ type: "button",
3635
+ className: "ae-wsDel",
3636
+ onClick: () => removeWorkspace(w),
3637
+ "aria-label": `移除 ${w}`,
3638
+ children: "×"
3639
+ })]
3640
+ }, w))
3641
+ }),
3642
+ knownWorkspaces.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
3609
3643
  className: "ae-note",
3610
- children: "(全部允许)"
3611
- }) : workspaces.map((w) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
3612
- className: "ae-wsChip",
3613
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", {
3614
- className: "ae-wsPath",
3615
- children: w
3616
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3617
- type: "button",
3618
- className: "ae-wsDel",
3619
- onClick: () => removeWorkspace(w),
3620
- "aria-label": `移除 ${w}`,
3621
- children: "×"
3622
- })]
3623
- }, w))
3624
- }),
3625
- knownWorkspaces.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
3626
- className: "ae-note",
3627
- children: "暂无可选工作区(workspace.list 未返回条目)"
3628
- }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
3629
- className: "ae-input ae-wsSelect",
3630
- value: "",
3631
- onChange: (e) => {
3632
- if (e.target.value !== "") toggleWorkspace(e.target.value);
3633
- },
3634
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
3644
+ children: "暂无可选工作区(workspace.list 未返回条目)"
3645
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
3646
+ className: "ae-input ae-wsSelect",
3635
3647
  value: "",
3636
- disabled: true,
3637
- children: "选择已有工作区…"
3638
- }), knownWorkspaces.map((w) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
3639
- value: w.path,
3640
- children: w.title
3641
- }, w.path))]
3642
- })
3643
- ]
3648
+ onChange: (e) => {
3649
+ if (e.target.value !== "") toggleWorkspace(e.target.value);
3650
+ },
3651
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
3652
+ value: "",
3653
+ disabled: true,
3654
+ children: "选择已有工作区…"
3655
+ }), knownWorkspaces.map((w) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
3656
+ value: w.path,
3657
+ children: w.title
3658
+ }, w.path))]
3659
+ })
3660
+ ]
3661
+ })]
3644
3662
  }),
3645
3663
  error !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
3646
3664
  className: "ae-error",
@@ -3661,7 +3679,7 @@ window.__ModuleLoader__.load({
3661
3679
  }
3662
3680
  //#endregion
3663
3681
  //#region \0sp-css:/home/yh/home/home-serenity/AI_LAB/dsh-serenity-plugin/hooks/dsh-serenity-hooks/src/client/PersonaEditor
3664
- 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";
3682
+ 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: 72px; /* v1.27.5 紧凑化:默认 4 行(原 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";
3665
3683
  if (typeof document !== "undefined" && document.querySelector("style[data-sp-css=\"PersonaEditor\"]") === null) {
3666
3684
  const tag = document.createElement("style");
3667
3685
  tag.setAttribute("data-sp-css", "PersonaEditor");
@@ -4363,7 +4381,7 @@ Instruction-following style:
4363
4381
  children: "目标 CCC"
4364
4382
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4365
4383
  className: "ss-rowDesc",
4366
- children: "选择要配置微信桥的认知容器(显式,非当前活跃会话)"
4384
+ children: "选择要配置微信桥的认知容器"
4367
4385
  })]
4368
4386
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4369
4387
  className: "ss-rowControl",
@@ -4399,12 +4417,16 @@ Instruction-following style:
4399
4417
  className: "ss-rowCard",
4400
4418
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4401
4419
  className: "ss-rowText",
4402
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4420
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
4403
4421
  className: "ss-rowName",
4404
- children: "总开关"
4422
+ children: [
4423
+ "总开关 · 账号(",
4424
+ status.accounts.length,
4425
+ ")"
4426
+ ]
4405
4427
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4406
4428
  className: "ss-rowDesc",
4407
- children: "启用后该 CCC 的微信桥开始轮询(需先扫码绑定至少一个账号)"
4429
+ children: status.accounts.length === 0 ? "未绑定账号——下方扫码绑定" : status.accounts.map((a) => `${a.accountId}${a.name ? `·${a.name}` : ""}${a.bound ? "✓" : "✗"}`).join(" ")
4408
4430
  })]
4409
4431
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4410
4432
  className: "ss-rowControl",
@@ -4418,23 +4440,6 @@ Instruction-following style:
4418
4440
  })
4419
4441
  })]
4420
4442
  }) }),
4421
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4422
- className: "ss-rowCard",
4423
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4424
- className: "ss-rowText",
4425
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
4426
- className: "ss-rowName",
4427
- children: [
4428
- "账号(",
4429
- status.accounts.length,
4430
- ")"
4431
- ]
4432
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4433
- className: "ss-rowDesc",
4434
- children: status.accounts.length === 0 ? "未绑定任何微信账号——点击下方「扫码绑定微信」逐个添加" : "每个账号独立轮询;可继续扫码添加更多"
4435
- })]
4436
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "ss-rowControl" })]
4437
- }) }),
4438
4443
  status.accounts.map((a) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4439
4444
  className: "ss-rowCard",
4440
4445
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -4471,8 +4476,8 @@ Instruction-following style:
4471
4476
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
4472
4477
  className: "ss-rowDesc",
4473
4478
  children: [
4474
- loginPhase === "idle" && "用手机微信「扫一扫」扫描二维码并确认——每扫一次绑定一个新账号",
4475
- loginPhase === "waiting" && "二维码已生成(5 分钟内有效)——微信扫一扫手机上确认绑定",
4479
+ loginPhase === "idle" && "微信「扫一扫」确认——每扫一次绑定一个新账号",
4480
+ loginPhase === "waiting" && "二维码已生成(5 分钟有效)——微信扫一扫手机确认",
4476
4481
  loginPhase === "confirmed" && (loginNotice ?? "绑定成功"),
4477
4482
  loginPhase === "error" && (loginError ?? "绑定失败"),
4478
4483
  loginPhase === "expired" && "二维码已过期,请重新获取"
@@ -4498,7 +4503,7 @@ Instruction-following style:
4498
4503
  className: "ss-rowText",
4499
4504
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4500
4505
  className: "ss-rowDesc",
4501
- children: "1. 打开手机微信 扫一扫 2. 扫描此二维码 3. 在手机上确认绑定"
4506
+ children: "微信扫一扫手机上确认绑定"
4502
4507
  })
4503
4508
  })]
4504
4509
  }) }),
@@ -4511,7 +4516,7 @@ Instruction-following style:
4511
4516
  children: "路由表"
4512
4517
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4513
4518
  className: "ss-rowDesc",
4514
- children: "微信用户 → 该 CCC 的 skiff 角色(`*` = 通配兜底;role 必须已定义)"
4519
+ children: "微信用户 → skiff 角色(`*` 通配兜底)"
4515
4520
  })]
4516
4521
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4517
4522
  className: "ss-rowControl",
@@ -4524,7 +4529,7 @@ Instruction-following style:
4524
4529
  })]
4525
4530
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
4526
4531
  className: "ss-routesEditor",
4527
- rows: 5,
4532
+ rows: 3,
4528
4533
  value: routesDraft,
4529
4534
  onChange: (e) => setRoutesDraft(e.target.value)
4530
4535
  })] })
@@ -4547,7 +4552,7 @@ Instruction-following style:
4547
4552
  }
4548
4553
  //#endregion
4549
4554
  //#region \0sp-css:/home/yh/home/home-serenity/AI_LAB/dsh-serenity-plugin/hooks/dsh-serenity-hooks/src/client/SettingsSection
4550
- 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/* 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-fill-l1, rgba(128, 128, 128, 0.08));\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/* ── 微信桥(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-fill-l1, rgba(128, 128, 128, 0.08));\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: flex-start;\n}\n\n.ss-qrSvg {\n flex: none;\n width: 160px;\n height: 160px;\n border-radius: 8px;\n border: 1px solid var(--dsw-alias-border-l2);\n background: #fff; /* 二维码需要白底才能被微信扫出 */\n padding: 8px;\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-fill-l1, rgba(128, 128, 128, 0.08));\n color: var(--dsw-alias-label-primary);\n font-size: 12px;\n line-height: 18px;\n font-family: var(--ds-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);\n resize: vertical;\n}\n";
4555
+ 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-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/* 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-fill-l1, rgba(128, 128, 128, 0.08));\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/* ── 微信桥(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-fill-l1, rgba(128, 128, 128, 0.08));\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-fill-l1, rgba(128, 128, 128, 0.08));\n color: var(--dsw-alias-label-primary);\n font-size: 12px;\n line-height: 18px;\n font-family: var(--ds-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);\n resize: vertical;\n}\n";
4551
4556
  if (typeof document !== "undefined" && document.querySelector("style[data-sp-css=\"SettingsSection\"]") === null) {
4552
4557
  const tag = document.createElement("style");
4553
4558
  tag.setAttribute("data-sp-css", "SettingsSection");
@@ -4605,6 +4610,44 @@ Instruction-following style:
4605
4610
  })]
4606
4611
  });
4607
4612
  }
4613
+ /** 折叠组(details/summary:默认收起,点开展开——v1.27.5 紧凑化) */
4614
+ function Collapse(props) {
4615
+ const { title, desc, open, children } = props;
4616
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", {
4617
+ className: "ss-collapse",
4618
+ open,
4619
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("summary", {
4620
+ className: "ss-collapseHead",
4621
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4622
+ className: "ss-collapseTitle",
4623
+ children: title
4624
+ }), desc && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4625
+ className: "ss-collapseDesc",
4626
+ children: desc
4627
+ })]
4628
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4629
+ className: "ss-collapseBody",
4630
+ children
4631
+ })]
4632
+ });
4633
+ }
4634
+ /** 只读定义列表(dl/dt/dd 网格——v1.27.5 紧凑化:只读状态不再各占一行卡) */
4635
+ function DefList(props) {
4636
+ const { items } = props;
4637
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("dl", {
4638
+ className: "ss-defList",
4639
+ children: items.map((it) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4640
+ className: "ss-defItem",
4641
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dt", {
4642
+ className: "ss-defTerm",
4643
+ children: it.term
4644
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("dd", {
4645
+ className: "ss-defValue",
4646
+ children: it.value
4647
+ })]
4648
+ }, it.term))
4649
+ });
4650
+ }
4608
4651
  /** dsh 原生设置面板:serenity-hooks 配置页(官方 settings 设计语言,多级标题) */
4609
4652
  function SettingsSection(props) {
4610
4653
  const { scope } = props;
@@ -4693,95 +4736,79 @@ Instruction-following style:
4693
4736
  }) })]
4694
4737
  }),
4695
4738
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Group, {
4696
- title: "Skiff",
4697
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RowCard, {
4698
- title: "认知子集调试服务",
4699
- desc: "Skiff 角色问答页(实验性;启停人工控制,仅监听 127.0.0.1)",
4700
- control: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Toggle, {
4701
- checked: skiffOn,
4702
- onChange: (on) => toggle("skiffEnabled", on)
4703
- })
4704
- }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RowCard, {
4705
- title: "调试端口",
4706
- desc: "Skiff 问答页端口(1024 ~ 65535,默认 3099)",
4707
- control: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4708
- className: "ss-threshold",
4709
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
4710
- className: "ss-portInput",
4711
- type: "number",
4712
- min: 1024,
4713
- max: 65535,
4714
- value: skiffPort,
4715
- disabled: !skiffOn,
4716
- onChange: (e) => setSkiffPort(Number(e.target.value))
4717
- })
4718
- })
4719
- }) })]
4720
- }),
4721
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Group, {
4722
- title: "ACP / 建议问答",
4739
+ title: "外部能力",
4723
4740
  children: [
4724
4741
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RowCard, {
4725
- title: "ACP JSON-RPC 端点",
4726
- desc: "程序化调用 Skiff 角色(指定 CCC+角色+会话;实验性,仅监听 127.0.0.1)",
4727
- control: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Toggle, {
4728
- checked: acpOn,
4729
- onChange: (on) => toggle("acpEnabled", on)
4730
- })
4731
- }) }),
4732
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RowCard, {
4733
- title: "建议问答页",
4734
- desc: "按认知容器暴露问答页供他人验证(需 key;首次开启自动生成固定 key,见 ~/.dsh/serenity-hooks.json)",
4735
- control: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Toggle, {
4736
- checked: publicAskOn,
4737
- onChange: (on) => toggle("publicAskEnabled", on)
4742
+ title: "Skiff 调试",
4743
+ desc: "Skiff 认知子集问答页(实验性,127.0.0.1)",
4744
+ control: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
4745
+ className: "ss-switchRow",
4746
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Toggle, {
4747
+ checked: skiffOn,
4748
+ onChange: (on) => toggle("skiffEnabled", on)
4749
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
4750
+ className: "ss-portInput",
4751
+ type: "number",
4752
+ min: 1024,
4753
+ max: 65535,
4754
+ value: skiffPort,
4755
+ disabled: !skiffOn,
4756
+ title: "Skiff 调试端口(默认 3099)",
4757
+ onChange: (e) => setSkiffPort(Number(e.target.value))
4758
+ })]
4738
4759
  })
4739
4760
  }) }),
4740
4761
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RowCard, {
4741
- title: "HTTP 端口",
4742
- desc: "ACP JSON-RPC + 问答页共用端口(1024 ~ 65535,默认 3100)",
4743
- control: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4744
- className: "ss-threshold",
4745
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
4762
+ title: "ACP JSON-RPC",
4763
+ desc: "程序化调用 Skiff 角色(实验性,127.0.0.1)",
4764
+ control: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
4765
+ className: "ss-switchRow",
4766
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Toggle, {
4767
+ checked: acpOn,
4768
+ onChange: (on) => toggle("acpEnabled", on)
4769
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
4746
4770
  className: "ss-portInput",
4747
4771
  type: "number",
4748
4772
  min: 1024,
4749
4773
  max: 65535,
4750
4774
  value: acpPort,
4751
4775
  disabled: !acpOn && !publicAskOn,
4776
+ title: "ACP + 建议问答共用端口(默认 3100)",
4752
4777
  onChange: (e) => setAcpPort(Number(e.target.value))
4753
- })
4778
+ })]
4779
+ })
4780
+ }) }),
4781
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RowCard, {
4782
+ title: "建议问答页",
4783
+ desc: "按认知容器暴露问答页(需 key;首次开启自动生成,见 ~/.dsh/serenity-hooks.json)",
4784
+ control: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Toggle, {
4785
+ checked: publicAskOn,
4786
+ onChange: (on) => toggle("publicAskEnabled", on)
4754
4787
  })
4755
4788
  }) })
4756
4789
  ]
4757
4790
  }),
4758
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4759
- className: "ss-group",
4760
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
4761
- className: "ss-groupTitle",
4762
- children: "建议问答"
4763
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PublicAskEditor, { publicAskOn })]
4791
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Collapse, {
4792
+ title: "建议问答配置",
4793
+ desc: "开放容器白名单 · 访问 key 与地址",
4794
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PublicAskEditor, { publicAskOn })
4764
4795
  }),
4765
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4766
- className: "ss-group",
4767
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
4768
- className: "ss-groupTitle",
4769
- children: "外部访问"
4770
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AccountsEditor, { gatewayOn })]
4796
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Collapse, {
4797
+ title: "外部访问",
4798
+ desc: "监听 · 登录账号 · 工作区白名单(plugin 全局)",
4799
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AccountsEditor, { gatewayOn })
4771
4800
  }),
4772
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4773
- className: "ss-group",
4774
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
4775
- className: "ss-groupTitle",
4776
- children: "彩蛋模式"
4777
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PersonaEditor, {})]
4801
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Collapse, {
4802
+ title: "彩蛋模式",
4803
+ desc: "persona 输出风格(默认关闭)",
4804
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PersonaEditor, {})
4778
4805
  }),
4779
4806
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4780
4807
  className: "ss-group",
4781
4808
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
4782
4809
  className: "ss-groupTitle",
4783
- children: "自主轨迹"
4784
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AutoTrajectoryStatusBlock, {})]
4810
+ children: "Autopilot Trajectory"
4811
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AutopilotTrajectoryStatusBlock, {})]
4785
4812
  }),
4786
4813
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4787
4814
  className: "ss-group",
@@ -4793,15 +4820,37 @@ Instruction-following style:
4793
4820
  ]
4794
4821
  });
4795
4822
  }
4796
- /** 「自主轨迹」只读状态区块(v1.26.14):展示当前工作区 CCC 的实验状态;实验配置改走 CCC 配置文件 */
4797
- function AutoTrajectoryStatusBlock() {
4823
+ /** 「Autopilot Trajectory」只读状态区块(v1.26.14;v1.27.4 CCC:显式 CCC 选择器——
4824
+ * GET/POST ?ccc=/body.ccc——用户"两个 CCC 都设定了,但手工唤起只能唤起一个"修复):
4825
+ * 展示所选 CCC 的状态(配置摘要 + 目标会话 + 窗口/预算/可唤起判定 + 审计);配置改走 CCC 配置文件 */
4826
+ function AutopilotTrajectoryStatusBlock() {
4827
+ const [cccs, setCccs] = (0, react.useState)([]);
4828
+ const [selectedRoot, setSelectedRoot] = (0, react.useState)("");
4798
4829
  const [status, setStatus] = (0, react.useState)(null);
4799
4830
  const [unavailable, setUnavailable] = (0, react.useState)(false);
4800
4831
  const [waking, setWaking] = (0, react.useState)(false);
4801
4832
  const [wakeResult, setWakeResult] = (0, react.useState)(null);
4833
+ (0, react.useEffect)(() => {
4834
+ let alive = true;
4835
+ (async () => {
4836
+ try {
4837
+ const res = await fetch("/serenity/cccs", { headers: { accept: "application/json" } });
4838
+ if (!res.ok) return;
4839
+ const body = await res.json();
4840
+ if (!alive || !Array.isArray(body.cccs)) return;
4841
+ setCccs(body.cccs);
4842
+ if (body.cccs.length > 0) setSelectedRoot((prev) => prev || body.cccs[0].root);
4843
+ else setUnavailable(true);
4844
+ } catch {}
4845
+ })();
4846
+ return () => {
4847
+ alive = false;
4848
+ };
4849
+ }, []);
4802
4850
  const refresh = (0, react.useCallback)(async () => {
4851
+ if (!selectedRoot) return;
4803
4852
  try {
4804
- const res = await fetch("/serenity/autotrajectory", { headers: { accept: "application/json" } });
4853
+ const res = await fetch(`/serenity/autopilot-trajectory?ccc=${encodeURIComponent(selectedRoot)}`, { headers: { accept: "application/json" } });
4805
4854
  if (!res.ok) return;
4806
4855
  const body = await res.json();
4807
4856
  if (body.status) {
@@ -4812,23 +4861,26 @@ Instruction-following style:
4812
4861
  setUnavailable(true);
4813
4862
  }
4814
4863
  } catch {}
4815
- }, []);
4864
+ }, [selectedRoot]);
4816
4865
  (0, react.useEffect)(() => {
4817
4866
  refresh();
4818
4867
  return () => {};
4819
4868
  }, [refresh]);
4820
4869
  const wakeNow = async () => {
4821
- if (waking) return;
4870
+ if (waking || !selectedRoot) return;
4822
4871
  setWaking(true);
4823
4872
  setWakeResult(null);
4824
4873
  try {
4825
- const res = await fetch("/serenity/autotrajectory", {
4874
+ const res = await fetch("/serenity/autopilot-trajectory", {
4826
4875
  method: "POST",
4827
4876
  headers: {
4828
4877
  "content-type": "application/json",
4829
4878
  "x-serenity-ui": "1"
4830
4879
  },
4831
- body: JSON.stringify({ action: "wake" })
4880
+ body: JSON.stringify({
4881
+ action: "wake",
4882
+ ccc: selectedRoot
4883
+ })
4832
4884
  });
4833
4885
  const body = await res.json();
4834
4886
  setWakeResult(body.detail ?? body.error ?? `HTTP ${res.status}`);
@@ -4839,11 +4891,11 @@ Instruction-following style:
4839
4891
  setWaking(false);
4840
4892
  }
4841
4893
  };
4842
- if (unavailable) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
4894
+ if (unavailable && cccs.length === 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
4843
4895
  className: "ss-rows",
4844
4896
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RowCard, {
4845
4897
  title: "未激活",
4846
- desc: "当前工作区不在 CCC 内(无 .serenity)——先在工作区打开一个 CCC 会话",
4898
+ desc: "未发现候选 CCC(/serenity/cccs 为空)——先在工作区打开一个 CCC 会话",
4847
4899
  control: null
4848
4900
  }) })
4849
4901
  });
@@ -4851,51 +4903,77 @@ Instruction-following style:
4851
4903
  className: "ss-rows",
4852
4904
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RowCard, {
4853
4905
  title: "加载中…",
4854
- desc: "读取自主轨迹实验状态",
4906
+ desc: "读取 Autopilot Trajectory 状态",
4855
4907
  control: null
4856
4908
  }) })
4857
4909
  });
4858
4910
  const target = status.target;
4859
- const stateText = !status.configured ? "未配置(实验未开始)" : !status.enabled ? "已配置,未启用(enabled=false,零资源占用)" : "已启用 — 时钟唤起等待中";
4911
+ const stateText = !status.configured ? "未配置(机制未开始)" : !status.enabled ? "已配置,未启用(enabled=false,零资源占用)" : "已启用 — 时钟唤起等待中";
4860
4912
  const targetText = target ? `${target.dirName}${target.autoFlag ? "(--auto ✓)" : "(无 --auto 标志)"} · 空闲 ${target.idleHours.toFixed(1)}h / 阈值 ${status.intervalHours}h` : status.session ? `会话 ${status.session} 未命中(AGENT_SESSIONS 无匹配)` : "未配置目标会话(不唤起)";
4861
4913
  const wakeReady = status.enabled && !!target && target.autoFlag;
4914
+ const lastWake = status.recentWakes[0];
4862
4915
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("ul", {
4863
4916
  className: "ss-rows",
4864
4917
  children: [
4865
4918
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RowCard, {
4866
- title: "实验状态",
4919
+ title: "目标 CCC",
4920
+ desc: "多 CCC 各自独立——选中哪个就查看/唤起哪个",
4921
+ control: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
4922
+ className: "ss-select",
4923
+ value: selectedRoot,
4924
+ onChange: (e) => {
4925
+ setSelectedRoot(e.target.value);
4926
+ setStatus(null);
4927
+ },
4928
+ children: [cccs.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
4929
+ value: "",
4930
+ children: "加载中…"
4931
+ }), cccs.map((c) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
4932
+ value: c.root,
4933
+ children: c.name || c.root
4934
+ }, c.root))]
4935
+ })
4936
+ }) }),
4937
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RowCard, {
4938
+ title: "运行状态",
4867
4939
  desc: stateText,
4868
4940
  control: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4869
4941
  className: "ss-value",
4870
4942
  children: status.enabled ? "● 运行中" : status.configured ? "○ 待启" : "—"
4871
4943
  })
4872
4944
  }) }),
4873
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RowCard, {
4874
- title: "目标会话",
4875
- desc: targetText,
4876
- control: target?.wakeable ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4877
- className: "ss-value",
4878
- children: "可唤起"
4879
- }) : null
4880
- }) }),
4881
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RowCard, {
4882
- title: "唤起窗口",
4883
- desc: `当前北京 ${status.beijingHour} 点 — ${status.windowAllowed ? "允许唤起" : `高峰避开中(${status.avoidWakeHours.start}~${status.avoidWakeHours.end})`}`,
4884
- control: null
4885
- }) }),
4886
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RowCard, {
4887
- title: "偏见提供者",
4888
- desc: status.biasProvider,
4889
- control: null
4890
- }) }),
4891
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RowCard, {
4892
- title: "轨迹焦点 (topPrompt)",
4893
- desc: status.topPrompt ? status.topPrompt : "未定义——CCC 定义 autotrajectory 时应填写本轨迹核心焦点(防多轮唤起焦点丢失)",
4894
- control: null
4945
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4946
+ className: "ss-rowCard",
4947
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DefList, { items: [
4948
+ {
4949
+ term: "目标会话",
4950
+ value: targetText
4951
+ },
4952
+ {
4953
+ term: "唤起窗口",
4954
+ value: `北京 ${status.beijingHour} 点 — ${status.windowAllowed ? "允许" : `避开 ${status.avoidWakeHours.start}~${status.avoidWakeHours.end}`}`
4955
+ },
4956
+ {
4957
+ term: "每日预算",
4958
+ value: `${status.maxDailyWakes} 次/日`
4959
+ },
4960
+ {
4961
+ term: "偏见提供者",
4962
+ value: status.biasProvider
4963
+ },
4964
+ {
4965
+ term: "轨迹焦点",
4966
+ value: status.topPrompt ?? "未定义(CCC 应填写,防焦点丢失)"
4967
+ },
4968
+ {
4969
+ term: "最近唤起",
4970
+ value: lastWake ? `${new Date(lastWake.time).toLocaleString()} — ${lastWake.ok ? "✓" : "✗"} ${lastWake.detail}` : "尚无"
4971
+ }
4972
+ ] })
4895
4973
  }) }),
4896
4974
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RowCard, {
4897
4975
  title: "立即唤起",
4898
- desc: wakeResult ?? "调试:手动触发一次唤起(跳过窗口/间隔,仍校验配置与偏见脚本)",
4976
+ desc: wakeResult ?? "调试:手动触发一次(跳过窗口/间隔/预算,仍校验配置与偏见脚本)",
4899
4977
  control: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
4900
4978
  type: "button",
4901
4979
  className: "ss-wakeBtn",