@modusensus/dsh-mneme 0.12.0 → 0.13.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/README.md +48 -19
- package/docs/CONFIGURATION.md +43 -4
- package/docs/DIRECTORIES.md +114 -0
- package/docs/DISTILL.md +64 -0
- package/docs/DSH-GO.md +97 -0
- package/docs/ENTITIES.md +5 -3
- package/docs/FORGET.md +77 -0
- package/docs/KB.md +110 -0
- package/docs/SLEEP.md +28 -3
- package/docs/STORAGE.md +23 -0
- package/lib/api-standalone.js +4 -1
- package/lib/api.js +581 -29
- package/lib/attachment-text.js +122 -0
- package/lib/choro-command.js +9 -2
- package/lib/client.js +3537 -1205
- package/lib/config.js +139 -1
- package/lib/continuity.js +7 -6
- package/lib/diary/auto.js +190 -0
- package/lib/diary/compose.js +440 -0
- package/lib/diary/dir.js +59 -0
- package/lib/diary/export.js +97 -0
- package/lib/diary/index.js +26 -0
- package/lib/diary/library.js +189 -0
- package/lib/diary/qq-inbox.js +142 -0
- package/lib/diary/rollover.js +61 -0
- package/lib/diary/session-provider.js +122 -0
- package/lib/dream/decisions.js +56 -5
- package/lib/dream/sleep.js +616 -15
- package/lib/dream.js +45 -13
- package/lib/dsh-go/host.js +162 -0
- package/lib/dsh-go/panel.js +2091 -0
- package/lib/dsh-go/text.js +342 -0
- package/lib/dsh-go/views/common.js +68 -0
- package/lib/dsh-go/views/entity.js +48 -0
- package/lib/dsh-go/views/memory.js +198 -0
- package/lib/dsh-go/views/root.js +30 -0
- package/lib/dsh-go/views/settings.js +398 -0
- package/lib/dsh-go/views/status.js +51 -0
- package/lib/embedding.js +42 -8
- package/lib/entities/extractor.js +36 -7
- package/lib/hot-memory.js +8 -9
- package/lib/index.js +92 -2
- package/lib/inject.js +189 -18
- package/lib/kb/index.js +309 -0
- package/lib/kb/routes.js +220 -0
- package/lib/kb/tools.js +148 -0
- package/lib/lang.js +87 -4
- package/lib/peak-hours.js +57 -2
- package/lib/semantic.js +347 -60
- package/lib/service.js +193 -66
- package/lib/settings.js +112 -14
- package/lib/store.js +347 -21
- package/lib/summarize.js +38 -11
- package/lib/tools.js +35 -4
- package/lib/user-settings.js +128 -32
- package/lib/vector-index.js +76 -6
- package/lib/wiki/cli-hint.js +90 -0
- package/lib/wiki/queries.js +116 -2
- package/lib/wiki/t1-jobs.js +232 -0
- package/lib/wiki/t1.js +7 -1
- package/package.json +25 -1
- package/src/api-standalone.js +4 -1
- package/src/api.js +581 -29
- package/src/attachment-text.js +122 -0
- package/src/choro-command.js +9 -2
- package/src/config.js +139 -1
- package/src/continuity.js +7 -6
- package/src/diary/auto.js +190 -0
- package/src/diary/compose.js +440 -0
- package/src/diary/dir.js +59 -0
- package/src/diary/export.js +97 -0
- package/src/diary/index.js +26 -0
- package/src/diary/library.js +189 -0
- package/src/diary/qq-inbox.js +142 -0
- package/src/diary/rollover.js +61 -0
- package/src/diary/session-provider.js +122 -0
- package/src/dream/decisions.js +56 -5
- package/src/dream/sleep.js +616 -15
- package/src/dream.js +45 -13
- package/src/dsh-go/host.js +162 -0
- package/src/dsh-go/panel.js +2091 -0
- package/src/dsh-go/text.js +342 -0
- package/src/dsh-go/views/common.js +68 -0
- package/src/dsh-go/views/entity.js +48 -0
- package/src/dsh-go/views/memory.js +198 -0
- package/src/dsh-go/views/root.js +30 -0
- package/src/dsh-go/views/settings.js +398 -0
- package/src/dsh-go/views/status.js +51 -0
- package/src/embedding.js +42 -8
- package/src/entities/extractor.js +36 -7
- package/src/hot-memory.js +8 -9
- package/src/index.js +92 -2
- package/src/inject.js +189 -18
- package/src/kb/index.js +309 -0
- package/src/kb/routes.js +220 -0
- package/src/kb/tools.js +148 -0
- package/src/lang.js +87 -4
- package/src/peak-hours.js +57 -2
- package/src/semantic.js +347 -60
- package/src/service.js +193 -66
- package/src/settings.js +112 -14
- package/src/store.js +347 -21
- package/src/summarize.js +38 -11
- package/src/tools.js +35 -4
- package/src/user-settings.js +128 -32
- package/src/vector-index.js +76 -6
- package/src/wiki/cli-hint.js +90 -0
- package/src/wiki/queries.js +116 -2
- package/src/wiki/t1-jobs.js +232 -0
- package/src/wiki/t1.js +7 -1
- package/test/api-routes-gaps.test.js +63 -0
- package/test/api.test.js +375 -4
- package/test/attachment-text.test.js +140 -0
- package/test/bm25-corpus-cache.test.js +145 -0
- package/test/capacity-warning.test.js +262 -0
- package/test/client.test.js +779 -154
- package/test/conflict-freeze.test.js +45 -1
- package/test/continuity.test.js +8 -1
- package/test/diary-library.test.js +187 -0
- package/test/diary.test.js +576 -0
- package/test/dream-maxtokens-fallback.test.js +3 -3
- package/test/dream.test.js +62 -1
- package/test/dsh-go-host.test.js +134 -0
- package/test/dsh-go-panel-actions.test.js +854 -0
- package/test/dsh-go-panel.test.js +251 -0
- package/test/embedding-ready.test.js +33 -3
- package/test/entities.test.js +73 -0
- package/test/forget-corrections.test.js +70 -0
- package/test/image-memory.test.js +171 -0
- package/test/issue-617-step1-query-and-fusion.test.js +361 -0
- package/test/kb-api-wiring.test.js +128 -0
- package/test/kb-collections.test.js +272 -0
- package/test/kb-routes.test.js +379 -0
- package/test/mint-source.test.js +26 -0
- package/test/peak-hours-observability.test.js +70 -0
- package/test/persona-api.test.js +3 -3
- package/test/persona-by-session.test.js +568 -0
- package/test/persona-settings.test.js +7 -7
- package/test/reflection-update-gate.test.js +129 -0
- package/test/reindex-backfill.test.js +334 -0
- package/test/reindex-scheduler.test.js +369 -0
- package/test/scope-candidates.test.js +249 -0
- package/test/sleep-action-set.test.js +14 -0
- package/test/sleep-heat.test.js +49 -0
- package/test/sleep.test.js +598 -0
- package/test/standalone-api.test.js +24 -0
- package/test/store.test.js +20 -0
- package/test/summarize.test.js +26 -0
- package/test/user-settings-segments.test.js +528 -0
- package/test/vector-index.test.js +120 -6
- package/test/wiki-api.test.js +355 -0
- package/test/wiki-cli-hint.test.js +118 -0
- package/test/wiki-queries.test.js +7 -0
- package/test/wiki-t1-jobs.test.js +125 -0
|
@@ -165,6 +165,13 @@ test("moduleMap:模块、页面状态与跨模块边同源返回", () => {
|
|
|
165
165
|
assert.deepEqual(slugs, ["root", "src"]);
|
|
166
166
|
const src = modules.find((m) => m.slug === "src");
|
|
167
167
|
assert.equal(src.page_status, "skeleton");
|
|
168
|
+
// 面板从地志页导入知识点时读的是 mod.relPath(契约 §3.6);SQL 行里只有
|
|
169
|
+
// page_rel_path,缺这层映射会让「选完模块点导入」永远提示请先选模块(#607)。
|
|
170
|
+
// 同时锁住原 snake_case 字段还在——choro_module_map 的 render 与 CLI 都在用。
|
|
171
|
+
assert.equal(typeof src.relPath, "string", "relPath 必须与 page_rel_path 同值");
|
|
172
|
+
assert.equal(src.relPath, src.page_rel_path);
|
|
173
|
+
assert.ok(src.relPath.endsWith(".md"), "页相对路径是磁盘上真实存在的 .md");
|
|
174
|
+
assert.equal(typeof src.file_count, "number", "file_count 原字段必须保留(choro_module_map 的 render 在吃)");
|
|
168
175
|
// fixture 的引用全在 src 模块内部(a→b→b2),left-pad 是外部依赖,root 只有
|
|
169
176
|
// package.json 没有代码——跨模块边应为空集。跨模块聚erge本身由 wiki-store 的
|
|
170
177
|
// 整仓替换用例与 t0 的 moduleEdges 排序覆盖。
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
// T1 面板后台任务状态机的回归锁(契约 §3.2)。
|
|
2
|
+
//
|
|
3
|
+
// **绝不真起进程**:T1 一次要花模型额度,测试里注入假 spawn 就够——这一层要证明的
|
|
4
|
+
// 是「记账与状态迁移对不对」,不是「模型跑得通不通」(那是 CLI 的 e2e 地盘)。
|
|
5
|
+
import test from "node:test";
|
|
6
|
+
import assert from "node:assert/strict";
|
|
7
|
+
import { EventEmitter } from "node:events";
|
|
8
|
+
import { createT1Jobs } from "../src/wiki/t1-jobs.js";
|
|
9
|
+
|
|
10
|
+
// 假子进程:stdout/stderr 是 EventEmitter,close/error 也走事件——形状贴着真
|
|
11
|
+
// ChildProcess,但一个字节都不会真跑出去。
|
|
12
|
+
function fakeSpawn() {
|
|
13
|
+
const calls = [];
|
|
14
|
+
const spawn = (cmd, args, opts) => {
|
|
15
|
+
const child = new EventEmitter();
|
|
16
|
+
child.stdout = new EventEmitter();
|
|
17
|
+
child.stderr = new EventEmitter();
|
|
18
|
+
child.stdout.setEncoding = () => {};
|
|
19
|
+
child.stderr.setEncoding = () => {};
|
|
20
|
+
child.killed = false;
|
|
21
|
+
child.kill = () => { child.killed = true; };
|
|
22
|
+
child.cmd = cmd;
|
|
23
|
+
child.args = args;
|
|
24
|
+
child.opts = opts;
|
|
25
|
+
calls.push(child);
|
|
26
|
+
return child;
|
|
27
|
+
};
|
|
28
|
+
return { spawn, calls };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function makeJobs(overrides = {}) {
|
|
32
|
+
const fake = fakeSpawn();
|
|
33
|
+
const jobs = createT1Jobs({
|
|
34
|
+
spawn: fake.spawn,
|
|
35
|
+
nodePath: "node",
|
|
36
|
+
scriptPath: "/pkg/bin/dsh-mneme-choro.mjs",
|
|
37
|
+
dbPath: "/mem/memory.db",
|
|
38
|
+
now: (() => { let i = 0; return () => `T${++i}`; })(),
|
|
39
|
+
...overrides
|
|
40
|
+
});
|
|
41
|
+
return { jobs, calls: fake.calls };
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const repo = { id: 1, name: "r", root_path: "/repo" };
|
|
45
|
+
|
|
46
|
+
test("start:起的是 CLI 的 --t1 --apply --json(面板必须带 apply,否则 CLI 只列候选不写)", () => {
|
|
47
|
+
const { jobs, calls } = makeJobs();
|
|
48
|
+
const r = jobs.start({ repo, module: "src", retryFailed: true });
|
|
49
|
+
assert.equal(r.started, true);
|
|
50
|
+
assert.ok(r.jobId);
|
|
51
|
+
assert.equal(calls.length, 1);
|
|
52
|
+
const [cmd, args, opts] = [calls[0].cmd, calls[0].args, calls[0].opts];
|
|
53
|
+
assert.equal(cmd, "node");
|
|
54
|
+
assert.deepEqual(args.slice(0, 5), ["/pkg/bin/dsh-mneme-choro.mjs", "/repo", "--t1", "--apply", "--json"]);
|
|
55
|
+
assert.ok(args.includes("--module") && args.includes("src"));
|
|
56
|
+
assert.ok(args.includes("--retry-failed"));
|
|
57
|
+
assert.ok(args.includes("--db") && args.includes("/mem/memory.db"));
|
|
58
|
+
// Electron 宿主里不设这个变量会去开窗口而不是跑脚本——这条是踩过的坑。
|
|
59
|
+
assert.equal(opts.env.ELECTRON_RUN_AS_NODE, "1");
|
|
60
|
+
assert.deepEqual(opts.stdio, ["ignore", "pipe", "pipe"]);
|
|
61
|
+
jobs.dispose();
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
test("同一仓库并发 → job-running 且带回在跑的 jobId(面板据此继续轮询而不是重起)", () => {
|
|
65
|
+
const { jobs } = makeJobs();
|
|
66
|
+
const first = jobs.start({ repo });
|
|
67
|
+
const second = jobs.start({ repo });
|
|
68
|
+
assert.equal(second.started, false);
|
|
69
|
+
assert.equal(second.code, "job-running");
|
|
70
|
+
assert.equal(second.jobId, first.jobId);
|
|
71
|
+
|
|
72
|
+
// 不同仓库互不影响:并发闸是按仓库的,不是全局的。
|
|
73
|
+
const other = jobs.start({ repo: { id: 2, name: "o", root_path: "/repo2" } });
|
|
74
|
+
assert.equal(other.started, true);
|
|
75
|
+
jobs.dispose();
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
test("stdout 逐行进 logTail(封顶 200 行),chunk 切在一行中间也不丢字", async () => {
|
|
79
|
+
const { jobs, calls } = makeJobs();
|
|
80
|
+
const { jobId } = jobs.start({ repo });
|
|
81
|
+
const child = calls[0];
|
|
82
|
+
// 故意把一行拆成两个 chunk:不做余量拼接的实现会把它切成两条假日志。
|
|
83
|
+
child.stdout.emit("data", "第一行\n第二");
|
|
84
|
+
child.stdout.emit("data", "行\n");
|
|
85
|
+
let view = jobs.status(jobId);
|
|
86
|
+
assert.deepEqual(view.logTail, ["第一行", "第二行"]);
|
|
87
|
+
|
|
88
|
+
for (let i = 0; i < 300; i += 1) child.stdout.emit("data", `l${i}\n`);
|
|
89
|
+
view = jobs.status(jobId);
|
|
90
|
+
assert.equal(view.logTail.length, 200, "ring buffer 封顶:长任务 stdout 不封顶就是内存泄漏");
|
|
91
|
+
assert.equal(view.logTail[199], "l299", "留下的是最新的尾巴(面板要看的是当前在干嘛)");
|
|
92
|
+
jobs.dispose();
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
test("退出码 0 → done 且从回执读出进度;非 0 → failed 且带 stderr 尾巴", () => {
|
|
96
|
+
const { jobs, calls } = makeJobs();
|
|
97
|
+
const ok = jobs.start({ repo });
|
|
98
|
+
// CLI --json 输出的是多行 JSON(不是 NDJSON):按行收日志、按全文解析回执,两条路
|
|
99
|
+
// 各走各的,才不会互相牺牲。
|
|
100
|
+
calls[0].stdout.emit("data", JSON.stringify({ dryRun: false, enriched: [{ slug: "a" }], failed: [{ slug: "b" }] }, null, 2));
|
|
101
|
+
calls[0].emit("close", 0);
|
|
102
|
+
const done = jobs.status(ok.jobId);
|
|
103
|
+
assert.equal(done.state, "done");
|
|
104
|
+
assert.deepEqual(done.modules, { total: 2, done: 1, failed: 1 });
|
|
105
|
+
assert.ok(done.finishedAt);
|
|
106
|
+
|
|
107
|
+
const bad = jobs.start({ repo: { id: 2, name: "o", root_path: "/repo2" } });
|
|
108
|
+
calls[1].stderr.emit("data", "拒绝运行(not-registered):仓库没登记\n");
|
|
109
|
+
calls[1].emit("close", 1);
|
|
110
|
+
const failed = jobs.status(bad.jobId);
|
|
111
|
+
assert.equal(failed.state, "failed");
|
|
112
|
+
// 只报 exit code 等于让面板说「失败了,不知道为啥」——stderr 尾巴才是人话。
|
|
113
|
+
assert.match(failed.error, /not-registered/);
|
|
114
|
+
jobs.dispose();
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
test("未知 jobId → null;dispose 杀掉在跑的进程并清账", () => {
|
|
118
|
+
const { jobs, calls } = makeJobs();
|
|
119
|
+
assert.equal(jobs.status("nope"), null);
|
|
120
|
+
const { jobId } = jobs.start({ repo });
|
|
121
|
+
assert.equal(jobs.status(jobId).state, "running");
|
|
122
|
+
jobs.dispose();
|
|
123
|
+
assert.equal(calls[0].killed, true, "宿主卸载时要带走子进程,不留孤儿");
|
|
124
|
+
assert.equal(jobs.status(jobId), null);
|
|
125
|
+
});
|