@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.
- package/README.md +76 -690
- package/dashboard/README.md +89 -0
- package/dashboard/public/app.js +1023 -543
- package/dashboard/public/index.html +283 -75
- package/dashboard/public/styles.css +583 -126
- package/dist/dashboard/routes/config.d.ts.map +1 -1
- package/dist/dashboard/routes/config.js +17 -1
- package/dist/dashboard/routes/config.js.map +1 -1
- package/dist/dashboard/routes/graph.d.ts +2 -2
- package/dist/dashboard/routes/graph.d.ts.map +1 -1
- package/dist/dashboard/routes/graph.js +61 -23
- package/dist/dashboard/routes/graph.js.map +1 -1
- package/dist/dashboard/routes/memories.d.ts.map +1 -1
- package/dist/dashboard/routes/memories.js +97 -11
- package/dist/dashboard/routes/memories.js.map +1 -1
- package/dist/dashboard/routes/scripts.d.ts.map +1 -1
- package/dist/dashboard/routes/scripts.js +3 -1
- package/dist/dashboard/routes/scripts.js.map +1 -1
- package/dist/dashboard/routes/workspace.d.ts +4 -3
- package/dist/dashboard/routes/workspace.d.ts.map +1 -1
- package/dist/dashboard/routes/workspace.js +119 -7
- package/dist/dashboard/routes/workspace.js.map +1 -1
- package/dist/dashboard/server.js +1 -1
- package/dist/dashboard/server.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +189 -43
- package/dist/index.js.map +1 -1
- package/dist/schemas/validation.d.ts +108 -12
- package/dist/schemas/validation.d.ts.map +1 -1
- package/dist/schemas/validation.js +66 -11
- package/dist/schemas/validation.js.map +1 -1
- package/dist/scripts/bootstrap_persona.d.ts.map +1 -1
- package/dist/scripts/bootstrap_persona.js +3 -3
- package/dist/scripts/bootstrap_persona.js.map +1 -1
- package/dist/scripts/setup-db.d.ts.map +1 -1
- package/dist/scripts/setup-db.js +74 -37
- package/dist/scripts/setup-db.js.map +1 -1
- package/dist/scripts/sleep_cycle.d.ts +1 -0
- package/dist/scripts/sleep_cycle.d.ts.map +1 -1
- package/dist/scripts/sleep_cycle.js +209 -38
- package/dist/scripts/sleep_cycle.js.map +1 -1
- package/dist/services/config.d.ts +1 -0
- package/dist/services/config.d.ts.map +1 -1
- package/dist/services/config.js +15 -29
- package/dist/services/config.js.map +1 -1
- package/dist/services/db.d.ts +10 -0
- package/dist/services/db.d.ts.map +1 -1
- package/dist/services/db.js +38 -1
- package/dist/services/db.js.map +1 -1
- package/dist/services/llm.d.ts.map +1 -1
- package/dist/services/llm.js +3 -1
- package/dist/services/llm.js.map +1 -1
- package/dist/services/memoryService.d.ts +4 -2
- package/dist/services/memoryService.d.ts.map +1 -1
- package/dist/services/memoryService.js +127 -43
- package/dist/services/memoryService.js.map +1 -1
- package/dist/services/personaService.d.ts +25 -0
- package/dist/services/personaService.d.ts.map +1 -1
- package/dist/services/personaService.js +79 -0
- package/dist/services/personaService.js.map +1 -1
- package/dist/tests/dashboard-schemas.test.js +71 -1
- package/dist/tests/dashboard-schemas.test.js.map +1 -1
- package/openclaw.plugin.json +5 -0
- package/package.json +2 -1
- package/schemas/README.md +64 -0
|
@@ -2,20 +2,21 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Dashboard API Routes — Workspace & agent endpoints.
|
|
4
4
|
*
|
|
5
|
-
* GET
|
|
6
|
-
* GET
|
|
7
|
-
* GET
|
|
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
|
-
|
|
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":";AAAA
|
|
1
|
+
{"version":3,"file":"workspace.js","sourceRoot":"","sources":["../../../dashboard/routes/workspace.ts"],"names":[],"mappings":"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"}
|
package/dist/dashboard/server.js
CHANGED
|
@@ -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":";AAAA;;;;;GAKG;;AA+BH,wCAiEC;AAMD,sCAOC;AA3GD,yCAAiD;AACjD,yCAA0C;AAC1C,2CAAqC;AACrC,6CAAsD;AACtD,sDAA6D;AAC7D,sDAA4D;AAC5D,gDAAwD;AACxD,oDAA2D;AAC3D,wDAAgE;AAChE,kDAA0D;AAE1D,gFAAgF;AAChF,eAAe;AACf,gFAAgF;AAEhF,IAAI,OAAO,GAAkB,IAAI,CAAC;AAClC,MAAM,YAAY,GAAG,IAAI,CAAC;AAC1B,MAAM,YAAY,GAAG,WAAW,CAAC;AAYjC,SAAgB,cAAc,CAAC,OAAyB,EAAE;IACxD,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,CAAC,GAAG,CAAC,6CAA6C,CAAC,CAAC;QAC3D,OAAO;IACT,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,YAAY,CAAC;IACvC,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,IAAI,YAAY,CAAC;IAE9C,2CAA2C;IAC3C,IAAI,IAAI,KAAK,WAAW,IAAI,IAAI,KAAK,WAAW,EAAE,CAAC;QACjD,OAAO,CAAC,IAAI,CAAC,uCAAuC,IAAI,wCAAwC,CAAC,CAAC;QAClG,OAAO,CAAC,IAAI,CAAC,gGAAgG,CAAC,CAAC;IACjH,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,kBAAM,EAAE,CAAC;IAC5B,IAAA,mCAAqB,EAAC,MAAM,CAAC,CAAC;IAC9B,IAAA,kCAAoB,EAAC,MAAM,CAAC,CAAC;IAC7B,IAAA,8BAAmB,EAAC,MAAM,CAAC,CAAC;IAC5B,IAAA,iCAAoB,EAAC,MAAM,CAAC,CAAC;IAC7B,IAAA,sCAAuB,EAAC,MAAM,CAAC,CAAC;IAChC,IAAA,gCAAoB,EAAC,MAAM,CAAC,CAAC;IAE7B,kCAAkC;IAClC,4EAA4E;IAC5E,wEAAwE;IACxE,MAAM,WAAW,GAAG,IAAA,gBAAI,EAAC,IAAA,mBAAO,EAAC,UAAU,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IAC1D,MAAM,SAAS,GAAG,IAAA,gBAAI,EAAC,WAAW,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC;IAC3D,MAAM,UAAU,GAAG,IAAA,gBAAI,EAAC,WAAW,EAAE,cAAc,EAAE,aAAa,EAAE,KAAK,CAAC,CAAC;
|
|
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";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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;
|
|
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:
|
|
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:
|
|
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: "
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
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
|
-
|
|
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:
|
|
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
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
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
|
-
|
|
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:
|
|
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
|
|
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
|
-
|
|
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:
|
|
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
|
|
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:
|
|
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: "
|
|
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
|
|
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
|
|
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
|
});
|