@christopherlittle51/postclaw 1.0.0

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 (46) hide show
  1. package/.env.example +4 -0
  2. package/LICENSE +15 -0
  3. package/README.md +731 -0
  4. package/dist/index.d.ts +36 -0
  5. package/dist/index.d.ts.map +1 -0
  6. package/dist/index.js +506 -0
  7. package/dist/index.js.map +1 -0
  8. package/dist/schemas/validation.d.ts +81 -0
  9. package/dist/schemas/validation.d.ts.map +1 -0
  10. package/dist/schemas/validation.js +27 -0
  11. package/dist/schemas/validation.js.map +1 -0
  12. package/dist/scripts/bootstrap_persona.d.ts +20 -0
  13. package/dist/scripts/bootstrap_persona.d.ts.map +1 -0
  14. package/dist/scripts/bootstrap_persona.js +150 -0
  15. package/dist/scripts/bootstrap_persona.js.map +1 -0
  16. package/dist/scripts/bootstrap_tools.d.ts +2 -0
  17. package/dist/scripts/bootstrap_tools.d.ts.map +1 -0
  18. package/dist/scripts/bootstrap_tools.js +67 -0
  19. package/dist/scripts/bootstrap_tools.js.map +1 -0
  20. package/dist/scripts/setup-db.d.ts +28 -0
  21. package/dist/scripts/setup-db.d.ts.map +1 -0
  22. package/dist/scripts/setup-db.js +539 -0
  23. package/dist/scripts/setup-db.js.map +1 -0
  24. package/dist/scripts/sleep_cycle.d.ts +32 -0
  25. package/dist/scripts/sleep_cycle.d.ts.map +1 -0
  26. package/dist/scripts/sleep_cycle.js +452 -0
  27. package/dist/scripts/sleep_cycle.js.map +1 -0
  28. package/dist/services/db.d.ts +28 -0
  29. package/dist/services/db.d.ts.map +1 -0
  30. package/dist/services/db.js +93 -0
  31. package/dist/services/db.js.map +1 -0
  32. package/dist/services/memoryService.d.ts +75 -0
  33. package/dist/services/memoryService.d.ts.map +1 -0
  34. package/dist/services/memoryService.js +391 -0
  35. package/dist/services/memoryService.js.map +1 -0
  36. package/dist/test-db.d.ts +8 -0
  37. package/dist/test-db.d.ts.map +1 -0
  38. package/dist/test-db.js +94 -0
  39. package/dist/test-db.js.map +1 -0
  40. package/dist/test-memory.d.ts +2 -0
  41. package/dist/test-memory.d.ts.map +1 -0
  42. package/dist/test-memory.js +79 -0
  43. package/dist/test-memory.js.map +1 -0
  44. package/openclaw.plugin.json +37 -0
  45. package/package.json +49 -0
  46. package/schemas/db.sql +371 -0
@@ -0,0 +1,539 @@
1
+ "use strict";
2
+ /**
3
+ * PostClaw Database Setup Script
4
+ *
5
+ * Fully automated PostgreSQL database bootstrapping for the PostClaw plugin.
6
+ * Creates the database, user, schema, indices, RLS policies, and grants.
7
+ *
8
+ * Usage (via OpenClaw CLI):
9
+ * openclaw postclaw setup [options]
10
+ *
11
+ * Usage (standalone):
12
+ * node dist/scripts/setup-db.js [options]
13
+ *
14
+ * Options:
15
+ * --admin-url <url> Superuser connection string (default: postgres://localhost/postgres)
16
+ * --db-name <name> Database name (default: memorydb)
17
+ * --db-user <user> App user name (default: openclaw)
18
+ * --db-password <pass> App user password (auto-generated if omitted)
19
+ * --skip-config Don't auto-update openclaw.json with the new dbUrl
20
+ */
21
+ var __importDefault = (this && this.__importDefault) || function (mod) {
22
+ return (mod && mod.__esModule) ? mod : { "default": mod };
23
+ };
24
+ Object.defineProperty(exports, "__esModule", { value: true });
25
+ exports.runSetup = runSetup;
26
+ const postgres_1 = __importDefault(require("postgres"));
27
+ const node_crypto_1 = require("node:crypto");
28
+ const node_fs_1 = require("node:fs");
29
+ const node_path_1 = require("node:path");
30
+ // ─── Helpers ─────────────────────────────────────────────────────────────────
31
+ function generatePassword(length = 16) {
32
+ const chars = "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz23456789!@#$%";
33
+ const bytes = (0, node_crypto_1.randomBytes)(length);
34
+ return Array.from(bytes, (b) => chars[b % chars.length]).join("");
35
+ }
36
+ function log(icon, msg) {
37
+ console.log(` ${icon} ${msg}`);
38
+ }
39
+ // ─── Schema SQL (idempotent) ─────────────────────────────────────────────────
40
+ function buildSchemaSql(appUser, appPassword) {
41
+ // We generate the full idempotent schema inline so passwords can be injected.
42
+ // Each statement is separated by a clear comment block.
43
+ return `
44
+ -- ==========================================================================
45
+ -- PostClaw Schema — Auto-generated by setup-db.ts
46
+ -- ==========================================================================
47
+
48
+ -- 1. Extensions
49
+ CREATE EXTENSION IF NOT EXISTS vector;
50
+ CREATE EXTENSION IF NOT EXISTS pgcrypto;
51
+
52
+ -- 2. Enumerated Types (idempotent via DO block)
53
+ DO $$ BEGIN
54
+ CREATE TYPE access_scope_enum AS ENUM ('private', 'shared', 'global');
55
+ EXCEPTION WHEN duplicate_object THEN NULL;
56
+ END $$;
57
+
58
+ DO $$ BEGIN
59
+ CREATE TYPE memory_tier_enum AS ENUM ('volatile', 'session', 'daily', 'stable', 'permanent');
60
+ EXCEPTION WHEN duplicate_object THEN NULL;
61
+ END $$;
62
+
63
+ DO $$ BEGIN
64
+ CREATE TYPE volatility_enum AS ENUM ('low', 'medium', 'high');
65
+ EXCEPTION WHEN duplicate_object THEN NULL;
66
+ END $$;
67
+
68
+ -- 3. Functions
69
+ CREATE OR REPLACE FUNCTION update_modified_column()
70
+ RETURNS TRIGGER AS $$
71
+ BEGIN
72
+ NEW.updated_at = CURRENT_TIMESTAMP;
73
+ RETURN NEW;
74
+ END;
75
+ $$ LANGUAGE plpgsql;
76
+
77
+ CREATE OR REPLACE FUNCTION enforce_immutable_ownership()
78
+ RETURNS TRIGGER AS $$
79
+ BEGIN
80
+ IF NEW.agent_id <> OLD.agent_id THEN
81
+ RAISE EXCEPTION 'Epistemic violation: Cannot change the original author (agent_id) of a memory.';
82
+ END IF;
83
+ RETURN NEW;
84
+ END;
85
+ $$ LANGUAGE plpgsql;
86
+
87
+ -- 4. Tables
88
+ CREATE TABLE IF NOT EXISTS agents (
89
+ id VARCHAR(100) PRIMARY KEY,
90
+ name VARCHAR(255) NOT NULL,
91
+ default_embedding_model VARCHAR(100) DEFAULT 'nomic-embed-text-v2-moe',
92
+ embedding_dimensions INT DEFAULT 768,
93
+ created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
94
+ is_active BOOLEAN DEFAULT true
95
+ );
96
+
97
+ CREATE TABLE IF NOT EXISTS agent_persona (
98
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
99
+ agent_id VARCHAR(100) NOT NULL REFERENCES agents(id) ON DELETE CASCADE,
100
+ access_scope access_scope_enum DEFAULT 'private',
101
+ category VARCHAR(50) NOT NULL,
102
+ content TEXT NOT NULL,
103
+ is_always_active BOOLEAN DEFAULT false,
104
+ embedding vector,
105
+ created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
106
+ UNIQUE(agent_id, category)
107
+ );
108
+
109
+ CREATE TABLE IF NOT EXISTS context_environment (
110
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
111
+ agent_id VARCHAR(100) NOT NULL REFERENCES agents(id) ON DELETE CASCADE,
112
+ access_scope access_scope_enum DEFAULT 'private',
113
+ tool_name VARCHAR(100) NOT NULL,
114
+ context_data TEXT NOT NULL,
115
+ embedding vector,
116
+ created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
117
+ UNIQUE(agent_id, tool_name)
118
+ );
119
+
120
+ CREATE TABLE IF NOT EXISTS memory_semantic (
121
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
122
+ agent_id VARCHAR(100) NOT NULL REFERENCES agents(id) ON DELETE CASCADE,
123
+ access_scope access_scope_enum DEFAULT 'private',
124
+ content TEXT NOT NULL,
125
+ content_hash VARCHAR(64) NOT NULL,
126
+ category VARCHAR(50),
127
+ source_uri VARCHAR(512),
128
+ volatility volatility_enum DEFAULT 'low',
129
+ is_pointer BOOLEAN DEFAULT false,
130
+ embedding vector,
131
+ embedding_model VARCHAR(100) NOT NULL,
132
+ token_count INT NOT NULL DEFAULT 0,
133
+ fts_vector tsvector GENERATED ALWAYS AS (to_tsvector('simple'::regconfig, content)) STORED,
134
+ confidence REAL DEFAULT 0.5,
135
+ tier memory_tier_enum DEFAULT 'daily',
136
+ usefulness_score REAL DEFAULT 0.0,
137
+ injection_count INT DEFAULT 0,
138
+ access_count INT DEFAULT 0,
139
+ last_injected_at TIMESTAMPTZ,
140
+ last_accessed_at TIMESTAMPTZ,
141
+ created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
142
+ updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
143
+ expires_at TIMESTAMPTZ,
144
+ is_archived BOOLEAN DEFAULT false,
145
+ metadata JSONB DEFAULT '{}'::jsonb,
146
+ superseded_by UUID REFERENCES memory_semantic(id) ON DELETE SET NULL,
147
+ UNIQUE(agent_id, content_hash)
148
+ );
149
+
150
+ CREATE TABLE IF NOT EXISTS memory_episodic (
151
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
152
+ agent_id VARCHAR(100) NOT NULL REFERENCES agents(id) ON DELETE CASCADE,
153
+ session_id VARCHAR(100) NOT NULL,
154
+ event_summary TEXT NOT NULL,
155
+ event_type VARCHAR(50),
156
+ source_uri VARCHAR(512),
157
+ embedding vector,
158
+ embedding_model VARCHAR(100) NOT NULL,
159
+ token_count INT NOT NULL DEFAULT 0,
160
+ fts_vector tsvector GENERATED ALWAYS AS (to_tsvector('simple'::regconfig, event_summary)) STORED,
161
+ usefulness_score REAL DEFAULT 0.0,
162
+ metadata JSONB DEFAULT '{}'::jsonb,
163
+ created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
164
+ is_archived BOOLEAN DEFAULT false
165
+ );
166
+
167
+ CREATE TABLE IF NOT EXISTS conversation_checkpoints (
168
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
169
+ agent_id VARCHAR(100) NOT NULL REFERENCES agents(id) ON DELETE CASCADE,
170
+ session_id VARCHAR(100) NOT NULL,
171
+ summary TEXT NOT NULL,
172
+ active_tasks JSONB,
173
+ token_count INT,
174
+ created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
175
+ );
176
+
177
+ CREATE TABLE IF NOT EXISTS entity_edges (
178
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
179
+ agent_id VARCHAR(100) NOT NULL REFERENCES agents(id) ON DELETE CASCADE,
180
+ source_memory_id UUID REFERENCES memory_semantic(id),
181
+ target_memory_id UUID REFERENCES memory_semantic(id),
182
+ relationship_type VARCHAR(100) NOT NULL,
183
+ weight REAL DEFAULT 1.0,
184
+ created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
185
+ CHECK (source_memory_id != target_memory_id),
186
+ UNIQUE(source_memory_id, target_memory_id, relationship_type)
187
+ );
188
+
189
+ -- 5. Triggers (idempotent: drop + create)
190
+ DROP TRIGGER IF EXISTS update_memory_semantic_modtime ON memory_semantic;
191
+ CREATE TRIGGER update_memory_semantic_modtime
192
+ BEFORE UPDATE ON memory_semantic
193
+ FOR EACH ROW EXECUTE FUNCTION update_modified_column();
194
+
195
+ DROP TRIGGER IF EXISTS trg_immutable_memory_owner ON memory_semantic;
196
+ CREATE TRIGGER trg_immutable_memory_owner
197
+ BEFORE UPDATE ON memory_semantic
198
+ FOR EACH ROW EXECUTE FUNCTION enforce_immutable_ownership();
199
+
200
+ DROP TRIGGER IF EXISTS trg_immutable_persona_owner ON agent_persona;
201
+ CREATE TRIGGER trg_immutable_persona_owner
202
+ BEFORE UPDATE ON agent_persona
203
+ FOR EACH ROW EXECUTE FUNCTION enforce_immutable_ownership();
204
+
205
+ DROP TRIGGER IF EXISTS trg_immutable_context_owner ON context_environment;
206
+ CREATE TRIGGER trg_immutable_context_owner
207
+ BEFORE UPDATE ON context_environment
208
+ FOR EACH ROW EXECUTE FUNCTION enforce_immutable_ownership();
209
+
210
+ -- 6. Indices
211
+ CREATE INDEX IF NOT EXISTS idx_mem_sem_agent_tier ON memory_semantic(agent_id, tier, is_archived);
212
+ CREATE INDEX IF NOT EXISTS idx_mem_sem_hash ON memory_semantic(content_hash);
213
+ CREATE INDEX IF NOT EXISTS idx_mem_epi_session ON memory_episodic(agent_id, session_id, is_archived);
214
+ CREATE INDEX IF NOT EXISTS idx_mem_sem_source_uri ON memory_semantic(source_uri) WHERE source_uri IS NOT NULL;
215
+ CREATE INDEX IF NOT EXISTS idx_mem_sem_metadata ON memory_semantic USING gin (metadata);
216
+ CREATE INDEX IF NOT EXISTS idx_mem_epi_metadata ON memory_episodic USING gin (metadata);
217
+ CREATE INDEX IF NOT EXISTS idx_mem_sem_expires ON memory_semantic(expires_at) WHERE expires_at IS NOT NULL;
218
+ CREATE INDEX IF NOT EXISTS idx_mem_sem_fts ON memory_semantic USING gin (fts_vector);
219
+ CREATE INDEX IF NOT EXISTS idx_mem_epi_fts ON memory_episodic USING gin (fts_vector);
220
+ CREATE INDEX IF NOT EXISTS idx_mem_sem_vector_nomic ON memory_semantic USING hnsw ((embedding::vector(768)) vector_cosine_ops) WHERE embedding_model = 'nomic-embed-text-v2-moe';
221
+ CREATE INDEX IF NOT EXISTS idx_mem_sem_vector_openai ON memory_semantic USING hnsw ((embedding::vector(1536)) vector_cosine_ops) WHERE embedding_model = 'text-embedding-3-small';
222
+ CREATE INDEX IF NOT EXISTS idx_edges_source ON entity_edges(source_memory_id);
223
+ CREATE INDEX IF NOT EXISTS idx_edges_target ON entity_edges(target_memory_id);
224
+ CREATE INDEX IF NOT EXISTS idx_mem_sem_superseded ON memory_semantic(superseded_by) WHERE superseded_by IS NOT NULL;
225
+
226
+ -- 7. Row-Level Security
227
+ ALTER TABLE memory_semantic ENABLE ROW LEVEL SECURITY;
228
+ ALTER TABLE memory_episodic ENABLE ROW LEVEL SECURITY;
229
+ ALTER TABLE agent_persona ENABLE ROW LEVEL SECURITY;
230
+ ALTER TABLE context_environment ENABLE ROW LEVEL SECURITY;
231
+ ALTER TABLE entity_edges ENABLE ROW LEVEL SECURITY;
232
+ ALTER TABLE conversation_checkpoints ENABLE ROW LEVEL SECURITY;
233
+
234
+ -- RLS Policies (idempotent: DROP IF EXISTS + CREATE)
235
+ -- memory_semantic
236
+ DROP POLICY IF EXISTS semantic_read ON memory_semantic;
237
+ CREATE POLICY semantic_read ON memory_semantic FOR SELECT
238
+ USING (agent_id = current_setting('app.current_agent_id', true) OR access_scope IN ('shared', 'global'));
239
+
240
+ DROP POLICY IF EXISTS semantic_insert ON memory_semantic;
241
+ CREATE POLICY semantic_insert ON memory_semantic FOR INSERT
242
+ WITH CHECK (agent_id = current_setting('app.current_agent_id', true));
243
+
244
+ DROP POLICY IF EXISTS semantic_update ON memory_semantic;
245
+ CREATE POLICY semantic_update ON memory_semantic FOR UPDATE
246
+ USING (agent_id = current_setting('app.current_agent_id', true) OR access_scope = 'global')
247
+ WITH CHECK ((agent_id = current_setting('app.current_agent_id', true)) OR (access_scope = 'global'));
248
+
249
+ DROP POLICY IF EXISTS semantic_delete ON memory_semantic;
250
+ CREATE POLICY semantic_delete ON memory_semantic FOR DELETE
251
+ USING (agent_id = current_setting('app.current_agent_id', true));
252
+
253
+ -- agent_persona
254
+ DROP POLICY IF EXISTS persona_read ON agent_persona;
255
+ CREATE POLICY persona_read ON agent_persona FOR SELECT
256
+ USING (agent_id = current_setting('app.current_agent_id', true) OR access_scope IN ('shared', 'global'));
257
+
258
+ DROP POLICY IF EXISTS persona_insert ON agent_persona;
259
+ CREATE POLICY persona_insert ON agent_persona FOR INSERT
260
+ WITH CHECK (agent_id = current_setting('app.current_agent_id', true));
261
+
262
+ DROP POLICY IF EXISTS persona_update ON agent_persona;
263
+ CREATE POLICY persona_update ON agent_persona FOR UPDATE
264
+ USING (agent_id = current_setting('app.current_agent_id', true) OR access_scope = 'global')
265
+ WITH CHECK (agent_id = current_setting('app.current_agent_id', true) OR access_scope = 'global');
266
+
267
+ DROP POLICY IF EXISTS persona_delete ON agent_persona;
268
+ CREATE POLICY persona_delete ON agent_persona FOR DELETE
269
+ USING (agent_id = current_setting('app.current_agent_id', true));
270
+
271
+ -- context_environment
272
+ DROP POLICY IF EXISTS context_read ON context_environment;
273
+ CREATE POLICY context_read ON context_environment FOR SELECT
274
+ USING (agent_id = current_setting('app.current_agent_id', true) OR access_scope IN ('shared', 'global'));
275
+
276
+ DROP POLICY IF EXISTS context_insert ON context_environment;
277
+ CREATE POLICY context_insert ON context_environment FOR INSERT
278
+ WITH CHECK (agent_id = current_setting('app.current_agent_id', true));
279
+
280
+ DROP POLICY IF EXISTS context_update ON context_environment;
281
+ CREATE POLICY context_update ON context_environment FOR UPDATE
282
+ USING (agent_id = current_setting('app.current_agent_id', true) OR access_scope = 'global')
283
+ WITH CHECK (agent_id = current_setting('app.current_agent_id', true) OR access_scope = 'global');
284
+
285
+ DROP POLICY IF EXISTS context_delete ON context_environment;
286
+ CREATE POLICY context_delete ON context_environment FOR DELETE
287
+ USING (agent_id = current_setting('app.current_agent_id', true));
288
+
289
+ -- memory_episodic
290
+ DROP POLICY IF EXISTS episodic_read ON memory_episodic;
291
+ CREATE POLICY episodic_read ON memory_episodic FOR SELECT
292
+ USING (agent_id = current_setting('app.current_agent_id', true));
293
+
294
+ DROP POLICY IF EXISTS episodic_insert ON memory_episodic;
295
+ CREATE POLICY episodic_insert ON memory_episodic FOR INSERT
296
+ WITH CHECK (agent_id = current_setting('app.current_agent_id', true));
297
+
298
+ DROP POLICY IF EXISTS episodic_update ON memory_episodic;
299
+ CREATE POLICY episodic_update ON memory_episodic FOR UPDATE
300
+ USING (agent_id = current_setting('app.current_agent_id', true))
301
+ WITH CHECK (agent_id = current_setting('app.current_agent_id', true));
302
+
303
+ DROP POLICY IF EXISTS episodic_delete ON memory_episodic;
304
+ CREATE POLICY episodic_delete ON memory_episodic FOR DELETE
305
+ USING (agent_id = current_setting('app.current_agent_id', true));
306
+
307
+ -- conversation_checkpoints
308
+ DROP POLICY IF EXISTS checkpoint_read ON conversation_checkpoints;
309
+ CREATE POLICY checkpoint_read ON conversation_checkpoints FOR SELECT
310
+ USING (agent_id = current_setting('app.current_agent_id', true));
311
+
312
+ DROP POLICY IF EXISTS checkpoint_insert ON conversation_checkpoints;
313
+ CREATE POLICY checkpoint_insert ON conversation_checkpoints FOR INSERT
314
+ WITH CHECK (agent_id = current_setting('app.current_agent_id', true));
315
+
316
+ DROP POLICY IF EXISTS checkpoint_update ON conversation_checkpoints;
317
+ CREATE POLICY checkpoint_update ON conversation_checkpoints FOR UPDATE
318
+ USING (agent_id = current_setting('app.current_agent_id', true))
319
+ WITH CHECK (agent_id = current_setting('app.current_agent_id', true));
320
+
321
+ DROP POLICY IF EXISTS checkpoint_delete ON conversation_checkpoints;
322
+ CREATE POLICY checkpoint_delete ON conversation_checkpoints FOR DELETE
323
+ USING (agent_id = current_setting('app.current_agent_id', true));
324
+
325
+ -- entity_edges
326
+ DROP POLICY IF EXISTS edge_read ON entity_edges;
327
+ CREATE POLICY edge_read ON entity_edges FOR SELECT
328
+ USING (
329
+ agent_id = current_setting('app.current_agent_id', true)
330
+ OR EXISTS (
331
+ SELECT 1 FROM memory_semantic ms
332
+ WHERE ms.id IN (source_memory_id, target_memory_id)
333
+ AND ms.access_scope IN ('shared', 'global')
334
+ )
335
+ );
336
+
337
+ DROP POLICY IF EXISTS edge_insert ON entity_edges;
338
+ CREATE POLICY edge_insert ON entity_edges FOR INSERT
339
+ WITH CHECK (agent_id = current_setting('app.current_agent_id', true));
340
+
341
+ DROP POLICY IF EXISTS edge_update ON entity_edges;
342
+ CREATE POLICY edge_update ON entity_edges FOR UPDATE
343
+ USING (agent_id = current_setting('app.current_agent_id', true))
344
+ WITH CHECK (agent_id = current_setting('app.current_agent_id', true));
345
+
346
+ DROP POLICY IF EXISTS edge_delete ON entity_edges;
347
+ CREATE POLICY edge_delete ON entity_edges FOR DELETE
348
+ USING (agent_id = current_setting('app.current_agent_id', true));
349
+
350
+ -- 8. App user grants
351
+ GRANT USAGE ON SCHEMA public TO ${appUser};
352
+ GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO ${appUser};
353
+ GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO ${appUser};
354
+ `;
355
+ }
356
+ async function runSetup(opts = {}) {
357
+ const adminUrl = opts.adminUrl || "postgres://localhost/postgres";
358
+ const dbName = opts.dbName || "memorydb";
359
+ const appUser = opts.dbUser || "openclaw";
360
+ const appPassword = opts.dbPassword || generatePassword();
361
+ const skipConfig = opts.skipConfig || false;
362
+ const adminPassword = generatePassword();
363
+ console.log("\n🦐 PostClaw Database Setup\n");
364
+ // ── Step 1: Connect as superuser ──────────────────────────────────────────
365
+ let adminSql;
366
+ try {
367
+ adminSql = (0, postgres_1.default)(adminUrl, { max: 1 });
368
+ await adminSql `SELECT 1`;
369
+ log("✅", `Connected to Postgres as superuser`);
370
+ }
371
+ catch (err) {
372
+ log("❌", `Cannot connect to ${adminUrl}`);
373
+ log("", `Error: ${err.message}`);
374
+ log("", `Try: openclaw postclaw setup --admin-url postgres://postgres:PASSWORD@localhost/postgres`);
375
+ throw new Error("Superuser connection failed");
376
+ }
377
+ // ── Step 2: Create database ───────────────────────────────────────────────
378
+ try {
379
+ const exists = await adminSql `
380
+ SELECT 1 FROM pg_database WHERE datname = ${dbName}
381
+ `;
382
+ if (exists.length > 0) {
383
+ log("✅", `Database '${dbName}' already exists`);
384
+ }
385
+ else {
386
+ // Can't use parameterized queries for CREATE DATABASE
387
+ await adminSql.unsafe(`CREATE DATABASE ${dbName}`);
388
+ log("✅", `Created database '${dbName}'`);
389
+ }
390
+ }
391
+ catch (err) {
392
+ log("❌", `Failed to create database: ${err.message}`);
393
+ await adminSql.end();
394
+ throw err;
395
+ }
396
+ // ── Step 3: Create app user ───────────────────────────────────────────────
397
+ try {
398
+ const userExists = await adminSql `
399
+ SELECT 1 FROM pg_roles WHERE rolname = ${appUser}
400
+ `;
401
+ if (userExists.length > 0) {
402
+ log("✅", `User '${appUser}' already exists`);
403
+ // Update password to the new one
404
+ await adminSql.unsafe(`ALTER USER ${appUser} WITH PASSWORD '${appPassword.replace(/'/g, "''")}'`);
405
+ }
406
+ else {
407
+ await adminSql.unsafe(`CREATE USER ${appUser} WITH LOGIN PASSWORD '${appPassword.replace(/'/g, "''")}'`);
408
+ log("✅", `Created user '${appUser}'`);
409
+ }
410
+ await adminSql.unsafe(`GRANT CONNECT ON DATABASE ${dbName} TO ${appUser}`);
411
+ }
412
+ catch (err) {
413
+ log("❌", `Failed to create user: ${err.message}`);
414
+ await adminSql.end();
415
+ throw err;
416
+ }
417
+ // ── Step 4: Create system_admin role ──────────────────────────────────────
418
+ try {
419
+ const adminExists = await adminSql `
420
+ SELECT 1 FROM pg_roles WHERE rolname = 'system_admin'
421
+ `;
422
+ if (adminExists.length > 0) {
423
+ log("✅", `Role 'system_admin' already exists`);
424
+ await adminSql.unsafe(`ALTER ROLE system_admin WITH PASSWORD '${adminPassword.replace(/'/g, "''")}'`);
425
+ }
426
+ else {
427
+ await adminSql.unsafe(`CREATE ROLE system_admin WITH LOGIN PASSWORD '${adminPassword.replace(/'/g, "''")}'`);
428
+ log("✅", `Created role 'system_admin'`);
429
+ }
430
+ await adminSql.unsafe(`ALTER ROLE system_admin BYPASSRLS`);
431
+ }
432
+ catch (err) {
433
+ log("⚠️", `system_admin role setup warning: ${err.message}`);
434
+ // Non-fatal — continue without it
435
+ }
436
+ await adminSql.end();
437
+ // ── Step 5: Connect to the target database and run schema ─────────────────
438
+ // Build a connection URL for the target database using the superuser
439
+ const parsedAdmin = new URL(adminUrl);
440
+ const targetUrl = `${parsedAdmin.protocol}//${parsedAdmin.username}${parsedAdmin.password ? ":" + parsedAdmin.password : ""}@${parsedAdmin.host}/${dbName}`;
441
+ let dbSql;
442
+ try {
443
+ dbSql = (0, postgres_1.default)(targetUrl, { max: 1 });
444
+ await dbSql `SELECT 1`;
445
+ log("✅", `Connected to '${dbName}'`);
446
+ }
447
+ catch (err) {
448
+ log("❌", `Cannot connect to database '${dbName}': ${err.message}`);
449
+ throw err;
450
+ }
451
+ try {
452
+ const schemaSql = buildSchemaSql(appUser, appPassword);
453
+ await dbSql.unsafe(schemaSql);
454
+ log("✅", `Schema created (6 tables, 14 indices, 18 RLS policies)`);
455
+ }
456
+ catch (err) {
457
+ log("❌", `Schema creation failed: ${err.message}`);
458
+ await dbSql.end();
459
+ throw err;
460
+ }
461
+ // Grant system_admin full access
462
+ try {
463
+ await dbSql.unsafe(`GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO system_admin`);
464
+ log("✅", `Granted permissions`);
465
+ }
466
+ catch (err) {
467
+ log("⚠️", `system_admin grants warning: ${err.message}`);
468
+ }
469
+ await dbSql.end();
470
+ // ── Step 6: Build connection string ───────────────────────────────────────
471
+ const host = parsedAdmin.hostname || "localhost";
472
+ const port = parsedAdmin.port || "5432";
473
+ const appDbUrl = `postgres://${appUser}:${encodeURIComponent(appPassword)}@${host}:${port}/${dbName}`;
474
+ // ── Step 7: Update openclaw.json ──────────────────────────────────────────
475
+ if (!skipConfig) {
476
+ const configPaths = [
477
+ (0, node_path_1.resolve)(process.env.HOME || "~", ".openclaw", "openclaw.json"),
478
+ ];
479
+ for (const cfgPath of configPaths) {
480
+ if ((0, node_fs_1.existsSync)(cfgPath)) {
481
+ try {
482
+ const raw = (0, node_fs_1.readFileSync)(cfgPath, "utf-8");
483
+ const config = JSON.parse(raw);
484
+ if (!config.plugins)
485
+ config.plugins = {};
486
+ if (!config.plugins.entries)
487
+ config.plugins.entries = {};
488
+ if (!config.plugins.entries.postclaw)
489
+ config.plugins.entries.postclaw = { enabled: true };
490
+ if (!config.plugins.entries.postclaw.config)
491
+ config.plugins.entries.postclaw.config = {};
492
+ config.plugins.entries.postclaw.config.dbUrl = appDbUrl;
493
+ (0, node_fs_1.writeFileSync)(cfgPath, JSON.stringify(config, null, 2) + "\n");
494
+ log("✅", `Updated ${cfgPath} with dbUrl`);
495
+ }
496
+ catch (err) {
497
+ log("⚠️", `Could not update ${cfgPath}: ${err.message}`);
498
+ }
499
+ break;
500
+ }
501
+ }
502
+ }
503
+ // ── Step 8: Print summary ─────────────────────────────────────────────────
504
+ console.log("\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
505
+ console.log(` Database: ${dbName}`);
506
+ console.log(` App User: ${appUser}`);
507
+ console.log(` App Password: ${appPassword}`);
508
+ console.log(` Admin User: system_admin`);
509
+ console.log(` Admin Pass: ${adminPassword}`);
510
+ console.log();
511
+ console.log(` Connection: ${appDbUrl}`);
512
+ if (!skipConfig) {
513
+ console.log();
514
+ console.log(` ✅ openclaw.json updated with dbUrl`);
515
+ }
516
+ console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
517
+ console.log(" Save these credentials! They won't be shown again.\n");
518
+ }
519
+ // ─── Standalone CLI entry point ──────────────────────────────────────────────
520
+ if (require.main === module) {
521
+ const args = process.argv.slice(2);
522
+ function getArg(name) {
523
+ const idx = args.indexOf(name);
524
+ if (idx === -1)
525
+ return undefined;
526
+ return args[idx + 1];
527
+ }
528
+ const opts = {
529
+ adminUrl: getArg("--admin-url"),
530
+ dbName: getArg("--db-name"),
531
+ dbUser: getArg("--db-user"),
532
+ dbPassword: getArg("--db-password"),
533
+ skipConfig: args.includes("--skip-config"),
534
+ };
535
+ runSetup(opts)
536
+ .then(() => process.exit(0))
537
+ .catch(() => process.exit(1));
538
+ }
539
+ //# sourceMappingURL=setup-db.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup-db.js","sourceRoot":"","sources":["../../scripts/setup-db.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * PostClaw Sleep Cycle — Knowledge Graph Maintenance Agent
3
+ *
4
+ * Runs 4 maintenance phases on the memory database:
5
+ * 1. Episodic Consolidation — extract durable facts from short-term memory
6
+ * 2. Duplicate Detection — find and merge near-duplicate semantic memories
7
+ * 3. Low-Value Cleanup — archive stale, unaccessed memories
8
+ * 4. Link Discovery — auto-discover and create knowledge graph edges
9
+ *
10
+ * Usage (via OpenClaw CLI):
11
+ * openclaw postclaw sleep [--agent-id <id>]
12
+ *
13
+ * Also runs as a background service on a configurable interval when the
14
+ * gateway is running (default: every 6 hours).
15
+ */
16
+ export interface SleepCycleOptions {
17
+ agentId?: string;
18
+ llmUrl?: string;
19
+ llmModel?: string;
20
+ }
21
+ export interface SleepCycleStats {
22
+ factsExtracted: number;
23
+ duplicatesMerged: number;
24
+ staleArchived: number;
25
+ linksCreated: number;
26
+ }
27
+ export declare function runSleepCycle(opts?: SleepCycleOptions): Promise<SleepCycleStats>;
28
+ export declare function startService(opts?: SleepCycleOptions & {
29
+ intervalHours?: number;
30
+ }): void;
31
+ export declare function stopService(): void;
32
+ //# sourceMappingURL=sleep_cycle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sleep_cycle.d.ts","sourceRoot":"","sources":["../../scripts/sleep_cycle.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AA6CH,MAAM,WAAW,iBAAiB;IAChC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;CACtB;AAkZD,wBAAsB,aAAa,CAAC,IAAI,GAAE,iBAAsB,GAAG,OAAO,CAAC,eAAe,CAAC,CAqC1F;AAQD,wBAAgB,YAAY,CAAC,IAAI,GAAE,iBAAiB,GAAG;IAAE,aAAa,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,IAAI,CAa5F;AAED,wBAAgB,WAAW,IAAI,IAAI,CAMlC"}