@nightpainters/dsh-ling 1.6.2 → 1.7.1
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/CHANGELOG.md +176 -9
- package/DESIGN.md +89 -6
- package/PHILOSOPHY.md +14 -4
- package/README.md +105 -19
- package/cordis.patch.yml +32 -2
- package/lib/client.js +2544 -61
- package/lib/host/agent-tools.js +286 -0
- package/lib/host/api.js +592 -59
- package/lib/host/archive.js +7 -7
- package/lib/host/autotree.js +2 -2
- package/lib/host/clock-skill.js +1 -1
- package/lib/host/config.js +38 -0
- package/lib/host/deep-index-skill.js +3 -3
- package/lib/host/deepsummary.js +80 -4
- package/lib/host/dsweb-summary.js +11 -5
- package/lib/host/genesis.js +5 -3
- package/lib/host/guard.js +53 -0
- package/lib/host/inject.js +18 -5
- package/lib/host/l1.js +17 -11
- package/lib/host/library-checker.js +552 -0
- package/lib/host/library-import-engine.js +211 -0
- package/lib/host/library-import.js +911 -0
- package/lib/host/library-runtime.js +199 -0
- package/lib/host/library-sqlite.js +344 -0
- package/lib/host/library-store.js +1714 -0
- package/lib/host/memory.js +119 -29
- package/lib/host/persona.js +13 -2
- package/lib/host/rawlog.js +67 -4
- package/lib/host/recall-search.js +60 -12
- package/lib/host/retitle.js +5 -5
- package/lib/host/session-line.js +7 -2
- package/lib/host/snapshot.js +9 -5
- package/lib/host/surgery.js +6 -4
- package/lib/host/tools.js +473 -27
- package/lib/host/util.js +1 -1
- package/lib/index.js +120 -81
- package/package.json +10 -5
- package/tools/deep-import-docs.mjs +1210 -0
package/lib/host/session-line.js
CHANGED
|
@@ -35,6 +35,9 @@ import { pick } from './util.js';
|
|
|
35
35
|
import { firstSentence } from './l1.js';
|
|
36
36
|
import { extractMessageText } from './snapshot.js';
|
|
37
37
|
import { canInject, kindOfAgent, sessionIdOfAgent } from './inject.js';
|
|
38
|
+
// F4(2026-10-17):按码点安全截断 —— 那一行会**进模型上下文**,原来直接 `slice` 会把 emoji
|
|
39
|
+
// 切成半个代理对,而半个代理能把官方路由打成 400(见 `rawlog.wellFormed` 的事故记录)。
|
|
40
|
+
import { clipChars } from './rawlog.js';
|
|
38
41
|
|
|
39
42
|
/** 我们那条活行的 `source.kind` —— 也是"认出自己"的唯一判据(不用记下的 seq:折叠后可能已不在面上)。 */
|
|
40
43
|
export const SESSION_LINE_SOURCE = 'dsh-ling:session-line';
|
|
@@ -74,11 +77,13 @@ function oneLine(t) {
|
|
|
74
77
|
return String(t ?? '').replace(/\s+/g, ' ').trim();
|
|
75
78
|
}
|
|
76
79
|
|
|
77
|
-
/** 硬夹到 n 字(超出留 `…`)
|
|
80
|
+
/** 硬夹到 n 字(超出留 `…`)。⚠️ F4(2026-10-17):改走 `clipChars`(按码点)—— 原来直接
|
|
81
|
+
* `slice(0, k-1)` 会把 emoji 切成半个代理对,而那一行会进模型上下文 ⇒ 半个代理能打成 400。
|
|
82
|
+
* 语义保持不变:**k 是含省略号的总长上限**。 */
|
|
78
83
|
function clip(s, n) {
|
|
79
84
|
const t = String(s ?? '');
|
|
80
85
|
const k = Math.max(1, Number(n) || 0);
|
|
81
|
-
return t.length <= k ? t : t.
|
|
86
|
+
return t.length <= k ? t : clipChars(t, Math.max(1, k - 1));
|
|
82
87
|
}
|
|
83
88
|
|
|
84
89
|
/** 本地时刻 HH:MM(与主人看到的钟一致;探针里用它判断"文本是否随对话变")。 */
|
package/lib/host/snapshot.js
CHANGED
|
@@ -7,11 +7,12 @@ import { assemblePersona } from './persona.js';
|
|
|
7
7
|
import { selectL1, formatL1Section } from './l1.js';
|
|
8
8
|
import { currentMode } from './mode.js';
|
|
9
9
|
import { neutralizeMustache } from './util.js';
|
|
10
|
+
import { wellFormed } from './rawlog.js'; // 1.7.1 F4 闭环:快照是注入面主出口
|
|
10
11
|
import { createHash } from 'node:crypto';
|
|
11
12
|
|
|
12
13
|
// §4「超量折叠成一行」的那行计数(由 `memory.js` 的 branchLogDigest 在明细之后 push 进 `lines`)
|
|
13
14
|
// —— 它是**汇总**,不是明细。零明细时它撑不起整段(见下方渲染判据);有明细时照旧显示。
|
|
14
|
-
// 判据只用开头:明细行一律以主语(
|
|
15
|
+
// 判据只用开头:明细行一律以主语(主人/器灵)或动作词开头,不会长成 `…另有 N 笔改动`。
|
|
15
16
|
// 若哪天 memory.js 改了措辞,这里退化成"照旧渲染"(fail-open)—— 只影响占不占地方,不吞明细。
|
|
16
17
|
const BRANCH_LOG_FOLD_LINE = /^…另有 \d+ 笔改动/;
|
|
17
18
|
|
|
@@ -28,7 +29,9 @@ export function buildSnapshotText(ctx, memory, settings, sessionId, { keywords =
|
|
|
28
29
|
const l0 = assemblePersona(s, mode);
|
|
29
30
|
if (l0) { l0Text = l0; parts.push(l0); }
|
|
30
31
|
}
|
|
31
|
-
|
|
32
|
+
// 1.7.1(审计 F-02):闸不再查 conv_overview —— 料已换成深层库(l1.js 的 deepLine),
|
|
33
|
+
// 查概述会在"只有深层条目"的库里把整段 L1 吞掉;交 selectL1 自己判空。
|
|
34
|
+
if (personaEnabled && s.memory?.l1Enabled !== false) {
|
|
32
35
|
const cfg = s.memory || {};
|
|
33
36
|
const result = selectL1(memory, {
|
|
34
37
|
mode,
|
|
@@ -93,13 +96,14 @@ export function buildSnapshotText(ctx, memory, settings, sessionId, { keywords =
|
|
|
93
96
|
// 下一轮照样进候选;与 §3 开关"只管渲染、不管交代记账"同一取向)。
|
|
94
97
|
const logLines = Array.isArray(d?.lines) ? d.lines : [];
|
|
95
98
|
const logDetailLines = logLines.filter((x) => !BRANCH_LOG_FOLD_LINE.test(String(x)));
|
|
96
|
-
// §3 独立开关:只管**树改动播报**(
|
|
99
|
+
// §3 独立开关:只管**树改动播报**(与 `settings.persona.enabled` **并列**的一道闸 ——
|
|
100
|
+
// 外层 `cfg.injectEnabled` 关掉的是**整个记忆段**,见 inject.js:registerMemorySection)。
|
|
97
101
|
// 关掉时:不成文、也不推进"已示人/已处置"水位(否则关着关着就把一段内容标成已读 ⇒
|
|
98
102
|
// 再打开时那段内容永远看不到)。`.last` 照走 —— 它是复盘退出判据,不是"已示人"判据:
|
|
99
103
|
// **开关只管"渲染",不管"交代记账"**(停推进会卡死复盘模式的退出,回归见 tree 套 9-5)。
|
|
100
104
|
if (s.memory?.branchLogEnabled !== false && logDetailLines.length) {
|
|
101
105
|
// A-03 / D-S03(1.5.1 红蓝对抗):段首此前**写死**「主人刚改动了记忆树」,而 schema v12 起
|
|
102
|
-
// 每一行都已带主语(`branchLogDigest` 按 actor
|
|
106
|
+
// 每一行都已带主语(`branchLogDigest` 按 actor 分流成「主人」/「器灵」)⇒ 器灵经工具
|
|
103
107
|
// 改的树,在它**下一轮的系统提示**里被读成"主人刚改动",与 tools.js 的设计意图正相反。
|
|
104
108
|
// 段首改中性措辞,**主语交给每一行** —— 谁改的由行内说,不由段头替它说。
|
|
105
109
|
parts.push(['【记忆树有改动】', ...logLines.map((x) => '- ' + x)].join('\n'));
|
|
@@ -109,7 +113,7 @@ export function buildSnapshotText(ctx, memory, settings, sessionId, { keywords =
|
|
|
109
113
|
// 注入面出口 ①(快照侧,2026-09-18):L0 人格 + L1 记忆在这里成文。宿主 renderPrompt
|
|
110
114
|
// 无 try/catch,未注册的 `{{名字}}` 会让该会话每一步都失败 ⇒ 成文即中和(幂等)。
|
|
111
115
|
// 时间锚不经此处,由 inject.js 的最终出口兜底。
|
|
112
|
-
const text = neutralizeMustache(parts.join('\n\n'));
|
|
116
|
+
const text = wellFormed(neutralizeMustache(parts.join('\n\n')));
|
|
113
117
|
// ── 投递留痕(1.6-A,2026-10-03)──────────────────────────────────────────────
|
|
114
118
|
// **只在首次定稿时落一条**(`bumpHits`):冻结快照的选取在此刻定下,此后同一会话每轮投递的都是同一段
|
|
115
119
|
// 文本;重建/空闲刷新再记只会把表撑大而不增信息(与 `hit_count` 只记首次定稿同一取向,见上)。
|
package/lib/host/surgery.js
CHANGED
|
@@ -13,9 +13,11 @@
|
|
|
13
13
|
// 1.2 每启动票据 = $DSH_HOME/cache/dsh-ling/surgery.ticket(32 字节随机),只对**本机直连**(无代理头且带 UA)的请求下发,
|
|
14
14
|
// 每启动轮换(旧票即废);客户端首次手术前取一次并缓存,随后带 `x-dsh-ling-surgery: <ticket>`。
|
|
15
15
|
// 1.3 门下沉为一处 requireSurgery(headers, body, opts),覆盖全部 **14** 条人格/规矩/习惯写面。
|
|
16
|
-
// ⚠️ 条数在 2026-10-05 夜由 12 订正为 14(B-5):下方的覆盖面清单**逐条列了 14
|
|
17
|
-
// `api.js`
|
|
18
|
-
//
|
|
16
|
+
// ⚠️ 条数在 2026-10-05 夜由 12 订正为 14(B-5):下方的覆盖面清单**逐条列了 14 行**,那才是有权威的那份。
|
|
17
|
+
// 当时本行与 `api.js` 的门下沉注释还写着"12" ⇒ **两处都在说谎**。2026-10-16 复核:`api.js` 那侧
|
|
18
|
+
// 已全部对齐到 14(`api.js:541/603/2154/…/3231` 逐处都是 14)⇒ 本句现在只是在解释历史,
|
|
19
|
+
// **不再是当下的口径指控**(别再照它去找 api.js 的"12")。
|
|
20
|
+
// 口径不变:**条数一律以清单行数为准**,改清单时必须同批改这里与 api.js 那一处。
|
|
19
21
|
// 1.4 事件留痕 = $DSH_HOME/logs/surgery-YYYY-MM.jsonl,append-only + 整行哈希链(改一行即断链)。
|
|
20
22
|
// 1.5 逃生开关:DSH_LING_GUARD=off 或 settings.guard.enforce === false ⇒ 整体放行(绝不把主人锁在门外)。
|
|
21
23
|
//
|
|
@@ -34,7 +36,7 @@ import { join } from 'node:path';
|
|
|
34
36
|
import { dshHome, defaultDataDir } from './util.js';
|
|
35
37
|
import { headerOf, realPeerAddress } from './guard.js';
|
|
36
38
|
|
|
37
|
-
// ── 覆盖面清单:
|
|
39
|
+
// ── 覆盖面清单:14 条能改人格/规矩/习惯的写面(行号 = 2026-09-30 深夜实测,改 api.js 后须复核)──
|
|
38
40
|
// # 端点 register 行 "原"过门情况(改前) 改后
|
|
39
41
|
// 1 /persona 1809 仅 wasSealed && !wantLock(wantLock 可绕过) 过门
|
|
40
42
|
// 2 /persona/check 1855 无门(只读验钥 —— 但是一把**验句预言机**) 过门
|