@shgroup/dsh-serenity-hooks 1.26.3 → 1.26.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/dsh.plugin.json +1 -1
- package/lib/index.js +181 -59
- 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.26.
|
|
3
|
+
"version": "1.26.4",
|
|
4
4
|
"main": "lib/index.js",
|
|
5
5
|
"description": "宁静号 ACC harness(Native Cordis 插件):真实 DSH 工具 cc_fs/session/acc_msm/eap/neat/cce/handyman/session_rebuild/skiff_admin + 拦截缝机械约束(safe-mode/路径守卫)+ 高级设定面板(双端口网关/账号管理)+ Skiff 认知子集角色(实验性)。适配 DSH 公开版(0.1.0-rc,deepseek-ai/deepseek-harness)。",
|
|
6
6
|
"engines": {
|
package/lib/index.js
CHANGED
|
@@ -11663,9 +11663,11 @@ function escapeHtml(s) {
|
|
|
11663
11663
|
* ① 提取 `<think>…</think>` 块(占位符 \u0000T<idx>\u0000)
|
|
11664
11664
|
* ② 正文与 think 内容**先 escapeHtml 再 marked.parse**(GFM + breaks)——markdown 语法不受
|
|
11665
11665
|
* 转义影响,原始 HTML 注入被消除(安全);代码块内 `<` 显示为实体(可接受)
|
|
11666
|
-
* ③ think
|
|
11666
|
+
* ③ think 占位符:默认还原为 `<details class="think">` 折叠卡(🧠 思考过程,默认收起);
|
|
11667
|
+
* **hideThink=true(v1.26.4,public 口)→ 直接移除**(思考过程对普通用户不展示)
|
|
11668
|
+
* @param hideThink 为 true 时 `<think>` 内容完全不渲染(public 问答页体验)
|
|
11667
11669
|
*/
|
|
11668
|
-
function renderSkiffMarkdown(raw) {
|
|
11670
|
+
function renderSkiffMarkdown(raw, hideThink = false) {
|
|
11669
11671
|
const thinks = [];
|
|
11670
11672
|
const body = raw.replace(/<think>([\s\S]*?)<\/think>/gi, (_m, inner) => {
|
|
11671
11673
|
const idx = thinks.length;
|
|
@@ -11677,6 +11679,7 @@ function renderSkiffMarkdown(raw) {
|
|
|
11677
11679
|
gfm: true
|
|
11678
11680
|
});
|
|
11679
11681
|
return (typeof parsed === "string" ? parsed : "").replace(/\u0000T(\d+)\u0000/g, (_m, idx) => {
|
|
11682
|
+
if (hideThink) return "";
|
|
11680
11683
|
const inner = thinks[Number(idx)] ?? "";
|
|
11681
11684
|
const innerHtml = inner === "" ? "" : f.parse(escapeHtml(inner), {
|
|
11682
11685
|
breaks: true,
|
|
@@ -12193,7 +12196,7 @@ async function handleAskParsed(ctx, ccc, body, res) {
|
|
|
12193
12196
|
const result = await askSkiff(ctx, agent, question, 0);
|
|
12194
12197
|
sendJson(res, 200, {
|
|
12195
12198
|
answer: result.answer,
|
|
12196
|
-
answer_html: renderSkiffMarkdown(result.answer),
|
|
12199
|
+
answer_html: renderSkiffMarkdown(result.answer, true),
|
|
12197
12200
|
sessionId: result.sessionId,
|
|
12198
12201
|
continued,
|
|
12199
12202
|
trajectory: result.trajectory
|
|
@@ -12228,39 +12231,77 @@ function publicAskContainerClosedHtml(name) {
|
|
|
12228
12231
|
<p style="font-size:13px"><a href="/" style="color:#0ba875">返回容器列表</a></p>
|
|
12229
12232
|
</body></html>`;
|
|
12230
12233
|
}
|
|
12231
|
-
/** 页面基础样式(列表页 +
|
|
12234
|
+
/** 页面基础样式(列表页 + 单容器页共用;v1.26.4 聊天 UI) */
|
|
12232
12235
|
const ASK_CSS = `
|
|
12233
|
-
:root { color-scheme: light dark; }
|
|
12234
|
-
|
|
12235
|
-
|
|
12236
|
+
:root { color-scheme: light dark; --sp-green: #0ba875; --sp-green-dim: #059669; }
|
|
12237
|
+
* { box-sizing: border-box; }
|
|
12238
|
+
html, body { height: 100%; }
|
|
12239
|
+
body { font-family: system-ui, -apple-system, sans-serif; margin: 0; background: #f6f7f9; color: #1f2328; }
|
|
12240
|
+
@media (prefers-color-scheme: dark) { body { background: #16181c; color: #e6e6e6; } }
|
|
12236
12241
|
main { max-width: 720px; margin: 0 auto; }
|
|
12237
12242
|
h1 { font-size: 18px; margin: 0 0 4px; }
|
|
12238
12243
|
.sub { opacity: .65; font-size: 13px; margin-bottom: 16px; }
|
|
12239
|
-
label { font-size: 13px; font-weight: 600; display: block; margin: 12px 0 4px; }
|
|
12240
|
-
input, select, textarea { width: 100%; box-sizing: border-box; padding: 8px 10px; border-radius: 8px; border: 1px solid #d0d7de; background: #fff; color: inherit; font-size: 14px; }
|
|
12241
|
-
@media (prefers-color-scheme: dark) { input, select, textarea { background: #26282c; border-color: #3a3d42; } }
|
|
12242
|
-
textarea { min-height: 72px; resize: vertical; }
|
|
12243
|
-
button { margin-top: 12px; padding: 9px 18px; border-radius: 8px; border: 0; background: #0ba875; color: #fff; font-size: 14px; font-weight: 600; cursor: pointer; }
|
|
12244
|
-
button:disabled { opacity: .55; cursor: wait; }
|
|
12245
12244
|
.card { background: #fff; border: 1px solid #d0d7de; border-radius: 10px; padding: 14px 16px; margin-bottom: 10px; display: block; text-decoration: none; color: inherit; }
|
|
12246
12245
|
@media (prefers-color-scheme: dark) { .card { background: #26282c; border-color: #3a3d42; } }
|
|
12247
|
-
.card:hover { border-color:
|
|
12246
|
+
.card:hover { border-color: var(--sp-green); }
|
|
12248
12247
|
.card .cname { font-weight: 600; font-size: 15px; }
|
|
12249
12248
|
.card .cmeta { opacity: .6; font-size: 12px; margin-top: 2px; }
|
|
12250
|
-
#answer { background: #fff; border: 1px solid #d0d7de; border-radius: 8px; padding: 12px; margin-top: 16px; font-size: 14px; line-height: 1.6; min-height: 48px; word-break: break-word; }
|
|
12251
|
-
@media (prefers-color-scheme: dark) { #answer { background: #26282c; border-color: #3a3d42; } }
|
|
12252
|
-
#answer p { margin: 6px 0; }
|
|
12253
|
-
#answer h1, #answer h2, #answer h3 { margin: 12px 0 6px; font-size: 15px; }
|
|
12254
|
-
#answer code { background: rgba(127,127,127,.14); border-radius: 4px; padding: 1px 5px; font-size: 13px; font-family: ui-monospace, monospace; }
|
|
12255
|
-
#answer pre { background: rgba(127,127,127,.1); border-radius: 8px; padding: 10px 12px; overflow-x: auto; }
|
|
12256
|
-
#answer ul, #answer ol { margin: 6px 0; padding-left: 22px; }
|
|
12257
|
-
.err { color: #cf222e; white-space: pre-wrap; }
|
|
12258
|
-
.muted { opacity: .6; font-size: 13px; }
|
|
12259
|
-
details.think { margin: 8px 0; border: 1px solid rgba(210,153,34,.4); border-radius: 8px; background: rgba(210,153,34,.06); }
|
|
12260
|
-
details.think summary { cursor: pointer; padding: 6px 10px; font-size: 12px; color: #d29922; font-weight: 600; }
|
|
12261
12249
|
.empty { text-align: center; opacity: .7; padding: 24px 0; }
|
|
12262
|
-
.
|
|
12263
|
-
|
|
12250
|
+
.ccname { font-weight: 600; color: var(--sp-green); }
|
|
12251
|
+
|
|
12252
|
+
/* ── 聊天布局(v1.26.4 体验升级:参考 ChatGPT/Claude 会话形态)── */
|
|
12253
|
+
.chat { display: flex; flex-direction: column; height: 100vh; max-width: 720px; margin: 0 auto; }
|
|
12254
|
+
.chatHead { display: flex; align-items: center; gap: 10px; padding: 10px 16px; border-bottom: 1px solid rgba(127,127,127,.18); background: rgba(127,127,127,.04); position: sticky; top: 0; z-index: 5; }
|
|
12255
|
+
.chatHead .back { color: var(--sp-green); text-decoration: none; font-size: 13px; white-space: nowrap; }
|
|
12256
|
+
.chatHead .title { font-weight: 600; font-size: 14px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
12257
|
+
.chatHead .spacer { flex: 1; }
|
|
12258
|
+
.chatHead select { border: 1px solid rgba(127,127,127,.25); border-radius: 8px; background: transparent; color: inherit; padding: 4px 8px; font-size: 12px; }
|
|
12259
|
+
.chatHead .newBtn { border: 1px solid rgba(127,127,127,.25); border-radius: 8px; background: transparent; color: inherit; padding: 4px 10px; font-size: 12px; cursor: pointer; white-space: nowrap; }
|
|
12260
|
+
.chatHead .newBtn:hover { border-color: var(--sp-green); color: var(--sp-green); }
|
|
12261
|
+
/* 消息流 */
|
|
12262
|
+
.msgList { flex: 1; overflow-y: auto; padding: 18px 16px; display: flex; flex-direction: column; gap: 16px; }
|
|
12263
|
+
.msg { display: flex; flex-direction: column; max-width: 88%; }
|
|
12264
|
+
.msg.user { align-self: flex-end; align-items: flex-end; }
|
|
12265
|
+
.msg.assistant { align-self: flex-start; align-items: flex-start; }
|
|
12266
|
+
.msg .who { font-size: 11px; opacity: .55; margin-bottom: 4px; padding: 0 4px; }
|
|
12267
|
+
.msg .bubble { padding: 10px 14px; border-radius: 14px; font-size: 14px; line-height: 1.65; word-break: break-word; white-space: normal; }
|
|
12268
|
+
.msg.user .bubble { background: var(--sp-green); color: #fff; border-bottom-right-radius: 4px; }
|
|
12269
|
+
.msg.assistant .bubble { background: #fff; border: 1px solid #d0d7de; border-bottom-left-radius: 4px; }
|
|
12270
|
+
@media (prefers-color-scheme: dark) { .msg.assistant .bubble { background: #26282c; border-color: #3a3d42; } }
|
|
12271
|
+
.bubble p { margin: 6px 0; }
|
|
12272
|
+
.bubble p:first-child { margin-top: 0; }
|
|
12273
|
+
.bubble p:last-child { margin-bottom: 0; }
|
|
12274
|
+
.bubble h1, .bubble h2, .bubble h3, .bubble h4 { margin: 12px 0 6px; font-size: 15px; line-height: 1.4; }
|
|
12275
|
+
.bubble ul, .bubble ol { margin: 6px 0; padding-left: 22px; }
|
|
12276
|
+
.bubble code { background: rgba(127,127,127,.14); border-radius: 4px; padding: 1px 5px; font-size: 13px; font-family: ui-monospace, monospace; }
|
|
12277
|
+
.bubble pre { background: rgba(127,127,127,.1); border-radius: 8px; padding: 10px 12px; overflow-x: auto; margin: 8px 0; }
|
|
12278
|
+
.bubble pre code { background: none; padding: 0; }
|
|
12279
|
+
.bubble blockquote { margin: 6px 0; padding: 2px 12px; border-left: 3px solid rgba(127,127,127,.3); opacity: .85; }
|
|
12280
|
+
.bubble a { color: var(--sp-green); }
|
|
12281
|
+
.bubble table { border-collapse: collapse; margin: 8px 0; }
|
|
12282
|
+
.bubble th, .bubble td { border: 1px solid rgba(127,127,127,.25); padding: 4px 10px; font-size: 13px; }
|
|
12283
|
+
.bubble img { max-width: 100%; border-radius: 8px; }
|
|
12284
|
+
.bubble hr { border: 0; border-top: 1px solid rgba(127,127,127,.2); margin: 10px 0; }
|
|
12285
|
+
.typing { display: inline-flex; align-items: center; gap: 4px; padding: 4px 2px; }
|
|
12286
|
+
.typing i { width: 6px; height: 6px; border-radius: 50%; background: rgba(127,127,127,.5); animation: blink 1.2s infinite; }
|
|
12287
|
+
.typing i:nth-child(2) { animation-delay: .2s; }
|
|
12288
|
+
.typing i:nth-child(3) { animation-delay: .4s; }
|
|
12289
|
+
@keyframes blink { 0%, 80%, 100% { opacity: .3 } 40% { opacity: 1 } }
|
|
12290
|
+
.err { color: #cf222e; white-space: pre-wrap; font-size: 13px; }
|
|
12291
|
+
.msg .err { padding: 0 4px; }
|
|
12292
|
+
/* 输入区 */
|
|
12293
|
+
.chatInput { border-top: 1px solid rgba(127,127,127,.18); padding: 10px 16px calc(12px + env(safe-area-inset-bottom)); background: rgba(127,127,127,.04); }
|
|
12294
|
+
.chatInput .keyRow { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
|
|
12295
|
+
.chatInput .keyRow label { font-size: 12px; opacity: .7; white-space: nowrap; }
|
|
12296
|
+
.chatInput .keyRow input { flex: 1; border: 1px solid rgba(127,127,127,.25); border-radius: 8px; background: transparent; color: inherit; padding: 6px 10px; font-size: 13px; }
|
|
12297
|
+
.inputRow { display: flex; align-items: flex-end; gap: 8px; }
|
|
12298
|
+
.inputRow textarea { flex: 1; border: 1px solid rgba(127,127,127,.25); border-radius: 12px; background: #fff; color: inherit; padding: 10px 12px; font-size: 14px; resize: none; min-height: 44px; max-height: 140px; line-height: 1.5; }
|
|
12299
|
+
@media (prefers-color-scheme: dark) { .inputRow textarea { background: #26282c; border-color: #3a3d42; } }
|
|
12300
|
+
.inputRow textarea:focus { outline: none; border-color: var(--sp-green); }
|
|
12301
|
+
.inputRow .sendBtn { border: 0; border-radius: 12px; background: var(--sp-green); color: #fff; padding: 10px 18px; font-size: 14px; font-weight: 600; cursor: pointer; white-space: nowrap; }
|
|
12302
|
+
.inputRow .sendBtn:disabled { opacity: .5; cursor: wait; }
|
|
12303
|
+
.inputRow .sendBtn:hover:not(:disabled) { background: var(--sp-green-dim); }
|
|
12304
|
+
.hint { text-align: center; font-size: 12px; opacity: .55; padding: 20px 0; }
|
|
12264
12305
|
`;
|
|
12265
12306
|
/** 容器列表页(v1.26.2):只列已开放容器,点击进入 /c/<name> */
|
|
12266
12307
|
function publicAskListPage(cccs) {
|
|
@@ -12286,7 +12327,7 @@ function publicAskListPage(cccs) {
|
|
|
12286
12327
|
</body>
|
|
12287
12328
|
</html>`;
|
|
12288
12329
|
}
|
|
12289
|
-
/** 单容器问答页(v1.26.2):URL
|
|
12330
|
+
/** 单容器问答页(v1.26.2→v1.26.4):URL 锁定容器;聊天 UI——消息流 + 连续对话 + key 自动记忆 */
|
|
12290
12331
|
function publicAskContainerPage(ccc) {
|
|
12291
12332
|
const data = JSON.stringify({
|
|
12292
12333
|
name: ccc.name,
|
|
@@ -12298,23 +12339,32 @@ function publicAskContainerPage(ccc) {
|
|
|
12298
12339
|
<head>
|
|
12299
12340
|
<meta charset="utf-8">
|
|
12300
12341
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
12301
|
-
<title>Serenity
|
|
12342
|
+
<title>Serenity · ${ccc.name}</title>
|
|
12302
12343
|
<style>${ASK_CSS}</style>
|
|
12303
12344
|
</head>
|
|
12304
12345
|
<body>
|
|
12305
|
-
<
|
|
12306
|
-
<
|
|
12307
|
-
|
|
12308
|
-
|
|
12309
|
-
|
|
12310
|
-
|
|
12311
|
-
|
|
12312
|
-
|
|
12313
|
-
|
|
12314
|
-
<
|
|
12315
|
-
|
|
12316
|
-
<div
|
|
12317
|
-
|
|
12346
|
+
<div class="chat">
|
|
12347
|
+
<div class="chatHead">
|
|
12348
|
+
<a class="back" href="/">← 容器</a>
|
|
12349
|
+
<span class="title">Serenity · <span class="ccname">${ccc.name}</span></span>
|
|
12350
|
+
<span class="spacer"></span>
|
|
12351
|
+
<select id="role" title="问答角色"></select>
|
|
12352
|
+
<button id="newChat" class="newBtn" title="清空当前对话(不存储,刷新即失)">新对话</button>
|
|
12353
|
+
</div>
|
|
12354
|
+
|
|
12355
|
+
<div id="msgs" class="msgList"></div>
|
|
12356
|
+
|
|
12357
|
+
<div class="chatInput">
|
|
12358
|
+
<div class="keyRow" id="keyRow">
|
|
12359
|
+
<label for="key">访问 Key</label>
|
|
12360
|
+
<input id="key" type="password" placeholder="请输入访问 key(自动记忆)" autocomplete="off">
|
|
12361
|
+
</div>
|
|
12362
|
+
<div class="inputRow">
|
|
12363
|
+
<textarea id="q" placeholder="向 ${ccc.name} 提问…(Enter 发送,Shift+Enter 换行)" rows="1"></textarea>
|
|
12364
|
+
<button id="ask" class="sendBtn">发送</button>
|
|
12365
|
+
</div>
|
|
12366
|
+
</div>
|
|
12367
|
+
</div>
|
|
12318
12368
|
<script id="ask-data" type="application/json">${data}<\/script>
|
|
12319
12369
|
<script>
|
|
12320
12370
|
const CCC = JSON.parse(document.getElementById('ask-data').textContent)
|
|
@@ -12322,37 +12372,109 @@ const KEY_STORE = 'serenity-public-ask-key'
|
|
|
12322
12372
|
const keyInput = document.getElementById('key')
|
|
12323
12373
|
const roleSel = document.getElementById('role')
|
|
12324
12374
|
const btn = document.getElementById('ask')
|
|
12325
|
-
const
|
|
12375
|
+
const msgs = document.getElementById('msgs')
|
|
12376
|
+
const qInput = document.getElementById('q')
|
|
12377
|
+
const keyRow = document.getElementById('keyRow')
|
|
12326
12378
|
let sessionId = ''
|
|
12327
|
-
|
|
12379
|
+
let busy = false
|
|
12380
|
+
|
|
12381
|
+
// 角色下拉
|
|
12328
12382
|
roleSel.innerHTML = (CCC.roles || []).map((r) => '<option value="' + r + '">' + r + '</option>').join('') || '<option value="">(无角色)</option>'
|
|
12329
|
-
// key 自动从 localStorage
|
|
12330
|
-
try { const saved = localStorage.getItem(KEY_STORE); if (saved) keyInput.value = saved } catch {}
|
|
12331
|
-
|
|
12332
|
-
|
|
12383
|
+
// key 自动从 localStorage 恢复
|
|
12384
|
+
try { const saved = localStorage.getItem(KEY_STORE); if (saved) { keyInput.value = saved; keyRow.style.display = 'none' } } catch {}
|
|
12385
|
+
|
|
12386
|
+
/** 追加一条消息气泡(role: user|assistant) */
|
|
12387
|
+
function addMsg(role, htmlOrText, isHtml) {
|
|
12388
|
+
const m = document.createElement('div')
|
|
12389
|
+
m.className = 'msg ' + role
|
|
12390
|
+
const who = document.createElement('div')
|
|
12391
|
+
who.className = 'who'
|
|
12392
|
+
who.textContent = role === 'user' ? '你' : CCC.name
|
|
12393
|
+
const bubble = document.createElement('div')
|
|
12394
|
+
bubble.className = 'bubble'
|
|
12395
|
+
if (isHtml) bubble.innerHTML = htmlOrText
|
|
12396
|
+
else bubble.textContent = htmlOrText
|
|
12397
|
+
m.appendChild(who)
|
|
12398
|
+
m.appendChild(bubble)
|
|
12399
|
+
msgs.appendChild(m)
|
|
12400
|
+
msgs.scrollTop = msgs.scrollHeight
|
|
12401
|
+
return bubble
|
|
12402
|
+
}
|
|
12403
|
+
|
|
12404
|
+
/** 打字指示器(等待回答时显示) */
|
|
12405
|
+
function addTyping() {
|
|
12406
|
+
const m = document.createElement('div')
|
|
12407
|
+
m.className = 'msg assistant'
|
|
12408
|
+
const who = document.createElement('div')
|
|
12409
|
+
who.className = 'who'
|
|
12410
|
+
who.textContent = CCC.name
|
|
12411
|
+
const bubble = document.createElement('div')
|
|
12412
|
+
bubble.className = 'bubble'
|
|
12413
|
+
bubble.innerHTML = '<span class="typing"><i></i><i></i><i></i></span>'
|
|
12414
|
+
m.appendChild(who)
|
|
12415
|
+
m.appendChild(bubble)
|
|
12416
|
+
msgs.appendChild(m)
|
|
12417
|
+
msgs.scrollTop = msgs.scrollHeight
|
|
12418
|
+
return bubble
|
|
12419
|
+
}
|
|
12420
|
+
|
|
12421
|
+
async function ask() {
|
|
12422
|
+
const q = qInput.value.trim()
|
|
12333
12423
|
const key = keyInput.value.trim()
|
|
12334
12424
|
const role = roleSel.value || undefined
|
|
12335
|
-
if (!q)
|
|
12336
|
-
if (!key) {
|
|
12337
|
-
|
|
12338
|
-
|
|
12425
|
+
if (!q) return
|
|
12426
|
+
if (!key) { keyInput.focus(); return }
|
|
12427
|
+
if (busy) return
|
|
12428
|
+
// 保存 key(下次自动记忆 + 隐藏 key 行)
|
|
12429
|
+
try { localStorage.setItem(KEY_STORE, key); keyRow.style.display = 'none' } catch {}
|
|
12430
|
+
// 追加用户消息 + 打字指示
|
|
12431
|
+
addMsg('user', q, false)
|
|
12432
|
+
qInput.value = ''
|
|
12433
|
+
autoGrow()
|
|
12434
|
+
const typing = addTyping()
|
|
12435
|
+
busy = true
|
|
12339
12436
|
btn.disabled = true
|
|
12340
|
-
answer.className = 'muted'
|
|
12341
|
-
answer.textContent = '运行中…'
|
|
12342
12437
|
try {
|
|
12343
12438
|
const res = await fetch('/c/' + encodeURIComponent(CCC.name) + '/ask', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ key, role, question: q, sessionId: sessionId || undefined }) })
|
|
12344
12439
|
const data = await res.json()
|
|
12345
|
-
|
|
12346
|
-
|
|
12347
|
-
|
|
12440
|
+
typing.remove() // 移除打字指示,替换为真实回答
|
|
12441
|
+
if (!res.ok) {
|
|
12442
|
+
sessionId = ''
|
|
12443
|
+
addMsg('assistant', '⚠️ ' + (data.error || ('HTTP ' + res.status)), true)
|
|
12444
|
+
return
|
|
12445
|
+
}
|
|
12446
|
+
addMsg('assistant', data.answer_html || data.answer || '(空回答)', true)
|
|
12348
12447
|
sessionId = data.sessionId || ''
|
|
12349
12448
|
} catch (err) {
|
|
12350
|
-
|
|
12351
|
-
|
|
12449
|
+
typing.remove()
|
|
12450
|
+
addMsg('assistant', '⚠️ ' + String(err.message || err), true)
|
|
12352
12451
|
} finally {
|
|
12452
|
+
busy = false
|
|
12353
12453
|
btn.disabled = false
|
|
12454
|
+
qInput.focus()
|
|
12354
12455
|
}
|
|
12456
|
+
}
|
|
12457
|
+
|
|
12458
|
+
function autoGrow() {
|
|
12459
|
+
qInput.style.height = 'auto'
|
|
12460
|
+
qInput.style.height = Math.min(qInput.scrollHeight, 140) + 'px'
|
|
12461
|
+
}
|
|
12462
|
+
|
|
12463
|
+
btn.addEventListener('click', () => void ask())
|
|
12464
|
+
qInput.addEventListener('keydown', (e) => {
|
|
12465
|
+
if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); void ask() }
|
|
12355
12466
|
})
|
|
12467
|
+
qInput.addEventListener('input', autoGrow)
|
|
12468
|
+
// 新对话:重置 sessionId + 清空消息流(前端内存,不存储——刷新即失)
|
|
12469
|
+
document.getElementById('newChat').addEventListener('click', () => {
|
|
12470
|
+
sessionId = ''
|
|
12471
|
+
msgs.innerHTML = ''
|
|
12472
|
+
qInput.focus()
|
|
12473
|
+
})
|
|
12474
|
+
|
|
12475
|
+
// 初始欢迎消息(外层模板求值注入容器名;textContent 渲染防注入)
|
|
12476
|
+
addMsg('assistant', '你好,我是「${ccc.name}」的认知助手。有什么可以帮你的?(本对话仅当前页面有效,刷新即失)', false)
|
|
12477
|
+
qInput.focus()
|
|
12356
12478
|
<\/script>
|
|
12357
12479
|
</body>
|
|
12358
12480
|
</html>`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shgroup/dsh-serenity-hooks",
|
|
3
|
-
"version": "1.26.
|
|
3
|
+
"version": "1.26.4",
|
|
4
4
|
"description": "宁静号 ACC harness — Native Cordis 插件(DeepSeek Harness 运行时)。真实 DSH 工具注册(cc_fs/session/acc_msm 等 9 工具)+ 拦截缝机械约束(safe-mode/路径守卫/会话落盘)+ 系统提示词注入(ACC/CCE/Constraints/SKILL/Session 五块)。适配 DSH 公开版(deepseek-ai/deepseek-harness 0.1.0-rc)。",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|