@shgroup/dsh-serenity-hooks 1.27.1 → 1.27.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/index.js +21 -16
- package/lib/skiff-core.d.ts +9 -0
- package/lib/{skiff-debug-ZVbIqttn.js → skiff-debug-vLsdk7wV.js} +73 -14
- package/lib/weixin-bridge.d.ts +3 -1
- package/lib/{weixin-route-CDdlFn1E.js → weixin-route-CvAWARN3.js} +7 -3
- package/lib/weixin-route.d.ts +6 -2
- 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.27.
|
|
3
|
+
"version": "1.27.2",
|
|
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
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
|
|
2
2
|
import { a as findSerenityRoot, c as matchBlacklist, d as readHandymanConfig, i as findGitRoot, l as pathInside, n as SAFE_MODE_MARKER, o as isSafeModeOn, p as resolveInside, r as classifyPath, s as loadSerenityConfig, t as DEFAULT_SERENITY_CONFIG_PATHS, u as readBlacklist } from "./ccc-CfDrlfA7.js";
|
|
3
3
|
import { a as resolveRoleSystemPrompt, i as readSkiffRoles, l as systemPromptSource, r as isSkiffSessionId, s as roleToolWhitelist } from "./skiff-role-Dw7UKCUm.js";
|
|
4
|
-
import { C as splitModel, E as skiffRoleFor, S as requireWhitelistedModel, T as writeProgress, _ as buildRoundPrompt, a as startSkiffDebugServer, b as newStopToken, c as askSkiff, d as skiffMsmGate, f as skiffSessionInfo, g as HANDYMAN_GUIDE, h as unregisterSkiffSession, l as createSkiffAgent, m as skiffTrajectoryEnabled, n as jscSafeJsonText, o as stopSkiffDebugServer, p as skiffSessionSnapshot, r as renderSkiffMarkdown, s as stripThink, t as discoverCccs, u as getSkiffAgent, v as handymanProgressPaths, w as writeFailedStatus, x as readProgress, y as listActiveHandymen } from "./skiff-debug-
|
|
5
|
-
import { a as weixinSessionIdFor, c as checkLocalstoreGitCompliance, d as runLocalStore, i as readWeixinSettings, l as localstorePath, n as matchWeixinRoute, r as readWeixinCredential, s as LOCALSTORE_SCOPES, t as extractWeixinText, u as readGitTrack } from "./weixin-route-
|
|
4
|
+
import { C as splitModel, E as skiffRoleFor, S as requireWhitelistedModel, T as writeProgress, _ as buildRoundPrompt, a as startSkiffDebugServer, b as newStopToken, c as askSkiff, d as skiffMsmGate, f as skiffSessionInfo, g as HANDYMAN_GUIDE, h as unregisterSkiffSession, l as createSkiffAgent, m as skiffTrajectoryEnabled, n as jscSafeJsonText, o as stopSkiffDebugServer, p as skiffSessionSnapshot, r as renderSkiffMarkdown, s as stripThink, t as discoverCccs, u as getSkiffAgent, v as handymanProgressPaths, w as writeFailedStatus, x as readProgress, y as listActiveHandymen } from "./skiff-debug-vLsdk7wV.js";
|
|
5
|
+
import { a as weixinSessionIdFor, c as checkLocalstoreGitCompliance, d as runLocalStore, i as readWeixinSettings, l as localstorePath, n as matchWeixinRoute, r as readWeixinCredential, s as LOCALSTORE_SCOPES, t as extractWeixinText, u as readGitTrack } from "./weixin-route-CvAWARN3.js";
|
|
6
6
|
import { n as sendTextMessage, t as getUpdates } from "./weixin-api-b8HLmcPE.js";
|
|
7
7
|
import z from "@deepseek-ai/schemastery";
|
|
8
8
|
import { defineTool } from "@deepseek-ai/dsh-tools";
|
|
@@ -8342,7 +8342,7 @@ function registerStatusApi(ctx, opts = {}) {
|
|
|
8342
8342
|
workspace: url.searchParams.get("workspace") ?? void 0
|
|
8343
8343
|
});
|
|
8344
8344
|
const root = findSerenityRoot(workspace) ?? "";
|
|
8345
|
-
const { discoverCccs } = await import("./skiff-debug-
|
|
8345
|
+
const { discoverCccs } = await import("./skiff-debug-vLsdk7wV.js").then((n) => n.i);
|
|
8346
8346
|
sendJson$1(res, 200, { cccs: await discoverCccs(ctx, root) });
|
|
8347
8347
|
} catch (err) {
|
|
8348
8348
|
sendJson$1(res, 400, { error: err.message ?? String(err) });
|
|
@@ -8468,11 +8468,11 @@ function registerStatusApi(ctx, opts = {}) {
|
|
|
8468
8468
|
sendJson$1(res, 400, { error: chk.error });
|
|
8469
8469
|
return;
|
|
8470
8470
|
}
|
|
8471
|
-
const { readWeixinSettings } = await import("./weixin-route-
|
|
8471
|
+
const { readWeixinSettings } = await import("./weixin-route-CvAWARN3.js").then((n) => n.o);
|
|
8472
8472
|
const { weixinBridgeStatus } = await Promise.resolve().then(() => weixin_bridge_exports);
|
|
8473
8473
|
const settings = readWeixinSettings(chk.root);
|
|
8474
8474
|
const bridge = weixinBridgeStatus().find((b) => b.ccc === chk.root);
|
|
8475
|
-
const { readWeixinCredential } = await import("./weixin-route-
|
|
8475
|
+
const { readWeixinCredential } = await import("./weixin-route-CvAWARN3.js").then((n) => n.o);
|
|
8476
8476
|
const accounts = (settings.accounts ?? []).map((a) => ({
|
|
8477
8477
|
accountId: a.accountId,
|
|
8478
8478
|
name: a.name ?? void 0,
|
|
@@ -8504,7 +8504,7 @@ function registerStatusApi(ctx, opts = {}) {
|
|
|
8504
8504
|
const { fetchQRCode } = await import("./weixin-api-b8HLmcPE.js").then((n) => n.r);
|
|
8505
8505
|
const { randomUUID } = await import("node:crypto");
|
|
8506
8506
|
for (const [key, v] of weixinLogins) if (Date.now() - v.startedAt > WEIXIN_LOGIN_TTL_MS) weixinLogins.delete(key);
|
|
8507
|
-
const { readWeixinSettings } = await import("./weixin-route-
|
|
8507
|
+
const { readWeixinSettings } = await import("./weixin-route-CvAWARN3.js").then((n) => n.o);
|
|
8508
8508
|
const qr = await fetchQRCode({ botType: readWeixinSettings(root).botType ?? void 0 });
|
|
8509
8509
|
const loginKey = randomUUID();
|
|
8510
8510
|
weixinLogins.set(loginKey, {
|
|
@@ -8525,7 +8525,7 @@ function registerStatusApi(ctx, opts = {}) {
|
|
|
8525
8525
|
sendJson$1(res, 400, { error: "missing accountId" });
|
|
8526
8526
|
return;
|
|
8527
8527
|
}
|
|
8528
|
-
const { removeWeixinAccount } = await import("./weixin-route-
|
|
8528
|
+
const { removeWeixinAccount } = await import("./weixin-route-CvAWARN3.js").then((n) => n.o);
|
|
8529
8529
|
const { syncCccBridge } = await Promise.resolve().then(() => weixin_bridge_exports);
|
|
8530
8530
|
removeWeixinAccount(root, body.accountId);
|
|
8531
8531
|
syncCccBridge(ctx, root);
|
|
@@ -8538,7 +8538,7 @@ function registerStatusApi(ctx, opts = {}) {
|
|
|
8538
8538
|
sendJson$1(res, 400, { error: "invalid routes (expected [{user, role}, ...])" });
|
|
8539
8539
|
return;
|
|
8540
8540
|
}
|
|
8541
|
-
const { saveWeixinRoutes } = await import("./weixin-route-
|
|
8541
|
+
const { saveWeixinRoutes } = await import("./weixin-route-CvAWARN3.js").then((n) => n.o);
|
|
8542
8542
|
const { readSkiffRoles } = await import("./skiff-role-Dw7UKCUm.js").then((n) => n.c);
|
|
8543
8543
|
const roles = readSkiffRoles(root);
|
|
8544
8544
|
for (const r of routes) if (!roles.has(r.role)) {
|
|
@@ -8551,7 +8551,7 @@ function registerStatusApi(ctx, opts = {}) {
|
|
|
8551
8551
|
}
|
|
8552
8552
|
if (body.action === "set-enabled") {
|
|
8553
8553
|
const enabled = body.enabled === true;
|
|
8554
|
-
const { readWeixinSettings, setWeixinEnabled } = await import("./weixin-route-
|
|
8554
|
+
const { readWeixinSettings, setWeixinEnabled } = await import("./weixin-route-CvAWARN3.js").then((n) => n.o);
|
|
8555
8555
|
const { syncCccBridge } = await Promise.resolve().then(() => weixin_bridge_exports);
|
|
8556
8556
|
const settings = readWeixinSettings(root);
|
|
8557
8557
|
if (enabled && (settings.accounts ?? []).length === 0) {
|
|
@@ -8598,7 +8598,7 @@ function registerStatusApi(ctx, opts = {}) {
|
|
|
8598
8598
|
return;
|
|
8599
8599
|
}
|
|
8600
8600
|
const { pollQRStatus } = await import("./weixin-api-b8HLmcPE.js").then((n) => n.r);
|
|
8601
|
-
const { readWeixinSettings } = await import("./weixin-route-
|
|
8601
|
+
const { readWeixinSettings } = await import("./weixin-route-CvAWARN3.js").then((n) => n.o);
|
|
8602
8602
|
const settings = readWeixinSettings(login.root);
|
|
8603
8603
|
const status = await pollQRStatus({
|
|
8604
8604
|
baseUrl: void 0,
|
|
@@ -8613,7 +8613,7 @@ function registerStatusApi(ctx, opts = {}) {
|
|
|
8613
8613
|
});
|
|
8614
8614
|
return;
|
|
8615
8615
|
}
|
|
8616
|
-
const { upsertWeixinAccount, writeWeixinCredential, nextWeixinAccountId } = await import("./weixin-route-
|
|
8616
|
+
const { upsertWeixinAccount, writeWeixinCredential, nextWeixinAccountId } = await import("./weixin-route-CvAWARN3.js").then((n) => n.o);
|
|
8617
8617
|
const { syncCccBridge } = await Promise.resolve().then(() => weixin_bridge_exports);
|
|
8618
8618
|
const accountId = nextWeixinAccountId(settings);
|
|
8619
8619
|
upsertWeixinAccount(login.root, {
|
|
@@ -10576,7 +10576,9 @@ async function runAccountLoop(ctx, root, accountId, cred, loop) {
|
|
|
10576
10576
|
*
|
|
10577
10577
|
* 会话语义:`weixinSessionIdFor(fromUserId)` 固定可重建——同用户长期同一会话;
|
|
10578
10578
|
* 进程内已有(getSkiffAgent 命中)→ 延续;无(首次/进程重启)→ createSkiffAgent
|
|
10579
|
-
*
|
|
10579
|
+
* 固定 id resume-or-create(v1.27.2):磁盘已有持久化 log → resume(历史延续,
|
|
10580
|
+
* 重启后记忆保留——真正的"同用户长期延续");无 log(首次)→ create。
|
|
10581
|
+
* "新的对话已开始"通知仅真正首次(create)时发送;resume/进程内延续不发。
|
|
10580
10582
|
*/
|
|
10581
10583
|
async function handleIncoming(ctx, root, _accountId, cred, msg) {
|
|
10582
10584
|
const fromUserId = msg.from_user_id;
|
|
@@ -10595,13 +10597,13 @@ async function handleIncoming(ctx, root, _accountId, cred, msg) {
|
|
|
10595
10597
|
}
|
|
10596
10598
|
const sessionId = weixinSessionIdFor(fromUserId);
|
|
10597
10599
|
const existing = getSkiffAgent(sessionId);
|
|
10598
|
-
const recreated = !existing;
|
|
10599
10600
|
const hc = readHandymanConfig(root);
|
|
10600
10601
|
const ref = existing ? {
|
|
10601
10602
|
agent: existing,
|
|
10602
|
-
sessionId
|
|
10603
|
+
sessionId,
|
|
10604
|
+
resumed: true
|
|
10603
10605
|
} : await createSkiffAgent(ctx, root, roleName, role, hc?.defaultModel, sessionId);
|
|
10604
|
-
if (
|
|
10606
|
+
if (!ref.resumed) await sendTextMessage({
|
|
10605
10607
|
baseUrl: cred.baseUrl,
|
|
10606
10608
|
token: cred.token,
|
|
10607
10609
|
toUserId: fromUserId,
|
|
@@ -10618,7 +10620,10 @@ async function handleIncoming(ctx, root, _accountId, cred, msg) {
|
|
|
10618
10620
|
contextToken: msg.context_token
|
|
10619
10621
|
});
|
|
10620
10622
|
} catch (err) {
|
|
10621
|
-
|
|
10623
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
10624
|
+
console.log(`[serenity-hooks] weixin-bridge error (ccc=${root}): ${msg}`);
|
|
10625
|
+
const stack = err instanceof Error ? err.stack : void 0;
|
|
10626
|
+
if (stack) console.log(`[serenity-hooks] weixin-bridge stack:\n${stack.slice(0, 1500)}`);
|
|
10622
10627
|
}
|
|
10623
10628
|
}
|
|
10624
10629
|
/**
|
package/lib/skiff-core.d.ts
CHANGED
|
@@ -31,10 +31,19 @@ export interface SkiffAgentRef {
|
|
|
31
31
|
handle: AgentHandle;
|
|
32
32
|
agent: Agent;
|
|
33
33
|
sessionId: string;
|
|
34
|
+
/** true = 从持久化恢复既有会话(历史延续,非新对话);false = 新建(首次/无持久化) */
|
|
35
|
+
resumed: boolean;
|
|
34
36
|
}
|
|
35
37
|
/**
|
|
36
38
|
* 创建 Skiff agent:标准 DSH agent + cwd=CCC root + 角色模型 +
|
|
37
39
|
* standard preset(平台工具面)+ scoped 系统提示词(基础提示词 + CCC 定义段,全替换 ACC 默认注入)。
|
|
40
|
+
*
|
|
41
|
+
* **固定 sessionId 的 resume-or-create(v1.27.2,微信桥 id collision 修复)**:
|
|
42
|
+
* 指定 sessionId 且磁盘已有持久化 log → `ctx.agents.resume`(DSH 持久化语义:
|
|
43
|
+
* sessionId 即身份,已持久化会话必须 resume——历史 + turn 续号延续,同用户长期记忆保留);
|
|
44
|
+
* 无 log(首次)/持久化未配置 → `ctx.agents.create`(新建)。不指定 sessionId →
|
|
45
|
+
* 随机 id 恒 create(ACP/调试页默认路径)。
|
|
46
|
+
*
|
|
38
47
|
* @param sessionId 指定会话 id(可选;微信桥等外部面用固定 id 实现用户↔会话长期映射——
|
|
39
48
|
* 不传则随机生成 skiff-<role>-<uuid>,ACP/调试页默认路径)
|
|
40
49
|
*/
|
|
@@ -251,6 +251,13 @@ const SKIFF_PRESET = "standard";
|
|
|
251
251
|
/**
|
|
252
252
|
* 创建 Skiff agent:标准 DSH agent + cwd=CCC root + 角色模型 +
|
|
253
253
|
* standard preset(平台工具面)+ scoped 系统提示词(基础提示词 + CCC 定义段,全替换 ACC 默认注入)。
|
|
254
|
+
*
|
|
255
|
+
* **固定 sessionId 的 resume-or-create(v1.27.2,微信桥 id collision 修复)**:
|
|
256
|
+
* 指定 sessionId 且磁盘已有持久化 log → `ctx.agents.resume`(DSH 持久化语义:
|
|
257
|
+
* sessionId 即身份,已持久化会话必须 resume——历史 + turn 续号延续,同用户长期记忆保留);
|
|
258
|
+
* 无 log(首次)/持久化未配置 → `ctx.agents.create`(新建)。不指定 sessionId →
|
|
259
|
+
* 随机 id 恒 create(ACP/调试页默认路径)。
|
|
260
|
+
*
|
|
254
261
|
* @param sessionId 指定会话 id(可选;微信桥等外部面用固定 id 实现用户↔会话长期映射——
|
|
255
262
|
* 不传则随机生成 skiff-<role>-<uuid>,ACP/调试页默认路径)
|
|
256
263
|
*/
|
|
@@ -258,19 +265,12 @@ async function createSkiffAgent(ctx, root, roleName, role, defaultModel, session
|
|
|
258
265
|
if (!ctx.agents) throw new Error("skiff: ctx.agents unavailable");
|
|
259
266
|
const model = role.model?.trim() || defaultModel || "";
|
|
260
267
|
const id = sessionId ?? `skiff-${roleName}-${randomUUID()}`;
|
|
261
|
-
const
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
setup: async (agentCtx) => {
|
|
268
|
-
try {
|
|
269
|
-
await agentCtx.get("agentPresets")?.mount?.(agentCtx, SKIFF_PRESET);
|
|
270
|
-
} catch {}
|
|
271
|
-
},
|
|
272
|
-
...model ? { agentOptions: splitModel(model) } : {}
|
|
273
|
-
});
|
|
268
|
+
const setup = async (agentCtx) => {
|
|
269
|
+
try {
|
|
270
|
+
await agentCtx.get("agentPresets")?.mount?.(agentCtx, SKIFF_PRESET);
|
|
271
|
+
} catch {}
|
|
272
|
+
};
|
|
273
|
+
const handle = await createOrResumeAgent(ctx, id, root, model, setup, sessionId !== void 0);
|
|
274
274
|
const agent = handle.agent;
|
|
275
275
|
let cccPrompt = "";
|
|
276
276
|
try {
|
|
@@ -291,9 +291,68 @@ async function createSkiffAgent(ctx, root, roleName, role, defaultModel, session
|
|
|
291
291
|
return {
|
|
292
292
|
handle,
|
|
293
293
|
agent,
|
|
294
|
-
sessionId: id
|
|
294
|
+
sessionId: id,
|
|
295
|
+
resumed: handle.resumed
|
|
295
296
|
};
|
|
296
297
|
}
|
|
298
|
+
/**
|
|
299
|
+
* resume-or-create 分派:固定 id → 优先 resume(持久化历史延续),失败降级 create;
|
|
300
|
+
* 随机 id(无固定 sessionId)→ 恒 create。返回 handle + resumed 标志。
|
|
301
|
+
*/
|
|
302
|
+
async function createOrResumeAgent(ctx, id, root, model, setup, fixedId) {
|
|
303
|
+
if (!fixedId) return {
|
|
304
|
+
...await ctx.agents.create({
|
|
305
|
+
sessionId: id,
|
|
306
|
+
meta: {
|
|
307
|
+
cwd: root,
|
|
308
|
+
agentPreset: SKIFF_PRESET
|
|
309
|
+
},
|
|
310
|
+
setup,
|
|
311
|
+
...model ? { agentOptions: splitModel(model) } : {}
|
|
312
|
+
}),
|
|
313
|
+
resumed: false
|
|
314
|
+
};
|
|
315
|
+
const agentsWithResume = ctx.agents;
|
|
316
|
+
if (typeof agentsWithResume.resume !== "function") return {
|
|
317
|
+
...await ctx.agents.create({
|
|
318
|
+
sessionId: id,
|
|
319
|
+
meta: {
|
|
320
|
+
cwd: root,
|
|
321
|
+
agentPreset: SKIFF_PRESET
|
|
322
|
+
},
|
|
323
|
+
setup,
|
|
324
|
+
...model ? { agentOptions: splitModel(model) } : {}
|
|
325
|
+
}),
|
|
326
|
+
resumed: false
|
|
327
|
+
};
|
|
328
|
+
try {
|
|
329
|
+
return {
|
|
330
|
+
...await agentsWithResume.resume({
|
|
331
|
+
resumeSessionId: id,
|
|
332
|
+
setup,
|
|
333
|
+
...model ? { agentOptions: splitModel(model) } : {}
|
|
334
|
+
}),
|
|
335
|
+
resumed: true
|
|
336
|
+
};
|
|
337
|
+
} catch (err) {
|
|
338
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
339
|
+
const stack = err instanceof Error ? err.stack ?? "" : "";
|
|
340
|
+
console.log(`[serenity-hooks] skiff resume 失败降级 create (id=${id}): ${msg}`);
|
|
341
|
+
if (stack) console.log(`[serenity-hooks] skiff resume stack:\n${stack.slice(0, 1200)}`);
|
|
342
|
+
return {
|
|
343
|
+
...await ctx.agents.create({
|
|
344
|
+
sessionId: id,
|
|
345
|
+
meta: {
|
|
346
|
+
cwd: root,
|
|
347
|
+
agentPreset: SKIFF_PRESET
|
|
348
|
+
},
|
|
349
|
+
setup,
|
|
350
|
+
...model ? { agentOptions: splitModel(model) } : {}
|
|
351
|
+
}),
|
|
352
|
+
resumed: false
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
}
|
|
297
356
|
/** 等待 agent 空闲(agent/status → idle);无超时(agent 工作多久等多久,handyman 同款) */
|
|
298
357
|
function waitIdle(ctx, agent) {
|
|
299
358
|
return new Promise((resolve) => {
|
package/lib/weixin-bridge.d.ts
CHANGED
|
@@ -19,7 +19,9 @@ import { type WeixinAccountCredential } from './weixin-route.js';
|
|
|
19
19
|
*
|
|
20
20
|
* 会话语义:`weixinSessionIdFor(fromUserId)` 固定可重建——同用户长期同一会话;
|
|
21
21
|
* 进程内已有(getSkiffAgent 命中)→ 延续;无(首次/进程重启)→ createSkiffAgent
|
|
22
|
-
*
|
|
22
|
+
* 固定 id resume-or-create(v1.27.2):磁盘已有持久化 log → resume(历史延续,
|
|
23
|
+
* 重启后记忆保留——真正的"同用户长期延续");无 log(首次)→ create。
|
|
24
|
+
* "新的对话已开始"通知仅真正首次(create)时发送;resume/进程内延续不发。
|
|
23
25
|
*/
|
|
24
26
|
export declare function handleIncoming(ctx: Context, root: string, _accountId: string, cred: WeixinAccountCredential, msg: {
|
|
25
27
|
from_user_id?: string;
|
|
@@ -282,7 +282,8 @@ function runLocalStore(root, args) {
|
|
|
282
282
|
* 职责(零 DSH 依赖,可独立单测):
|
|
283
283
|
* - 读取 CCC 的 weixin 配置(.opencode/serenity.json weixin 段——结构/路由/开关)
|
|
284
284
|
* - 读取/写入 CCC localstore 的账号凭据(weixin.accounts.<accountId>.token/.baseUrl/.userId)
|
|
285
|
-
* - 微信用户 → skiff 会话 id 映射(固定可重建:skiff-weixin-<sha256(userid)>.slice(
|
|
285
|
+
* - 微信用户 → skiff 会话 id 映射(固定可重建:skiff-weixin-<sha256(userid)>.slice(1, 17);
|
|
286
|
+
* v1.27.3 错位一位避开损坏 log)
|
|
286
287
|
* - 路由匹配(exact user → 通配 * 兜底)
|
|
287
288
|
*
|
|
288
289
|
* 配置归属(S142 用户拍板):**CCC 级**——serenity.json 结构 + localstore 凭据分离;
|
|
@@ -312,9 +313,12 @@ function accountKeyPart(accountId) {
|
|
|
312
313
|
}
|
|
313
314
|
/** 微信桥 skiff 会话 id 前缀(seams 旁路判定;对外面纯净——守卫识别外部面) */
|
|
314
315
|
const WEIXIN_SESSION_PREFIX = "skiff-weixin-";
|
|
315
|
-
/** 微信用户 → 固定会话 id
|
|
316
|
+
/** 微信用户 → 固定会话 id(同用户长期同一会话,记忆延续;多用户天然隔离)。
|
|
317
|
+
* **v1.27.3 错位一位(用户拍板)**:`.slice(0, 16)` → `.slice(1, 17)`——旧规则生成的
|
|
318
|
+
* 固定 id 已与磁盘损坏的持久化 log 绑定(dsh 不可硬删,create 同 id 必撞)→
|
|
319
|
+
* 新规则下同用户生成**全新 id**,避开损坏 log;固定可重建语义不变(同用户恒同 id)。 */
|
|
316
320
|
function weixinSessionIdFor(fromUserId) {
|
|
317
|
-
const digest = createHash("sha256").update(fromUserId).digest("hex").slice(
|
|
321
|
+
const digest = createHash("sha256").update(fromUserId).digest("hex").slice(1, 17);
|
|
318
322
|
return `${WEIXIN_SESSION_PREFIX}${digest}`;
|
|
319
323
|
}
|
|
320
324
|
/**
|
package/lib/weixin-route.d.ts
CHANGED
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
* 职责(零 DSH 依赖,可独立单测):
|
|
5
5
|
* - 读取 CCC 的 weixin 配置(.opencode/serenity.json weixin 段——结构/路由/开关)
|
|
6
6
|
* - 读取/写入 CCC localstore 的账号凭据(weixin.accounts.<accountId>.token/.baseUrl/.userId)
|
|
7
|
-
* - 微信用户 → skiff 会话 id 映射(固定可重建:skiff-weixin-<sha256(userid)>.slice(
|
|
7
|
+
* - 微信用户 → skiff 会话 id 映射(固定可重建:skiff-weixin-<sha256(userid)>.slice(1, 17);
|
|
8
|
+
* v1.27.3 错位一位避开损坏 log)
|
|
8
9
|
* - 路由匹配(exact user → 通配 * 兜底)
|
|
9
10
|
*
|
|
10
11
|
* 配置归属(S142 用户拍板):**CCC 级**——serenity.json 结构 + localstore 凭据分离;
|
|
@@ -15,7 +16,10 @@ import { type WeixinSettings, type WeixinRouteConfig, type WeixinAccountConfig }
|
|
|
15
16
|
export declare const WEIXIN_SESSION_PREFIX = "skiff-weixin-";
|
|
16
17
|
/** 判定 sessionId 是否为微信桥会话(外部面——输出守卫/轨迹隐藏生效) */
|
|
17
18
|
export declare function isWeixinSessionId(sessionId: string | undefined): boolean;
|
|
18
|
-
/** 微信用户 → 固定会话 id
|
|
19
|
+
/** 微信用户 → 固定会话 id(同用户长期同一会话,记忆延续;多用户天然隔离)。
|
|
20
|
+
* **v1.27.3 错位一位(用户拍板)**:`.slice(0, 16)` → `.slice(1, 17)`——旧规则生成的
|
|
21
|
+
* 固定 id 已与磁盘损坏的持久化 log 绑定(dsh 不可硬删,create 同 id 必撞)→
|
|
22
|
+
* 新规则下同用户生成**全新 id**,避开损坏 log;固定可重建语义不变(同用户恒同 id)。 */
|
|
19
23
|
export declare function weixinSessionIdFor(fromUserId: string): string;
|
|
20
24
|
/**
|
|
21
25
|
* 读取 CCC 微信桥配置(未配置/未启用 → 归一默认)。
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shgroup/dsh-serenity-hooks",
|
|
3
|
-
"version": "1.27.
|
|
3
|
+
"version": "1.27.2",
|
|
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": {
|