@christopherlittle51/postclaw 1.3.1 → 1.3.4

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.
Files changed (66) hide show
  1. package/README.md +76 -690
  2. package/dashboard/README.md +89 -0
  3. package/dashboard/public/app.js +1023 -543
  4. package/dashboard/public/index.html +283 -75
  5. package/dashboard/public/styles.css +583 -126
  6. package/dist/dashboard/routes/config.d.ts.map +1 -1
  7. package/dist/dashboard/routes/config.js +17 -1
  8. package/dist/dashboard/routes/config.js.map +1 -1
  9. package/dist/dashboard/routes/graph.d.ts +2 -2
  10. package/dist/dashboard/routes/graph.d.ts.map +1 -1
  11. package/dist/dashboard/routes/graph.js +61 -23
  12. package/dist/dashboard/routes/graph.js.map +1 -1
  13. package/dist/dashboard/routes/memories.d.ts.map +1 -1
  14. package/dist/dashboard/routes/memories.js +97 -11
  15. package/dist/dashboard/routes/memories.js.map +1 -1
  16. package/dist/dashboard/routes/scripts.d.ts.map +1 -1
  17. package/dist/dashboard/routes/scripts.js +3 -1
  18. package/dist/dashboard/routes/scripts.js.map +1 -1
  19. package/dist/dashboard/routes/workspace.d.ts +4 -3
  20. package/dist/dashboard/routes/workspace.d.ts.map +1 -1
  21. package/dist/dashboard/routes/workspace.js +119 -7
  22. package/dist/dashboard/routes/workspace.js.map +1 -1
  23. package/dist/dashboard/server.js +1 -1
  24. package/dist/dashboard/server.js.map +1 -1
  25. package/dist/index.d.ts +1 -1
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js +189 -43
  28. package/dist/index.js.map +1 -1
  29. package/dist/schemas/validation.d.ts +108 -12
  30. package/dist/schemas/validation.d.ts.map +1 -1
  31. package/dist/schemas/validation.js +66 -11
  32. package/dist/schemas/validation.js.map +1 -1
  33. package/dist/scripts/bootstrap_persona.d.ts.map +1 -1
  34. package/dist/scripts/bootstrap_persona.js +3 -3
  35. package/dist/scripts/bootstrap_persona.js.map +1 -1
  36. package/dist/scripts/setup-db.d.ts.map +1 -1
  37. package/dist/scripts/setup-db.js +74 -37
  38. package/dist/scripts/setup-db.js.map +1 -1
  39. package/dist/scripts/sleep_cycle.d.ts +1 -0
  40. package/dist/scripts/sleep_cycle.d.ts.map +1 -1
  41. package/dist/scripts/sleep_cycle.js +209 -38
  42. package/dist/scripts/sleep_cycle.js.map +1 -1
  43. package/dist/services/config.d.ts +1 -0
  44. package/dist/services/config.d.ts.map +1 -1
  45. package/dist/services/config.js +15 -29
  46. package/dist/services/config.js.map +1 -1
  47. package/dist/services/db.d.ts +10 -0
  48. package/dist/services/db.d.ts.map +1 -1
  49. package/dist/services/db.js +38 -1
  50. package/dist/services/db.js.map +1 -1
  51. package/dist/services/llm.d.ts.map +1 -1
  52. package/dist/services/llm.js +3 -1
  53. package/dist/services/llm.js.map +1 -1
  54. package/dist/services/memoryService.d.ts +4 -2
  55. package/dist/services/memoryService.d.ts.map +1 -1
  56. package/dist/services/memoryService.js +127 -43
  57. package/dist/services/memoryService.js.map +1 -1
  58. package/dist/services/personaService.d.ts +25 -0
  59. package/dist/services/personaService.d.ts.map +1 -1
  60. package/dist/services/personaService.js +79 -0
  61. package/dist/services/personaService.js.map +1 -1
  62. package/dist/tests/dashboard-schemas.test.js +71 -1
  63. package/dist/tests/dashboard-schemas.test.js.map +1 -1
  64. package/openclaw.plugin.json +5 -0
  65. package/package.json +2 -1
  66. package/schemas/README.md +64 -0
@@ -2,20 +2,21 @@
2
2
  /**
3
3
  * Dashboard API Routes — Workspace & agent endpoints.
4
4
  *
5
- * GET /api/agents — List agents
6
- * GET /api/workspace-files — List .md files from workspace dir
7
- * GET /api/workspace-files/:filename — Read workspace .md file content
5
+ * GET /api/agents — List agents
6
+ * GET /api/workspace-files — List .md files from workspace dir
7
+ * GET /api/workspace-files/:filename — Read workspace .md file content
8
+ * POST /api/workspace-import — LLM-powered import of .md file as persona or memory
8
9
  */
9
10
  Object.defineProperty(exports, "__esModule", { value: true });
10
11
  exports.registerWorkspaceRoutes = registerWorkspaceRoutes;
11
12
  const helpers_js_1 = require("../helpers.js");
12
13
  const db_js_1 = require("../../services/db.js");
14
+ const memoryService_js_1 = require("../../services/memoryService.js");
15
+ const llm_js_1 = require("../../services/llm.js");
13
16
  const promises_1 = require("node:fs/promises");
14
17
  const node_path_1 = require("node:path");
15
- // =============================================================================
16
- // CONFIG workspace directory (set during startup)
17
- // =============================================================================
18
- // Workspace directory is now stored in the database per agent.
18
+ const zod_1 = require("zod");
19
+ const validation_js_1 = require("../../schemas/validation.js");
19
20
  // =============================================================================
20
21
  // REGISTER ROUTES
21
22
  // =============================================================================
@@ -78,5 +79,116 @@ function registerWorkspaceRoutes(router) {
78
79
  (0, helpers_js_1.sendError)(res, 404, `File not found in workspace`);
79
80
  }
80
81
  });
82
+ // WORKSPACE IMPORT — LLM-powered import of .md file as persona entries or memory chunks
83
+ router.post("/api/workspace-import", async (req, res, ctx) => {
84
+ const agentId = ctx.query.agentId || "main";
85
+ const body = await (0, helpers_js_1.parseBody)(req);
86
+ if (!body)
87
+ return (0, helpers_js_1.sendError)(res, 400, "Invalid JSON body");
88
+ try {
89
+ const data = validation_js_1.WorkspaceImportSchema.parse(body);
90
+ const sql = (0, db_js_1.getSql)();
91
+ // Read the workspace file
92
+ const agents = await sql `SELECT workspace_dir FROM agents WHERE id = ${agentId}`;
93
+ const workspaceDir = agents[0]?.workspace_dir;
94
+ if (!workspaceDir) {
95
+ return (0, helpers_js_1.sendError)(res, 400, "Workspace directory not configured for this agent");
96
+ }
97
+ // Security check
98
+ if (data.filename.includes("..") || data.filename.includes("/")) {
99
+ return (0, helpers_js_1.sendError)(res, 400, "No path traversal allowed");
100
+ }
101
+ const markdownText = await (0, promises_1.readFile)((0, node_path_1.join)(workspaceDir, data.filename), "utf-8");
102
+ await (0, memoryService_js_1.ensureAgent)(agentId);
103
+ if (data.target === "persona") {
104
+ // Use LLM to semantically chunk into persona entries (same as bootstrap_persona.ts)
105
+ const systemPrompt = `You are an expert data architect. Break down this Markdown file into discrete, atomic semantic chunks.
106
+ Extract the core rules, behaviors, and instructions.
107
+
108
+ Output your response EXCLUSIVELY as a raw JSON array of objects. Do not use markdown blocks.
109
+ Each object must have:
110
+ - "category": A short, unique identifier for this rule (max 50 chars, e.g., "communication_style", "discord_rules").
111
+ - "content": The actual text of the rule or instruction.
112
+ - "is_always_active": Boolean. Set to true ONLY for core identity traits that must be injected into every prompt. Set to false if situational.`;
113
+ const combined = `${systemPrompt}\n\nHere is the file to chunk:\n\n${markdownText}`;
114
+ const jsonString = await (0, llm_js_1.callLLMviaAgent)(combined, agentId);
115
+ let chunks;
116
+ try {
117
+ chunks = zod_1.z.array(validation_js_1.PersonaChunkSchema).parse(JSON.parse(jsonString));
118
+ }
119
+ catch {
120
+ return (0, helpers_js_1.sendError)(res, 500, "LLM returned invalid persona chunks");
121
+ }
122
+ let stored = 0;
123
+ for (const chunk of chunks) {
124
+ try {
125
+ const embedding = await (0, db_js_1.getEmbedding)(chunk.content);
126
+ await sql.begin(async (tx) => {
127
+ await tx `SELECT set_config('app.current_agent_id', ${agentId}, true)`;
128
+ await tx `
129
+ INSERT INTO agent_persona (
130
+ agent_id, access_scope, category, content, is_always_active, embedding
131
+ ) VALUES (
132
+ ${agentId}, 'private', ${chunk.category}, ${chunk.content},
133
+ ${chunk.is_always_active}, ${JSON.stringify(embedding)}
134
+ )
135
+ ON CONFLICT (agent_id, category)
136
+ DO UPDATE SET
137
+ content = EXCLUDED.content,
138
+ embedding = EXCLUDED.embedding,
139
+ is_always_active = EXCLUDED.is_always_active
140
+ `;
141
+ });
142
+ stored++;
143
+ }
144
+ catch (err) {
145
+ console.error(`[IMPORT] Failed to store persona "${chunk.category}":`, err);
146
+ }
147
+ }
148
+ (0, helpers_js_1.sendJson)(res, 201, {
149
+ ok: true,
150
+ data: { target: "persona", imported: stored, total: chunks.length, filename: data.filename },
151
+ });
152
+ }
153
+ else {
154
+ // Memory target: use LLM to extract durable facts
155
+ const systemPrompt = `You are a knowledge extraction expert. Extract discrete, atomic facts from this Markdown file.
156
+ Each fact should be a standalone piece of knowledge that is worth remembering.
157
+
158
+ Output your response EXCLUSIVELY as a raw JSON array of strings. Do not use markdown blocks.
159
+ Each string should be a single fact or piece of knowledge.`;
160
+ const combined = `${systemPrompt}\n\nHere is the file:\n\n${markdownText}`;
161
+ const jsonString = await (0, llm_js_1.callLLMviaAgent)(combined, agentId);
162
+ let facts;
163
+ try {
164
+ facts = zod_1.z.array(zod_1.z.string().min(1)).parse(JSON.parse(jsonString));
165
+ }
166
+ catch {
167
+ return (0, helpers_js_1.sendError)(res, 500, "LLM returned invalid memory facts");
168
+ }
169
+ const results = [];
170
+ for (const fact of facts) {
171
+ const result = await (0, memoryService_js_1.storeMemory)(agentId, fact, "private", {
172
+ tier: data.tier,
173
+ source_uri: data.filename,
174
+ category: "imported",
175
+ });
176
+ results.push(result);
177
+ }
178
+ (0, helpers_js_1.sendJson)(res, 201, {
179
+ ok: true,
180
+ data: {
181
+ target: "memory",
182
+ imported: results.filter((r) => r.status === "stored").length,
183
+ total: facts.length,
184
+ filename: data.filename,
185
+ },
186
+ });
187
+ }
188
+ }
189
+ catch (err) {
190
+ (0, helpers_js_1.sendError)(res, 500, err instanceof Error ? err.message : "Import failed");
191
+ }
192
+ });
81
193
  }
82
194
  //# sourceMappingURL=workspace.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"workspace.js","sourceRoot":"","sources":["../../../dashboard/routes/workspace.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"workspace.js","sourceRoot":"","sources":["../../../dashboard/routes/workspace.ts"],"names":[],"mappings":"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"}
@@ -48,7 +48,7 @@ function startDashboard(opts = {}) {
48
48
  // Static files are NOT compiled by tsc — they live in dashboard/public/
49
49
  const projectRoot = (0, node_path_1.join)((0, node_path_1.dirname)(__filename), "..", "..");
50
50
  const publicDir = (0, node_path_1.join)(projectRoot, "dashboard", "public");
51
- const ambientDir = (0, node_path_1.join)(projectRoot, "node_modules", "@ambientcss", "css");
51
+ const ambientDir = (0, node_path_1.join)(projectRoot, "node_modules", "@ambientcss", "css", "dist");
52
52
  _server = (0, node_http_1.createServer)(async (req, res) => {
53
53
  const url = req.url || "/";
54
54
  const pathname = url.split("?")[0];
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../../dashboard/server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../dashboard/server.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { getSql, LM_STUDIO_URL, POSTCLAW_DB_URL, EMBEDDING_MODEL, getEmbedding, hashContent, setEmbeddingConfig, setDbUrl } from "./services/db.js";
1
+ export { getSql, LM_STUDIO_URL, POSTCLAW_DB_URL, EMBEDDING_MODEL, getEmbedding, hashContent, setEmbeddingConfig, setDbUrl, validateEmbeddingDimension } from "./services/db.js";
2
2
  export { ensureAgent, searchPostgres, logEpisodicMemory, logEpisodicToolCall, fetchPersonaContext, storeMemory, updateMemory, linkMemories } from "./services/memoryService.js";
3
3
  export { listPersonas, getPersona, createPersona, updatePersona, deletePersona } from "./services/personaService.js";
4
4
  export type { ChatMessage, ContentPart, ToolCallRecord } from "./schemas/validation.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,eAAe,EAAE,eAAe,EAAE,YAAY,EAAE,WAAW,EAAE,kBAAkB,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACpJ,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,WAAW,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChL,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAoBrH,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAgDxF,QAAA,MAAM,sBAAsB;;;;kBAKZ,GAAG;CA2lBlB,CAAC;AAEF,eAAe,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,eAAe,EAAE,eAAe,EAAE,YAAY,EAAE,WAAW,EAAE,kBAAkB,EAAE,QAAQ,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,CAAC;AAChL,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,WAAW,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChL,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAoBrH,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAgDxF,QAAA,MAAM,sBAAsB;;;;kBAKZ,GAAG;CAovBlB,CAAC;AAEF,eAAe,sBAAsB,CAAC"}
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@
3
3
  // RE-EXPORTS — Single entry point for downstream consumers
4
4
  // =============================================================================
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.deletePersona = exports.updatePersona = exports.createPersona = exports.getPersona = exports.listPersonas = exports.linkMemories = exports.updateMemory = exports.storeMemory = exports.fetchPersonaContext = exports.logEpisodicToolCall = exports.logEpisodicMemory = exports.searchPostgres = exports.ensureAgent = exports.setDbUrl = exports.setEmbeddingConfig = exports.hashContent = exports.getEmbedding = exports.EMBEDDING_MODEL = exports.POSTCLAW_DB_URL = exports.LM_STUDIO_URL = exports.getSql = void 0;
6
+ exports.deletePersona = exports.updatePersona = exports.createPersona = exports.getPersona = exports.listPersonas = exports.linkMemories = exports.updateMemory = exports.storeMemory = exports.fetchPersonaContext = exports.logEpisodicToolCall = exports.logEpisodicMemory = exports.searchPostgres = exports.ensureAgent = exports.validateEmbeddingDimension = exports.setDbUrl = exports.setEmbeddingConfig = exports.hashContent = exports.getEmbedding = exports.EMBEDDING_MODEL = exports.POSTCLAW_DB_URL = exports.LM_STUDIO_URL = exports.getSql = void 0;
7
7
  var db_js_1 = require("./services/db.js");
8
8
  Object.defineProperty(exports, "getSql", { enumerable: true, get: function () { return db_js_1.getSql; } });
9
9
  Object.defineProperty(exports, "LM_STUDIO_URL", { enumerable: true, get: function () { return db_js_1.LM_STUDIO_URL; } });
@@ -13,6 +13,7 @@ Object.defineProperty(exports, "getEmbedding", { enumerable: true, get: function
13
13
  Object.defineProperty(exports, "hashContent", { enumerable: true, get: function () { return db_js_1.hashContent; } });
14
14
  Object.defineProperty(exports, "setEmbeddingConfig", { enumerable: true, get: function () { return db_js_1.setEmbeddingConfig; } });
15
15
  Object.defineProperty(exports, "setDbUrl", { enumerable: true, get: function () { return db_js_1.setDbUrl; } });
16
+ Object.defineProperty(exports, "validateEmbeddingDimension", { enumerable: true, get: function () { return db_js_1.validateEmbeddingDimension; } });
16
17
  var memoryService_js_1 = require("./services/memoryService.js");
17
18
  Object.defineProperty(exports, "ensureAgent", { enumerable: true, get: function () { return memoryService_js_1.ensureAgent; } });
18
19
  Object.defineProperty(exports, "searchPostgres", { enumerable: true, get: function () { return memoryService_js_1.searchPostgres; } });
@@ -82,6 +83,11 @@ const openclawPostgresPlugin = {
82
83
  console.log("[PostClaw] Registering plugin hooks...");
83
84
  // Apply database URL from plugin config (plugins.entries.postclaw.config.dbUrl)
84
85
  const pluginConfig = api.config?.plugins?.entries?.postclaw?.config;
86
+ const debugLogging = pluginConfig?.debugLogging === true;
87
+ const debugLog = (...args) => {
88
+ if (debugLogging)
89
+ console.log("[PostClaw DEBUG]", ...args);
90
+ };
85
91
  if (pluginConfig?.dbUrl) {
86
92
  (0, db_js_3.setDbUrl)(pluginConfig.dbUrl);
87
93
  console.log("[PostClaw] Database URL configured via plugin config");
@@ -96,6 +102,12 @@ const openclawPostgresPlugin = {
96
102
  (0, memoryService_js_2.ensureAgent)(agentId, workspaceDir).then(() => {
97
103
  (0, config_js_1.loadConfig)(agentId).then(() => {
98
104
  console.log("[PostClaw] Configuration loaded successfully");
105
+ // Verify that the configured embedding model dimensions match the schema
106
+ import("./services/db.js").then(({ validateEmbeddingDimension }) => {
107
+ validateEmbeddingDimension(agentId).catch((err) => {
108
+ console.error("[PostClaw] Failed initial embedding validation check:", err);
109
+ });
110
+ });
99
111
  });
100
112
  });
101
113
  // -------------------------------------------------------------------------
@@ -117,6 +129,8 @@ const openclawPostgresPlugin = {
117
129
  // -------------------------------------------------------------------------
118
130
  api.on("before_prompt_build", async (event, ctx) => {
119
131
  try {
132
+ debugLog("before_prompt_build event:", JSON.stringify(event, null, 2));
133
+ debugLog("before_prompt_build ctx:", JSON.stringify(ctx, null, 2));
120
134
  const messages = event.messages ?? [];
121
135
  const userText = lastReceivedMessage || extractUserText(messages);
122
136
  lastReceivedMessage = ""; // consume once — prevent stale leak into heartbeats
@@ -170,7 +184,8 @@ const openclawPostgresPlugin = {
170
184
  hasUserText ? (0, memoryService_js_2.searchPostgres)(agentId, cleanText, {
171
185
  semanticLimit: config.rag.semanticLimit,
172
186
  linkedSimilarity: config.rag.linkedSimilarity,
173
- totalLimit: config.rag.totalLimit
187
+ totalLimit: config.rag.totalLimit,
188
+ trackAs: "injection"
174
189
  }) : Promise.resolve(null),
175
190
  // Persona: always fetch (core rules work without embedding)
176
191
  (0, memoryService_js_2.fetchPersonaContext)(agentId, embedding, {
@@ -215,12 +230,17 @@ const openclawPostgresPlugin = {
215
230
  // --- memory_search: Semantic search across stored memories ---
216
231
  api.registerTool({
217
232
  name: "memory_search",
218
- description: "Search the agent's long-term semantic memory using natural language. Returns the most relevant stored facts and their UUIDs.",
233
+ description: `Search the agent's long-term semantic memory using natural language. Returns the most relevant stored facts with their UUIDs and metadata.
234
+
235
+ Each result includes: id (UUID), content, category, tier (permanent/stable/daily/session/volatile), volatility (low/medium/high), confidence (0.0–1.0), usefulness_score, access_count, injection_count, is_pointer, is_archived, metadata (JSON), created_at, updated_at, and expires_at.
236
+
237
+ Results also include graph-linked memories discovered via multi-hop traversal of the entity_edges knowledge graph. Linked results include persona↔memory cross-links.`,
219
238
  parameters: typebox_1.Type.Object({
220
- query: typebox_1.Type.String({ description: "Natural language search query" }),
239
+ query: typebox_1.Type.String({ description: "Natural language search query. Be specific — this drives vector cosine similarity matching against stored memory embeddings." }),
221
240
  }),
222
241
  async execute(_toolCallId, args, _signal, _onUpdate, ctx) {
223
- const agentId = ctx?.agentId || "main";
242
+ const agentId = toolCallIdToAgentId.get(_toolCallId) || ctx?.agentId || "main";
243
+ debugLog("memory_search mapped agentId:", agentId);
224
244
  await (0, memoryService_js_2.ensureAgent)(agentId, ctx?.workspaceDir);
225
245
  const config = (0, config_js_1.getCurrentConfig)();
226
246
  const result = await (0, memoryService_js_2.searchPostgres)(agentId, args.query, {
@@ -234,17 +254,47 @@ const openclawPostgresPlugin = {
234
254
  // --- memory_store: Save a new durable fact ---
235
255
  api.registerTool({
236
256
  name: "memory_store",
237
- description: "Store a new durable fact. You can categorize it, set volatility, and add metadata.",
257
+ description: `Store a new durable fact in the semantic memory database. Each memory is embedded as a vector for similarity search and can be linked in the knowledge graph.
258
+
259
+ Columns you control:
260
+ - content: The fact text (required). Will be embedded for vector search.
261
+ - category: Short tag for grouping (e.g. 'preference', 'project_detail', 'family_details', 'technical', 'behavioral_rule'). Used for filtering.
262
+ - tier: Permanence level. 'permanent' = never auto-archived. 'stable' = protected from low-value cleanup. 'daily' = standard. 'session' = current session only. 'volatile' = may be cleaned up quickly.
263
+ - volatility: Expected change rate. 'low' = stable facts (names, dates). 'medium' = may change (preferences, statuses). 'high' = frequently changing (moods, temporary states). Affects sleep cycle scoring.
264
+ - metadata: JSON object for additional context (e.g. {"source": "user_stated", "topic": "birthday"}).
265
+ - confidence: Your confidence in the fact (0.0 to 1.0). Default is 0.5.
266
+ - usefulness_score: How useful this fact is for future inference. Default is 0.0.
267
+ - expires_at: For volatile or session-tied facts, the ISO timestamp when it should be archived.
268
+ - scope: The access scope: 'private' (this agent only), 'shared' (accessible by some other agents in the same circle), or 'global' (accessible by all agents on the system).
269
+
270
+ Auto-managed columns (do not set): access_count, injection_count, is_pointer, content_hash, embedding, token_count.`,
238
271
  parameters: typebox_1.Type.Object({
239
- content: typebox_1.Type.String({ description: "The fact or knowledge to store" }),
240
- scope: typebox_1.Type.Optional(typebox_1.Type.Union([typebox_1.Type.Literal("private"), typebox_1.Type.Literal("shared"), typebox_1.Type.Literal("global")], { default: "private" })),
241
- category: typebox_1.Type.Optional(typebox_1.Type.String({ description: "A short categorical tag (e.g., 'preference', 'project_detail')" })),
242
- volatility: typebox_1.Type.Optional(typebox_1.Type.Union([typebox_1.Type.Literal("low"), typebox_1.Type.Literal("medium"), typebox_1.Type.Literal("high")], { default: "low" })),
243
- tier: typebox_1.Type.Optional(typebox_1.Type.Union([typebox_1.Type.Literal("volatile"), typebox_1.Type.Literal("session"), typebox_1.Type.Literal("daily"), typebox_1.Type.Literal("stable"), typebox_1.Type.Literal("permanent")], { default: "daily" })),
244
- metadata: typebox_1.Type.Optional(typebox_1.Type.Any({ description: "A JSON object of additional contextual key-value pairs" }))
272
+ content: typebox_1.Type.String({ description: "The fact or knowledge to store. Should be a clear, self-contained statement." }),
273
+ scope: typebox_1.Type.Optional(typebox_1.Type.Union([typebox_1.Type.Literal("private"), typebox_1.Type.Literal("shared"), typebox_1.Type.Literal("global")], { default: "private", description: "Who can access this memory. Use 'private' for agent-specific data, 'shared' for circle data, or 'global' for facts all agents should know." })),
274
+ category: typebox_1.Type.Optional(typebox_1.Type.String({ description: "Short categorical tag for grouping and filtering (e.g. 'preference', 'project_detail'). Memories without categories are harder to filter." })),
275
+ source_uri: typebox_1.Type.Optional(typebox_1.Type.String({ description: "Optional URL or resource URI to trace the origin of the memory." })),
276
+ volatility: typebox_1.Type.Optional(typebox_1.Type.Union([typebox_1.Type.Literal("low"), typebox_1.Type.Literal("medium"), typebox_1.Type.Literal("high")], { default: "low", description: "Expected change rate for facts: 'low' for stable, 'high' for temporary state." })),
277
+ is_pointer: typebox_1.Type.Optional(typebox_1.Type.Boolean({ description: "Whether this memory is merely a soft pointer to external knowledge. Defaults to false." })),
278
+ embedding_model: typebox_1.Type.Optional(typebox_1.Type.String({ description: "Optional override for the model used to embed this semantic value." })),
279
+ tier: typebox_1.Type.Optional(typebox_1.Type.Union([typebox_1.Type.Literal("volatile"), typebox_1.Type.Literal("session"), typebox_1.Type.Literal("daily"), typebox_1.Type.Literal("stable"), typebox_1.Type.Literal("permanent")], { default: "daily", description: "Permanence level. 'permanent' and 'stable' are protected from automatic archival." })),
280
+ confidence: typebox_1.Type.Optional(typebox_1.Type.Number({ description: "Your confidence in the fact (0.0 to 1.0). Default is 0.5." })),
281
+ usefulness_score: typebox_1.Type.Optional(typebox_1.Type.Number({ description: "Tracker for inference usefulness. Default is 0.0." })),
282
+ injection_count: typebox_1.Type.Optional(typebox_1.Type.Integer({ description: "Override auto-tracked injection count." })),
283
+ access_count: typebox_1.Type.Optional(typebox_1.Type.Integer({ description: "Override auto-tracked access count." })),
284
+ last_injected_at: typebox_1.Type.Optional(typebox_1.Type.String({ description: "Timestamp of last injection (ISO string)." })),
285
+ last_accessed_at: typebox_1.Type.Optional(typebox_1.Type.String({ description: "Timestamp of last access (ISO string)." })),
286
+ expires_at: typebox_1.Type.Optional(typebox_1.Type.String({ description: "Optional expiration timestamp (ISO string) for volatile memories." })),
287
+ created_at: typebox_1.Type.Optional(typebox_1.Type.String({ description: "Timestamp of creation (ISO string)." })),
288
+ updated_at: typebox_1.Type.Optional(typebox_1.Type.String({ description: "Timestamp of last update (ISO string)." })),
289
+ is_archived: typebox_1.Type.Optional(typebox_1.Type.Boolean({ description: "Whether the memory is considered archived/inactive. Defaults to false." })),
290
+ superseded_by: typebox_1.Type.Optional(typebox_1.Type.String({ description: "UUID pointer to a memory replacing this one." })),
291
+ metadata: typebox_1.Type.Optional(typebox_1.Type.Any({ description: "JSON object of additional context (e.g. {source: 'user_stated', topic: 'birthday', related_to: 'family'}). Stored as JSONB for flexible querying." }))
245
292
  }),
246
293
  async execute(_toolCallId, args, _signal, _onUpdate, ctx) {
247
- const agentId = ctx?.agentId || "main";
294
+ debugLog("memory_store args:", JSON.stringify(args, null, 2));
295
+ debugLog("memory_store ctx (from execute params):", JSON.stringify(ctx, null, 2));
296
+ const agentId = toolCallIdToAgentId.get(_toolCallId) || ctx?.agentId || "main";
297
+ debugLog("memory_store mapped agentId:", agentId);
248
298
  await (0, memoryService_js_2.ensureAgent)(agentId, ctx?.workspaceDir);
249
299
  const { content, scope, ...options } = args;
250
300
  const result = await (0, memoryService_js_2.storeMemory)(agentId, content, scope, options);
@@ -254,34 +304,72 @@ const openclawPostgresPlugin = {
254
304
  // --- memory_update: Supersede an old fact with a corrected one ---
255
305
  api.registerTool({
256
306
  name: "memory_update",
257
- description: "Correct or update an existing memory. Archives the old fact and creates a new one with a causal chain link. You can assign categories, volatility, and metadata.",
307
+ description: `Correct or update an existing memory. Archives the old fact (sets is_archived=true, superseded_by=new_id) and creates a fresh memory with the corrected content, preserving the causal chain.
308
+
309
+ The new memory inherits nothing from the old one — you must re-specify category, tier, volatility, metadata, and scope. The old memory remains searchable if you query archived content but won't appear in normal retrieval.
310
+
311
+ Columns you can modify:
312
+ - new_fact: The new corrected fact.
313
+ - scope: The access scope: 'private' (this agent only), 'shared', or 'global' (accessible by all agents).
314
+ - category: Short tag for grouping (e.g. 'preference', 'project_detail').
315
+ - tier: Permanence level. 'permanent' = never auto-archived. 'stable' = protected from low-value cleanup. 'daily' = standard. 'session' = current session. 'volatile' = quickly cleaned.
316
+ - volatility: Expected change rate. 'low' = stable facts, 'medium' = may change, 'high' = expected to change quickly.
317
+ - metadata: JSON object for additional context.
318
+ - confidence: Your confidence in the fact (0.0 to 1.0). Default is 0.5.
319
+ - usefulness_score: How useful this fact is for future inference. Default is 0.0.
320
+ - expires_at: For volatile or session-tied facts, the ISO timestamp when it should be archived.
321
+
322
+ Use this instead of memory_store when you know the UUID of the outdated fact.`,
258
323
  parameters: typebox_1.Type.Object({
259
- old_memory_id: typebox_1.Type.String({ description: "UUID of the outdated memory to supersede" }),
260
- new_fact: typebox_1.Type.String({ description: "The corrected or updated fact" }),
261
- category: typebox_1.Type.Optional(typebox_1.Type.String({ description: "A short categorical tag (e.g., 'preference', 'project_detail')" })),
262
- volatility: typebox_1.Type.Optional(typebox_1.Type.Union([typebox_1.Type.Literal("low"), typebox_1.Type.Literal("medium"), typebox_1.Type.Literal("high")], { default: "low" })),
263
- tier: typebox_1.Type.Optional(typebox_1.Type.Union([typebox_1.Type.Literal("volatile"), typebox_1.Type.Literal("session"), typebox_1.Type.Literal("daily"), typebox_1.Type.Literal("stable"), typebox_1.Type.Literal("permanent")], { default: "daily" })),
264
- metadata: typebox_1.Type.Optional(typebox_1.Type.Any({ description: "A JSON object of additional contextual key-value pairs" }))
324
+ old_memory_id: typebox_1.Type.String({ description: "UUID of the outdated memory to supersede. This memory will be archived and linked via superseded_by." }),
325
+ new_fact: typebox_1.Type.String({ description: "The corrected or updated fact. Will be re-embedded for vector search." }),
326
+ scope: typebox_1.Type.Optional(typebox_1.Type.Union([typebox_1.Type.Literal("private"), typebox_1.Type.Literal("shared"), typebox_1.Type.Literal("global")], { default: "private", description: "Who can access this memory. Use 'private' for agent-specific data, 'shared' for circle data, or 'global' for facts all agents should know." })),
327
+ category: typebox_1.Type.Optional(typebox_1.Type.String({ description: "Category for the new memory (e.g. 'preference', 'project_detail'). Does NOT carry over from old memory." })),
328
+ source_uri: typebox_1.Type.Optional(typebox_1.Type.String({ description: "Optional URL or resource URI to trace the origin of the memory." })),
329
+ volatility: typebox_1.Type.Optional(typebox_1.Type.Union([typebox_1.Type.Literal("low"), typebox_1.Type.Literal("medium"), typebox_1.Type.Literal("high")], { default: "low", description: "Expected change rate for facts: 'low' for stable, 'high' for temporary state." })),
330
+ is_pointer: typebox_1.Type.Optional(typebox_1.Type.Boolean({ description: "Whether this memory is merely a soft pointer to external knowledge. Defaults to false." })),
331
+ embedding_model: typebox_1.Type.Optional(typebox_1.Type.String({ description: "Optional override for the model used to embed this semantic value." })),
332
+ tier: typebox_1.Type.Optional(typebox_1.Type.Union([typebox_1.Type.Literal("volatile"), typebox_1.Type.Literal("session"), typebox_1.Type.Literal("daily"), typebox_1.Type.Literal("stable"), typebox_1.Type.Literal("permanent")], { default: "daily", description: "Permanence level for the new memory. Set to 'permanent' for core facts that should never be auto-archived." })),
333
+ confidence: typebox_1.Type.Optional(typebox_1.Type.Number({ description: "Your confidence in the fact (0.0 to 1.0). Default is 0.5." })),
334
+ usefulness_score: typebox_1.Type.Optional(typebox_1.Type.Number({ description: "Tracker for inference usefulness. Default is 0.0." })),
335
+ injection_count: typebox_1.Type.Optional(typebox_1.Type.Integer({ description: "Override auto-tracked injection count." })),
336
+ access_count: typebox_1.Type.Optional(typebox_1.Type.Integer({ description: "Override auto-tracked access count." })),
337
+ last_injected_at: typebox_1.Type.Optional(typebox_1.Type.String({ description: "Timestamp of last injection (ISO string)." })),
338
+ last_accessed_at: typebox_1.Type.Optional(typebox_1.Type.String({ description: "Timestamp of last access (ISO string)." })),
339
+ expires_at: typebox_1.Type.Optional(typebox_1.Type.String({ description: "Optional expiration timestamp (ISO string) for volatile memories." })),
340
+ created_at: typebox_1.Type.Optional(typebox_1.Type.String({ description: "Timestamp of creation (ISO string)." })),
341
+ updated_at: typebox_1.Type.Optional(typebox_1.Type.String({ description: "Timestamp of last update (ISO string)." })),
342
+ is_archived: typebox_1.Type.Optional(typebox_1.Type.Boolean({ description: "Whether the memory is considered archived/inactive. Defaults to false." })),
343
+ superseded_by: typebox_1.Type.Optional(typebox_1.Type.String({ description: "UUID pointer to a memory replacing this one." })),
344
+ metadata: typebox_1.Type.Optional(typebox_1.Type.Any({ description: "JSON metadata for the new memory. Does NOT carry over from old memory." }))
265
345
  }),
266
346
  async execute(_toolCallId, args, _signal, _onUpdate, ctx) {
267
- const agentId = ctx?.agentId || "main";
347
+ debugLog("memory_update args:", JSON.stringify(args, null, 2));
348
+ const agentId = toolCallIdToAgentId.get(_toolCallId) || ctx?.agentId || "main";
349
+ debugLog("memory_update mapped agentId:", agentId);
268
350
  await (0, memoryService_js_2.ensureAgent)(agentId, ctx?.workspaceDir);
269
- const { old_memory_id, new_fact, ...options } = args;
270
- const result = await (0, memoryService_js_2.updateMemory)(agentId, old_memory_id, new_fact, options);
351
+ const { old_memory_id, new_fact, scope, ...options } = args;
352
+ const result = await (0, memoryService_js_2.updateMemory)(agentId, old_memory_id, new_fact, scope, options);
271
353
  return JSON.stringify(result);
272
354
  },
273
355
  }, { names: ["memory_update"] });
274
356
  // --- memory_link: Create a knowledge graph edge between two memories ---
275
357
  api.registerTool({
276
358
  name: "memory_link",
277
- description: "Create a directed relationship edge between two memories in the knowledge graph.",
359
+ description: `Create a directed relationship edge between two nodes in the knowledge graph (entity_edges table). Links can connect memory↔memory or persona↔memory. Linked memories are discovered during RAG retrieval via multi-hop graph traversal.
360
+
361
+ Relationship types: 'related_to' (general topical), 'elaborates' (B adds detail to A), 'contradicts' (B conflicts with A), 'depends_on' (B needs A), 'part_of' (B is subset of A), 'defines' (A defines context for B, typically persona→memory), 'supports' (B provides evidence for A).
362
+
363
+ The edge weight defaults to 1.0. Edges are also auto-discovered during the sleep cycle, but you should create them immediately when the relationship is obvious.`,
278
364
  parameters: typebox_1.Type.Object({
279
- source_id: typebox_1.Type.String({ description: "UUID of the source memory" }),
280
- target_id: typebox_1.Type.String({ description: "UUID of the target memory" }),
281
- relationship: typebox_1.Type.String({ description: "Relationship type (e.g. related_to, elaborates, contradicts, depends_on, part_of)" }),
365
+ source_id: typebox_1.Type.String({ description: "UUID of the source node (memory or persona trait)" }),
366
+ target_id: typebox_1.Type.String({ description: "UUID of the target node (memory or persona trait)" }),
367
+ relationship: typebox_1.Type.String({ description: "Relationship type: 'related_to', 'elaborates', 'contradicts', 'depends_on', 'part_of', 'defines', or 'supports'" }),
282
368
  }),
283
369
  async execute(_toolCallId, args, _signal, _onUpdate, ctx) {
284
- const agentId = ctx?.agentId || "main";
370
+ debugLog("memory_link args:", JSON.stringify(args, null, 2));
371
+ const agentId = toolCallIdToAgentId.get(_toolCallId) || ctx?.agentId || "main";
372
+ debugLog("memory_link mapped agentId:", agentId);
285
373
  await (0, memoryService_js_2.ensureAgent)(agentId, ctx?.workspaceDir);
286
374
  const result = await (0, memoryService_js_2.linkMemories)(agentId, args.source_id, args.target_id, args.relationship);
287
375
  return JSON.stringify(result);
@@ -290,10 +378,15 @@ const openclawPostgresPlugin = {
290
378
  // --- persona_list: List all persona entries ---
291
379
  api.registerTool({
292
380
  name: "persona_list",
293
- description: "List all persona rules for the current agent.",
381
+ description: `List all persona traits for the current agent from the agent_persona table.
382
+
383
+ Each entry includes: id (UUID), category (unique per agent, e.g. 'core_identity', 'communication_style'), content (the rule text), is_always_active (whether injected into every prompt), embedding (vector for situational matching), and created_at.
384
+
385
+ Persona traits tagged is_always_active=true are always in the system prompt. Others are selected by cosine similarity to the current user message.`,
294
386
  parameters: typebox_1.Type.Object({}),
295
387
  async execute(_toolCallId, _args, _signal, _onUpdate, ctx) {
296
- const agentId = ctx?.agentId || "main";
388
+ const agentId = toolCallIdToAgentId.get(_toolCallId) || ctx?.agentId || "main";
389
+ debugLog("persona_list mapped agentId:", agentId);
297
390
  await (0, memoryService_js_2.ensureAgent)(agentId, ctx?.workspaceDir);
298
391
  const personas = await (0, personaService_js_2.listPersonas)(agentId);
299
392
  return JSON.stringify(personas);
@@ -302,44 +395,83 @@ const openclawPostgresPlugin = {
302
395
  // --- persona_get: Get a specific persona entry ---
303
396
  api.registerTool({
304
397
  name: "persona_get",
305
- description: "Get a specific persona rule by its UUID.",
398
+ description: "Get a specific persona trait by its UUID. Returns the full record: id, category, content, is_always_active, embedding, and created_at.",
306
399
  parameters: typebox_1.Type.Object({
307
400
  persona_id: typebox_1.Type.String({ description: "UUID of the persona entry" }),
308
401
  }),
309
402
  async execute(_toolCallId, args, _signal, _onUpdate, ctx) {
310
- const agentId = ctx?.agentId || "main";
403
+ const agentId = toolCallIdToAgentId.get(_toolCallId) || ctx?.agentId || "main";
404
+ debugLog("persona_get mapped agentId:", agentId);
311
405
  await (0, memoryService_js_2.ensureAgent)(agentId, ctx?.workspaceDir);
312
406
  const persona = await (0, personaService_js_2.getPersona)(agentId, args.persona_id);
313
407
  return persona ? JSON.stringify(persona) : "Persona not found.";
314
408
  },
315
409
  }, { names: ["persona_get"] });
410
+ // --- persona_create: Create a new persona entry ---
411
+ api.registerTool({
412
+ name: "persona_create",
413
+ description: `Create a new persona trait for the current agent.
414
+ **CRITICAL INSTRUCTION**: You must explicitly report the creation of any new persona trait to the user. Do not use this tool unless explicitly instructed or permitted by the user to do so.
415
+
416
+ Each entry requires a category (must be unique per agent, e.g. 'core_identity', 'communication_style') and content (the rule text). is_always_active determines whether it is injected into every system prompt (true) or selected by cosine similarity (false).`,
417
+ parameters: typebox_1.Type.Object({
418
+ category: typebox_1.Type.String({ description: "Category name (must be unique per agent, e.g. 'core_identity', 'communication_style', 'behavioral_rule')" }),
419
+ content: typebox_1.Type.String({ description: "The content text of the persona rule. Will be embedded for situational matching." }),
420
+ is_always_active: typebox_1.Type.Optional(typebox_1.Type.Boolean({ description: "If true, this persona trait is always injected into the system prompt. If false, it is only injected when contextually relevant. Defaults to false." })),
421
+ scope: typebox_1.Type.Optional(typebox_1.Type.Union([typebox_1.Type.Literal("private"), typebox_1.Type.Literal("shared"), typebox_1.Type.Literal("global")], { default: "private", description: "Who can access this persona. 'private' (this agent only) or 'global' (all agents share this trait)." })),
422
+ }),
423
+ async execute(_toolCallId, args, _signal, _onUpdate, ctx) {
424
+ const agentId = toolCallIdToAgentId.get(_toolCallId) || ctx?.agentId || "main";
425
+ debugLog("persona_create mapped agentId:", agentId);
426
+ await (0, memoryService_js_2.ensureAgent)(agentId, ctx?.workspaceDir);
427
+ try {
428
+ const newPersona = await (0, personaService_js_2.createPersona)(agentId, {
429
+ category: args.category,
430
+ content: args.content,
431
+ is_always_active: args.is_always_active ?? false,
432
+ access_scope: args.scope || "private"
433
+ });
434
+ return JSON.stringify(newPersona);
435
+ }
436
+ catch (err) {
437
+ const msg = err instanceof Error ? err.message : String(err);
438
+ return `Error creating persona: ${msg}`;
439
+ }
440
+ },
441
+ }, { names: ["persona_create"] });
316
442
  // --- persona_update: Update a persona entry ---
317
443
  api.registerTool({
318
444
  name: "persona_update",
319
- description: "Update an existing persona rule. You can change the category, content, or whether it is always active.",
445
+ description: `Update an existing persona trait. You can change the category, content, or is_always_active flag.
446
+
447
+ Changing content will re-embed the persona for situational matching. Categories are unique per agent — changing a category effectively reclassifies the trait. Setting is_always_active=true means this persona is injected into every system prompt regardless of relevance.`,
320
448
  parameters: typebox_1.Type.Object({
321
449
  persona_id: typebox_1.Type.String({ description: "UUID of the persona entry to update" }),
322
- category: typebox_1.Type.Optional(typebox_1.Type.String({ description: "New category name" })),
323
- content: typebox_1.Type.Optional(typebox_1.Type.String({ description: "New content text" })),
324
- is_always_active: typebox_1.Type.Optional(typebox_1.Type.Boolean({ description: "Whether this rule is always injected" })),
450
+ category: typebox_1.Type.Optional(typebox_1.Type.String({ description: "New category name (must be unique per agent, e.g. 'core_identity', 'communication_style', 'behavioral_rule')" })),
451
+ content: typebox_1.Type.Optional(typebox_1.Type.String({ description: "New content text. Will be re-embedded for situational matching." })),
452
+ is_always_active: typebox_1.Type.Optional(typebox_1.Type.Boolean({ description: "If true, this persona trait is always injected into the system prompt. If false, it is only injected when contextually relevant." })),
453
+ scope: typebox_1.Type.Optional(typebox_1.Type.Union([typebox_1.Type.Literal("private"), typebox_1.Type.Literal("shared"), typebox_1.Type.Literal("global")], { description: "Update access scope. 'private', 'shared', or 'global'." })),
325
454
  }),
326
455
  async execute(_toolCallId, args, _signal, _onUpdate, ctx) {
327
- const agentId = ctx?.agentId || "main";
456
+ const agentId = toolCallIdToAgentId.get(_toolCallId) || ctx?.agentId || "main";
457
+ debugLog("persona_update mapped agentId:", agentId);
328
458
  await (0, memoryService_js_2.ensureAgent)(agentId, ctx?.workspaceDir);
329
- const { persona_id, ...updates } = args;
330
- const result = await (0, personaService_js_2.updatePersona)(agentId, persona_id, updates);
459
+ const { persona_id, scope, ...updates } = args;
460
+ const payload = scope ? { ...updates, access_scope: scope } : updates;
461
+ const result = await (0, personaService_js_2.updatePersona)(agentId, persona_id, payload);
331
462
  return result ? JSON.stringify(result) : "Persona not found.";
332
463
  },
333
464
  }, { names: ["persona_update"] });
334
465
  // --- persona_delete: Delete a persona entry ---
335
466
  api.registerTool({
336
467
  name: "persona_delete",
337
- description: "Delete a persona rule by its UUID.",
468
+ description: "Delete a persona trait by its UUID. This also removes any persona↔memory edges in the entity_edges knowledge graph that reference this persona.",
338
469
  parameters: typebox_1.Type.Object({
339
- persona_id: typebox_1.Type.String({ description: "UUID of the persona entry to delete" }),
470
+ persona_id: typebox_1.Type.String({ description: "UUID of the persona entry to delete. Cascades to remove associated graph edges." }),
340
471
  }),
341
472
  async execute(_toolCallId, args, _signal, _onUpdate, ctx) {
342
- const agentId = ctx?.agentId || "main";
473
+ const agentId = toolCallIdToAgentId.get(_toolCallId) || ctx?.agentId || "main";
474
+ debugLog("persona_delete mapped agentId:", agentId);
343
475
  await (0, memoryService_js_2.ensureAgent)(agentId, ctx?.workspaceDir);
344
476
  const deleted = await (0, personaService_js_2.deletePersona)(agentId, args.persona_id);
345
477
  return deleted ? '{"status": "deleted"}' : "Persona not found.";
@@ -352,8 +484,19 @@ const openclawPostgresPlugin = {
352
484
  // event = { messages: ChatMessage[], success: boolean, error?: string, durationMs: number }
353
485
  // ctx = { agentId, sessionKey, sessionId, workspaceDir, messageProvider }
354
486
  // -------------------------------------------------------------------------
487
+ const toolCallIdToAgentId = new Map();
488
+ api.on("before_tool_call", async (event, ctx) => {
489
+ debugLog("before_tool_call event:", JSON.stringify(event, null, 2));
490
+ debugLog("before_tool_call ctx:", JSON.stringify(ctx, null, 2));
491
+ const agentId = ctx?.agentId;
492
+ if (agentId && event.toolCallId) {
493
+ toolCallIdToAgentId.set(event.toolCallId, agentId);
494
+ }
495
+ });
355
496
  api.on("agent_end", async (event, ctx) => {
356
497
  try {
498
+ debugLog("agent_end event:", JSON.stringify(event, null, 2));
499
+ debugLog("agent_end ctx:", JSON.stringify(ctx, null, 2));
357
500
  const messages = event.messages ?? [];
358
501
  const agentId = ctx.agentId;
359
502
  const provider = ctx?.messageProvider ?? "";
@@ -375,6 +518,10 @@ const openclawPostgresPlugin = {
375
518
  ? lastUser.content.filter((p) => p.type === "text").map((p) => p.text).join(" ")
376
519
  : ""
377
520
  : "";
521
+ if (userMessage.includes("[POSTCLAW_INTERNAL_LLM_CALL_DO_NOT_LOG]")) {
522
+ console.log("[PostClaw] Skipped episodic logging for internal script call");
523
+ return;
524
+ }
378
525
  const promises = [];
379
526
  // Log user message as episodic event
380
527
  if (userMessage.trim()) {
@@ -556,7 +703,6 @@ const openclawPostgresPlugin = {
556
703
  import("./scripts/sleep_cycle.js").then(({ startService }) => {
557
704
  const config = (0, config_js_1.getCurrentConfig)();
558
705
  startService({
559
- agentId: "main",
560
706
  intervalHours: sleepIntervalHours || 6,
561
707
  config: config.sleep
562
708
  });