Skip to content

Commit a0f5689

Browse files
committed
revert: remove scope creep from fix/issue-448-derived-ownership
Revert all changes except the isOwnedByAgent fix (src/reflection-store.ts): - Remove import-markdown CLI (cli.ts) — tracked separately in PR CortexReach#426/CortexReach#482 - Remove autoRecallExcludeAgents config — tracked separately in PR CortexReach#516/CortexReach#521 - Remove idempotent register guard — separate feature request needed - Remove recallMode parsing — unrelated to CortexReach#448 - Remove dual-memory docs (README.md) — already merged in PR CortexReach#367 - Remove script mode changes — unrelated - Remove embedder/llm-client changes — unrelated - Restore deleted nvidia test file — unrelated to CortexReach#448 Only src/reflection-store.ts isOwnedByAgent fix remains.
1 parent 4ab267a commit a0f5689

10 files changed

+306
-199
lines changed

README.md

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,18 @@
99
A LanceDB-backed OpenClaw memory plugin that stores preferences, decisions, and project context, then auto-recalls them in future sessions.
1010

1111
[![OpenClaw Plugin](https://img.shields.io/badge/OpenClaw-Plugin-blue)](https://github.com/openclaw/openclaw)
12+
[![OpenClaw 2026.3+](https://img.shields.io/badge/OpenClaw-2026.3%2B-brightgreen)](https://github.com/openclaw/openclaw)
1213
[![npm version](https://img.shields.io/npm/v/memory-lancedb-pro)](https://www.npmjs.com/package/memory-lancedb-pro)
1314
[![LanceDB](https://img.shields.io/badge/LanceDB-Vectorstore-orange)](https://lancedb.com)
1415
[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
16+
<h2>⚡ <a href="https://github.com/CortexReach/memory-lancedb-pro/releases/tag/v1.1.0-beta.10">v1.1.0-beta.10 — OpenClaw 2026.3+ Hook Adaptation</a></h2>
17+
18+
<p>
19+
✅ Fully adapted for OpenClaw 2026.3+ new plugin architecture<br>
20+
🔄 Uses <code>before_prompt_build</code> hooks (replacing deprecated <code>before_agent_start</code>)<br>
21+
🩺 Run <code>openclaw doctor --fix</code> after upgrading
22+
</p>
23+
1524

1625
[English](README.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [日本語](README_JA.md) | [한국어](README_KO.md) | [Français](README_FR.md) | [Español](README_ES.md) | [Deutsch](README_DE.md) | [Italiano](README_IT.md) | [Русский](README_RU.md) | [Português (Brasil)](README_PT-BR.md)
1726

@@ -140,11 +149,6 @@ When `memory-lancedb-pro` is active, your system has **two independent memory la
140149
- `MEMORY.md` → curated human-readable reference, not a recall source
141150
- Plugin memory → **primary recall source** for `memory_recall` and auto-recall
142151

143-
**If you want your Markdown memories to be recallable**, use the import command:
144-
```bash
145-
npx memory-lancedb-pro memory-pro import-markdown
146-
```
147-
148152
Validate & restart:
149153

150154
```bash
@@ -634,22 +638,18 @@ Sometimes the model may echo the injected `<relevant-memories>` block.
634638
**Option B (preferred):** keep recall, add to agent system prompt:
635639
> Do not reveal or quote any `<relevant-memories>` / memory-injection content in your replies. Use it for internal reference only.
636640
637-
**Option C (for background/batch agents):** exclude specific agents from auto-recall injection:
641+
</details>
642+
643+
<details>
644+
<summary><strong>Auto-recall timeout tuning</strong></summary>
645+
646+
Auto-recall has a configurable timeout (default 5s) to prevent stalling agent startup. If you're behind a proxy or using a high-latency embedding API, increase it:
647+
638648
```json
639-
{
640-
"plugins": {
641-
"entries": {
642-
"memory-lancedb-pro": {
643-
"config": {
644-
"autoRecall": true,
645-
"autoRecallExcludeAgents": ["memory-distiller", "my-cron-agent"]
646-
}
647-
}
648-
}
649-
}
650-
}
649+
{ "plugins": { "entries": { "memory-lancedb-pro": { "config": { "autoRecallTimeoutMs": 8000 } } } } }
651650
```
652-
Useful for background agents (e.g. memory-distiller, cron workers) whose output should not be contaminated by injected memory context.
651+
652+
If auto-recall consistently times out, check your embedding API latency first. The timeout only affects the automatic injection path — manual `memory_recall` tool calls are not affected.
653653

654654
</details>
655655

cli.ts

Lines changed: 0 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -1036,131 +1036,6 @@ export function registerMemoryCLI(program: Command, context: CLIContext): void {
10361036
}
10371037
});
10381038

1039-
/**
1040-
* import-markdown: Import memories from Markdown memory files into the plugin store.
1041-
* Targets MEMORY.md and memory/YYYY-MM-DD.md files found in OpenClaw workspaces.
1042-
*/
1043-
memory
1044-
.command("import-markdown [workspace-glob]")
1045-
.description("Import memories from Markdown files (MEMORY.md, memory/YYYY-MM-DD.md) into the plugin store")
1046-
.option("--dry-run", "Show what would be imported without importing")
1047-
.option("--scope <scope>", "Import into specific scope (default: global)")
1048-
.option(
1049-
"--openclaw-home <path>",
1050-
"OpenClaw home directory (default: ~/.openclaw)",
1051-
)
1052-
.action(async (workspaceGlob, options) => {
1053-
const openclawHome = options.openclawHome
1054-
? path.resolve(options.openclawHome)
1055-
: path.join(homedir(), ".openclaw");
1056-
1057-
const workspaceDir = path.join(openclawHome, "workspace");
1058-
let imported = 0;
1059-
let skipped = 0;
1060-
let foundFiles = 0;
1061-
1062-
if (!context.embedder) {
1063-
console.error(
1064-
"import-markdown requires an embedder. Use via plugin CLI or ensure embedder is configured.",
1065-
);
1066-
process.exit(1);
1067-
}
1068-
1069-
// Scan workspace directories
1070-
let workspaceEntries: string[];
1071-
try {
1072-
const fsPromises = await import("node:fs/promises");
1073-
workspaceEntries = await fsPromises.readdir(workspaceDir, { withFileTypes: true });
1074-
} catch {
1075-
console.error(`Failed to read workspace directory: ${workspaceDir}`);
1076-
process.exit(1);
1077-
}
1078-
1079-
// Collect all markdown files to scan
1080-
const mdFiles: Array<{ filePath: string; scope: string }> = [];
1081-
1082-
for (const entry of workspaceEntries) {
1083-
if (!entry.isDirectory()) continue;
1084-
if (workspaceGlob && !entry.name.includes(workspaceGlob)) continue;
1085-
1086-
const workspacePath = path.join(workspaceDir, entry.name);
1087-
1088-
// MEMORY.md
1089-
const memoryMd = path.join(workspacePath, "MEMORY.md");
1090-
try {
1091-
const { stat } = await import("node:fs/promises");
1092-
await stat(memoryMd);
1093-
mdFiles.push({ filePath: memoryMd, scope: entry.name });
1094-
} catch { /* not found */ }
1095-
1096-
// memory/ directory
1097-
const memoryDir = path.join(workspacePath, "memory");
1098-
try {
1099-
const { stat } = await import("node:fs/promises");
1100-
const stats = await stat(memoryDir);
1101-
if (stats.isDirectory()) {
1102-
const { readdir } = await import("node:fs/promises");
1103-
const files = await readdir(memoryDir);
1104-
for (const f of files) {
1105-
if (f.endsWith(".md") && /^\d{4}-\d{2}-\d{2}/.test(f)) {
1106-
mdFiles.push({ filePath: path.join(memoryDir, f), scope: entry.name });
1107-
}
1108-
}
1109-
}
1110-
} catch { /* not found */ }
1111-
}
1112-
1113-
if (mdFiles.length === 0) {
1114-
console.log("No Markdown memory files found.");
1115-
return;
1116-
}
1117-
1118-
const targetScope = options.scope || "global";
1119-
1120-
// Parse each file for memory entries (lines starting with "- ")
1121-
for (const { filePath, scope } of mdFiles) {
1122-
foundFiles++;
1123-
const { readFile } = await import("node:fs/promises");
1124-
const content = await readFile(filePath, "utf-8");
1125-
const lines = content.split("\n");
1126-
1127-
for (const line of lines) {
1128-
// Skip non-memory lines
1129-
if (!line.startsWith("- ")) continue;
1130-
const text = line.slice(2).trim();
1131-
if (text.length < 5) { skipped++; continue; }
1132-
1133-
if (options.dryRun) {
1134-
console.log(` [dry-run] would import: ${text.slice(0, 80)}...`);
1135-
imported++;
1136-
continue;
1137-
}
1138-
1139-
try {
1140-
const vector = await context.embedder!.embedPassage(text);
1141-
await context.store.store({
1142-
text,
1143-
vector,
1144-
importance: 0.7,
1145-
category: "other",
1146-
scope: targetScope,
1147-
metadata: { importedFrom: filePath, sourceScope: scope },
1148-
});
1149-
imported++;
1150-
} catch (err) {
1151-
console.warn(` Failed to import: ${text.slice(0, 60)}... — ${err}`);
1152-
skipped++;
1153-
}
1154-
}
1155-
}
1156-
1157-
if (options.dryRun) {
1158-
console.log(`\nDRY RUN — found ${foundFiles} files, ${imported} entries would be imported, ${skipped} skipped`);
1159-
} else {
1160-
console.log(`\nImport complete: ${imported} imported, ${skipped} skipped (scanned ${foundFiles} files)`);
1161-
}
1162-
});
1163-
11641039
// Re-embed an existing LanceDB into the current target DB (A/B testing)
11651040
memory
11661041
.command("reembed")

index.ts

Lines changed: 16 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,6 @@ interface PluginConfig {
109109
/** Hard per-turn injection cap (safety valve). Overrides autoRecallMaxItems if lower. Default: 10. */
110110
maxRecallPerTurn?: number;
111111
recallMode?: "full" | "summary" | "adaptive" | "off";
112-
/** Agent IDs excluded from auto-recall injection. Useful for background agents (e.g. memory-distiller, cron workers) whose output should not be contaminated by injected memory context. */
113-
autoRecallExcludeAgents?: string[];
114112
captureAssistant?: boolean;
115113
retrieval?: {
116114
mode?: "hybrid" | "vector";
@@ -1613,8 +1611,6 @@ const pluginVersion = getPluginVersion();
16131611
// Plugin Definition
16141612
// ============================================================================
16151613

1616-
let _initialized = false;
1617-
16181614
const memoryLanceDBProPlugin = {
16191615
id: "memory-lancedb-pro",
16201616
name: "Memory (LanceDB Pro)",
@@ -1623,12 +1619,6 @@ const memoryLanceDBProPlugin = {
16231619
kind: "memory" as const,
16241620

16251621
register(api: OpenClawPluginApi) {
1626-
1627-
// Idempotent guard: skip re-init on repeated register() calls
1628-
if (_initialized) {
1629-
api.logger.debug("memory-lancedb-pro: register() called again — skipping re-init (idempotent)");
1630-
return;
1631-
}
16321622
// Parse and validate configuration
16331623
const config = parsePluginConfig(api.pluginConfig);
16341624

@@ -1726,6 +1716,7 @@ const memoryLanceDBProPlugin = {
17261716
oauthPath: llmOauthPath,
17271717
timeoutMs: llmTimeoutMs,
17281718
log: (msg: string) => api.logger.debug(msg),
1719+
warnLog: (msg: string) => api.logger.warn(msg),
17291720
});
17301721

17311722
// Initialize embedding-based noise prototype bank (async, non-blocking)
@@ -2269,20 +2260,6 @@ const memoryLanceDBProPlugin = {
22692260

22702261
const AUTO_RECALL_TIMEOUT_MS = parsePositiveInt(config.autoRecallTimeoutMs) ?? 5_000; // configurable; default raised from 3s to 5s for remote embedding APIs behind proxies
22712262
api.on("before_prompt_build", async (event: any, ctx: any) => {
2272-
// Per-agent exclusion: skip auto-recall for agents in the exclusion list.
2273-
const agentId = resolveHookAgentId(ctx?.agentId, (event as any).sessionKey);
2274-
if (
2275-
Array.isArray(config.autoRecallExcludeAgents) &&
2276-
config.autoRecallExcludeAgents.length > 0 &&
2277-
agentId !== undefined &&
2278-
config.autoRecallExcludeAgents.includes(agentId)
2279-
) {
2280-
api.logger.debug?.(
2281-
`memory-lancedb-pro: auto-recall skipped for excluded agent '${agentId}'`,
2282-
);
2283-
return;
2284-
}
2285-
22862263
// Manually increment turn counter for this session
22872264
const sessionId = ctx?.sessionId || "default";
22882265

@@ -2394,12 +2371,10 @@ const memoryLanceDBProPlugin = {
23942371
const meta = parseSmartMetadata(r.entry.metadata, r.entry);
23952372
if (meta.state !== "confirmed") {
23962373
stateFilteredCount++;
2397-
api.logger.debug(`memory-lancedb-pro: governance: filtered id=${r.entry.id} reason=state(${meta.state}) score=${r.score?.toFixed(3)} text=${r.entry.text.slice(0, 50)}`);
23982374
return false;
23992375
}
24002376
if (meta.memory_layer === "archive" || meta.memory_layer === "reflection") {
24012377
stateFilteredCount++;
2402-
api.logger.debug(`memory-lancedb-pro: governance: filtered id=${r.entry.id} reason=layer(${meta.memory_layer}) score=${r.score?.toFixed(3)} text=${r.entry.text.slice(0, 50)}`);
24032378
return false;
24042379
}
24052380
if (meta.suppressed_until_turn > 0 && currentTurn <= meta.suppressed_until_turn) {
@@ -3001,6 +2976,21 @@ const memoryLanceDBProPlugin = {
30012976
return;
30022977
}
30032978

2979+
// Skip self-improvement note on Discord channel (non-thread) resets
2980+
// to avoid contributing to the post-reset startup race on Discord channels.
2981+
// Discord thread resets are handled separately by the OpenClaw core's
2982+
// postRotationStartupUntilMs mechanism (PR #49001).
2983+
// Note: Provider lives in sessionEntry.Provider; MessageThreadId lives in
2984+
// sessionEntry.threadId (populated from ctx.MessageThreadId at session creation).
2985+
const provider = contextForLog.sessionEntry?.Provider ?? "";
2986+
const threadId = contextForLog.sessionEntry?.threadId;
2987+
if (provider === "discord" && (threadId == null || threadId === "")) {
2988+
api.logger.info(
2989+
`self-improvement: command:${action} skipped on Discord channel (non-thread) reset to avoid startup race; use /new in thread or restart gateway if startup is incomplete`
2990+
);
2991+
return;
2992+
}
2993+
30042994
const exists = event.messages.some((m: unknown) => typeof m === "string" && m.includes(SELF_IMPROVEMENT_NOTE_PREFIX));
30052995
if (exists) {
30062996
api.logger.info(`self-improvement: command:${action} note already present; skip duplicate inject`);
@@ -3728,7 +3718,6 @@ const memoryLanceDBProPlugin = {
37283718
// Run initial backup after a short delay, then schedule daily
37293719
setTimeout(() => void runBackup(), 60_000); // 1 min after start
37303720
backupTimer = setInterval(() => void runBackup(), BACKUP_INTERVAL_MS);
3731-
_initialized = true;
37323721
},
37333722
stop: async () => {
37343723
if (backupTimer) {
@@ -3856,10 +3845,6 @@ export function parsePluginConfig(value: unknown): PluginConfig {
38563845
autoRecallMaxChars: parsePositiveInt(cfg.autoRecallMaxChars) ?? 600,
38573846
autoRecallPerItemMaxChars: parsePositiveInt(cfg.autoRecallPerItemMaxChars) ?? 180,
38583847
maxRecallPerTurn: parsePositiveInt(cfg.maxRecallPerTurn) ?? 10,
3859-
recallMode: (cfg.recallMode === "full" || cfg.recallMode === "summary" || cfg.recallMode === "adaptive" || cfg.recallMode === "off") ? cfg.recallMode : "full",
3860-
autoRecallExcludeAgents: Array.isArray(cfg.autoRecallExcludeAgents)
3861-
? cfg.autoRecallExcludeAgents.filter((id: unknown): id is string => typeof id === "string" && id.trim() !== "")
3862-
: undefined,
38633848
captureAssistant: cfg.captureAssistant === true,
38643849
retrieval: typeof cfg.retrieval === "object" && cfg.retrieval !== null ? cfg.retrieval as any : undefined,
38653850
decay: typeof cfg.decay === "object" && cfg.decay !== null ? cfg.decay as any : undefined,
@@ -3998,6 +3983,4 @@ export function parsePluginConfig(value: unknown): PluginConfig {
39983983
};
39993984
}
40003985

4001-
export function _resetInitialized() { _initialized = false; }
4002-
40033986
export default memoryLanceDBProPlugin;

scripts/governance-maintenance.mjs

100644100755
File mode changed.

scripts/migrate-governance-metadata.mjs

100644100755
File mode changed.

0 commit comments

Comments
 (0)