@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.
- package/.env.example +4 -0
- package/LICENSE +15 -0
- package/README.md +731 -0
- package/dist/index.d.ts +36 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +506 -0
- package/dist/index.js.map +1 -0
- package/dist/schemas/validation.d.ts +81 -0
- package/dist/schemas/validation.d.ts.map +1 -0
- package/dist/schemas/validation.js +27 -0
- package/dist/schemas/validation.js.map +1 -0
- package/dist/scripts/bootstrap_persona.d.ts +20 -0
- package/dist/scripts/bootstrap_persona.d.ts.map +1 -0
- package/dist/scripts/bootstrap_persona.js +150 -0
- package/dist/scripts/bootstrap_persona.js.map +1 -0
- package/dist/scripts/bootstrap_tools.d.ts +2 -0
- package/dist/scripts/bootstrap_tools.d.ts.map +1 -0
- package/dist/scripts/bootstrap_tools.js +67 -0
- package/dist/scripts/bootstrap_tools.js.map +1 -0
- package/dist/scripts/setup-db.d.ts +28 -0
- package/dist/scripts/setup-db.d.ts.map +1 -0
- package/dist/scripts/setup-db.js +539 -0
- package/dist/scripts/setup-db.js.map +1 -0
- package/dist/scripts/sleep_cycle.d.ts +32 -0
- package/dist/scripts/sleep_cycle.d.ts.map +1 -0
- package/dist/scripts/sleep_cycle.js +452 -0
- package/dist/scripts/sleep_cycle.js.map +1 -0
- package/dist/services/db.d.ts +28 -0
- package/dist/services/db.d.ts.map +1 -0
- package/dist/services/db.js +93 -0
- package/dist/services/db.js.map +1 -0
- package/dist/services/memoryService.d.ts +75 -0
- package/dist/services/memoryService.d.ts.map +1 -0
- package/dist/services/memoryService.js +391 -0
- package/dist/services/memoryService.js.map +1 -0
- package/dist/test-db.d.ts +8 -0
- package/dist/test-db.d.ts.map +1 -0
- package/dist/test-db.js +94 -0
- package/dist/test-db.js.map +1 -0
- package/dist/test-memory.d.ts +2 -0
- package/dist/test-memory.d.ts.map +1 -0
- package/dist/test-memory.js +79 -0
- package/dist/test-memory.js.map +1 -0
- package/openclaw.plugin.json +37 -0
- package/package.json +49 -0
- 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"}
|