nlm-memory 0.5.18 → 0.5.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/cli/nlm.js +147 -80
- package/dist/cli/nlm.js.map +1 -1
- package/dist/cli/supersede.js +5 -2
- package/dist/cli/supersede.js.map +1 -1
- package/dist/core/actions/actions-log.d.ts +9 -0
- package/dist/core/actions/actions-log.js +86 -0
- package/dist/core/actions/actions-log.js.map +1 -1
- package/dist/core/digest/compose.d.ts +0 -1
- package/dist/core/digest/compose.js +0 -4
- package/dist/core/digest/compose.js.map +1 -1
- package/dist/core/providers/provider-registry.d.ts +15 -0
- package/dist/core/providers/provider-registry.js +85 -0
- package/dist/core/providers/provider-registry.js.map +1 -1
- package/dist/core/recall/query-log.d.ts +1 -2
- package/dist/core/recall/query-log.js +1 -5
- package/dist/core/recall/query-log.js.map +1 -1
- package/dist/core/scheduler/scan-once.d.ts +4 -0
- package/dist/core/scheduler/scan-once.js +64 -0
- package/dist/core/scheduler/scan-once.js.map +1 -1
- package/dist/core/scheduler/scheduler.js +25 -9
- package/dist/core/scheduler/scheduler.js.map +1 -1
- package/dist/core/sources/source-registry.d.ts +16 -0
- package/dist/core/sources/source-registry.js +123 -0
- package/dist/core/sources/source-registry.js.map +1 -1
- package/dist/core/storage/pg-fact-store.d.ts +24 -0
- package/dist/core/storage/pg-fact-store.js +233 -0
- package/dist/core/storage/pg-fact-store.js.map +1 -0
- package/dist/core/storage/pg-session-store.d.ts +29 -0
- package/dist/core/storage/pg-session-store.js +315 -0
- package/dist/core/storage/pg-session-store.js.map +1 -0
- package/dist/core/storage/pg-storage.d.ts +36 -0
- package/dist/core/storage/pg-storage.js +87 -0
- package/dist/core/storage/pg-storage.js.map +1 -0
- package/dist/core/storage/pg-tx-context.d.ts +44 -0
- package/dist/core/storage/pg-tx-context.js +133 -0
- package/dist/core/storage/pg-tx-context.js.map +1 -0
- package/dist/core/storage/sqlite-fact-store.d.ts +13 -7
- package/dist/core/storage/sqlite-fact-store.js +38 -12
- package/dist/core/storage/sqlite-fact-store.js.map +1 -1
- package/dist/core/storage/sqlite-session-store.d.ts +6 -16
- package/dist/core/storage/sqlite-session-store.js +51 -42
- package/dist/core/storage/sqlite-session-store.js.map +1 -1
- package/dist/core/storage/sqlite-storage.d.ts +38 -0
- package/dist/core/storage/sqlite-storage.js +66 -0
- package/dist/core/storage/sqlite-storage.js.map +1 -0
- package/dist/hook/pi-extension.d.ts +43 -0
- package/dist/hook/pi-extension.js +50 -0
- package/dist/hook/pi-extension.js.map +1 -0
- package/dist/hook/prompt-recall-hook.js +1 -36
- package/dist/hook/prompt-recall-hook.js.map +1 -1
- package/dist/hook/recall-over-http.d.ts +10 -0
- package/dist/hook/recall-over-http.js +41 -0
- package/dist/hook/recall-over-http.js.map +1 -0
- package/dist/hook/stop-hook.d.ts +1 -3
- package/dist/hook/stop-hook.js +1 -3
- package/dist/hook/stop-hook.js.map +1 -1
- package/dist/http/app.d.ts +6 -5
- package/dist/http/app.js +15 -4
- package/dist/http/app.js.map +1 -1
- package/dist/install/pi.d.ts +42 -0
- package/dist/install/pi.js +84 -0
- package/dist/install/pi.js.map +1 -0
- package/dist/install/setup.js +21 -5
- package/dist/install/setup.js.map +1 -1
- package/dist/ports/fact-store.d.ts +26 -0
- package/dist/ports/storage.d.ts +45 -0
- package/dist/ports/storage.js +14 -0
- package/dist/ports/storage.js.map +1 -0
- package/package.json +5 -1
- package/plugin/scripts/prompt-recall-hook.mjs +31 -29
- package/plugin-pi/README.md +71 -0
- package/plugin-pi/package.json +12 -0
- package/plugin-pi/scripts/nlm-extension.mjs +280 -0
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PgFactStore — FactStore implementation over pg.Pool + pgvector.
|
|
3
|
+
*
|
|
4
|
+
* Receives its Pool from PgStorage. Never opens its own connection.
|
|
5
|
+
*/
|
|
6
|
+
export class PgFactStore {
|
|
7
|
+
pool;
|
|
8
|
+
constructor(pool) {
|
|
9
|
+
this.pool = pool;
|
|
10
|
+
}
|
|
11
|
+
async insert(fact) {
|
|
12
|
+
await this.pool.query(`INSERT INTO facts (id, kind, subject, predicate, value, source_session_id,
|
|
13
|
+
source_quote, created_at, superseded_by, confidence)
|
|
14
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)`, [fact.id, fact.kind, fact.subject, fact.predicate, fact.value,
|
|
15
|
+
fact.sourceSessionId, fact.sourceQuote, fact.createdAt, fact.supersededBy, fact.confidence]);
|
|
16
|
+
}
|
|
17
|
+
async insertMany(facts) {
|
|
18
|
+
if (facts.length === 0)
|
|
19
|
+
return;
|
|
20
|
+
const client = await this.pool.connect();
|
|
21
|
+
try {
|
|
22
|
+
await client.query("BEGIN");
|
|
23
|
+
for (const f of facts) {
|
|
24
|
+
await client.query(`INSERT INTO facts (id, kind, subject, predicate, value, source_session_id,
|
|
25
|
+
source_quote, created_at, superseded_by, confidence)
|
|
26
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)`, [f.id, f.kind, f.subject, f.predicate, f.value,
|
|
27
|
+
f.sourceSessionId, f.sourceQuote, f.createdAt, f.supersededBy, f.confidence]);
|
|
28
|
+
}
|
|
29
|
+
await client.query("COMMIT");
|
|
30
|
+
}
|
|
31
|
+
catch (err) {
|
|
32
|
+
await client.query("ROLLBACK");
|
|
33
|
+
throw err;
|
|
34
|
+
}
|
|
35
|
+
finally {
|
|
36
|
+
client.release();
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
async getById(id) {
|
|
40
|
+
const result = await this.pool.query(`SELECT id, kind, subject, predicate, value, source_session_id,
|
|
41
|
+
source_quote, created_at, superseded_by, confidence
|
|
42
|
+
FROM facts WHERE id = $1`, [id]);
|
|
43
|
+
return result.rows[0] ? rowToFact(result.rows[0]) : null;
|
|
44
|
+
}
|
|
45
|
+
async findCurrent(subject, predicate) {
|
|
46
|
+
const result = await this.pool.query(`SELECT id, kind, subject, predicate, value, source_session_id,
|
|
47
|
+
source_quote, created_at, superseded_by, confidence
|
|
48
|
+
FROM facts
|
|
49
|
+
WHERE subject = $1 AND predicate = $2 AND superseded_by IS NULL
|
|
50
|
+
ORDER BY created_at DESC
|
|
51
|
+
LIMIT 1`, [subject, predicate]);
|
|
52
|
+
return result.rows[0] ? rowToFact(result.rows[0]) : null;
|
|
53
|
+
}
|
|
54
|
+
async list(query) {
|
|
55
|
+
const limit = Math.max(1, Math.trunc(query.limit ?? 50));
|
|
56
|
+
const includeSuperseded = query.includeSuperseded === true;
|
|
57
|
+
const where = ["subject = $1"];
|
|
58
|
+
const params = [query.subject];
|
|
59
|
+
let idx = 2;
|
|
60
|
+
if (query.predicate !== undefined) {
|
|
61
|
+
where.push(`predicate = $${idx++}`);
|
|
62
|
+
params.push(query.predicate);
|
|
63
|
+
}
|
|
64
|
+
if (!includeSuperseded)
|
|
65
|
+
where.push("superseded_by IS NULL");
|
|
66
|
+
params.push(limit);
|
|
67
|
+
const result = await this.pool.query(`SELECT id, kind, subject, predicate, value, source_session_id,
|
|
68
|
+
source_quote, created_at, superseded_by, confidence
|
|
69
|
+
FROM facts
|
|
70
|
+
WHERE ${where.join(" AND ")}
|
|
71
|
+
ORDER BY created_at DESC
|
|
72
|
+
LIMIT $${idx}`, params);
|
|
73
|
+
return result.rows.map(rowToFact);
|
|
74
|
+
}
|
|
75
|
+
async listBySession(sessionId) {
|
|
76
|
+
const result = await this.pool.query(`SELECT id, kind, subject, predicate, value, source_session_id,
|
|
77
|
+
source_quote, created_at, superseded_by, confidence
|
|
78
|
+
FROM facts
|
|
79
|
+
WHERE source_session_id = $1
|
|
80
|
+
ORDER BY created_at ASC`, [sessionId]);
|
|
81
|
+
return result.rows.map(rowToFact);
|
|
82
|
+
}
|
|
83
|
+
async listForRecall(filter) {
|
|
84
|
+
const where = [];
|
|
85
|
+
const params = [];
|
|
86
|
+
let idx = 1;
|
|
87
|
+
if (filter.subject !== undefined) {
|
|
88
|
+
where.push(`subject = $${idx++}`);
|
|
89
|
+
params.push(filter.subject);
|
|
90
|
+
}
|
|
91
|
+
if (filter.predicate !== undefined) {
|
|
92
|
+
where.push(`predicate = $${idx++}`);
|
|
93
|
+
params.push(filter.predicate);
|
|
94
|
+
}
|
|
95
|
+
if (filter.kind !== undefined) {
|
|
96
|
+
where.push(`kind = $${idx++}`);
|
|
97
|
+
params.push(filter.kind);
|
|
98
|
+
}
|
|
99
|
+
if (filter.minConfidence !== undefined) {
|
|
100
|
+
where.push(`confidence >= $${idx++}`);
|
|
101
|
+
params.push(filter.minConfidence);
|
|
102
|
+
}
|
|
103
|
+
if (filter.includeSuperseded !== true)
|
|
104
|
+
where.push("superseded_by IS NULL");
|
|
105
|
+
const limit = Math.max(1, Math.trunc(filter.limit ?? 500));
|
|
106
|
+
params.push(limit);
|
|
107
|
+
const sql = `
|
|
108
|
+
SELECT id, kind, subject, predicate, value, source_session_id,
|
|
109
|
+
source_quote, created_at, superseded_by, confidence
|
|
110
|
+
FROM facts
|
|
111
|
+
${where.length > 0 ? "WHERE " + where.join(" AND ") : ""}
|
|
112
|
+
ORDER BY created_at DESC
|
|
113
|
+
LIMIT $${idx}
|
|
114
|
+
`;
|
|
115
|
+
const result = await this.pool.query(sql, params);
|
|
116
|
+
return result.rows.map(rowToFact);
|
|
117
|
+
}
|
|
118
|
+
async markSuperseded(oldId, newId) {
|
|
119
|
+
if (newId !== null && oldId === newId) {
|
|
120
|
+
throw new Error("A fact cannot supersede itself");
|
|
121
|
+
}
|
|
122
|
+
const client = await this.pool.connect();
|
|
123
|
+
try {
|
|
124
|
+
await client.query("BEGIN");
|
|
125
|
+
const old = await client.query("SELECT id FROM facts WHERE id = $1", [oldId]);
|
|
126
|
+
if (old.rows.length === 0)
|
|
127
|
+
throw new Error(`Fact ${oldId} not found`);
|
|
128
|
+
if (newId !== null) {
|
|
129
|
+
const next = await client.query("SELECT id FROM facts WHERE id = $1", [newId]);
|
|
130
|
+
if (next.rows.length === 0)
|
|
131
|
+
throw new Error(`Fact ${newId} not found`);
|
|
132
|
+
}
|
|
133
|
+
await client.query("UPDATE facts SET superseded_by = $1 WHERE id = $2", [newId, oldId]);
|
|
134
|
+
await client.query("COMMIT");
|
|
135
|
+
}
|
|
136
|
+
catch (err) {
|
|
137
|
+
await client.query("ROLLBACK");
|
|
138
|
+
throw err;
|
|
139
|
+
}
|
|
140
|
+
finally {
|
|
141
|
+
client.release();
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
async ingestSessionFacts(sessionId, facts) {
|
|
145
|
+
const client = await this.pool.connect();
|
|
146
|
+
try {
|
|
147
|
+
await client.query("BEGIN");
|
|
148
|
+
await client.query("DELETE FROM facts WHERE source_session_id = $1", [sessionId]);
|
|
149
|
+
if (facts.length > 0) {
|
|
150
|
+
for (const f of facts) {
|
|
151
|
+
await client.query(`INSERT INTO facts (id, kind, subject, predicate, value, source_session_id,
|
|
152
|
+
source_quote, created_at, superseded_by, confidence)
|
|
153
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)`, [f.id, f.kind, f.subject, f.predicate, f.value,
|
|
154
|
+
f.sourceSessionId, f.sourceQuote, f.createdAt, f.supersededBy, f.confidence]);
|
|
155
|
+
}
|
|
156
|
+
const values = facts
|
|
157
|
+
.map((_, i) => `($${i * 3 + 1}, $${i * 3 + 2}, $${i * 3 + 3})`)
|
|
158
|
+
.join(", ");
|
|
159
|
+
const params = [];
|
|
160
|
+
for (const f of facts)
|
|
161
|
+
params.push(f.subject, f.predicate, f.id);
|
|
162
|
+
await client.query(`UPDATE facts AS old
|
|
163
|
+
SET superseded_by = new_f.new_id
|
|
164
|
+
FROM (VALUES ${values}) AS new_f(subject, predicate, new_id)
|
|
165
|
+
WHERE old.subject = new_f.subject
|
|
166
|
+
AND old.predicate = new_f.predicate
|
|
167
|
+
AND old.superseded_by IS NULL
|
|
168
|
+
AND old.id != new_f.new_id`, params);
|
|
169
|
+
}
|
|
170
|
+
await client.query("COMMIT");
|
|
171
|
+
}
|
|
172
|
+
catch (err) {
|
|
173
|
+
await client.query("ROLLBACK");
|
|
174
|
+
throw err;
|
|
175
|
+
}
|
|
176
|
+
finally {
|
|
177
|
+
client.release();
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
async upsertEmbedding(factId, vector) {
|
|
181
|
+
const vecStr = `[${Array.from(vector).join(",")}]`;
|
|
182
|
+
await this.pool.query(`INSERT INTO fact_embeddings (fact_id, embedding)
|
|
183
|
+
VALUES ($1, $2::vector)
|
|
184
|
+
ON CONFLICT (fact_id) DO UPDATE SET embedding = EXCLUDED.embedding`, [factId, vecStr]);
|
|
185
|
+
}
|
|
186
|
+
async semanticSearch(queryVector, limit) {
|
|
187
|
+
const k = Math.max(1, Math.trunc(limit));
|
|
188
|
+
const vecStr = `[${Array.from(queryVector).join(",")}]`;
|
|
189
|
+
const result = await this.pool.query(`SELECT fact_id, embedding <-> $1::vector AS distance
|
|
190
|
+
FROM fact_embeddings
|
|
191
|
+
ORDER BY embedding <-> $1::vector
|
|
192
|
+
LIMIT $2`, [vecStr, k]);
|
|
193
|
+
return result.rows.map((r) => ({ factId: r.fact_id, distance: r.distance }));
|
|
194
|
+
}
|
|
195
|
+
async getHistory(subject, predicate) {
|
|
196
|
+
const result = predicate
|
|
197
|
+
? await this.pool.query(`SELECT id, kind, subject, predicate, value, source_session_id,
|
|
198
|
+
source_quote, created_at, superseded_by, confidence
|
|
199
|
+
FROM facts
|
|
200
|
+
WHERE subject = $1 AND predicate = $2
|
|
201
|
+
ORDER BY predicate ASC, created_at DESC`, [subject, predicate])
|
|
202
|
+
: await this.pool.query(`SELECT id, kind, subject, predicate, value, source_session_id,
|
|
203
|
+
source_quote, created_at, superseded_by, confidence
|
|
204
|
+
FROM facts
|
|
205
|
+
WHERE subject = $1
|
|
206
|
+
ORDER BY predicate ASC, created_at DESC`, [subject]);
|
|
207
|
+
const byPred = new Map();
|
|
208
|
+
for (const row of result.rows) {
|
|
209
|
+
const fact = rowToFact(row);
|
|
210
|
+
const bucket = byPred.get(fact.predicate);
|
|
211
|
+
if (bucket)
|
|
212
|
+
bucket.push(fact);
|
|
213
|
+
else
|
|
214
|
+
byPred.set(fact.predicate, [fact]);
|
|
215
|
+
}
|
|
216
|
+
return [...byPred.entries()].map(([pred, history]) => ({ subject, predicate: pred, history }));
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
function rowToFact(row) {
|
|
220
|
+
return {
|
|
221
|
+
id: row.id,
|
|
222
|
+
kind: row.kind,
|
|
223
|
+
subject: row.subject,
|
|
224
|
+
predicate: row.predicate,
|
|
225
|
+
value: row.value,
|
|
226
|
+
sourceSessionId: row.source_session_id,
|
|
227
|
+
sourceQuote: row.source_quote,
|
|
228
|
+
createdAt: row.created_at,
|
|
229
|
+
supersededBy: row.superseded_by,
|
|
230
|
+
confidence: row.confidence,
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
//# sourceMappingURL=pg-fact-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pg-fact-store.js","sourceRoot":"","sources":["../../../src/core/storage/pg-fact-store.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAwBH,MAAM,OAAO,WAAW;IACO;IAA7B,YAA6B,IAAU;QAAV,SAAI,GAAJ,IAAI,CAAM;IAAG,CAAC;IAE3C,KAAK,CAAC,MAAM,CAAC,IAAU;QACrB,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CACnB;;wDAEkD,EAClD,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,KAAK;YAC5D,IAAI,CAAC,eAAe,EAAE,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,UAAU,CAAC,CAC7F,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,KAA0B;QACzC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QAC/B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;QACzC,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAC5B,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;gBACtB,MAAM,MAAM,CAAC,KAAK,CAChB;;4DAEkD,EAClD,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,KAAK;oBAC7C,CAAC,CAAC,eAAe,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC,UAAU,CAAC,CAC9E,CAAC;YACJ,CAAC;YACD,MAAM,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QAC/B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;YAC/B,MAAM,GAAG,CAAC;QACZ,CAAC;gBAAS,CAAC;YACT,MAAM,CAAC,OAAO,EAAE,CAAC;QACnB,CAAC;IACH,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,EAAU;QACtB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAClC;;gCAE0B,EAC1B,CAAC,EAAE,CAAC,CACL,CAAC;QACF,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC3D,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,OAAe,EAAE,SAAiB;QAClD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAClC;;;;;eAKS,EACT,CAAC,OAAO,EAAE,SAAS,CAAC,CACrB,CAAC;QACF,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC3D,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,KAAgB;QACzB,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC;QACzD,MAAM,iBAAiB,GAAG,KAAK,CAAC,iBAAiB,KAAK,IAAI,CAAC;QAC3D,MAAM,KAAK,GAAa,CAAC,cAAc,CAAC,CAAC;QACzC,MAAM,MAAM,GAAc,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC1C,IAAI,GAAG,GAAG,CAAC,CAAC;QACZ,IAAI,KAAK,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;YAClC,KAAK,CAAC,IAAI,CAAC,gBAAgB,GAAG,EAAE,EAAE,CAAC,CAAC;YACpC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QAC/B,CAAC;QACD,IAAI,CAAC,iBAAiB;YAAE,KAAK,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;QAC5D,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAClC;;;eAGS,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC;;gBAElB,GAAG,EAAE,EACf,MAAM,CACP,CAAC;QACF,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IACpC,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,SAAiB;QACnC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAClC;;;;+BAIyB,EACzB,CAAC,SAAS,CAAC,CACZ,CAAC;QACF,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IACpC,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,MAAsB;QACxC,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,MAAM,MAAM,GAAc,EAAE,CAAC;QAC7B,IAAI,GAAG,GAAG,CAAC,CAAC;QACZ,IAAI,MAAM,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;YAAC,KAAK,CAAC,IAAI,CAAC,cAAc,GAAG,EAAE,EAAE,CAAC,CAAC;YAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAAC,CAAC;QACrG,IAAI,MAAM,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;YAAC,KAAK,CAAC,IAAI,CAAC,gBAAgB,GAAG,EAAE,EAAE,CAAC,CAAC;YAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAAC,CAAC;QAC3G,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAAC,KAAK,CAAC,IAAI,CAAC,WAAW,GAAG,EAAE,EAAE,CAAC,CAAC;YAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAAC,CAAC;QAC5F,IAAI,MAAM,CAAC,aAAa,KAAK,SAAS,EAAE,CAAC;YAAC,KAAK,CAAC,IAAI,CAAC,kBAAkB,GAAG,EAAE,EAAE,CAAC,CAAC;YAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;QAAC,CAAC;QACrH,IAAI,MAAM,CAAC,iBAAiB,KAAK,IAAI;YAAE,KAAK,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;QAC3E,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,IAAI,GAAG,CAAC,CAAC,CAAC;QAC3D,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnB,MAAM,GAAG,GAAG;;;;QAIR,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE;;eAE/C,GAAG;KACb,CAAC;QACF,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAU,GAAG,EAAE,MAAM,CAAC,CAAC;QAC3D,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IACpC,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,KAAa,EAAE,KAAoB;QACtD,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,KAAK,EAAE,CAAC;YACtC,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;QACpD,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;QACzC,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAC5B,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,KAAK,CAC5B,oCAAoC,EAAE,CAAC,KAAK,CAAC,CAC9C,CAAC;YACF,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC;gBAAE,MAAM,IAAI,KAAK,CAAC,QAAQ,KAAK,YAAY,CAAC,CAAC;YACtE,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;gBACnB,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,KAAK,CAC7B,oCAAoC,EAAE,CAAC,KAAK,CAAC,CAC9C,CAAC;gBACF,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC;oBAAE,MAAM,IAAI,KAAK,CAAC,QAAQ,KAAK,YAAY,CAAC,CAAC;YACzE,CAAC;YACD,MAAM,MAAM,CAAC,KAAK,CAChB,mDAAmD,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,CACpE,CAAC;YACF,MAAM,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QAC/B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;YAC/B,MAAM,GAAG,CAAC;QACZ,CAAC;gBAAS,CAAC;YACT,MAAM,CAAC,OAAO,EAAE,CAAC;QACnB,CAAC;IACH,CAAC;IAED,KAAK,CAAC,kBAAkB,CACtB,SAAiB,EACjB,KAA0B;QAE1B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;QACzC,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAC5B,MAAM,MAAM,CAAC,KAAK,CAAC,gDAAgD,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC;YAClF,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACrB,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;oBACtB,MAAM,MAAM,CAAC,KAAK,CAChB;;8DAEkD,EAClD,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,KAAK;wBAC7C,CAAC,CAAC,eAAe,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC,UAAU,CAAC,CAC9E,CAAC;gBACJ,CAAC;gBACD,MAAM,MAAM,GAAG,KAAK;qBACjB,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC;qBAC9D,IAAI,CAAC,IAAI,CAAC,CAAC;gBACd,MAAM,MAAM,GAAc,EAAE,CAAC;gBAC7B,KAAK,MAAM,CAAC,IAAI,KAAK;oBAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;gBACjE,MAAM,MAAM,CAAC,KAAK,CAChB;;0BAEgB,MAAM;;;;wCAIQ,EAC9B,MAAM,CACP,CAAC;YACJ,CAAC;YACD,MAAM,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QAC/B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;YAC/B,MAAM,GAAG,CAAC;QACZ,CAAC;gBAAS,CAAC;YACT,MAAM,CAAC,OAAO,EAAE,CAAC;QACnB,CAAC;IACH,CAAC;IAED,KAAK,CAAC,eAAe,CAAC,MAAc,EAAE,MAAoB;QACxD,MAAM,MAAM,GAAG,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;QACnD,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CACnB;;0EAEoE,EACpE,CAAC,MAAM,EAAE,MAAM,CAAC,CACjB,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,cAAc,CAClB,WAAyB,EACzB,KAAa;QAEb,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;QACzC,MAAM,MAAM,GAAG,IAAI,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;QACxD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAClC;;;gBAGU,EACV,CAAC,MAAM,EAAE,CAAC,CAAC,CACZ,CAAC;QACF,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;IAC/E,CAAC;IAED,KAAK,CAAC,UAAU,CACd,OAAe,EACf,SAAkB;QAElB,MAAM,MAAM,GAAG,SAAS;YACtB,CAAC,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CACnB;;;;mDAIyC,EACzC,CAAC,OAAO,EAAE,SAAS,CAAC,CACrB;YACH,CAAC,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CACnB;;;;mDAIyC,EACzC,CAAC,OAAO,CAAC,CACV,CAAC;QAEN,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;QACzC,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;YAC9B,MAAM,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;YAC5B,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAC1C,IAAI,MAAM;gBAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;;gBACzB,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;QAC1C,CAAC;QACD,OAAO,CAAC,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;IACjG,CAAC;CACF;AAED,SAAS,SAAS,CAAC,GAAY;IAC7B,OAAO;QACL,EAAE,EAAE,GAAG,CAAC,EAAE;QACV,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,OAAO,EAAE,GAAG,CAAC,OAAO;QACpB,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,KAAK,EAAE,GAAG,CAAC,KAAK;QAChB,eAAe,EAAE,GAAG,CAAC,iBAAiB;QACtC,WAAW,EAAE,GAAG,CAAC,YAAY;QAC7B,SAAS,EAAE,GAAG,CAAC,UAAU;QACzB,YAAY,EAAE,GAAG,CAAC,aAAa;QAC/B,UAAU,EAAE,GAAG,CAAC,UAAU;KAC3B,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PgSessionStore — SessionStore implementation over pg.Pool + pgvector.
|
|
3
|
+
*
|
|
4
|
+
* Constructor takes the Pool from PgStorage. Also exposes recentWrites()
|
|
5
|
+
* and recentMarkers() for the /live HTTP endpoints, and insertSession() +
|
|
6
|
+
* insertSessionForTest() for ingest and test seeding.
|
|
7
|
+
*/
|
|
8
|
+
import type { Pool } from "pg";
|
|
9
|
+
import type { KeywordNeighbor, SemanticNeighbor, SessionFilter, SessionStore } from "../../ports/session-store.js";
|
|
10
|
+
import type { Session, SessionStatus } from "../../shared/types.js";
|
|
11
|
+
import type { IngestRecord, RecentMarker, RecentWrite } from "./sqlite-session-store.js";
|
|
12
|
+
export declare class PgSessionStore implements SessionStore {
|
|
13
|
+
private readonly pool;
|
|
14
|
+
constructor(pool: Pool);
|
|
15
|
+
list(filter?: SessionFilter): Promise<ReadonlyArray<Session>>;
|
|
16
|
+
getById(sessionId: string): Promise<Session | null>;
|
|
17
|
+
getByIds(ids: ReadonlyArray<string>): Promise<ReadonlyArray<Session>>;
|
|
18
|
+
semanticSearch(queryVector: Float32Array, limit: number): Promise<ReadonlyArray<SemanticNeighbor>>;
|
|
19
|
+
keywordSearch(query: string, limit: number): Promise<ReadonlyArray<KeywordNeighbor>>;
|
|
20
|
+
updateStatus(sessionId: string, status: SessionStatus): Promise<void>;
|
|
21
|
+
markSuperseded(predecessorId: string, successorId: string): Promise<void>;
|
|
22
|
+
recentWrites(limit: number): Promise<RecentWrite[]>;
|
|
23
|
+
recentMarkers(limit: number): Promise<RecentMarker[]>;
|
|
24
|
+
insertSession(record: IngestRecord, embedder?: import("../../ports/llm-client.js").LLMClient | null, supersedes?: string | null): Promise<void>;
|
|
25
|
+
insertSessionForTest(session: Session): Promise<void>;
|
|
26
|
+
private loadEntities;
|
|
27
|
+
private loadMarkers;
|
|
28
|
+
private loadEdges;
|
|
29
|
+
}
|
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PgSessionStore — SessionStore implementation over pg.Pool + pgvector.
|
|
3
|
+
*
|
|
4
|
+
* Constructor takes the Pool from PgStorage. Also exposes recentWrites()
|
|
5
|
+
* and recentMarkers() for the /live HTTP endpoints, and insertSession() +
|
|
6
|
+
* insertSessionForTest() for ingest and test seeding.
|
|
7
|
+
*/
|
|
8
|
+
import { chunkSessionText } from "../embedding/chunk-body.js";
|
|
9
|
+
export class PgSessionStore {
|
|
10
|
+
pool;
|
|
11
|
+
constructor(pool) {
|
|
12
|
+
this.pool = pool;
|
|
13
|
+
}
|
|
14
|
+
async list(filter) {
|
|
15
|
+
const result = await this.pool.query(`SELECT id, runtime, runtime_session_id, started_at, ended_at, duration_min,
|
|
16
|
+
label, summary, status, transcript_kind, transcript_path, body
|
|
17
|
+
FROM sessions ORDER BY started_at ASC`);
|
|
18
|
+
if (result.rows.length === 0)
|
|
19
|
+
return [];
|
|
20
|
+
const ids = result.rows.map((r) => r.id);
|
|
21
|
+
const [entitiesMap, markersMap] = await Promise.all([
|
|
22
|
+
this.loadEntities(ids),
|
|
23
|
+
this.loadMarkers(ids),
|
|
24
|
+
]);
|
|
25
|
+
const sessions = result.rows.map((r) => rowToSession(r, entitiesMap, markersMap));
|
|
26
|
+
if (!filter)
|
|
27
|
+
return sessions;
|
|
28
|
+
return sessions.filter((s) => {
|
|
29
|
+
if (filter.entity !== undefined && !s.entities.includes(filter.entity))
|
|
30
|
+
return false;
|
|
31
|
+
if (filter.hasDecisions === true && s.decisions.length === 0)
|
|
32
|
+
return false;
|
|
33
|
+
if (filter.hasOpenQuestions === true && s.open.length === 0)
|
|
34
|
+
return false;
|
|
35
|
+
return true;
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
async getById(sessionId) {
|
|
39
|
+
const result = await this.pool.query(`SELECT id, runtime, runtime_session_id, started_at, ended_at, duration_min,
|
|
40
|
+
label, summary, status, transcript_kind, transcript_path, body
|
|
41
|
+
FROM sessions WHERE id = $1`, [sessionId]);
|
|
42
|
+
if (!result.rows[0])
|
|
43
|
+
return null;
|
|
44
|
+
const [entitiesMap, markersMap, edgesMap] = await Promise.all([
|
|
45
|
+
this.loadEntities([sessionId]),
|
|
46
|
+
this.loadMarkers([sessionId]),
|
|
47
|
+
this.loadEdges([sessionId]),
|
|
48
|
+
]);
|
|
49
|
+
const edges = edgesMap.get(sessionId);
|
|
50
|
+
return rowToSession(result.rows[0], entitiesMap, markersMap, edges);
|
|
51
|
+
}
|
|
52
|
+
async getByIds(ids) {
|
|
53
|
+
if (ids.length === 0)
|
|
54
|
+
return [];
|
|
55
|
+
const placeholders = ids.map((_, i) => `$${i + 1}`).join(",");
|
|
56
|
+
const result = await this.pool.query(`SELECT id, runtime, runtime_session_id, started_at, ended_at, duration_min,
|
|
57
|
+
label, summary, status, transcript_kind, transcript_path
|
|
58
|
+
FROM sessions WHERE id IN (${placeholders})`, [...ids]);
|
|
59
|
+
if (result.rows.length === 0)
|
|
60
|
+
return [];
|
|
61
|
+
const foundIds = result.rows.map((r) => r.id);
|
|
62
|
+
const [entitiesMap, markersMap] = await Promise.all([
|
|
63
|
+
this.loadEntities(foundIds),
|
|
64
|
+
this.loadMarkers(foundIds),
|
|
65
|
+
]);
|
|
66
|
+
return result.rows.map((r) => rowToSession({ ...r, body: null }, entitiesMap, markersMap));
|
|
67
|
+
}
|
|
68
|
+
async semanticSearch(queryVector, limit) {
|
|
69
|
+
const k = Math.max(1, Math.trunc(limit));
|
|
70
|
+
const vecStr = `[${Array.from(queryVector).join(",")}]`;
|
|
71
|
+
const result = await this.pool.query(`SELECT session_id, MIN(embedding <-> $1::vector) AS distance
|
|
72
|
+
FROM session_embedding_chunks
|
|
73
|
+
GROUP BY session_id
|
|
74
|
+
ORDER BY distance
|
|
75
|
+
LIMIT $2`, [vecStr, k]);
|
|
76
|
+
return result.rows.map((r) => ({ sessionId: r.session_id, distance: r.distance }));
|
|
77
|
+
}
|
|
78
|
+
async keywordSearch(query, limit) {
|
|
79
|
+
if (!query.trim())
|
|
80
|
+
return [];
|
|
81
|
+
const k = Math.max(1, Math.trunc(limit));
|
|
82
|
+
const result = await this.pool.query(`SELECT id AS session_id,
|
|
83
|
+
ts_rank_cd(fts_vector, websearch_to_tsquery('english', $1)) AS score
|
|
84
|
+
FROM sessions
|
|
85
|
+
WHERE fts_vector @@ websearch_to_tsquery('english', $1)
|
|
86
|
+
ORDER BY score DESC
|
|
87
|
+
LIMIT $2`, [query, k]);
|
|
88
|
+
return result.rows.map((r) => ({ sessionId: r.session_id, score: r.score }));
|
|
89
|
+
}
|
|
90
|
+
async updateStatus(sessionId, status) {
|
|
91
|
+
if (status === "idle") {
|
|
92
|
+
throw new Error("Cannot persist derived status 'idle' — only active/closed/superseded");
|
|
93
|
+
}
|
|
94
|
+
await this.pool.query("UPDATE sessions SET status = $1, updated_at = NOW() WHERE id = $2", [status, sessionId]);
|
|
95
|
+
}
|
|
96
|
+
async markSuperseded(predecessorId, successorId) {
|
|
97
|
+
if (predecessorId === successorId) {
|
|
98
|
+
throw new Error("A session cannot supersede itself");
|
|
99
|
+
}
|
|
100
|
+
const client = await this.pool.connect();
|
|
101
|
+
try {
|
|
102
|
+
await client.query("BEGIN");
|
|
103
|
+
const predExists = await client.query("SELECT COUNT(*) AS c FROM sessions WHERE id = $1", [predecessorId]);
|
|
104
|
+
if (Number(predExists.rows[0]?.c) === 0) {
|
|
105
|
+
throw new Error(`predecessor session ${predecessorId} not found`);
|
|
106
|
+
}
|
|
107
|
+
const succExists = await client.query("SELECT COUNT(*) AS c FROM sessions WHERE id = $1", [successorId]);
|
|
108
|
+
if (Number(succExists.rows[0]?.c) === 0) {
|
|
109
|
+
throw new Error(`successor session ${successorId} not found`);
|
|
110
|
+
}
|
|
111
|
+
await client.query(`DELETE FROM session_edges WHERE to_session = $1 AND kind = 'supersedes' AND from_session != $2`, [predecessorId, successorId]);
|
|
112
|
+
await client.query(`INSERT INTO session_edges (from_session, to_session, kind)
|
|
113
|
+
VALUES ($1, $2, 'supersedes')
|
|
114
|
+
ON CONFLICT DO NOTHING`, [successorId, predecessorId]);
|
|
115
|
+
await client.query("UPDATE sessions SET status = 'superseded', updated_at = NOW() WHERE id = $1", [predecessorId]);
|
|
116
|
+
await client.query("COMMIT");
|
|
117
|
+
}
|
|
118
|
+
catch (err) {
|
|
119
|
+
await client.query("ROLLBACK");
|
|
120
|
+
throw err;
|
|
121
|
+
}
|
|
122
|
+
finally {
|
|
123
|
+
client.release();
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
async recentWrites(limit) {
|
|
127
|
+
const result = await this.pool.query(`SELECT id, runtime, label, summary, created_at AS "createdAt"
|
|
128
|
+
FROM sessions ORDER BY created_at DESC LIMIT $1`, [limit]);
|
|
129
|
+
return result.rows;
|
|
130
|
+
}
|
|
131
|
+
async recentMarkers(limit) {
|
|
132
|
+
const result = await this.pool.query(`SELECT m.session_id AS "sessionId", m.kind, m.text, s.label, s.created_at AS "createdAt"
|
|
133
|
+
FROM markers m
|
|
134
|
+
JOIN sessions s ON s.id = m.session_id
|
|
135
|
+
ORDER BY s.created_at DESC, m.position ASC
|
|
136
|
+
LIMIT $1`, [limit]);
|
|
137
|
+
return result.rows;
|
|
138
|
+
}
|
|
139
|
+
async insertSession(record, embedder = null, supersedes = null) {
|
|
140
|
+
const client = await this.pool.connect();
|
|
141
|
+
try {
|
|
142
|
+
await client.query("BEGIN");
|
|
143
|
+
await client.query(`INSERT INTO sessions (
|
|
144
|
+
id, runtime, runtime_session_id, started_at, ended_at, duration_min,
|
|
145
|
+
label, summary, body, status, transcript_kind, transcript_path,
|
|
146
|
+
transcript_offset, transcript_length
|
|
147
|
+
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14)
|
|
148
|
+
ON CONFLICT (id) DO UPDATE SET
|
|
149
|
+
ended_at = EXCLUDED.ended_at,
|
|
150
|
+
duration_min = EXCLUDED.duration_min,
|
|
151
|
+
label = EXCLUDED.label,
|
|
152
|
+
summary = EXCLUDED.summary,
|
|
153
|
+
body = EXCLUDED.body,
|
|
154
|
+
status = EXCLUDED.status,
|
|
155
|
+
updated_at = NOW()`, [
|
|
156
|
+
record.id, record.runtime, record.runtimeSessionId,
|
|
157
|
+
record.startedAt, record.endedAt, record.durationMin,
|
|
158
|
+
record.label, record.summary, record.body,
|
|
159
|
+
record.status === "idle" ? "active" : record.status,
|
|
160
|
+
record.transcriptKind, record.transcriptPath,
|
|
161
|
+
record.transcriptOffset, record.transcriptLength,
|
|
162
|
+
]);
|
|
163
|
+
await client.query("DELETE FROM markers WHERE session_id = $1", [record.id]);
|
|
164
|
+
for (let i = 0; i < record.decisions.length; i++) {
|
|
165
|
+
await client.query("INSERT INTO markers (session_id, kind, text, position) VALUES ($1, 'decision', $2, $3)", [record.id, record.decisions[i].trim(), i]);
|
|
166
|
+
}
|
|
167
|
+
for (let i = 0; i < record.openQuestions.length; i++) {
|
|
168
|
+
await client.query("INSERT INTO markers (session_id, kind, text, position) VALUES ($1, 'open', $2, $3)", [record.id, record.openQuestions[i].trim(), i]);
|
|
169
|
+
}
|
|
170
|
+
for (const raw of record.entities) {
|
|
171
|
+
const name = raw.trim();
|
|
172
|
+
if (!name)
|
|
173
|
+
continue;
|
|
174
|
+
await client.query(`INSERT INTO entities (canonical, type, status, source, first_seen_session, last_seen_session, session_count)
|
|
175
|
+
VALUES ($1, 'candidate', 'candidate', 'auto-detected', $2, $2, 0)
|
|
176
|
+
ON CONFLICT (canonical) DO UPDATE SET
|
|
177
|
+
last_seen_session = $2,
|
|
178
|
+
session_count = entities.session_count + 1,
|
|
179
|
+
updated_at = NOW()`, [name, record.id]);
|
|
180
|
+
await client.query("INSERT INTO session_entities (session_id, entity_canonical) VALUES ($1, $2) ON CONFLICT DO NOTHING", [record.id, name]);
|
|
181
|
+
}
|
|
182
|
+
if (supersedes) {
|
|
183
|
+
await client.query(`INSERT INTO session_edges (from_session, to_session, kind)
|
|
184
|
+
VALUES ($1, $2, 'supersedes') ON CONFLICT DO NOTHING`, [record.id, supersedes]);
|
|
185
|
+
await client.query("UPDATE sessions SET status = 'superseded', updated_at = NOW() WHERE id = $1", [supersedes]);
|
|
186
|
+
}
|
|
187
|
+
await client.query("COMMIT");
|
|
188
|
+
}
|
|
189
|
+
catch (err) {
|
|
190
|
+
await client.query("ROLLBACK");
|
|
191
|
+
throw err;
|
|
192
|
+
}
|
|
193
|
+
finally {
|
|
194
|
+
client.release();
|
|
195
|
+
}
|
|
196
|
+
if (embedder) {
|
|
197
|
+
const chunks = chunkSessionText({ label: record.label, summary: record.summary, body: record.body });
|
|
198
|
+
await this.pool.query("DELETE FROM session_embedding_chunks WHERE session_id = $1", [record.id]);
|
|
199
|
+
for (let chunkIdx = 0; chunkIdx < chunks.length; chunkIdx++) {
|
|
200
|
+
const text = chunks[chunkIdx];
|
|
201
|
+
if (!text)
|
|
202
|
+
continue;
|
|
203
|
+
try {
|
|
204
|
+
const { vector } = await embedder.embed(text, "document");
|
|
205
|
+
const vecStr = `[${Array.from(vector).join(",")}]`;
|
|
206
|
+
const ins = await this.pool.query(`INSERT INTO session_embedding_chunks (session_id, chunk_idx, embedding)
|
|
207
|
+
VALUES ($1, $2, $3::vector) RETURNING chunk_id`, [record.id, chunkIdx, vecStr]);
|
|
208
|
+
const chunkId = ins.rows[0].chunk_id;
|
|
209
|
+
await this.pool.query("INSERT INTO session_chunk_map (chunk_id, session_id, chunk_idx) VALUES ($1, $2, $3)", [chunkId, record.id, chunkIdx]);
|
|
210
|
+
}
|
|
211
|
+
catch (err) {
|
|
212
|
+
process.stderr.write(`[nlm] embedding chunk failed session=${record.id} chunk=${chunkIdx}: ${String(err)}\n`);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
async insertSessionForTest(session) {
|
|
218
|
+
const status = session.status === "idle" ? "active" : session.status;
|
|
219
|
+
await this.pool.query(`INSERT INTO sessions (id, runtime, runtime_session_id, started_at, ended_at,
|
|
220
|
+
duration_min, label, summary, body, status, transcript_kind, transcript_path)
|
|
221
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)`, [
|
|
222
|
+
session.id, session.runtime, session.runtimeSessionId, session.startedAt,
|
|
223
|
+
session.endedAt, session.durationMin, session.label, session.summary,
|
|
224
|
+
session.body, status, session.transcriptKind, session.transcriptPath,
|
|
225
|
+
]);
|
|
226
|
+
for (const e of session.entities) {
|
|
227
|
+
await this.pool.query("INSERT INTO entities (canonical, type, status) VALUES ($1, 'candidate', 'active') ON CONFLICT DO NOTHING", [e]);
|
|
228
|
+
await this.pool.query("INSERT INTO session_entities (session_id, entity_canonical) VALUES ($1, $2) ON CONFLICT DO NOTHING", [session.id, e]);
|
|
229
|
+
}
|
|
230
|
+
for (let i = 0; i < session.decisions.length; i++) {
|
|
231
|
+
await this.pool.query("INSERT INTO markers (session_id, kind, text, position) VALUES ($1, 'decision', $2, $3)", [session.id, session.decisions[i], i]);
|
|
232
|
+
}
|
|
233
|
+
for (let i = 0; i < session.open.length; i++) {
|
|
234
|
+
await this.pool.query("INSERT INTO markers (session_id, kind, text, position) VALUES ($1, 'open', $2, $3)", [session.id, session.open[i], i]);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
async loadEntities(ids) {
|
|
238
|
+
if (ids.length === 0)
|
|
239
|
+
return new Map();
|
|
240
|
+
const placeholders = ids.map((_, i) => `$${i + 1}`).join(",");
|
|
241
|
+
const result = await this.pool.query(`SELECT session_id, entity_canonical FROM session_entities
|
|
242
|
+
WHERE session_id IN (${placeholders}) ORDER BY session_id`, [...ids]);
|
|
243
|
+
const out = new Map();
|
|
244
|
+
for (const r of result.rows) {
|
|
245
|
+
const list = out.get(r.session_id);
|
|
246
|
+
if (list)
|
|
247
|
+
list.push(r.entity_canonical);
|
|
248
|
+
else
|
|
249
|
+
out.set(r.session_id, [r.entity_canonical]);
|
|
250
|
+
}
|
|
251
|
+
return out;
|
|
252
|
+
}
|
|
253
|
+
async loadMarkers(ids) {
|
|
254
|
+
if (ids.length === 0)
|
|
255
|
+
return new Map();
|
|
256
|
+
const placeholders = ids.map((_, i) => `$${i + 1}`).join(",");
|
|
257
|
+
const result = await this.pool.query(`SELECT session_id, kind, text FROM markers
|
|
258
|
+
WHERE session_id IN (${placeholders}) ORDER BY session_id, position`, [...ids]);
|
|
259
|
+
const out = new Map();
|
|
260
|
+
for (const r of result.rows) {
|
|
261
|
+
let bucket = out.get(r.session_id);
|
|
262
|
+
if (!bucket) {
|
|
263
|
+
bucket = { decisions: [], open: [] };
|
|
264
|
+
out.set(r.session_id, bucket);
|
|
265
|
+
}
|
|
266
|
+
if (r.kind === "decision")
|
|
267
|
+
bucket.decisions.push(r.text);
|
|
268
|
+
else
|
|
269
|
+
bucket.open.push(r.text);
|
|
270
|
+
}
|
|
271
|
+
return out;
|
|
272
|
+
}
|
|
273
|
+
async loadEdges(ids) {
|
|
274
|
+
if (ids.length === 0)
|
|
275
|
+
return new Map();
|
|
276
|
+
const placeholders = ids.map((_, i) => `$${i + 1}`).join(",");
|
|
277
|
+
const result = await this.pool.query(`SELECT from_session, to_session FROM session_edges
|
|
278
|
+
WHERE kind = 'supersedes'
|
|
279
|
+
AND (from_session IN (${placeholders}) OR to_session IN (${placeholders}))`, [...ids, ...ids]);
|
|
280
|
+
const out = new Map();
|
|
281
|
+
for (const id of ids)
|
|
282
|
+
out.set(id, { supersededBy: null, supersedes: [] });
|
|
283
|
+
for (const r of result.rows) {
|
|
284
|
+
out.get(r.from_session)?.supersedes.push(r.to_session);
|
|
285
|
+
const toEntry = out.get(r.to_session);
|
|
286
|
+
if (toEntry)
|
|
287
|
+
toEntry.supersededBy = r.from_session;
|
|
288
|
+
}
|
|
289
|
+
return out;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
function rowToSession(row, entitiesById, markersById, edges) {
|
|
293
|
+
const m = markersById.get(row.id);
|
|
294
|
+
return {
|
|
295
|
+
id: row.id,
|
|
296
|
+
runtime: row.runtime,
|
|
297
|
+
runtimeSessionId: row.runtime_session_id ?? "",
|
|
298
|
+
startedAt: row.started_at,
|
|
299
|
+
endedAt: row.ended_at,
|
|
300
|
+
durationMin: row.duration_min,
|
|
301
|
+
label: row.label,
|
|
302
|
+
summary: row.summary,
|
|
303
|
+
status: row.status,
|
|
304
|
+
transcriptKind: row.transcript_kind ?? "",
|
|
305
|
+
transcriptPath: row.transcript_path,
|
|
306
|
+
body: row.body ?? "",
|
|
307
|
+
entities: entitiesById.get(row.id) ?? [],
|
|
308
|
+
decisions: m?.decisions ?? [],
|
|
309
|
+
open: m?.open ?? [],
|
|
310
|
+
...(edges !== undefined
|
|
311
|
+
? { supersededBy: edges.supersededBy, supersedes: edges.supersedes }
|
|
312
|
+
: {}),
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
//# sourceMappingURL=pg-session-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pg-session-store.js","sourceRoot":"","sources":["../../../src/core/storage/pg-session-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PgStorage — canonical Storage adapter for PostgreSQL + pgvector.
|
|
3
|
+
*
|
|
4
|
+
* Implements the Storage port (init/close/withTransaction). withTransaction
|
|
5
|
+
* uses the write-queue pattern: the sync callback queues SQL ops, then
|
|
6
|
+
* PgStorage flushes the queue inside a single BEGIN/COMMIT after the
|
|
7
|
+
* callback returns.
|
|
8
|
+
*
|
|
9
|
+
* pgPool() is a deprecated escape hatch for callers not yet ported to the
|
|
10
|
+
* Storage interface. Tracked for removal in #215a (PG branch).
|
|
11
|
+
*/
|
|
12
|
+
import { Pool } from "pg";
|
|
13
|
+
import type { Storage, StorageContext } from "../../ports/storage.js";
|
|
14
|
+
import { PgFactStore } from "./pg-fact-store.js";
|
|
15
|
+
import { PgSessionStore } from "./pg-session-store.js";
|
|
16
|
+
export interface PgStorageOptions {
|
|
17
|
+
readonly connectionString: string;
|
|
18
|
+
readonly migrationsDir: string;
|
|
19
|
+
}
|
|
20
|
+
export declare class PgStorage implements Storage {
|
|
21
|
+
readonly facts: PgFactStore;
|
|
22
|
+
readonly sessions: PgSessionStore;
|
|
23
|
+
private readonly _pool;
|
|
24
|
+
private readonly _migrationsDir;
|
|
25
|
+
private inTxn;
|
|
26
|
+
private constructor();
|
|
27
|
+
static create(opts: PgStorageOptions): PgStorage;
|
|
28
|
+
init(): Promise<void>;
|
|
29
|
+
close(): Promise<void>;
|
|
30
|
+
withTransaction<T>(fn: (ctx: StorageContext) => T): Promise<T>;
|
|
31
|
+
/**
|
|
32
|
+
* @deprecated Escape hatch for callers not yet ported to the Storage
|
|
33
|
+
* interface. Tracked for removal in #215a (PG branch).
|
|
34
|
+
*/
|
|
35
|
+
pgPool(): Pool;
|
|
36
|
+
}
|