@shgroup/dsh-serenity-hooks 1.84.0 → 1.86.0
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/{ccc-roots-4LwGLCXa.js → ccc-roots-BI_4UVcj.js} +1 -1
- package/lib/client.js +150 -95
- package/lib/im/channels.d.ts +33 -0
- package/lib/im/hook.d.ts +17 -0
- package/lib/im/log-scan.d.ts +53 -0
- package/lib/im/route.d.ts +8 -1
- package/lib/index.js +465 -38
- package/lib/{message-source-CfqdGIi2.js → message-source-DRkQwfgh.js} +2 -2
- package/lib/{profile-CiRWh2a2.js → profile-vHheCJiU.js} +17 -6
- package/lib/{route-Dr0SFD8A.js → route-GtYJdR06.js} +7 -0
- package/lib/seams/context.d.ts +13 -0
- package/lib/{session-BF4C3hJL.js → session-DZXSLLEx.js} +3 -3
- package/lib/{settings-Dj4_ppTC.js → settings-H7TVDayZ.js} +1 -1
- package/lib/tools/im-docs.d.ts +20 -0
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { r as cccRootForCwd } from "./ccc-roots-
|
|
1
|
+
import { r as cccRootForCwd } from "./ccc-roots-BI_4UVcj.js";
|
|
2
2
|
import { _ as resolveInside, g as readUtf8 } from "./ccc-CyYJL4F2.js";
|
|
3
|
-
import {
|
|
3
|
+
import { D as parseTrajectoryCode, M as sessionsRoot, S as getLastActiveSessionInfo, j as sessionEvents, x as getActiveSessionInfo } from "./profile-vHheCJiU.js";
|
|
4
4
|
import { dirname, join } from "node:path";
|
|
5
5
|
import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, statSync, writeFileSync } from "node:fs";
|
|
6
6
|
import { fileURLToPath } from "node:url";
|
|
@@ -501,12 +501,16 @@ function findSession(sessionsDir, key) {
|
|
|
501
501
|
const all = readAllSessions(sessionsDir);
|
|
502
502
|
const byName = all.find((s) => s.dirName === key);
|
|
503
503
|
if (byName) return byName;
|
|
504
|
-
const
|
|
504
|
+
const byCodeHits = all.filter((s) => parseTrajectoryCode(s.dirName) === key);
|
|
505
|
+
if (byCodeHits.length > 1) throw new Error(`编码「${key}」在本 CCC 有 ${byCodeHits.length} 条轨迹同时占用,无法确定要操作哪一条:\n` + byCodeHits.map((s) => ` · ${s.dirName}`).join("\n") + "\n认知轨迹的编码是**终身身份**(AXIOM 3),重码意味着历史存量有问题 —— ⛔ 不会替你任选其一。\n⇒ 改用**完整目录名**指定(上列任一)。");
|
|
506
|
+
const byCode = byCodeHits[0];
|
|
505
507
|
if (byCode) return byCode;
|
|
506
508
|
const padded = key.match(/^S(\d{1,})$/);
|
|
507
509
|
if (padded) {
|
|
508
510
|
const want = `S${padded[1].padStart(3, "0")}`;
|
|
509
|
-
const
|
|
511
|
+
const byPaddedHits = all.filter((s) => parseTrajectoryCode(s.dirName) === want);
|
|
512
|
+
if (byPaddedHits.length > 1) throw new Error(`编码「${want}」(由「${key}」补零而来)有 ${byPaddedHits.length} 条轨迹同时占用,无法确定:\n` + byPaddedHits.map((s) => ` · ${s.dirName}`).join("\n") + "\n⇒ 改用**完整目录名**指定。");
|
|
513
|
+
const byPadded = byPaddedHits[0];
|
|
510
514
|
if (byPadded) return byPadded;
|
|
511
515
|
}
|
|
512
516
|
const byUid = all.find((s) => readTrajectoryUid(s.path) === key);
|
|
@@ -576,7 +580,12 @@ function createSession(opts) {
|
|
|
576
580
|
}
|
|
577
581
|
if (issue) {
|
|
578
582
|
if (issue.length > 100) throw new Error(`issue too long: ${issue.length} chars (max 100)`);
|
|
579
|
-
const
|
|
583
|
+
const issueCode = sanitizeDirName(issue);
|
|
584
|
+
if (!isValidTrajectoryCode(issueCode)) throw new Error(`issue「${issue}」会被当成本轨迹的**编码**(目录名 = 日期--<编码>),但它不是合法编码:允许 [A-Za-z0-9._-]、首字符须字母或数字、长度 ≤64,且不得含中文与 "--"。`);
|
|
585
|
+
const issueDup = findCodeCollision(sessionsDir, issueCode);
|
|
586
|
+
if (issueDup !== null) throw new Error(`issue「${issue}」会被当成本轨迹的**编码**,而它已被占用:${issueDup}\n认知轨迹的编码是**终身身份**(AXIOM 3),归档不会释放它。
|
|
587
|
+
⇒ 换一个工单号,或用 \`create --desc … --id <新码>\` 显式指定。`);
|
|
588
|
+
const dirName = `${datePrefix}--${issueCode}`;
|
|
580
589
|
const sessionPath = join(sessionsDir, dirName);
|
|
581
590
|
if (!dryRun && existsSync(sessionPath)) throw new Error(`Session directory already exists: "${dirName}"`);
|
|
582
591
|
if (dryRun) return {
|
|
@@ -1137,8 +1146,10 @@ function listTrajectoryConstraints(root) {
|
|
|
1137
1146
|
* 静默投到一条相近的轨迹上——那正是最难查的一类串味。
|
|
1138
1147
|
*/
|
|
1139
1148
|
function findDirNameByCode(root, code) {
|
|
1140
|
-
|
|
1141
|
-
|
|
1149
|
+
const hits = [];
|
|
1150
|
+
for (const name of activeTrajectoryDirNames(root)) if (parseTrajectoryCode(name) === code) hits.push(name);
|
|
1151
|
+
if (hits.length > 1) throw new Error(`编码「${code}」在本 CCC 有 ${hits.length} 条轨迹同时占用,无法确定要施加到哪一条:\n` + hits.map((n) => ` · ${n}`).join("\n") + "\n编码是终身身份(AXIOM 3)⇒ 不替你任选其一。改用**完整目录名**指定。");
|
|
1152
|
+
return hits[0] ?? null;
|
|
1142
1153
|
}
|
|
1143
1154
|
/**
|
|
1144
1155
|
* **会话级**判据(J2):这个 dsh 会话是不是 轨迹约束会话 —— 唯一入口。
|
|
@@ -1211,4 +1222,4 @@ function replacesDefaultIdentity(profile) {
|
|
|
1211
1222
|
return hasFile || hasInline;
|
|
1212
1223
|
}
|
|
1213
1224
|
//#endregion
|
|
1214
|
-
export {
|
|
1225
|
+
export { resolveSessionByTitle as A, readTrajectoryFile as B, listActiveTrajectories as C, parseTrajectoryCode as D, parseSessionContextFromEvents as E, summarize as F, localFileStamp as H, trajectoryDescOf as I, useSession as L, sessionsRoot as M, setActiveSessionInfo as N, readActiveSessionMd as O, showSession as P, TRAJECTORY_FILENAME as R, getLastActiveSessionInfo as S, namingTitleFor as T, localHuman as U, isoLocal as V, localIdStamp as W, clearActiveSessionInfo as _, profile_exports as a, findSession as b, replacesDefaultIdentity as c, trajectoryDirNameForSession as d, unregisterTrajectorySession as f, archiveSession as g, UID_FILENAME as h, listTrajectoryConstraints as i, sessionEvents as j, readTrajectoryUid as k, trajectoryConstraintForSession as l, DEFAULT_SESSION_SCOPE as m, findDirNameByCode as n, readTrajectoryConstraintAt as o, COGNITIVE_TRAJECTORY_ACTIONS as p, isTrajectoryConstrained as r, readTrajectoryConstraintByCode as s, TRAJECTORY_CONSTRAINT_FILENAME as t, registerTrajectorySession as u, createSession as v, listSessions as w, getActiveSessionInfo as x, extractSessionMdPathFromText as y, TRAJECTORY_LEGACY_FILENAMES as z };
|
|
@@ -172,6 +172,13 @@ function normalizeImSection(w, d) {
|
|
|
172
172
|
* ⚠️ 2026-10-19 起它是 {@link readImSettings} 的**薄别名**(签名与返回形状不变):
|
|
173
173
|
* 旧调用点无需改动,但**配置来源已经统一**——`im` 段优先、`weixin` 段回退。
|
|
174
174
|
* 保留名字是为了让既有调用点与测试**逐字不动**(P1 是纯重构,读数必须不变)。
|
|
175
|
+
*
|
|
176
|
+
* 🔴 2026-10-22:**返回类型由 `WeixinSettings` 改为 `ImSettings`**。
|
|
177
|
+
* 此前实现返回的就是 `readImSettings(...)`(已是归一形态:`accounts[].channel` 必填),
|
|
178
|
+
* 却把它断言成旧类型 —— 于是类型层"看不见"`channel` 字段,
|
|
179
|
+
* 调用方写 `a.channel` 会报 TS2339,而**运行时它一直在那儿**。
|
|
180
|
+
* ⇒ 那是**类型声明在撒谎**,不是调用方写错。改成真实类型后,多账户/多渠道的读侧才敢用它。
|
|
181
|
+
* ⚠️ 附带效应:`WeixinSettings` 的旧形状调用方若用到旧字段,会在此处暴露(好事,早暴露)。
|
|
175
182
|
*/
|
|
176
183
|
function readWeixinSettings(root, paths = DEFAULT_SERENITY_CONFIG_PATHS) {
|
|
177
184
|
return readImSettings(root, paths);
|
package/lib/seams/context.d.ts
CHANGED
|
@@ -21,6 +21,19 @@ export declare function accIdentityText(root: string, configPaths?: string[], en
|
|
|
21
21
|
* 不再重复注入同一内容(token 双倍浪费,见 S134 注入方案梳理)。
|
|
22
22
|
*/
|
|
23
23
|
export declare function accMessage(root: string, configPaths: string[], entrySkillMaxChars: number): UserMessage;
|
|
24
|
+
/**
|
|
25
|
+
* 这条会话的历史里**是否已经有** ACC 身份横幅(= 判据的唯一权威)。
|
|
26
|
+
*
|
|
27
|
+
* 🔴 这是本条修复的核心:**"注入过没有"是会话的属性,不是进程的属性。**
|
|
28
|
+
* 会话历史随会话走(落盘、重启后仍在),进程内状态随进程死。
|
|
29
|
+
*
|
|
30
|
+
* ⚠️ 读不到 events(受限宿主 / 投影未就绪)⇒ 返回 `false`(退回"注入一次")。
|
|
31
|
+
* 这是**偏保守**的选择:多注入一条横幅(可见、可清理)远好于
|
|
32
|
+
* **永远不再注入**(陈旧会话里 ACC 身份彻底缺失,且零信号)。
|
|
33
|
+
*
|
|
34
|
+
* @param session 目标会话(`sessionEvents` 能读的形状)
|
|
35
|
+
*/
|
|
36
|
+
export declare function hasAccBanner(session: unknown): boolean;
|
|
24
37
|
/**
|
|
25
38
|
* 重启恢复的根会话判定(S134 需求):
|
|
26
39
|
* 只有"conversation 根会话"才自动恢复最近激活的宁静号会话——
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { n as agentCwdFor, r as cccRootForCwd, s as hostAgents } from "./ccc-roots-
|
|
1
|
+
import { n as agentCwdFor, r as cccRootForCwd, s as hostAgents } from "./ccc-roots-BI_4UVcj.js";
|
|
2
2
|
import { g as readUtf8, o as isSafeModeOn, p as readCognitiveTrajectorySkills, u as readBlacklist } from "./ccc-CyYJL4F2.js";
|
|
3
|
-
import {
|
|
3
|
+
import { M as sessionsRoot, O as readActiveSessionMd, V as isoLocal, d as trajectoryDirNameForSession, f as unregisterTrajectorySession$1, l as trajectoryConstraintForSession, m as DEFAULT_SESSION_SCOPE, o as readTrajectoryConstraintAt, u as registerTrajectorySession$1 } from "./profile-vHheCJiU.js";
|
|
4
4
|
import { a as readGitTrack, i as localstorePath } from "./service-DDmHSglV.js";
|
|
5
|
-
import { d as constraintCognitiveTrajectory, m as profileMsmWhitelist, n as PLUGIN_SOURCE, o as readLastBound, p as createProfilePromptReader, u as buildTrajectoryBasePrompt, v as ACC_VERSION } from "./message-source-
|
|
5
|
+
import { d as constraintCognitiveTrajectory, m as profileMsmWhitelist, n as PLUGIN_SOURCE, o as readLastBound, p as createProfilePromptReader, u as buildTrajectoryBasePrompt, v as ACC_VERSION } from "./message-source-DRkQwfgh.js";
|
|
6
6
|
import { basename, dirname, join, resolve } from "node:path";
|
|
7
7
|
import { chmodSync, existsSync, mkdirSync, readFileSync, readdirSync, renameSync, statSync, writeFileSync } from "node:fs";
|
|
8
8
|
import { createUserMessage } from "@deepseek-ai/dsh-llm";
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* tools/im-docs.ts — 「IM 桥怎么用、怎么配路由」的**手册正文**(2026-10-22)
|
|
3
|
+
*
|
|
4
|
+
* ## 为什么需要这一章(owner 原话)
|
|
5
|
+
*
|
|
6
|
+
* 「我在测试飞书,发现 ACC 没提供 IM 桥使用说明和账户查询方法,**导致 CCC 没办法自己配路由**,
|
|
7
|
+
* 这个要完善下」+「配路由需要的是**账户到轨迹**,轨迹 CCC 知道,**账户 CCC 不知道**,
|
|
8
|
+
* 需要有个能力让 CCC 查询用户配好的账户」。
|
|
9
|
+
*
|
|
10
|
+
* ⇒ 两件事被同时指出来:**没有说明面**(只能猜配置形状)+ **没有查询面**(拿不到对方 id)。
|
|
11
|
+
* 后者已由 `im-bridge action=contacts` 兑现;本章补前者。
|
|
12
|
+
*
|
|
13
|
+
* ## 🔴 写这一章时守的两条纪律
|
|
14
|
+
*
|
|
15
|
+
* 1. **只描述已经建成的东西**(D179):本章出现的每个字段、每个动作,都必须在实现里存在。
|
|
16
|
+
* 写"打算做"的功能进手册 = 教用户按图施工然后把自己锁死。
|
|
17
|
+
* 2. **指针从读者真正打开的那个工具发出**(D178):读这一章的人是 **CCC 的 agent**,
|
|
18
|
+
* 它手边常用的入口是 `im-bridge`(工具描述已指向本章)。⛔ 不能只藏在 container_admin 里。
|
|
19
|
+
*/
|
|
20
|
+
export declare const IM_BRIDGE_GUIDE = "# IM \u6865\uFF08im-bridge\uFF09\u2014\u2014 \u600E\u4E48\u7528\u3001\u600E\u4E48\u914D\u3001\u600E\u4E48\u67E5\n\n## \u4E00\u3001\u5B83\u662F\u4EC0\u4E48\n\n\u4E00\u4E2A CCC \u901A\u8FC7 IM \u6E20\u9053\uFF08\u5FAE\u4FE1 / \u98DE\u4E66\uFF09\u8DDF\u5BB6\u4EBA\u6536\u53D1\u6D88\u606F\u7684\u80FD\u529B\u3002\n**\u53EA\u4F5C\u7528\u4E8E\u672C\u5BB9\u5668**\u2014\u2014\u6CA1\u6709\"\u76EE\u6807\u5BB9\u5668\"\u53C2\u6570\uFF08\u8DE8 CCC \u53D1\u9001\u4E0D\u5728\u80FD\u529B\u9762\uFF09\u3002\n\n\u5DE5\u5177\u5728**\u672A\u914D\u7F6E\u4EFB\u4F55 IM \u6E20\u9053\u65F6\u6839\u672C\u4E0D\u53EF\u89C1**\uFF08\u4E0D\u662F\"\u770B\u5F97\u5230\u4F46\u88AB\u62D2\"\uFF09\u3002\n\u21D2 \u4F60\u770B\u5230\u8FD9\u4E2A\u5DE5\u5177\uFF0C\u8BF4\u660E\u672C CCC \u5DF2\u914D\u4E86\u81F3\u5C11\u4E00\u4E2A\u6E20\u9053\u3002\n\n## \u4E8C\u3001\u4E94\u4E2A\u52A8\u4F5C\n\n| \u52A8\u4F5C | \u7528\u9014 | \u5173\u952E\u53C2\u6570 |\n|---|---|---|\n| `send` | \u53D1\u4E00\u6761\u6587\u672C | `user`\uFF08\u5BF9\u65B9\uFF09\uFF0B `text` |\n| `send-file` | \u53D1\u672C\u5BB9\u5668\u5185\u7684\u4E00\u4E2A\u6587\u4EF6 | `user` \uFF0B `file`\uFF08**CCC \u6839\u76F8\u5BF9\u8DEF\u5F84**\uFF09\uFF0B \u53EF\u9009 `caption` |\n| `users` | \u5DF2\u914D\u7684**\u522B\u540D**\u8868 | \u2014 |\n| `status` | \u6E20\u9053\u5065\u5EB7 \uFF0B **\u8D26\u53F7** \uFF0B **\u5F53\u524D\u8DEF\u7531**\uFF08\u542B\u6BCF\u6761\u8DEF\u7531\u7684\u76EE\u6807\u662F\u5426\u5B58\u5728\uFF09 | \u2014 |\n| `contacts` | **\u8DDF\u672C\u5BB9\u5668\u6709\u8FC7\u5F80\u6765\u7684\u4EBA**\uFF08\u542B\u5BF9\u65B9 id\uFF09\uFF0B \u672A\u914D\u8DEF\u7531\u7684 \uFF0F \u914D\u4E86\u5374\u6CA1\u5F80\u6765\u7684 | \u2014 |\n\n\u26A0\uFE0F \u6E20\u9053\u4E0D\u4E00\u5B9A\u652F\u6301\u5168\u90E8\u52A8\u4F5C\uFF08\u4F8B\u5982\u98DE\u4E66\u76EE\u524D\u4E0D\u652F\u6301 `send-file`\uFF0C\u4F1A\u5982\u5B9E\u8FD4\u56DE `ACTION_UNSUPPORTED`\uFF09\u3002\n**\u5982\u5B9E\u8FD4\u56DE\"\u4E0D\u652F\u6301\"\u6BD4\u5047\u88C5\u652F\u6301\u597D**\u2014\u2014\u540E\u8005\u4F1A\u5F97\u5230\u4E00\u6761\"\u53D1\u51FA\u53BB\u4F46\u5BF9\u65B9\u6536\u4E0D\u5230\"\u7684\u9759\u9ED8\u6545\u969C\u3002\n\n## \u4E09\u3001\uD83D\uDD34 \u914D\u8DEF\u7531\uFF1A\u5148 `contacts`\uFF0C\u518D\u5199\uFF0C\u518D `status` \u81EA\u68C0\n\n\u8DEF\u7531\u7684\u5F62\u72B6\uFF08`.opencode/serenity.json` \u7684 `im.routes`\uFF09\uFF1A\n\n```json\n{\n \"im\": {\n \"enabled\": true,\n \"accounts\": [\n { \"accountId\": \"wechat-1\", \"channel\": \"weixin\", \"enabled\": true },\n { \"accountId\": \"feishu-1\", \"channel\": \"feishu\", \"enabled\": true }\n ],\n \"routes\": [\n { \"user\": \"o9cq\u2026@im.wechat\", \"trajectory\": \"zhaocai-xingzai\" },\n { \"user\": \"ou_xxxxxxxx\", \"trajectory\": \"llm-intel\" }\n ]\n }\n}\n```\n\n- `user` = **\u5BF9\u65B9\u5728\u8BE5\u6E20\u9053\u5185\u7684 id**\uFF08\u4E0D\u662F\u6211\u4EEC\u7684\u8D26\u53F7\uFF0C\u4E5F\u4E0D\u662F\u522B\u540D\uFF09\n \u00B7 \u5FAE\u4FE1\uFF1A\u5F62\u5982 `xxx@im.wechat`\n \u00B7 \u98DE\u4E66\uFF1A\u5F62\u5982 `ou_\u2026`\uFF08open_id\uFF09\n- `trajectory` = **\u8BA4\u77E5\u8F68\u8FF9\u7F16\u7801**\uFF08\u76EE\u5F55\u540D\u91CC\u90A3\u4E00\u6BB5\uFF0C\u5982 `S142` / `llm-intel`\uFF09\n- `*` \u53EF\u4F5C\u4E3A `user` \u7684**\u901A\u914D\u515C\u5E95**\uFF08exact \u4F18\u5148\uFF09\n\n### \u90A3\u4E2A `user` id \u4ECE\u54EA\u91CC\u6765 \u2014\u2014 \u8FD9\u662F\u672C\u8282\u5B58\u5728\u7684\u539F\u56E0\n\n**\u4F60\u4E0D\u77E5\u9053\u5BF9\u65B9 id\uFF0C\u800C\u5B83\u4E5F\u4E0D\u5728\u4EFB\u4F55\u914D\u7F6E\u6587\u4EF6\u91CC\u3002** \u5B83\u53EA\u51FA\u73B0\u5728\u804A\u5929\u8BB0\u5F55\u4E2D\u3002\n\u21D2 \u7528 `im-bridge({channel:\"weixin\", action:\"contacts\"})`\uFF0C\u5B83\u4F1A\u7ED9\u51FA\uFF1A\n\n```json\n{\n \"contacts\": [\n { \"channel\": \"weixin\", \"userId\": \"o9cq\u2026@im.wechat\", \"accountIds\": [\"wechat-1\"],\n \"route\": null, \"firstSeen\": \"2026-09-04T\u2026\", \"lastSeen\": \"2026-10-22T\u2026\", \"messages\": 1284 }\n ],\n \"unrouted\": [\"o9cq\u2026@im.wechat\"],\n \"orphanRoutes\": [\"ou_typo_never_seen\"],\n \"sources\": [\"AGENT_SESSIONS/_im-logs/weixin/2026-10-22.jsonl\", \"\u2026\"]\n}\n```\n\n\u4E09\u884C\u8F93\u51FA**\u5404\u6709\u7528\u9014\uFF0C\u7F3A\u4E00\u884C\u8FD9\u4E2A\u52A8\u4F5C\u5C31\u53EA\u5269\"\u5217\u540D\u5B57\"**\uFF1A\n\n| \u5B57\u6BB5 | \u542B\u4E49 | \u4F60\u8981\u505A\u4EC0\u4E48 |\n|---|---|---|\n| `contacts[].userId` | \u5BF9\u65B9 id | **\u590D\u5236\u5B83**\u586B\u8FDB `routes[].user` |\n| `unrouted` | \u26A0\uFE0F \u6709\u5F80\u6765\u3001\u4F46**\u6CA1\u914D\u8DEF\u7531** | \u8FD9\u4E9B\u4EBA\u7684\u6D88\u606F\u73B0\u5728**\u65E0\u5904\u53EF\u53BB** \u21D2 \u8FD9\u5C31\u662F\u8BE5\u914D\u7684 |\n| `orphanRoutes` | \u2753 \u914D\u4E86\u8DEF\u7531\u3001\u4F46\u8BB0\u5F55\u91CC**\u4ECE\u6CA1\u51FA\u73B0\u8FC7** | \u5927\u6982\u7387 **id \u5199\u9519**\uFF08\u6216\u4ECE\u672A\u6709\u4EBA\u53D1\u8FC7\uFF09 |\n| `sources` | \u5B9E\u9645\u8BFB\u8FC7\u7684\u6587\u4EF6 | **\u5426\u5B9A\u6027\u7ED3\u8BBA\u7684\u53EF\u4FE1\u5EA6\u4E0A\u9650** = \u8FD9\u4E2A\u5217\u8868\uFF1B\u5B83\u7A7A\u7740\u5C31\u522B\u4E0B\"\u6CA1\u4EBA\"\u7684\u7ED3\u8BBA |\n\n### \u5199\u5B8C\u600E\u4E48\u81EA\u68C0\n\n`im-bridge({channel:\"weixin\", action:\"status\"})` \u7684 `routes[]` \u6BCF\u6761\u90FD\u5E26 **`targetExists`**\uFF1A\n\n- `true` \u21D2 \u8BE5\u8F68\u8FF9\u76EE\u5F55\u771F\u5B9E\u5B58\u5728\uFF0C\u8DEF\u7531**\u6709\u673A\u4F1A**\u751F\u6548\n- `false` \u21D2 **\u8F68\u8FF9\u7F16\u7801\u5199\u9519\u4E86**\uFF08\u6216\u90A3\u6761\u8F68\u8FF9\u5DF2\u88AB\u5F52\u6863/\u5220\u9664\uFF09\n\n\uD83D\uDD34 \u8FD9\u4E00\u683C\u662F\"\u914D\u4E86\u4E0D\u751F\u6548\"\u7684**\u552F\u4E00\u673A\u68B0\u4FE1\u53F7**\uFF1A\u5199\u9519\u4E00\u4E2A\u7F16\u7801**\u4E0D\u4F1A\u6709\u4EFB\u4F55\u62A5\u9519**\uFF0C\n\u6D88\u606F\u8FDB\u6765\u627E\u4E0D\u5230\u76EE\u6807\u5C31\u9759\u9ED8\u4E0D\u6295\u9012\uFF0C\u4F60\u53EA\u4F1A\u770B\u5230\"\u6CA1\u56DE\u97F3\"\u3002\n\n## \u56DB\u3001\u591A\u8D26\u53F7 / \u591A\u6E20\u9053\n\n\u4E00\u4E2A CCC \u7ED1\u591A\u4E2A\u8D26\u53F7\u662F\u5E38\u6001\uFF08owner 2026-10-22\uFF1A\u300C\u4E00\u4E2A CCC \u7ED1\u5B9A\u591A\u4E2A\u8D26\u6237\u5F88\u5E38\u89C1\u300D\uFF09\u3002\n\n- **\u8D26\u53F7**\u5728 `im.accounts[]`\uFF0C\u6BCF\u6761\u81EA\u5E26 `channel`\uFF08\u7F3A\u7701 `weixin`\uFF09\n- **\u8DEF\u7531\u662F\u901A\u9053\u65E0\u5173\u7684**\uFF08`user \u2192 trajectory`\uFF09\uFF1B\u540C\u4E00\u8F68\u8FF9\u53EF\u4EE5\u88AB\u591A\u4E2A\u6E20\u9053\u7684\u5BF9\u7AEF\u6307\u5411\n- `contacts` \u7684\u6BCF\u6761\u5E26 `accountIds`\uFF08\u8BE5\u5BF9\u7AEF\u88AB\u54EA\u4E9B\u8D26\u53F7\u6536\u8FC7\uFF09\u2014\u2014**\u591A\u8D26\u53F7\u9760\u5B83\u533A\u5206**\n- \u53D1\u6D88\u606F\u65F6\u53EF\u7528 `account` \u53C2\u6570\u6307\u5B9A\u7528\u54EA\u4E2A\u8D26\u53F7\uFF08\u7F3A\u7701\uFF1A\u7B2C\u4E00\u4E2A\u542F\u7528\u4E14\u5DF2\u7ED1\u5B9A\u7684\uFF09\n\n## \u4E94\u3001\u804A\u5929\u8BB0\u5F55\u843D\u5728\u54EA\n\n```\nAGENT_SESSIONS/_im-logs/<channel>/<YYYY-MM-DD>.jsonl\n```\n\n- \u6309**\u6E20\u9053**\u5206\u76EE\u5F55\uFF08`weixin` / `feishu`\uFF09\uFF0C\u6309**\u672C\u5730\u81EA\u7136\u5929**\u5206\u6587\u4EF6\uFF0C\u9010\u884C JSON \u8FFD\u52A0\n- \u8001\u8DEF\u5F84 `AGENT_SESSIONS/_weixin-logs/` \u662F**\u540C\u4E00\u65CF\u7684\u524D\u4EE3**\uFF082026-10-22 \u4E4B\u524D\u7684\u5FAE\u4FE1\u8BB0\u5F55\uFF09\uFF1B\n \u8BFB\u4FA7**\u4E24\u4E2A\u90FD\u8BA4**\uFF0C\u26D4 \u4F46**\u53EA\u5F80\u65B0\u8DEF\u5F84\u5199**\n- \u6BCF\u6761\u4E8B\u4EF6\u5E26 `channel` \u5B57\u6BB5 \u21D2 \u98DE\u4E66\u4E8B\u4EF6\u4E0D\u4F1A\u518D\u6DF7\u8FDB\u5FAE\u4FE1\u76EE\u5F55\uFF08\u6B64\u524D\u4F1A\uFF0C\u76EE\u5F55\u540D\u4F1A\u8BF4\u8C0E\uFF09\n- \u5A92\u4F53\u7684\u6301\u4E45\u526F\u672C\u5728 `_im-logs/<channel>/media/<\u65E5\u671F>/`\n\n\u26A0\uFE0F **\u8BB0\u5F55\u5F52 CCC**\uFF08`im.hook` \u6307\u5411\u672C\u5BB9\u5668\u7684\u811A\u672C\uFF09\uFF0CACC \u4E0D\u8BA4\u8BC6\u5B58\u50A8\u683C\u5F0F \u2014\u2014 \u8FD9\u5C42\u5206\u79BB\u662F\u6709\u610F\u7684\u3002\n\n## \u516D\u3001\u51FA\u9519\u65F6\n\n\u5DE5\u5177\u8FD4\u56DE**\u7A33\u5B9A\u9519\u8BEF\u7801 + \u53EF\u884C\u52A8\u63D0\u793A**\uFF0C\u5E38\u89C1\u7684\uFF1A\n\n| \u7801 | \u610F\u601D | \u600E\u4E48\u6539 |\n|---|---|---|\n| `CHANNEL_NOT_CONFIGURED` | \u672C CCC \u6CA1\u542F\u7528\u8BE5\u6E20\u9053 | \u770B\u63D0\u793A\u91CC\u7684**\u90A3\u4E00\u534A**\uFF08\u603B\u5F00\u5173 vs \u7F3A\u8D26\u53F7\uFF0C\u4E24\u8005\u6539\u6CD5\u4E0D\u540C\uFF09 |\n| `ALIAS_UNKNOWN` | `user` \u65E2\u4E0D\u662F\u5DF2\u914D\u522B\u540D\u3001\u4E5F\u4E0D\u662F\u5408\u6CD5\u7684\u88F8 id | \u5148 `action=users` \u770B\u522B\u540D\uFF0C\u6216\u7528 `contacts` \u62FF\u88F8 id |\n| `ACTION_UNSUPPORTED` | \u8BE5\u6E20\u9053\u6CA1\u5B9E\u73B0\u8FD9\u4E2A\u52A8\u4F5C | \u6362\u52A8\u4F5C\uFF1B\u26D4 \u4E0D\u8981\u91CD\u8BD5 |\n| `FILE_ESCAPE` | `file` \u8DD1\u51FA\u4E86 CCC \u6839 | \u7528\u5BB9\u5668\u5185\u76F8\u5BF9\u8DEF\u5F84 |\n\n## \u4E03\u3001\u8FB9\u754C\uFF08\u660E\u786E\u4E0D\u505A\uFF09\n\n- \u26D4 \u8DE8 CCC \u53D1\u9001\uFF08\u53EA\u4F5C\u7528\u4E8E\u672C\u5BB9\u5668\uFF09\n- \u26D4 \u4FEE\u6539\u914D\u7F6E\uFF08`contacts` \u53EA\u8BFB\uFF1B\u52A0\u8DEF\u7531\u8981\u4EBA/CCC \u81EA\u5DF1\u5199 `serenity.json`\uFF09\n- \u26D4 \u5224\u65AD\"\u5BF9\u65B9\u8BFB\u6CA1\u8BFB\"\u2014\u2014\u8BB0\u5F55\u53EA\u8BC1\u660E**\u5DF2\u53D1\u51FA**\n";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shgroup/dsh-serenity-hooks",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.86.0",
|
|
4
4
|
"description": "宁静号 ACC harness(Native Cordis 插件)——给 DeepSeek Harness 装一个「AI 工作区」:14 个工具(container_fs/cognitive_trajectory/dashboard/container_git/msm/praxis/ontology/serenity-skill-creator/cheap-worker/localstore/container_admin;另三个 im-bridge/acc-diag/diagram 按配置条件出现)+ 机械约束(安全模式/工作区围墙/密钥守卫/对外输出守卫)+ 认知轨迹日志与原地重建 + 网页登录入口/IM 桥/认知轨迹唤醒注册表。轨迹声明 = 轨迹目录下的 trajectory.json(约束面 + 旧标识 uid + CRO 机器绑定 cro.host;旧名 trajectory-constraint.json / skiff.json 仍在读取族里);轨迹提示词 = 轨迹目录下的 PROMPT.md(一条轨迹「是谁、按什么章程工作」,所有轨迹通用,追加在容器层与质量层之后,不替换它们)。适配 DSH 0.1.7-rc.1 / 0.2.0-rc.1 / 0.2.1-rc.1(三档)。",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|