rag-memory-epf-mcp 6.3.0 → 6.3.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/README.md +16 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +76 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -154,6 +154,22 @@ storeDocument(id, content, metadata)
|
|
|
154
154
|
|
|
155
155
|
## Changelog
|
|
156
156
|
|
|
157
|
+
### v6.3.1
|
|
158
|
+
|
|
159
|
+
- **Changed — the engine empties the WAL while it is idle.** It runs `wal_checkpoint(TRUNCATE)` itself:
|
|
160
|
+
on a 1 s tick whenever the `-wal` file has bytes in it, ~200 ms after a tool call, first thing in the
|
|
161
|
+
signal handler, and before closing. SQLite folds the WAL only when the *last* connection closes and
|
|
162
|
+
only if that close gets to run; with several engines on one file, or a host that kills the engine
|
|
163
|
+
(measured: codex-cli 0.155.1 sends SIGTERM and SIGKILLs ~185 ms later; Windows terminates children
|
|
164
|
+
outright), frames stayed in the WAL — on 6.3.0 a fresh database sat at 4 KB main + 663 KB WAL for as
|
|
165
|
+
long as the engine ran. In a cloud-synced folder such a WAL can be replayed onto a main file written
|
|
166
|
+
by another machine. A write made in the last ~1 s before a hard kill can still be in the WAL; a 0-byte
|
|
167
|
+
`-wal` and a `-shm` left behind by a hard kill are harmless. Running engines on two machines against
|
|
168
|
+
the same synced file at the same time is still unsafe.
|
|
169
|
+
- **Changed — SIGHUP and SIGBREAK shut the engine down cleanly.** Closing the terminal or multiplexer
|
|
170
|
+
pane used to kill the process by default signal action, before the database was closed.
|
|
171
|
+
- No tool, argument, return shape or schema changed.
|
|
172
|
+
|
|
157
173
|
### v6.3.0 (2026-09-16)
|
|
158
174
|
|
|
159
175
|
- **Changed — a relative `DB_FILE_PATH` now resolves against the server's working directory.** It used
|
package/dist/index.d.ts
CHANGED
|
@@ -101,6 +101,11 @@ export declare class RAGKnowledgeGraphManager {
|
|
|
101
101
|
description: string;
|
|
102
102
|
}>;
|
|
103
103
|
}>;
|
|
104
|
+
checkpointWal(): boolean;
|
|
105
|
+
private walTimer;
|
|
106
|
+
private walSoon;
|
|
107
|
+
startWalKeeper(tickMs?: number): void;
|
|
108
|
+
noteActivity(delayMs?: number): void;
|
|
104
109
|
cleanup(): void;
|
|
105
110
|
private _timestampObservation;
|
|
106
111
|
createEntities(entities: Array<Entity & {
|
package/dist/index.js
CHANGED
|
@@ -593,13 +593,78 @@ export class RAGKnowledgeGraphManager {
|
|
|
593
593
|
}))
|
|
594
594
|
};
|
|
595
595
|
}
|
|
596
|
+
// Fold the WAL into the main file and empty it. Returns true when the WAL holds no
|
|
597
|
+
// frames afterwards.
|
|
598
|
+
//
|
|
599
|
+
// Why the engine does this itself instead of leaving it to SQLite: SQLite folds the WAL
|
|
600
|
+
// only when the LAST connection closes, and only if that close gets to run. Neither holds
|
|
601
|
+
// here — several engines keep the same file open (one per CLI), and some hosts end the
|
|
602
|
+
// engine without letting it finish (codex-cli 0.155.1, measured: SIGTERM, then SIGKILL
|
|
603
|
+
// ~185 ms later; on Windows a child is simply terminated). A WAL with frames that outlives
|
|
604
|
+
// its process is replayed at the next open against whatever main file is there by then, and
|
|
605
|
+
// in a cloud-synced folder that can be a main file written by another machine. SQLite does
|
|
606
|
+
// not check that a WAL belongs to the main file next to it. That corrupted a live database
|
|
607
|
+
// twice. So the invariant is kept continuously: while idle, the WAL is empty.
|
|
608
|
+
//
|
|
609
|
+
// TRUNCATE, not PASSIVE: PASSIVE copies the frames into the main file but leaves them in
|
|
610
|
+
// the WAL, still valid, still replayable onto a foreign main file.
|
|
611
|
+
// busy_timeout is dropped to 0 around the call: TRUNCATE runs the busy handler, and a 5 s
|
|
612
|
+
// stall inside a signal handler or a timer tick is worse than retrying on the next tick.
|
|
613
|
+
checkpointWal() {
|
|
614
|
+
if (!this.db)
|
|
615
|
+
return true;
|
|
616
|
+
try {
|
|
617
|
+
const st = fsSync.statSync(DB_FILE_PATH + '-wal', { throwIfNoEntry: false });
|
|
618
|
+
if (!st || st.size === 0)
|
|
619
|
+
return true;
|
|
620
|
+
this.db.pragma('busy_timeout = 0');
|
|
621
|
+
try {
|
|
622
|
+
const r = this.db.pragma('wal_checkpoint(TRUNCATE)');
|
|
623
|
+
return r?.[0]?.busy === 0;
|
|
624
|
+
}
|
|
625
|
+
finally {
|
|
626
|
+
this.db.pragma('busy_timeout = 5000');
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
catch {
|
|
630
|
+
return false; // inside a transaction, or the file is locked — the next tick retries
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
walTimer = null;
|
|
634
|
+
walSoon = null;
|
|
635
|
+
// Every write path ends up here without having to be listed: the periodic tick looks at
|
|
636
|
+
// the size of the -wal file, not at which tool ran, so background writers (reconciliation,
|
|
637
|
+
// backfill) are covered as well. noteActivity() only shortens the wait after a tool call.
|
|
638
|
+
startWalKeeper(tickMs = 1000) {
|
|
639
|
+
if (this.walTimer)
|
|
640
|
+
return;
|
|
641
|
+
this.walTimer = setInterval(() => { this.checkpointWal(); }, tickMs);
|
|
642
|
+
this.walTimer.unref();
|
|
643
|
+
}
|
|
644
|
+
noteActivity(delayMs = 200) {
|
|
645
|
+
if (this.walSoon)
|
|
646
|
+
return;
|
|
647
|
+
this.walSoon = setTimeout(() => { this.walSoon = null; this.checkpointWal(); }, delayMs);
|
|
648
|
+
this.walSoon.unref();
|
|
649
|
+
}
|
|
596
650
|
cleanup() {
|
|
651
|
+
if (this.walTimer) {
|
|
652
|
+
clearInterval(this.walTimer);
|
|
653
|
+
this.walTimer = null;
|
|
654
|
+
}
|
|
655
|
+
if (this.walSoon) {
|
|
656
|
+
clearTimeout(this.walSoon);
|
|
657
|
+
this.walSoon = null;
|
|
658
|
+
}
|
|
597
659
|
if (this.encoding) {
|
|
598
660
|
this.encoding.free();
|
|
599
661
|
this.encoding = null;
|
|
600
662
|
}
|
|
601
663
|
this.embeddingCache.clear();
|
|
602
664
|
if (this.db) {
|
|
665
|
+
// close() folds the WAL only for the last connection; with other engines attached it
|
|
666
|
+
// would leave every frame behind.
|
|
667
|
+
this.checkpointWal();
|
|
603
668
|
this.db.close();
|
|
604
669
|
this.db = null;
|
|
605
670
|
}
|
|
@@ -4061,6 +4126,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4061
4126
|
try {
|
|
4062
4127
|
// Validate arguments using our structured schema
|
|
4063
4128
|
const validatedArgs = validateToolArgs(name, args);
|
|
4129
|
+
ragKgManager.noteActivity(); // fold the WAL shortly after this call, whatever it wrote
|
|
4064
4130
|
switch (name) {
|
|
4065
4131
|
// Original MCP tools
|
|
4066
4132
|
case "createEntities":
|
|
@@ -4235,6 +4301,9 @@ async function main() {
|
|
|
4235
4301
|
if (shuttingDown)
|
|
4236
4302
|
return;
|
|
4237
4303
|
shuttingDown = true;
|
|
4304
|
+
// Synchronously, before anything is awaited: a host may SIGKILL before the settle
|
|
4305
|
+
// sequence below completes (codex: ~185 ms after SIGTERM).
|
|
4306
|
+
ragKgManager.checkpointWal();
|
|
4238
4307
|
void (async () => {
|
|
4239
4308
|
try {
|
|
4240
4309
|
await server.close();
|
|
@@ -4250,6 +4319,13 @@ async function main() {
|
|
|
4250
4319
|
};
|
|
4251
4320
|
process.on('SIGINT', shutdown);
|
|
4252
4321
|
process.on('SIGTERM', shutdown);
|
|
4322
|
+
// SIGHUP = the terminal or multiplexer pane was closed. Without a handler the default
|
|
4323
|
+
// action kills the process before 'exit' listeners run, so the database is never closed.
|
|
4324
|
+
// On Windows, Node raises SIGHUP when the console window is closed and SIGBREAK on
|
|
4325
|
+
// Ctrl+Break; registering them is harmless where they never fire.
|
|
4326
|
+
process.on('SIGHUP', shutdown);
|
|
4327
|
+
process.on('SIGBREAK', shutdown);
|
|
4328
|
+
ragKgManager.startWalKeeper();
|
|
4253
4329
|
process.on('exit', () => { try {
|
|
4254
4330
|
ragKgManager.cleanup();
|
|
4255
4331
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rag-memory-epf-mcp",
|
|
3
|
-
"version": "6.3.
|
|
3
|
+
"version": "6.3.1",
|
|
4
4
|
"engines": {
|
|
5
5
|
"node": ">=24"
|
|
6
6
|
},
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"prepare": "npm run build",
|
|
46
46
|
"watch": "tsc --watch",
|
|
47
47
|
"verify:invariants": "node test/chunk-invariants.test.mjs",
|
|
48
|
-
"verify:engine": "node test/engine-smoke.test.mjs && node test/launch-smoke.test.mjs && node test/sync-atomicity.test.mjs && node test/dedup.test.mjs && node test/search-degradation.test.mjs && node test/entity-embed-cap.test.mjs && node test/migration12.test.mjs && node test/model-cache.test.mjs && node test/embedding-gate.test.mjs && node test/lazy-boot.test.mjs && node test/reconciliation.test.mjs && node test/backfill.test.mjs && node test/fts-query.test.mjs && node test/search-contracts.test.mjs && node test/tool-contracts.test.mjs && node test/bounded-exit.test.mjs && node test/observation-schema.test.mjs && node test/search-graph-default.test.mjs && node test/observation-migration.test.mjs && node test/observation-lifecycle.test.mjs && node test/observation-contracts.test.mjs && node test/observation-search.test.mjs && node test/observation-cascade.test.mjs && node test/observation-realdata.test.mjs && node test/chunker-c.test.mjs && node test/migration14.test.mjs && node test/chunk-params-validation.test.mjs && node test/vector-reuse.test.mjs && node test/entity-range-linking.test.mjs && node test/alias-link-gate.test.mjs && node test/entity-name-boundary.test.mjs && node test/stats-chunking.test.mjs && node test/migration14-realdata.test.mjs && node test/migration14-realdata-sync.test.mjs && node test/search-summaries-off.test.mjs && node test/document-return-contracts.test.mjs && node test/observation-date-prefix.test.mjs && node test/delete-entities-cascade.test.mjs && node test/delete-entities-kg-hygiene.test.mjs && node test/backup-publish-portable.test.mjs && node test/graph-context-explain.test.mjs && node test/eval-graph-role-libs.test.mjs && node test/eval-graph-role-t5b.test.mjs && node --test test/eval-graph-role-t8-fix.test.mjs && node --test test/eval-graph-role-t7-upstream.test.mjs && node --test test/eval-graph-role-t11-decision.test.mjs && node --test test/eval-graph-role-prereq-fix.test.mjs && node test/db-path.test.mjs && node test/mmap-option.test.mjs",
|
|
48
|
+
"verify:engine": "node test/engine-smoke.test.mjs && node test/launch-smoke.test.mjs && node test/sync-atomicity.test.mjs && node test/dedup.test.mjs && node test/search-degradation.test.mjs && node test/entity-embed-cap.test.mjs && node test/migration12.test.mjs && node test/model-cache.test.mjs && node test/embedding-gate.test.mjs && node test/lazy-boot.test.mjs && node test/reconciliation.test.mjs && node test/backfill.test.mjs && node test/fts-query.test.mjs && node test/search-contracts.test.mjs && node test/tool-contracts.test.mjs && node test/bounded-exit.test.mjs && node test/observation-schema.test.mjs && node test/search-graph-default.test.mjs && node test/observation-migration.test.mjs && node test/observation-lifecycle.test.mjs && node test/observation-contracts.test.mjs && node test/observation-search.test.mjs && node test/observation-cascade.test.mjs && node test/observation-realdata.test.mjs && node test/chunker-c.test.mjs && node test/migration14.test.mjs && node test/chunk-params-validation.test.mjs && node test/vector-reuse.test.mjs && node test/entity-range-linking.test.mjs && node test/alias-link-gate.test.mjs && node test/entity-name-boundary.test.mjs && node test/stats-chunking.test.mjs && node test/migration14-realdata.test.mjs && node test/migration14-realdata-sync.test.mjs && node test/search-summaries-off.test.mjs && node test/document-return-contracts.test.mjs && node test/observation-date-prefix.test.mjs && node test/delete-entities-cascade.test.mjs && node test/delete-entities-kg-hygiene.test.mjs && node test/backup-publish-portable.test.mjs && node test/graph-context-explain.test.mjs && node test/eval-graph-role-libs.test.mjs && node test/eval-graph-role-t5b.test.mjs && node --test test/eval-graph-role-t8-fix.test.mjs && node --test test/eval-graph-role-t7-upstream.test.mjs && node --test test/eval-graph-role-t11-decision.test.mjs && node --test test/eval-graph-role-prereq-fix.test.mjs && node test/db-path.test.mjs && node test/mmap-option.test.mjs && node test/wal-exit.test.mjs",
|
|
49
49
|
"test": "npm run build && npm run verify:invariants && npm run verify:engine",
|
|
50
50
|
"prepublishOnly": "npm run build && npm run verify:invariants && npm run verify:engine"
|
|
51
51
|
},
|