@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.
@@ -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
- for (const event of session.events ?? []) {
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.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.7",
9
+ "version": "0.7.10",
10
10
  "license": "MIT",
11
11
  "dependencies": {
12
12
  "@huggingface/transformers": "^4.2.0"
@@ -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.8",
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
- // 契约是 9 条 exact 路由;prefix fallback(/api/dsh-mneme 404)是兜底,
110
- // 不计入路由数。
111
- checks.push(["注册 9 API 路由", apiRoutes.filter((r) => r.kind === "exact").length === 9]);
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`);
@@ -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: 19,
821
+ routes: 20,
803
822
  dispose: () => {
804
823
  for (const dispose of disposers) dispose();
805
824
  }