@modusensus/dsh-mneme 0.7.8 → 0.7.10
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 +1 -1
- package/CONTRIBUTING.md +24 -8
- package/README.md +7 -5
- package/SECURITY.md +48 -4
- package/dsh-mneme/CHANGELOG.md +24 -0
- package/dsh-mneme/README.md +9 -6
- package/dsh-mneme/lib/api.js +20 -1
- package/dsh-mneme/lib/client.js +324 -132
- package/dsh-mneme/lib/inject.js +2 -2
- package/dsh-mneme/lib/summarize.js +3 -1
- package/dsh-mneme/package-lock.json +2 -2
- package/dsh-mneme/package.json +1 -1
- package/dsh-mneme/scripts/check-sync.js +42 -0
- package/dsh-mneme/scripts/e2e-dsh.js +4 -3
- package/dsh-mneme/src/api.js +20 -1
- package/dsh-mneme/src/client.js +324 -132
- package/dsh-mneme/test/client.test.js +12 -1
- package/dsh-mneme/test/lib-smoke.test.js +109 -0
- package/package.json +2 -1
package/dsh-mneme/lib/inject.js
CHANGED
|
@@ -8,7 +8,7 @@ import { createHotMemory } from "./hot-memory.js";
|
|
|
8
8
|
// falls back to the legacy rule-based pick, never breaking the render.
|
|
9
9
|
function lastUserQuery(ctx) {
|
|
10
10
|
try {
|
|
11
|
-
const events = ctx?.agent?.session?.events;
|
|
11
|
+
const events = ctx?.agent?.session?.snapshotEvents?.() ?? ctx?.agent?.session?.events;
|
|
12
12
|
if (!Array.isArray(events) || events.length === 0) return "";
|
|
13
13
|
for (let i = events.length - 1; i >= 0; i--) {
|
|
14
14
|
const event = events[i];
|
|
@@ -34,7 +34,7 @@ function lastUserQuery(ctx) {
|
|
|
34
34
|
// returns [] on any failure, and the hot block simply does not render.
|
|
35
35
|
function extractRounds(ctx, maxRounds) {
|
|
36
36
|
try {
|
|
37
|
-
const events = ctx?.agent?.session?.events;
|
|
37
|
+
const events = ctx?.agent?.session?.snapshotEvents?.() ?? ctx?.agent?.session?.events;
|
|
38
38
|
if (!Array.isArray(events) || events.length === 0) return [];
|
|
39
39
|
const rounds = [];
|
|
40
40
|
let pendingQuery = null;
|
|
@@ -78,7 +78,9 @@ function toProtocolChunk(chunk) {
|
|
|
78
78
|
// check below.
|
|
79
79
|
function collectMessages(session) {
|
|
80
80
|
const messages = [];
|
|
81
|
-
|
|
81
|
+
// DSH 0.1.2-rc.1 起 Session 改用 snapshotEvents(),兼容旧版 .events
|
|
82
|
+
const events = session.snapshotEvents?.() ?? session.events ?? [];
|
|
83
|
+
for (const event of events) {
|
|
82
84
|
const kind = event.data?.source?.kind;
|
|
83
85
|
if (event.type !== "user/message") continue;
|
|
84
86
|
if (kind !== undefined && kind !== "user") continue;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@modusensus/dsh-mneme",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.10",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@modusensus/dsh-mneme",
|
|
9
|
-
"version": "0.7.
|
|
9
|
+
"version": "0.7.10",
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@huggingface/transformers": "^4.2.0"
|
package/dsh-mneme/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@modusensus/dsh-mneme",
|
|
3
3
|
"description": "Cross-session memory plugin for DeepSeek Harness with autoDream consolidation: SQLite store, Markdown mirrors, 7 model tools, automatic injection, session summarization, user profile/rules, custom slash commands, vector (semantic) search, and a Web GUI panel",
|
|
4
|
-
"version": "0.7.
|
|
4
|
+
"version": "0.7.10",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// 发布前校验 src/ 与 lib/ 一致性。
|
|
2
|
+
//
|
|
3
|
+
// npm 包实际加载 lib/(package main → lib/index.js),而 root 层 `npm publish`
|
|
4
|
+
// 不触发 dsh-mneme/ 的 prepack → sync 同步。历史教训:PR #60 只改了 src 忘了同步
|
|
5
|
+
// lib,v0.7.8 发出去的 npm 包跑的还是旧代码(issue #65)。此脚本让这类漂移在发布时
|
|
6
|
+
// 直接 fail,而不是带着旧产物上线。
|
|
7
|
+
//
|
|
8
|
+
// 用法:node scripts/check-sync.js (root package.json 的 prepack 钩子自动调用)
|
|
9
|
+
import { existsSync, readFileSync, readdirSync } from "node:fs";
|
|
10
|
+
import { join, relative } from "node:path";
|
|
11
|
+
import { fileURLToPath } from "node:url";
|
|
12
|
+
|
|
13
|
+
const root = join(fileURLToPath(new URL("..", import.meta.url))); // dsh-mneme/
|
|
14
|
+
const srcDir = join(root, "src");
|
|
15
|
+
const libDir = join(root, "lib");
|
|
16
|
+
|
|
17
|
+
function walk(dir) {
|
|
18
|
+
const out = [];
|
|
19
|
+
for (const entry of readdirSync(dir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
20
|
+
const full = join(dir, entry.name);
|
|
21
|
+
if (entry.isDirectory()) out.push(...walk(full));
|
|
22
|
+
else if (entry.isFile()) out.push(full);
|
|
23
|
+
}
|
|
24
|
+
return out;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const bad = [];
|
|
28
|
+
for (const file of walk(srcDir)) {
|
|
29
|
+
const rel = relative(srcDir, file);
|
|
30
|
+
const dest = join(libDir, rel);
|
|
31
|
+
if (!existsSync(dest)) {
|
|
32
|
+
bad.push(`missing lib/${rel}`);
|
|
33
|
+
} else if (!readFileSync(file).equals(readFileSync(dest))) {
|
|
34
|
+
bad.push(`differ lib/${rel}`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
if (bad.length) {
|
|
38
|
+
console.error(`✗ src/ 与 lib/ 不一致(${bad.length} 处)——npm 包实际加载 lib/,请先 npm run sync 并提交:`);
|
|
39
|
+
for (const line of bad) console.error(` ${line}`);
|
|
40
|
+
process.exit(1);
|
|
41
|
+
}
|
|
42
|
+
console.log(`✓ src/ 与 lib/ 一致(${walk(srcDir).length} 个文件)`);
|
|
@@ -106,9 +106,10 @@ console.log("【1】插件装载");
|
|
|
106
106
|
const checks = [];
|
|
107
107
|
checks.push(["注册 7 个模型工具", registeredTools.length === 7]);
|
|
108
108
|
checks.push(["注册 2 个注入上下文", injectContexts.length === 2 && injectContexts[0].name === "memory"]);
|
|
109
|
-
// 契约是
|
|
110
|
-
//
|
|
111
|
-
|
|
109
|
+
// 契约是 20 条 exact 路由(实体清单接口后由 19 条扩到 20 条);该断言此前
|
|
110
|
+
// 长期停在 9 条失去意义,现与 src/api.js 的 routes 返回值对齐,prefix
|
|
111
|
+
// fallback(/api/dsh-mneme → 404)是兜底,不计入路由数。
|
|
112
|
+
checks.push(["注册 20 条 API 路由", apiRoutes.filter((r) => r.kind === "exact").length === 20]);
|
|
112
113
|
for (const [label, ok] of checks) console.log(` ${ok ? "✅" : "❌"} ${label}`);
|
|
113
114
|
if (!checks.every(([, ok]) => ok)) { console.log("\n装载检查失败,中止。"); process.exit(1); }
|
|
114
115
|
console.log(` 工具:${registeredTools.map((t) => t.name).join(", ")}\n`);
|
package/dsh-mneme/src/api.js
CHANGED
|
@@ -637,6 +637,25 @@ export function createApi(ctx, service, settings, commands, embedder, semantic =
|
|
|
637
637
|
}
|
|
638
638
|
});
|
|
639
639
|
|
|
640
|
+
// --- entity directory (entity gene v0.3.0): read-only list for the UI ---
|
|
641
|
+
// Flat entity list (newest-seen first). Attributes and relations stay on
|
|
642
|
+
// their own per-entity endpoints, the directory only carries the columns
|
|
643
|
+
// the rail needs: name, type, mention_count, first/last seen.
|
|
644
|
+
register({
|
|
645
|
+
kind: "exact",
|
|
646
|
+
path: "/api/dsh-mneme/entities",
|
|
647
|
+
handler(req, res) {
|
|
648
|
+
try {
|
|
649
|
+
const url = new URL(req.url, "http://localhost");
|
|
650
|
+
const limit = Math.min(1000, Math.max(1, Number(url.searchParams.get("limit") ?? 500) || 500));
|
|
651
|
+
const entities = service.listEntities?.({ limit }) ?? [];
|
|
652
|
+
sendJson(res, 200, { entities, total: entities.length });
|
|
653
|
+
} catch {
|
|
654
|
+
sendJson(res, 500, { error: "internal" });
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
});
|
|
658
|
+
|
|
640
659
|
// --- health: mirror sync state (F-NEW-03 / v0.3.6) ---
|
|
641
660
|
// Auth-gated; only returns a sanitized error code (never raw last_error which
|
|
642
661
|
// may leak paths/token-like strings/internal hosts). On state read failure it
|
|
@@ -799,7 +818,7 @@ export function createApi(ctx, service, settings, commands, embedder, semantic =
|
|
|
799
818
|
});
|
|
800
819
|
|
|
801
820
|
return {
|
|
802
|
-
routes:
|
|
821
|
+
routes: 20,
|
|
803
822
|
dispose: () => {
|
|
804
823
|
for (const dispose of disposers) dispose();
|
|
805
824
|
}
|