@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,5 +1,5 @@
|
|
|
1
1
|
import { a as KV, l as hasCjk, 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 {
|
|
2
|
+
import { H as getAgentId, _ as recordAudit, at as isAgentScopeIsolated, c as memoryToObservation, d as getSearchResultLayer, dt as isGraphExtractionEnabled, f as isSearchLayer, k as logger, l as observationEmbedText, m as matchesSearchLayer, nt as getVectorBackfillMax, o as buildRecallResponse, p as isSearchResultLayer, pt as isVectorBackfillAllEnabled, y as safeAudit } from "./secret-store-iYXRcrO8.mjs";
|
|
3
3
|
import { i as isManagedImagePath } from "./image-store-BsN4vyjr.mjs";
|
|
4
4
|
import { chmodSync, closeSync, existsSync, fsyncSync, mkdirSync, openSync, readFileSync, readdirSync, renameSync, statSync, unlinkSync, utimesSync, writeFileSync, writeSync } from "node:fs";
|
|
5
5
|
import { dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
@@ -128,7 +128,29 @@ function resolveDataDir(options = {}) {
|
|
|
128
128
|
}
|
|
129
129
|
//#endregion
|
|
130
130
|
//#region src/functions/privacy.ts
|
|
131
|
-
const
|
|
131
|
+
const PRIVATE_TAG_TOKEN_RE = /<private(?=\s|>)[^>]*>|<\/private\s*>/gi;
|
|
132
|
+
function redactPrivateBlocks(input) {
|
|
133
|
+
const tokens = new RegExp(PRIVATE_TAG_TOKEN_RE.source, PRIVATE_TAG_TOKEN_RE.flags);
|
|
134
|
+
let out = "";
|
|
135
|
+
let cursor = 0;
|
|
136
|
+
let depth = 0;
|
|
137
|
+
for (let match = tokens.exec(input); match; match = tokens.exec(input)) {
|
|
138
|
+
const closing = match[0].startsWith("</");
|
|
139
|
+
if (depth === 0) {
|
|
140
|
+
if (closing) continue;
|
|
141
|
+
out += input.slice(cursor, match.index);
|
|
142
|
+
depth = 1;
|
|
143
|
+
} else if (closing) {
|
|
144
|
+
depth -= 1;
|
|
145
|
+
if (depth === 0) {
|
|
146
|
+
out += "[REDACTED]";
|
|
147
|
+
cursor = match.index + match[0].length;
|
|
148
|
+
}
|
|
149
|
+
} else depth += 1;
|
|
150
|
+
}
|
|
151
|
+
if (depth > 0) return `${out}[REDACTED]`;
|
|
152
|
+
return out + input.slice(cursor);
|
|
153
|
+
}
|
|
132
154
|
const SECRET_PATTERN_SOURCES = [
|
|
133
155
|
/(?:api[_-]?key|secret|token|password|credential|auth)[\s]*[=:]\s*["']?[A-Za-z0-9_\-/.+]{20,}["']?/gi,
|
|
134
156
|
/Bearer\s+[A-Za-z0-9._\-+/=]{20,}/gi,
|
|
@@ -148,7 +170,7 @@ const SECRET_PATTERN_SOURCES = [
|
|
|
148
170
|
const PRIVATE_KEY_BLOCK_RE = /-----BEGIN [A-Z0-9 ]*PRIVATE KEY(?: BLOCK)?-----[\s\S]*?(?:-----END [A-Z0-9 ]*PRIVATE KEY(?: BLOCK)?-----|$)/g;
|
|
149
171
|
const URL_CREDENTIALS_RE = /\b([a-z][a-z0-9+.-]*:\/\/)[^\s/?#@:"'<>]*:[^\s/?#@"'<>]+@/gi;
|
|
150
172
|
function stripPrivateData(input) {
|
|
151
|
-
let result = input
|
|
173
|
+
let result = redactPrivateBlocks(input);
|
|
152
174
|
result = result.replace(new RegExp(PRIVATE_KEY_BLOCK_RE.source, PRIVATE_KEY_BLOCK_RE.flags), "[REDACTED_SECRET]");
|
|
153
175
|
result = result.replace(new RegExp(URL_CREDENTIALS_RE.source, URL_CREDENTIALS_RE.flags), "$1[REDACTED_SECRET]@");
|
|
154
176
|
for (const source of SECRET_PATTERN_SOURCES) {
|
|
@@ -2686,7 +2708,7 @@ const FUNCTION_FIXES = {
|
|
|
2686
2708
|
"mem::compress": "Compression calls your LLM provider. Check the provider key and model, or set AGENTMEMORY_AUTO_COMPRESS=false to use zero-LLM compression.",
|
|
2687
2709
|
"mem::graph-extract": "Graph extraction calls your LLM provider. Check the provider key and model, or set GRAPH_EXTRACTION_ENABLED=false."
|
|
2688
2710
|
};
|
|
2689
|
-
const LLM_KEY_FIX = "
|
|
2711
|
+
const LLM_KEY_FIX = "Set AGENTMEMORY_LLM_PROVIDER and that provider's key (for example AGENTMEMORY_LLM_PROVIDER=anthropic and ANTHROPIC_API_KEY) in ~/.agentmemory/.env and restart.";
|
|
2690
2712
|
const OFF_WITHOUT_LLM = [
|
|
2691
2713
|
"session summaries",
|
|
2692
2714
|
"consolidation into semantic facts and procedures",
|
|
@@ -2795,8 +2817,17 @@ function evaluateStatus(input) {
|
|
|
2795
2817
|
level: "info",
|
|
2796
2818
|
code: "no-llm-provider",
|
|
2797
2819
|
message: "No LLM provider is configured, so summaries, consolidation and graph extraction stay off. Search still works.",
|
|
2798
|
-
fix:
|
|
2820
|
+
fix: input.providerHint || "Set AGENTMEMORY_LLM_PROVIDER and that provider's key (for example AGENTMEMORY_LLM_PROVIDER=anthropic and ANTHROPIC_API_KEY) in ~/.agentmemory/.env and restart."
|
|
2799
2821
|
});
|
|
2822
|
+
if (input.embeddingHint) {
|
|
2823
|
+
const keyMissing = input.embeddingHint.startsWith("EMBEDDING_PROVIDER=");
|
|
2824
|
+
problems.push({
|
|
2825
|
+
level: "info",
|
|
2826
|
+
code: keyMissing ? "embedding-provider-key-missing" : "embedding-provider-not-chosen",
|
|
2827
|
+
message: keyMissing ? "EMBEDDING_PROVIDER names a cloud provider whose key is missing, so search is keyword and graph only." : "A cloud embedding key is present, but no embedding provider is chosen, so search is keyword and graph only.",
|
|
2828
|
+
fix: input.embeddingHint
|
|
2829
|
+
});
|
|
2830
|
+
}
|
|
2800
2831
|
const noLlm = input.provider === "noop";
|
|
2801
2832
|
const functions = markLlmFunctions(input.functionMetrics, input.provider).map((m) => ({
|
|
2802
2833
|
...m,
|
|
@@ -2977,7 +3008,9 @@ function evaluateStatus(input) {
|
|
|
2977
3008
|
provider: {
|
|
2978
3009
|
llm: input.provider,
|
|
2979
3010
|
route: input.provider === "noop" ? null : input.llmRoute ?? null,
|
|
3011
|
+
hint: input.providerHint ?? null,
|
|
2980
3012
|
embeddings: input.embeddingProvider,
|
|
3013
|
+
embeddingHint: input.embeddingHint ?? null,
|
|
2981
3014
|
circuitBreaker: input.circuitBreaker,
|
|
2982
3015
|
offWithoutLlm: noLlm ? OFF_WITHOUT_LLM : []
|
|
2983
3016
|
},
|
|
@@ -3302,7 +3335,7 @@ Rules:
|
|
|
3302
3335
|
- Be concise but preserve ALL technically relevant details
|
|
3303
3336
|
- File paths must be exact
|
|
3304
3337
|
- Importance: 1-3 for routine reads, 4-6 for edits/commands, 7-9 for architectural decisions, 10 for breaking changes
|
|
3305
|
-
- Concepts should be reusable search terms (e.g., "React hooks", "SQL migration", "auth middleware")
|
|
3338
|
+
- Concepts should be reusable search terms (e.g., "React hooks", "SQL migration", "auth middleware"); keep them in the user's language: when the source content is not English, include at least one concept in that original language, and when the observation mixes languages include both the original-language and English terms so search works in either
|
|
3306
3339
|
- Strip any secrets, tokens, or credentials from the output`;
|
|
3307
3340
|
function buildCompressionPrompt(observation) {
|
|
3308
3341
|
const parts = [`Timestamp: ${observation.timestamp}`, `Hook: ${observation.hookType}`];
|
|
@@ -3684,6 +3717,9 @@ function getSynonyms(stemmedTerm) {
|
|
|
3684
3717
|
}
|
|
3685
3718
|
//#endregion
|
|
3686
3719
|
//#region src/state/search-index.ts
|
|
3720
|
+
const USER_PROMPT_TERM_CAP = 2e3;
|
|
3721
|
+
const ASSISTANT_RESPONSE_TERM_CAP = 1e3;
|
|
3722
|
+
const TOOL_OUTPUT_TERM_CAP = 1e3;
|
|
3687
3723
|
var SearchIndex = class SearchIndex {
|
|
3688
3724
|
entries = /* @__PURE__ */ new Map();
|
|
3689
3725
|
invertedIndex = /* @__PURE__ */ new Map();
|
|
@@ -3942,6 +3978,9 @@ var SearchIndex = class SearchIndex {
|
|
|
3942
3978
|
...obs.files,
|
|
3943
3979
|
obs.type
|
|
3944
3980
|
];
|
|
3981
|
+
if (obs.source?.userPrompt) parts.push(obs.source.userPrompt.slice(0, USER_PROMPT_TERM_CAP));
|
|
3982
|
+
if (obs.source?.assistantResponse) parts.push(obs.source.assistantResponse.slice(0, ASSISTANT_RESPONSE_TERM_CAP));
|
|
3983
|
+
if (obs.source?.toolName === "conversation" && typeof obs.source.toolOutput === "string") parts.push(obs.source.toolOutput.slice(0, TOOL_OUTPUT_TERM_CAP));
|
|
3945
3984
|
return this.tokenize(parts.join(" ").toLowerCase());
|
|
3946
3985
|
}
|
|
3947
3986
|
tokenize(text) {
|
|
@@ -4449,7 +4488,11 @@ async function indexRecords(observations, memories) {
|
|
|
4449
4488
|
id: memory.id,
|
|
4450
4489
|
revision,
|
|
4451
4490
|
sessionId: memory.sessionIds?.[0] ?? "memory",
|
|
4452
|
-
text:
|
|
4491
|
+
text: observationEmbedText({
|
|
4492
|
+
title: memory.title,
|
|
4493
|
+
narrative: memory.content,
|
|
4494
|
+
concepts: memory.concepts
|
|
4495
|
+
}),
|
|
4453
4496
|
context: {
|
|
4454
4497
|
kind: "memory",
|
|
4455
4498
|
logId: memory.id
|
|
@@ -4463,7 +4506,7 @@ async function indexRecords(observations, memories) {
|
|
|
4463
4506
|
id: obs.id,
|
|
4464
4507
|
revision,
|
|
4465
4508
|
sessionId: obs.sessionId,
|
|
4466
|
-
text: obs
|
|
4509
|
+
text: observationEmbedText(obs),
|
|
4467
4510
|
context: {
|
|
4468
4511
|
kind: "observation",
|
|
4469
4512
|
logId: obs.id
|
|
@@ -4496,21 +4539,36 @@ async function findUnindexedObservations(kv) {
|
|
|
4496
4539
|
missing
|
|
4497
4540
|
};
|
|
4498
4541
|
}
|
|
4499
|
-
const
|
|
4500
|
-
const
|
|
4542
|
+
const LIST_RETRY_ATTEMPTS = 8;
|
|
4543
|
+
const LIST_RETRY_BASE_MS = 2500;
|
|
4544
|
+
const LIST_RETRY_BUDGET_MS = 7e4;
|
|
4501
4545
|
function delay(ms) {
|
|
4502
4546
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
4503
4547
|
}
|
|
4504
|
-
|
|
4548
|
+
function isStateNotReadyError(err) {
|
|
4549
|
+
const code = err?.code;
|
|
4550
|
+
if (code === "function_not_found" || code === "invocation_timeout" || code === "timeout" || code === "ECONNRESET" || code === "ECONNREFUSED" || code === "EPIPE") return true;
|
|
4551
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
4552
|
+
return /function_not_found|Function state::\w+ not found|timed out|timeout|ETIMEDOUT|ECONNRESET|ECONNREFUSED|EPIPE|socket hang up|connection (?:closed|reset)/i.test(message);
|
|
4553
|
+
}
|
|
4554
|
+
async function listWithRetry(kv, scope, label, deadline) {
|
|
4505
4555
|
let lastErr;
|
|
4506
|
-
|
|
4507
|
-
|
|
4508
|
-
|
|
4509
|
-
|
|
4510
|
-
|
|
4556
|
+
let attempts = 0;
|
|
4557
|
+
while (attempts < LIST_RETRY_ATTEMPTS) {
|
|
4558
|
+
attempts++;
|
|
4559
|
+
try {
|
|
4560
|
+
return await kv.list(scope);
|
|
4561
|
+
} catch (err) {
|
|
4562
|
+
lastErr = err;
|
|
4563
|
+
if (!isStateNotReadyError(err)) break;
|
|
4564
|
+
const remaining = deadline - performance.now();
|
|
4565
|
+
const wait = LIST_RETRY_BASE_MS * attempts;
|
|
4566
|
+
if (attempts >= LIST_RETRY_ATTEMPTS || wait >= remaining) break;
|
|
4567
|
+
await delay(wait);
|
|
4568
|
+
}
|
|
4511
4569
|
}
|
|
4512
|
-
logger.warn(
|
|
4513
|
-
attempts
|
|
4570
|
+
logger.warn(`${label}: failed to load`, {
|
|
4571
|
+
attempts,
|
|
4514
4572
|
error: lastErr instanceof Error ? lastErr.message : String(lastErr)
|
|
4515
4573
|
});
|
|
4516
4574
|
return null;
|
|
@@ -4560,20 +4618,24 @@ async function runKeywordRebuild(kv, vectorBackfillSince) {
|
|
|
4560
4618
|
};
|
|
4561
4619
|
let documents = 0;
|
|
4562
4620
|
let memoriesLoaded = false;
|
|
4563
|
-
|
|
4564
|
-
|
|
4621
|
+
const listDeadline = performance.now() + LIST_RETRY_BUDGET_MS;
|
|
4622
|
+
const memories = await listWithRetry(kv, KV.memories, "rebuildKeywordIndex: memories", listDeadline);
|
|
4623
|
+
const sessions = await listWithRetry(kv, KV.sessions, "rebuildKeywordIndex: sessions", listDeadline);
|
|
4624
|
+
if (memories === null) bm25RebuildIncomplete = true;
|
|
4625
|
+
else {
|
|
4565
4626
|
memoriesLoaded = true;
|
|
4566
4627
|
for (const memory of memories) {
|
|
4567
4628
|
if (memory.isLatest === false) continue;
|
|
4568
4629
|
if (!memory.title || !memory.content) continue;
|
|
4569
4630
|
idx.add(memoryToObservation(memory), "memory");
|
|
4570
|
-
consider(memory.id, memory.sessionIds?.[0] ?? "memory",
|
|
4631
|
+
consider(memory.id, memory.sessionIds?.[0] ?? "memory", observationEmbedText({
|
|
4632
|
+
title: memory.title,
|
|
4633
|
+
narrative: memory.content,
|
|
4634
|
+
concepts: memory.concepts
|
|
4635
|
+
}), memory.createdAt, "memory");
|
|
4571
4636
|
documents++;
|
|
4572
4637
|
}
|
|
4573
|
-
} catch (err) {
|
|
4574
|
-
logger.warn("rebuildKeywordIndex: failed to load memories", { error: err instanceof Error ? err.message : String(err) });
|
|
4575
4638
|
}
|
|
4576
|
-
const sessions = await listSessionsWithRetry(kv);
|
|
4577
4639
|
if (sessions === null) {
|
|
4578
4640
|
bm25RebuildIncomplete = true;
|
|
4579
4641
|
if (memoriesLoaded) memoryIndexReady = true;
|
|
@@ -4597,7 +4659,7 @@ async function runKeywordRebuild(kv, vectorBackfillSince) {
|
|
|
4597
4659
|
for (const obs of results.flat()) {
|
|
4598
4660
|
if (!obs.title || !obs.narrative) continue;
|
|
4599
4661
|
idx.add(obs);
|
|
4600
|
-
consider(obs.id, obs.sessionId, obs
|
|
4662
|
+
consider(obs.id, obs.sessionId, observationEmbedText(obs), obs.timestamp, "observation");
|
|
4601
4663
|
documents++;
|
|
4602
4664
|
}
|
|
4603
4665
|
}
|
|
@@ -4704,6 +4766,7 @@ function registerSearchFunction(sdk, kv) {
|
|
|
4704
4766
|
if (data.targetLayer !== void 0 && !isSearchLayer(data.targetLayer)) throw new Error("mem::search: targetLayer must be one of 'all', 'memory', or 'observation'");
|
|
4705
4767
|
const targetLayer = data.targetLayer ?? "all";
|
|
4706
4768
|
const MAX_LIMIT = 100;
|
|
4769
|
+
const MAX_CANDIDATES = 1e3;
|
|
4707
4770
|
let effectiveLimit = 20;
|
|
4708
4771
|
if (data.limit !== void 0) {
|
|
4709
4772
|
if (!Number.isInteger(data.limit) || data.limit < 1) throw new Error("mem::search: limit must be a positive integer");
|
|
@@ -4741,7 +4804,7 @@ function registerSearchFunction(sdk, kv) {
|
|
|
4741
4804
|
await rebuildPromise;
|
|
4742
4805
|
}
|
|
4743
4806
|
const filtering = !!(projectFilter || cwdFilter || filterAgentId);
|
|
4744
|
-
|
|
4807
|
+
let fetchLimit = filtering ? Math.max(effectiveLimit * 10, 100) : effectiveLimit;
|
|
4745
4808
|
let results;
|
|
4746
4809
|
const authorizeGraph = async (record, sessionId, read) => {
|
|
4747
4810
|
if (filterAgentId !== void 0 && record.agentId !== filterAgentId) return false;
|
|
@@ -4755,25 +4818,12 @@ function registerSearchFunction(sdk, kv) {
|
|
|
4755
4818
|
}
|
|
4756
4819
|
return true;
|
|
4757
4820
|
};
|
|
4758
|
-
if (hybridRanker) try {
|
|
4759
|
-
results = (await hybridRanker(query, fetchLimit, targetLayer, authorizeGraph)).map((r) => ({
|
|
4760
|
-
obsId: r.observation.id,
|
|
4761
|
-
sessionId: r.sessionId,
|
|
4762
|
-
score: r.combinedScore,
|
|
4763
|
-
observation: r.observation,
|
|
4764
|
-
layer: r.layer
|
|
4765
|
-
}));
|
|
4766
|
-
} catch (err) {
|
|
4767
|
-
logger.warn("hybrid ranking failed, falling back to keyword search", { error: err instanceof Error ? err.message : String(err) });
|
|
4768
|
-
results = idx.search(query, fetchLimit, targetLayer);
|
|
4769
|
-
}
|
|
4770
|
-
else results = idx.search(query, fetchLimit, targetLayer);
|
|
4771
4821
|
const sessionCache = /* @__PURE__ */ new Map();
|
|
4772
4822
|
const loadSession = async (sessionId) => {
|
|
4773
4823
|
if (sessionCache.has(sessionId)) return sessionCache.get(sessionId);
|
|
4774
|
-
const
|
|
4775
|
-
sessionCache.set(sessionId,
|
|
4776
|
-
return
|
|
4824
|
+
const pending = kv.get(KV.sessions, sessionId).then((session) => session ?? null);
|
|
4825
|
+
sessionCache.set(sessionId, pending);
|
|
4826
|
+
return pending;
|
|
4777
4827
|
};
|
|
4778
4828
|
const memoryProjectCache = /* @__PURE__ */ new Map();
|
|
4779
4829
|
const loadMemoryProject = async (obsId) => {
|
|
@@ -4782,53 +4832,88 @@ function registerSearchFunction(sdk, kv) {
|
|
|
4782
4832
|
memoryProjectCache.set(obsId, proj);
|
|
4783
4833
|
return proj;
|
|
4784
4834
|
};
|
|
4785
|
-
const
|
|
4786
|
-
const
|
|
4787
|
-
|
|
4788
|
-
|
|
4789
|
-
|
|
4790
|
-
|
|
4791
|
-
if (
|
|
4792
|
-
|
|
4793
|
-
|
|
4794
|
-
|
|
4795
|
-
|
|
4796
|
-
|
|
4797
|
-
|
|
4835
|
+
const observationCache = /* @__PURE__ */ new Map();
|
|
4836
|
+
const hybridRequest = {};
|
|
4837
|
+
let enriched = [];
|
|
4838
|
+
let useHybridRanker = hybridRanker !== null;
|
|
4839
|
+
while (true) {
|
|
4840
|
+
hybridRequest.candidateCount = void 0;
|
|
4841
|
+
if (useHybridRanker && hybridRanker) try {
|
|
4842
|
+
results = (await hybridRanker(query, fetchLimit, targetLayer, authorizeGraph, hybridRequest)).map((r) => ({
|
|
4843
|
+
obsId: r.observation.id,
|
|
4844
|
+
sessionId: r.sessionId,
|
|
4845
|
+
score: r.combinedScore,
|
|
4846
|
+
observation: r.observation,
|
|
4847
|
+
layer: r.layer
|
|
4848
|
+
}));
|
|
4849
|
+
} catch (err) {
|
|
4850
|
+
hybridRequest.candidateCount = void 0;
|
|
4851
|
+
logger.warn("hybrid ranking failed", { error: err instanceof Error ? err.message : String(err) });
|
|
4852
|
+
if (enriched.length > 0) break;
|
|
4853
|
+
useHybridRanker = false;
|
|
4854
|
+
results = idx.search(query, fetchLimit, targetLayer);
|
|
4855
|
+
}
|
|
4856
|
+
else results = idx.search(query, fetchLimit, targetLayer);
|
|
4857
|
+
enriched = [];
|
|
4858
|
+
let batchSize = Math.min(10, effectiveLimit);
|
|
4859
|
+
for (let offset = 0; offset < Math.min(results.length, fetchLimit) && enriched.length < effectiveLimit;) {
|
|
4860
|
+
const batch = results.slice(offset, Math.min(offset + batchSize, fetchLimit));
|
|
4861
|
+
offset += batch.length;
|
|
4862
|
+
const obsResults = await Promise.all(batch.map(async (r) => {
|
|
4863
|
+
const layer = r.layer ?? idx.layerOf(r.obsId) ?? getSearchResultLayer(r.obsId, r.sessionId);
|
|
4864
|
+
if (!matchesSearchLayer(r.obsId, r.sessionId, targetLayer, layer)) return null;
|
|
4865
|
+
if (filtering) {
|
|
4866
|
+
const memoryProject = projectFilter && layer === "memory" ? await loadMemoryProject(r.obsId) : null;
|
|
4867
|
+
if (projectFilter && memoryProject !== null && memoryProject !== projectFilter) return null;
|
|
4868
|
+
const session = projectFilter || cwdFilter ? await loadSession(r.sessionId) : null;
|
|
4869
|
+
if (projectFilter && memoryProject === null && !session) return null;
|
|
4870
|
+
if (cwdFilter && layer === "observation" && !session) return null;
|
|
4871
|
+
if (session) {
|
|
4872
|
+
if (projectFilter && memoryProject === null && session.project !== projectFilter) return null;
|
|
4873
|
+
if (cwdFilter && session.cwd !== cwdFilter) return null;
|
|
4874
|
+
}
|
|
4875
|
+
}
|
|
4876
|
+
const key = JSON.stringify([r.obsId, r.sessionId]);
|
|
4877
|
+
let pending = observationCache.get(key);
|
|
4878
|
+
if (!pending) {
|
|
4879
|
+
pending = (async () => {
|
|
4880
|
+
if (r.observation) return {
|
|
4881
|
+
observation: r.observation,
|
|
4882
|
+
layer: r.layer ?? idx.layerOf(r.obsId) ?? getSearchResultLayer(r.obsId, r.sessionId)
|
|
4883
|
+
};
|
|
4884
|
+
const obs = await kv.get(KV.observations(r.sessionId), r.obsId).catch(() => null);
|
|
4885
|
+
if (obs) return {
|
|
4886
|
+
observation: obs,
|
|
4887
|
+
layer: "observation"
|
|
4888
|
+
};
|
|
4889
|
+
const mem = await kv.get(KV.memories, r.obsId).catch(() => null);
|
|
4890
|
+
return mem ? {
|
|
4891
|
+
observation: memoryToObservation(mem),
|
|
4892
|
+
layer: "memory"
|
|
4893
|
+
} : null;
|
|
4894
|
+
})();
|
|
4895
|
+
observationCache.set(key, pending);
|
|
4896
|
+
}
|
|
4897
|
+
return pending;
|
|
4898
|
+
}));
|
|
4899
|
+
for (let i = 0; i < batch.length; i++) {
|
|
4900
|
+
const resolved = obsResults[i];
|
|
4901
|
+
if (!resolved) continue;
|
|
4902
|
+
const obs = resolved.observation;
|
|
4903
|
+
if (!matchesSearchLayer(obs.id, obs.sessionId, targetLayer, resolved.layer)) continue;
|
|
4904
|
+
if (filterAgentId !== void 0 && obs.agentId !== filterAgentId) continue;
|
|
4905
|
+
if (enriched.length >= effectiveLimit) break;
|
|
4906
|
+
enriched.push({
|
|
4907
|
+
observation: withoutObservationSource(obs),
|
|
4908
|
+
layer: resolved.layer,
|
|
4909
|
+
score: batch[i].score,
|
|
4910
|
+
sessionId: batch[i].sessionId
|
|
4911
|
+
});
|
|
4798
4912
|
}
|
|
4913
|
+
batchSize = Math.min(10, Math.max(effectiveLimit - enriched.length, batchSize * 2));
|
|
4799
4914
|
}
|
|
4800
|
-
|
|
4801
|
-
|
|
4802
|
-
const obsResults = await Promise.all(candidates.map(async (r) => {
|
|
4803
|
-
if (r.observation) return {
|
|
4804
|
-
observation: r.observation,
|
|
4805
|
-
layer: r.layer ?? idx.layerOf(r.obsId) ?? getSearchResultLayer(r.obsId, r.sessionId)
|
|
4806
|
-
};
|
|
4807
|
-
const obs = await kv.get(KV.observations(r.sessionId), r.obsId).catch(() => null);
|
|
4808
|
-
if (obs) return {
|
|
4809
|
-
observation: obs,
|
|
4810
|
-
layer: "observation"
|
|
4811
|
-
};
|
|
4812
|
-
const mem = await kv.get(KV.memories, r.obsId).catch(() => null);
|
|
4813
|
-
return mem ? {
|
|
4814
|
-
observation: memoryToObservation(mem),
|
|
4815
|
-
layer: "memory"
|
|
4816
|
-
} : null;
|
|
4817
|
-
}));
|
|
4818
|
-
const enriched = [];
|
|
4819
|
-
for (let i = 0; i < candidates.length; i++) {
|
|
4820
|
-
const resolved = obsResults[i];
|
|
4821
|
-
if (!resolved) continue;
|
|
4822
|
-
const obs = resolved.observation;
|
|
4823
|
-
if (!matchesSearchLayer(obs.id, obs.sessionId, targetLayer, resolved.layer)) continue;
|
|
4824
|
-
if (filterAgentId !== void 0 && obs.agentId !== filterAgentId) continue;
|
|
4825
|
-
if (enriched.length >= effectiveLimit) break;
|
|
4826
|
-
enriched.push({
|
|
4827
|
-
observation: withoutObservationSource(obs),
|
|
4828
|
-
layer: resolved.layer,
|
|
4829
|
-
score: candidates[i].score,
|
|
4830
|
-
sessionId: candidates[i].sessionId
|
|
4831
|
-
});
|
|
4915
|
+
if (!filtering || enriched.length >= effectiveLimit || (hybridRequest.candidateCount ?? results.length) < fetchLimit || fetchLimit >= MAX_CANDIDATES) break;
|
|
4916
|
+
fetchLimit = Math.min(fetchLimit * 2, MAX_CANDIDATES);
|
|
4832
4917
|
}
|
|
4833
4918
|
const response = buildRecallResponse(enriched, format, tokenBudget);
|
|
4834
4919
|
recordAccessBatch(kv, enriched.slice(0, response.results.length).map((result) => result.observation.id));
|
|
@@ -5579,7 +5664,7 @@ function registerCompressFunction(sdk, kv, provider, metricsStore) {
|
|
|
5579
5664
|
retryable: false
|
|
5580
5665
|
};
|
|
5581
5666
|
const committedRevision = observationRevision(compressed);
|
|
5582
|
-
await bounded(() => vectorIndexAddGuarded(observationId, sessionId, compressed
|
|
5667
|
+
await bounded(() => vectorIndexAddGuarded(observationId, sessionId, observationEmbedText(compressed), {
|
|
5583
5668
|
kind: "observation",
|
|
5584
5669
|
logId: observationId
|
|
5585
5670
|
}, (embedding, isCurrent) => withKeyedLock(`obs:${sessionId}`, async () => {
|
|
@@ -5909,4 +5994,4 @@ function registerCompressionRecovery(sdk, kv) {
|
|
|
5909
5994
|
//#endregion
|
|
5910
5995
|
export { normalizeAccessLog as $, resolveDataDir as $t, getVectorBackfillState as A, withGraphSnapshotUnknownMutation as At, scheduleIndexSave as B, resolveGraphScope as Bt, findUnindexedObservations as C, initializeGraphIndex as Ct, getKeywordRebuildEpoch as D, recoverGraphIndex as Dt, getIndexPersistenceStatus as E, reconcileGraphIndexRecord as Et, isMemoryIndexReady as F, isLegacyGraphState as Ft, setVectorBackfillState as G, retainSent as Gt, setHybridRanker as H, drainSpool as Ht, markKeywordRebuildPending as I, notifyGraphGenerationChange as It, vectorIndexRemove as J, spoolSummary as Jt, setVectorIndex as K, spoolDir as Kt, rankMemoryIds as L, pinGraphState as Lt, indexRecords as M, noteGraphSnapshotWrite as Mt, isBm25RebuildIncomplete as N, withoutGraphRecovery as Nt, getPendingVectorBackfillCount as O, withGraphIndexMutation as Ot, isKeywordRebuildInProgress as P, getGraphGeneration as Pt, emptyAccessLog as Q, withWriteScrubbing as Qt, rebuildKeywordIndex as R, pinGraphStateGeneration as Rt, backfillVectorBacklog as S, graphEdgeLookupKey as St, getEmbeddingProvider as T, normalizeGraphIndexText as Tt, setIndexPersistence as U, parseSentMark as Ut, setEmbeddingProvider as V, setGraphGenerationListener as Vt, setPendingVectorBackfillCount as W, reconcileSent as Wt, withoutObservationSource as X, scrubRecord as Xt, rawFromObservationSource as Y, registerPrivacyFunction as Yt, deleteAccessLog as Z, stripPrivateData as Zt, getLiveEventsStats as _, GRAPH_INDEX_MAX_ID_BYTES as _t, markCompressionDispatchFailed as a, runtimeMetadataPath as an, markLlmFunctions as at, validateOutput as b, finishGraphIndexBuild as bt, isValidEventId as c, singleFlight as ct, budgetLiveObservationSource as d, runGraphCompactOnBoot as dt, SHUTDOWN_FLUSH_TIMEOUT_MS as en, recordAccessBatch as et, SAFE_PAYLOAD_BYTES as f, setGraphCompactBootDisabled as ft, emitLiveEvent as g, registerGraphFunction as gt, payloadByteLength as h, persistGraphDelta as ht, compressionRaw as i, settleWithin as in, evaluateStatus as it, getVectorIndex as j, ensureGraphConsistency as jt, getSearchIndex as k, withGraphSnapshotIndexBarrier as kt, buildSyntheticCompression as l, GRAPH_COMPACT_BOOT_DELAY_MS as lt, oversizedPayloadError as m, boundSources as mt, compressionInFlight as n, registerStartupCleanup as nn, CURL_AUTH_HEADER as nt, needsCompression as o, prefersHtml as ot, checkPayloadFrameSize as p, COMPACT_SCOPES as pt, vectorIndexAddGuarded as q, spoolPolicy as qt, registerCompressFunction as r, runStartupCleanup as rn, UNINDEXED_SCAN_REUSE_MS as rt, pendingCompression as s, renderStatusHtml as st, parseCompressionScope as t, SHUTDOWN_HARD_EXIT_MS as tn, SearchIndex as tt, budgetImportedObservationSources as u, getGraphCompactBootStatus as ut, liveEvents as v, GraphIndexError as vt, flushIndexSave as w, mutateIndexedGraphRecord as wt, SummaryOutputSchema as x, getGraphIndexStatus as xt, scoreSummary as y, createGraphIndexReader as yt, registerSearchFunction as z, replaceGraphGeneration as zt };
|
|
5911
5996
|
|
|
5912
|
-
//# sourceMappingURL=compression-recovery-
|
|
5997
|
+
//# sourceMappingURL=compression-recovery-CZh63Jmz.mjs.map
|