Browse Source

Skip auto-recall injection for cron sessions

Lukas Goldschmidt 1 tháng trước cách đây
mục cha
commit
fe0ee142e5
4 tập tin đã thay đổi với 22 bổ sung2 xóa
  1. 6 1
      PROJECT.md
  2. 1 0
      README.md
  3. 1 1
      hook/HOOK.md
  4. 14 0
      hook/handler.ts

+ 6 - 1
PROJECT.md

@@ -31,4 +31,9 @@ Defaults are documented in `README.md`. Keep a sample `~/.openclaw/mem0.json` ne
 - Tag a Git release (e.g., `v1.0.0`).
 - If releasing publicly, include a license (MIT/Apache/…?).
 
-Maintainer: Lukas Goldschmidt / GOLEM assistant (builds, tests, deploys).
+## Operational notes
+- Development happens in `/home/lucky/.openclaw/workspace/mem0-auto-capture-hook` (the Git workspace that holds the docs and project files). Do not edit the installed hook copy directly.
+- The hook that OpenClaw loads at runtime lives in `/home/lucky/.openclaw/workspace/hooks/mem0-auto-capture`; keep it synced via `openclaw hooks install --link /home/lucky/.openclaw/workspace/mem0-auto-capture-hook/hook` whenever the handler changes.
+- There’s no manual compilation step—OpenClaw executes the TypeScript file directly—so reinstalling the hook and restarting the gateway is sufficient after edits (re-running the install command only matters if you need to refresh the symlink).
+
+Maintainer: Lukas Goldschmidt / GOLEM assistant (builds, tests, deploys).

+ 1 - 0
README.md

@@ -11,6 +11,7 @@ A self-contained OpenClaw hook that wires incoming messages to your Mem0 instanc
 2. **Auto-Recall** — before the agent answers (on the `preprocessed` or `transcribed` event) it queries `<baseUrl>/memories/search` (conversational memory only), filters by rerank score, and injects `[MEMORY - Personal]` into `bodyForAgent`. Knowledge base retrieval is now tool-only.
 
 3. **Audio support** — if the event includes media, the hook posts the file to the local STT service at `http://192.168.0.200:5005/transcribe`, caches transcripts, and uses them for both capture and recall. It also rewrites `bodyForAgent` so that audio messages appear as text when the agent eats them.
+4. **Cron sessions** — the hook now detects session keys that begin with `main:main:cron:` and skips the auto-recall injection for those jobs so scheduled tasks stay free of `[MEMORY – Personal]` text. When that happens you’ll see `[mem0] auto-recall-skip-cron {…}` in the logs with a short snippet of the cron’s output.
 
 ## Configuration
 

+ 1 - 1
hook/HOOK.md

@@ -8,7 +8,7 @@ metadata:
 # mem0-auto-capture
 
 - **Capture**: on `message:received`, only stores when the message contains **"please remember"** (case-insensitive). Captures the **last 2 messages** (previous + current).
-- **Recall**: on `message:preprocessed`, injects top mem0 matches into `bodyForAgent`.
+- **Recall**: on `message:preprocessed`, injects top mem0 matches into `bodyForAgent`. Sessions whose `sessionKey` starts with `main:main:cron:` are skipped so cron jobs never receive `[MEMORY …]` text; these skips emit `[mem0] auto-recall-skip-cron` in the logs.
 
 Config flags used:
 - `plugins.entries.openclaw-mem0-python.config.autoCapture`

+ 14 - 0
hook/handler.ts

@@ -134,6 +134,12 @@ function getAgentIdFromSessionKey(sessionKey?: string): string | undefined {
   return undefined;
 }
 
+// Cron jobs are launched with session keys like "main:main:cron:<id>"; they are not
+// human conversations, so don’t inject memories into them.
+function isCronSession(sessionKey?: string): boolean {
+  return typeof sessionKey === "string" && sessionKey.startsWith("main:main:cron:");
+}
+
 function isMediaPlaceholder(text: string): boolean {
   return /<media:[^>]+>/i.test(text);
 }
@@ -551,6 +557,14 @@ export default async function handler(event: HookEvent) {
 
   // ── Auto-recall: queries both endpoints in parallel ───────────────────────
   const runAutoRecall = async (text: string) => {
+    if (isCronSession(event.sessionKey)) {
+      logHook("auto-recall-skip-cron", {
+        sessionKey: event.sessionKey,
+        userId,
+        snippet: text.slice(0, 120),
+      });
+      return;
+    }
     if (!pluginCfg.autoRecall) return;
 
     const { baseUrl, recallLimit, rerankThreshold } = pluginCfg;