ahok-skill 1.3.1

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 (141) hide show
  1. package/.prettierrc +8 -0
  2. package/Dockerfile +59 -0
  3. package/RAW_SKILL.md +219 -0
  4. package/README.md +277 -0
  5. package/SKILL.md +58 -0
  6. package/bin/opm.js +268 -0
  7. package/data/openmemory.sqlite +0 -0
  8. package/data/openmemory.sqlite-shm +0 -0
  9. package/data/openmemory.sqlite-wal +0 -0
  10. package/dist/ai/graph.js +293 -0
  11. package/dist/ai/mcp.js +397 -0
  12. package/dist/cli.js +78 -0
  13. package/dist/core/cfg.js +87 -0
  14. package/dist/core/db.js +636 -0
  15. package/dist/core/memory.js +116 -0
  16. package/dist/core/migrate.js +227 -0
  17. package/dist/core/models.js +105 -0
  18. package/dist/core/telemetry.js +57 -0
  19. package/dist/core/types.js +2 -0
  20. package/dist/core/vector/postgres.js +52 -0
  21. package/dist/core/vector/valkey.js +246 -0
  22. package/dist/core/vector_store.js +2 -0
  23. package/dist/index.js +44 -0
  24. package/dist/memory/decay.js +301 -0
  25. package/dist/memory/embed.js +675 -0
  26. package/dist/memory/hsg.js +959 -0
  27. package/dist/memory/reflect.js +131 -0
  28. package/dist/memory/user_summary.js +99 -0
  29. package/dist/migrate.js +9 -0
  30. package/dist/ops/compress.js +255 -0
  31. package/dist/ops/dynamics.js +189 -0
  32. package/dist/ops/extract.js +333 -0
  33. package/dist/ops/ingest.js +214 -0
  34. package/dist/server/index.js +109 -0
  35. package/dist/server/middleware/auth.js +137 -0
  36. package/dist/server/routes/auth.js +186 -0
  37. package/dist/server/routes/compression.js +108 -0
  38. package/dist/server/routes/dashboard.js +399 -0
  39. package/dist/server/routes/docs.js +241 -0
  40. package/dist/server/routes/dynamics.js +312 -0
  41. package/dist/server/routes/ide.js +280 -0
  42. package/dist/server/routes/index.js +33 -0
  43. package/dist/server/routes/keys.js +132 -0
  44. package/dist/server/routes/langgraph.js +61 -0
  45. package/dist/server/routes/memory.js +213 -0
  46. package/dist/server/routes/sources.js +140 -0
  47. package/dist/server/routes/system.js +63 -0
  48. package/dist/server/routes/temporal.js +293 -0
  49. package/dist/server/routes/users.js +101 -0
  50. package/dist/server/routes/vercel.js +57 -0
  51. package/dist/server/server.js +211 -0
  52. package/dist/server.js +3 -0
  53. package/dist/sources/base.js +223 -0
  54. package/dist/sources/github.js +171 -0
  55. package/dist/sources/google_drive.js +166 -0
  56. package/dist/sources/google_sheets.js +112 -0
  57. package/dist/sources/google_slides.js +139 -0
  58. package/dist/sources/index.js +34 -0
  59. package/dist/sources/notion.js +165 -0
  60. package/dist/sources/onedrive.js +143 -0
  61. package/dist/sources/web_crawler.js +166 -0
  62. package/dist/temporal_graph/index.js +20 -0
  63. package/dist/temporal_graph/query.js +240 -0
  64. package/dist/temporal_graph/store.js +116 -0
  65. package/dist/temporal_graph/timeline.js +241 -0
  66. package/dist/temporal_graph/types.js +2 -0
  67. package/dist/utils/chunking.js +60 -0
  68. package/dist/utils/index.js +31 -0
  69. package/dist/utils/keyword.js +94 -0
  70. package/dist/utils/text.js +120 -0
  71. package/nodemon.json +7 -0
  72. package/package.json +50 -0
  73. package/references/api_reference.md +66 -0
  74. package/references/examples.md +45 -0
  75. package/src/ai/graph.ts +363 -0
  76. package/src/ai/mcp.ts +494 -0
  77. package/src/cli.ts +94 -0
  78. package/src/core/cfg.ts +110 -0
  79. package/src/core/db.ts +1052 -0
  80. package/src/core/memory.ts +99 -0
  81. package/src/core/migrate.ts +302 -0
  82. package/src/core/models.ts +107 -0
  83. package/src/core/telemetry.ts +47 -0
  84. package/src/core/types.ts +130 -0
  85. package/src/core/vector/postgres.ts +61 -0
  86. package/src/core/vector/valkey.ts +261 -0
  87. package/src/core/vector_store.ts +9 -0
  88. package/src/index.ts +5 -0
  89. package/src/memory/decay.ts +427 -0
  90. package/src/memory/embed.ts +707 -0
  91. package/src/memory/hsg.ts +1245 -0
  92. package/src/memory/reflect.ts +158 -0
  93. package/src/memory/user_summary.ts +110 -0
  94. package/src/migrate.ts +8 -0
  95. package/src/ops/compress.ts +296 -0
  96. package/src/ops/dynamics.ts +272 -0
  97. package/src/ops/extract.ts +360 -0
  98. package/src/ops/ingest.ts +286 -0
  99. package/src/server/index.ts +159 -0
  100. package/src/server/middleware/auth.ts +156 -0
  101. package/src/server/routes/auth.ts +223 -0
  102. package/src/server/routes/compression.ts +106 -0
  103. package/src/server/routes/dashboard.ts +420 -0
  104. package/src/server/routes/docs.ts +380 -0
  105. package/src/server/routes/dynamics.ts +516 -0
  106. package/src/server/routes/ide.ts +283 -0
  107. package/src/server/routes/index.ts +32 -0
  108. package/src/server/routes/keys.ts +131 -0
  109. package/src/server/routes/langgraph.ts +71 -0
  110. package/src/server/routes/memory.ts +440 -0
  111. package/src/server/routes/sources.ts +111 -0
  112. package/src/server/routes/system.ts +68 -0
  113. package/src/server/routes/temporal.ts +335 -0
  114. package/src/server/routes/users.ts +111 -0
  115. package/src/server/routes/vercel.ts +55 -0
  116. package/src/server/server.js +215 -0
  117. package/src/server.ts +1 -0
  118. package/src/sources/base.ts +257 -0
  119. package/src/sources/github.ts +156 -0
  120. package/src/sources/google_drive.ts +144 -0
  121. package/src/sources/google_sheets.ts +85 -0
  122. package/src/sources/google_slides.ts +115 -0
  123. package/src/sources/index.ts +19 -0
  124. package/src/sources/notion.ts +148 -0
  125. package/src/sources/onedrive.ts +131 -0
  126. package/src/sources/web_crawler.ts +161 -0
  127. package/src/temporal_graph/index.ts +4 -0
  128. package/src/temporal_graph/query.ts +299 -0
  129. package/src/temporal_graph/store.ts +156 -0
  130. package/src/temporal_graph/timeline.ts +319 -0
  131. package/src/temporal_graph/types.ts +41 -0
  132. package/src/utils/chunking.ts +66 -0
  133. package/src/utils/index.ts +25 -0
  134. package/src/utils/keyword.ts +137 -0
  135. package/src/utils/text.ts +115 -0
  136. package/tests/test_api_workspace_management.ts +413 -0
  137. package/tests/test_bulk_delete.ts +267 -0
  138. package/tests/test_omnibus.ts +166 -0
  139. package/tests/test_workspace_management.ts +278 -0
  140. package/tests/verify.ts +104 -0
  141. package/tsconfig.json +15 -0
@@ -0,0 +1,636 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.vector_store = exports.memories_table = exports.run_async = exports.get_async = exports.all_async = exports.transaction = exports.q = exports.log_maint_op = void 0;
7
+ const sqlite3_1 = __importDefault(require("sqlite3"));
8
+ const pg_1 = require("pg");
9
+ const cfg_1 = require("./cfg");
10
+ const node_fs_1 = __importDefault(require("node:fs"));
11
+ const node_path_1 = __importDefault(require("node:path"));
12
+ const postgres_1 = require("./vector/postgres");
13
+ const valkey_1 = require("./vector/valkey");
14
+ let run_async;
15
+ let get_async;
16
+ let all_async;
17
+ let transaction;
18
+ let q;
19
+ let vector_store;
20
+ let memories_table;
21
+ const is_pg = cfg_1.env.metadata_backend === "postgres";
22
+ // Convert SQLite-style ? placeholders to PostgreSQL $1, $2, $3 placeholders
23
+ function convertPlaceholders(sql) {
24
+ if (!is_pg)
25
+ return sql;
26
+ let index = 1;
27
+ return sql.replace(/\?/g, () => `$${index++}`);
28
+ }
29
+ if (is_pg) {
30
+ const ssl = process.env.OM_PG_SSL === "require"
31
+ ? { rejectUnauthorized: false }
32
+ : process.env.OM_PG_SSL === "disable"
33
+ ? false
34
+ : undefined;
35
+ const db_name = process.env.OM_PG_DB || "openmemory";
36
+ const pool = (db) => new pg_1.Pool({
37
+ host: process.env.OM_PG_HOST,
38
+ port: process.env.OM_PG_PORT ? +process.env.OM_PG_PORT : undefined,
39
+ database: db,
40
+ user: process.env.OM_PG_USER,
41
+ password: process.env.OM_PG_PASSWORD,
42
+ ssl,
43
+ });
44
+ let pg = pool(db_name);
45
+ let cli = null;
46
+ const sc = process.env.OM_PG_SCHEMA || "public";
47
+ const m = `"${sc}"."${process.env.OM_PG_TABLE || "openmemory_memories"}"`;
48
+ exports.memories_table = memories_table = m;
49
+ const v = `"${sc}"."${process.env.OM_VECTOR_TABLE || "openmemory_vectors"}"`;
50
+ const w = `"${sc}"."openmemory_waypoints"`;
51
+ const l = `"${sc}"."openmemory_embed_logs"`;
52
+ const f = `"${sc}"."openmemory_memories_fts"`;
53
+ const exec = async (sql, p = []) => {
54
+ const c = cli || pg;
55
+ return (await c.query(convertPlaceholders(sql), p)).rows;
56
+ };
57
+ exports.run_async = run_async = async (sql, p = []) => {
58
+ await exec(sql, p);
59
+ };
60
+ exports.get_async = get_async = async (sql, p = []) => (await exec(sql, p))[0];
61
+ exports.all_async = all_async = async (sql, p = []) => await exec(sql, p);
62
+ exports.transaction = transaction = {
63
+ begin: async () => {
64
+ if (cli)
65
+ throw new Error("transaction active");
66
+ cli = await pg.connect();
67
+ await cli.query("BEGIN");
68
+ },
69
+ commit: async () => {
70
+ if (!cli)
71
+ return;
72
+ try {
73
+ await cli.query("COMMIT");
74
+ }
75
+ finally {
76
+ cli.release();
77
+ cli = null;
78
+ }
79
+ },
80
+ rollback: async () => {
81
+ if (!cli)
82
+ return;
83
+ try {
84
+ await cli.query("ROLLBACK");
85
+ }
86
+ finally {
87
+ cli.release();
88
+ cli = null;
89
+ }
90
+ },
91
+ };
92
+ let ready = false;
93
+ const wait_ready = () => new Promise((ok) => {
94
+ const check = () => (ready ? ok() : setTimeout(check, 10));
95
+ check();
96
+ });
97
+ const init = async () => {
98
+ try {
99
+ await pg.query("SELECT 1");
100
+ }
101
+ catch (err) {
102
+ if (err.code === "3D000") {
103
+ const admin = pool("postgres");
104
+ try {
105
+ await admin.query(`CREATE DATABASE ${db_name}`);
106
+ console.error(`[DB] Created ${db_name}`);
107
+ }
108
+ catch (e) {
109
+ if (e.code !== "42P04")
110
+ throw e;
111
+ }
112
+ finally {
113
+ await admin.end();
114
+ }
115
+ pg = pool(db_name);
116
+ await pg.query("SELECT 1");
117
+ }
118
+ else
119
+ throw err;
120
+ }
121
+ await pg.query(`create table if not exists ${m}(id uuid primary key,user_id text,segment integer default 0,content text not null,simhash text,primary_sector text not null,tags text,meta text,created_at bigint,updated_at bigint,last_seen_at bigint,salience double precision,decay_lambda double precision,version integer default 1,mean_dim integer,mean_vec bytea,compressed_vec bytea,feedback_score double precision default 0, memory_key_id text)`);
122
+ await pg.query(`create table if not exists "${sc}"."api_keys"(id text primary key, user_id text not null, label text, secret_key text unique not null, created_at bigint, updated_at bigint)`);
123
+ // Auto-migration for api_keys table
124
+ await pg.query(`ALTER TABLE "${sc}"."api_keys" ADD COLUMN IF NOT EXISTS updated_at bigint`);
125
+ await pg.query(`create table if not exists ${v}(id uuid,sector text,user_id text,v bytea,dim integer not null,primary key(id,sector))`);
126
+ await pg.query(`create table if not exists ${w}(src_id text,dst_id text not null,user_id text,weight double precision not null,created_at bigint,updated_at bigint,primary key(src_id,user_id))`);
127
+ await pg.query(`create table if not exists ${l}(id text primary key,model text,status text,ts bigint,err text)`);
128
+ await pg.query(`create table if not exists "${sc}"."openmemory_users"(user_id text primary key, clerk_id text unique, api_key text unique, stripe_customer_id text, stripe_subscription_id text, memory_capacity bigint default 1000, memory_usage bigint default 0, summary text, reflection_count integer default 0, created_at bigint, updated_at bigint)`);
129
+ // Auto-migration for existing tables
130
+ const users_table = `"${sc}"."openmemory_users"`;
131
+ await pg.query(`ALTER TABLE ${users_table} ADD COLUMN IF NOT EXISTS clerk_id text unique`);
132
+ await pg.query(`ALTER TABLE ${users_table} ADD COLUMN IF NOT EXISTS api_key text unique`);
133
+ await pg.query(`ALTER TABLE ${users_table} ADD COLUMN IF NOT EXISTS stripe_customer_id text`);
134
+ await pg.query(`ALTER TABLE ${users_table} ADD COLUMN IF NOT EXISTS stripe_subscription_id text`);
135
+ await pg.query(`ALTER TABLE ${users_table} ADD COLUMN IF NOT EXISTS memory_capacity bigint default 1000`);
136
+ await pg.query(`ALTER TABLE ${users_table} ADD COLUMN IF NOT EXISTS memory_usage bigint default 0`);
137
+ await pg.query(`ALTER TABLE ${users_table} ADD COLUMN IF NOT EXISTS summary text`);
138
+ await pg.query(`ALTER TABLE ${users_table} ADD COLUMN IF NOT EXISTS reflection_count integer default 0`);
139
+ await pg.query(`create table if not exists "${sc}"."stats"(id serial primary key,type text not null,count integer default 1,ts bigint not null)`);
140
+ await pg.query(`create index if not exists openmemory_memories_sector_idx on ${m}(primary_sector)`);
141
+ await pg.query(`create index if not exists openmemory_memories_segment_idx on ${m}(segment)`);
142
+ await pg.query(`create index if not exists openmemory_memories_simhash_idx on ${m}(simhash)`);
143
+ await pg.query(`create index if not exists openmemory_memories_user_idx on ${m}(user_id)`);
144
+ await pg.query(`create index if not exists openmemory_vectors_user_idx on ${v}(user_id)`);
145
+ await pg.query(`create index if not exists openmemory_waypoints_user_idx on ${w}(user_id)`);
146
+ await pg.query(`create index if not exists openmemory_stats_ts_idx on "${sc}"."stats"(ts)`);
147
+ await pg.query(`create index if not exists openmemory_stats_type_idx on "${sc}"."stats"(type)`);
148
+ await pg.query(`create index if not exists openmemory_stats_type_idx on "${sc}"."stats"(type)`);
149
+ ready = true;
150
+ // Initialize VectorStore
151
+ if (cfg_1.env.vector_backend === "valkey") {
152
+ exports.vector_store = vector_store = new valkey_1.ValkeyVectorStore();
153
+ console.error("[DB] Using Valkey VectorStore");
154
+ }
155
+ else {
156
+ const vt = process.env.OM_VECTOR_TABLE || "openmemory_vectors";
157
+ exports.vector_store = vector_store = new postgres_1.PostgresVectorStore({ run_async, get_async, all_async }, v.replace(/"/g, ""));
158
+ console.error(`[DB] Using Postgres VectorStore with table: ${v}`);
159
+ }
160
+ };
161
+ init().catch((err) => {
162
+ console.error("[DB] Init failed:", err);
163
+ process.exit(1);
164
+ });
165
+ const safe_exec = async (sql, p = []) => {
166
+ await wait_ready();
167
+ return exec(sql, p);
168
+ };
169
+ exports.run_async = run_async = async (sql, p = []) => {
170
+ await safe_exec(sql, p);
171
+ };
172
+ exports.get_async = get_async = async (sql, p = []) => (await safe_exec(sql, p))[0];
173
+ exports.all_async = all_async = async (sql, p = []) => await safe_exec(sql, p);
174
+ const clean = (s) => s ? s.replace(/"/g, "").replace(/\s+OR\s+/gi, " OR ") : "";
175
+ exports.q = q = {
176
+ ins_mem: {
177
+ run: (...p) => run_async(`insert into ${m}(id,user_id,segment,content,simhash,primary_sector,tags,meta,created_at,updated_at,last_seen_at,salience,decay_lambda,version,mean_dim,mean_vec,compressed_vec,feedback_score,memory_key_id) values($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19) on conflict(id) do update set user_id=excluded.user_id,segment=excluded.segment,content=excluded.content,simhash=excluded.simhash,primary_sector=excluded.primary_sector,tags=excluded.tags,meta=excluded.meta,created_at=excluded.created_at,updated_at=excluded.updated_at,last_seen_at=excluded.last_seen_at,salience=excluded.salience,decay_lambda=excluded.decay_lambda,version=excluded.version,mean_dim=excluded.mean_dim,mean_vec=excluded.mean_vec,compressed_vec=excluded.compressed_vec,feedback_score=excluded.feedback_score,memory_key_id=excluded.memory_key_id`, p),
178
+ },
179
+ upd_mean_vec: {
180
+ run: (...p) => run_async(`update ${m} set mean_dim=$2,mean_vec=$3 where id=$1`, p),
181
+ },
182
+ upd_compressed_vec: {
183
+ run: (...p) => run_async(`update ${m} set compressed_vec=$2 where id=$1`, p),
184
+ },
185
+ upd_feedback: {
186
+ run: (...p) => run_async(`update ${m} set feedback_score=$2 where id=$1`, p),
187
+ },
188
+ upd_seen: {
189
+ run: (...p) => run_async(`update ${m} set last_seen_at=$2,salience=$3,updated_at=$4 where id=$1`, p),
190
+ },
191
+ upd_mem: {
192
+ run: (...p) => run_async(`update ${m} set content=$1,tags=$2,meta=$3,updated_at=$4,version=version+1 where id=$5`, p),
193
+ },
194
+ upd_mem_with_sector: {
195
+ run: (...p) => run_async(`update ${m} set content=$1,primary_sector=$2,tags=$3,meta=$4,updated_at=$5,version=version+1 where id=$6`, p),
196
+ },
197
+ del_mem: {
198
+ run: (...p) => run_async(`delete from ${m} where id=$1`, p),
199
+ },
200
+ get_mem: {
201
+ get: (id) => get_async(`select * from ${m} where id=$1`, [id]),
202
+ },
203
+ get_mem_by_simhash: {
204
+ get: (simhash) => get_async(`select * from ${m} where simhash=$1 order by salience desc limit 1`, [simhash]),
205
+ },
206
+ all_mem: {
207
+ all: (limit, offset) => all_async(`select * from ${m} order by created_at desc limit $1 offset $2`, [limit, offset]),
208
+ },
209
+ all_mem_by_sector: {
210
+ all: (sector, limit, offset) => all_async(`select * from ${m} where primary_sector=$1 order by created_at desc limit $2 offset $3`, [sector, limit, offset]),
211
+ },
212
+ get_segment_count: {
213
+ get: (segment) => get_async(`select count(*) as c from ${m} where segment=$1`, [
214
+ segment,
215
+ ]),
216
+ },
217
+ get_max_segment: {
218
+ get: () => get_async(`select coalesce(max(segment), 0) as max_seg from ${m}`, []),
219
+ },
220
+ get_segments: {
221
+ all: () => all_async(`select distinct segment from ${m} order by segment desc`, []),
222
+ },
223
+ get_mem_by_segment: {
224
+ all: (segment) => all_async(`select * from ${m} where segment=$1 order by created_at desc`, [segment]),
225
+ },
226
+ // Vector operations removed
227
+ ins_waypoint: {
228
+ run: (...p) => run_async(`insert into ${w}(src_id,dst_id,user_id,weight,created_at,updated_at) values($1,$2,$3,$4,$5,$6) on conflict(src_id,user_id) do update set dst_id=excluded.dst_id,weight=excluded.weight,updated_at=excluded.updated_at`, p),
229
+ },
230
+ get_neighbors: {
231
+ all: (src) => all_async(`select dst_id,weight from ${w} where src_id=$1 order by weight desc`, [src]),
232
+ },
233
+ get_waypoints_by_src: {
234
+ all: (src) => all_async(`select src_id,dst_id,weight,created_at,updated_at from ${w} where src_id=$1`, [src]),
235
+ },
236
+ get_waypoint: {
237
+ get: (src, dst) => get_async(`select weight from ${w} where src_id=$1 and dst_id=$2`, [src, dst]),
238
+ },
239
+ upd_waypoint: {
240
+ run: (...p) => run_async(`update ${w} set weight=$2,updated_at=$3 where src_id=$1 and dst_id=$4`, p),
241
+ },
242
+ del_waypoints: {
243
+ run: (...p) => run_async(`delete from ${w} where src_id=$1 or dst_id=$2`, p),
244
+ },
245
+ prune_waypoints: {
246
+ run: (t) => run_async(`delete from ${w} where weight<$1`, [t]),
247
+ },
248
+ ins_log: {
249
+ run: (...p) => run_async(`insert into ${l}(id,model,status,ts,err) values($1,$2,$3,$4,$5) on conflict(id) do update set model=excluded.model,status=excluded.status,ts=excluded.ts,err=excluded.err`, p),
250
+ },
251
+ upd_log: {
252
+ run: (...p) => run_async(`update ${l} set status=$2,err=$3 where id=$1`, p),
253
+ },
254
+ get_pending_logs: {
255
+ all: () => all_async(`select * from ${l} where status=$1`, ["pending"]),
256
+ },
257
+ get_failed_logs: {
258
+ all: () => all_async(`select * from ${l} where status=$1 order by ts desc limit 100`, ["failed"]),
259
+ },
260
+ all_mem_by_user: {
261
+ all: (user_id, limit, offset) => all_async(`select * from ${m} where user_id=$1 order by created_at desc limit $2 offset $3`, [user_id, limit, offset]),
262
+ },
263
+ ins_user: {
264
+ run: (...p) => run_async(`insert into "${sc}"."openmemory_users"(user_id, clerk_id, api_key, stripe_customer_id, stripe_subscription_id, memory_capacity, memory_usage, summary, reflection_count, created_at, updated_at) values($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11) on conflict(user_id) do update set clerk_id=excluded.clerk_id, api_key=excluded.api_key, stripe_customer_id=excluded.stripe_customer_id, stripe_subscription_id=excluded.stripe_subscription_id, memory_capacity=excluded.memory_capacity, memory_usage=excluded.memory_usage, summary=excluded.summary, reflection_count=excluded.reflection_count, updated_at=excluded.updated_at`, p),
265
+ },
266
+ get_user: {
267
+ get: (user_id) => get_async(`select * from "${sc}"."openmemory_users" where user_id=$1`, [user_id]),
268
+ },
269
+ get_user_by_api_key: {
270
+ get: (api_key) => get_async(`select * from "${sc}"."openmemory_users" where api_key=$1`, [api_key]),
271
+ },
272
+ get_user_by_memory_key: {
273
+ get: (key) => get_async(`select u.*, k.id as key_id, k.label as key_label from "${sc}"."api_keys" k join "${sc}"."openmemory_users" u on k.user_id = u.user_id where k.secret_key=$1`, [key]),
274
+ },
275
+ ins_memory_key: {
276
+ run: (...p) => run_async(`insert into "${sc}"."api_keys"(id, user_id, label, secret_key, created_at) values($1,$2,$3,$4,$5)`, p),
277
+ },
278
+ del_memory_key: {
279
+ run: (...p) => run_async(`delete from "${sc}"."api_keys" where id=$1 and user_id=$2`, p),
280
+ },
281
+ get_memory_keys_by_user: {
282
+ all: (user_id) => all_async(`select * from "${sc}"."api_keys" where user_id=$1 order by created_at desc`, [user_id]),
283
+ },
284
+ upd_memory_key_label: {
285
+ run: (label, updated_at, id, user_id) => run_async(`update "${sc}"."api_keys" set label=$1, updated_at=$2 where id=$3 and user_id=$4`, [label, updated_at, id, user_id]),
286
+ },
287
+ get_memory_counts_by_key: {
288
+ all: (user_id) => all_async(`select memory_key_id, count(*)::integer as count from ${m} where user_id=$1 group by memory_key_id`, [user_id]),
289
+ },
290
+ bulk_del_mem: {
291
+ run: async (ids, user_id) => {
292
+ if (ids.length === 0)
293
+ return;
294
+ const placeholders = ids.map((_, i) => `$${i + 1}`).join(',');
295
+ await run_async(`delete from ${m} where id in (${placeholders}) and user_id=$${ids.length + 1}`, [...ids, user_id]);
296
+ },
297
+ },
298
+ bulk_upd_mem_key: {
299
+ run: async (memory_key_id, updated_at, ids, user_id) => {
300
+ if (ids.length === 0)
301
+ return;
302
+ // Parameters: memory_key_id=$1, updated_at=$2, ids=$3..$N+2, user_id=$N+3
303
+ const idPlaceholders = ids.map((_, i) => `$${i + 3}`).join(',');
304
+ const userIdPlaceholder = `$${ids.length + 3}`;
305
+ await run_async(`update ${m} set memory_key_id=$1, updated_at=$2 where id in (${idPlaceholders}) and user_id=${userIdPlaceholder}`, [memory_key_id, updated_at, ...ids, user_id]);
306
+ },
307
+ },
308
+ get_user_by_clerk_id: {
309
+ get: (clerk_id) => get_async(`select * from "${sc}"."openmemory_users" where clerk_id=$1`, [clerk_id]),
310
+ },
311
+ get_user_by_stripe_customer_id: {
312
+ get: (customer_id) => get_async(`select * from "${sc}"."openmemory_users" where stripe_customer_id=$1`, [customer_id]),
313
+ },
314
+ upd_user_summary: {
315
+ run: (...p) => run_async(`update "${sc}"."openmemory_users" set summary=$2,reflection_count=reflection_count+1,updated_at=$3 where user_id=$1`, p),
316
+ },
317
+ upd_user_billing: {
318
+ run: (...p) => run_async(`update "${sc}"."openmemory_users" set stripe_customer_id=$2, stripe_subscription_id=$3, memory_capacity=$4, updated_at=$5 where user_id=$1`, p),
319
+ },
320
+ inc_user_usage: {
321
+ run: (user_id, delta) => run_async(`update "${sc}"."openmemory_users" set memory_usage=memory_usage+$2, updated_at=$3 where user_id=$1`, [user_id, delta, Date.now()]),
322
+ },
323
+ clear_all: {
324
+ run: async () => {
325
+ await run_async(`delete from ${m}`);
326
+ await run_async(`delete from ${v}`);
327
+ await run_async(`delete from ${w}`);
328
+ await run_async(`delete from "${sc}"."openmemory_users"`);
329
+ },
330
+ },
331
+ };
332
+ }
333
+ else {
334
+ const db_path = cfg_1.env.db_path ||
335
+ node_path_1.default.resolve(__dirname, "../../data/openmemory.sqlite");
336
+ const dir = node_path_1.default.dirname(db_path);
337
+ if (!node_fs_1.default.existsSync(dir))
338
+ node_fs_1.default.mkdirSync(dir, { recursive: true });
339
+ const db = new sqlite3_1.default.Database(db_path);
340
+ // SQLite vector table name from env (default: "vectors" for backward compatibility)
341
+ const sqlite_vector_table = process.env.OM_VECTOR_TABLE || "vectors";
342
+ db.serialize(() => {
343
+ db.run("PRAGMA journal_mode=WAL");
344
+ db.run("PRAGMA synchronous=NORMAL");
345
+ db.run("PRAGMA temp_store=MEMORY");
346
+ db.run("PRAGMA cache_size=-8000");
347
+ db.run("PRAGMA mmap_size=134217728");
348
+ db.run("PRAGMA foreign_keys=OFF");
349
+ db.run("PRAGMA wal_autocheckpoint=20000");
350
+ db.run("PRAGMA locking_mode=NORMAL"); // Changed from EXCLUSIVE to allow MCP access
351
+ db.run("PRAGMA busy_timeout=5000"); // Increased timeout to handle concurrent access
352
+ db.run(`create table if not exists memories(id text primary key,user_id text,segment integer default 0,content text not null,simhash text,primary_sector text not null,tags text,meta text,created_at integer,updated_at integer,last_seen_at integer,salience real,decay_lambda real,version integer default 1,mean_dim integer,mean_vec blob,compressed_vec blob,feedback_score real default 0)`);
353
+ db.run(`create table if not exists ${sqlite_vector_table}(id text not null,sector text not null,user_id text,v blob not null,dim integer not null,primary key(id,sector))`);
354
+ db.run(`create table if not exists waypoints(src_id text,dst_id text not null,user_id text,weight real not null,created_at integer,updated_at integer,primary key(src_id,user_id))`);
355
+ db.run(`create table if not exists embed_logs(id text primary key,model text,status text,ts integer,err text)`);
356
+ db.run(`create table if not exists users(user_id text primary key, clerk_id text unique, api_key text unique, stripe_customer_id text, stripe_subscription_id text, memory_capacity integer default 1000, memory_usage integer default 0, summary text, reflection_count integer default 0, created_at integer, updated_at integer)`);
357
+ db.run(`create table if not exists api_keys(id text primary key, user_id text not null, label text, secret_key text unique not null, created_at integer, updated_at integer)`);
358
+ db.run(`create table if not exists stats(id integer primary key autoincrement,type text not null,count integer default 1,ts integer not null)`);
359
+ db.run(`create table if not exists temporal_facts(id text primary key,subject text not null,predicate text not null,object text not null,valid_from integer not null,valid_to integer,confidence real not null check(confidence >= 0 and confidence <= 1),last_updated integer not null,metadata text,unique(subject,predicate,object,valid_from))`);
360
+ db.run(`create table if not exists temporal_edges(id text primary key,source_id text not null,target_id text not null,relation_type text not null,valid_from integer not null,valid_to integer,weight real not null,metadata text,foreign key(source_id) references temporal_facts(id),foreign key(target_id) references temporal_facts(id))`);
361
+ db.run("create index if not exists idx_memories_sector on memories(primary_sector)");
362
+ db.run("create index if not exists idx_memories_segment on memories(segment)");
363
+ db.run("create index if not exists idx_memories_simhash on memories(simhash)");
364
+ db.run("create index if not exists idx_memories_ts on memories(last_seen_at)");
365
+ db.run("create index if not exists idx_memories_user on memories(user_id)");
366
+ db.run(`create index if not exists idx_vectors_user on ${sqlite_vector_table}(user_id)`);
367
+ db.run("create index if not exists idx_waypoints_src on waypoints(src_id)");
368
+ db.run("create index if not exists idx_waypoints_dst on waypoints(dst_id)");
369
+ db.run("create index if not exists idx_waypoints_user on waypoints(user_id)");
370
+ db.run("create index if not exists idx_stats_ts on stats(ts)");
371
+ db.run("create index if not exists idx_stats_type on stats(type)");
372
+ db.run("create index if not exists idx_temporal_subject on temporal_facts(subject)");
373
+ db.run("create index if not exists idx_temporal_predicate on temporal_facts(predicate)");
374
+ db.run("create index if not exists idx_temporal_validity on temporal_facts(valid_from,valid_to)");
375
+ db.run("create index if not exists idx_temporal_composite on temporal_facts(subject,predicate,valid_from,valid_to)");
376
+ db.run("create index if not exists idx_edges_source on temporal_edges(source_id)");
377
+ db.run("create index if not exists idx_edges_target on temporal_edges(target_id)");
378
+ db.run("create index if not exists idx_edges_validity on temporal_edges(valid_from,valid_to)");
379
+ db.run("create index if not exists idx_edges_validity on temporal_edges(valid_from,valid_to)");
380
+ });
381
+ exports.memories_table = memories_table = "memories";
382
+ const exec = (sql, p = []) => new Promise((ok, no) => db.run(sql, p, (err) => (err ? no(err) : ok())));
383
+ const one = (sql, p = []) => new Promise((ok, no) => db.get(sql, p, (err, row) => (err ? no(err) : ok(row))));
384
+ const many = (sql, p = []) => new Promise((ok, no) => db.all(sql, p, (err, rows) => (err ? no(err) : ok(rows))));
385
+ exports.run_async = run_async = exec;
386
+ exports.get_async = get_async = one;
387
+ exports.all_async = all_async = many;
388
+ // Initialize VectorStore (SQLite fallback uses PostgresVectorStore logic but with SQLite db ops)
389
+ // Note: PostgresVectorStore uses SQL syntax which might be compatible with SQLite for simple things,
390
+ // but `bytea` vs `blob` might differ.
391
+ // However, the interface implementation I wrote uses `run_async` etc.
392
+ // I should probably rename PostgresVectorStore to SqlVectorStore or similar if it supports both.
393
+ // For now, I'll use it for SQLite too as the SQL seems standard enough (except maybe bytea/blob handling in param binding).
394
+ // SQLite uses `blob`. Postgres uses `bytea`.
395
+ // The `PostgresVectorStore` implementation uses `vectorToBuffer` which returns a Buffer.
396
+ // `sqlite3` handles Buffer as BLOB. `pg` handles Buffer as bytea.
397
+ // So it should work.
398
+ if (cfg_1.env.vector_backend === "valkey") {
399
+ exports.vector_store = vector_store = new valkey_1.ValkeyVectorStore();
400
+ console.error("[DB] Using Valkey VectorStore");
401
+ }
402
+ else {
403
+ exports.vector_store = vector_store = new postgres_1.PostgresVectorStore({ run_async, get_async, all_async }, sqlite_vector_table);
404
+ console.error(`[DB] Using SQLite VectorStore with table: ${sqlite_vector_table}`);
405
+ }
406
+ // Simple Mutex for transaction serialization
407
+ class Mutex {
408
+ mutex = Promise.resolve();
409
+ lock() {
410
+ let unlock = () => { };
411
+ const willUnlock = new Promise(resolve => {
412
+ unlock = resolve;
413
+ });
414
+ const willAcquire = this.mutex.then(() => unlock);
415
+ this.mutex = this.mutex.then(() => willUnlock);
416
+ return willAcquire;
417
+ }
418
+ }
419
+ const txLock = new Mutex();
420
+ let releaseTx = null;
421
+ exports.transaction = transaction = {
422
+ begin: async () => {
423
+ /*
424
+ if (releaseTx) {
425
+ // console.error("[TX] ERROR: Active during begin!");
426
+ throw new Error("Transaction already active via lock");
427
+ }
428
+ */
429
+ const release = await txLock.lock();
430
+ releaseTx = release;
431
+ try {
432
+ await exec("BEGIN TRANSACTION");
433
+ }
434
+ catch (e) {
435
+ releaseTx();
436
+ releaseTx = null;
437
+ throw e;
438
+ }
439
+ },
440
+ commit: async () => {
441
+ if (!releaseTx)
442
+ return;
443
+ try {
444
+ await exec("COMMIT");
445
+ }
446
+ finally {
447
+ releaseTx();
448
+ releaseTx = null;
449
+ }
450
+ },
451
+ rollback: async () => {
452
+ if (!releaseTx)
453
+ return;
454
+ try {
455
+ await exec("ROLLBACK");
456
+ }
457
+ finally {
458
+ releaseTx();
459
+ releaseTx = null;
460
+ }
461
+ },
462
+ };
463
+ exports.q = q = {
464
+ ins_mem: {
465
+ run: (...p) => exec("insert into memories(id,user_id,segment,content,simhash,primary_sector,tags,meta,created_at,updated_at,last_seen_at,salience,decay_lambda,version,mean_dim,mean_vec,compressed_vec,feedback_score) values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", p),
466
+ },
467
+ upd_mean_vec: {
468
+ run: (...p) =>
469
+ // p: [id, mean_dim, mean_vec]
470
+ exec("update memories set mean_dim=?,mean_vec=? where id=?", [
471
+ p[1],
472
+ p[2],
473
+ p[0],
474
+ ]),
475
+ },
476
+ upd_compressed_vec: {
477
+ run: (...p) => exec("update memories set compressed_vec=? where id=?", p),
478
+ },
479
+ upd_feedback: {
480
+ run: (...p) => exec("update memories set feedback_score=? where id=?", p),
481
+ },
482
+ upd_seen: {
483
+ run: (...p) => exec("update memories set last_seen_at=?,salience=?,updated_at=? where id=?", p),
484
+ },
485
+ upd_mem: {
486
+ run: (...p) => exec("update memories set content=?,tags=?,meta=?,updated_at=?,version=version+1 where id=?", p),
487
+ },
488
+ upd_mem_with_sector: {
489
+ run: (...p) => exec("update memories set content=?,primary_sector=?,tags=?,meta=?,updated_at=?,version=version+1 where id=?", p),
490
+ },
491
+ del_mem: { run: (...p) => exec("delete from memories where id=?", p) },
492
+ get_mem: {
493
+ get: (id) => one("select * from memories where id=?", [id]),
494
+ },
495
+ get_mem_by_simhash: {
496
+ get: (simhash) => one("select * from memories where simhash=? order by salience desc limit 1", [simhash]),
497
+ },
498
+ all_mem: {
499
+ all: (limit, offset) => many("select * from memories order by created_at desc limit ? offset ?", [limit, offset]),
500
+ },
501
+ all_mem_by_sector: {
502
+ all: (sector, limit, offset) => many("select * from memories where primary_sector=? order by created_at desc limit ? offset ?", [sector, limit, offset]),
503
+ },
504
+ get_segment_count: {
505
+ get: (segment) => one("select count(*) as c from memories where segment=?", [
506
+ segment,
507
+ ]),
508
+ },
509
+ get_max_segment: {
510
+ get: () => one("select coalesce(max(segment), 0) as max_seg from memories", []),
511
+ },
512
+ get_segments: {
513
+ all: () => many("select distinct segment from memories order by segment desc", []),
514
+ },
515
+ get_mem_by_segment: {
516
+ all: (segment) => many("select * from memories where segment=? order by created_at desc", [segment]),
517
+ },
518
+ // Vector operations removed
519
+ ins_waypoint: {
520
+ run: (...p) => exec("insert or replace into waypoints(src_id,dst_id,user_id,weight,created_at,updated_at) values(?,?,?,?,?,?)", p),
521
+ },
522
+ get_neighbors: {
523
+ all: (src) => many("select dst_id,weight from waypoints where src_id=? order by weight desc", [src]),
524
+ },
525
+ get_waypoints_by_src: {
526
+ all: (src) => many("select src_id,dst_id,weight,created_at,updated_at from waypoints where src_id=?", [src]),
527
+ },
528
+ get_waypoint: {
529
+ get: (src, dst) => one("select weight from waypoints where src_id=? and dst_id=?", [src, dst]),
530
+ },
531
+ upd_waypoint: {
532
+ run: (...p) => exec("update waypoints set weight=?,updated_at=? where src_id=? and dst_id=?", p),
533
+ },
534
+ del_waypoints: {
535
+ run: (...p) => exec("delete from waypoints where src_id=? or dst_id=?", p),
536
+ },
537
+ prune_waypoints: {
538
+ run: (t) => exec("delete from waypoints where weight<?", [t]),
539
+ },
540
+ ins_log: {
541
+ run: (...p) => exec("insert or replace into embed_logs(id,model,status,ts,err) values(?,?,?,?,?)", p),
542
+ },
543
+ upd_log: {
544
+ run: (...p) => exec("update embed_logs set status=?,err=? where id=?", p),
545
+ },
546
+ get_pending_logs: {
547
+ all: () => many("select * from embed_logs where status=?", ["pending"]),
548
+ },
549
+ get_failed_logs: {
550
+ all: () => many("select * from embed_logs where status=? order by ts desc limit 100", ["failed"]),
551
+ },
552
+ all_mem_by_user: {
553
+ all: (user_id, limit, offset) => many("select * from memories where user_id=? order by created_at desc limit ? offset ?", [user_id, limit, offset]),
554
+ },
555
+ ins_user: {
556
+ run: (...p) => exec("insert into users(user_id, clerk_id, api_key, stripe_customer_id, stripe_subscription_id, memory_capacity, memory_usage, summary, reflection_count, created_at, updated_at) values(?,?,?,?,?,?,?,?,?,?,?) on conflict(user_id) do update set clerk_id=excluded.clerk_id, api_key=excluded.api_key, stripe_customer_id=excluded.stripe_customer_id, stripe_subscription_id=excluded.stripe_subscription_id, memory_capacity=excluded.memory_capacity, memory_usage=excluded.memory_usage, summary=excluded.summary, reflection_count=excluded.reflection_count, updated_at=excluded.updated_at", p),
557
+ },
558
+ get_user: {
559
+ get: (user_id) => one("select * from users where user_id=?", [user_id]),
560
+ },
561
+ get_user_by_api_key: {
562
+ get: (api_key) => one("select * from users where api_key=?", [api_key]),
563
+ },
564
+ get_user_by_memory_key: {
565
+ get: (key) => one("select u.*, k.id as key_id, k.label as key_label from api_keys k join users u on k.user_id = u.user_id where k.secret_key=?", [key]),
566
+ },
567
+ ins_memory_key: {
568
+ run: (...p) => exec("insert into api_keys(id, user_id, label, secret_key, created_at) values(?,?,?,?,?)", p),
569
+ },
570
+ del_memory_key: {
571
+ run: (...p) => exec("delete from api_keys where id=? and user_id=?", p),
572
+ },
573
+ get_memory_keys_by_user: {
574
+ all: (user_id) => many("select * from api_keys where user_id=? order by created_at desc", [user_id]),
575
+ },
576
+ upd_memory_key_label: {
577
+ run: (label, updated_at, id, user_id) => exec("update api_keys set label=?, updated_at=? where id=? and user_id=?", [label, updated_at, id, user_id]),
578
+ },
579
+ get_memory_counts_by_key: {
580
+ all: (user_id) => many("select memory_key_id, count(*) as count from memories where user_id=? group by memory_key_id", [user_id]),
581
+ },
582
+ bulk_del_mem: {
583
+ run: async (ids, user_id) => {
584
+ if (ids.length === 0)
585
+ return;
586
+ const placeholders = ids.map(() => '?').join(',');
587
+ await exec(`delete from memories where id in (${placeholders}) and user_id=?`, [...ids, user_id]);
588
+ },
589
+ },
590
+ bulk_upd_mem_key: {
591
+ run: async (memory_key_id, updated_at, ids, user_id) => {
592
+ if (ids.length === 0)
593
+ return;
594
+ const idPlaceholders = ids.map(() => '?').join(',');
595
+ await exec(`update memories set memory_key_id=?, updated_at=? where id in (${idPlaceholders}) and user_id=?`, [memory_key_id, updated_at, ...ids, user_id]);
596
+ },
597
+ },
598
+ get_user_by_clerk_id: {
599
+ get: (clerk_id) => one("select * from users where clerk_id=?", [clerk_id]),
600
+ },
601
+ get_user_by_stripe_customer_id: {
602
+ get: (customer_id) => one("select * from users where stripe_customer_id=?", [customer_id]),
603
+ },
604
+ upd_user_summary: {
605
+ run: (...p) => exec("update users set summary=?,reflection_count=reflection_count+1,updated_at=? where user_id=?", p),
606
+ },
607
+ upd_user_billing: {
608
+ run: (...p) => exec("update users set stripe_customer_id=?, stripe_subscription_id=?, memory_capacity=?, updated_at=? where user_id=?", p),
609
+ },
610
+ inc_user_usage: {
611
+ run: (user_id, delta) => exec("update users set memory_usage=memory_usage+?, updated_at=? where user_id=?", [delta, Date.now(), user_id]),
612
+ },
613
+ clear_all: {
614
+ run: async () => {
615
+ await exec("delete from memories");
616
+ await exec("delete from waypoints");
617
+ await exec("delete from users");
618
+ // vector table name is variable
619
+ const vec_table = process.env.OM_VECTOR_TABLE || "vectors";
620
+ await exec(`delete from ${vec_table}`);
621
+ },
622
+ },
623
+ };
624
+ }
625
+ const log_maint_op = async (type, cnt = 1) => {
626
+ try {
627
+ const sql = is_pg
628
+ ? `insert into "${process.env.OM_PG_SCHEMA || "public"}"."stats"(type,count,ts) values($1,$2,$3)`
629
+ : "insert into stats(type,count,ts) values(?,?,?)";
630
+ await run_async(sql, [type, cnt, Date.now()]);
631
+ }
632
+ catch (e) {
633
+ console.error("[DB] Maintenance log error:", e);
634
+ }
635
+ };
636
+ exports.log_maint_op = log_maint_op;