@aki_riko/hymem-dsh 0.0.0-stage → 0.2.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/dist/config.js ADDED
@@ -0,0 +1,69 @@
1
+ /** 工作区路径规范化:统一分隔符、去尾斜杠、小写(Windows 不区分大小写)。 */
2
+ export function normalizeWorkspacePath(p) {
3
+ return p.replace(/[\\/]+/g, "\\").replace(/\\+$/, "").toLowerCase();
4
+ }
5
+ /** 会话 cwd 是否落在工作区白名单内;名单为空表示不限制。 */
6
+ export function isWorkspaceAllowed(workspaceAllow, cwd) {
7
+ if (workspaceAllow.length === 0)
8
+ return true;
9
+ if (typeof cwd !== "string" || cwd.length === 0)
10
+ return false;
11
+ const current = normalizeWorkspacePath(cwd);
12
+ return workspaceAllow.some((allowed) => {
13
+ const root = normalizeWorkspacePath(allowed);
14
+ return current === root || current.startsWith(root + "\\");
15
+ });
16
+ }
17
+ /** 顶层会话判定:子代理(subagent/fork)不注入 SOUL / MEMORY,避免人格污染。 */
18
+ export function isTopLevelSession(header) {
19
+ if (!header || typeof header !== "object")
20
+ return true;
21
+ const h = header;
22
+ if (h.parentSession)
23
+ return false;
24
+ if (typeof h.origin === "string" && h.origin.toLowerCase().includes("subagent"))
25
+ return false;
26
+ return true;
27
+ }
28
+ /** 规范化解析传入的配置对象。 */
29
+ export function resolveConfig(raw = {}) {
30
+ const url = typeof raw.hyMemoryUrl === "string" && raw.hyMemoryUrl.trim()
31
+ ? raw.hyMemoryUrl.trim()
32
+ : "http://127.0.0.1:19527";
33
+ // 身份铁律:user_id 代表人类用户(爹地),agent_id 代表 AI(Riko)。
34
+ const userId = typeof raw.userId === "string" && raw.userId.trim() ? raw.userId.trim() : "aki";
35
+ const agentId = typeof raw.agentId === "string" && raw.agentId.trim() ? raw.agentId.trim() : "riko";
36
+ const workspaceAllow = Array.isArray(raw.workspaceAllow)
37
+ ? raw.workspaceAllow.filter((w) => typeof w === "string" && w.trim().length > 0)
38
+ : [];
39
+ const timeoutMs = typeof raw.timeoutMs === "number" && raw.timeoutMs > 0 ? raw.timeoutMs : 15000;
40
+ const soulFile = typeof raw.soulFile === "string" && raw.soulFile.trim()
41
+ ? raw.soulFile.trim()
42
+ : (process.env.RIKO_SOUL_FILE ?? "");
43
+ const soulUrl = typeof raw.soulUrl === "string" && raw.soulUrl.trim() ? raw.soulUrl.trim() : "";
44
+ const soulCacheFile = typeof raw.soulCacheFile === "string" && raw.soulCacheFile.trim()
45
+ ? raw.soulCacheFile.trim()
46
+ : "";
47
+ const soulTimeoutMs = typeof raw.soulTimeoutMs === "number" && raw.soulTimeoutMs > 0 ? raw.soulTimeoutMs : 8000;
48
+ const residentBudgetChars = typeof raw.residentBudgetChars === "number" && raw.residentBudgetChars > 0
49
+ ? raw.residentBudgetChars
50
+ : 6000;
51
+ return {
52
+ hyMemoryUrl: url,
53
+ userId,
54
+ agentId,
55
+ toolsEnabled: raw.toolsEnabled !== false,
56
+ captureEnabled: raw.captureEnabled === true,
57
+ workspaceAllow,
58
+ timeoutMs,
59
+ soulEnabled: raw.soulEnabled !== false,
60
+ soulFile,
61
+ soulUrl,
62
+ soulCacheFile,
63
+ soulTimeoutMs,
64
+ targetAgent: typeof raw.targetAgent === "string" ? raw.targetAgent.trim() : "",
65
+ residentEnabled: raw.residentEnabled !== false,
66
+ residentBudgetChars,
67
+ };
68
+ }
69
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * @aki_riko/hymem-dsh —— Hy-Memory 的 DSH 适配层(单插件)。
3
+ *
4
+ * 四块职责:
5
+ * 1. tools 7 个记忆工具 → Hy-Memory HTTP
6
+ * 2. soul 文件式 SOUL 注入 system prompt(静止:只有 compaction/end 才重读)
7
+ * 3. resident compaction/end 后一次性注入常驻记忆(数据来自 Hy-Memory)
8
+ * 4. curator 定时整理(后续版本;本版留接口)
9
+ *
10
+ * 设计铁律(2026-10-26):
11
+ * - 不依赖 memoryd / dream,Hy-Memory 是唯一后端
12
+ * - SOUL 静止、不动态注入,检索只靠主动 tool call
13
+ * - 子代理会话不注入 SOUL/MEMORY(防人格污染)
14
+ */
15
+ import type { Context } from "@deepseek-ai/cordis";
16
+ export declare const name = "riko-hymem";
17
+ export declare const inject: string[];
18
+ export type Config = Record<string, unknown>;
19
+ export declare function apply(ctx: Context, config?: Config): Promise<void>;
package/dist/index.js ADDED
@@ -0,0 +1,215 @@
1
+ import { readFileSync, writeFileSync, mkdirSync } from "node:fs";
2
+ import { fileURLToPath } from "node:url";
3
+ import { resolve, dirname, join } from "node:path";
4
+ import { homedir } from "node:os";
5
+ import { createUserMessage } from "@deepseek-ai/dsh-llm";
6
+ import { resolveConfig, isWorkspaceAllowed, isTopLevelSession } from "./config.js";
7
+ import { HyClient } from "./client.js";
8
+ import { buildHyTools } from "./tools.js";
9
+ import { setupCapture } from "./capture.js";
10
+ import { renderResident } from "./resident.js";
11
+ export const name = "riko-hymem";
12
+ export const inject = ["tools"];
13
+ const SOUL_SECTION_NAME = "riko-soul";
14
+ const SOUL_SECTION_ORDER = 100;
15
+ function makeLogger(ctx) {
16
+ const anyCtx = ctx;
17
+ const l = anyCtx.logger;
18
+ return {
19
+ warn: (m) => l?.warn(m),
20
+ error: (m) => l?.error(m),
21
+ info: (m) => l?.info(m),
22
+ };
23
+ }
24
+ /** 注入进 prompt 的文本要转义,避免被当成 XML 指令执行。 */
25
+ function escapeXmlData(text) {
26
+ return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
27
+ }
28
+ /** 在每个顶层 Agent 的 ctx 上挂 hook(DSH 的 agent/created 模式)。 */
29
+ function registerPerAgent(ctx, event, hook, workspaceAllow) {
30
+ const host = ctx;
31
+ host.on("agent/created", (payload) => {
32
+ const header = payload?.agent?.session?.header;
33
+ if (!isTopLevelSession(header))
34
+ return;
35
+ if (!isWorkspaceAllowed(workspaceAllow, header?.cwd))
36
+ return;
37
+ const agentCtx = payload.agent.ctx;
38
+ agentCtx.on(event, hook);
39
+ });
40
+ }
41
+ export async function apply(ctx, config = {}) {
42
+ const cfg = resolveConfig(config);
43
+ const logger = makeLogger(ctx);
44
+ const client = new HyClient({
45
+ baseUrl: cfg.hyMemoryUrl,
46
+ userId: cfg.userId,
47
+ timeoutMs: cfg.timeoutMs,
48
+ logger,
49
+ });
50
+ // ---------- 1. 记忆工具 ----------
51
+ if (cfg.toolsEnabled) {
52
+ const tools = buildHyTools(client);
53
+ const registry = ctx.tools;
54
+ for (const tool of tools) {
55
+ registry.register(tool);
56
+ }
57
+ logger.info?.(`riko-hymem: 已注册记忆工具 (user_id=${cfg.userId}, url=${cfg.hyMemoryUrl})`);
58
+ }
59
+ // ---------- 2. SOUL 注入 ----------
60
+ if (cfg.soulEnabled) {
61
+ const soulPath = cfg.soulFile
62
+ ? resolve(cfg.soulFile)
63
+ : fileURLToPath(new URL("../soul.md", import.meta.url));
64
+ const soulCachePath = cfg.soulCacheFile
65
+ ? resolve(cfg.soulCacheFile)
66
+ : join(homedir(), ".riko", "soul.cache.md");
67
+ let soulText = "";
68
+ let soulVersion = "local";
69
+ /**
70
+ * SOUL 加载:三级降级(服务器 = 唯一真相,PC 端只读同步)
71
+ * ① soulUrl 远程拉取
72
+ * ② 本地缓存 ~/.riko/soul.cache.md
73
+ * ③ 包内 soul.md(出厂人格)
74
+ * 任何一步失败都保留旧文本 —— prompt 前缀绝不能抖动。
75
+ */
76
+ const loadSoul = async (reason) => {
77
+ if (cfg.soulUrl) {
78
+ try {
79
+ const controller = new AbortController();
80
+ const timer = setTimeout(() => controller.abort(), cfg.soulTimeoutMs);
81
+ let res;
82
+ try {
83
+ res = await fetch(cfg.soulUrl, { signal: controller.signal });
84
+ }
85
+ finally {
86
+ clearTimeout(timer);
87
+ }
88
+ if (!res.ok)
89
+ throw new Error("HTTP " + res.status);
90
+ const text = await res.text();
91
+ if (!text.trim())
92
+ throw new Error("内容为空");
93
+ soulText = text;
94
+ soulVersion = "remote";
95
+ try {
96
+ mkdirSync(dirname(soulCachePath), { recursive: true });
97
+ writeFileSync(soulCachePath, text, "utf8");
98
+ }
99
+ catch (cacheError) {
100
+ logger.warn("riko-hymem: SOUL 缓存写入失败 " +
101
+ (cacheError instanceof Error ? cacheError.message : String(cacheError)));
102
+ }
103
+ logger.info?.("riko-hymem: SOUL 已从服务器拉取 (" + reason + ", " + soulText.length + " 字符)");
104
+ return;
105
+ }
106
+ catch (error) {
107
+ logger.warn("riko-hymem: SOUL 拉取失败 (" + reason + "),尝试缓存:" +
108
+ (error instanceof Error ? error.message : String(error)));
109
+ try {
110
+ soulText = readFileSync(soulCachePath, "utf8");
111
+ soulVersion = "cache";
112
+ logger.info?.("riko-hymem: SOUL 使用本地缓存 (" + soulText.length + " 字符)");
113
+ return;
114
+ }
115
+ catch {
116
+ // 继续降级到包内文件
117
+ }
118
+ }
119
+ }
120
+ try {
121
+ soulText = readFileSync(soulPath, "utf8");
122
+ soulVersion = "local";
123
+ logger.info?.("riko-hymem: SOUL 读取本地文件 (" + reason + ", " + soulText.length + " 字符)");
124
+ }
125
+ catch (error) {
126
+ logger.warn("riko-hymem: SOUL 读取失败,保留旧缓存 " +
127
+ (error instanceof Error ? error.message : String(error)));
128
+ }
129
+ };
130
+ // 启动时等待完成(第一轮 prompt 就带 SOUL,前缀稳定)
131
+ await loadSoul("startup");
132
+ // SOUL 静止:只有 compact 结束才重读(爹地要求)
133
+ ctx.on("session/event", async (session, event) => {
134
+ if (event?.type !== "compaction/end")
135
+ return;
136
+ if (!isTopLevelSession(session?.header))
137
+ return;
138
+ await loadSoul("compaction/end");
139
+ });
140
+ const soulHook = async (assembly, context, next) => {
141
+ const result = (await next());
142
+ const ctxInfo = context;
143
+ const header = ctxInfo.agent?.session?.header;
144
+ if (!isTopLevelSession(header))
145
+ return result;
146
+ if (!isWorkspaceAllowed(cfg.workspaceAllow, header?.cwd))
147
+ return result;
148
+ if (cfg.targetAgent && String(ctxInfo.agent?.id ?? "") !== cfg.targetAgent)
149
+ return result;
150
+ if (result.sections.some((s) => s.name === SOUL_SECTION_NAME))
151
+ return result;
152
+ if (!soulText.trim())
153
+ return result;
154
+ result.sections.push({
155
+ name: SOUL_SECTION_NAME,
156
+ order: SOUL_SECTION_ORDER,
157
+ text: `<agent_memory:soul version="${soulVersion}">\n${escapeXmlData(soulText)}\n</agent_memory:soul>`,
158
+ interpolate: false,
159
+ });
160
+ return result;
161
+ };
162
+ registerPerAgent(ctx, "system-prompt/assemble", soulHook, cfg.workspaceAllow);
163
+ }
164
+ // ---------- 3. 常驻记忆(compact 后一次)----------
165
+ if (cfg.residentEnabled) {
166
+ let pending = false;
167
+ ctx.on("session/event", (session, event) => {
168
+ if (event?.type !== "compaction/end")
169
+ return;
170
+ if (!isTopLevelSession(session?.header))
171
+ return;
172
+ pending = true;
173
+ });
174
+ const residentHook = async (payload, next) => {
175
+ const decision = (await next());
176
+ if (!pending)
177
+ return decision;
178
+ pending = false;
179
+ const p = payload;
180
+ if (!isTopLevelSession(p.agent?.session?.header))
181
+ return decision;
182
+ if (decision?.kind !== "enter" || p.signal?.aborted)
183
+ return decision;
184
+ try {
185
+ const text = await renderResident(client, cfg.residentBudgetChars, logger, p.signal);
186
+ if (!text)
187
+ return decision;
188
+ const message = createUserMessage({
189
+ content: [
190
+ {
191
+ type: "text",
192
+ text: `<agent_memory:resident>\n${escapeXmlData(text)}\n</agent_memory:resident>`,
193
+ },
194
+ ],
195
+ // dsh-llm 的 source 类型是封闭枚举:注入的记忆按"系统提供的召回"标记。
196
+ source: { kind: "system-prompt", form: "recall" },
197
+ });
198
+ return { ...decision, messages: [message, ...(decision.messages ?? [])] };
199
+ }
200
+ catch (error) {
201
+ logger.warn(`riko-hymem: 常驻记忆注入失败 ${error instanceof Error ? error.message : String(error)}`);
202
+ return decision;
203
+ }
204
+ };
205
+ registerPerAgent(ctx, "agent/pre-step", residentHook, cfg.workspaceAllow);
206
+ }
207
+ // ---------- 4. 自动捕获(默认关,写入交给 hy-sync)----------
208
+ if (cfg.captureEnabled) {
209
+ const cleanupCapture = setupCapture(ctx, client, cfg, logger);
210
+ ctx.effect(() => cleanupCapture);
211
+ logger.info?.(`riko-hymem: 已启用消息捕获 (workspaceAllow=${JSON.stringify(cfg.workspaceAllow)})`);
212
+ }
213
+ logger.info?.(`riko-hymem: 插件加载完成 tools=${cfg.toolsEnabled} soul=${cfg.soulEnabled} resident=${cfg.residentEnabled} url=${cfg.hyMemoryUrl}`);
214
+ }
215
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACnF,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAG/C,MAAM,CAAC,MAAM,IAAI,GAAG,YAAY,CAAC;AACjC,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,OAAO,CAAC,CAAC;AAEhC,MAAM,iBAAiB,GAAG,WAAW,CAAC;AACtC,MAAM,kBAAkB,GAAG,GAAG,CAAC;AAI/B,SAAS,UAAU,CAAC,GAAY;IAC9B,MAAM,MAAM,GAAG,GAA4F,CAAC;IAC5G,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC;IACxB,OAAO;QACL,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;QACvB,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;QACzB,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;KACxB,CAAC;AACJ,CAAC;AAED,wCAAwC;AACxC,SAAS,aAAa,CAAC,IAAY;IACjC,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AACjF,CAAC;AAUD,yDAAyD;AACzD,SAAS,gBAAgB,CACvB,GAAY,EACZ,KAAa,EACb,IAAa,EACb,cAAwB;IAExB,MAAM,IAAI,GAAG,GAAgE,CAAC;IAC9E,IAAI,CAAC,EAAE,CAAC,eAAe,EAAE,CAAC,OAA4B,EAAE,EAAE;QACxD,MAAM,MAAM,GAAG,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC;QAC/C,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC;YAAE,OAAO;QACvC,IAAI,CAAC,kBAAkB,CAAC,cAAc,EAAE,MAAM,EAAE,GAAG,CAAC;YAAE,OAAO;QAC7D,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,GAAiD,CAAC;QACjF,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAC3B,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,KAAK,CAAC,GAAY,EAAE,SAAiB,EAAE;IAC3D,MAAM,GAAG,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IAClC,MAAM,MAAM,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;IAE/B,MAAM,MAAM,GAAG,IAAI,QAAQ,CAAC;QAC1B,OAAO,EAAE,GAAG,CAAC,WAAW;QACxB,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,MAAM;KACP,CAAC,CAAC;IAEH,gCAAgC;IAChC,IAAI,GAAG,CAAC,YAAY,EAAE,CAAC;QACrB,MAAM,KAAK,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;QACnC,MAAM,QAAQ,GAAI,GAAoE,CAAC,KAAK,CAAC;QAC7F,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC1B,CAAC;QACD,MAAM,CAAC,IAAI,EAAE,CAAC,gCAAgC,GAAG,CAAC,MAAM,SAAS,GAAG,CAAC,WAAW,GAAG,CAAC,CAAC;IACvF,CAAC;IAED,mCAAmC;IACnC,IAAI,GAAG,CAAC,WAAW,EAAE,CAAC;QACpB,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ;YAC3B,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC;YACvB,CAAC,CAAC,aAAa,CAAC,IAAI,GAAG,CAAC,YAAY,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QAE1D,MAAM,aAAa,GAAG,GAAG,CAAC,aAAa;YACrC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC;YAC5B,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,eAAe,CAAC,CAAC;QAE9C,IAAI,QAAQ,GAAG,EAAE,CAAC;QAClB,IAAI,WAAW,GAAG,OAAO,CAAC;QAE1B;;;;;;WAMG;QACH,MAAM,QAAQ,GAAG,KAAK,EAAE,MAAc,EAAiB,EAAE;YACvD,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC;gBAChB,IAAI,CAAC;oBACH,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;oBACzC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,GAAG,CAAC,aAAa,CAAC,CAAC;oBACtE,IAAI,GAAa,CAAC;oBAClB,IAAI,CAAC;wBACH,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC;oBAChE,CAAC;4BAAS,CAAC;wBACT,YAAY,CAAC,KAAK,CAAC,CAAC;oBACtB,CAAC;oBACD,IAAI,CAAC,GAAG,CAAC,EAAE;wBAAE,MAAM,IAAI,KAAK,CAAC,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC;oBACnD,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;oBAC9B,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;wBAAE,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC;oBAC1C,QAAQ,GAAG,IAAI,CAAC;oBAChB,WAAW,GAAG,QAAQ,CAAC;oBACvB,IAAI,CAAC;wBACH,SAAS,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;wBACvD,aAAa,CAAC,aAAa,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;oBAC7C,CAAC;oBAAC,OAAO,UAAU,EAAE,CAAC;wBACpB,MAAM,CAAC,IAAI,CACT,0BAA0B;4BACxB,CAAC,UAAU,YAAY,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAC1E,CAAC;oBACJ,CAAC;oBACD,MAAM,CAAC,IAAI,EAAE,CACX,4BAA4B,GAAG,MAAM,GAAG,IAAI,GAAG,QAAQ,CAAC,MAAM,GAAG,MAAM,CACxE,CAAC;oBACF,OAAO;gBACT,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,MAAM,CAAC,IAAI,CACT,yBAAyB,GAAG,MAAM,GAAG,SAAS;wBAC5C,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAC3D,CAAC;oBACF,IAAI,CAAC;wBACH,QAAQ,GAAG,YAAY,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;wBAC/C,WAAW,GAAG,OAAO,CAAC;wBACtB,MAAM,CAAC,IAAI,EAAE,CAAC,2BAA2B,GAAG,QAAQ,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;wBACtE,OAAO;oBACT,CAAC;oBAAC,MAAM,CAAC;wBACP,YAAY;oBACd,CAAC;gBACH,CAAC;YACH,CAAC;YACD,IAAI,CAAC;gBACH,QAAQ,GAAG,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;gBAC1C,WAAW,GAAG,OAAO,CAAC;gBACtB,MAAM,CAAC,IAAI,EAAE,CAAC,2BAA2B,GAAG,MAAM,GAAG,IAAI,GAAG,QAAQ,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;YACxF,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,CAAC,IAAI,CACT,8BAA8B;oBAC5B,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAC3D,CAAC;YACJ,CAAC;QACH,CAAC,CAAC;QAEF,mCAAmC;QACnC,MAAM,QAAQ,CAAC,SAAS,CAAC,CAAC;QAE1B,iCAAiC;QAChC,GAA8D,CAAC,EAAE,CAChE,eAAe,EACf,KAAK,EAAE,OAA6B,EAAE,KAAwB,EAAE,EAAE;YAChE,IAAI,KAAK,EAAE,IAAI,KAAK,gBAAgB;gBAAE,OAAO;YAC7C,IAAI,CAAC,iBAAiB,CAAC,OAAO,EAAE,MAAM,CAAC;gBAAE,OAAO;YAChD,MAAM,QAAQ,CAAC,gBAAgB,CAAC,CAAC;QACnC,CAAC,CACF,CAAC;QAEF,MAAM,QAAQ,GAAG,KAAK,EACpB,QAAiB,EACjB,OAAgB,EAChB,IAA4B,EACV,EAAE;YACpB,MAAM,MAAM,GAAG,CAAC,MAAM,IAAI,EAAE,CAAiD,CAAC;YAC9E,MAAM,OAAO,GAAG,OAEf,CAAC;YACF,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC;YAC9C,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC;gBAAE,OAAO,MAAM,CAAC;YAC9C,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,cAAc,EAAE,MAAM,EAAE,GAAG,CAAC;gBAAE,OAAO,MAAM,CAAC;YACxE,IAAI,GAAG,CAAC,WAAW,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,IAAI,EAAE,CAAC,KAAK,GAAG,CAAC,WAAW;gBAAE,OAAO,MAAM,CAAC;YAC1F,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,iBAAiB,CAAC;gBAAE,OAAO,MAAM,CAAC;YAC7E,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE;gBAAE,OAAO,MAAM,CAAC;YACpC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;gBACnB,IAAI,EAAE,iBAAiB;gBACvB,KAAK,EAAE,kBAAkB;gBACzB,IAAI,EAAE,+BAA+B,WAAW,OAAO,aAAa,CAAC,QAAQ,CAAC,wBAAwB;gBACtG,WAAW,EAAE,KAAK;aACnB,CAAC,CAAC;YACH,OAAO,MAAM,CAAC;QAChB,CAAC,CAAC;QACF,gBAAgB,CAAC,GAAG,EAAE,wBAAwB,EAAE,QAAQ,EAAE,GAAG,CAAC,cAAc,CAAC,CAAC;IAChF,CAAC;IAED,4CAA4C;IAC5C,IAAI,GAAG,CAAC,eAAe,EAAE,CAAC;QACxB,IAAI,OAAO,GAAG,KAAK,CAAC;QAEnB,GAA8D,CAAC,EAAE,CAChE,eAAe,EACf,CAAC,OAA6B,EAAE,KAAwB,EAAE,EAAE;YAC1D,IAAI,KAAK,EAAE,IAAI,KAAK,gBAAgB;gBAAE,OAAO;YAC7C,IAAI,CAAC,iBAAiB,CAAC,OAAO,EAAE,MAAM,CAAC;gBAAE,OAAO;YAChD,OAAO,GAAG,IAAI,CAAC;QACjB,CAAC,CACF,CAAC;QAEF,MAAM,YAAY,GAAG,KAAK,EACxB,OAAgB,EAChB,IAA4B,EACV,EAAE;YACpB,MAAM,QAAQ,GAAG,CAAC,MAAM,IAAI,EAAE,CAG7B,CAAC;YACF,IAAI,CAAC,OAAO;gBAAE,OAAO,QAAQ,CAAC;YAC9B,OAAO,GAAG,KAAK,CAAC;YAChB,MAAM,CAAC,GAAG,OAGT,CAAC;YACF,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC;gBAAE,OAAO,QAAQ,CAAC;YAClE,IAAI,QAAQ,EAAE,IAAI,KAAK,OAAO,IAAI,CAAC,CAAC,MAAM,EAAE,OAAO;gBAAE,OAAO,QAAQ,CAAC;YACrE,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,MAAM,cAAc,CAAC,MAAM,EAAE,GAAG,CAAC,mBAAmB,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;gBACrF,IAAI,CAAC,IAAI;oBAAE,OAAO,QAAQ,CAAC;gBAC3B,MAAM,OAAO,GAAG,iBAAiB,CAAC;oBAChC,OAAO,EAAE;wBACP;4BACE,IAAI,EAAE,MAAM;4BACZ,IAAI,EAAE,4BAA4B,aAAa,CAAC,IAAI,CAAC,4BAA4B;yBAClF;qBACF;oBACD,8CAA8C;oBAC9C,MAAM,EAAE,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,QAAQ,EAAE;iBAClD,CAAC,CAAC;gBACH,OAAO,EAAE,GAAG,QAAQ,EAAE,QAAQ,EAAE,CAAC,OAAO,EAAE,GAAG,CAAC,QAAQ,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;YAC5E,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,CAAC,IAAI,CACT,wBAAwB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CACjF,CAAC;gBACF,OAAO,QAAQ,CAAC;YAClB,CAAC;QACH,CAAC,CAAC;QACF,gBAAgB,CAAC,GAAG,EAAE,gBAAgB,EAAE,YAAY,EAAE,GAAG,CAAC,cAAc,CAAC,CAAC;IAC5E,CAAC;IAED,iDAAiD;IACjD,IAAI,GAAG,CAAC,cAAc,EAAE,CAAC;QACvB,MAAM,cAAc,GAAG,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;QAC7D,GAA6D,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,cAAc,CAAC,CAAC;QAC5F,MAAM,CAAC,IAAI,EAAE,CAAC,uCAAuC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC;IAC9F,CAAC;IAED,MAAM,CAAC,IAAI,EAAE,CACX,4BAA4B,GAAG,CAAC,YAAY,SAAS,GAAG,CAAC,WAAW,aAAa,GAAG,CAAC,eAAe,QAAQ,GAAG,CAAC,WAAW,EAAE,CAC9H,CAAC;AACJ,CAAC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Resident(常驻记忆)渲染器。
3
+ *
4
+ * 设计(2026-10-26 定稿):
5
+ * - compact 后注入一次,平时零占用
6
+ * - 数据全部来自 Hy-Memory,不再依赖 memoryd / dream
7
+ * - 三源合并:L0 画像 + L6 行为模式(图库)+ L2 关键事实 / L7 未完成打算
8
+ * - 按字符预算截断,超预算先砍细节
9
+ */
10
+ import type { HyClient } from "./client.js";
11
+ import type { Logger } from "./types.js";
12
+ export declare function renderResident(client: HyClient, budgetChars: number, logger: Logger, signal?: AbortSignal): Promise<string | null>;
@@ -0,0 +1,59 @@
1
+ function textOf(value) {
2
+ return typeof value === "string" ? value.trim() : "";
3
+ }
4
+ export async function renderResident(client, budgetChars, logger, signal) {
5
+ const blocks = [];
6
+ // 1) L0:爹地的稳定信息
7
+ try {
8
+ const r = await client.getUserProfile({}, signal);
9
+ const data = (r.data ?? {});
10
+ const profile = data.profile;
11
+ if (profile && typeof profile === "object") {
12
+ const lines = Object.entries(profile)
13
+ .map(([key, value]) => [key, textOf(value)])
14
+ .filter(([, value]) => value.length > 0)
15
+ .map(([key, value]) => `- ${key}:${value}`);
16
+ if (lines.length > 0)
17
+ blocks.push(`## 爹地的稳定信息\n${lines.join("\n")}`);
18
+ }
19
+ }
20
+ catch (error) {
21
+ logger.warn(`resident: user_profile 读取失败 ${error instanceof Error ? error.message : String(error)}`);
22
+ }
23
+ // 2) L6 / L2 / L7:一次 list 全拿
24
+ try {
25
+ const r = await client.list({ limit: 100 }, signal);
26
+ const data = (r.data ?? {});
27
+ const nodes = Array.isArray(data.graph?.nodes) ? data.graph.nodes : [];
28
+ const memories = Array.isArray(data.vdb?.memories) ? data.vdb.memories : [];
29
+ const patterns = nodes.map((n) => textOf(n?.content)).filter((t) => t.length > 0);
30
+ if (patterns.length > 0) {
31
+ blocks.push("## 行为模式(跨会话归纳)\n" + patterns.map((t) => `- ${t}`).join("\n"));
32
+ }
33
+ const facts = memories
34
+ .filter((m) => m?.layer === "l2_fact")
35
+ .map((m) => textOf(m?.content))
36
+ .filter((t) => t.length > 0);
37
+ if (facts.length > 0) {
38
+ blocks.push("## 关键事实\n" + facts.map((t) => `- ${t}`).join("\n"));
39
+ }
40
+ const plans = memories
41
+ .filter((m) => m?.layer === "l7_intention")
42
+ .map((m) => textOf(m?.content))
43
+ .filter((t) => t.length > 0);
44
+ if (plans.length > 0) {
45
+ blocks.push("## 之前留下的打算\n" + plans.map((t) => `- ${t}`).join("\n"));
46
+ }
47
+ }
48
+ catch (error) {
49
+ logger.warn(`resident: list 读取失败 ${error instanceof Error ? error.message : String(error)}`);
50
+ }
51
+ if (blocks.length === 0)
52
+ return null;
53
+ let text = "# 长期记忆(Hy-Memory 自动渲染)\n\n" + blocks.join("\n\n");
54
+ if (text.length > budgetChars) {
55
+ text = text.slice(0, budgetChars).trimEnd() + "\n- …(已达预算上限,其余略)";
56
+ }
57
+ return text;
58
+ }
59
+ //# sourceMappingURL=resident.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resident.js","sourceRoot":"","sources":["../src/resident.ts"],"names":[],"mappings":"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"}
package/dist/soul.d.ts ADDED
@@ -0,0 +1,18 @@
1
+ import type { Context } from "@deepseek-ai/cordis";
2
+ export declare const TWIN_SOUL_SECTION_NAME = "twin-soul";
3
+ export declare const TWIN_SOUL_SECTION_ORDER = 100;
4
+ /** Default template lives beside the package's dist/ directory and is user-editable. */
5
+ export declare function defaultSoulFilePath(): string;
6
+ export interface FileSoulWatcher {
7
+ getText(): string;
8
+ close(): void;
9
+ }
10
+ /** Create a hot-reloading watcher for a local soul file. */
11
+ export declare function createFileSoulWatcher(soulFile?: string, onChange?: () => void, logger?: {
12
+ warn(msg: string): void;
13
+ }): FileSoulWatcher;
14
+ /**
15
+ * @deprecated B1 编排收口:默认只走内核 Soul(order 10300);
16
+ * 全局 twin-soul(order 100)平行注入已废弃。若需文件覆盖,使用 config.fileSoulEnabled opt-in。
17
+ */
18
+ export declare function registerTwinSoul(ctx: Context, soulFile?: string): void;
package/dist/soul.js ADDED
@@ -0,0 +1,151 @@
1
+ /**
2
+ * File-based twin personality.
3
+ *
4
+ * B1 编排收口:内核 Soul(order 10300,按 agent 隔离)是单一真相源。
5
+ * 本模块提供文件监听与读取辅助(createFileSoulWatcher);旧版全局平行注入
6
+ * registerTwinSoul 已废弃,默认不再调用。
7
+ */
8
+ import { readFile, readFileSync, watch } from "node:fs";
9
+ import { basename, dirname, resolve } from "node:path";
10
+ import { fileURLToPath } from "node:url";
11
+ export const TWIN_SOUL_SECTION_NAME = "twin-soul";
12
+ export const TWIN_SOUL_SECTION_ORDER = 100;
13
+ /** Default template lives beside the package's dist/ directory and is user-editable. */
14
+ export function defaultSoulFilePath() {
15
+ const configured = process.env.RIKO_DSH_SOUL_FILE;
16
+ return configured
17
+ ? resolve(configured)
18
+ : fileURLToPath(new URL("../soul.md", import.meta.url));
19
+ }
20
+ function warn(ctx, message) {
21
+ const logger = ctx.logger;
22
+ logger?.warn?.(`riko-dsh: ${message}`);
23
+ }
24
+ /** Create a hot-reloading watcher for a local soul file. */
25
+ export function createFileSoulWatcher(soulFile = defaultSoulFilePath(), onChange, logger) {
26
+ const path = resolve(soulFile);
27
+ let soulText = "";
28
+ try {
29
+ soulText = readFileSync(path, "utf8");
30
+ }
31
+ catch (error) {
32
+ logger?.warn(`soul 文件无法读取: ${path} (${error instanceof Error ? error.message : String(error)})`);
33
+ }
34
+ let watcher;
35
+ let reloadTimer;
36
+ const reload = () => {
37
+ readFile(path, "utf8", (error, nextText) => {
38
+ if (error) {
39
+ if (error.code === "ENOENT") {
40
+ nextText = "";
41
+ }
42
+ else {
43
+ logger?.warn(`soul 文件重载失败: ${path} (${error.message})`);
44
+ return;
45
+ }
46
+ }
47
+ if (nextText === soulText)
48
+ return;
49
+ soulText = nextText;
50
+ try {
51
+ onChange?.();
52
+ }
53
+ catch (emitError) {
54
+ logger?.warn(`system prompt 更新通知失败: ${emitError instanceof Error ? emitError.message : String(emitError)}`);
55
+ }
56
+ });
57
+ };
58
+ try {
59
+ watcher = watch(dirname(path), (_eventType, filename) => {
60
+ if (filename !== null && filename.toString() !== basename(path))
61
+ return;
62
+ if (reloadTimer !== undefined)
63
+ clearTimeout(reloadTimer);
64
+ reloadTimer = setTimeout(() => {
65
+ reloadTimer = undefined;
66
+ reload();
67
+ }, 40);
68
+ });
69
+ watcher.on("error", (error) => logger?.warn(`soul 文件监听失败: ${error.message}`));
70
+ }
71
+ catch (error) {
72
+ logger?.warn(`soul 文件监听无法启动: ${path} (${error instanceof Error ? error.message : String(error)})`);
73
+ }
74
+ return {
75
+ getText: () => soulText,
76
+ close: () => {
77
+ if (reloadTimer !== undefined)
78
+ clearTimeout(reloadTimer);
79
+ watcher?.close();
80
+ },
81
+ };
82
+ }
83
+ /**
84
+ * @deprecated B1 编排收口:默认只走内核 Soul(order 10300);
85
+ * 全局 twin-soul(order 100)平行注入已废弃。若需文件覆盖,使用 config.fileSoulEnabled opt-in。
86
+ */
87
+ export function registerTwinSoul(ctx, soulFile = defaultSoulFilePath()) {
88
+ const path = resolve(soulFile);
89
+ ctx.effect(() => {
90
+ let soulText = "";
91
+ try {
92
+ soulText = readFileSync(path, "utf8");
93
+ }
94
+ catch (error) {
95
+ warn(ctx, `soul 文件无法读取: ${path} (${error instanceof Error ? error.message : String(error)})`);
96
+ }
97
+ const removeSection = ctx.systemPrompt.section({
98
+ name: TWIN_SOUL_SECTION_NAME,
99
+ order: TWIN_SOUL_SECTION_ORDER,
100
+ text: () => soulText,
101
+ interpolate: false,
102
+ });
103
+ let watcher;
104
+ let reloadTimer;
105
+ const reload = () => {
106
+ readFile(path, "utf8", (error, nextText) => {
107
+ if (error) {
108
+ if (error.code === "ENOENT") {
109
+ nextText = "";
110
+ }
111
+ else {
112
+ warn(ctx, `soul 文件重载失败: ${path} (${error.message})`);
113
+ return;
114
+ }
115
+ }
116
+ if (nextText === soulText)
117
+ return;
118
+ soulText = nextText;
119
+ try {
120
+ ctx.emit("system-prompt/change");
121
+ }
122
+ catch (emitError) {
123
+ warn(ctx, `system prompt 更新通知失败: ${emitError instanceof Error ? emitError.message : String(emitError)}`);
124
+ }
125
+ });
126
+ };
127
+ try {
128
+ watcher = watch(dirname(path), (_eventType, filename) => {
129
+ if (filename !== null && filename.toString() !== basename(path))
130
+ return;
131
+ if (reloadTimer !== undefined)
132
+ clearTimeout(reloadTimer);
133
+ reloadTimer = setTimeout(() => {
134
+ reloadTimer = undefined;
135
+ reload();
136
+ }, 40);
137
+ });
138
+ watcher.on("error", (error) => warn(ctx, `soul 文件监听失败: ${error.message}`));
139
+ }
140
+ catch (error) {
141
+ warn(ctx, `soul 文件监听无法启动: ${path} (${error instanceof Error ? error.message : String(error)})`);
142
+ }
143
+ return () => {
144
+ if (reloadTimer !== undefined)
145
+ clearTimeout(reloadTimer);
146
+ watcher?.close();
147
+ removeSection();
148
+ };
149
+ }, "riko-dsh.twin-soul");
150
+ }
151
+ //# sourceMappingURL=soul.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"soul.js","sourceRoot":"","sources":["../src/soul.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { ToolDefinition } from "@deepseek-ai/dsh-tools";
2
+ import type { HyClient } from "./client.js";
3
+ export declare function buildHyTools(client: HyClient): ToolDefinition[];