@agentmemory/agentmemory 0.9.14 → 0.9.16
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 +44 -0
- package/dist/cli.mjs +1956 -40
- package/dist/cli.mjs.map +1 -1
- package/dist/{image-refs-HVu22rfu.mjs → image-refs-R3tin9MR.mjs} +2 -2
- package/dist/{image-refs-HVu22rfu.mjs.map → image-refs-R3tin9MR.mjs.map} +1 -1
- package/dist/{image-store-BfN1vDbj.mjs → image-store-DyrKZKqZ.mjs} +1 -1
- package/dist/index.mjs +64 -35
- package/dist/index.mjs.map +1 -1
- package/dist/{src-BBI-ah3h.mjs → src-3Oy_OOlF.mjs} +63 -72
- package/dist/src-3Oy_OOlF.mjs.map +1 -0
- package/dist/{standalone-Cf5sp0XM.mjs → standalone-BQOaGF4z.mjs} +3 -3
- package/dist/{standalone-Cf5sp0XM.mjs.map → standalone-BQOaGF4z.mjs.map} +1 -1
- package/dist/standalone.mjs +1 -1
- package/dist/standalone.mjs.map +1 -1
- package/dist/{tools-registry-BDimtXJb.mjs → tools-registry-BF0pgZmI.mjs} +2 -6
- package/dist/tools-registry-BF0pgZmI.mjs.map +1 -0
- package/package.json +1 -1
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/.codex-plugin/plugin.json +1 -1
- package/dist/src-BBI-ah3h.mjs.map +0 -1
- package/dist/tools-registry-BDimtXJb.mjs.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { i as KV } from "./cli.mjs";
|
|
2
2
|
import { existsSync } from "node:fs";
|
|
3
3
|
import { join, resolve, sep } from "node:path";
|
|
4
4
|
import { homedir } from "node:os";
|
|
@@ -113,4 +113,4 @@ async function decrementImageRef(kv, sdk, filePath) {
|
|
|
113
113
|
|
|
114
114
|
//#endregion
|
|
115
115
|
export { isManagedImagePath as a, decrementImageRef, getImageRefCount, getMaxBytes as i, incrementImageRef, IMAGES_DIR as n, saveImageToDisk as o, deleteImage as r, touchImage as s, withKeyedLock as t };
|
|
116
|
-
//# sourceMappingURL=image-refs-
|
|
116
|
+
//# sourceMappingURL=image-refs-R3tin9MR.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image-refs-
|
|
1
|
+
{"version":3,"file":"image-refs-R3tin9MR.mjs","names":[],"sources":["../src/utils/image-store.ts","../src/state/keyed-mutex.ts","../src/functions/image-refs.ts"],"sourcesContent":["import { homedir } from \"node:os\";\nimport { join, resolve, sep } from \"node:path\";\nimport { existsSync } from \"node:fs\";\nimport { mkdir, writeFile, unlink, utimes, stat } from \"node:fs/promises\";\nimport { createHash } from \"node:crypto\";\n\nexport const IMAGES_DIR = join(homedir(), \".agentmemory\", \"images\");\n\nconst DEFAULT_MAX_BYTES = 500 * 1024 * 1024;\n\nexport function getMaxBytes(): number {\n return Number(process.env.AGENTMEMORY_IMAGE_STORE_MAX_BYTES) || DEFAULT_MAX_BYTES;\n}\n\nexport function isManagedImagePath(filePath: string): boolean {\n const resolved = resolve(filePath);\n const normalizedImagesDir = resolve(IMAGES_DIR);\n return resolved.startsWith(normalizedImagesDir + sep) || resolved === normalizedImagesDir;\n}\n\nfunction contentHash(data: string): string {\n return createHash(\"sha256\").update(data).digest(\"hex\");\n}\n\nexport async function saveImageToDisk(base64Data: string): Promise<{ filePath: string; bytesWritten: number }> {\n if (!base64Data) return { filePath: \"\", bytesWritten: 0 };\n\n if (!existsSync(IMAGES_DIR)) {\n await mkdir(IMAGES_DIR, { recursive: true });\n }\n\n let cleanBase64 = base64Data;\n let ext = \"png\";\n\n if (base64Data.startsWith(\"data:image/\")) {\n const commaIdx = base64Data.indexOf(\",\");\n if (commaIdx !== -1) {\n const meta = base64Data.substring(0, commaIdx);\n if (meta.includes(\"jpeg\") || meta.includes(\"jpg\")) ext = \"jpg\";\n else if (meta.includes(\"webp\")) ext = \"webp\";\n else if (meta.includes(\"gif\")) ext = \"gif\";\n cleanBase64 = base64Data.substring(commaIdx + 1);\n }\n } else if (base64Data.startsWith(\"/9j/\")) {\n ext = \"jpg\";\n }\n\n const hash = contentHash(cleanBase64);\n const filePath = join(IMAGES_DIR, `${hash}.${ext}`);\n\n if (existsSync(filePath)) {\n return { filePath, bytesWritten: 0 };\n }\n\n const buffer = Buffer.from(cleanBase64, \"base64\");\n await writeFile(filePath, buffer);\n\n const s = await stat(filePath);\n\n return { filePath, bytesWritten: s.size };\n}\n\nexport async function deleteImage(filePath: string | undefined): Promise<{ deletedBytes: number }> {\n if (!filePath) return { deletedBytes: 0 };\n if (!isManagedImagePath(filePath)) return { deletedBytes: 0 };\n try {\n if (existsSync(filePath)) {\n const s = await stat(filePath);\n const size = s.size;\n await unlink(filePath);\n return { deletedBytes: size };\n }\n } catch (err) {\n console.error(\"[agentmemory] Failed to delete image context:\", err);\n }\n return { deletedBytes: 0 };\n}\n\n/** Touch an image file to update its mtime (marking it as recently used for LRU eviction) */\nexport async function touchImage(filePath: string): Promise<void> {\n if (!filePath || !isManagedImagePath(filePath)) return;\n try {\n if (existsSync(filePath)) {\n const now = new Date();\n await utimes(filePath, now, now);\n }\n } catch (err) {\n // Ignore touch errors silently\n }\n}\n","const locks = new Map<string, Promise<void>>();\n\nexport function withKeyedLock<T>(\n key: string,\n fn: () => Promise<T>,\n): Promise<T> {\n const prev = locks.get(key) ?? Promise.resolve();\n const next = prev.then(fn, fn);\n const cleanup = next.then(\n () => {},\n () => {},\n );\n locks.set(key, cleanup);\n cleanup.then(() => {\n if (locks.get(key) === cleanup) locks.delete(key);\n });\n return next;\n}\n","import type { ISdk } from \"iii-sdk\";\nimport { KV } from \"../state/schema.js\";\nimport { StateKV } from \"../state/kv.js\";\nimport { deleteImage, touchImage } from \"../utils/image-store.js\";\nimport { withKeyedLock } from \"../state/keyed-mutex.js\";\n\nexport async function getImageRefCount(kv: StateKV, filePath: string): Promise<number> {\n const count = await kv.get<number>(KV.imageRefs, filePath);\n return count ? Number(count) : 0;\n}\n\nexport async function incrementImageRef(kv: StateKV, filePath: string): Promise<void> {\n return withKeyedLock(`imgRef:${filePath}`, async () => {\n const current = await getImageRefCount(kv, filePath);\n await kv.set(KV.imageRefs, filePath, current + 1);\n await touchImage(filePath);\n });\n}\n\nexport async function decrementImageRef(kv: StateKV, sdk: ISdk, filePath: string): Promise<void> {\n return withKeyedLock(`imgRef:${filePath}`, async () => {\n const current = await getImageRefCount(kv, filePath);\n if (current <= 1) {\n await kv.delete(KV.imageEmbeddings, filePath);\n await kv.delete(KV.imageRefs, filePath);\n const { deletedBytes } = await deleteImage(filePath);\n if (deletedBytes > 0) {\n sdk.triggerVoid(\"mem::disk-size-delta\", { deltaBytes: -deletedBytes });\n }\n } else {\n await kv.set(KV.imageRefs, filePath, current - 1);\n }\n });\n}\n"],"mappings":"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"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { a as isManagedImagePath, i as getMaxBytes, n as IMAGES_DIR, o as saveImageToDisk, r as deleteImage, s as touchImage } from "./image-refs-
|
|
1
|
+
import { a as isManagedImagePath, i as getMaxBytes, n as IMAGES_DIR, o as saveImageToDisk, r as deleteImage, s as touchImage } from "./image-refs-R3tin9MR.mjs";
|
|
2
2
|
|
|
3
3
|
export { deleteImage, saveImageToDisk };
|
package/dist/index.mjs
CHANGED
|
@@ -1452,6 +1452,17 @@ const logger = {
|
|
|
1452
1452
|
emit("error", msg, fields);
|
|
1453
1453
|
}
|
|
1454
1454
|
};
|
|
1455
|
+
let bootVerbose = process.env["AGENTMEMORY_VERBOSE"] === "1" || process.env["AGENTMEMORY_VERBOSE"] === "true";
|
|
1456
|
+
const bootBuffer = [];
|
|
1457
|
+
function bootLog(msg) {
|
|
1458
|
+
if (bootVerbose) {
|
|
1459
|
+
try {
|
|
1460
|
+
process.stderr.write(`[agentmemory] ${msg}\n`);
|
|
1461
|
+
} catch {}
|
|
1462
|
+
return;
|
|
1463
|
+
}
|
|
1464
|
+
if (bootBuffer.length < 500) bootBuffer.push(msg);
|
|
1465
|
+
}
|
|
1455
1466
|
|
|
1456
1467
|
//#endregion
|
|
1457
1468
|
//#region src/functions/query-expansion.ts
|
|
@@ -5956,7 +5967,7 @@ function registerAutoForgetFunction(sdk, kv) {
|
|
|
5956
5967
|
|
|
5957
5968
|
//#endregion
|
|
5958
5969
|
//#region src/version.ts
|
|
5959
|
-
const VERSION = "0.9.
|
|
5970
|
+
const VERSION = "0.9.16";
|
|
5960
5971
|
|
|
5961
5972
|
//#endregion
|
|
5962
5973
|
//#region src/functions/export-import.ts
|
|
@@ -6088,7 +6099,9 @@ function registerExportImportFunction(sdk, kv) {
|
|
|
6088
6099
|
"0.9.11",
|
|
6089
6100
|
"0.9.12",
|
|
6090
6101
|
"0.9.13",
|
|
6091
|
-
"0.9.14"
|
|
6102
|
+
"0.9.14",
|
|
6103
|
+
"0.9.15",
|
|
6104
|
+
"0.9.16"
|
|
6092
6105
|
]).has(importData.version)) return {
|
|
6093
6106
|
success: false,
|
|
6094
6107
|
error: `Unsupported export version: ${importData.version}`
|
|
@@ -19395,8 +19408,10 @@ function readBody(req) {
|
|
|
19395
19408
|
req.on("error", reject);
|
|
19396
19409
|
});
|
|
19397
19410
|
}
|
|
19411
|
+
const MAX_VIEWER_PORT_RETRIES = 10;
|
|
19398
19412
|
function startViewerServer(port, _kv, _sdk, secret, restPort) {
|
|
19399
19413
|
const resolvedRestPort = restPort ?? port - 2;
|
|
19414
|
+
const requestedPort = port;
|
|
19400
19415
|
const server = createServer(async (req, res) => {
|
|
19401
19416
|
const raw = req.url || "/";
|
|
19402
19417
|
const qIdx = raw.indexOf("?");
|
|
@@ -19433,13 +19448,26 @@ function startViewerServer(port, _kv, _sdk, secret, restPort) {
|
|
|
19433
19448
|
json(res, 502, { error: "upstream error" }, req);
|
|
19434
19449
|
}
|
|
19435
19450
|
});
|
|
19451
|
+
let attempt = 0;
|
|
19452
|
+
let currentPort = requestedPort;
|
|
19453
|
+
const tryListen = () => {
|
|
19454
|
+
server.listen(currentPort, "127.0.0.1");
|
|
19455
|
+
};
|
|
19456
|
+
server.on("listening", () => {
|
|
19457
|
+
if (currentPort === requestedPort) console.log(`[agentmemory] Viewer: http://localhost:${currentPort}`);
|
|
19458
|
+
else console.log(`[agentmemory] Viewer started on http://localhost:${currentPort} (fallback from ${requestedPort})`);
|
|
19459
|
+
});
|
|
19436
19460
|
server.on("error", (err) => {
|
|
19437
|
-
if (err.code === "EADDRINUSE"
|
|
19461
|
+
if (err.code === "EADDRINUSE" && attempt < MAX_VIEWER_PORT_RETRIES) {
|
|
19462
|
+
attempt++;
|
|
19463
|
+
currentPort = requestedPort + attempt;
|
|
19464
|
+
setImmediate(tryListen);
|
|
19465
|
+
return;
|
|
19466
|
+
}
|
|
19467
|
+
if (err.code === "EADDRINUSE") console.warn(`[agentmemory] Viewer ports ${requestedPort}-${requestedPort + MAX_VIEWER_PORT_RETRIES} all in use, skipping viewer.`);
|
|
19438
19468
|
else console.error(`[agentmemory] Viewer error:`, err.message);
|
|
19439
19469
|
});
|
|
19440
|
-
|
|
19441
|
-
console.log(`[agentmemory] Viewer: http://localhost:${port}`);
|
|
19442
|
-
});
|
|
19470
|
+
tryListen();
|
|
19443
19471
|
return server;
|
|
19444
19472
|
}
|
|
19445
19473
|
async function proxyToRestApi(restPort, pathname, qs, method, req, res, secret) {
|
|
@@ -19633,14 +19661,14 @@ async function main() {
|
|
|
19633
19661
|
const provider = fallbackConfig.providers.length > 0 ? createFallbackProvider(config.provider, fallbackConfig) : createProvider(config.provider);
|
|
19634
19662
|
const embeddingProvider = createEmbeddingProvider();
|
|
19635
19663
|
const imageEmbeddingProvider = createImageEmbeddingProvider();
|
|
19636
|
-
|
|
19637
|
-
|
|
19638
|
-
|
|
19639
|
-
if (embeddingProvider)
|
|
19640
|
-
else
|
|
19641
|
-
if (imageEmbeddingProvider)
|
|
19642
|
-
|
|
19643
|
-
|
|
19664
|
+
bootLog(`Starting worker v${VERSION}...`);
|
|
19665
|
+
bootLog(`Engine: ${config.engineUrl}`);
|
|
19666
|
+
bootLog(`Provider: ${config.provider.provider} (${config.provider.model})`);
|
|
19667
|
+
if (embeddingProvider) bootLog(`Embedding provider: ${embeddingProvider.name} (${embeddingProvider.dimensions} dims)`);
|
|
19668
|
+
else bootLog(`Embedding provider: none (BM25-only mode)`);
|
|
19669
|
+
if (imageEmbeddingProvider) bootLog(`Image embedding provider: ${imageEmbeddingProvider.name} (${imageEmbeddingProvider.dimensions} dims) — vision-search active`);
|
|
19670
|
+
bootLog(`REST API: http://localhost:${config.restPort}/agentmemory/*`);
|
|
19671
|
+
bootLog(`Streams: ws://localhost:${config.streamsPort}`);
|
|
19644
19672
|
const sdk = registerWorker(config.engineUrl, {
|
|
19645
19673
|
workerName: "agentmemory",
|
|
19646
19674
|
invocationTimeoutMs: 18e4,
|
|
@@ -19683,22 +19711,22 @@ async function main() {
|
|
|
19683
19711
|
const claudeBridgeConfig = loadClaudeBridgeConfig();
|
|
19684
19712
|
if (claudeBridgeConfig.enabled) {
|
|
19685
19713
|
registerClaudeBridgeFunction(sdk, kv, claudeBridgeConfig);
|
|
19686
|
-
|
|
19714
|
+
bootLog(`Claude bridge: syncing to ${claudeBridgeConfig.memoryFilePath}`);
|
|
19687
19715
|
}
|
|
19688
19716
|
if (isGraphExtractionEnabled()) {
|
|
19689
19717
|
registerGraphFunction(sdk, kv, provider);
|
|
19690
|
-
|
|
19718
|
+
bootLog(`Knowledge graph: extraction enabled`);
|
|
19691
19719
|
}
|
|
19692
19720
|
registerConsolidationPipelineFunction(sdk, kv, provider);
|
|
19693
|
-
|
|
19694
|
-
if (isAutoCompressEnabled())
|
|
19695
|
-
else
|
|
19696
|
-
if (isContextInjectionEnabled())
|
|
19697
|
-
else
|
|
19721
|
+
bootLog(`Consolidation pipeline: registered (CONSOLIDATION_ENABLED=${isConsolidationEnabled() ? "true" : "false"})`);
|
|
19722
|
+
if (isAutoCompressEnabled()) bootLog(`WARNING: AGENTMEMORY_AUTO_COMPRESS=true — every PostToolUse observation will be sent to your LLM provider for compression. This spends API tokens proportional to your session tool-use frequency (see #138). Set AGENTMEMORY_AUTO_COMPRESS=false to disable.`);
|
|
19723
|
+
else bootLog(`Auto-compress: OFF (default, #138) — observations indexed via zero-LLM synthetic compression. Set AGENTMEMORY_AUTO_COMPRESS=true to opt-in to LLM-powered summaries (uses your API key).`);
|
|
19724
|
+
if (isContextInjectionEnabled()) bootLog(`WARNING: AGENTMEMORY_INJECT_CONTEXT=true — the PreToolUse and SessionStart hooks will inject up to ~4000 chars of memory context into every tool turn. On Claude Pro this burns session tokens proportional to your tool-call frequency (see #143). Set AGENTMEMORY_INJECT_CONTEXT=false to disable.`);
|
|
19725
|
+
else bootLog(`Context injection: OFF (default, #143) — hooks capture observations but do not inject context into Claude Code's conversation. Set AGENTMEMORY_INJECT_CONTEXT=true to opt-in (warning: expect your Claude Pro allocation to drain faster).`);
|
|
19698
19726
|
const teamConfig = loadTeamConfig();
|
|
19699
19727
|
if (teamConfig) {
|
|
19700
19728
|
registerTeamFunction(sdk, kv, teamConfig);
|
|
19701
|
-
|
|
19729
|
+
bootLog(`Team memory: ${teamConfig.teamId} (${teamConfig.mode})`);
|
|
19702
19730
|
}
|
|
19703
19731
|
registerGovernanceFunction(sdk, kv);
|
|
19704
19732
|
registerActionsFunction(sdk, kv);
|
|
@@ -19728,13 +19756,13 @@ async function main() {
|
|
|
19728
19756
|
registerRetentionFunctions(sdk, kv);
|
|
19729
19757
|
registerCompressFileFunction(sdk, kv, provider);
|
|
19730
19758
|
registerReplayFunctions(sdk, kv);
|
|
19731
|
-
|
|
19732
|
-
|
|
19733
|
-
if (isSlotsEnabled())
|
|
19759
|
+
bootLog(`v0.6 advanced retrieval: sliding-window, query-expansion, temporal-graph, retention-scoring`);
|
|
19760
|
+
bootLog(`Orchestration layer: actions, frontier, leases, routines, signals, checkpoints, flow-compress, mesh, branch-aware, sentinels, sketches, crystallize, diagnostics, facets`);
|
|
19761
|
+
if (isSlotsEnabled()) bootLog(`Slots: enabled (pinned editable memory). Reflect on Stop hook: ${isReflectEnabled() ? "on" : "off"}`);
|
|
19734
19762
|
const snapshotConfig = loadSnapshotConfig();
|
|
19735
19763
|
if (snapshotConfig.enabled) {
|
|
19736
19764
|
registerSnapshotFunction(sdk, kv, snapshotConfig.dir);
|
|
19737
|
-
|
|
19765
|
+
bootLog(`Git snapshots: ${snapshotConfig.dir} (every ${snapshotConfig.interval}s)`);
|
|
19738
19766
|
}
|
|
19739
19767
|
const bm25Index = getSearchIndex();
|
|
19740
19768
|
const graphWeight = parseFloat(getEnvVar("AGENTMEMORY_GRAPH_WEIGHT") || "0.3");
|
|
@@ -19751,7 +19779,7 @@ async function main() {
|
|
|
19751
19779
|
});
|
|
19752
19780
|
if (loaded?.bm25 && loaded.bm25.size > 0) {
|
|
19753
19781
|
bm25Index.restoreFrom(loaded.bm25);
|
|
19754
|
-
|
|
19782
|
+
bootLog(`Loaded persisted BM25 index (${bm25Index.size} docs)`);
|
|
19755
19783
|
}
|
|
19756
19784
|
if (loaded?.vector && vectorIndex && loaded.vector.size > 0) {
|
|
19757
19785
|
const activeDim = embeddingProvider?.dimensions ?? 0;
|
|
@@ -19766,7 +19794,7 @@ async function main() {
|
|
|
19766
19794
|
else throw new Error(`[agentmemory] Refusing to start: persisted vector index has ${mismatches.length} of ${loaded.vector.size} vectors with the wrong dimension. Active provider (${embeddingProvider?.name}) declares ${activeDim}; dimensions seen on disk: ${distinct}. First mismatched obsIds: ${sample}. Loading would silently corrupt search (cross-dimension cosine returns 0). Choose one:\n - Re-embed the existing index against the new provider, then start.\n - Set AGENTMEMORY_DROP_STALE_INDEX=true to discard the persisted vectors and rebuild from live observations.\n - Switch the embedding provider back to the one that wrote the index.`);
|
|
19767
19795
|
} else {
|
|
19768
19796
|
vectorIndex.restoreFrom(loaded.vector);
|
|
19769
|
-
|
|
19797
|
+
bootLog(`Loaded persisted vector index (${vectorIndex.size} vectors)`);
|
|
19770
19798
|
}
|
|
19771
19799
|
}
|
|
19772
19800
|
if (bm25Index.size === 0) {
|
|
@@ -19775,7 +19803,7 @@ async function main() {
|
|
|
19775
19803
|
return 0;
|
|
19776
19804
|
});
|
|
19777
19805
|
if (indexCount > 0) {
|
|
19778
|
-
|
|
19806
|
+
bootLog(`Search index rebuilt: ${indexCount} entries`);
|
|
19779
19807
|
indexPersistence.scheduleSave();
|
|
19780
19808
|
}
|
|
19781
19809
|
} else try {
|
|
@@ -19800,14 +19828,15 @@ async function main() {
|
|
|
19800
19828
|
backfilled++;
|
|
19801
19829
|
}
|
|
19802
19830
|
if (backfilled > 0) {
|
|
19803
|
-
|
|
19831
|
+
bootLog(`Backfilled ${backfilled} memories into BM25 (legacy gap before #257)`);
|
|
19804
19832
|
indexPersistence.scheduleSave();
|
|
19805
19833
|
}
|
|
19806
19834
|
} catch (err) {
|
|
19807
19835
|
console.warn(`[agentmemory] Failed to backfill memories into BM25:`, err);
|
|
19808
19836
|
}
|
|
19809
|
-
|
|
19810
|
-
|
|
19837
|
+
bootLog(`Ready. ${embeddingProvider ? "Triple-stream (BM25+Vector+Graph)" : "BM25+Graph"} search active.`);
|
|
19838
|
+
bootLog(`REST API: 107 endpoints at http://localhost:${config.restPort}/agentmemory/*`);
|
|
19839
|
+
bootLog(`MCP surface (opt-in via \`npx @agentmemory/mcp\`): ${getAllTools().length} tools · 6 resources · 3 prompts`);
|
|
19811
19840
|
const viewerServer = startViewerServer(config.restPort + 2, kv, sdk, secret, config.restPort);
|
|
19812
19841
|
const autoForgetIntervalMs = parseInt(process.env.AUTO_FORGET_INTERVAL_MS || "3600000", 10);
|
|
19813
19842
|
const consolidationIntervalMs = parseInt(process.env.CONSOLIDATION_INTERVAL_MS || "7200000", 10);
|
|
@@ -19820,7 +19849,7 @@ async function main() {
|
|
|
19820
19849
|
});
|
|
19821
19850
|
} catch {}
|
|
19822
19851
|
}, autoForgetIntervalMs).unref();
|
|
19823
|
-
|
|
19852
|
+
bootLog(`Auto-forget: enabled (every ${autoForgetIntervalMs / 6e4}m)`);
|
|
19824
19853
|
}
|
|
19825
19854
|
if (process.env.LESSON_DECAY_ENABLED !== "false") {
|
|
19826
19855
|
setInterval(async () => {
|
|
@@ -19831,7 +19860,7 @@ async function main() {
|
|
|
19831
19860
|
});
|
|
19832
19861
|
} catch {}
|
|
19833
19862
|
}, 864e5).unref();
|
|
19834
|
-
|
|
19863
|
+
bootLog(`Lesson decay sweep: enabled (every 24h)`);
|
|
19835
19864
|
}
|
|
19836
19865
|
if (process.env.INSIGHT_DECAY_ENABLED !== "false") setInterval(async () => {
|
|
19837
19866
|
try {
|
|
@@ -19850,7 +19879,7 @@ async function main() {
|
|
|
19850
19879
|
});
|
|
19851
19880
|
} catch {}
|
|
19852
19881
|
}, consolidationIntervalMs).unref();
|
|
19853
|
-
|
|
19882
|
+
bootLog(`Auto-consolidation: enabled (every ${consolidationIntervalMs / 6e4}m)`);
|
|
19854
19883
|
}
|
|
19855
19884
|
const shutdown = async () => {
|
|
19856
19885
|
console.log(`\n[agentmemory] Shutting down...`);
|