@agentmemory/agentmemory 0.9.31 → 0.9.32
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/.env.example +18 -15
- package/AGENTS.md +4 -4
- package/README.md +92 -270
- package/dist/.env.example +18 -15
- package/dist/cli.d.mts.map +1 -1
- package/dist/cli.mjs +530 -75
- package/dist/cli.mjs.map +1 -1
- package/dist/{compression-recovery-CnhLQC6N.mjs → compression-recovery-CZh63Jmz.mjs} +174 -89
- package/dist/compression-recovery-CZh63Jmz.mjs.map +1 -0
- package/dist/{connect-BSLIAMpw.mjs → connect-BX3njQ3Y.mjs} +28 -14
- package/dist/connect-BX3njQ3Y.mjs.map +1 -0
- package/dist/hooks/_capture.d.mts +3 -2
- package/dist/hooks/_capture.d.mts.map +1 -1
- package/dist/hooks/_capture.mjs +87 -8
- package/dist/hooks/_capture.mjs.map +1 -1
- package/dist/hooks/post-commit.mjs +58 -5
- package/dist/hooks/post-commit.mjs.map +1 -1
- package/dist/hooks/post-tool-failure.mjs +7 -2
- package/dist/hooks/post-tool-failure.mjs.map +1 -1
- package/dist/hooks/post-tool-use.mjs +7 -2
- package/dist/hooks/post-tool-use.mjs.map +1 -1
- package/dist/hooks/pre-compact.mjs +67 -12
- package/dist/hooks/pre-compact.mjs.map +1 -1
- package/dist/hooks/pre-tool-use.mjs +58 -5
- package/dist/hooks/pre-tool-use.mjs.map +1 -1
- package/dist/hooks/session-end.mjs +14 -3
- package/dist/hooks/session-end.mjs.map +1 -1
- package/dist/hooks/session-start.mjs +58 -5
- package/dist/hooks/session-start.mjs.map +1 -1
- package/dist/hooks/stop.mjs +2 -1
- package/dist/hooks/stop.mjs.map +1 -1
- package/dist/hooks/subagent-stop.mjs +15 -5
- package/dist/hooks/subagent-stop.mjs.map +1 -1
- package/dist/hooks/task-completed.mjs +8 -1
- package/dist/hooks/task-completed.mjs.map +1 -1
- package/dist/index.mjs +724 -200
- package/dist/index.mjs.map +1 -1
- package/dist/integrations/dsh.mjs +31 -4
- package/dist/integrations/dsh.mjs.map +1 -1
- package/dist/{secret-store-D9GwO0xp.mjs → secret-store-iYXRcrO8.mjs} +197 -55
- package/dist/secret-store-iYXRcrO8.mjs.map +1 -0
- package/dist/{src-DaMtDzt_.mjs → src-C23nMpda.mjs} +359 -62
- package/dist/src-C23nMpda.mjs.map +1 -0
- package/dist/{standalone-BlqshyZ5.mjs → standalone-BYo5USDb.mjs} +169 -10
- package/dist/standalone-BYo5USDb.mjs.map +1 -0
- package/dist/standalone.d.mts.map +1 -1
- package/dist/standalone.mjs +240 -10
- package/dist/standalone.mjs.map +1 -1
- package/dist/viewer/index.html +49 -28
- package/integrations/hermes/README.md +11 -1
- package/integrations/hermes/__init__.py +1 -0
- package/integrations/hermes/plugin.yaml +1 -1
- package/integrations/omp/dist/index.mjs +31 -4
- package/integrations/omp/package.json +1 -1
- package/integrations/omp/skills/agentmemory-agents/REFERENCE.md +1 -1
- package/integrations/omp/skills/agentmemory-architecture/SKILL.md +5 -1
- package/integrations/omp/skills/agentmemory-config/REFERENCE.md +2 -1
- package/integrations/omp/skills/agentmemory-config/SKILL.md +29 -9
- package/integrations/omp/skills/agentmemory-hooks/SKILL.md +17 -6
- package/integrations/omp/skills/agentmemory-mcp-tools/REFERENCE.md +1 -1
- package/integrations/omp/skills/agentmemory-mcp-tools/SKILL.md +10 -0
- package/integrations/omp/skills/agentmemory-rest-api/REFERENCE.md +2 -1
- package/integrations/omp/skills/agentmemory-rest-api/SKILL.md +1 -1
- package/integrations/openclaw/README.md +10 -0
- package/integrations/openclaw/openclaw.plugin.json +1 -1
- package/integrations/openclaw/package.json +1 -1
- package/integrations/openclaw/plugin.yaml +1 -1
- package/integrations/openclaw/skills/agentmemory-agents/REFERENCE.md +1 -1
- package/integrations/openclaw/skills/agentmemory-architecture/SKILL.md +5 -1
- package/integrations/openclaw/skills/agentmemory-config/REFERENCE.md +2 -1
- package/integrations/openclaw/skills/agentmemory-config/SKILL.md +29 -9
- package/integrations/openclaw/skills/agentmemory-hooks/SKILL.md +17 -6
- package/integrations/openclaw/skills/agentmemory-mcp-tools/REFERENCE.md +1 -1
- package/integrations/openclaw/skills/agentmemory-mcp-tools/SKILL.md +10 -0
- package/integrations/openclaw/skills/agentmemory-rest-api/REFERENCE.md +2 -1
- package/integrations/openclaw/skills/agentmemory-rest-api/SKILL.md +1 -1
- package/integrations/pi/README.md +1 -0
- package/integrations/pi/dist/index.mjs +92 -11
- package/integrations/pi/index.ts +56 -6
- package/integrations/pi/package.json +1 -1
- package/integrations/pi/skills/agentmemory-agents/REFERENCE.md +1 -1
- package/integrations/pi/skills/agentmemory-architecture/SKILL.md +5 -1
- package/integrations/pi/skills/agentmemory-config/REFERENCE.md +2 -1
- package/integrations/pi/skills/agentmemory-config/SKILL.md +29 -9
- package/integrations/pi/skills/agentmemory-hooks/SKILL.md +17 -6
- package/integrations/pi/skills/agentmemory-mcp-tools/REFERENCE.md +1 -1
- package/integrations/pi/skills/agentmemory-mcp-tools/SKILL.md +10 -0
- package/integrations/pi/skills/agentmemory-rest-api/REFERENCE.md +2 -1
- package/integrations/pi/skills/agentmemory-rest-api/SKILL.md +1 -1
- package/package.json +4 -3
- package/plugin/.claude-plugin/plugin.json +16 -3
- package/plugin/.codex-plugin/plugin.json +1 -1
- package/plugin/.devin-plugin/plugin.json +3 -4
- package/plugin/.mcp.json +5 -1
- package/plugin/README.md +71 -0
- package/plugin/hooks/hooks.json +24 -12
- package/plugin/opencode/plugin.json +1 -1
- package/plugin/plugin.json +1 -1
- package/plugin/scripts/_capture.d.mts +3 -2
- package/plugin/scripts/_capture.d.mts.map +1 -1
- package/plugin/scripts/_capture.mjs +87 -8
- package/plugin/scripts/_capture.mjs.map +1 -1
- package/plugin/scripts/plugin-bridge.mjs +25 -6
- package/plugin/scripts/post-tool-failure.mjs +7 -2
- package/plugin/scripts/post-tool-failure.mjs.map +1 -1
- package/plugin/scripts/post-tool-use.mjs +7 -2
- package/plugin/scripts/post-tool-use.mjs.map +1 -1
- package/plugin/scripts/pre-compact.mjs +67 -12
- package/plugin/scripts/pre-compact.mjs.map +1 -1
- package/plugin/scripts/pre-tool-use.mjs +58 -5
- package/plugin/scripts/pre-tool-use.mjs.map +1 -1
- package/plugin/scripts/session-end.mjs +14 -3
- package/plugin/scripts/session-end.mjs.map +1 -1
- package/plugin/scripts/session-start.mjs +58 -5
- package/plugin/scripts/session-start.mjs.map +1 -1
- package/plugin/scripts/stop.mjs +2 -1
- package/plugin/scripts/stop.mjs.map +1 -1
- package/plugin/scripts/subagent-stop.mjs +15 -5
- package/plugin/scripts/subagent-stop.mjs.map +1 -1
- package/plugin/scripts/task-completed.mjs +8 -1
- package/plugin/scripts/task-completed.mjs.map +1 -1
- package/plugin/skills/agentmemory-agents/REFERENCE.md +1 -1
- package/plugin/skills/agentmemory-architecture/SKILL.md +5 -1
- package/plugin/skills/agentmemory-config/REFERENCE.md +2 -1
- package/plugin/skills/agentmemory-config/SKILL.md +29 -9
- package/plugin/skills/agentmemory-hooks/SKILL.md +17 -6
- package/plugin/skills/agentmemory-mcp-tools/REFERENCE.md +1 -1
- package/plugin/skills/agentmemory-mcp-tools/SKILL.md +10 -0
- package/plugin/skills/agentmemory-rest-api/REFERENCE.md +2 -1
- package/plugin/skills/agentmemory-rest-api/SKILL.md +1 -1
- package/dist/compression-recovery-CnhLQC6N.mjs.map +0 -1
- package/dist/connect-BSLIAMpw.mjs.map +0 -1
- package/dist/secret-store-D9GwO0xp.mjs.map +0 -1
- package/dist/src-DaMtDzt_.mjs.map +0 -1
- package/dist/standalone-BlqshyZ5.mjs.map +0 -1
- package/plugin/scripts/post-commit.d.mts +0 -1
- package/plugin/scripts/post-commit.mjs +0 -204
- package/plugin/scripts/post-commit.mjs.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { a as KV, c as jaccardSimilarity, i as withKeyedLocks, n as isKeyedLockHeld, o as fingerprintId, r as withKeyedLock, s as generateId, t as afterKeyedLock } from "./keyed-mutex-DCUh7PG-.mjs";
|
|
2
|
-
import {
|
|
3
|
-
import { $ as normalizeAccessLog, A as getVectorBackfillState, At as withGraphSnapshotUnknownMutation, B as scheduleIndexSave, Bt as resolveGraphScope, C as findUnindexedObservations, Ct as initializeGraphIndex, D as getKeywordRebuildEpoch, Dt as recoverGraphIndex, E as getIndexPersistenceStatus, Et as reconcileGraphIndexRecord, F as isMemoryIndexReady, Ft as isLegacyGraphState, G as setVectorBackfillState, Gt as retainSent, H as setHybridRanker, Ht as drainSpool, I as markKeywordRebuildPending, It as notifyGraphGenerationChange, J as vectorIndexRemove, Jt as spoolSummary, K as setVectorIndex, Kt as spoolDir, L as rankMemoryIds, Lt as pinGraphState, M as indexRecords, Mt as noteGraphSnapshotWrite, N as isBm25RebuildIncomplete, Nt as withoutGraphRecovery, O as getPendingVectorBackfillCount, Ot as withGraphIndexMutation, P as isKeywordRebuildInProgress, Pt as getGraphGeneration, Q as emptyAccessLog, Qt as withWriteScrubbing, R as rebuildKeywordIndex, Rt as pinGraphStateGeneration, S as backfillVectorBacklog, St as graphEdgeLookupKey, T as getEmbeddingProvider, Tt as normalizeGraphIndexText, U as setIndexPersistence, V as setEmbeddingProvider, Vt as setGraphGenerationListener, W as setPendingVectorBackfillCount, Wt as reconcileSent, X as withoutObservationSource, Xt as scrubRecord, Y as rawFromObservationSource, Yt as registerPrivacyFunction, Z as deleteAccessLog, Zt as stripPrivateData, _ as getLiveEventsStats, a as markCompressionDispatchFailed, an as runtimeMetadataPath, at as markLlmFunctions, b as validateOutput, bt as finishGraphIndexBuild, c as isValidEventId, ct as singleFlight, d as budgetLiveObservationSource, dt as runGraphCompactOnBoot, en as SHUTDOWN_FLUSH_TIMEOUT_MS, et as recordAccessBatch, f as SAFE_PAYLOAD_BYTES, ft as setGraphCompactBootDisabled, g as emitLiveEvent, gt as registerGraphFunction, h as payloadByteLength, ht as persistGraphDelta, i as compressionRaw, in as settleWithin, it as evaluateStatus, j as getVectorIndex, jt as ensureGraphConsistency, k as getSearchIndex, kt as withGraphSnapshotIndexBarrier, l as buildSyntheticCompression, lt as GRAPH_COMPACT_BOOT_DELAY_MS, m as oversizedPayloadError, mt as boundSources, n as compressionInFlight, o as needsCompression, ot as prefersHtml, p as checkPayloadFrameSize, pt as COMPACT_SCOPES, q as vectorIndexAddGuarded, qt as spoolPolicy, r as registerCompressFunction, rn as runStartupCleanup, rt as UNINDEXED_SCAN_REUSE_MS, s as pendingCompression, st as renderStatusHtml, t as parseCompressionScope, tn as SHUTDOWN_HARD_EXIT_MS, tt as SearchIndex, u as budgetImportedObservationSources, ut as getGraphCompactBootStatus, v as liveEvents, vt as GraphIndexError, w as flushIndexSave, wt as mutateIndexedGraphRecord, x as SummaryOutputSchema, xt as getGraphIndexStatus, y as scoreSummary, yt as createGraphIndexReader, z as registerSearchFunction, zt as replaceGraphGeneration } from "./compression-recovery-
|
|
1
|
+
import { a as KV, c as jaccardSimilarity, i as withKeyedLocks, n as isKeyedLockHeld, o as fingerprintId, r as withKeyedLock, s as generateId, t as afterKeyedLock, u as segmentCjk } from "./keyed-mutex-DCUh7PG-.mjs";
|
|
2
|
+
import { B as detectLlmProviderKind, C as getAllTools, D as bootLog, E as VERSION, F as runtimeConfigPath, G as getConsolidationDecayDays, H as getAgentId, J as getFinalizeIdleMs, K as getConsolidationIntervalMs, L as MAX_IMPORT_OBS_PER_SESSION, N as engineStateConfigPaths, O as bootWarn, Q as getSessionSweepStaleHours, R as describeLlmRoute, T as III_PINNED_VERSION, U as getAuditRetentionMonths, V as embeddingOptInHint, W as getConsolidationCooldownMs, X as getIndexSaveIntervalMs, Y as getFollowupWindowSeconds, _ as recordAudit, _t as loadEmbeddingConfig, a as secretFilePath, at as isAgentScopeIsolated, b as setAuditRecordedListener, bt as loadTeamConfig, c as memoryToObservation, ct as isContextInjectionEnabled, d as getSearchResultLayer, dt as isGraphExtractionEnabled, et as getStateBackend, f as isSearchLayer, ft as isSessionSweepEnabled, g as queryAudit, gt as loadConfig, h as AUDIT_MIGRATION_STATE_KEY, ht as loadClaudeBridgeConfig, it as hydrateProcessEnvFromFile, j as captureDurableAfterMs, k as logger, l as observationEmbedText, lt as isDropStaleIndexEnabled, m as matchesSearchLayer, mt as llmOptInHint, n as ensureServerSecret, nt as getVectorBackfillMax, ot as isAutoCompressEnabled, pt as isVectorBackfillAllEnabled, q as getEnvVar, r as explicitSecret, rt as getVectorBucketSize, s as lessonToObservation, st as isConsolidationEnabled, u as supersededAt, ut as isGraphCompactOnBootEnabled, v as runAuditRetentionSweep, vt as loadFallbackConfig, w as getVisibleTools, x as startAuditMigration, y as safeAudit, yt as loadSnapshotConfig, z as detectEmbeddingProvider } from "./secret-store-iYXRcrO8.mjs";
|
|
3
|
+
import { $ as normalizeAccessLog, A as getVectorBackfillState, At as withGraphSnapshotUnknownMutation, B as scheduleIndexSave, Bt as resolveGraphScope, C as findUnindexedObservations, Ct as initializeGraphIndex, D as getKeywordRebuildEpoch, Dt as recoverGraphIndex, E as getIndexPersistenceStatus, Et as reconcileGraphIndexRecord, F as isMemoryIndexReady, Ft as isLegacyGraphState, G as setVectorBackfillState, Gt as retainSent, H as setHybridRanker, Ht as drainSpool, I as markKeywordRebuildPending, It as notifyGraphGenerationChange, J as vectorIndexRemove, Jt as spoolSummary, K as setVectorIndex, Kt as spoolDir, L as rankMemoryIds, Lt as pinGraphState, M as indexRecords, Mt as noteGraphSnapshotWrite, N as isBm25RebuildIncomplete, Nt as withoutGraphRecovery, O as getPendingVectorBackfillCount, Ot as withGraphIndexMutation, P as isKeywordRebuildInProgress, Pt as getGraphGeneration, Q as emptyAccessLog, Qt as withWriteScrubbing, R as rebuildKeywordIndex, Rt as pinGraphStateGeneration, S as backfillVectorBacklog, St as graphEdgeLookupKey, T as getEmbeddingProvider, Tt as normalizeGraphIndexText, U as setIndexPersistence, V as setEmbeddingProvider, Vt as setGraphGenerationListener, W as setPendingVectorBackfillCount, Wt as reconcileSent, X as withoutObservationSource, Xt as scrubRecord, Y as rawFromObservationSource, Yt as registerPrivacyFunction, Z as deleteAccessLog, Zt as stripPrivateData, _ as getLiveEventsStats, a as markCompressionDispatchFailed, an as runtimeMetadataPath, at as markLlmFunctions, b as validateOutput, bt as finishGraphIndexBuild, c as isValidEventId, ct as singleFlight, d as budgetLiveObservationSource, dt as runGraphCompactOnBoot, en as SHUTDOWN_FLUSH_TIMEOUT_MS, et as recordAccessBatch, f as SAFE_PAYLOAD_BYTES, ft as setGraphCompactBootDisabled, g as emitLiveEvent, gt as registerGraphFunction, h as payloadByteLength, ht as persistGraphDelta, i as compressionRaw, in as settleWithin, it as evaluateStatus, j as getVectorIndex, jt as ensureGraphConsistency, k as getSearchIndex, kt as withGraphSnapshotIndexBarrier, l as buildSyntheticCompression, lt as GRAPH_COMPACT_BOOT_DELAY_MS, m as oversizedPayloadError, mt as boundSources, n as compressionInFlight, o as needsCompression, ot as prefersHtml, p as checkPayloadFrameSize, pt as COMPACT_SCOPES, q as vectorIndexAddGuarded, qt as spoolPolicy, r as registerCompressFunction, rn as runStartupCleanup, rt as UNINDEXED_SCAN_REUSE_MS, s as pendingCompression, st as renderStatusHtml, t as parseCompressionScope, tn as SHUTDOWN_HARD_EXIT_MS, tt as SearchIndex, u as budgetImportedObservationSources, ut as getGraphCompactBootStatus, v as liveEvents, vt as GraphIndexError, w as flushIndexSave, wt as mutateIndexedGraphRecord, x as SummaryOutputSchema, xt as getGraphIndexStatus, y as scoreSummary, yt as createGraphIndexReader, z as registerSearchFunction, zt as replaceGraphGeneration } from "./compression-recovery-CZh63Jmz.mjs";
|
|
4
4
|
import { a as saveImageToDisk, i as isManagedImagePath, n as deleteImage, r as getMaxBytes, t as IMAGES_DIR } from "./image-store-BsN4vyjr.mjs";
|
|
5
5
|
import { a as pageAfterCursor, c as sortByKeyDesc, i as matchesText, n as parseSearchExpansionIds, o as pageByOffset, r as encodeCursor, s as parseListQuery, t as parseSessionArguments } from "./session-arguments-zxsbbd8y.mjs";
|
|
6
6
|
import { execFile, execFileSync, execSync } from "node:child_process";
|
|
@@ -408,9 +408,11 @@ var OpenAIProvider = class {
|
|
|
408
408
|
throw new Error(`OpenAI API error (${response.status}): ${text}`);
|
|
409
409
|
}
|
|
410
410
|
const data = await response.json();
|
|
411
|
-
const
|
|
411
|
+
const choice = data.choices?.[0];
|
|
412
|
+
const message = choice?.message;
|
|
412
413
|
const content = message?.content;
|
|
413
|
-
if (content) return content;
|
|
414
|
+
if (content?.trim()) return content;
|
|
415
|
+
if (choice?.finish_reason === "length") throw new Error(`OpenAI response hit max_tokens (${this.maxTokens}) before any content. Raise MAX_TOKENS or lower OPENAI_REASONING_EFFORT.`);
|
|
414
416
|
const reasoning = message?.reasoning ?? message?.reasoning_content;
|
|
415
417
|
if (reasoning) return reasoning;
|
|
416
418
|
throw new Error(`OpenAI returned unexpected response: ${JSON.stringify(data).slice(0, 200)}`);
|
|
@@ -1218,8 +1220,84 @@ var StateKV = class {
|
|
|
1218
1220
|
if (this.backend !== "redis" || !Array.isArray(values)) return values;
|
|
1219
1221
|
return orderLikeInsertion(values);
|
|
1220
1222
|
}
|
|
1223
|
+
async listGroups() {
|
|
1224
|
+
const groups = (await this.sdk.trigger({
|
|
1225
|
+
function_id: "state::list_groups",
|
|
1226
|
+
payload: {}
|
|
1227
|
+
}))?.groups;
|
|
1228
|
+
if (!Array.isArray(groups) || !groups.every((group) => typeof group === "string")) throw new Error("state::list_groups returned an unexpected shape");
|
|
1229
|
+
return groups;
|
|
1230
|
+
}
|
|
1221
1231
|
};
|
|
1222
1232
|
//#endregion
|
|
1233
|
+
//#region src/state/state-readiness.ts
|
|
1234
|
+
const STATE_READY_TIMEOUT_MS = 12e4;
|
|
1235
|
+
const STATE_READY_INTERVAL_MS = 100;
|
|
1236
|
+
const PROBE_TIMEOUT_MS = 1e4;
|
|
1237
|
+
const READINESS_PROBE_KEY = "__agentmemory_state_readiness__";
|
|
1238
|
+
function errorMessage$3(error) {
|
|
1239
|
+
return error instanceof Error ? error.message : String(error);
|
|
1240
|
+
}
|
|
1241
|
+
function isRetryableProbeError(error) {
|
|
1242
|
+
const code = error?.code;
|
|
1243
|
+
if (code === "function_not_found" || code === "invocation_timeout" || code === "timeout") return true;
|
|
1244
|
+
return /Function state::(?:get|list) not found|timed out|timeout|ETIMEDOUT/i.test(errorMessage$3(error));
|
|
1245
|
+
}
|
|
1246
|
+
async function waitForStateReady(sdk, options = {}) {
|
|
1247
|
+
const scope = options.scope ?? KV.config;
|
|
1248
|
+
const timeoutMs = options.timeoutMs ?? STATE_READY_TIMEOUT_MS;
|
|
1249
|
+
const intervalMs = options.intervalMs ?? STATE_READY_INTERVAL_MS;
|
|
1250
|
+
const now = options.now ?? (() => performance.now());
|
|
1251
|
+
const sleep = options.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
|
|
1252
|
+
const startedAt = now();
|
|
1253
|
+
let attempts = 0;
|
|
1254
|
+
let lastError;
|
|
1255
|
+
const probeTimeoutMs = () => Math.min(PROBE_TIMEOUT_MS, Math.max(1, timeoutMs - (now() - startedAt)));
|
|
1256
|
+
for (;;) {
|
|
1257
|
+
attempts += 1;
|
|
1258
|
+
try {
|
|
1259
|
+
await sdk.trigger({
|
|
1260
|
+
function_id: "state::list",
|
|
1261
|
+
payload: { scope },
|
|
1262
|
+
timeoutMs: probeTimeoutMs()
|
|
1263
|
+
});
|
|
1264
|
+
await sdk.trigger({
|
|
1265
|
+
function_id: "state::get",
|
|
1266
|
+
payload: {
|
|
1267
|
+
scope,
|
|
1268
|
+
key: READINESS_PROBE_KEY
|
|
1269
|
+
},
|
|
1270
|
+
timeoutMs: probeTimeoutMs()
|
|
1271
|
+
});
|
|
1272
|
+
return {
|
|
1273
|
+
ready: true,
|
|
1274
|
+
waitedMs: Math.round(now() - startedAt),
|
|
1275
|
+
attempts
|
|
1276
|
+
};
|
|
1277
|
+
} catch (error) {
|
|
1278
|
+
lastError = errorMessage$3(error);
|
|
1279
|
+
if (!isRetryableProbeError(error)) return {
|
|
1280
|
+
ready: false,
|
|
1281
|
+
waitedMs: Math.round(now() - startedAt),
|
|
1282
|
+
attempts,
|
|
1283
|
+
error: lastError
|
|
1284
|
+
};
|
|
1285
|
+
if (attempts === 1) options.onWaiting?.(lastError);
|
|
1286
|
+
}
|
|
1287
|
+
const elapsed = now() - startedAt;
|
|
1288
|
+
if (elapsed >= timeoutMs) return {
|
|
1289
|
+
ready: false,
|
|
1290
|
+
waitedMs: Math.round(elapsed),
|
|
1291
|
+
attempts,
|
|
1292
|
+
error: lastError
|
|
1293
|
+
};
|
|
1294
|
+
await sleep(Math.min(intervalMs, timeoutMs - elapsed));
|
|
1295
|
+
}
|
|
1296
|
+
}
|
|
1297
|
+
function assertStateReady(readiness) {
|
|
1298
|
+
if (!readiness.ready) throw new Error(`State worker did not become ready within ${readiness.waitedMs}ms: ${readiness.error ?? "timeout"}`);
|
|
1299
|
+
}
|
|
1300
|
+
//#endregion
|
|
1223
1301
|
//#region src/state/vector-index.ts
|
|
1224
1302
|
function float32ToBase64(arr) {
|
|
1225
1303
|
return Buffer.from(arr.buffer, arr.byteOffset, arr.byteLength).toString("base64");
|
|
@@ -1982,10 +2060,12 @@ function registerQueryExpansionFunction(sdk, provider) {
|
|
|
1982
2060
|
}
|
|
1983
2061
|
});
|
|
1984
2062
|
}
|
|
2063
|
+
const CJK_RUN = /[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}]+/gu;
|
|
1985
2064
|
function extractEntitiesFromQuery(query) {
|
|
1986
2065
|
const entities = [];
|
|
1987
2066
|
const quoted = query.match(/"([^"]+)"/g);
|
|
1988
2067
|
if (quoted) for (const q of quoted) entities.push(q.replace(/"/g, ""));
|
|
2068
|
+
for (const run of query.matchAll(CJK_RUN)) for (const seg of segmentCjk(run[0])) if (seg.trim().length >= 2) entities.push(seg.trim());
|
|
1989
2069
|
const capitalized = query.match(/\b[A-Z][a-zA-Z0-9_.-]+\b/g);
|
|
1990
2070
|
if (capitalized) {
|
|
1991
2071
|
const stopWords = new Set([
|
|
@@ -2128,8 +2208,8 @@ var HybridSearch = class {
|
|
|
2128
2208
|
this.rerankEnabled = rerankEnabled;
|
|
2129
2209
|
this.graphRetrieval = new GraphRetrieval(kv, (id) => this.bm25.layerOf(id), (id) => this.bm25.sessionOf(id));
|
|
2130
2210
|
}
|
|
2131
|
-
async search(query, limit = 20, targetLayer = "all", authorizeGraph) {
|
|
2132
|
-
return this.tripleStreamSearch(query, limit, targetLayer, this.graphRetrieval.createQuery(authorizeGraph));
|
|
2211
|
+
async search(query, limit = 20, targetLayer = "all", authorizeGraph, request) {
|
|
2212
|
+
return this.tripleStreamSearch(query, limit, targetLayer, this.graphRetrieval.createQuery(authorizeGraph), void 0, true, request);
|
|
2133
2213
|
}
|
|
2134
2214
|
async searchWithExpansion(query, limit, expansion, targetLayer = "all", authorizeGraph) {
|
|
2135
2215
|
const allQueries = [
|
|
@@ -2149,13 +2229,25 @@ var HybridSearch = class {
|
|
|
2149
2229
|
const combined = Array.from(merged.values()).sort((a, b) => b.combinedScore - a.combinedScore || (a.observation.id < b.observation.id ? -1 : a.observation.id > b.observation.id ? 1 : 0));
|
|
2150
2230
|
return this.rerankResults(query, combined, limit);
|
|
2151
2231
|
}
|
|
2152
|
-
async tripleStreamSearch(query, limit, targetLayer, graphQuery, entityHints, applyReranking = true) {
|
|
2232
|
+
async tripleStreamSearch(query, limit, targetLayer, graphQuery, entityHints, applyReranking = true, request) {
|
|
2153
2233
|
const retrievalLimit = this.rerankEnabled ? Math.max(limit, 20) : limit;
|
|
2154
2234
|
const bm25Results = this.bm25.search(query, retrievalLimit * 2, targetLayer);
|
|
2155
2235
|
let vectorResults = [];
|
|
2156
2236
|
let queryEmbedding = null;
|
|
2157
2237
|
if (this.vector && this.embeddingProvider && this.vector.size > 0) try {
|
|
2158
|
-
|
|
2238
|
+
if (request) {
|
|
2239
|
+
if (!request.embedding || request.embedding.query !== query) request.embedding = {
|
|
2240
|
+
query,
|
|
2241
|
+
value: this.embeddingProvider.embed(query)
|
|
2242
|
+
};
|
|
2243
|
+
const embedding = request.embedding;
|
|
2244
|
+
try {
|
|
2245
|
+
queryEmbedding = await embedding.value;
|
|
2246
|
+
} catch (error) {
|
|
2247
|
+
if (request.embedding === embedding) request.embedding = void 0;
|
|
2248
|
+
throw error;
|
|
2249
|
+
}
|
|
2250
|
+
} else queryEmbedding = await this.embeddingProvider.embed(query);
|
|
2159
2251
|
vectorResults = this.vector.search(queryEmbedding, retrievalLimit * 2, targetLayer, (id) => this.bm25.layerOf(id));
|
|
2160
2252
|
} catch {}
|
|
2161
2253
|
const entities = entityHints && entityHints.length > 0 ? entityHints : extractEntitiesFromQuery(query);
|
|
@@ -2230,6 +2322,7 @@ var HybridSearch = class {
|
|
|
2230
2322
|
graphContext: s.graphContext,
|
|
2231
2323
|
combinedScore
|
|
2232
2324
|
}));
|
|
2325
|
+
if (request) request.candidateCount = combined.length;
|
|
2233
2326
|
const retrievalDepth = Math.max(limit, 20);
|
|
2234
2327
|
const diversified = this.diversifyBySession(combined, retrievalDepth);
|
|
2235
2328
|
const enriched = await this.enrichResults(diversified, retrievalDepth);
|
|
@@ -2333,6 +2426,10 @@ const PENDING_LOG_SAVE_THRESHOLD = 500;
|
|
|
2333
2426
|
const EARLY_SAVE_MIN_GAP_MS = 5e3;
|
|
2334
2427
|
const BACKFILL_MARKER_KEY = "vectors:backfill";
|
|
2335
2428
|
const MEMORY_ID_PREFIX = "mem_";
|
|
2429
|
+
const LEGACY_SHARD_SCOPE_PREFIXES = [`${KV.bm25Index}:bm25:`, `${KV.bm25Index}:vectors:`];
|
|
2430
|
+
const LEGACY_SHARD_KEY = "data";
|
|
2431
|
+
const LEGACY_SHARD_SUFFIX = /^((?:[0-9a-z]+-[0-9a-f]{32})|(?:idx_[0-9a-z]+_[0-9a-f]{12})):\d{5}$/;
|
|
2432
|
+
const ORPHAN_SWEEP_KEY = "legacy:sweep";
|
|
2336
2433
|
function auditIndexPersistEnabled() {
|
|
2337
2434
|
const raw = process.env.AGENTMEMORY_AUDIT_INDEX_PERSIST;
|
|
2338
2435
|
if (!raw) return false;
|
|
@@ -2367,6 +2464,11 @@ function isValidShardDescriptor(shard) {
|
|
|
2367
2464
|
const candidate = shard;
|
|
2368
2465
|
return typeof candidate.scope === "string" && candidate.scope.length > 0 && typeof candidate.key === "string" && candidate.key.length > 0 && Number.isInteger(candidate.chars) && candidate.chars >= 0;
|
|
2369
2466
|
}
|
|
2467
|
+
function legacyShardGeneration(scope) {
|
|
2468
|
+
const prefix = LEGACY_SHARD_SCOPE_PREFIXES.find((candidate) => scope.startsWith(candidate));
|
|
2469
|
+
if (!prefix) return void 0;
|
|
2470
|
+
return LEGACY_SHARD_SUFFIX.exec(scope.slice(prefix.length))?.[1] ?? null;
|
|
2471
|
+
}
|
|
2370
2472
|
function isPersistedVector(row) {
|
|
2371
2473
|
if (!row || typeof row !== "object") return false;
|
|
2372
2474
|
const candidate = row;
|
|
@@ -2737,7 +2839,7 @@ var IndexPersistence = class {
|
|
|
2737
2839
|
}
|
|
2738
2840
|
async load() {
|
|
2739
2841
|
if (!this.vector) {
|
|
2740
|
-
await this.
|
|
2842
|
+
await this.finishLegacyCleanup();
|
|
2741
2843
|
return {
|
|
2742
2844
|
vector: null,
|
|
2743
2845
|
state: "none",
|
|
@@ -2765,7 +2867,7 @@ var IndexPersistence = class {
|
|
|
2765
2867
|
this.hasVectorCheckpoint = loaded.size > 0;
|
|
2766
2868
|
this.checkpointBackfillSince = meta.backfillSince;
|
|
2767
2869
|
await this.removeLegacyVectorSnapshotIfPresent();
|
|
2768
|
-
await this.
|
|
2870
|
+
await this.finishLegacyCleanup();
|
|
2769
2871
|
const expectedCount = Number.isInteger(meta.count) ? meta.count : void 0;
|
|
2770
2872
|
this.vectorCountShortfall = expectedCount !== void 0 && loaded.size < expectedCount ? {
|
|
2771
2873
|
expected: expectedCount,
|
|
@@ -2951,7 +3053,7 @@ var IndexPersistence = class {
|
|
|
2951
3053
|
savedAt: null
|
|
2952
3054
|
};
|
|
2953
3055
|
if (!(manifest.value != null || typeof legacyKey.value === "string" && legacyKey.value.length > 0)) {
|
|
2954
|
-
await this.
|
|
3056
|
+
await this.finishLegacyCleanup();
|
|
2955
3057
|
return {
|
|
2956
3058
|
vector: null,
|
|
2957
3059
|
state: "none",
|
|
@@ -2984,7 +3086,7 @@ var IndexPersistence = class {
|
|
|
2984
3086
|
};
|
|
2985
3087
|
}
|
|
2986
3088
|
await this.removeLegacyVectorSnapshot(manifest.value);
|
|
2987
|
-
await this.
|
|
3089
|
+
await this.finishLegacyCleanup();
|
|
2988
3090
|
await this.auditIndexPersistence("migrate", [statePath(KV.bm25Index, VECTOR_META_KEY)], {
|
|
2989
3091
|
vectors: legacy.size,
|
|
2990
3092
|
buckets: this.bucketCountInUse()
|
|
@@ -3024,6 +3126,71 @@ var IndexPersistence = class {
|
|
|
3024
3126
|
if (manifest != null) await this.deleteKey(KV.bm25Index, LEGACY_BM25_MANIFEST_KEY, "legacy_bm25_cleanup");
|
|
3025
3127
|
if (legacy != null) await this.deleteKey(KV.bm25Index, LEGACY_BM25_KEY, "legacy_bm25_cleanup");
|
|
3026
3128
|
}
|
|
3129
|
+
async finishLegacyCleanup() {
|
|
3130
|
+
await this.removeLegacyBm25Snapshot();
|
|
3131
|
+
await this.sweepOrphanedGenerations();
|
|
3132
|
+
}
|
|
3133
|
+
async sweepOrphanedGenerations() {
|
|
3134
|
+
try {
|
|
3135
|
+
if (await this.kv.get(KV.bm25Index, ORPHAN_SWEEP_KEY) != null) return;
|
|
3136
|
+
const candidates = /* @__PURE__ */ new Map();
|
|
3137
|
+
for (const scope of await this.kv.listGroups()) {
|
|
3138
|
+
const generation = legacyShardGeneration(scope);
|
|
3139
|
+
if (generation === void 0) continue;
|
|
3140
|
+
if (generation === null) {
|
|
3141
|
+
logger.warn("index persistence: orphan sweep skipped, unrecognized legacy shard scope", { scope });
|
|
3142
|
+
return;
|
|
3143
|
+
}
|
|
3144
|
+
candidates.set(scope, generation);
|
|
3145
|
+
}
|
|
3146
|
+
const named = await this.namedLegacyGenerations();
|
|
3147
|
+
if (!named) return;
|
|
3148
|
+
const orphans = [...candidates].filter(([, generation]) => !named.has(generation));
|
|
3149
|
+
const failures = await inBatches(orphans, WRITE_CONCURRENCY, async ([scope]) => {
|
|
3150
|
+
if (!await this.deleteKey(scope, LEGACY_SHARD_KEY, "orphan_generation_sweep")) throw new Error(scope);
|
|
3151
|
+
});
|
|
3152
|
+
const summary = {
|
|
3153
|
+
generations: new Set(orphans.map(([, generation]) => generation)).size,
|
|
3154
|
+
shards: orphans.length,
|
|
3155
|
+
failed: failures.length
|
|
3156
|
+
};
|
|
3157
|
+
if (failures.length > 0) {
|
|
3158
|
+
logger.warn("index persistence: orphan sweep left shards behind; the next boot retries", summary);
|
|
3159
|
+
return;
|
|
3160
|
+
}
|
|
3161
|
+
if (candidates.size > orphans.length) {
|
|
3162
|
+
if (orphans.length > 0) logger.info("index persistence: swept orphaned legacy index generations", summary);
|
|
3163
|
+
return;
|
|
3164
|
+
}
|
|
3165
|
+
await this.kv.set(KV.bm25Index, ORPHAN_SWEEP_KEY, {
|
|
3166
|
+
v: 1,
|
|
3167
|
+
at: new Date(this.now()).toISOString(),
|
|
3168
|
+
...summary
|
|
3169
|
+
});
|
|
3170
|
+
await this.auditIndexPersistence("sweep", [statePath(KV.bm25Index, ORPHAN_SWEEP_KEY)], summary);
|
|
3171
|
+
logger.info("index persistence: swept orphaned legacy index generations", summary);
|
|
3172
|
+
} catch (err) {
|
|
3173
|
+
logger.warn("index persistence: orphan sweep failed; the next boot retries", { message: errorMessage$2(err) });
|
|
3174
|
+
}
|
|
3175
|
+
}
|
|
3176
|
+
async namedLegacyGenerations() {
|
|
3177
|
+
const named = /* @__PURE__ */ new Set();
|
|
3178
|
+
for (const [key, label] of [[LEGACY_BM25_MANIFEST_KEY, "bm25"], [LEGACY_VECTOR_MANIFEST_KEY, "vector"]]) {
|
|
3179
|
+
const read = await this.readIndexValue(KV.bm25Index, key, label, "manifest");
|
|
3180
|
+
if (!read.ok) return null;
|
|
3181
|
+
const manifest = read.value;
|
|
3182
|
+
if (manifest == null) continue;
|
|
3183
|
+
const generations = typeof manifest === "object" && Array.isArray(manifest.shards) ? manifest.shards.filter((shard) => typeof shard?.scope === "string" && shard.scope.length > 0).map((shard) => legacyShardGeneration(shard.scope)) : [];
|
|
3184
|
+
if (typeof manifest === "object" && typeof manifest.generation === "string") generations.push(manifest.generation);
|
|
3185
|
+
const usable = generations.filter((generation) => !!generation);
|
|
3186
|
+
for (const generation of usable) named.add(generation);
|
|
3187
|
+
if (usable.length === 0) {
|
|
3188
|
+
logger.warn("index persistence: orphan sweep skipped, a legacy manifest names no generation", { key });
|
|
3189
|
+
return null;
|
|
3190
|
+
}
|
|
3191
|
+
}
|
|
3192
|
+
return named;
|
|
3193
|
+
}
|
|
3027
3194
|
logFailure(err) {
|
|
3028
3195
|
const now = this.now();
|
|
3029
3196
|
if (now - this.lastFailureLogAt < FAILURE_LOG_THROTTLE_MS) return;
|
|
@@ -3058,9 +3225,12 @@ var IndexPersistence = class {
|
|
|
3058
3225
|
result,
|
|
3059
3226
|
error
|
|
3060
3227
|
});
|
|
3228
|
+
return error === void 0;
|
|
3061
3229
|
}
|
|
3062
3230
|
async deleteShards(shards, reason) {
|
|
3063
|
-
await inBatches(shards, WRITE_CONCURRENCY, (shard) =>
|
|
3231
|
+
await inBatches(shards, WRITE_CONCURRENCY, async (shard) => {
|
|
3232
|
+
await this.deleteKey(shard.scope, shard.key, reason);
|
|
3233
|
+
});
|
|
3064
3234
|
}
|
|
3065
3235
|
async loadShardedData(legacyKey, manifestKey, label) {
|
|
3066
3236
|
const manifest = await this.readIndexValue(KV.bm25Index, manifestKey, label, "manifest");
|
|
@@ -3618,7 +3788,7 @@ async function restoreIndexEntries(obs) {
|
|
|
3618
3788
|
scheduleIndexSave();
|
|
3619
3789
|
}
|
|
3620
3790
|
const vectors = getVectorIndex();
|
|
3621
|
-
if (vectors && !vectors.has(obs.id)) await vectorIndexAddGuarded(obs.id, obs.sessionId,
|
|
3791
|
+
if (vectors && !vectors.has(obs.id)) await vectorIndexAddGuarded(obs.id, obs.sessionId, observationEmbedText(obs), {
|
|
3622
3792
|
kind: "synthetic",
|
|
3623
3793
|
logId: obs.id
|
|
3624
3794
|
});
|
|
@@ -3840,7 +4010,7 @@ function registerObserveFunction(sdk, kv, dedupMap, maxObservationsPerSession) {
|
|
|
3840
4010
|
}
|
|
3841
4011
|
getSearchIndex().add(synthetic);
|
|
3842
4012
|
scheduleIndexSave();
|
|
3843
|
-
await vectorIndexAddGuarded(synthetic.id, synthetic.sessionId,
|
|
4013
|
+
await vectorIndexAddGuarded(synthetic.id, synthetic.sessionId, observationEmbedText(synthetic), {
|
|
3844
4014
|
kind: "synthetic",
|
|
3845
4015
|
logId: synthetic.id
|
|
3846
4016
|
});
|
|
@@ -5650,7 +5820,7 @@ function registerSummarizeFunction(sdk, kv, provider, metricsStore) {
|
|
|
5650
5820
|
return {
|
|
5651
5821
|
success: false,
|
|
5652
5822
|
error: "no_provider",
|
|
5653
|
-
reason: "No LLM provider
|
|
5823
|
+
reason: "No LLM provider chosen; Summarize is a no-op. Set AGENTMEMORY_LLM_PROVIDER and that provider's key in ~/.agentmemory/.env to enable."
|
|
5654
5824
|
};
|
|
5655
5825
|
}
|
|
5656
5826
|
const boundedProvider = {
|
|
@@ -6261,6 +6431,7 @@ function registerConsolidateFunction(sdk, kv, provider) {
|
|
|
6261
6431
|
const existingMatch = existingMemories.find((m) => m.title.toLowerCase() === parsed.title.toLowerCase() && (!scopedProject || !m.project || m.project === scopedProject));
|
|
6262
6432
|
if (existingMatch) {
|
|
6263
6433
|
existingMatch.isLatest = false;
|
|
6434
|
+
existingMatch.updatedAt = supersededAt(existingMatch.updatedAt, now);
|
|
6264
6435
|
await kv.set(KV.memories, existingMatch.id, existingMatch);
|
|
6265
6436
|
await recordAudit(kv, "evolve", "mem::consolidate", [existingMatch.id], {
|
|
6266
6437
|
action: "mark_non_latest",
|
|
@@ -6459,25 +6630,52 @@ function registerPatternsFunction(sdk, kv) {
|
|
|
6459
6630
|
}
|
|
6460
6631
|
//#endregion
|
|
6461
6632
|
//#region src/functions/facets.ts
|
|
6462
|
-
async function
|
|
6633
|
+
async function targetLiveness(kv, id) {
|
|
6634
|
+
let observation = false;
|
|
6635
|
+
if (id.startsWith("obs_")) {
|
|
6636
|
+
const sessionId = await lookupObservationSession(kv, id);
|
|
6637
|
+
observation = !!sessionId && !!await kv.get(KV.observations(sessionId), id);
|
|
6638
|
+
}
|
|
6639
|
+
if (id.startsWith("lsn_") || id.startsWith("lesson_")) {
|
|
6640
|
+
const lesson = await kv.get(KV.lessons, id);
|
|
6641
|
+
if (lesson && !lesson.deleted) return {
|
|
6642
|
+
observation,
|
|
6643
|
+
record: true
|
|
6644
|
+
};
|
|
6645
|
+
}
|
|
6646
|
+
const [mem, sem] = await Promise.all([kv.get(KV.memories, id), kv.get(KV.semantic, id)]);
|
|
6647
|
+
return {
|
|
6648
|
+
observation,
|
|
6649
|
+
record: !!(mem || sem)
|
|
6650
|
+
};
|
|
6651
|
+
}
|
|
6652
|
+
function facetTargetLive(facet, liveness) {
|
|
6653
|
+
if (!liveness) return false;
|
|
6654
|
+
if (facet.targetType === "observation") return liveness.observation;
|
|
6655
|
+
return liveness.record || liveness.observation;
|
|
6656
|
+
}
|
|
6657
|
+
async function deleteFacetsForTargets(kv, targetIds, options) {
|
|
6463
6658
|
const ids = new Set(targetIds);
|
|
6464
6659
|
ids.delete("");
|
|
6465
6660
|
if (ids.size === 0) return;
|
|
6661
|
+
const targetTypes = new Set(options?.targetTypes ?? ["memory"]);
|
|
6466
6662
|
try {
|
|
6467
|
-
const live = /* @__PURE__ */ new
|
|
6663
|
+
const live = /* @__PURE__ */ new Map();
|
|
6468
6664
|
await Promise.all([...ids].map(async (id) => {
|
|
6469
6665
|
for (let attempt = 0; attempt < 2; attempt++) try {
|
|
6470
|
-
|
|
6471
|
-
if (mem || sem) live.add(id);
|
|
6666
|
+
live.set(id, await targetLiveness(kv, id));
|
|
6472
6667
|
return;
|
|
6473
6668
|
} catch {
|
|
6474
6669
|
if (attempt === 1) {
|
|
6475
|
-
live.
|
|
6670
|
+
live.set(id, {
|
|
6671
|
+
observation: true,
|
|
6672
|
+
record: true
|
|
6673
|
+
});
|
|
6476
6674
|
logger.warn("Facet cleanup skipped unverifiable target", { targetId: id });
|
|
6477
6675
|
}
|
|
6478
6676
|
}
|
|
6479
6677
|
}));
|
|
6480
|
-
const matches = (await kv.list(KV.facets)).filter((f) => ids.has(f.targetId) &&
|
|
6678
|
+
const matches = (await kv.list(KV.facets)).filter((f) => ids.has(f.targetId) && targetTypes.has(f.targetType) && !facetTargetLive(f, live.get(f.targetId)));
|
|
6481
6679
|
await Promise.all(matches.map((f) => kv.delete(KV.facets, f.id)));
|
|
6482
6680
|
} catch (err) {
|
|
6483
6681
|
logger.warn("Facet cleanup failed", {
|
|
@@ -6753,6 +6951,7 @@ function registerRememberFunction(sdk, kv) {
|
|
|
6753
6951
|
if (data.ttlDays && typeof data.ttlDays === "number" && data.ttlDays > 0) memory.forgetAfter = new Date(Date.now() + data.ttlDays * 864e5).toISOString();
|
|
6754
6952
|
if (supersededMemory) {
|
|
6755
6953
|
supersededMemory.isLatest = false;
|
|
6954
|
+
supersededMemory.updatedAt = supersededAt(supersededMemory.updatedAt, now);
|
|
6756
6955
|
await kv.set(KV.memories, supersededMemory.id, supersededMemory);
|
|
6757
6956
|
try {
|
|
6758
6957
|
getSearchIndex().remove(supersededMemory.id);
|
|
@@ -6775,7 +6974,11 @@ function registerRememberFunction(sdk, kv) {
|
|
|
6775
6974
|
nearMatch
|
|
6776
6975
|
};
|
|
6777
6976
|
});
|
|
6778
|
-
await vectorIndexAddGuarded(memory.id, memory.sessionIds?.[0] ?? "memory",
|
|
6977
|
+
await vectorIndexAddGuarded(memory.id, memory.sessionIds?.[0] ?? "memory", observationEmbedText({
|
|
6978
|
+
title: memory.title,
|
|
6979
|
+
narrative: memory.content,
|
|
6980
|
+
concepts: memory.concepts
|
|
6981
|
+
}), {
|
|
6779
6982
|
kind: "memory",
|
|
6780
6983
|
logId: memory.id
|
|
6781
6984
|
}, (embedding, isCurrent) => withKeyedLock("mem:remember", async () => {
|
|
@@ -6917,6 +7120,7 @@ function registerRememberFunction(sdk, kv) {
|
|
|
6917
7120
|
}
|
|
6918
7121
|
});
|
|
6919
7122
|
}
|
|
7123
|
+
if (deletedObservationIds.length > 0) await deleteFacetsForTargets(kv, deletedObservationIds, { targetTypes: ["memory", "observation"] });
|
|
6920
7124
|
if (deleted > 0 || indexCleaned) await flushIndexSave();
|
|
6921
7125
|
if (deleted > 0 || failures.length > 0) await recordAudit(kv, "forget", "mem::forget", [...deletedMemoryIds, ...deletedObservationIds], {
|
|
6922
7126
|
sessionId: data.sessionId,
|
|
@@ -7357,6 +7561,7 @@ function registerRelationsFunction(sdk, kv) {
|
|
|
7357
7561
|
isLatest: true
|
|
7358
7562
|
};
|
|
7359
7563
|
existing.isLatest = false;
|
|
7564
|
+
existing.updatedAt = supersededAt(existing.updatedAt, now);
|
|
7360
7565
|
await kv.set(KV.memories, existing.id, existing);
|
|
7361
7566
|
try {
|
|
7362
7567
|
getSearchIndex().remove(existing.id);
|
|
@@ -7377,7 +7582,11 @@ function registerRelationsFunction(sdk, kv) {
|
|
|
7377
7582
|
error: err instanceof Error ? err.message : String(err)
|
|
7378
7583
|
});
|
|
7379
7584
|
}
|
|
7380
|
-
await vectorIndexAddGuarded(evolved.id, evolved.sessionIds?.[0] ?? "memory",
|
|
7585
|
+
await vectorIndexAddGuarded(evolved.id, evolved.sessionIds?.[0] ?? "memory", observationEmbedText({
|
|
7586
|
+
title: evolved.title,
|
|
7587
|
+
narrative: evolved.content,
|
|
7588
|
+
concepts: evolved.concepts
|
|
7589
|
+
}), {
|
|
7381
7590
|
kind: "memory",
|
|
7382
7591
|
logId: evolved.id
|
|
7383
7592
|
});
|
|
@@ -7620,6 +7829,7 @@ function getFollowupStats() {
|
|
|
7620
7829
|
};
|
|
7621
7830
|
}
|
|
7622
7831
|
const LESSON_CONTENT_PREVIEW_CHARS = 240;
|
|
7832
|
+
const SCOPED_RETRY_CANDIDATES = 1e3;
|
|
7623
7833
|
function registerSmartSearchFunction(sdk, kv, searchFn) {
|
|
7624
7834
|
sdk.registerFunction("mem::smart-search", async (data) => {
|
|
7625
7835
|
if (data.targetLayer !== void 0 && !isSearchLayer(data.targetLayer)) throw new Error("mem::smart-search: targetLayer must be one of 'all', 'memory', or 'observation'");
|
|
@@ -7696,16 +7906,32 @@ function registerSmartSearchFunction(sdk, kv, searchFn) {
|
|
|
7696
7906
|
return (await read(KV.sessions, sessionId))?.project === project;
|
|
7697
7907
|
};
|
|
7698
7908
|
const [hybridResults, lessons] = await Promise.all([searchFn(data.query, overFetchLimit, targetLayer, authorizeGraph), includeLessons ? recallLessons(sdk, data.query, lessonLimit, project) : Promise.resolve([])]);
|
|
7699
|
-
const
|
|
7700
|
-
|
|
7701
|
-
|
|
7702
|
-
|
|
7703
|
-
|
|
7704
|
-
|
|
7705
|
-
|
|
7706
|
-
|
|
7707
|
-
|
|
7708
|
-
|
|
7909
|
+
const scopeResults = async (results) => {
|
|
7910
|
+
const layerResults = results.filter((result) => matchesSearchLayer(result.observation.id, result.sessionId, targetLayer, result.layer ?? getSearchIndex().layerOf(result.observation.id)));
|
|
7911
|
+
const projectResults = matchesProject ? await filterProjectResults(layerResults, (result) => matchesProject(result.observation.id, result.sessionId)) : layerResults;
|
|
7912
|
+
return filterAgentId ? projectResults.filter((r) => r.observation.agentId === filterAgentId).slice(0, limit) : projectResults.slice(0, limit);
|
|
7913
|
+
};
|
|
7914
|
+
let filteredHybrid = await scopeResults(hybridResults);
|
|
7915
|
+
if ((filterAgentId || project) && filteredHybrid.length < limit && getSearchIndex().size > overFetchLimit) try {
|
|
7916
|
+
const deeper = await scopeResults(await searchFn(data.query, SCOPED_RETRY_CANDIDATES, targetLayer, authorizeGraph));
|
|
7917
|
+
const seen = new Set(deeper.map((result) => result.observation.id));
|
|
7918
|
+
filteredHybrid = [...deeper, ...filteredHybrid.filter((result) => !seen.has(result.observation.id))].slice(0, limit);
|
|
7919
|
+
} catch (err) {
|
|
7920
|
+
logger.warn("Smart search deeper scoped ranking failed; keeping first-pass results", { error: err instanceof Error ? err.message : String(err) });
|
|
7921
|
+
}
|
|
7922
|
+
const compact = await Promise.all(filteredHybrid.map(async (r) => {
|
|
7923
|
+
const layer = r.layer ?? getSearchIndex().layerOf(r.observation.id) ?? getSearchResultLayer(r.observation.id, r.sessionId);
|
|
7924
|
+
const memoryType = layer === "memory" ? (await kv.get(KV.memories, r.observation.id).catch(() => null))?.type ?? r.observation.memoryType : void 0;
|
|
7925
|
+
return {
|
|
7926
|
+
obsId: r.observation.id,
|
|
7927
|
+
layer,
|
|
7928
|
+
sessionId: r.sessionId,
|
|
7929
|
+
title: r.observation.title,
|
|
7930
|
+
type: r.observation.type,
|
|
7931
|
+
...memoryType !== void 0 && { memoryType },
|
|
7932
|
+
score: r.combinedScore,
|
|
7933
|
+
timestamp: r.observation.timestamp
|
|
7934
|
+
};
|
|
7709
7935
|
}));
|
|
7710
7936
|
recordAccessBatch(kv, compact.map((r) => r.obsId));
|
|
7711
7937
|
if (data.sessionId && typeof data.sessionId === "string" && data.source !== "viewer" && compact.length > 0) {
|
|
@@ -7906,6 +8132,7 @@ function registerRecentSearchesSweepFunction(sdk, kv) {
|
|
|
7906
8132
|
const HOUR_MS = 3600 * 1e3;
|
|
7907
8133
|
function isStaleActive(session, cutoff) {
|
|
7908
8134
|
if (!session || session.status !== "active") return false;
|
|
8135
|
+
if (typeof session.id !== "string" || session.id.length === 0) return false;
|
|
7909
8136
|
const freshness = session.updatedAt ?? session.startedAt;
|
|
7910
8137
|
if (!freshness) return false;
|
|
7911
8138
|
const ts = new Date(freshness).getTime();
|
|
@@ -8201,6 +8428,7 @@ function registerAutoForgetFunction(sdk, kv) {
|
|
|
8201
8428
|
if (!dryRun) {
|
|
8202
8429
|
const older = new Date(memA.createdAt).getTime() < new Date(memB.createdAt).getTime() ? memA : memB;
|
|
8203
8430
|
older.isLatest = false;
|
|
8431
|
+
older.updatedAt = supersededAt(older.updatedAt, (/* @__PURE__ */ new Date()).toISOString());
|
|
8204
8432
|
await kv.set(KV.memories, older.id, older);
|
|
8205
8433
|
await recordAudit(kv, "forget", "mem::auto-forget", [older.id], {
|
|
8206
8434
|
resource: "memory",
|
|
@@ -8723,6 +8951,7 @@ function registerLessonsFunctions(sdk, kv) {
|
|
|
8723
8951
|
lessonRecords.delete(lesson.id);
|
|
8724
8952
|
if (lessonIndex) lessonIndex.remove(lesson.id);
|
|
8725
8953
|
noteLessonMutation();
|
|
8954
|
+
await deleteFacetsForTargets(kv, [lesson.id]);
|
|
8726
8955
|
try {
|
|
8727
8956
|
await recordAudit(kv, "lesson_delete", "mem::lesson-delete", [lesson.id]);
|
|
8728
8957
|
} catch {}
|
|
@@ -8768,11 +8997,14 @@ function registerLessonsFunctions(sdk, kv) {
|
|
|
8768
8997
|
}
|
|
8769
8998
|
}
|
|
8770
8999
|
await Promise.all(dirty.map((l) => kv.set(KV.lessons, l.id, l)));
|
|
9000
|
+
const softDeletedIds = [];
|
|
8771
9001
|
for (const l of dirty) if (l.deleted) {
|
|
9002
|
+
softDeletedIds.push(l.id);
|
|
8772
9003
|
lessonRecords.delete(l.id);
|
|
8773
9004
|
if (lessonIndex) lessonIndex.remove(l.id);
|
|
8774
9005
|
} else lessonRecords.set(l.id, l);
|
|
8775
9006
|
if (dirty.length > 0) noteLessonMutation();
|
|
9007
|
+
if (softDeletedIds.length > 0) await deleteFacetsForTargets(kv, softDeletedIds);
|
|
8776
9008
|
await Promise.all(auditEvents.map((event) => recordAudit(kv, "lesson_strengthen", "mem::lesson-decay-sweep", [event.id], {
|
|
8777
9009
|
action: event.action,
|
|
8778
9010
|
actor: "system",
|
|
@@ -9021,7 +9253,8 @@ function registerExportImportFunction(sdk, state) {
|
|
|
9021
9253
|
"0.9.28",
|
|
9022
9254
|
"0.9.29",
|
|
9023
9255
|
"0.9.30",
|
|
9024
|
-
"0.9.31"
|
|
9256
|
+
"0.9.31",
|
|
9257
|
+
"0.9.32"
|
|
9025
9258
|
]).has(importData.version)) return {
|
|
9026
9259
|
success: false,
|
|
9027
9260
|
error: `Unsupported export version: ${importData.version}`
|
|
@@ -10399,7 +10632,7 @@ function registerConsolidationPipelineFunction(sdk, kv, provider) {
|
|
|
10399
10632
|
if (!data?.force && !isConsolidationEnabled()) return {
|
|
10400
10633
|
success: false,
|
|
10401
10634
|
skipped: true,
|
|
10402
|
-
reason: "Consolidation disabled: set CONSOLIDATION_ENABLED=true or
|
|
10635
|
+
reason: "Consolidation disabled: set CONSOLIDATION_ENABLED=true or choose an LLM provider (AGENTMEMORY_LLM_PROVIDER=anthropic, openai, gemini, openrouter or minimax with that provider's key, or AGENTMEMORY_ALLOW_AGENT_SDK=true). A provider key alone does not turn on LLM use."
|
|
10403
10636
|
};
|
|
10404
10637
|
const tier = data?.tier || "all";
|
|
10405
10638
|
const decayDays = getConsolidationDecayDays();
|
|
@@ -18382,7 +18615,9 @@ function createStatusReporter(sdk, kv, deps) {
|
|
|
18382
18615
|
llmRoute: describeLlmRoute(config.provider),
|
|
18383
18616
|
functionMetrics: functionMetrics ?? [],
|
|
18384
18617
|
provider: detectLlmProviderKind(),
|
|
18618
|
+
providerHint: llmOptInHint(),
|
|
18385
18619
|
embeddingProvider: describeEmbeddingProvider(),
|
|
18620
|
+
embeddingHint: embeddingOptInHint(),
|
|
18386
18621
|
flags: buildConfigFlags(),
|
|
18387
18622
|
index: {
|
|
18388
18623
|
bm25Documents: idx.size,
|
|
@@ -18527,13 +18762,18 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
|
|
|
18527
18762
|
sdk.registerFunction("api::config-flags", async (req) => {
|
|
18528
18763
|
const authErr = checkAuth(req, secret);
|
|
18529
18764
|
if (authErr) return authErr;
|
|
18765
|
+
const providerKind = detectLlmProviderKind();
|
|
18766
|
+
const embeddingProvider = describeEmbeddingProvider();
|
|
18767
|
+
const flags = buildConfigFlags();
|
|
18530
18768
|
return {
|
|
18531
18769
|
status_code: 200,
|
|
18532
18770
|
body: {
|
|
18533
18771
|
version: VERSION,
|
|
18534
|
-
provider:
|
|
18535
|
-
|
|
18536
|
-
|
|
18772
|
+
provider: providerKind,
|
|
18773
|
+
providerHint: llmOptInHint(),
|
|
18774
|
+
embeddingProvider,
|
|
18775
|
+
embeddingHint: embeddingOptInHint(),
|
|
18776
|
+
flags
|
|
18537
18777
|
}
|
|
18538
18778
|
};
|
|
18539
18779
|
});
|
|
@@ -22384,6 +22624,45 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
|
|
|
22384
22624
|
http_method: "POST"
|
|
22385
22625
|
}
|
|
22386
22626
|
});
|
|
22627
|
+
sdk.registerFunction("api::lesson-get", async (req) => {
|
|
22628
|
+
const denied = checkAuth(req, secret);
|
|
22629
|
+
if (denied) return denied;
|
|
22630
|
+
const body = req.body;
|
|
22631
|
+
const lessonId = typeof body?.lessonId === "string" ? body.lessonId.trim() : "";
|
|
22632
|
+
if (!lessonId) return {
|
|
22633
|
+
status_code: 400,
|
|
22634
|
+
body: { error: "lessonId is required" }
|
|
22635
|
+
};
|
|
22636
|
+
if (body.project !== void 0 && typeof body.project !== "string") return {
|
|
22637
|
+
status_code: 400,
|
|
22638
|
+
body: { error: "project must be a string" }
|
|
22639
|
+
};
|
|
22640
|
+
const project = typeof body.project === "string" ? body.project.trim() : "";
|
|
22641
|
+
const lesson = await kv.get(KV.lessons, lessonId);
|
|
22642
|
+
if (!lesson || lesson.deleted) return {
|
|
22643
|
+
status_code: 404,
|
|
22644
|
+
body: { error: "lesson not found" }
|
|
22645
|
+
};
|
|
22646
|
+
if (lesson.project !== void 0 && lesson.project !== project) return {
|
|
22647
|
+
status_code: 404,
|
|
22648
|
+
body: { error: "lesson not found" }
|
|
22649
|
+
};
|
|
22650
|
+
return {
|
|
22651
|
+
status_code: 200,
|
|
22652
|
+
body: {
|
|
22653
|
+
success: true,
|
|
22654
|
+
lesson
|
|
22655
|
+
}
|
|
22656
|
+
};
|
|
22657
|
+
});
|
|
22658
|
+
sdk.registerTrigger({
|
|
22659
|
+
type: "http",
|
|
22660
|
+
function_id: "api::lesson-get",
|
|
22661
|
+
config: {
|
|
22662
|
+
api_path: "/agentmemory/lessons/get",
|
|
22663
|
+
http_method: "POST"
|
|
22664
|
+
}
|
|
22665
|
+
});
|
|
22387
22666
|
sdk.registerFunction("api::lesson-strengthen", async (req) => {
|
|
22388
22667
|
const denied = checkAuth(req, secret);
|
|
22389
22668
|
if (denied) return denied;
|
|
@@ -23162,13 +23441,18 @@ function parseCsvList(value) {
|
|
|
23162
23441
|
if (Array.isArray(value)) return value.map((v) => typeof v === "string" ? v.trim() : "").filter(Boolean);
|
|
23163
23442
|
return [];
|
|
23164
23443
|
}
|
|
23444
|
+
const SLOT_TOOL_NAMES = new Set(getAllTools().filter((t) => t.name.startsWith("memory_slot_")).map((t) => t.name));
|
|
23445
|
+
function isSlotTool(name) {
|
|
23446
|
+
return SLOT_TOOL_NAMES.has(name);
|
|
23447
|
+
}
|
|
23165
23448
|
function registerMcpEndpoints(sdk, kv, secret) {
|
|
23449
|
+
const slotsEnabled = isSlotsEnabled();
|
|
23166
23450
|
sdk.registerFunction("mcp::tools::list", async (req) => {
|
|
23167
23451
|
const authErr = checkAuth(req, secret);
|
|
23168
23452
|
if (authErr) return authErr;
|
|
23169
23453
|
return {
|
|
23170
23454
|
status_code: 200,
|
|
23171
|
-
body: { tools: getVisibleTools() }
|
|
23455
|
+
body: { tools: getVisibleTools().filter((t) => slotsEnabled || !isSlotTool(t.name)) }
|
|
23172
23456
|
};
|
|
23173
23457
|
});
|
|
23174
23458
|
sdk.registerTrigger({
|
|
@@ -23187,6 +23471,7 @@ function registerMcpEndpoints(sdk, kv, secret) {
|
|
|
23187
23471
|
body: { error: "name is required" }
|
|
23188
23472
|
};
|
|
23189
23473
|
const { name, arguments: args = {} } = req.body;
|
|
23474
|
+
if (isSlotTool(name) && !slotsEnabled) return slotsDisabledResponse();
|
|
23190
23475
|
try {
|
|
23191
23476
|
switch (name) {
|
|
23192
23477
|
case "memory_recall": {
|
|
@@ -24208,6 +24493,11 @@ function registerMcpEndpoints(sdk, kv, secret) {
|
|
|
24208
24493
|
body: { error: "content is required" }
|
|
24209
24494
|
};
|
|
24210
24495
|
const lessonTags = typeof args.tags === "string" && args.tags.trim() ? args.tags.split(",").map((t) => t.trim()).filter(Boolean) : [];
|
|
24496
|
+
const lessonSourceIds = normalizeLessonSourceIds(args.sourceIds);
|
|
24497
|
+
if (!lessonSourceIds) return {
|
|
24498
|
+
status_code: 400,
|
|
24499
|
+
body: { error: `sourceIds must be an array of at most 50 ids (session, memory, observation or crystal ids) without spaces` }
|
|
24500
|
+
};
|
|
24211
24501
|
const lessonSaveResult = await sdk.trigger({
|
|
24212
24502
|
function_id: "mem::lesson-save",
|
|
24213
24503
|
payload: {
|
|
@@ -24216,7 +24506,8 @@ function registerMcpEndpoints(sdk, kv, secret) {
|
|
|
24216
24506
|
confidence: args.confidence,
|
|
24217
24507
|
project: args.project,
|
|
24218
24508
|
tags: lessonTags,
|
|
24219
|
-
source: "manual"
|
|
24509
|
+
source: "manual",
|
|
24510
|
+
sourceIds: lessonSourceIds
|
|
24220
24511
|
}
|
|
24221
24512
|
});
|
|
24222
24513
|
return {
|
|
@@ -24638,24 +24929,16 @@ function registerMcpEndpoints(sdk, kv, secret) {
|
|
|
24638
24929
|
};
|
|
24639
24930
|
}
|
|
24640
24931
|
if (uri === "agentmemory://graph/stats") try {
|
|
24641
|
-
const
|
|
24642
|
-
|
|
24643
|
-
|
|
24644
|
-
|
|
24645
|
-
for (const n of nodes) nodesByType[n.type] = (nodesByType[n.type] || 0) + 1;
|
|
24646
|
-
const edgesByType = {};
|
|
24647
|
-
for (const e of edges) edgesByType[e.type] = (edgesByType[e.type] || 0) + 1;
|
|
24932
|
+
const stats = await sdk.trigger({
|
|
24933
|
+
function_id: "mem::graph-stats",
|
|
24934
|
+
payload: {}
|
|
24935
|
+
});
|
|
24648
24936
|
return {
|
|
24649
24937
|
status_code: 200,
|
|
24650
24938
|
body: { contents: [{
|
|
24651
24939
|
uri,
|
|
24652
24940
|
mimeType: "application/json",
|
|
24653
|
-
text: JSON.stringify(
|
|
24654
|
-
totalNodes: nodes.length,
|
|
24655
|
-
totalEdges: edges.length,
|
|
24656
|
-
nodesByType,
|
|
24657
|
-
edgesByType
|
|
24658
|
-
})
|
|
24941
|
+
text: JSON.stringify(stats)
|
|
24659
24942
|
}] }
|
|
24660
24943
|
};
|
|
24661
24944
|
} catch {
|
|
@@ -24665,8 +24948,15 @@ function registerMcpEndpoints(sdk, kv, secret) {
|
|
|
24665
24948
|
uri,
|
|
24666
24949
|
mimeType: "application/json",
|
|
24667
24950
|
text: JSON.stringify({
|
|
24668
|
-
totalNodes:
|
|
24669
|
-
totalEdges:
|
|
24951
|
+
totalNodes: null,
|
|
24952
|
+
totalEdges: null,
|
|
24953
|
+
nodesByType: {},
|
|
24954
|
+
edgesByType: {},
|
|
24955
|
+
fromSnapshot: false,
|
|
24956
|
+
fromIndex: false,
|
|
24957
|
+
available: false,
|
|
24958
|
+
coverage: "unknown",
|
|
24959
|
+
warning: "Graph stats are unavailable. Check agentmemory graph-index status."
|
|
24670
24960
|
})
|
|
24671
24961
|
}] }
|
|
24672
24962
|
};
|
|
@@ -24948,14 +25238,18 @@ async function main() {
|
|
|
24948
25238
|
const config = loadConfig();
|
|
24949
25239
|
const embeddingConfig = loadEmbeddingConfig();
|
|
24950
25240
|
const fallbackConfig = loadFallbackConfig();
|
|
24951
|
-
const provider = fallbackConfig.providers.length > 0 ? createFallbackProvider(config.provider, fallbackConfig) : createProvider(config.provider);
|
|
25241
|
+
const provider = fallbackConfig.providers.length > 0 && config.provider.provider !== "noop" ? createFallbackProvider(config.provider, fallbackConfig) : createProvider(config.provider);
|
|
24952
25242
|
const embeddingProvider = createEmbeddingProvider();
|
|
24953
25243
|
const imageEmbeddingProvider = createImageEmbeddingProvider();
|
|
24954
25244
|
bootLog(`Starting worker v${VERSION}...`);
|
|
24955
25245
|
bootLog(`Engine: ${config.engineUrl}`);
|
|
24956
25246
|
bootLog(`Provider: ${config.provider.provider} (${config.provider.model})`);
|
|
24957
25247
|
if (embeddingProvider) bootLog(`Embedding provider: ${embeddingProvider.name} (${embeddingProvider.dimensions} dims)`);
|
|
24958
|
-
else
|
|
25248
|
+
else {
|
|
25249
|
+
bootLog(`Embedding provider: none (BM25-only mode)`);
|
|
25250
|
+
const embeddingHint = embeddingOptInHint();
|
|
25251
|
+
if (embeddingHint) bootLog(embeddingHint);
|
|
25252
|
+
}
|
|
24959
25253
|
if (imageEmbeddingProvider) bootLog(`Image embedding provider: ${imageEmbeddingProvider.name} (${imageEmbeddingProvider.dimensions} dims) — vision-search active`);
|
|
24960
25254
|
bootLog(`REST API: http://localhost:${config.restPort}/agentmemory/*`);
|
|
24961
25255
|
const sdk = withWriteScrubbing(registerWorker(config.engineUrl, {
|
|
@@ -24978,6 +25272,9 @@ async function main() {
|
|
|
24978
25272
|
stateBackend = getStateBackend();
|
|
24979
25273
|
} catch {}
|
|
24980
25274
|
const kv = new StateKV(sdk, { backend: stateBackend });
|
|
25275
|
+
const stateReadiness = await waitForStateReady(sdk, { onWaiting: (error) => bootWarn(`Waiting for the state worker to register state::get and state::list (${error})`) });
|
|
25276
|
+
assertStateReady(stateReadiness);
|
|
25277
|
+
if (stateReadiness.attempts > 1) bootLog(`State worker ready after ${stateReadiness.waitedMs}ms (${stateReadiness.attempts} attempts)`);
|
|
24981
25278
|
const secret = resolveWorkerSecret();
|
|
24982
25279
|
const metricsStore = new MetricsStore(kv);
|
|
24983
25280
|
const dedupMap = new DedupMap();
|
|
@@ -25082,7 +25379,7 @@ async function main() {
|
|
|
25082
25379
|
const bm25Index = getSearchIndex();
|
|
25083
25380
|
const graphWeight = parseFloat(getEnvVar("AGENTMEMORY_GRAPH_WEIGHT") || "0.3");
|
|
25084
25381
|
const hybridSearch = new HybridSearch(bm25Index, vectorIndex, embeddingProvider, kv, embeddingConfig.bm25Weight, embeddingConfig.vectorWeight, graphWeight);
|
|
25085
|
-
const hybridRanker = (query, limit, targetLayer, authorizeGraph) => hybridSearch.search(query, limit, targetLayer, authorizeGraph);
|
|
25382
|
+
const hybridRanker = (query, limit, targetLayer, authorizeGraph, request) => hybridSearch.search(query, limit, targetLayer, authorizeGraph, request);
|
|
25086
25383
|
registerSmartSearchFunction(sdk, kv, hybridRanker);
|
|
25087
25384
|
setHybridRanker(hybridRanker);
|
|
25088
25385
|
registerRecentSearchesSweepFunction(sdk, kv);
|
|
@@ -25180,7 +25477,7 @@ async function main() {
|
|
|
25180
25477
|
console.warn(`[agentmemory] Failed to rebuild the BM25 index:`, err);
|
|
25181
25478
|
}
|
|
25182
25479
|
bootLog(`Ready. ${embeddingProvider ? "Triple-stream (BM25+Vector+Graph)" : "BM25+Graph"} search active.`);
|
|
25183
|
-
bootLog(`REST API:
|
|
25480
|
+
bootLog(`REST API: 147 endpoints at http://localhost:${config.restPort}/agentmemory/*`);
|
|
25184
25481
|
bootLog(`MCP surface (opt-in via \`npx @agentmemory/mcp\`): ${getAllTools().length} tools · 6 resources · 3 prompts`);
|
|
25185
25482
|
(async () => {
|
|
25186
25483
|
try {
|
|
@@ -25340,4 +25637,4 @@ main().catch(async (err) => {
|
|
|
25340
25637
|
//#endregion
|
|
25341
25638
|
export {};
|
|
25342
25639
|
|
|
25343
|
-
//# sourceMappingURL=src-
|
|
25640
|
+
//# sourceMappingURL=src-C23nMpda.mjs.map
|