ソースを参照

messages array, chat logger support

Lukas Goldschmidt 1 ヶ月 前
コミット
a8a400249e
4 ファイル変更23 行追加21 行削除
  1. 1 1
      PROJECT.md
  2. 1 1
      README.md
  3. 19 17
      hook/handler.ts
  4. 2 2
      tsconfig.json

+ 1 - 1
PROJECT.md

@@ -5,7 +5,7 @@ Provide a standalone hook that keeps OpenClaw agents in sync with Mem0 by captur
 
 ## Scope
 - Auto-capture incoming messages when triggers fire.
-- Auto-recall both personal memories and a dedicated knowledge-user scope before each response.
+- Auto-recall conversational (personal) memories only before each response; knowledge base is tool-driven.
 - Work with local STT for audio, deduplicate rapid captures, and gracefully degrade when Mem0 is unreachable.
 - If assistant lookup by session key fails, still capture by falling back to the latest assistant turn globally (with warning log).
 - Prefix injected personal memories with human-readable age labels from `created_at` metadata when available.

+ 1 - 1
README.md

@@ -6,7 +6,7 @@ A self-contained OpenClaw hook that wires incoming messages to your Mem0 instanc
 
 1. **Auto-Capture** — whenever a received message matches the configured trigger (default: every message or the phrase “please remember”), the hook gathers the most recent lines from that session (controlled by `recentKeep`) and POSTs them to `<baseUrl>/memories` with the resolved user id. It deduplicates captures by hashing the text and short-circuiting identical payloads within one minute.
 
-2. **Auto-Recall** — before the agent answers (on the `preprocessed` or `transcribed` event) it runs parallel searches against `<baseUrl>/memories/search` and `/knowledge/search`, filters them by rerank score, and appends the results as `[MEMORY - Personal]` and `[MEMORY - Knowledge Base]` sections inside `bodyForAgent` so the LLM has both long-term and knowledge-base context.
+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.
 

+ 19 - 17
hook/handler.ts

@@ -46,7 +46,7 @@ function loadPluginCfg() {
     recentKeep: Number(
       process.env.MEM0_RECENT_KEEP || fileCfg.recentKeep || 5
     ),
-    // Knowledge-base settings
+    // Knowledge-base settings (tool-only; hook no longer injects knowledge)
     knowledgeUserId:
       process.env.MEM0_KNOWLEDGE_USER_ID ||
       (fileCfg.knowledgeUserId as string) ||
@@ -182,7 +182,11 @@ function readLastAssistantMessage(sessionKey?: string): string | undefined {
         ) {
           continue;
         }
-        const assistantText = entry?.messages?.[1]?.content;
+        const candidate = entry?.messages?.[1];
+        if (candidate?.role && candidate.role !== "assistant") {
+          continue;
+        }
+        const assistantText = candidate?.content;
         if (typeof assistantText === "string" && assistantText.trim()) {
           return assistantText.trim();
         }
@@ -196,7 +200,11 @@ function readLastAssistantMessage(sessionKey?: string): string | undefined {
       for (let i = lines.length - 1; i >= 0; i--) {
         try {
           const entry = JSON.parse(lines[i]);
-          const assistantText = entry?.messages?.[1]?.content;
+          const candidate = entry?.messages?.[1];
+          if (candidate?.role && candidate.role !== "assistant") {
+            continue;
+          }
+          const assistantText = candidate?.content;
           if (typeof assistantText === "string" && assistantText.trim()) {
             console.warn(
               "[mem0-auto-capture] assistant lookup fallback to global latest",
@@ -470,32 +478,26 @@ export default async function handler(event: HookEvent) {
   const runAutoRecall = async (text: string) => {
     if (!pluginCfg.autoRecall) return;
 
-    const {
-      baseUrl,
-      knowledgeUserId,
-      recallLimit,
-      knowledgeLimit,
-      rerankThreshold,
-    } = pluginCfg;
+    const { baseUrl, recallLimit, rerankThreshold } = pluginCfg;
 
     console.log("[mem0-auto-recall] query:", text.slice(0, 120));
 
-    // Fire both searches in parallel — neither blocks the other
-    const [personalResults, knowledgeResults] = await Promise.all([
-      mem0SearchMemories(baseUrl, userId, text, recallLimit),
-      mem0SearchKnowledge(baseUrl, knowledgeUserId, text, knowledgeLimit),
-    ]);
+    const personalResults = await mem0SearchMemories(
+      baseUrl,
+      userId,
+      text,
+      recallLimit
+    );
 
     console.log("[mem0-auto-recall]", {
       userId,
       personalCount: personalResults?.length ?? "error",
-      knowledgeCount: knowledgeResults?.length ?? "error",
       threshold: rerankThreshold,
     });
 
     const injectionBlock = buildInjectionBlock(
       personalResults,
-      knowledgeResults,
+      null,
       rerankThreshold
     );
 

+ 2 - 2
tsconfig.json

@@ -9,6 +9,6 @@
     "esModuleInterop": true,
     "skipLibCheck": true
   },
-  "include": ["handler.ts"],
+  "include": ["hook/handler.ts"],
   "exclude": ["node_modules", "dist"]
-}
+}