memory-eternal 0.10.16 → 0.10.18
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/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/.cursor-plugin/plugin.json +1 -1
- package/README.en.md +5 -3
- package/README.md +5 -3
- package/bin/dsh-memory.mjs +4 -1
- package/index.js +10 -5
- package/lib/api.js +45 -6
- package/lib/client.js +15 -15
- package/lib/watchdog.js +50 -2
- package/package.json +2 -2
- package/web/app.js +16 -16
package/lib/watchdog.js
CHANGED
|
@@ -463,6 +463,39 @@ export async function waitForServedVersion(port, expect, { timeoutMs = 15000, in
|
|
|
463
463
|
}
|
|
464
464
|
}
|
|
465
465
|
|
|
466
|
+
/**
|
|
467
|
+
* 等「**新实例真的接管了**」:端口服着期望版本 **且** 锁里出现一个不在 `beforePids` 里的活看门狗。
|
|
468
|
+
*
|
|
469
|
+
* 为什么不能只看版本(issue #28 的根):升级前后版本号常常相同、或旧实例本来就是这个版本 ——
|
|
470
|
+
* 那时「端口服着 vX」与「替换还没发生」同时为真,只看版本的自检会立刻通过。实测现场:
|
|
471
|
+
* `restart` 打印「自检通过:端口 7999 正在服务 v0.10.16(等待 0s)」,紧接着 `status` 说
|
|
472
|
+
* 「锁文件里没有登记的看门狗(没有常驻实例)」—— 状态自相矛盾,面板据此给出的结论也会是错的。
|
|
473
|
+
*
|
|
474
|
+
* @returns {Promise<{ok:boolean, version:string, waitedMs:number, tookOver:boolean}>}
|
|
475
|
+
*/
|
|
476
|
+
export async function waitForTakeover(port, expect, {
|
|
477
|
+
env = process.env, beforePids = new Set(), timeoutMs = 25000, intervalMs = 500,
|
|
478
|
+
probe, sleep, readLock,
|
|
479
|
+
} = {}) {
|
|
480
|
+
const p = Number(port) || 0
|
|
481
|
+
const want = String(expect || '')
|
|
482
|
+
const probeVersion = probe || probeServedVersion
|
|
483
|
+
const sleepFn = sleep || ((ms) => new Promise((r) => setTimeout(r, ms)))
|
|
484
|
+
const lockOf = readLock || ((e) => readWatchdogLock(e))
|
|
485
|
+
const start = Date.now()
|
|
486
|
+
let version = ''
|
|
487
|
+
for (;;) {
|
|
488
|
+
try { version = String((await probeVersion(p)) || '') } catch { version = '' }
|
|
489
|
+
let fresh = []
|
|
490
|
+
try {
|
|
491
|
+
fresh = lockOf(env).watchdogs.filter((w) => Number(w.port) === p && isPidAlive(w.pid) && !beforePids.has(Number(w.pid)))
|
|
492
|
+
} catch { fresh = [] }
|
|
493
|
+
if (version && version === want && fresh.length) return { ok: true, version, waitedMs: Date.now() - start, tookOver: true }
|
|
494
|
+
if (Date.now() - start >= Math.max(0, Number(timeoutMs) || 0)) return { ok: false, version, waitedMs: Date.now() - start, tookOver: false }
|
|
495
|
+
await sleepFn(Math.max(50, Number(intervalMs) || 500))
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
|
|
466
499
|
// -- 常驻实例的「版本漂移自愈」--------------------------------------------------
|
|
467
500
|
//
|
|
468
501
|
// 为什么需要它:常驻 web(默认 7999)**比 DSH 宿主活得久**。升级 npm 包只换磁盘上的
|
|
@@ -601,6 +634,8 @@ export async function restartResident({
|
|
|
601
634
|
const p = Number(port) || 7999
|
|
602
635
|
const expect = String(expectVersion !== undefined ? expectVersion : currentPkgVersion())
|
|
603
636
|
const before = readWatchdogLock(env).watchdogs.filter((w) => Number(w.port) === p)
|
|
637
|
+
// 替换**前**就存在的 pid(看门狗 + 它拉起的 web):自检时用来区分「还是那个旧实例」与「新实例接管了」
|
|
638
|
+
const beforePids = new Set(before.flatMap((w) => [Number(w.pid), Number(w.webPid) || 0]).filter((n) => n > 0))
|
|
604
639
|
let helperPid = 0
|
|
605
640
|
try {
|
|
606
641
|
const child = (deps.spawnHelper || spawnReplaceHelper)({ port: p, vaultRoot, interval, maxRestart })
|
|
@@ -609,7 +644,15 @@ export async function restartResident({
|
|
|
609
644
|
return { ok: false, stage: 'spawn-helper', expect, served: '', waitedMs: 0, helperPid: 0, before, error: String(error?.message || error) }
|
|
610
645
|
}
|
|
611
646
|
let check = { ok: false, version: '', waitedMs: 0 }
|
|
612
|
-
try {
|
|
647
|
+
try {
|
|
648
|
+
// 只看版本会被**旧实例**骗过(版本号常常没变)→ 自检必须等到「新看门狗接管」才认成功(#28)
|
|
649
|
+
check = await (deps.waitForTakeover || waitForTakeover)(p, expect, {
|
|
650
|
+
env, beforePids, timeoutMs,
|
|
651
|
+
probe: deps.probeServedVersion,
|
|
652
|
+
sleep: deps.sleep,
|
|
653
|
+
readLock: deps.readLock,
|
|
654
|
+
})
|
|
655
|
+
} catch { check = { ok: false, version: '', waitedMs: 0 } }
|
|
613
656
|
return {
|
|
614
657
|
ok: Boolean(check.ok),
|
|
615
658
|
stage: check.ok ? 'done' : 'verify',
|
|
@@ -618,7 +661,12 @@ export async function restartResident({
|
|
|
618
661
|
waitedMs: Number(check.waitedMs) || 0,
|
|
619
662
|
helperPid,
|
|
620
663
|
before,
|
|
621
|
-
|
|
664
|
+
// 失败原因要分清两种:版本不对(旧实例还在服务)与**没人接管**(端口服务着期望版本,
|
|
665
|
+
// 但锁里没有新的活看门狗 —— 端口上那只是旧实例/孤儿)
|
|
666
|
+
error: check.ok ? undefined : (check.version === expect && !check.tookOver
|
|
667
|
+
? `端口 ${p} 服务着 v${check.version},但没有新看门狗接管它(端口上可能仍是替换前的旧实例或孤儿)`
|
|
668
|
+
: `端口 ${p} 上服务的版本是 ${check.version || '(无响应)'},本机是 ${expect || '?'}`),
|
|
669
|
+
tookOver: Boolean(check.tookOver),
|
|
622
670
|
}
|
|
623
671
|
}
|
|
624
672
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "memory-eternal",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.18",
|
|
4
4
|
"description": "记忆核心(Memory Eternal):自研的 DeepSeek Harness 记忆插件,不移植任何既有记忆框架——对话结束后自动沉淀知识卡到本地 Markdown Vault(自研去重、自研 CJK 检索、可 git 管理),设置页提供图形化知识库(统计 / 搜索 / 知识图谱 + 侧边栏一键弹窗),Agent 通过 memory_recall 工具按需召回历史上下文。零人工干预。",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
"prepublishOnly": "node build.mjs",
|
|
65
65
|
"release": "node scripts/release.mjs",
|
|
66
66
|
"release:dry": "node scripts/release.mjs --dry-run",
|
|
67
|
-
"test": "node build.mjs && node tests/vault.test.mjs && node tests/capture.test.mjs && node tests/capture-route.test.mjs && node tests/stall.test.mjs && node tests/vault-path.test.mjs && node tests/vault-resolve.test.mjs && node tests/minhash.test.mjs && node tests/settings-save.test.mjs && node tests/config-coverage.test.mjs && node tests/config-sync.test.mjs && node tests/config-merge.test.mjs && node tests/sse.test.mjs && node tests/api.test.mjs && node tests/import-roundtrip.test.mjs && node tests/graph-perf.test.mjs && node tests/settings-compat.test.mjs && node tests/node-bin.test.mjs && node tests/watchdog-lock.test.mjs && node tests/markdown.test.mjs && node tests/feedback.test.mjs && node tests/graph-lod.test.mjs && node tests/ssr.test.mjs && node tests/web-assets.test.mjs && node tests/manifests.test.mjs && node tests/two-store.test.mjs && node tests/noise-gate.test.mjs && node tests/e2e-recall.test.mjs && node tests/issue-fixes.test.mjs && node tests/issue-fixes-2.test.mjs && node tests/issue-fixes-3.test.mjs && node tests/watchdog-orphans.test.mjs && node tests/watchdog-restart.test.mjs && node tests/readme-i18n.test.mjs && node tests/issue-fixes-4.test.mjs && node tests/host-drain.test.mjs && node tests/e2e-host-drain.mjs && node tests/issue-fixes-5.test.mjs && node tests/issue-fixes-6.test.mjs && node tests/capture-json-repair.test.mjs && node tests/csrf-origin.test.mjs && node tests/watchdog-orphan-web.test.mjs"
|
|
67
|
+
"test": "node build.mjs && node tests/vault.test.mjs && node tests/capture.test.mjs && node tests/capture-route.test.mjs && node tests/stall.test.mjs && node tests/vault-path.test.mjs && node tests/vault-resolve.test.mjs && node tests/minhash.test.mjs && node tests/settings-save.test.mjs && node tests/config-coverage.test.mjs && node tests/config-sync.test.mjs && node tests/config-merge.test.mjs && node tests/sse.test.mjs && node tests/api.test.mjs && node tests/import-roundtrip.test.mjs && node tests/graph-perf.test.mjs && node tests/settings-compat.test.mjs && node tests/node-bin.test.mjs && node tests/watchdog-lock.test.mjs && node tests/markdown.test.mjs && node tests/feedback.test.mjs && node tests/graph-lod.test.mjs && node tests/ssr.test.mjs && node tests/web-assets.test.mjs && node tests/manifests.test.mjs && node tests/two-store.test.mjs && node tests/noise-gate.test.mjs && node tests/e2e-recall.test.mjs && node tests/issue-fixes.test.mjs && node tests/issue-fixes-2.test.mjs && node tests/issue-fixes-3.test.mjs && node tests/watchdog-orphans.test.mjs && node tests/watchdog-restart.test.mjs && node tests/readme-i18n.test.mjs && node tests/issue-fixes-4.test.mjs && node tests/host-drain.test.mjs && node tests/e2e-host-drain.mjs && node tests/issue-fixes-5.test.mjs && node tests/issue-fixes-6.test.mjs && node tests/capture-json-repair.test.mjs && node tests/csrf-origin.test.mjs && node tests/watchdog-orphan-web.test.mjs && node tests/config-validate.test.mjs"
|
|
68
68
|
},
|
|
69
69
|
"dependencies": {
|
|
70
70
|
"@deepseek-ai/schemastery": "^3.18.1"
|