@remnic/plugin-openclaw 1.0.11 → 1.0.12
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/dist/capsule-cli-GBM3WPAM.js +33 -0
- package/dist/capsule-export-IXVERCQG.js +17 -0
- package/dist/{capsule-import-CFX7BY5W.js → capsule-import-IA6VIOPQ.js} +3 -3
- package/dist/{capsule-merge-7RVOHJK3.js → capsule-merge-IWOQ34KL.js} +2 -2
- package/dist/{causal-consolidation-JD6KJJH6.js → causal-consolidation-YI53C2AO.js} +3 -3
- package/dist/{chunk-K7EUBNDD.js → chunk-4LYQ4ONL.js} +1 -1
- package/dist/{chunk-N7EOZY6F.js → chunk-6F6EKSVP.js} +54 -1
- package/dist/{chunk-TNH24SF6.js → chunk-7UZNLMW5.js} +301 -125
- package/dist/{chunk-TVKKIS53.js → chunk-CDAZGIGT.js} +1 -1
- package/dist/{chunk-XMSDA5WA.js → chunk-EXDYWXMB.js} +1 -0
- package/dist/{capsule-export-CVA3CKUQ.js → chunk-FGTYFLL5.js} +21 -12
- package/dist/{chunk-ETJZRIAM.js → chunk-L6I4MQKO.js} +1 -1
- package/dist/{capsule-cli-TFKLAG3S.js → chunk-LLUROTZJ.js} +11 -12
- package/dist/{chunk-L4PRBB2A.js → chunk-OAE7AQ6R.js} +63 -91
- package/dist/{chunk-3I7RHWYT.js → chunk-RKR6PTPA.js} +105 -11
- package/dist/{chunk-P3DIW2SD.js → chunk-TILAJIJR.js} +1 -1
- package/dist/{engine-VMTFKFGO.js → engine-BIYI3P4J.js} +6 -4
- package/dist/index.js +1020 -308
- package/dist/{memory-governance-DWGFV4FX.js → memory-governance-SJ5DGRB3.js} +3 -3
- package/dist/{secure-store-FWJ7LBPH.js → secure-store-A4NGCNXV.js} +8 -2
- package/dist/{storage-T2OGFUF4.js → storage-PTQ2H2YJ.js} +2 -2
- package/dist/{types-H5R5D3WF.js → types-R4DO7AKM.js} +2 -2
- package/package.json +2 -2
- package/dist/chunk-YGXXBRV7.js +0 -10
|
@@ -3,9 +3,10 @@ import {
|
|
|
3
3
|
} from "./chunk-6OJAU466.js";
|
|
4
4
|
import {
|
|
5
5
|
SecureStoreLockedError,
|
|
6
|
+
isEncryptedFile,
|
|
6
7
|
readMaybeEncryptedFile,
|
|
7
8
|
writeMaybeEncryptedFile
|
|
8
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-RKR6PTPA.js";
|
|
9
10
|
import {
|
|
10
11
|
log
|
|
11
12
|
} from "./chunk-UFU5GGGA.js";
|
|
@@ -34,6 +35,12 @@ function setCachedEntities(baseDir, entities, version, schemaKey = "") {
|
|
|
34
35
|
loadedAt: Date.now()
|
|
35
36
|
});
|
|
36
37
|
}
|
|
38
|
+
function invalidateCachedEntities(baseDir) {
|
|
39
|
+
const prefix = `${baseDir}\0`;
|
|
40
|
+
for (const key of entityCacheByDir.keys()) {
|
|
41
|
+
if (key.startsWith(prefix)) entityCacheByDir.delete(key);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
37
44
|
var episodeMapByDir = /* @__PURE__ */ new Map();
|
|
38
45
|
var ruleMemoriesByDir = /* @__PURE__ */ new Map();
|
|
39
46
|
function getCachedEpisodeMap(baseDir, currentVersion) {
|
|
@@ -594,25 +601,44 @@ function loadBetterSqlite3() {
|
|
|
594
601
|
if (cachedCtor) return cachedCtor;
|
|
595
602
|
const require2 = createRequire(import.meta.url);
|
|
596
603
|
try {
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
if (typeof ctor !== "function") {
|
|
600
|
-
throw new Error("module did not export a constructor");
|
|
601
|
-
}
|
|
602
|
-
cachedCtor = ctor;
|
|
603
|
-
return ctor;
|
|
604
|
+
cachedCtor = requireBetterSqlite3Ctor(require2);
|
|
605
|
+
return cachedCtor;
|
|
604
606
|
} catch (error) {
|
|
605
|
-
|
|
606
|
-
throw new Error(
|
|
607
|
-
"better-sqlite3 is unavailable. Rebuild it in the plugin install with `npm rebuild better-sqlite3 --build-from-source` before using SQLite-backed Engram features" + detail,
|
|
608
|
-
{ cause: error instanceof Error ? error : void 0 }
|
|
609
|
-
);
|
|
607
|
+
throw unavailableError(error);
|
|
610
608
|
}
|
|
611
609
|
}
|
|
612
610
|
function openBetterSqlite3(file, options) {
|
|
613
611
|
const Database = loadBetterSqlite3();
|
|
614
612
|
return new Database(file, options);
|
|
615
613
|
}
|
|
614
|
+
function requireBetterSqlite3Ctor(require2) {
|
|
615
|
+
const loaded = require2("better-sqlite3");
|
|
616
|
+
const ctor = typeof loaded === "function" ? loaded : loaded.default;
|
|
617
|
+
if (typeof ctor !== "function") {
|
|
618
|
+
throw new Error("module did not export a constructor");
|
|
619
|
+
}
|
|
620
|
+
return ctor;
|
|
621
|
+
}
|
|
622
|
+
function isLikelyBetterSqlite3NativeBindingError(error) {
|
|
623
|
+
const detail = errorDetail(error);
|
|
624
|
+
return detail.includes("Could not locate the bindings file") || detail.includes("better_sqlite3.node") || detail.includes("node-v") && detail.includes("better-sqlite3") || detail.includes("NODE_MODULE_VERSION") && detail.includes("better-sqlite3") || detail.includes("was compiled against a different Node.js version");
|
|
625
|
+
}
|
|
626
|
+
function unavailableError(error) {
|
|
627
|
+
const detail = errorDetail(error);
|
|
628
|
+
const nativeBindingHint = isLikelyBetterSqlite3NativeBindingError(error) ? " This usually means the better-sqlite3 native binding was not compiled for this Node.js/platform combination. Run `node scripts/ensure-better-sqlite3.mjs` from the Remnic install directory, or run `npx node-gyp rebuild --directory=node_modules/better-sqlite3` if the verification script is unavailable." : "";
|
|
629
|
+
return new Error(
|
|
630
|
+
"better-sqlite3 is unavailable. Remnic attempted to load the native SQLite binding and could not." + nativeBindingHint + (detail ? ` Original error: ${detail}` : ""),
|
|
631
|
+
{ cause: error instanceof Error ? error : void 0 }
|
|
632
|
+
);
|
|
633
|
+
}
|
|
634
|
+
function errorDetail(error) {
|
|
635
|
+
if (error instanceof Error) {
|
|
636
|
+
const stack = error.stack && error.stack !== error.message ? `
|
|
637
|
+
${error.stack}` : "";
|
|
638
|
+
return `${error.message}${stack}`;
|
|
639
|
+
}
|
|
640
|
+
return String(error ?? "");
|
|
641
|
+
}
|
|
616
642
|
|
|
617
643
|
// ../remnic-core/src/memory-projection-store.ts
|
|
618
644
|
var MEMORY_PROJECTION_SCHEMA_VERSION = 2;
|
|
@@ -2274,13 +2300,19 @@ var ContentHashIndex = class _ContentHashIndex {
|
|
|
2274
2300
|
hashes = /* @__PURE__ */ new Set();
|
|
2275
2301
|
dirty = false;
|
|
2276
2302
|
filePath;
|
|
2277
|
-
|
|
2303
|
+
secureStoreKeyProvider;
|
|
2304
|
+
secureStoreWriteKeyProvider;
|
|
2305
|
+
memoryDir;
|
|
2306
|
+
constructor(stateDir, secureStoreKeyProvider = () => null, secureStoreWriteKeyProvider = secureStoreKeyProvider, memoryDir = path4.dirname(stateDir)) {
|
|
2278
2307
|
this.filePath = path4.join(stateDir, "fact-hashes.txt");
|
|
2308
|
+
this.secureStoreKeyProvider = secureStoreKeyProvider;
|
|
2309
|
+
this.secureStoreWriteKeyProvider = secureStoreWriteKeyProvider;
|
|
2310
|
+
this.memoryDir = memoryDir;
|
|
2279
2311
|
}
|
|
2280
2312
|
/** Load existing hashes from disk. Safe to call multiple times. */
|
|
2281
2313
|
async load() {
|
|
2282
2314
|
try {
|
|
2283
|
-
const raw = await
|
|
2315
|
+
const raw = await readMaybeEncryptedFile(this.filePath, this.secureStoreKeyProvider(), this.memoryDir);
|
|
2284
2316
|
for (const line of raw.split("\n")) {
|
|
2285
2317
|
const trimmed = line.trim();
|
|
2286
2318
|
if (trimmed.length > 0) {
|
|
@@ -2288,7 +2320,9 @@ var ContentHashIndex = class _ContentHashIndex {
|
|
|
2288
2320
|
}
|
|
2289
2321
|
}
|
|
2290
2322
|
log.debug(`content-hash index: loaded ${this.hashes.size} hashes`);
|
|
2291
|
-
} catch {
|
|
2323
|
+
} catch (err) {
|
|
2324
|
+
if (err instanceof SecureStoreLockedError) throw err;
|
|
2325
|
+
if (!isErrnoCode(err, "ENOENT")) throw err;
|
|
2292
2326
|
log.debug("content-hash index: no existing index \u2014 starting fresh");
|
|
2293
2327
|
}
|
|
2294
2328
|
}
|
|
@@ -2311,7 +2345,13 @@ var ContentHashIndex = class _ContentHashIndex {
|
|
|
2311
2345
|
async save() {
|
|
2312
2346
|
if (!this.dirty) return;
|
|
2313
2347
|
await mkdir2(path4.dirname(this.filePath), { recursive: true });
|
|
2314
|
-
await
|
|
2348
|
+
await writeMaybeEncryptedFile(
|
|
2349
|
+
this.filePath,
|
|
2350
|
+
[...this.hashes].join("\n") + "\n",
|
|
2351
|
+
this.secureStoreWriteKeyProvider(),
|
|
2352
|
+
{},
|
|
2353
|
+
this.memoryDir
|
|
2354
|
+
);
|
|
2315
2355
|
this.dirty = false;
|
|
2316
2356
|
log.debug(`content-hash index: saved ${this.hashes.size} hashes`);
|
|
2317
2357
|
}
|
|
@@ -3174,6 +3214,8 @@ var StorageManager = class _StorageManager {
|
|
|
3174
3214
|
// 1 minute
|
|
3175
3215
|
static artifactWriteVersionByDir = /* @__PURE__ */ new Map();
|
|
3176
3216
|
static memoryStatusVersionByDir = /* @__PURE__ */ new Map();
|
|
3217
|
+
static secureStoreEntityCacheKeyIds = /* @__PURE__ */ new WeakMap();
|
|
3218
|
+
static nextSecureStoreEntityCacheKeyId = 1;
|
|
3177
3219
|
// In-process fallback for the cold-write sentinel (used when the disk file
|
|
3178
3220
|
// is not accessible). The canonical source of truth is state/cold-write.log.
|
|
3179
3221
|
static coldWriteVersionByDir = /* @__PURE__ */ new Map();
|
|
@@ -3221,6 +3263,7 @@ var StorageManager = class _StorageManager {
|
|
|
3221
3263
|
factHashIndexLoadPromise = null;
|
|
3222
3264
|
factHashIndexAuthoritative = null;
|
|
3223
3265
|
factHashIndexAuthoritativePromise = null;
|
|
3266
|
+
secureAppendChains = /* @__PURE__ */ new Map();
|
|
3224
3267
|
/** Optional: set by the orchestrator after construction to enable template-aware citation stripping during legacy hash rebuild. */
|
|
3225
3268
|
citationTemplate = DEFAULT_CITATION_FORMAT;
|
|
3226
3269
|
/** Page-versioning configuration. Set by the orchestrator after construction. */
|
|
@@ -3264,6 +3307,17 @@ var StorageManager = class _StorageManager {
|
|
|
3264
3307
|
setSecureStoreKey(key, encryptOnWrite = true) {
|
|
3265
3308
|
this._secureStoreKey = key;
|
|
3266
3309
|
this._secureStoreEncryptOnWrite = encryptOnWrite;
|
|
3310
|
+
invalidateCachedEntities(this.baseDir);
|
|
3311
|
+
this.invalidateKnowledgeIndexCache();
|
|
3312
|
+
}
|
|
3313
|
+
getEntityCacheSecureStoreKey() {
|
|
3314
|
+
if (!this._secureStoreKey) return "secure-store:locked";
|
|
3315
|
+
let id = _StorageManager.secureStoreEntityCacheKeyIds.get(this._secureStoreKey);
|
|
3316
|
+
if (id === void 0) {
|
|
3317
|
+
id = _StorageManager.nextSecureStoreEntityCacheKeyId++;
|
|
3318
|
+
_StorageManager.secureStoreEntityCacheKeyIds.set(this._secureStoreKey, id);
|
|
3319
|
+
}
|
|
3320
|
+
return `secure-store:key:${id}`;
|
|
3267
3321
|
}
|
|
3268
3322
|
/**
|
|
3269
3323
|
* Mark the secure-store as required for this storage instance.
|
|
@@ -3415,6 +3469,57 @@ var StorageManager = class _StorageManager {
|
|
|
3415
3469
|
get entitiesDir() {
|
|
3416
3470
|
return path4.join(this.baseDir, "entities");
|
|
3417
3471
|
}
|
|
3472
|
+
readStorageSecureFile(filePath) {
|
|
3473
|
+
return readMaybeEncryptedFile(filePath, this._secureStoreKey, this.baseDir);
|
|
3474
|
+
}
|
|
3475
|
+
writeStorageSecureFile(filePath, content) {
|
|
3476
|
+
return writeMaybeEncryptedFile(filePath, content, this.resolveWriteKey(), {}, this.baseDir);
|
|
3477
|
+
}
|
|
3478
|
+
createContentHashIndex() {
|
|
3479
|
+
return new ContentHashIndex(
|
|
3480
|
+
this.stateDir,
|
|
3481
|
+
() => this._secureStoreKey,
|
|
3482
|
+
() => this.resolveWriteKey(),
|
|
3483
|
+
this.baseDir
|
|
3484
|
+
);
|
|
3485
|
+
}
|
|
3486
|
+
async appendStorageSecureFile(filePath, content) {
|
|
3487
|
+
const previous = this.secureAppendChains.get(filePath) ?? Promise.resolve();
|
|
3488
|
+
const current = previous.catch(() => void 0).then(() => this.appendStorageSecureFileUnlocked(filePath, content));
|
|
3489
|
+
const next = current.catch(() => void 0);
|
|
3490
|
+
this.secureAppendChains.set(filePath, next);
|
|
3491
|
+
try {
|
|
3492
|
+
await current;
|
|
3493
|
+
} finally {
|
|
3494
|
+
if (this.secureAppendChains.get(filePath) === next) {
|
|
3495
|
+
this.secureAppendChains.delete(filePath);
|
|
3496
|
+
}
|
|
3497
|
+
}
|
|
3498
|
+
}
|
|
3499
|
+
async appendStorageSecureFileUnlocked(filePath, content) {
|
|
3500
|
+
const writeKey = this.resolveWriteKey();
|
|
3501
|
+
await mkdir2(path4.dirname(filePath), { recursive: true });
|
|
3502
|
+
if (writeKey === null) {
|
|
3503
|
+
try {
|
|
3504
|
+
if (isEncryptedFile(await readFile2(filePath))) {
|
|
3505
|
+
const existing2 = await this.readStorageSecureFile(filePath);
|
|
3506
|
+
await writeMaybeEncryptedFile(filePath, `${existing2}${content}`, null, {}, this.baseDir);
|
|
3507
|
+
return;
|
|
3508
|
+
}
|
|
3509
|
+
} catch (err) {
|
|
3510
|
+
if (!isErrnoCode(err, "ENOENT")) throw err;
|
|
3511
|
+
}
|
|
3512
|
+
await appendFile(filePath, content, "utf-8");
|
|
3513
|
+
return;
|
|
3514
|
+
}
|
|
3515
|
+
let existing = "";
|
|
3516
|
+
try {
|
|
3517
|
+
existing = await this.readStorageSecureFile(filePath);
|
|
3518
|
+
} catch (err) {
|
|
3519
|
+
if (!isErrnoCode(err, "ENOENT")) throw err;
|
|
3520
|
+
}
|
|
3521
|
+
await writeMaybeEncryptedFile(filePath, `${existing}${content}`, writeKey, {}, this.baseDir);
|
|
3522
|
+
}
|
|
3418
3523
|
get stateDir() {
|
|
3419
3524
|
return path4.join(this.baseDir, "state");
|
|
3420
3525
|
}
|
|
@@ -3429,7 +3534,7 @@ var StorageManager = class _StorageManager {
|
|
|
3429
3534
|
return this.factHashIndex;
|
|
3430
3535
|
}
|
|
3431
3536
|
if (!this.factHashIndexLoadPromise) {
|
|
3432
|
-
const index =
|
|
3537
|
+
const index = this.createContentHashIndex();
|
|
3433
3538
|
this.factHashIndexLoadPromise = index.load().then(() => {
|
|
3434
3539
|
this.factHashIndex = index;
|
|
3435
3540
|
return index;
|
|
@@ -3896,9 +4001,11 @@ ${sanitized.text}
|
|
|
3896
4001
|
aliases: []
|
|
3897
4002
|
};
|
|
3898
4003
|
try {
|
|
3899
|
-
const existing = await
|
|
4004
|
+
const existing = await this.readStorageSecureFile(filePath);
|
|
3900
4005
|
entity = parseEntityFile(existing, this.entitySchemas);
|
|
3901
|
-
} catch {
|
|
4006
|
+
} catch (err) {
|
|
4007
|
+
if (err instanceof SecureStoreLockedError) throw err;
|
|
4008
|
+
if (!isErrnoCode(err, "ENOENT")) throw err;
|
|
3902
4009
|
}
|
|
3903
4010
|
const timestamp = options.timestamp?.trim() || (/* @__PURE__ */ new Date()).toISOString();
|
|
3904
4011
|
const source = options.source?.trim() || void 0;
|
|
@@ -3954,7 +4061,7 @@ ${sanitized.text}
|
|
|
3954
4061
|
entity.created = entity.created || timestamp;
|
|
3955
4062
|
entity.updated = (/* @__PURE__ */ new Date()).toISOString();
|
|
3956
4063
|
await this.snapshotBeforeWrite(filePath, "write");
|
|
3957
|
-
await
|
|
4064
|
+
await this.writeStorageSecureFile(filePath, serializeEntityFile(entity, this.entitySchemas));
|
|
3958
4065
|
this.invalidateKnowledgeIndexCache();
|
|
3959
4066
|
this.bumpMemoryStatusVersion();
|
|
3960
4067
|
log.debug(`wrote entity ${normalized}`);
|
|
@@ -4585,8 +4692,10 @@ ${memory.content}
|
|
|
4585
4692
|
}
|
|
4586
4693
|
async readEntity(name) {
|
|
4587
4694
|
try {
|
|
4588
|
-
return await
|
|
4589
|
-
} catch {
|
|
4695
|
+
return await this.readStorageSecureFile(path4.join(this.entitiesDir, `${name}.md`));
|
|
4696
|
+
} catch (err) {
|
|
4697
|
+
if (err instanceof SecureStoreLockedError) throw err;
|
|
4698
|
+
if (!isErrnoCode(err, "ENOENT")) throw err;
|
|
4590
4699
|
return "";
|
|
4591
4700
|
}
|
|
4592
4701
|
}
|
|
@@ -4767,21 +4876,23 @@ ${memory.content}
|
|
|
4767
4876
|
async loadBuffer() {
|
|
4768
4877
|
const bufferPath = path4.join(this.stateDir, "buffer.json");
|
|
4769
4878
|
try {
|
|
4770
|
-
const raw = await
|
|
4879
|
+
const raw = await this.readStorageSecureFile(bufferPath);
|
|
4771
4880
|
return JSON.parse(raw);
|
|
4772
|
-
} catch {
|
|
4881
|
+
} catch (err) {
|
|
4882
|
+
if (err instanceof SecureStoreLockedError) throw err;
|
|
4883
|
+
if (!isErrnoCode(err, "ENOENT")) throw err;
|
|
4773
4884
|
return { turns: [], lastExtractionAt: null, extractionCount: 0 };
|
|
4774
4885
|
}
|
|
4775
4886
|
}
|
|
4776
4887
|
async saveBuffer(state) {
|
|
4777
4888
|
await this.ensureDirectories();
|
|
4778
4889
|
const bufferPath = path4.join(this.stateDir, "buffer.json");
|
|
4779
|
-
await
|
|
4890
|
+
await this.writeStorageSecureFile(bufferPath, JSON.stringify(state, null, 2));
|
|
4780
4891
|
}
|
|
4781
4892
|
async loadMeta() {
|
|
4782
4893
|
const metaPath = path4.join(this.stateDir, "meta.json");
|
|
4783
4894
|
try {
|
|
4784
|
-
const raw = await
|
|
4895
|
+
const raw = await this.readStorageSecureFile(metaPath);
|
|
4785
4896
|
const parsed = JSON.parse(raw);
|
|
4786
4897
|
return {
|
|
4787
4898
|
extractionCount: typeof parsed.extractionCount === "number" ? parsed.extractionCount : 0,
|
|
@@ -4798,7 +4909,9 @@ ${memory.content}
|
|
|
4798
4909
|
observedAt: entry.observedAt
|
|
4799
4910
|
})) : []
|
|
4800
4911
|
};
|
|
4801
|
-
} catch {
|
|
4912
|
+
} catch (err) {
|
|
4913
|
+
if (err instanceof SecureStoreLockedError) throw err;
|
|
4914
|
+
if (!isErrnoCode(err, "ENOENT")) throw err;
|
|
4802
4915
|
return {
|
|
4803
4916
|
extractionCount: 0,
|
|
4804
4917
|
lastExtractionAt: null,
|
|
@@ -4812,7 +4925,7 @@ ${memory.content}
|
|
|
4812
4925
|
async saveMeta(state) {
|
|
4813
4926
|
await this.ensureDirectories();
|
|
4814
4927
|
const metaPath = path4.join(this.stateDir, "meta.json");
|
|
4815
|
-
await
|
|
4928
|
+
await this.writeStorageSecureFile(metaPath, JSON.stringify(state, null, 2));
|
|
4816
4929
|
}
|
|
4817
4930
|
async appendMemoryActionEvents(events) {
|
|
4818
4931
|
if (events.length === 0) return 0;
|
|
@@ -4826,7 +4939,7 @@ ${memory.content}
|
|
|
4826
4939
|
return `${JSON.stringify(normalized)}
|
|
4827
4940
|
`;
|
|
4828
4941
|
}).join("");
|
|
4829
|
-
await
|
|
4942
|
+
await this.appendStorageSecureFile(this.memoryActionsPath, payload);
|
|
4830
4943
|
return events.length;
|
|
4831
4944
|
}
|
|
4832
4945
|
async appendMemoryLifecycleEvents(events) {
|
|
@@ -4841,7 +4954,7 @@ ${memory.content}
|
|
|
4841
4954
|
return `${JSON.stringify(normalized)}
|
|
4842
4955
|
`;
|
|
4843
4956
|
}).join("");
|
|
4844
|
-
await
|
|
4957
|
+
await this.appendStorageSecureFile(this.memoryLifecycleLedgerPath, payload);
|
|
4845
4958
|
return events.length;
|
|
4846
4959
|
}
|
|
4847
4960
|
/**
|
|
@@ -4866,7 +4979,7 @@ ${memory.content}
|
|
|
4866
4979
|
return `${JSON.stringify(normalized)}
|
|
4867
4980
|
`;
|
|
4868
4981
|
}).join("");
|
|
4869
|
-
await
|
|
4982
|
+
await this.appendStorageSecureFile(this.bufferSurpriseLedgerPath, payload);
|
|
4870
4983
|
return events.length;
|
|
4871
4984
|
}
|
|
4872
4985
|
/**
|
|
@@ -4903,8 +5016,9 @@ ${memory.content}
|
|
|
4903
5016
|
async readBufferSurpriseEvents(options = {}) {
|
|
4904
5017
|
let raw;
|
|
4905
5018
|
try {
|
|
4906
|
-
raw = await
|
|
5019
|
+
raw = await this.readStorageSecureFile(this.bufferSurpriseLedgerPath);
|
|
4907
5020
|
} catch (err) {
|
|
5021
|
+
if (err instanceof SecureStoreLockedError) throw err;
|
|
4908
5022
|
const code = err.code;
|
|
4909
5023
|
if (code === "ENOENT") return [];
|
|
4910
5024
|
throw err;
|
|
@@ -4939,7 +5053,7 @@ ${memory.content}
|
|
|
4939
5053
|
await this.ensureDirectories();
|
|
4940
5054
|
let existingKeys = /* @__PURE__ */ new Set();
|
|
4941
5055
|
try {
|
|
4942
|
-
const raw = await
|
|
5056
|
+
const raw = await this.readStorageSecureFile(this.behaviorSignalsPath);
|
|
4943
5057
|
const lines = raw.split("\n");
|
|
4944
5058
|
for (const line of lines) {
|
|
4945
5059
|
const row = line.trim();
|
|
@@ -4952,7 +5066,9 @@ ${memory.content}
|
|
|
4952
5066
|
} catch {
|
|
4953
5067
|
}
|
|
4954
5068
|
}
|
|
4955
|
-
} catch {
|
|
5069
|
+
} catch (err) {
|
|
5070
|
+
if (err instanceof SecureStoreLockedError) throw err;
|
|
5071
|
+
if (!isErrnoCode(err, "ENOENT")) throw err;
|
|
4956
5072
|
existingKeys = /* @__PURE__ */ new Set();
|
|
4957
5073
|
}
|
|
4958
5074
|
const nowIso = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -4969,7 +5085,7 @@ ${memory.content}
|
|
|
4969
5085
|
if (deduped.length === 0) return 0;
|
|
4970
5086
|
const payload = deduped.map((event) => `${JSON.stringify(event)}
|
|
4971
5087
|
`).join("");
|
|
4972
|
-
await
|
|
5088
|
+
await this.appendStorageSecureFile(this.behaviorSignalsPath, payload);
|
|
4973
5089
|
return deduped.length;
|
|
4974
5090
|
}
|
|
4975
5091
|
async appendReextractJobs(events) {
|
|
@@ -4978,9 +5094,11 @@ ${memory.content}
|
|
|
4978
5094
|
const filePath = path4.join(this.stateDir, "reextract-jobs.jsonl");
|
|
4979
5095
|
const lines = events.map((event) => JSON.stringify(event)).join("\n") + "\n";
|
|
4980
5096
|
try {
|
|
4981
|
-
await
|
|
5097
|
+
await this.appendStorageSecureFile(filePath, lines);
|
|
4982
5098
|
return events.length;
|
|
4983
|
-
} catch {
|
|
5099
|
+
} catch (err) {
|
|
5100
|
+
if (err instanceof SecureStoreLockedError) throw err;
|
|
5101
|
+
if (!isErrnoCode(err, "ENOENT")) throw err;
|
|
4984
5102
|
return 0;
|
|
4985
5103
|
}
|
|
4986
5104
|
}
|
|
@@ -4988,7 +5106,7 @@ ${memory.content}
|
|
|
4988
5106
|
const safeLimit = Number.isFinite(limit) ? Math.max(1, Math.min(1e3, Math.floor(limit))) : 200;
|
|
4989
5107
|
const filePath = path4.join(this.stateDir, "reextract-jobs.jsonl");
|
|
4990
5108
|
try {
|
|
4991
|
-
const raw = await
|
|
5109
|
+
const raw = await this.readStorageSecureFile(filePath);
|
|
4992
5110
|
const lines = raw.split("\n").filter((line) => line.trim().length > 0);
|
|
4993
5111
|
const parsed = [];
|
|
4994
5112
|
for (const line of lines) {
|
|
@@ -5008,7 +5126,9 @@ ${memory.content}
|
|
|
5008
5126
|
}
|
|
5009
5127
|
}
|
|
5010
5128
|
return parsed.slice(-safeLimit);
|
|
5011
|
-
} catch {
|
|
5129
|
+
} catch (err) {
|
|
5130
|
+
if (err instanceof SecureStoreLockedError) throw err;
|
|
5131
|
+
if (!isErrnoCode(err, "ENOENT")) throw err;
|
|
5012
5132
|
return [];
|
|
5013
5133
|
}
|
|
5014
5134
|
}
|
|
@@ -5016,7 +5136,7 @@ ${memory.content}
|
|
|
5016
5136
|
const cappedLimit = Math.max(0, Math.floor(limit));
|
|
5017
5137
|
if (cappedLimit === 0) return [];
|
|
5018
5138
|
try {
|
|
5019
|
-
const raw = await
|
|
5139
|
+
const raw = await this.readStorageSecureFile(this.behaviorSignalsPath);
|
|
5020
5140
|
const out = [];
|
|
5021
5141
|
const lines = raw.split("\n");
|
|
5022
5142
|
for (let i = lines.length - 1; i >= 0 && out.length < cappedLimit; i -= 1) {
|
|
@@ -5031,15 +5151,20 @@ ${memory.content}
|
|
|
5031
5151
|
}
|
|
5032
5152
|
}
|
|
5033
5153
|
return out.reverse();
|
|
5034
|
-
} catch {
|
|
5154
|
+
} catch (err) {
|
|
5155
|
+
if (err instanceof SecureStoreLockedError) throw err;
|
|
5156
|
+
if (!isErrnoCode(err, "ENOENT")) throw err;
|
|
5035
5157
|
return [];
|
|
5036
5158
|
}
|
|
5037
5159
|
}
|
|
5038
5160
|
async readMemoryActionEvents(limit = 200) {
|
|
5161
|
+
return (await this.readMemoryActionEventRows(limit)).map((row) => row.event);
|
|
5162
|
+
}
|
|
5163
|
+
async readMemoryActionEventRows(limit = 200) {
|
|
5039
5164
|
const cappedLimit = Math.max(0, Math.floor(limit));
|
|
5040
5165
|
if (cappedLimit === 0) return [];
|
|
5041
5166
|
try {
|
|
5042
|
-
const raw = await
|
|
5167
|
+
const raw = await this.readStorageSecureFile(this.memoryActionsPath);
|
|
5043
5168
|
const out = [];
|
|
5044
5169
|
const lines = raw.split("\n");
|
|
5045
5170
|
for (let i = lines.length - 1; i >= 0 && out.length < cappedLimit; i -= 1) {
|
|
@@ -5047,20 +5172,29 @@ ${memory.content}
|
|
|
5047
5172
|
if (!line) continue;
|
|
5048
5173
|
try {
|
|
5049
5174
|
const parsed = JSON.parse(line);
|
|
5050
|
-
|
|
5051
|
-
|
|
5175
|
+
const outcome = parsed.outcome === "applied" || parsed.outcome === "skipped" || parsed.outcome === "failed" ? parsed.outcome : null;
|
|
5176
|
+
if (typeof parsed.timestamp === "string" && typeof parsed.action === "string" && outcome !== null) {
|
|
5177
|
+
out.push({
|
|
5178
|
+
line: i + 1,
|
|
5179
|
+
event: {
|
|
5180
|
+
...parsed,
|
|
5181
|
+
outcome
|
|
5182
|
+
}
|
|
5183
|
+
});
|
|
5052
5184
|
}
|
|
5053
5185
|
} catch {
|
|
5054
5186
|
}
|
|
5055
5187
|
}
|
|
5056
5188
|
return out.reverse();
|
|
5057
|
-
} catch {
|
|
5189
|
+
} catch (err) {
|
|
5190
|
+
if (err instanceof SecureStoreLockedError) throw err;
|
|
5191
|
+
if (!isErrnoCode(err, "ENOENT")) throw err;
|
|
5058
5192
|
return [];
|
|
5059
5193
|
}
|
|
5060
5194
|
}
|
|
5061
5195
|
async readAllMemoryLifecycleEvents() {
|
|
5062
5196
|
try {
|
|
5063
|
-
const raw = await
|
|
5197
|
+
const raw = await this.readStorageSecureFile(this.memoryLifecycleLedgerPath);
|
|
5064
5198
|
const out = [];
|
|
5065
5199
|
const lines = raw.split("\n");
|
|
5066
5200
|
for (const line of lines) {
|
|
@@ -5075,7 +5209,9 @@ ${memory.content}
|
|
|
5075
5209
|
}
|
|
5076
5210
|
}
|
|
5077
5211
|
return sortMemoryLifecycleEvents(out);
|
|
5078
|
-
} catch {
|
|
5212
|
+
} catch (err) {
|
|
5213
|
+
if (err instanceof SecureStoreLockedError) throw err;
|
|
5214
|
+
if (!isErrnoCode(err, "ENOENT")) throw err;
|
|
5079
5215
|
return [];
|
|
5080
5216
|
}
|
|
5081
5217
|
}
|
|
@@ -5087,35 +5223,39 @@ ${memory.content}
|
|
|
5087
5223
|
}
|
|
5088
5224
|
async writeCompressionGuidelines(content) {
|
|
5089
5225
|
await this.ensureDirectories();
|
|
5090
|
-
await
|
|
5226
|
+
await this.writeStorageSecureFile(this.compressionGuidelinesPath, content);
|
|
5091
5227
|
}
|
|
5092
5228
|
async readCompressionGuidelines() {
|
|
5093
5229
|
try {
|
|
5094
|
-
return await
|
|
5095
|
-
} catch {
|
|
5230
|
+
return await this.readStorageSecureFile(this.compressionGuidelinesPath);
|
|
5231
|
+
} catch (err) {
|
|
5232
|
+
if (err instanceof SecureStoreLockedError) throw err;
|
|
5233
|
+
if (!isErrnoCode(err, "ENOENT")) throw err;
|
|
5096
5234
|
return null;
|
|
5097
5235
|
}
|
|
5098
5236
|
}
|
|
5099
5237
|
async writeCompressionGuidelineDraft(content) {
|
|
5100
5238
|
await this.ensureDirectories();
|
|
5101
|
-
await
|
|
5239
|
+
await this.writeStorageSecureFile(this.compressionGuidelineDraftPath, content);
|
|
5102
5240
|
}
|
|
5103
5241
|
async readCompressionGuidelineDraft() {
|
|
5104
5242
|
try {
|
|
5105
|
-
return await
|
|
5106
|
-
} catch {
|
|
5243
|
+
return await this.readStorageSecureFile(this.compressionGuidelineDraftPath);
|
|
5244
|
+
} catch (err) {
|
|
5245
|
+
if (err instanceof SecureStoreLockedError) throw err;
|
|
5246
|
+
if (!isErrnoCode(err, "ENOENT")) throw err;
|
|
5107
5247
|
return null;
|
|
5108
5248
|
}
|
|
5109
5249
|
}
|
|
5110
5250
|
async writeCompressionGuidelineOptimizerState(state) {
|
|
5111
5251
|
await this.ensureDirectories();
|
|
5112
|
-
await
|
|
5113
|
-
|
|
5252
|
+
await this.writeStorageSecureFile(this.compressionGuidelineStatePath, `${JSON.stringify(state, null, 2)}
|
|
5253
|
+
`);
|
|
5114
5254
|
}
|
|
5115
5255
|
async writeCompressionGuidelineDraftState(state) {
|
|
5116
5256
|
await this.ensureDirectories();
|
|
5117
|
-
await
|
|
5118
|
-
|
|
5257
|
+
await this.writeStorageSecureFile(this.compressionGuidelineDraftStatePath, `${JSON.stringify(state, null, 2)}
|
|
5258
|
+
`);
|
|
5119
5259
|
}
|
|
5120
5260
|
async readCompressionGuidelineOptimizerState() {
|
|
5121
5261
|
return this.readCompressionGuidelineStateFile(this.compressionGuidelineStatePath);
|
|
@@ -5163,7 +5303,7 @@ ${memory.content}
|
|
|
5163
5303
|
return typeof rule.action === "string" && typeof rule.delta === "number" && Number.isFinite(rule.delta) && (rule.direction === "increase" || rule.direction === "decrease" || rule.direction === "hold") && (rule.confidence === "low" || rule.confidence === "medium" || rule.confidence === "high") && Array.isArray(rule.notes) && rule.notes.every((note) => typeof note === "string");
|
|
5164
5304
|
};
|
|
5165
5305
|
try {
|
|
5166
|
-
const raw = await
|
|
5306
|
+
const raw = await this.readStorageSecureFile(filePath);
|
|
5167
5307
|
const parsed = JSON.parse(raw);
|
|
5168
5308
|
const sourceWindow = parsed?.sourceWindow;
|
|
5169
5309
|
const eventCounts = parsed?.eventCounts;
|
|
@@ -5193,18 +5333,21 @@ ${memory.content}
|
|
|
5193
5333
|
...actionSummaries ? { actionSummaries } : {},
|
|
5194
5334
|
...ruleUpdates ? { ruleUpdates } : {}
|
|
5195
5335
|
};
|
|
5196
|
-
} catch {
|
|
5336
|
+
} catch (err) {
|
|
5337
|
+
if (err instanceof SecureStoreLockedError) throw err;
|
|
5338
|
+
if (!isErrnoCode(err, "ENOENT")) throw err;
|
|
5197
5339
|
return null;
|
|
5198
5340
|
}
|
|
5199
5341
|
}
|
|
5200
5342
|
async writeIdentityAnchor(content) {
|
|
5201
5343
|
await this.ensureDirectories();
|
|
5202
|
-
await
|
|
5344
|
+
await this.writeStorageSecureFile(this.identityAnchorPath, content);
|
|
5203
5345
|
}
|
|
5204
5346
|
async readIdentityAnchor() {
|
|
5205
5347
|
try {
|
|
5206
|
-
return await
|
|
5207
|
-
} catch {
|
|
5348
|
+
return await this.readStorageSecureFile(this.identityAnchorPath);
|
|
5349
|
+
} catch (err) {
|
|
5350
|
+
if (!isErrnoCode(err, "ENOENT")) throw err;
|
|
5208
5351
|
return null;
|
|
5209
5352
|
}
|
|
5210
5353
|
}
|
|
@@ -5216,7 +5359,7 @@ ${memory.content}
|
|
|
5216
5359
|
const id = this.generateId("incident");
|
|
5217
5360
|
const incident = createContinuityIncidentRecord(id, input, nowIso);
|
|
5218
5361
|
const filePath = path4.join(this.identityIncidentsDir, `${date}-${id}.md`);
|
|
5219
|
-
await
|
|
5362
|
+
await this.writeStorageSecureFile(filePath, serializeContinuityIncident(incident));
|
|
5220
5363
|
return { ...incident, filePath };
|
|
5221
5364
|
}
|
|
5222
5365
|
async readContinuityIncidents(limit = 200, state = "all") {
|
|
@@ -5230,16 +5373,19 @@ ${memory.content}
|
|
|
5230
5373
|
if (incidents.length >= cappedLimit) break;
|
|
5231
5374
|
const filePath = path4.join(this.identityIncidentsDir, file);
|
|
5232
5375
|
try {
|
|
5233
|
-
const raw = await
|
|
5376
|
+
const raw = await this.readStorageSecureFile(filePath);
|
|
5234
5377
|
const parsed = parseContinuityIncident(raw);
|
|
5235
5378
|
if (!parsed) continue;
|
|
5236
5379
|
if (state !== "all" && parsed.state !== state) continue;
|
|
5237
5380
|
incidents.push({ ...parsed, filePath });
|
|
5238
|
-
} catch {
|
|
5381
|
+
} catch (err) {
|
|
5382
|
+
if (err instanceof SecureStoreLockedError) throw err;
|
|
5239
5383
|
}
|
|
5240
5384
|
}
|
|
5241
5385
|
return incidents;
|
|
5242
|
-
} catch {
|
|
5386
|
+
} catch (err) {
|
|
5387
|
+
if (err instanceof SecureStoreLockedError) throw err;
|
|
5388
|
+
if (!isErrnoCode(err, "ENOENT")) throw err;
|
|
5243
5389
|
return [];
|
|
5244
5390
|
}
|
|
5245
5391
|
}
|
|
@@ -5249,7 +5395,7 @@ ${memory.content}
|
|
|
5249
5395
|
if (!target || !directFilePath) return null;
|
|
5250
5396
|
if (target.state === "closed") return target;
|
|
5251
5397
|
const closed = closeContinuityIncidentRecord(target, closure, (/* @__PURE__ */ new Date()).toISOString());
|
|
5252
|
-
await
|
|
5398
|
+
await this.writeStorageSecureFile(directFilePath, serializeContinuityIncident(closed));
|
|
5253
5399
|
return { ...closed, filePath: directFilePath };
|
|
5254
5400
|
}
|
|
5255
5401
|
async writeIdentityAudit(period, key, content) {
|
|
@@ -5257,26 +5403,29 @@ ${memory.content}
|
|
|
5257
5403
|
const safeKey = this.sanitizeIdentityAuditKey(key);
|
|
5258
5404
|
const dir = period === "weekly" ? this.identityAuditsWeeklyDir : this.identityAuditsMonthlyDir;
|
|
5259
5405
|
const filePath = path4.join(dir, `${safeKey}.md`);
|
|
5260
|
-
await
|
|
5406
|
+
await this.writeStorageSecureFile(filePath, content);
|
|
5261
5407
|
return filePath;
|
|
5262
5408
|
}
|
|
5263
5409
|
async readIdentityAudit(period, key) {
|
|
5264
5410
|
try {
|
|
5265
5411
|
const safeKey = this.sanitizeIdentityAuditKey(key);
|
|
5266
5412
|
const dir = period === "weekly" ? this.identityAuditsWeeklyDir : this.identityAuditsMonthlyDir;
|
|
5267
|
-
return await
|
|
5268
|
-
} catch {
|
|
5413
|
+
return await this.readStorageSecureFile(path4.join(dir, `${safeKey}.md`));
|
|
5414
|
+
} catch (err) {
|
|
5415
|
+
if (err instanceof Error && err.message === "Invalid identity audit key") return null;
|
|
5416
|
+
if (!isErrnoCode(err, "ENOENT")) throw err;
|
|
5269
5417
|
return null;
|
|
5270
5418
|
}
|
|
5271
5419
|
}
|
|
5272
5420
|
async writeIdentityImprovementLoops(content) {
|
|
5273
5421
|
await this.ensureDirectories();
|
|
5274
|
-
await
|
|
5422
|
+
await this.writeStorageSecureFile(this.identityImprovementLoopsPath, content);
|
|
5275
5423
|
}
|
|
5276
5424
|
async readIdentityImprovementLoops() {
|
|
5277
5425
|
try {
|
|
5278
|
-
return await
|
|
5279
|
-
} catch {
|
|
5426
|
+
return await this.readStorageSecureFile(this.identityImprovementLoopsPath);
|
|
5427
|
+
} catch (err) {
|
|
5428
|
+
if (!isErrnoCode(err, "ENOENT")) throw err;
|
|
5280
5429
|
return null;
|
|
5281
5430
|
}
|
|
5282
5431
|
}
|
|
@@ -5313,10 +5462,11 @@ ${memory.content}
|
|
|
5313
5462
|
}
|
|
5314
5463
|
async readContinuityIncidentFile(filePath) {
|
|
5315
5464
|
try {
|
|
5316
|
-
const raw = await
|
|
5465
|
+
const raw = await this.readStorageSecureFile(filePath);
|
|
5317
5466
|
const parsed = parseContinuityIncident(raw);
|
|
5318
5467
|
return parsed ? { ...parsed, filePath } : null;
|
|
5319
|
-
} catch {
|
|
5468
|
+
} catch (err) {
|
|
5469
|
+
if (err instanceof SecureStoreLockedError) throw err;
|
|
5320
5470
|
return null;
|
|
5321
5471
|
}
|
|
5322
5472
|
}
|
|
@@ -5515,20 +5665,22 @@ ${reflection}
|
|
|
5515
5665
|
}
|
|
5516
5666
|
async readIdentityReflections() {
|
|
5517
5667
|
try {
|
|
5518
|
-
return await
|
|
5519
|
-
} catch {
|
|
5668
|
+
return await this.readStorageSecureFile(this.identityReflectionsPath);
|
|
5669
|
+
} catch (err) {
|
|
5670
|
+
if (!isErrnoCode(err, "ENOENT")) throw err;
|
|
5520
5671
|
return null;
|
|
5521
5672
|
}
|
|
5522
5673
|
}
|
|
5523
5674
|
async writeIdentityReflections(content) {
|
|
5524
5675
|
await mkdir2(this.identityDir, { recursive: true });
|
|
5525
|
-
await
|
|
5676
|
+
await this.writeStorageSecureFile(this.identityReflectionsPath, content);
|
|
5526
5677
|
}
|
|
5527
5678
|
async appendIdentityReflection(reflection) {
|
|
5528
5679
|
let existing = "";
|
|
5529
5680
|
try {
|
|
5530
|
-
existing = await
|
|
5531
|
-
} catch {
|
|
5681
|
+
existing = await this.readStorageSecureFile(this.identityReflectionsPath);
|
|
5682
|
+
} catch (err) {
|
|
5683
|
+
if (!isErrnoCode(err, "ENOENT")) throw err;
|
|
5532
5684
|
}
|
|
5533
5685
|
if (existing.length > _StorageManager.IDENTITY_MAX_BYTES) {
|
|
5534
5686
|
log.debug(
|
|
@@ -5553,7 +5705,7 @@ ${reflection}
|
|
|
5553
5705
|
${reflection}
|
|
5554
5706
|
`;
|
|
5555
5707
|
await mkdir2(this.identityDir, { recursive: true });
|
|
5556
|
-
await
|
|
5708
|
+
await this.writeStorageSecureFile(this.identityReflectionsPath, `${existing.trimEnd()}${section}`);
|
|
5557
5709
|
log.debug(`appended namespace-local reflection to ${this.identityReflectionsPath}`);
|
|
5558
5710
|
}
|
|
5559
5711
|
// ---------------------------------------------------------------------------
|
|
@@ -5567,9 +5719,11 @@ ${reflection}
|
|
|
5567
5719
|
const filePath = path4.join(this.entitiesDir, `${name}.md`);
|
|
5568
5720
|
let entity;
|
|
5569
5721
|
try {
|
|
5570
|
-
const content = await
|
|
5722
|
+
const content = await this.readStorageSecureFile(filePath);
|
|
5571
5723
|
entity = parseEntityFile(content, this.entitySchemas);
|
|
5572
|
-
} catch {
|
|
5724
|
+
} catch (err) {
|
|
5725
|
+
if (err instanceof SecureStoreLockedError) throw err;
|
|
5726
|
+
if (!isErrnoCode(err, "ENOENT")) throw err;
|
|
5573
5727
|
log.debug(`addEntityRelationship: entity file ${name}.md not found`);
|
|
5574
5728
|
return;
|
|
5575
5729
|
}
|
|
@@ -5579,7 +5733,7 @@ ${reflection}
|
|
|
5579
5733
|
if (exists) return;
|
|
5580
5734
|
entity.relationships.push(rel);
|
|
5581
5735
|
entity.updated = (/* @__PURE__ */ new Date()).toISOString();
|
|
5582
|
-
await
|
|
5736
|
+
await this.writeStorageSecureFile(filePath, serializeEntityFile(entity, this.entitySchemas));
|
|
5583
5737
|
this.invalidateKnowledgeIndexCache();
|
|
5584
5738
|
}
|
|
5585
5739
|
/**
|
|
@@ -5590,9 +5744,11 @@ ${reflection}
|
|
|
5590
5744
|
const filePath = path4.join(this.entitiesDir, `${name}.md`);
|
|
5591
5745
|
let entity;
|
|
5592
5746
|
try {
|
|
5593
|
-
const content = await
|
|
5747
|
+
const content = await this.readStorageSecureFile(filePath);
|
|
5594
5748
|
entity = parseEntityFile(content, this.entitySchemas);
|
|
5595
|
-
} catch {
|
|
5749
|
+
} catch (err) {
|
|
5750
|
+
if (err instanceof SecureStoreLockedError) throw err;
|
|
5751
|
+
if (!isErrnoCode(err, "ENOENT")) throw err;
|
|
5596
5752
|
log.debug(`addEntityActivity: entity file ${name}.md not found`);
|
|
5597
5753
|
return;
|
|
5598
5754
|
}
|
|
@@ -5601,7 +5757,7 @@ ${reflection}
|
|
|
5601
5757
|
entity.activity = entity.activity.slice(0, maxEntries);
|
|
5602
5758
|
}
|
|
5603
5759
|
entity.updated = (/* @__PURE__ */ new Date()).toISOString();
|
|
5604
|
-
await
|
|
5760
|
+
await this.writeStorageSecureFile(filePath, serializeEntityFile(entity, this.entitySchemas));
|
|
5605
5761
|
this.invalidateKnowledgeIndexCache();
|
|
5606
5762
|
}
|
|
5607
5763
|
/**
|
|
@@ -5611,16 +5767,18 @@ ${reflection}
|
|
|
5611
5767
|
const filePath = path4.join(this.entitiesDir, `${name}.md`);
|
|
5612
5768
|
let entity;
|
|
5613
5769
|
try {
|
|
5614
|
-
const content = await
|
|
5770
|
+
const content = await this.readStorageSecureFile(filePath);
|
|
5615
5771
|
entity = parseEntityFile(content, this.entitySchemas);
|
|
5616
|
-
} catch {
|
|
5772
|
+
} catch (err) {
|
|
5773
|
+
if (err instanceof SecureStoreLockedError) throw err;
|
|
5774
|
+
if (!isErrnoCode(err, "ENOENT")) throw err;
|
|
5617
5775
|
log.debug(`addEntityAlias: entity file ${name}.md not found`);
|
|
5618
5776
|
return;
|
|
5619
5777
|
}
|
|
5620
5778
|
if (entity.aliases.includes(alias)) return;
|
|
5621
5779
|
entity.aliases.push(alias);
|
|
5622
5780
|
entity.updated = (/* @__PURE__ */ new Date()).toISOString();
|
|
5623
|
-
await
|
|
5781
|
+
await this.writeStorageSecureFile(filePath, serializeEntityFile(entity, this.entitySchemas));
|
|
5624
5782
|
this.invalidateKnowledgeIndexCache();
|
|
5625
5783
|
}
|
|
5626
5784
|
/**
|
|
@@ -5630,9 +5788,11 @@ ${reflection}
|
|
|
5630
5788
|
const filePath = path4.join(this.entitiesDir, `${name}.md`);
|
|
5631
5789
|
let entity;
|
|
5632
5790
|
try {
|
|
5633
|
-
const content = await
|
|
5791
|
+
const content = await this.readStorageSecureFile(filePath);
|
|
5634
5792
|
entity = parseEntityFile(content, this.entitySchemas);
|
|
5635
|
-
} catch {
|
|
5793
|
+
} catch (err) {
|
|
5794
|
+
if (err instanceof SecureStoreLockedError) throw err;
|
|
5795
|
+
if (!isErrnoCode(err, "ENOENT")) throw err;
|
|
5636
5796
|
log.debug(`updateEntitySynthesis: entity file ${name}.md not found`);
|
|
5637
5797
|
return;
|
|
5638
5798
|
}
|
|
@@ -5649,7 +5809,7 @@ ${reflection}
|
|
|
5649
5809
|
entity.synthesisStructuredFactDigest = synthesisStructuredFactDigest;
|
|
5650
5810
|
entity.synthesisVersion = Math.max(0, entity.synthesisVersion ?? 0) + (options.incrementVersion === false ? 0 : 1);
|
|
5651
5811
|
entity.updated = entityUpdatedAt;
|
|
5652
|
-
await
|
|
5812
|
+
await this.writeStorageSecureFile(filePath, serializeEntityFile(entity, this.entitySchemas));
|
|
5653
5813
|
await this.removeEntitySynthesisQueueEntries([
|
|
5654
5814
|
.../* @__PURE__ */ new Set([name, normalizeEntityName(entity.name, entity.type)])
|
|
5655
5815
|
]);
|
|
@@ -5664,9 +5824,11 @@ ${reflection}
|
|
|
5664
5824
|
let synthesisTimelineCount;
|
|
5665
5825
|
try {
|
|
5666
5826
|
const filePath = path4.join(this.entitiesDir, `${name}.md`);
|
|
5667
|
-
const content = await
|
|
5827
|
+
const content = await this.readStorageSecureFile(filePath);
|
|
5668
5828
|
synthesisTimelineCount = parseEntityFile(content, this.entitySchemas).timeline.length;
|
|
5669
|
-
} catch {
|
|
5829
|
+
} catch (err) {
|
|
5830
|
+
if (err instanceof SecureStoreLockedError) throw err;
|
|
5831
|
+
if (!isErrnoCode(err, "ENOENT")) throw err;
|
|
5670
5832
|
synthesisTimelineCount = void 0;
|
|
5671
5833
|
}
|
|
5672
5834
|
await this.updateEntitySynthesis(name, summary, {
|
|
@@ -5677,10 +5839,12 @@ ${reflection}
|
|
|
5677
5839
|
}
|
|
5678
5840
|
async readEntitySynthesisQueue() {
|
|
5679
5841
|
try {
|
|
5680
|
-
const raw = await
|
|
5842
|
+
const raw = await this.readStorageSecureFile(this.entitySynthesisQueuePath);
|
|
5681
5843
|
const parsed = JSON.parse(raw);
|
|
5682
5844
|
return Array.isArray(parsed.entityNames) ? parsed.entityNames.filter((value) => typeof value === "string") : [];
|
|
5683
|
-
} catch {
|
|
5845
|
+
} catch (err) {
|
|
5846
|
+
if (err instanceof SecureStoreLockedError) throw err;
|
|
5847
|
+
if (!isErrnoCode(err, "ENOENT")) throw err;
|
|
5684
5848
|
return [];
|
|
5685
5849
|
}
|
|
5686
5850
|
}
|
|
@@ -5702,7 +5866,7 @@ ${reflection}
|
|
|
5702
5866
|
return compareEntityTimestamps(rightTs, leftTs);
|
|
5703
5867
|
}).map(({ entityName }) => entityName);
|
|
5704
5868
|
await mkdir2(this.stateDir, { recursive: true });
|
|
5705
|
-
await
|
|
5869
|
+
await this.writeStorageSecureFile(
|
|
5706
5870
|
this.entitySynthesisQueuePath,
|
|
5707
5871
|
JSON.stringify(
|
|
5708
5872
|
{
|
|
@@ -5711,8 +5875,7 @@ ${reflection}
|
|
|
5711
5875
|
},
|
|
5712
5876
|
null,
|
|
5713
5877
|
2
|
|
5714
|
-
) + "\n"
|
|
5715
|
-
"utf-8"
|
|
5878
|
+
) + "\n"
|
|
5716
5879
|
);
|
|
5717
5880
|
return staleEntityNames;
|
|
5718
5881
|
}
|
|
@@ -5723,7 +5886,7 @@ ${reflection}
|
|
|
5723
5886
|
const removals = new Set(entityNames);
|
|
5724
5887
|
const nextQueue = queue.filter((name) => !removals.has(name));
|
|
5725
5888
|
await mkdir2(this.stateDir, { recursive: true });
|
|
5726
|
-
await
|
|
5889
|
+
await this.writeStorageSecureFile(
|
|
5727
5890
|
this.entitySynthesisQueuePath,
|
|
5728
5891
|
JSON.stringify(
|
|
5729
5892
|
{
|
|
@@ -5732,8 +5895,7 @@ ${reflection}
|
|
|
5732
5895
|
},
|
|
5733
5896
|
null,
|
|
5734
5897
|
2
|
|
5735
|
-
) + "\n"
|
|
5736
|
-
"utf-8"
|
|
5898
|
+
) + "\n"
|
|
5737
5899
|
);
|
|
5738
5900
|
}
|
|
5739
5901
|
async migrateEntityFilesToCompiledTruthTimeline() {
|
|
@@ -5744,7 +5906,7 @@ ${reflection}
|
|
|
5744
5906
|
if (!raw) continue;
|
|
5745
5907
|
const serialized = serializeEntityFile(parseEntityFile(raw, this.entitySchemas), this.entitySchemas);
|
|
5746
5908
|
if (raw.trimEnd() === serialized.trimEnd()) continue;
|
|
5747
|
-
await
|
|
5909
|
+
await this.writeStorageSecureFile(path4.join(this.entitiesDir, `${entityName}.md`), serialized);
|
|
5748
5910
|
migrated += 1;
|
|
5749
5911
|
}
|
|
5750
5912
|
if (migrated > 0) {
|
|
@@ -5766,7 +5928,8 @@ ${reflection}
|
|
|
5766
5928
|
async readAllEntityFiles() {
|
|
5767
5929
|
const currentVersion = this.getMemoryStatusVersion();
|
|
5768
5930
|
const schemaCacheKey = buildEntitySchemaCacheKey(this.entitySchemas);
|
|
5769
|
-
const
|
|
5931
|
+
const cacheKey = `${this.getEntityCacheSecureStoreKey()}\0${schemaCacheKey}`;
|
|
5932
|
+
const cached = getCachedEntities(this.baseDir, currentVersion, cacheKey);
|
|
5770
5933
|
if (cached) return cached;
|
|
5771
5934
|
try {
|
|
5772
5935
|
const entries = await readdir(this.entitiesDir);
|
|
@@ -5777,17 +5940,24 @@ ${reflection}
|
|
|
5777
5940
|
for (let i = 0; i < mdFiles.length; i += BATCH_SIZE) {
|
|
5778
5941
|
const batch = mdFiles.slice(i, i + BATCH_SIZE);
|
|
5779
5942
|
const results = await Promise.all(
|
|
5780
|
-
batch.map(
|
|
5781
|
-
|
|
5782
|
-
|
|
5943
|
+
batch.map(async (entry) => {
|
|
5944
|
+
try {
|
|
5945
|
+
return await this.readStorageSecureFile(path4.join(this.entitiesDir, entry));
|
|
5946
|
+
} catch (err) {
|
|
5947
|
+
if (err instanceof SecureStoreLockedError) throw err;
|
|
5948
|
+
if (!isErrnoCode(err, "ENOENT")) throw err;
|
|
5949
|
+
return null;
|
|
5950
|
+
}
|
|
5951
|
+
})
|
|
5783
5952
|
);
|
|
5784
5953
|
for (const content of results) {
|
|
5785
5954
|
if (content !== null) entities.push(parseEntityFile(content, this.entitySchemas));
|
|
5786
5955
|
}
|
|
5787
5956
|
}
|
|
5788
|
-
setCachedEntities(this.baseDir, entities, currentVersion,
|
|
5957
|
+
setCachedEntities(this.baseDir, entities, currentVersion, cacheKey);
|
|
5789
5958
|
return entities;
|
|
5790
|
-
} catch {
|
|
5959
|
+
} catch (err) {
|
|
5960
|
+
if (err instanceof SecureStoreLockedError || !isErrnoCode(err, "ENOENT")) throw err;
|
|
5791
5961
|
return [];
|
|
5792
5962
|
}
|
|
5793
5963
|
}
|
|
@@ -5920,7 +6090,7 @@ ${rows.join("\n")}
|
|
|
5920
6090
|
for (const file of files) {
|
|
5921
6091
|
const filePath = path4.join(this.entitiesDir, file);
|
|
5922
6092
|
try {
|
|
5923
|
-
const content = await
|
|
6093
|
+
const content = await this.readStorageSecureFile(filePath);
|
|
5924
6094
|
const parsed = parseEntityFile(content, this.entitySchemas);
|
|
5925
6095
|
if (!mergedEntity.type || mergedEntity.type === "other") {
|
|
5926
6096
|
mergedEntity.type = parsed.type;
|
|
@@ -5997,7 +6167,9 @@ ${rows.join("\n")}
|
|
|
5997
6167
|
title: section.title,
|
|
5998
6168
|
lines: [...section.lines]
|
|
5999
6169
|
})));
|
|
6000
|
-
} catch {
|
|
6170
|
+
} catch (err) {
|
|
6171
|
+
if (err instanceof SecureStoreLockedError) throw err;
|
|
6172
|
+
if (!isErrnoCode(err, "ENOENT")) throw err;
|
|
6001
6173
|
}
|
|
6002
6174
|
}
|
|
6003
6175
|
const timelineKeys = /* @__PURE__ */ new Set();
|
|
@@ -6048,7 +6220,7 @@ ${rows.join("\n")}
|
|
|
6048
6220
|
mergedEntity.created = mergedEntity.created || mergedEntity.updated || (/* @__PURE__ */ new Date()).toISOString();
|
|
6049
6221
|
mergedEntity.updated = mergedEntity.updated || (/* @__PURE__ */ new Date()).toISOString();
|
|
6050
6222
|
const canonicalPath = path4.join(this.entitiesDir, `${canonical}.md`);
|
|
6051
|
-
await
|
|
6223
|
+
await this.writeStorageSecureFile(canonicalPath, serializeEntityFile(mergedEntity, this.entitySchemas));
|
|
6052
6224
|
for (const file of files) {
|
|
6053
6225
|
const filePath = path4.join(this.entitiesDir, file);
|
|
6054
6226
|
if (filePath !== canonicalPath) {
|
|
@@ -6061,7 +6233,8 @@ ${rows.join("\n")}
|
|
|
6061
6233
|
}
|
|
6062
6234
|
}
|
|
6063
6235
|
}
|
|
6064
|
-
} catch {
|
|
6236
|
+
} catch (err) {
|
|
6237
|
+
if (err instanceof SecureStoreLockedError || !isErrnoCode(err, "ENOENT")) throw err;
|
|
6065
6238
|
}
|
|
6066
6239
|
return merged;
|
|
6067
6240
|
}
|
|
@@ -6115,7 +6288,7 @@ ${rows.join("\n")}
|
|
|
6115
6288
|
${memory.content}
|
|
6116
6289
|
`;
|
|
6117
6290
|
try {
|
|
6118
|
-
await
|
|
6291
|
+
await this.writeStorageSecureFile(memory.path, fileContent);
|
|
6119
6292
|
updated++;
|
|
6120
6293
|
} catch (err) {
|
|
6121
6294
|
log.debug(`failed to update access tracking for ${entry.memoryId}: ${err}`);
|
|
@@ -6256,7 +6429,7 @@ ${sanitized.text}
|
|
|
6256
6429
|
} else {
|
|
6257
6430
|
filePath = path4.join(this.factsDir, today, `${id}.md`);
|
|
6258
6431
|
}
|
|
6259
|
-
await
|
|
6432
|
+
await this.writeStorageSecureFile(filePath, fileContent);
|
|
6260
6433
|
log.debug(`wrote chunk ${id} (${chunkIndex + 1}/${chunkTotal}) to ${filePath}`);
|
|
6261
6434
|
return id;
|
|
6262
6435
|
}
|
|
@@ -6331,7 +6504,7 @@ Reason: ${reason}`, {
|
|
|
6331
6504
|
async writeSummary(summary) {
|
|
6332
6505
|
await mkdir2(this.summariesDir, { recursive: true });
|
|
6333
6506
|
const filePath = path4.join(this.summariesDir, `${summary.id}.json`);
|
|
6334
|
-
await
|
|
6507
|
+
await this.writeStorageSecureFile(filePath, JSON.stringify(summary, null, 2));
|
|
6335
6508
|
log.debug(`wrote summary ${summary.id}`);
|
|
6336
6509
|
}
|
|
6337
6510
|
/**
|
|
@@ -6344,11 +6517,13 @@ Reason: ${reason}`, {
|
|
|
6344
6517
|
for (const file of files) {
|
|
6345
6518
|
if (!file.endsWith(".json")) continue;
|
|
6346
6519
|
const filePath = path4.join(this.summariesDir, file);
|
|
6347
|
-
const raw = await
|
|
6520
|
+
const raw = await this.readStorageSecureFile(filePath);
|
|
6348
6521
|
summaries.push(JSON.parse(raw));
|
|
6349
6522
|
}
|
|
6350
6523
|
return summaries;
|
|
6351
|
-
} catch {
|
|
6524
|
+
} catch (err) {
|
|
6525
|
+
if (err instanceof SecureStoreLockedError) throw err;
|
|
6526
|
+
if (!isErrnoCode(err, "ENOENT")) throw err;
|
|
6352
6527
|
return [];
|
|
6353
6528
|
}
|
|
6354
6529
|
}
|
|
@@ -6374,7 +6549,7 @@ Reason: ${reason}`, {
|
|
|
6374
6549
|
${memory.content}
|
|
6375
6550
|
`;
|
|
6376
6551
|
try {
|
|
6377
|
-
await
|
|
6552
|
+
await this.writeStorageSecureFile(memory.path, fileContent);
|
|
6378
6553
|
await this.appendGeneratedMemoryLifecycleEventFailOpen("storage.archiveMemories", {
|
|
6379
6554
|
memoryId: id,
|
|
6380
6555
|
eventType: "archived",
|
|
@@ -6404,7 +6579,7 @@ ${memory.content}
|
|
|
6404
6579
|
async saveTopics(topics) {
|
|
6405
6580
|
const metaPath = path4.join(this.stateDir, "topics.json");
|
|
6406
6581
|
await mkdir2(this.stateDir, { recursive: true });
|
|
6407
|
-
await
|
|
6582
|
+
await this.writeStorageSecureFile(metaPath, JSON.stringify({ topics, updatedAt: (/* @__PURE__ */ new Date()).toISOString() }, null, 2));
|
|
6408
6583
|
log.debug(`saved ${topics.length} topic scores`);
|
|
6409
6584
|
}
|
|
6410
6585
|
/**
|
|
@@ -6413,9 +6588,11 @@ ${memory.content}
|
|
|
6413
6588
|
async loadTopics() {
|
|
6414
6589
|
const metaPath = path4.join(this.stateDir, "topics.json");
|
|
6415
6590
|
try {
|
|
6416
|
-
const raw = await
|
|
6591
|
+
const raw = await this.readStorageSecureFile(metaPath);
|
|
6417
6592
|
return JSON.parse(raw);
|
|
6418
|
-
} catch {
|
|
6593
|
+
} catch (err) {
|
|
6594
|
+
if (err instanceof SecureStoreLockedError) throw err;
|
|
6595
|
+
if (!isErrnoCode(err, "ENOENT")) throw err;
|
|
6419
6596
|
return { topics: [], updatedAt: null };
|
|
6420
6597
|
}
|
|
6421
6598
|
}
|
|
@@ -6527,7 +6704,6 @@ export {
|
|
|
6527
6704
|
readProjectedGovernanceRecord,
|
|
6528
6705
|
normalizeProjectionPreview,
|
|
6529
6706
|
normalizeProjectionTags,
|
|
6530
|
-
parseContinuityIncident,
|
|
6531
6707
|
parseContinuityImprovementLoops,
|
|
6532
6708
|
normalizeEntityName,
|
|
6533
6709
|
ContentHashIndex,
|