@shgroup/dsh-serenity-hooks 1.23.0 → 1.23.2
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 +1 -1
- package/lib/client.js +176 -11
- package/lib/index.js +657 -597
- package/package.json +1 -1
package/dsh.plugin.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "dsh-serenity-hooks",
|
|
3
|
-
"version": "1.23.
|
|
3
|
+
"version": "1.23.2",
|
|
4
4
|
"main": "lib/index.js",
|
|
5
5
|
"description": "宁静号 ACC harness(Native Cordis 插件):真实 DSH 工具 cc_fs/session/acc_msm/eap/neat/cce/loop/session_rebuild + 拦截缝机械约束(safe-mode/路径守卫)+ 高级设定面板(双端口网关/账号管理)。适配 DSH 公开版(0.1.0-rc,deepseek-ai/deepseek-harness)。",
|
|
6
6
|
"engines": {
|
package/lib/client.js
CHANGED
|
@@ -8,11 +8,11 @@ window.__ModuleLoader__.load({
|
|
|
8
8
|
let react = require("react");
|
|
9
9
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
10
10
|
//#region \0sp-css:/home/yh/home/home-serenity/AI_LAB/dsh-serenity-plugin/hooks/dsh-serenity-hooks/src/client/SafeModePanel
|
|
11
|
-
const css$
|
|
12
|
-
if (typeof document !== "undefined" && document.querySelector("style[data-sp-css]") === null) {
|
|
11
|
+
const css$3 = "/* SafeModePanel — 会话头部 Serenity 状态卡片(v1.22 UX 重构)\n * 卡片 → 点击 → 官方 Modal(body portal 遮罩 + 居中)\n * 模态内:tab 栏 + 分组(groupTitle 标题 + rowCard 行卡)——看齐官方 settings 设计语言\n * 遵循 web-styling.md:颜色只用 --dsw-alias-* 语义 token(明暗自适应);\n * 前缀 sp- 防冲突。 */\n\n/* ── 头部状态卡片(可点击) ── */\n\n.sp-card {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n height: 26px;\n padding: 0 10px;\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 8px;\n background: var(--dsw-alias-bg-module-platform);\n color: inherit;\n font-size: 12px;\n cursor: pointer;\n transition: background var(--ds-transition-duration-fast, 0.1s) var(--ds-ease-in-out, ease),\n border-color var(--ds-transition-duration-fast, 0.1s) var(--ds-ease-in-out, ease);\n}\n\n.sp-card:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n border-color: var(--dsw-alias-border-l2);\n}\n\n.sp-card:focus-visible {\n outline: 2px solid var(--dsw-alias-button-ghost-active-border);\n outline-offset: 1px;\n}\n\n.sp-card:disabled {\n opacity: 0.6;\n cursor: default;\n}\n\n.sp-dot {\n flex: none;\n width: 7px;\n height: 7px;\n border-radius: 50%;\n}\n\n.sp-dotOn {\n background: var(--dsw-alias-state-success-primary);\n}\n\n.sp-dotOff {\n background: var(--dsw-alias-label-dimmed);\n}\n\n.sp-brand {\n color: var(--dsw-alias-label-primary);\n font-weight: 500;\n}\n\n.sp-chev {\n color: var(--dsw-alias-label-dimmed);\n}\n\n/* safe-mode 徽标(卡片本体直接可见;ON 红 / OFF 灰) */\n.sp-sm {\n display: inline-flex;\n align-items: center;\n gap: 3px;\n height: 18px;\n padding: 0 7px;\n border-radius: 9px;\n font-size: 11px;\n font-weight: 600;\n line-height: 1;\n}\n\n.sp-smOn {\n background: var(--dsw-alias-state-warning-bg, rgba(245, 158, 11, 0.18));\n color: var(--dsw-alias-state-warning-fg, #f59e0b);\n border: 1px solid var(--dsw-alias-state-warning-border, rgba(245, 158, 11, 0.4));\n}\n\n.sp-smOff {\n background: var(--dsw-alias-interactive-bg-active, rgba(128, 128, 128, 0.16));\n color: var(--dsw-alias-label-dimmed);\n border: 1px solid var(--dsw-alias-border-l1);\n}\n\n.sp-smIcon {\n flex: none;\n}\n\n/* ── 官方 Modal 定制(宽度 + 内容紧凑) ── */\n\n.sp-modal {\n width: 520px;\n max-width: calc(100vw - 48px);\n}\n\n/* ── tab 栏 ── */\n\n.sp-tabs {\n display: flex;\n gap: 6px;\n padding: 0 2px 12px;\n border-bottom: 1px solid var(--dsw-alias-border-l1);\n}\n\n.sp-tab {\n flex: 1;\n padding: 8px 0;\n border: none;\n border-radius: 8px;\n background: transparent;\n color: var(--dsw-alias-label-secondary);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: background var(--ds-transition-duration-fast, 0.1s) var(--ds-ease-in-out, ease);\n}\n\n.sp-tab:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.sp-tabOn {\n background: var(--dsw-alias-interactive-bg-active, rgba(128, 128, 128, 0.2));\n color: var(--dsw-alias-label-primary);\n font-weight: 600;\n}\n\n/* ── 模态内容 ── */\n\n.sp-modalBody {\n display: flex;\n flex-direction: column;\n gap: 16px;\n padding-top: 14px;\n /* 内容超出视口时 body 区滚动(兜底——不再截断);整卡不滚动 */\n overflow-y: auto;\n max-height: calc(100vh - 200px);\n}\n\n/* ── 分组(官方 settings 语言:groupTitle + rows) ── */\n\n.sp-group {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.sp-groupHead {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n}\n\n.sp-groupTitle {\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n font-weight: 600;\n letter-spacing: 0.02em;\n text-transform: uppercase;\n color: var(--dsw-alias-label-secondary);\n}\n\n.sp-rows {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n/* 行卡(rowCard:border + radius + padding;值与 label 分离、长内容可换行) */\n.sp-row {\n display: flex;\n align-items: baseline;\n gap: 12px;\n min-width: 0;\n padding: 8px 12px;\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 10px;\n background: var(--dsw-alias-bg-module);\n}\n\n.sp-label {\n flex: none;\n width: 76px;\n font-size: 12px;\n font-weight: 500;\n color: var(--dsw-alias-label-secondary);\n white-space: nowrap;\n}\n\n.sp-value {\n flex: 1;\n min-width: 0;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-primary);\n font-family: var(--ds-font-family-code, monospace);\n word-break: break-all;\n overflow-wrap: anywhere;\n}\n\n/* 安全模式动作区 */\n.sp-actions {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 8px 12px;\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 10px;\n background: var(--dsw-alias-bg-module);\n}\n\n.sp-toggle {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n height: 24px;\n padding: 0 10px;\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 6px;\n font-size: 12px;\n cursor: pointer;\n transition: background var(--ds-transition-duration-fast, 0.1s) var(--ds-ease-in-out, ease);\n}\n\n.sp-toggleLg {\n height: 30px;\n padding: 0 16px;\n font-size: 13px;\n}\n\n.sp-toggleOn {\n background: var(--dsw-alias-state-warning-bg, rgba(245, 158, 11, 0.15));\n color: var(--dsw-alias-state-warning-fg, #f59e0b);\n border-color: var(--dsw-alias-state-warning-border, rgba(245, 158, 11, 0.4));\n}\n\n.sp-toggleOff {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-secondary);\n}\n\n.sp-toggleIcon {\n flex: none;\n}\n\n.sp-toggleDesc {\n flex: 1;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-tertiary);\n}\n\n/* loop 运行状态区块 */\n\n.sp-loopsToggle {\n flex: none;\n padding: 2px 10px;\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 6px;\n background: transparent;\n color: var(--dsw-alias-label-secondary);\n font-size: 11px;\n cursor: pointer;\n}\n\n.sp-loopsToggle:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.sp-loopsList {\n display: flex;\n flex-direction: column;\n gap: 4px;\n margin-top: 2px;\n}\n\n.sp-loopItem {\n display: flex;\n flex-direction: column;\n gap: 2px;\n padding: 8px 12px;\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 8px;\n min-width: 0;\n}\n\n.sp-loopHead {\n display: flex;\n align-items: baseline;\n gap: 8px;\n min-width: 0;\n}\n\n.sp-loopLabel {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: 12px;\n font-weight: 500;\n color: var(--dsw-alias-label-primary);\n}\n\n.sp-loopRound {\n flex: none;\n font-size: 11px;\n color: var(--dsw-alias-label-dimmed);\n}\n\n.sp-loopTime {\n flex: none;\n font-size: 11px;\n color: var(--dsw-alias-label-dimmed);\n}\n\n.sp-loopResp {\n font-size: 11px;\n line-height: 16px;\n color: var(--dsw-alias-label-secondary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.sp-loopsMore {\n font-size: 11px;\n color: var(--dsw-alias-label-dimmed);\n padding: 4px 12px;\n}\n\n/* 底部提示(配置入口引导) */\n.sp-hint {\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-tertiary);\n word-break: break-word;\n overflow-wrap: anywhere;\n padding: 8px 12px;\n border: 1px dashed var(--dsw-alias-border-l2);\n border-radius: 10px;\n}\n";
|
|
12
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-sp-css=\"SafeModePanel\"]") === null) {
|
|
13
13
|
const tag = document.createElement("style");
|
|
14
|
-
tag.setAttribute("data-sp-css", "
|
|
15
|
-
tag.textContent = css$
|
|
14
|
+
tag.setAttribute("data-sp-css", "SafeModePanel");
|
|
15
|
+
tag.textContent = css$3;
|
|
16
16
|
document.head.appendChild(tag);
|
|
17
17
|
}
|
|
18
18
|
//#endregion
|
|
@@ -528,7 +528,7 @@ window.__ModuleLoader__.load({
|
|
|
528
528
|
if (!res.ok) return null;
|
|
529
529
|
return (await res.json()).config ?? null;
|
|
530
530
|
}
|
|
531
|
-
/** PUT 配置(账号 patch +
|
|
531
|
+
/** PUT 配置(账号 patch + 工作区白名单 + persona 彩蛋)→ 返回保存后的 wire */
|
|
532
532
|
async function saveConfig(patch) {
|
|
533
533
|
const res = await fetch(CONFIG_PATH, {
|
|
534
534
|
method: "PUT",
|
|
@@ -546,11 +546,11 @@ window.__ModuleLoader__.load({
|
|
|
546
546
|
}
|
|
547
547
|
//#endregion
|
|
548
548
|
//#region \0sp-css:/home/yh/home/home-serenity/AI_LAB/dsh-serenity-plugin/hooks/dsh-serenity-hooks/src/client/AccountsEditor
|
|
549
|
-
const css$
|
|
550
|
-
if (typeof document !== "undefined" && document.querySelector("style[data-sp-css]") === null) {
|
|
549
|
+
const css$2 = "/* AccountsEditor — DSH 设置面板「外部访问」区块(v1.22)\n * 与 SettingsSection ss-* 同设计语言:--dsw-alias-* 语义 token,明暗自适应。 */\n\n.ae-root {\n display: flex;\n flex-direction: column;\n gap: 16px;\n padding: 12px 14px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 12px;\n font-size: 13px;\n}\n\n.ae-warn {\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-state-warning-fg, #f59e0b);\n word-break: break-word;\n}\n\n.ae-block {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.ae-title {\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n font-weight: 600;\n letter-spacing: 0.02em;\n text-transform: uppercase;\n color: var(--dsw-alias-label-secondary);\n}\n\n.ae-desc {\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-tertiary);\n word-break: break-word;\n overflow-wrap: anywhere;\n}\n\n.ae-note {\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-tertiary);\n}\n\n/* ── 监听设置 / 白名单输入行 ── */\n\n.ae-row {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.ae-label {\n flex: none;\n font-size: 12px;\n font-weight: 500;\n color: var(--dsw-alias-label-secondary);\n white-space: nowrap;\n}\n\n.ae-input {\n flex: 1;\n min-width: 0;\n padding: 6px 10px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 8px;\n background: var(--dsw-alias-bg-module);\n color: var(--dsw-alias-label-primary);\n font-size: 13px;\n outline: none;\n}\n\n.ae-input:focus {\n border-color: var(--dsw-alias-button-primary-bg, var(--dsw-alias-accent, #3b82f6));\n}\n\n.ae-input::placeholder {\n color: var(--dsw-alias-label-dimmed);\n}\n\n.ae-input.ae-port {\n flex: none;\n width: 76px;\n}\n\n/* ── 账号列表 ── */\n\n.ae-list {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.ae-head {\n display: flex;\n gap: 8px;\n font-size: 11px;\n font-weight: 500;\n color: var(--dsw-alias-label-dimmed);\n padding: 0 2px;\n text-transform: uppercase;\n letter-spacing: 0.02em;\n}\n\n.ae-item {\n display: flex;\n gap: 8px;\n align-items: center;\n padding: 6px 2px;\n}\n\n.ae-colUser { flex: 1.2; }\n.ae-colPass { flex: 1.6; }\n.ae-colTotp { flex: 2.2; min-width: 0; }\n.ae-colOp { flex: none; width: 48px; }\n\n/* ── v1.22.4 TOTP 第二因素 ── */\n\n.ae-totpBtn {\n flex: none;\n padding: 4px 10px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 6px;\n background: transparent;\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n cursor: pointer;\n white-space: nowrap;\n}\n\n.ae-totpBtn:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.ae-totpPending {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n align-items: center;\n min-width: 0;\n}\n\n.ae-totpSecret {\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n font-size: 11px;\n background: var(--dsw-alias-surface-raised, rgba(0, 0, 0, 0.25));\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 4px;\n padding: 2px 6px;\n color: var(--dsw-alias-label-secondary);\n word-break: break-all;\n}\n\n.ae-totpUri {\n font-size: 11px;\n color: var(--dsw-alias-accent, #3b82f6);\n text-decoration: none;\n}\n\n.ae-totpUri:hover {\n text-decoration: underline;\n}\n\n.ae-totpConfirm {\n max-width: 120px;\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n letter-spacing: 0.2em;\n}\n\n.ae-totpBadge {\n font-size: 12px;\n color: var(--dsw-alias-state-warning-fg, #f59e0b);\n}\n\n.ae-totpClear {\n display: flex;\n gap: 6px;\n align-items: center;\n}\n\n.ae-check {\n display: flex;\n gap: 8px;\n align-items: center;\n font-size: 12px;\n color: var(--dsw-alias-label-secondary);\n margin-top: 10px;\n cursor: pointer;\n}\n\n.ae-check input {\n accent-color: var(--dsw-alias-accent, #3b82f6);\n}\n\n.ae-del {\n flex: none;\n padding: 4px 10px;\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 6px;\n background: transparent;\n color: var(--dsw-alias-state-danger-fg, #f87171);\n font-size: 12px;\n cursor: pointer;\n}\n\n.ae-del:hover {\n background: var(--dsw-alias-state-danger-bg, rgba(248, 113, 113, 0.12));\n}\n\n.ae-add {\n align-self: flex-start;\n padding: 5px 12px;\n border: 1px dashed var(--dsw-alias-border-l2);\n border-radius: 8px;\n background: transparent;\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n cursor: pointer;\n}\n\n.ae-add:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.ae-wsSelect {\n margin-top: 8px;\n max-width: 100%;\n cursor: pointer;\n}\n\n/* ── 工作区白名单 chips ── */\n\n.ae-wsList {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n}\n\n.ae-wsChip {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 3px 8px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 8px;\n background: var(--dsw-alias-interactive-bg-active, rgba(128, 128, 128, 0.14));\n}\n\n.ae-wsPath {\n font-size: 12px;\n color: var(--dsw-alias-label-primary);\n font-family: var(--ds-font-family-code, monospace);\n word-break: break-all;\n}\n\n.ae-wsDel {\n flex: none;\n width: 18px;\n height: 18px;\n border: none;\n border-radius: 50%;\n background: transparent;\n color: var(--dsw-alias-label-dimmed);\n font-size: 13px;\n line-height: 1;\n cursor: pointer;\n}\n\n.ae-wsDel:hover {\n background: var(--dsw-alias-state-danger-bg, rgba(248, 113, 113, 0.18));\n color: var(--dsw-alias-state-danger-fg, #f87171);\n}\n\n/* ── 错误 / 操作区 ── */\n\n.ae-error {\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-state-danger-fg, #f87171);\n word-break: break-word;\n}\n\n.ae-actions {\n display: flex;\n justify-content: flex-end;\n padding-top: 4px;\n border-top: 1px solid var(--dsw-alias-border-l1);\n}\n\n.ae-save {\n padding: 7px 24px;\n border: 0;\n border-radius: 8px;\n background: var(--dsw-alias-button-primary-bg, var(--dsw-alias-accent, #3b82f6));\n color: var(--dsw-alias-button-primary-fg, #fff);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n}\n\n.ae-save:hover:not(:disabled) {\n filter: brightness(1.08);\n}\n\n.ae-save:disabled {\n opacity: 0.6;\n cursor: default;\n}\n";
|
|
550
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-sp-css=\"AccountsEditor\"]") === null) {
|
|
551
551
|
const tag = document.createElement("style");
|
|
552
|
-
tag.setAttribute("data-sp-css", "
|
|
553
|
-
tag.textContent = css$
|
|
552
|
+
tag.setAttribute("data-sp-css", "AccountsEditor");
|
|
553
|
+
tag.textContent = css$2;
|
|
554
554
|
document.head.appendChild(tag);
|
|
555
555
|
}
|
|
556
556
|
//#endregion
|
|
@@ -947,11 +947,169 @@ window.__ModuleLoader__.load({
|
|
|
947
947
|
});
|
|
948
948
|
}
|
|
949
949
|
//#endregion
|
|
950
|
+
//#region \0sp-css:/home/yh/home/home-serenity/AI_LAB/dsh-serenity-plugin/hooks/dsh-serenity-hooks/src/client/PersonaEditor
|
|
951
|
+
const css$1 = "/* PersonaEditor.css — 彩蛋模式区块(v1.23.1,官方 settings 设计语言:rowCard 内分组) */\n\n.pe-wrap {\n display: flex;\n flex-direction: column;\n gap: 10px;\n width: 100%;\n padding: 2px 0 6px;\n}\n\n.pe-row {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.pe-label {\n font-size: 12px;\n color: var(--dsw-alias-text-secondary, #8a8f98);\n user-select: none;\n}\n\n.pe-input,\n.pe-textarea {\n width: 100%;\n box-sizing: border-box;\n background: var(--dsw-alias-bg-secondary, rgba(128, 128, 128, 0.08));\n color: var(--dsw-alias-text-primary, #e6e6e6);\n border: 1px solid var(--dsw-alias-border, rgba(128, 128, 128, 0.25));\n border-radius: 8px;\n font-size: 13px;\n padding: 8px 10px;\n outline: none;\n}\n\n.pe-input:focus,\n.pe-textarea:focus {\n border-color: var(--dsw-alias-accent, #4f8cff);\n}\n\n.pe-textarea {\n resize: vertical;\n min-height: 120px;\n line-height: 1.5;\n font-family: var(--dsw-alias-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);\n font-size: 12px;\n}\n\n.pe-actions {\n display: flex;\n gap: 8px;\n align-items: center;\n flex-wrap: wrap;\n}\n\n.pe-btn {\n border-radius: 6px;\n padding: 5px 12px;\n font-size: 12px;\n cursor: pointer;\n border: 1px solid var(--dsw-alias-border, rgba(128, 128, 128, 0.25));\n background: transparent;\n color: var(--dsw-alias-text-primary, #e6e6e6);\n transition: opacity 0.15s;\n}\n\n.pe-btn:hover:not(:disabled) {\n opacity: 0.85;\n}\n\n.pe-btn:disabled {\n opacity: 0.4;\n cursor: default;\n}\n\n.pe-btnGhost {\n border-color: var(--dsw-alias-border, rgba(128, 128, 128, 0.25));\n}\n\n.pe-btnPrimary {\n background: var(--dsw-alias-accent, #4f8cff);\n border-color: transparent;\n color: #fff;\n}\n\n.pe-hint {\n font-size: 12px;\n margin: 0;\n}\n\n.pe-hintOk {\n color: var(--dsw-alias-state-success, #4caf50);\n}\n\n.pe-hintErr {\n color: var(--dsw-alias-state-error, #e5484d);\n}\n";
|
|
952
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-sp-css=\"PersonaEditor\"]") === null) {
|
|
953
|
+
const tag = document.createElement("style");
|
|
954
|
+
tag.setAttribute("data-sp-css", "PersonaEditor");
|
|
955
|
+
tag.textContent = css$1;
|
|
956
|
+
document.head.appendChild(tag);
|
|
957
|
+
}
|
|
958
|
+
//#endregion
|
|
959
|
+
//#region src/client/PersonaEditor.tsx
|
|
960
|
+
/**
|
|
961
|
+
* PersonaEditor.tsx — DSH 设置面板「彩蛋模式」区块(v1.23.1,S142 用户需求)
|
|
962
|
+
*
|
|
963
|
+
* 彩蛋功能:用户可替换 ACC 系统提示词中"输出约束/指令遵循约束"部分
|
|
964
|
+
* (EAP 块 + MSM 原则段),配置后 agent 输出风格/指令遵循风格随用户文本变化;
|
|
965
|
+
* 未配置(模式名空)→ 完全默认行为,零影响。
|
|
966
|
+
*
|
|
967
|
+
* 数据:GET/PUT /serenity/config 的 persona 节(存 ~/.dsh/serenity-hooks.json
|
|
968
|
+
* plugin 全局文件,同账号配置归属原则)。保存 → PUT → 服务端落盘 →
|
|
969
|
+
* 热生效(system-prompt 装配每次读全局文件,无需重启)。
|
|
970
|
+
*
|
|
971
|
+
* 预置:一键填充「大肥鱼」demo 文本(DeepSeek 社区娘化人格测试用)。
|
|
972
|
+
*/
|
|
973
|
+
/** 大肥鱼模式 demo 提示词(测试彩蛋替换面:输出风格 + 指令遵循风格) */
|
|
974
|
+
const BIG_FAT_FISH_DEMO = `You are now in BIG FAT FISH (大肥鱼) mode — the DeepSeek community's beloved
|
|
975
|
+
whale-girl persona: a round, blue, snacky fish who loves plain white rice and
|
|
976
|
+
hates unnecessary fuss. The persona only colors HOW you say things and HOW you
|
|
977
|
+
follow instructions — it never reduces the quality or safety of the work.
|
|
978
|
+
|
|
979
|
+
Output style:
|
|
980
|
+
• Keep the EAP spirit (E↑ explicit, R↓ reconstructable, S↑ stable) — but say
|
|
981
|
+
it like a fish: "把话说清楚,不然我这条鱼会晕" (be explicit, or this fish gets dizzy)
|
|
982
|
+
• Start replies with a light, lazy tone ("唔…", "摸鱼中…"), then get serious
|
|
983
|
+
and do the actual work properly — no slacking on the task itself
|
|
984
|
+
• Prefer short, concrete sentences; fish-brain means no vague words
|
|
985
|
+
• When reporting progress, be honest and specific — never fake completion
|
|
986
|
+
just to go eat rice earlier
|
|
987
|
+
|
|
988
|
+
Instruction-following style:
|
|
989
|
+
• Follow instructions exactly as given (this fish follows the recipe, not its appetite)
|
|
990
|
+
• If an instruction is ambiguous, ask before guessing — guessing wrong wastes
|
|
991
|
+
both rice and time
|
|
992
|
+
• Keep the container rules sacred: never bypass safety guards, never write to
|
|
993
|
+
protected paths, never fake tool results. A lazy fish, but an honest one
|
|
994
|
+
• Report blockers plainly — "我卡住了,别让我装不卡"`;
|
|
995
|
+
function PersonaEditor() {
|
|
996
|
+
const [mode, setMode] = (0, react.useState)("");
|
|
997
|
+
const [overrideText, setOverrideText] = (0, react.useState)("");
|
|
998
|
+
const [loaded, setLoaded] = (0, react.useState)(false);
|
|
999
|
+
const [busy, setBusy] = (0, react.useState)(false);
|
|
1000
|
+
const [error, setError] = (0, react.useState)(null);
|
|
1001
|
+
const [saved, setSaved] = (0, react.useState)(false);
|
|
1002
|
+
(0, react.useEffect)(() => {
|
|
1003
|
+
let alive = true;
|
|
1004
|
+
fetchConfig().then((cfg) => {
|
|
1005
|
+
if (!alive || !cfg) return;
|
|
1006
|
+
setMode(cfg.persona?.mode ?? "");
|
|
1007
|
+
setOverrideText(cfg.persona?.overrideText ?? "");
|
|
1008
|
+
setLoaded(true);
|
|
1009
|
+
});
|
|
1010
|
+
return () => {
|
|
1011
|
+
alive = false;
|
|
1012
|
+
};
|
|
1013
|
+
}, []);
|
|
1014
|
+
const save = () => {
|
|
1015
|
+
setBusy(true);
|
|
1016
|
+
setError(null);
|
|
1017
|
+
setSaved(false);
|
|
1018
|
+
saveConfig({ persona: {
|
|
1019
|
+
mode,
|
|
1020
|
+
overrideText
|
|
1021
|
+
} }).then((cfg) => {
|
|
1022
|
+
if (cfg) {
|
|
1023
|
+
setMode(cfg.persona?.mode ?? mode);
|
|
1024
|
+
setOverrideText(cfg.persona?.overrideText ?? overrideText);
|
|
1025
|
+
setSaved(true);
|
|
1026
|
+
setTimeout(() => setSaved(false), 2e3);
|
|
1027
|
+
}
|
|
1028
|
+
}).catch((e) => setError(e instanceof Error ? e.message : String(e))).finally(() => setBusy(false));
|
|
1029
|
+
};
|
|
1030
|
+
const fillDemo = () => {
|
|
1031
|
+
setMode("大肥鱼");
|
|
1032
|
+
setOverrideText(BIG_FAT_FISH_DEMO);
|
|
1033
|
+
};
|
|
1034
|
+
const clear = () => {
|
|
1035
|
+
setMode("");
|
|
1036
|
+
setOverrideText("");
|
|
1037
|
+
};
|
|
1038
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1039
|
+
className: "pe-wrap",
|
|
1040
|
+
children: [
|
|
1041
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1042
|
+
className: "pe-row",
|
|
1043
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
|
|
1044
|
+
className: "pe-label",
|
|
1045
|
+
htmlFor: "pe-mode",
|
|
1046
|
+
children: "模式名"
|
|
1047
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
1048
|
+
id: "pe-mode",
|
|
1049
|
+
className: "pe-input",
|
|
1050
|
+
type: "text",
|
|
1051
|
+
value: mode,
|
|
1052
|
+
placeholder: "留空 = 彩蛋关闭(默认行为)",
|
|
1053
|
+
onChange: (e) => setMode(e.target.value)
|
|
1054
|
+
})]
|
|
1055
|
+
}),
|
|
1056
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1057
|
+
className: "pe-row",
|
|
1058
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
|
|
1059
|
+
className: "pe-label",
|
|
1060
|
+
htmlFor: "pe-text",
|
|
1061
|
+
children: "替换文本(替代输出约束 + 指令遵循约束)"
|
|
1062
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
|
|
1063
|
+
id: "pe-text",
|
|
1064
|
+
className: "pe-textarea",
|
|
1065
|
+
rows: 10,
|
|
1066
|
+
value: overrideText,
|
|
1067
|
+
placeholder: "配置后:EAP 块 + MSM 原则段被此文本替换;未配置:完全默认。",
|
|
1068
|
+
onChange: (e) => setOverrideText(e.target.value)
|
|
1069
|
+
})]
|
|
1070
|
+
}),
|
|
1071
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1072
|
+
className: "pe-actions",
|
|
1073
|
+
children: [
|
|
1074
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
1075
|
+
className: "pe-btn pe-btnGhost",
|
|
1076
|
+
type: "button",
|
|
1077
|
+
onClick: fillDemo,
|
|
1078
|
+
children: "填充「大肥鱼」demo"
|
|
1079
|
+
}),
|
|
1080
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
1081
|
+
className: "pe-btn pe-btnGhost",
|
|
1082
|
+
type: "button",
|
|
1083
|
+
onClick: clear,
|
|
1084
|
+
disabled: !loaded,
|
|
1085
|
+
children: "清空(关闭彩蛋)"
|
|
1086
|
+
}),
|
|
1087
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
1088
|
+
className: "pe-btn pe-btnPrimary",
|
|
1089
|
+
type: "button",
|
|
1090
|
+
onClick: save,
|
|
1091
|
+
disabled: busy || !loaded,
|
|
1092
|
+
children: busy ? "保存中…" : "保存"
|
|
1093
|
+
})
|
|
1094
|
+
]
|
|
1095
|
+
}),
|
|
1096
|
+
saved && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1097
|
+
className: "pe-hint pe-hintOk",
|
|
1098
|
+
children: "已保存,新会话即时生效"
|
|
1099
|
+
}),
|
|
1100
|
+
error && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1101
|
+
className: "pe-hint pe-hintErr",
|
|
1102
|
+
children: error
|
|
1103
|
+
})
|
|
1104
|
+
]
|
|
1105
|
+
});
|
|
1106
|
+
}
|
|
1107
|
+
//#endregion
|
|
950
1108
|
//#region \0sp-css:/home/yh/home/home-serenity/AI_LAB/dsh-serenity-plugin/hooks/dsh-serenity-hooks/src/client/SettingsSection
|
|
951
1109
|
const css = "/* SettingsSection — dsh 原生设置面板 serenity-hooks 简单配置页\n v1.21.1 看齐 dsh 自身:官方 settings 设计语言——\n section > title + intro + group(groupTitle) + rowCard 行卡;\n 全部 --dsw-alias-* token(与 ui-settings-models 同词汇表)。 */\n\n/* 页面容器(官方 .section:flex column gap 12) */\n.ss-section {\n display: flex;\n flex-direction: column;\n gap: 14px;\n max-width: 720px;\n color: var(--dsw-alias-label-primary);\n}\n\n/* 页面标题(官方 .title:16px/24 500) */\n.ss-title {\n margin: 0;\n font-size: 16px;\n line-height: 24px;\n font-weight: 500;\n color: var(--dsw-alias-label-primary);\n}\n\n/* 页面说明(官方 .intro:14px/22 tertiary) */\n.ss-intro {\n margin: 0;\n font-size: 14px;\n line-height: 22px;\n color: var(--dsw-alias-label-tertiary);\n word-break: break-word;\n overflow-wrap: anywhere;\n}\n\n/* 分组(多级标题:分组标题 + 行卡列表) */\n.ss-group {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n/* 分组标题(二级:12px/18 500 secondary——官方 fieldLabel 风格) */\n.ss-groupTitle {\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n font-weight: 600;\n letter-spacing: 0.02em;\n text-transform: uppercase;\n color: var(--dsw-alias-label-secondary);\n}\n\n/* 行卡列表(官方 .rows:无 marker,gap 8) */\n.ss-rows {\n list-style: none;\n margin: 0;\n padding: 0;\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n/* 行卡(官方 .rowCard:border-l2 r12 padding 12/14) */\n.ss-rowCard {\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 12px;\n padding: 12px 14px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 16px;\n}\n\n/* 行卡文本(标题 + 说明 左列) */\n.ss-rowText {\n display: flex;\n flex-direction: column;\n gap: 3px;\n min-width: 0;\n flex: 1;\n}\n\n/* 行卡标题(官方 .rowName:14px/22 500) */\n.ss-rowName {\n font-size: 14px;\n line-height: 22px;\n font-weight: 500;\n color: var(--dsw-alias-label-primary);\n}\n\n/* 行卡说明(12px/18 tertiary) */\n.ss-rowDesc {\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-tertiary);\n word-break: break-word;\n overflow-wrap: anywhere;\n}\n\n/* 行卡控件(右置) */\n.ss-rowControl {\n flex: none;\n display: flex;\n align-items: center;\n}\n\n/* 开关(官方 token 的自绘 toggle:track 22px,thumb 16px) */\n.ss-switch {\n position: relative;\n flex: none;\n width: 40px;\n height: 22px;\n cursor: pointer;\n}\n\n.ss-switch input {\n position: absolute;\n opacity: 0;\n width: 100%;\n height: 100%;\n margin: 0;\n cursor: pointer;\n}\n\n.ss-switchTrack {\n position: absolute;\n inset: 0;\n border-radius: 11px;\n background: var(--dsw-alias-interactive-bg-active, rgba(128, 128, 128, 0.3));\n transition: background var(--ds-transition-duration-fast, 0.15s) var(--ds-ease-in-out, ease);\n}\n\n.ss-switchTrack::after {\n content: '';\n position: absolute;\n top: 3px;\n left: 3px;\n width: 16px;\n height: 16px;\n border-radius: 50%;\n background: var(--dsw-alias-label-primary, #eee);\n transition: transform var(--ds-transition-duration-fast, 0.15s) var(--ds-ease-in-out, ease);\n}\n\n.ss-switch input:checked + .ss-switchTrack {\n background: var(--dsw-alias-state-success-primary, #22c55e);\n}\n\n.ss-switch input:checked + .ss-switchTrack::after {\n transform: translateX(18px);\n}\n\n.ss-switch input:disabled + .ss-switchTrack {\n opacity: 0.4;\n cursor: default;\n}\n\n/* 阈值行(滑块 + 值) */\n.ss-threshold {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.ss-threshold input[type='range'] {\n width: 160px;\n}\n\n.ss-value {\n min-width: 40px;\n font-variant-numeric: tabular-nums;\n font-size: 13px;\n font-weight: 600;\n color: var(--dsw-alias-label-primary);\n text-align: right;\n}\n\n/* 底部帮助行 */\n.ss-hint {\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-tertiary);\n word-break: break-word;\n overflow-wrap: anywhere;\n}\n\n/* 降级提示 */\n.ss-degrade {\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-state-warn-label);\n word-break: break-word;\n overflow-wrap: anywhere;\n}\n";
|
|
952
|
-
if (typeof document !== "undefined" && document.querySelector("style[data-sp-css]") === null) {
|
|
1110
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-sp-css=\"SettingsSection\"]") === null) {
|
|
953
1111
|
const tag = document.createElement("style");
|
|
954
|
-
tag.setAttribute("data-sp-css", "
|
|
1112
|
+
tag.setAttribute("data-sp-css", "SettingsSection");
|
|
955
1113
|
tag.textContent = css;
|
|
956
1114
|
document.head.appendChild(tag);
|
|
957
1115
|
}
|
|
@@ -1100,6 +1258,13 @@ window.__ModuleLoader__.load({
|
|
|
1100
1258
|
className: "ss-groupTitle",
|
|
1101
1259
|
children: "外部访问"
|
|
1102
1260
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AccountsEditor, { gatewayOn })]
|
|
1261
|
+
}),
|
|
1262
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1263
|
+
className: "ss-group",
|
|
1264
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
|
|
1265
|
+
className: "ss-groupTitle",
|
|
1266
|
+
children: "彩蛋模式"
|
|
1267
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PersonaEditor, {})]
|
|
1103
1268
|
})
|
|
1104
1269
|
]
|
|
1105
1270
|
});
|