nlm-memory 0.5.17 → 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.
Files changed (74) hide show
  1. package/README.md +22 -1
  2. package/dist/cli/nlm.js +161 -81
  3. package/dist/cli/nlm.js.map +1 -1
  4. package/dist/cli/supersede.js +5 -2
  5. package/dist/cli/supersede.js.map +1 -1
  6. package/dist/core/actions/actions-log.d.ts +9 -0
  7. package/dist/core/actions/actions-log.js +86 -0
  8. package/dist/core/actions/actions-log.js.map +1 -1
  9. package/dist/core/digest/compose.d.ts +0 -1
  10. package/dist/core/digest/compose.js +0 -4
  11. package/dist/core/digest/compose.js.map +1 -1
  12. package/dist/core/providers/provider-registry.d.ts +15 -0
  13. package/dist/core/providers/provider-registry.js +85 -0
  14. package/dist/core/providers/provider-registry.js.map +1 -1
  15. package/dist/core/recall/query-log.d.ts +1 -2
  16. package/dist/core/recall/query-log.js +1 -5
  17. package/dist/core/recall/query-log.js.map +1 -1
  18. package/dist/core/scheduler/scan-once.d.ts +4 -0
  19. package/dist/core/scheduler/scan-once.js +64 -0
  20. package/dist/core/scheduler/scan-once.js.map +1 -1
  21. package/dist/core/scheduler/scheduler.js +25 -9
  22. package/dist/core/scheduler/scheduler.js.map +1 -1
  23. package/dist/core/sources/source-registry.d.ts +16 -0
  24. package/dist/core/sources/source-registry.js +123 -0
  25. package/dist/core/sources/source-registry.js.map +1 -1
  26. package/dist/core/storage/pg-fact-store.d.ts +24 -0
  27. package/dist/core/storage/pg-fact-store.js +233 -0
  28. package/dist/core/storage/pg-fact-store.js.map +1 -0
  29. package/dist/core/storage/pg-session-store.d.ts +29 -0
  30. package/dist/core/storage/pg-session-store.js +315 -0
  31. package/dist/core/storage/pg-session-store.js.map +1 -0
  32. package/dist/core/storage/pg-storage.d.ts +36 -0
  33. package/dist/core/storage/pg-storage.js +87 -0
  34. package/dist/core/storage/pg-storage.js.map +1 -0
  35. package/dist/core/storage/pg-tx-context.d.ts +44 -0
  36. package/dist/core/storage/pg-tx-context.js +133 -0
  37. package/dist/core/storage/pg-tx-context.js.map +1 -0
  38. package/dist/core/storage/sqlite-fact-store.d.ts +13 -7
  39. package/dist/core/storage/sqlite-fact-store.js +38 -12
  40. package/dist/core/storage/sqlite-fact-store.js.map +1 -1
  41. package/dist/core/storage/sqlite-session-store.d.ts +6 -16
  42. package/dist/core/storage/sqlite-session-store.js +51 -42
  43. package/dist/core/storage/sqlite-session-store.js.map +1 -1
  44. package/dist/core/storage/sqlite-storage.d.ts +38 -0
  45. package/dist/core/storage/sqlite-storage.js +66 -0
  46. package/dist/core/storage/sqlite-storage.js.map +1 -0
  47. package/dist/hook/pi-extension.d.ts +43 -0
  48. package/dist/hook/pi-extension.js +50 -0
  49. package/dist/hook/pi-extension.js.map +1 -0
  50. package/dist/hook/prompt-recall-hook.js +1 -36
  51. package/dist/hook/prompt-recall-hook.js.map +1 -1
  52. package/dist/hook/recall-over-http.d.ts +10 -0
  53. package/dist/hook/recall-over-http.js +41 -0
  54. package/dist/hook/recall-over-http.js.map +1 -0
  55. package/dist/hook/stop-hook.d.ts +1 -3
  56. package/dist/hook/stop-hook.js +1 -3
  57. package/dist/hook/stop-hook.js.map +1 -1
  58. package/dist/http/app.d.ts +6 -5
  59. package/dist/http/app.js +15 -4
  60. package/dist/http/app.js.map +1 -1
  61. package/dist/install/pi.d.ts +42 -0
  62. package/dist/install/pi.js +84 -0
  63. package/dist/install/pi.js.map +1 -0
  64. package/dist/install/setup.js +21 -5
  65. package/dist/install/setup.js.map +1 -1
  66. package/dist/ports/fact-store.d.ts +26 -0
  67. package/dist/ports/storage.d.ts +45 -0
  68. package/dist/ports/storage.js +14 -0
  69. package/dist/ports/storage.js.map +1 -0
  70. package/package.json +5 -1
  71. package/plugin/scripts/prompt-recall-hook.mjs +31 -29
  72. package/plugin-pi/README.md +71 -0
  73. package/plugin-pi/package.json +12 -0
  74. package/plugin-pi/scripts/nlm-extension.mjs +280 -0
@@ -0,0 +1,87 @@
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 { readFileSync } from "node:fs";
14
+ import { join } from "node:path";
15
+ import { PgFactStore } from "./pg-fact-store.js";
16
+ import { PgSessionStore } from "./pg-session-store.js";
17
+ import { PgTxBoundFactStore, PgTxBoundSessionStore } from "./pg-tx-context.js";
18
+ export class PgStorage {
19
+ facts;
20
+ sessions;
21
+ _pool;
22
+ _migrationsDir;
23
+ // Guards against re-entrant (synchronous) nesting only. Not concurrent-call-safe.
24
+ inTxn = false;
25
+ constructor(pool, migrationsDir) {
26
+ this._pool = pool;
27
+ this._migrationsDir = migrationsDir;
28
+ this.facts = new PgFactStore(pool);
29
+ this.sessions = new PgSessionStore(pool);
30
+ }
31
+ static create(opts) {
32
+ const pool = new Pool({ connectionString: opts.connectionString });
33
+ return new PgStorage(pool, opts.migrationsDir);
34
+ }
35
+ async init() {
36
+ const sql = readFileSync(join(this._migrationsDir, "001_initial.sql"), "utf8");
37
+ await this._pool.query(sql);
38
+ }
39
+ async close() {
40
+ await this._pool.end();
41
+ }
42
+ async withTransaction(fn) {
43
+ if (this.inTxn) {
44
+ throw new Error("PgStorage.withTransaction does not support nesting");
45
+ }
46
+ this.inTxn = true;
47
+ const queue = [];
48
+ const txFacts = new PgTxBoundFactStore(queue);
49
+ const txSessions = new PgTxBoundSessionStore(queue);
50
+ const ctx = { facts: txFacts, sessions: txSessions };
51
+ let result;
52
+ try {
53
+ result = fn(ctx);
54
+ }
55
+ catch (err) {
56
+ this.inTxn = false;
57
+ throw err;
58
+ }
59
+ this.inTxn = false;
60
+ if (queue.length > 0) {
61
+ const client = await this._pool.connect();
62
+ try {
63
+ await client.query("BEGIN");
64
+ for (const op of queue) {
65
+ await client.query(op.sql, op.params);
66
+ }
67
+ await client.query("COMMIT");
68
+ }
69
+ catch (err) {
70
+ await client.query("ROLLBACK");
71
+ throw err;
72
+ }
73
+ finally {
74
+ client.release();
75
+ }
76
+ }
77
+ return result;
78
+ }
79
+ /**
80
+ * @deprecated Escape hatch for callers not yet ported to the Storage
81
+ * interface. Tracked for removal in #215a (PG branch).
82
+ */
83
+ pgPool() {
84
+ return this._pool;
85
+ }
86
+ }
87
+ //# sourceMappingURL=pg-storage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pg-storage.js","sourceRoot":"","sources":["../../../src/core/storage/pg-storage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,IAAI,CAAC;AAC1B,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,qBAAqB,EAAiB,MAAM,oBAAoB,CAAC;AAO9F,MAAM,OAAO,SAAS;IACX,KAAK,CAAc;IACnB,QAAQ,CAAiB;IACjB,KAAK,CAAO;IACZ,cAAc,CAAS;IACxC,kFAAkF;IAC1E,KAAK,GAAG,KAAK,CAAC;IAEtB,YAAoB,IAAU,EAAE,aAAqB;QACnD,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAClB,IAAI,CAAC,cAAc,GAAG,aAAa,CAAC;QACpC,IAAI,CAAC,KAAK,GAAG,IAAI,WAAW,CAAC,IAAI,CAAC,CAAC;QACnC,IAAI,CAAC,QAAQ,GAAG,IAAI,cAAc,CAAC,IAAI,CAAC,CAAC;IAC3C,CAAC;IAED,MAAM,CAAC,MAAM,CAAC,IAAsB;QAClC,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,EAAE,gBAAgB,EAAE,IAAI,CAAC,gBAAgB,EAAE,CAAC,CAAC;QACnE,OAAO,IAAI,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;IACjD,CAAC;IAED,KAAK,CAAC,IAAI;QACR,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,iBAAiB,CAAC,EAAE,MAAM,CAAC,CAAC;QAC/E,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC9B,CAAC;IAED,KAAK,CAAC,KAAK;QACT,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,eAAe,CAAI,EAA8B;QACrD,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;QACxE,CAAC;QACD,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAClB,MAAM,KAAK,GAAe,EAAE,CAAC;QAC7B,MAAM,OAAO,GAAG,IAAI,kBAAkB,CAAC,KAAK,CAAC,CAAC;QAC9C,MAAM,UAAU,GAAG,IAAI,qBAAqB,CAAC,KAAK,CAAC,CAAC;QACpD,MAAM,GAAG,GAAmB,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC;QACrE,IAAI,MAAS,CAAC;QACd,IAAI,CAAC;YACH,MAAM,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC;QACnB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;YACnB,MAAM,GAAG,CAAC;QACZ,CAAC;QACD,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACrB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;YAC1C,IAAI,CAAC;gBACH,MAAM,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;gBAC5B,KAAK,MAAM,EAAE,IAAI,KAAK,EAAE,CAAC;oBACvB,MAAM,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,MAAmB,CAAC,CAAC;gBACrD,CAAC;gBACD,MAAM,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;YAC/B,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;gBAC/B,MAAM,GAAG,CAAC;YACZ,CAAC;oBAAS,CAAC;gBACT,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,CAAC;QACH,CAAC;QACD,OAAO,MAAO,CAAC;IACjB,CAAC;IAED;;;OAGG;IACH,MAAM;QACJ,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;CACF"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * PgTxContext — write-queue for PgStorage.withTransaction.
3
+ *
4
+ * PgStorage.withTransaction requires a sync callback (port contract). PG
5
+ * transactions are async. Bridge: sync callback queues SQL ops; PgStorage
6
+ * flushes the queue in one BEGIN/COMMIT after the callback returns.
7
+ *
8
+ * Read methods throw — they cannot see uncommitted queue state. The
9
+ * FactStore/SessionStore contracts never read inside withTransaction.
10
+ */
11
+ import type { FactListFilter, FactQuery, FactSemanticNeighbor, FactStore } from "../../ports/fact-store.js";
12
+ import type { KeywordNeighbor, SemanticNeighbor, SessionFilter, SessionStore } from "../../ports/session-store.js";
13
+ import type { Fact, FactHistoryChain, Session, SessionStatus } from "../../shared/types.js";
14
+ export interface QueuedOp {
15
+ readonly sql: string;
16
+ readonly params: readonly unknown[];
17
+ }
18
+ export declare class PgTxBoundFactStore implements FactStore {
19
+ private readonly q;
20
+ constructor(q: QueuedOp[]);
21
+ insert(fact: Fact): Promise<void>;
22
+ insertMany(facts: ReadonlyArray<Fact>): Promise<void>;
23
+ markSuperseded(oldId: string, newId: string | null): Promise<void>;
24
+ ingestSessionFacts(sessionId: string, facts: ReadonlyArray<Fact>): Promise<void>;
25
+ upsertEmbedding(factId: string, vector: Float32Array): Promise<void>;
26
+ getById(_id: string): Promise<Fact | null>;
27
+ findCurrent(_s: string, _p: string): Promise<Fact | null>;
28
+ list(_q: FactQuery): Promise<ReadonlyArray<Fact>>;
29
+ listBySession(_id: string): Promise<ReadonlyArray<Fact>>;
30
+ listForRecall(_f: FactListFilter): Promise<ReadonlyArray<Fact>>;
31
+ semanticSearch(_v: Float32Array, _n: number): Promise<ReadonlyArray<FactSemanticNeighbor>>;
32
+ getHistory(_s: string, _p?: string): Promise<ReadonlyArray<FactHistoryChain>>;
33
+ }
34
+ export declare class PgTxBoundSessionStore implements SessionStore {
35
+ private readonly q;
36
+ constructor(q: QueuedOp[]);
37
+ updateStatus(sessionId: string, status: SessionStatus): Promise<void>;
38
+ markSuperseded(predecessorId: string, successorId: string): Promise<void>;
39
+ list(_filter?: SessionFilter): Promise<ReadonlyArray<Session>>;
40
+ getById(_id: string): Promise<Session | null>;
41
+ getByIds(_ids: ReadonlyArray<string>): Promise<ReadonlyArray<Session>>;
42
+ semanticSearch(_v: Float32Array, _n: number): Promise<ReadonlyArray<SemanticNeighbor>>;
43
+ keywordSearch(_q: string, _n: number): Promise<ReadonlyArray<KeywordNeighbor>>;
44
+ }
@@ -0,0 +1,133 @@
1
+ /**
2
+ * PgTxContext — write-queue for PgStorage.withTransaction.
3
+ *
4
+ * PgStorage.withTransaction requires a sync callback (port contract). PG
5
+ * transactions are async. Bridge: sync callback queues SQL ops; PgStorage
6
+ * flushes the queue in one BEGIN/COMMIT after the callback returns.
7
+ *
8
+ * Read methods throw — they cannot see uncommitted queue state. The
9
+ * FactStore/SessionStore contracts never read inside withTransaction.
10
+ */
11
+ function noRead(method) {
12
+ throw new Error(`PgStorage.withTransaction: ${method} read not supported inside sync callback`);
13
+ }
14
+ export class PgTxBoundFactStore {
15
+ q;
16
+ constructor(q) {
17
+ this.q = q;
18
+ }
19
+ insert(fact) {
20
+ this.q.push(insertFactOp(fact));
21
+ return Promise.resolve();
22
+ }
23
+ insertMany(facts) {
24
+ for (const f of facts)
25
+ this.q.push(insertFactOp(f));
26
+ return Promise.resolve();
27
+ }
28
+ markSuperseded(oldId, newId) {
29
+ this.q.push({
30
+ sql: "UPDATE facts SET superseded_by = $1 WHERE id = $2",
31
+ params: [newId, oldId],
32
+ });
33
+ return Promise.resolve();
34
+ }
35
+ ingestSessionFacts(sessionId, facts) {
36
+ this.q.push({
37
+ sql: "DELETE FROM facts WHERE source_session_id = $1",
38
+ params: [sessionId],
39
+ });
40
+ for (const f of facts)
41
+ this.q.push(insertFactOp(f));
42
+ if (facts.length > 0) {
43
+ const values = facts
44
+ .map((_, i) => `($${i * 3 + 1}, $${i * 3 + 2}, $${i * 3 + 3})`)
45
+ .join(", ");
46
+ const params = [];
47
+ for (const f of facts)
48
+ params.push(f.subject, f.predicate, f.id);
49
+ this.q.push({
50
+ sql: `
51
+ UPDATE facts AS old
52
+ SET superseded_by = new_f.new_id
53
+ FROM (VALUES ${values}) AS new_f(subject, predicate, new_id)
54
+ WHERE old.subject = new_f.subject
55
+ AND old.predicate = new_f.predicate
56
+ AND old.superseded_by IS NULL
57
+ AND old.id != new_f.new_id
58
+ `,
59
+ params,
60
+ });
61
+ }
62
+ return Promise.resolve();
63
+ }
64
+ upsertEmbedding(factId, vector) {
65
+ this.q.push({
66
+ sql: `
67
+ INSERT INTO fact_embeddings (fact_id, embedding)
68
+ VALUES ($1, $2)
69
+ ON CONFLICT (fact_id) DO UPDATE SET embedding = EXCLUDED.embedding
70
+ `,
71
+ params: [factId, `[${Array.from(vector).join(",")}]`],
72
+ });
73
+ return Promise.resolve();
74
+ }
75
+ getById(_id) { return noRead("FactStore.getById"); }
76
+ findCurrent(_s, _p) { return noRead("FactStore.findCurrent"); }
77
+ list(_q) { return noRead("FactStore.list"); }
78
+ listBySession(_id) { return noRead("FactStore.listBySession"); }
79
+ listForRecall(_f) { return noRead("FactStore.listForRecall"); }
80
+ semanticSearch(_v, _n) { return noRead("FactStore.semanticSearch"); }
81
+ getHistory(_s, _p) { return noRead("FactStore.getHistory"); }
82
+ }
83
+ export class PgTxBoundSessionStore {
84
+ q;
85
+ constructor(q) {
86
+ this.q = q;
87
+ }
88
+ updateStatus(sessionId, status) {
89
+ if (status === "idle") {
90
+ throw new Error("Cannot persist derived status 'idle'");
91
+ }
92
+ this.q.push({
93
+ sql: "UPDATE sessions SET status = $1, updated_at = NOW() WHERE id = $2",
94
+ params: [status, sessionId],
95
+ });
96
+ return Promise.resolve();
97
+ }
98
+ markSuperseded(predecessorId, successorId) {
99
+ this.q.push({
100
+ sql: `
101
+ INSERT INTO session_edges (from_session, to_session, kind)
102
+ VALUES ($1, $2, 'supersedes')
103
+ ON CONFLICT DO NOTHING
104
+ `,
105
+ params: [successorId, predecessorId],
106
+ });
107
+ this.q.push({
108
+ sql: "UPDATE sessions SET status = 'superseded', updated_at = NOW() WHERE id = $1",
109
+ params: [predecessorId],
110
+ });
111
+ return Promise.resolve();
112
+ }
113
+ list(_filter) { return noRead("SessionStore.list"); }
114
+ getById(_id) { return noRead("SessionStore.getById"); }
115
+ getByIds(_ids) { return noRead("SessionStore.getByIds"); }
116
+ semanticSearch(_v, _n) { return noRead("SessionStore.semanticSearch"); }
117
+ keywordSearch(_q, _n) { return noRead("SessionStore.keywordSearch"); }
118
+ }
119
+ function insertFactOp(f) {
120
+ return {
121
+ sql: `
122
+ INSERT INTO facts (
123
+ id, kind, subject, predicate, value, source_session_id,
124
+ source_quote, created_at, superseded_by, confidence
125
+ ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
126
+ `,
127
+ params: [
128
+ f.id, f.kind, f.subject, f.predicate, f.value,
129
+ f.sourceSessionId, f.sourceQuote, f.createdAt, f.supersededBy, f.confidence,
130
+ ],
131
+ };
132
+ }
133
+ //# sourceMappingURL=pg-tx-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pg-tx-context.js","sourceRoot":"","sources":["../../../src/core/storage/pg-tx-context.ts"],"names":[],"mappings":"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"}
@@ -10,7 +10,7 @@
10
10
  *
11
11
  * Surface evolution:
12
12
  * B.1 — insert, getById, findCurrent, list, listBySession, markSuperseded
13
- * B.2 — insertManyInTxn (atomic session+facts ingest), embedding write helper
13
+ * B.2: ingestSessionFacts (atomic session+facts ingest), embedding write helper
14
14
  * B.3 — listForRecall (pre-filter for FactRecallService), semanticSearch,
15
15
  * getHistory (supersedence chain inspection)
16
16
  * B.4 — auto-supersedence on (subject, predicate) collision (deferred)
@@ -20,16 +20,21 @@ import type { FactListFilter, FactQuery, FactSemanticNeighbor, FactStore } from
20
20
  import type { Fact, FactHistoryChain } from "../../shared/types.js";
21
21
  export declare class SqliteFactStore implements FactStore {
22
22
  private readonly db;
23
+ /**
24
+ * @internal. Construct via SqliteStorage.create(...) instead. Direct
25
+ * construction is preserved for the SqliteStorage adapter only; all
26
+ * other callers should reach FactStore via storage.facts.
27
+ */
23
28
  constructor(db: Database.Database);
24
29
  insert(fact: Fact): Promise<void>;
25
30
  insertMany(facts: ReadonlyArray<Fact>): Promise<void>;
26
31
  /**
27
- * Insert facts inside an already-open transaction (no own txn opened).
28
- * Callable only from code that has already begun a transaction on the same
29
- * connection — currently SqliteSessionStore.insertSession. Phase B.2: this
30
- * is how session+facts ingest commits atomically (Section 5 of the plan).
32
+ * @internal. Sync row insert for use inside an already-open better-sqlite3
33
+ * transaction. Used only by SqliteSessionStore's inlined ingest blocks
34
+ * (which require sync execution inside the txn callback). External callers
35
+ * use insertMany() or ingestSessionFacts() via Storage.withTransaction.
31
36
  */
32
- insertManyInTxn(facts: ReadonlyArray<Fact>): void;
37
+ insertRowInTxn(fact: Fact): void;
33
38
  getById(id: string): Promise<Fact | null>;
34
39
  findCurrent(subject: string, predicate: string): Promise<Fact | null>;
35
40
  list(query: FactQuery): Promise<ReadonlyArray<Fact>>;
@@ -42,8 +47,9 @@ export declare class SqliteFactStore implements FactStore {
42
47
  * trap embedder errors so an unreachable Ollama doesn't roll back ingest.
43
48
  * vec0 doesn't UPDATE, so this is a DELETE+INSERT pair.
44
49
  */
45
- upsertEmbedding(factId: string, vector: Float32Array): void;
50
+ upsertEmbedding(factId: string, vector: Float32Array): Promise<void>;
46
51
  markSuperseded(oldId: string, newId: string | null): Promise<void>;
52
+ ingestSessionFacts(sessionId: string, facts: ReadonlyArray<Fact>): Promise<void>;
47
53
  private insertStmt;
48
54
  private toRow;
49
55
  private rowToFact;
@@ -10,13 +10,18 @@
10
10
  *
11
11
  * Surface evolution:
12
12
  * B.1 — insert, getById, findCurrent, list, listBySession, markSuperseded
13
- * B.2 — insertManyInTxn (atomic session+facts ingest), embedding write helper
13
+ * B.2: ingestSessionFacts (atomic session+facts ingest), embedding write helper
14
14
  * B.3 — listForRecall (pre-filter for FactRecallService), semanticSearch,
15
15
  * getHistory (supersedence chain inspection)
16
16
  * B.4 — auto-supersedence on (subject, predicate) collision (deferred)
17
17
  */
18
18
  export class SqliteFactStore {
19
19
  db;
20
+ /**
21
+ * @internal. Construct via SqliteStorage.create(...) instead. Direct
22
+ * construction is preserved for the SqliteStorage adapter only; all
23
+ * other callers should reach FactStore via storage.facts.
24
+ */
20
25
  constructor(db) {
21
26
  this.db = db;
22
27
  }
@@ -34,17 +39,13 @@ export class SqliteFactStore {
34
39
  txn(facts.map((f) => this.toRow(f)));
35
40
  }
36
41
  /**
37
- * Insert facts inside an already-open transaction (no own txn opened).
38
- * Callable only from code that has already begun a transaction on the same
39
- * connection — currently SqliteSessionStore.insertSession. Phase B.2: this
40
- * is how session+facts ingest commits atomically (Section 5 of the plan).
42
+ * @internal. Sync row insert for use inside an already-open better-sqlite3
43
+ * transaction. Used only by SqliteSessionStore's inlined ingest blocks
44
+ * (which require sync execution inside the txn callback). External callers
45
+ * use insertMany() or ingestSessionFacts() via Storage.withTransaction.
41
46
  */
42
- insertManyInTxn(facts) {
43
- if (facts.length === 0)
44
- return;
45
- const stmt = this.insertStmt();
46
- for (const f of facts)
47
- stmt.run(this.toRow(f));
47
+ insertRowInTxn(fact) {
48
+ this.insertStmt().run(this.toRow(fact));
48
49
  }
49
50
  async getById(id) {
50
51
  const row = this.db
@@ -183,7 +184,7 @@ export class SqliteFactStore {
183
184
  * trap embedder errors so an unreachable Ollama doesn't roll back ingest.
184
185
  * vec0 doesn't UPDATE, so this is a DELETE+INSERT pair.
185
186
  */
186
- upsertEmbedding(factId, vector) {
187
+ async upsertEmbedding(factId, vector) {
187
188
  const blob = Buffer.from(vector.buffer, vector.byteOffset, vector.byteLength);
188
189
  this.db.prepare("DELETE FROM fact_embeddings WHERE fact_id = ?").run(factId);
189
190
  this.db
@@ -213,6 +214,31 @@ export class SqliteFactStore {
213
214
  });
214
215
  txn();
215
216
  }
217
+ async ingestSessionFacts(sessionId, facts) {
218
+ this.db.prepare("DELETE FROM facts WHERE source_session_id = ?").run(sessionId);
219
+ if (facts.length === 0)
220
+ return;
221
+ const insertStmt = this.insertStmt();
222
+ for (const f of facts)
223
+ insertStmt.run(this.toRow(f));
224
+ const findCollisionStmt = this.db.prepare(`
225
+ SELECT id
226
+ FROM facts
227
+ WHERE subject = ?
228
+ AND predicate = ?
229
+ AND superseded_by IS NULL
230
+ AND id != ?
231
+ ORDER BY created_at DESC
232
+ LIMIT 1
233
+ `);
234
+ const markSupersededStmt = this.db.prepare("UPDATE facts SET superseded_by = ? WHERE id = ?");
235
+ for (const f of facts) {
236
+ const collision = findCollisionStmt.get(f.subject, f.predicate, f.id);
237
+ if (collision && collision.id !== f.id) {
238
+ markSupersededStmt.run(f.id, collision.id);
239
+ }
240
+ }
241
+ }
216
242
  insertStmt() {
217
243
  return this.db.prepare(`
218
244
  INSERT INTO facts (
@@ -1 +1 @@
1
- {"version":3,"file":"sqlite-fact-store.js","sourceRoot":"","sources":["../../../src/core/storage/sqlite-fact-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AA0BH,MAAM,OAAO,eAAe;IACG;IAA7B,YAA6B,EAAqB;QAArB,OAAE,GAAF,EAAE,CAAmB;IAAG,CAAC;IAEtD,KAAK,CAAC,MAAM,CAAC,IAAU;QACrB,IAAI,CAAC,UAAU,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;IAC1C,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,KAA0B;QACzC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QAC/B,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;QAC/B,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,IAA4B,EAAE,EAAE;YAC/D,KAAK,MAAM,GAAG,IAAI,IAAI;gBAAE,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACxC,CAAC,CAAC,CAAC;QACH,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACvC,CAAC;IAED;;;;;OAKG;IACH,eAAe,CAAC,KAA0B;QACxC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QAC/B,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;QAC/B,KAAK,MAAM,CAAC,IAAI,KAAK;YAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACjD,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,EAAU;QACtB,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE;aAChB,OAAO,CACN;;iCAEyB,CAC1B;aACA,GAAG,CAAC,EAAE,CAAC,CAAC;QACX,OAAO,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC1C,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,OAAe,EAAE,SAAiB;QAClD,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE;aAChB,OAAO,CACN;;;;;iBAKS,CACV;aACA,GAAG,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QAC3B,OAAO,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC1C,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;QAE3D,MAAM,KAAK,GAAa,CAAC,aAAa,CAAC,CAAC;QACxC,MAAM,MAAM,GAA2B,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACvD,IAAI,KAAK,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;YAClC,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;YAC5B,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;QAEnB,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE;aACjB,OAAO,CACN;;;iBAGS,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC;;iBAEnB,CACV;aACA,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC;QAClB,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5C,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,SAAiB;QACnC,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE;aACjB,OAAO,CACN;;;;iCAIyB,CAC1B;aACA,GAAG,CAAC,SAAS,CAAC,CAAC;QAClB,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5C,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,MAAsB;QACxC,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,MAAM,MAAM,GAA2B,EAAE,CAAC;QAC1C,IAAI,MAAM,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;YACjC,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YAC1B,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC9B,CAAC;QACD,IAAI,MAAM,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;YACnC,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;YAC5B,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAChC,CAAC;QACD,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC9B,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACvB,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC3B,CAAC;QACD,IAAI,MAAM,CAAC,aAAa,KAAK,SAAS,EAAE,CAAC;YACvC,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;YAC9B,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;QACpC,CAAC;QACD,IAAI,MAAM,CAAC,iBAAiB,KAAK,IAAI,EAAE,CAAC;YACtC,KAAK,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;QACtC,CAAC;QACD,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;;;KAGzD,CAAC;QACF,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE;aACjB,OAAO,CAAkC,GAAG,CAAC;aAC7C,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC;QAClB,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5C,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,IAAI,GAAG,MAAM,CAAC,IAAI,CACtB,WAAW,CAAC,MAAM,EAClB,WAAW,CAAC,UAAU,EACtB,WAAW,CAAC,UAAU,CACvB,CAAC;QACF,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE;aACjB,OAAO,CAAgC;;;;;;OAMvC,CAAC;aACD,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QAChB,OAAO,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;IACxE,CAAC;IAED,KAAK,CAAC,UAAU,CACd,OAAe,EACf,SAAkB;QAElB,MAAM,GAAG,GAAG,SAAS;YACnB,CAAC,CAAC;;;;iDAIyC;YAC3C,CAAC,CAAC;;;;iDAIyC,CAAC;QAC9C,MAAM,IAAI,GAAG,SAAS;YACpB,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAA4B,GAAG,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,SAAS,CAAC;YACzE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAoB,GAAG,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAEzD,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;QACzC,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;YACrB,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;YAC/B,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,MAAM,MAAM,GAAuB,EAAE,CAAC;QACtC,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC;YAC/C,MAAM,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;QACrD,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;;OAIG;IACH,eAAe,CAAC,MAAc,EAAE,MAAoB;QAClD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;QAC9E,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,+CAA+C,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC7E,IAAI,CAAC,EAAE;aACJ,OAAO,CAAC,gEAAgE,CAAC;aACzE,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACvB,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,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE;YACnC,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE;iBAChB,OAAO,CAA2B,mCAAmC,CAAC;iBACtE,GAAG,CAAC,KAAK,CAAC,CAAC;YACd,IAAI,CAAC,GAAG;gBAAE,MAAM,IAAI,KAAK,CAAC,QAAQ,KAAK,YAAY,CAAC,CAAC;YACrD,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;gBACnB,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE;qBACjB,OAAO,CAA2B,mCAAmC,CAAC;qBACtE,GAAG,CAAC,KAAK,CAAC,CAAC;gBACd,IAAI,CAAC,IAAI;oBAAE,MAAM,IAAI,KAAK,CAAC,QAAQ,KAAK,YAAY,CAAC,CAAC;YACxD,CAAC;YACD,IAAI,CAAC,EAAE;iBACJ,OAAO,CAAC,iDAAiD,CAAC;iBAC1D,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QACvB,CAAC,CAAC,CAAC;QACH,GAAG,EAAE,CAAC;IACR,CAAC;IAEO,UAAU;QAChB,OAAO,IAAI,CAAC,EAAE,CAAC,OAAO,CAAU;;;;;;;;KAQ/B,CAAC,CAAC;IACL,CAAC;IAEO,KAAK,CAAC,IAAU;QACtB,OAAO;YACL,EAAE,EAAE,IAAI,CAAC,EAAE;YACX,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,iBAAiB,EAAE,IAAI,CAAC,eAAe;YACvC,YAAY,EAAE,IAAI,CAAC,WAAW;YAC9B,UAAU,EAAE,IAAI,CAAC,SAAS;YAC1B,aAAa,EAAE,IAAI,CAAC,YAAY;YAChC,UAAU,EAAE,IAAI,CAAC,UAAU;SAC5B,CAAC;IACJ,CAAC;IAEO,SAAS,CAAC,GAAY;QAC5B,OAAO;YACL,EAAE,EAAE,GAAG,CAAC,EAAE;YACV,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,OAAO,EAAE,GAAG,CAAC,OAAO;YACpB,SAAS,EAAE,GAAG,CAAC,SAAS;YACxB,KAAK,EAAE,GAAG,CAAC,KAAK;YAChB,eAAe,EAAE,GAAG,CAAC,iBAAiB;YACtC,WAAW,EAAE,GAAG,CAAC,YAAY;YAC7B,SAAS,EAAE,GAAG,CAAC,UAAU;YACzB,YAAY,EAAE,GAAG,CAAC,aAAa;YAC/B,UAAU,EAAE,GAAG,CAAC,UAAU;SAC3B,CAAC;IACJ,CAAC;CACF"}
1
+ {"version":3,"file":"sqlite-fact-store.js","sourceRoot":"","sources":["../../../src/core/storage/sqlite-fact-store.ts"],"names":[],"mappings":"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"}
@@ -57,6 +57,11 @@ export interface RecentMarker {
57
57
  }
58
58
  export declare class SqliteSessionStore implements SessionStore {
59
59
  private readonly db;
60
+ /**
61
+ * @internal. Construct via SqliteStorage.create(...) instead. Direct
62
+ * construction is preserved for the SqliteStorage adapter only; all
63
+ * other callers should reach SessionStore via storage.sessions.
64
+ */
60
65
  constructor(opts: SqliteSessionStoreOptions);
61
66
  close(): void;
62
67
  /**
@@ -102,22 +107,6 @@ export declare class SqliteSessionStore implements SessionStore {
102
107
  * internal helpers directly so session+facts commit together.
103
108
  */
104
109
  insertFactsForSession(sessionId: string, factStore: SqliteFactStore, facts: ReadonlyArray<Fact>, embedder?: import("../../ports/llm-client.js").LLMClient | null): Promise<void>;
105
- /**
106
- * Sync core of the fact-ingest block. Runs inside an EXISTING transaction
107
- * — opens no txn of its own. Used by both `insertSession` (Phase B.2
108
- * atomic ingest) and `insertFactsForSession` (Phase B.5 backfill).
109
- *
110
- * Behavior (mirrored across both callers):
111
- * 1. DELETE prior facts attributed to this session (idempotent on
112
- * backfill, drops stale rows on re-ingest).
113
- * 2. Insert all new facts atomically.
114
- * 3. For each, mark the prior current (subject, predicate) fact as
115
- * superseded — Phase B.4 deterministic supersedence policy.
116
- *
117
- * Ordering: inserts before updates so the supersedence FK target exists.
118
- * CASCADE-SET-NULL on `superseded_by` handles chain repair on re-ingest.
119
- */
120
- private applyFactsInTxn;
121
110
  /**
122
111
  * Best-effort per-fact embedding. Writes `${subject} ${predicate} ${value}`
123
112
  * embeddings to fact_embeddings via FactStore.upsertEmbedding. Per-fact
@@ -144,6 +133,7 @@ export declare class SqliteSessionStore implements SessionStore {
144
133
  keywordSearch(query: string, limit: number): Promise<ReadonlyArray<KeywordNeighbor>>;
145
134
  updateStatus(sessionId: string, status: SessionStatus): Promise<void>;
146
135
  markSuperseded(predecessorId: string, successorId: string): Promise<void>;
136
+ /** @internal test-only helper; production callers use insertSession(). */
147
137
  insertSessionForTest(session: Session): void;
148
138
  insertEdgeForTest(fromSession: string, toSession: string, kind?: "supersedes" | "continues"): void;
149
139
  insertEmbeddingForTest(sessionId: string, vector: Float32Array): void;
@@ -22,6 +22,11 @@ import { tokenize } from "../recall/tokenize.js";
22
22
  import { chunkSessionText } from "../embedding/chunk-body.js";
23
23
  export class SqliteSessionStore {
24
24
  db;
25
+ /**
26
+ * @internal. Construct via SqliteStorage.create(...) instead. Direct
27
+ * construction is preserved for the SqliteStorage adapter only; all
28
+ * other callers should reach SessionStore via storage.sessions.
29
+ */
25
30
  constructor(opts) {
26
31
  const dbPath = resolve(opts.dbPath);
27
32
  const parent = dirname(dbPath);
@@ -158,7 +163,7 @@ export class SqliteSessionStore {
158
163
  // carries new provenance (new source_session_id) and is informative
159
164
  // history. See Section 2 of factstore-design.md.
160
165
  //
161
- // Ordering note: insertManyInTxn FIRST so the new fact id exists in
166
+ // Ordering note: inserts FIRST so the new fact id exists in
162
167
  // facts(id) before any UPDATE sets superseded_by = newId (the FK
163
168
  // would reject otherwise). The DELETE above plus the CASCADE-SET-NULL
164
169
  // on superseded_by means re-ingest naturally repairs chains: if an
@@ -166,7 +171,30 @@ export class SqliteSessionStore {
166
171
  // session, deleting our prior fact unlinks the chain; the loop below
167
172
  // re-establishes it with the freshly-inserted row.
168
173
  if (factSink !== null) {
169
- this.applyFactsInTxn(record.id, factSink.factStore, factSink.facts);
174
+ // Inlined ingest. See SqliteFactStore.ingestSessionFacts for the
175
+ // backend-agnostic version. SqliteSessionStore runs this synchronously
176
+ // inside the better-sqlite3 txn callback (which must be sync). The
177
+ // logic mirrors the port method exactly; if you change one, change
178
+ // the other. Tracked as a known duplication for the SQLite adapter.
179
+ const db = this.db;
180
+ db.prepare("DELETE FROM facts WHERE source_session_id = ?").run(record.id);
181
+ if (factSink.facts.length > 0) {
182
+ const factStoreImpl = factSink.factStore;
183
+ for (const f of factSink.facts)
184
+ factStoreImpl.insertRowInTxn(f);
185
+ const findCollisionStmt = db.prepare(`
186
+ SELECT id FROM facts
187
+ WHERE subject = ? AND predicate = ? AND superseded_by IS NULL AND id != ?
188
+ ORDER BY created_at DESC LIMIT 1
189
+ `);
190
+ const markSupersededStmt = db.prepare("UPDATE facts SET superseded_by = ? WHERE id = ?");
191
+ for (const f of factSink.facts) {
192
+ const collision = findCollisionStmt.get(f.subject, f.predicate, f.id);
193
+ if (collision && collision.id !== f.id) {
194
+ markSupersededStmt.run(f.id, collision.id);
195
+ }
196
+ }
197
+ }
170
198
  }
171
199
  });
172
200
  txn();
@@ -239,51 +267,31 @@ export class SqliteSessionStore {
239
267
  async insertFactsForSession(sessionId, factStore, facts, embedder = null) {
240
268
  const db = this.db;
241
269
  const txn = db.transaction(() => {
242
- this.applyFactsInTxn(sessionId, factStore, facts);
270
+ // Inlined ingest. Same logic as SqliteFactStore.ingestSessionFacts.
271
+ // Sync because better-sqlite3 txn callbacks must be sync.
272
+ db.prepare("DELETE FROM facts WHERE source_session_id = ?").run(sessionId);
273
+ if (facts.length > 0) {
274
+ for (const f of facts)
275
+ factStore.insertRowInTxn(f);
276
+ const findCollisionStmt = db.prepare(`
277
+ SELECT id FROM facts
278
+ WHERE subject = ? AND predicate = ? AND superseded_by IS NULL AND id != ?
279
+ ORDER BY created_at DESC LIMIT 1
280
+ `);
281
+ const markSupersededStmt = db.prepare("UPDATE facts SET superseded_by = ? WHERE id = ?");
282
+ for (const f of facts) {
283
+ const collision = findCollisionStmt.get(f.subject, f.predicate, f.id);
284
+ if (collision && collision.id !== f.id) {
285
+ markSupersededStmt.run(f.id, collision.id);
286
+ }
287
+ }
288
+ }
243
289
  });
244
290
  txn();
245
291
  if (embedder) {
246
292
  await this.embedFacts(factStore, facts, embedder);
247
293
  }
248
294
  }
249
- /**
250
- * Sync core of the fact-ingest block. Runs inside an EXISTING transaction
251
- * — opens no txn of its own. Used by both `insertSession` (Phase B.2
252
- * atomic ingest) and `insertFactsForSession` (Phase B.5 backfill).
253
- *
254
- * Behavior (mirrored across both callers):
255
- * 1. DELETE prior facts attributed to this session (idempotent on
256
- * backfill, drops stale rows on re-ingest).
257
- * 2. Insert all new facts atomically.
258
- * 3. For each, mark the prior current (subject, predicate) fact as
259
- * superseded — Phase B.4 deterministic supersedence policy.
260
- *
261
- * Ordering: inserts before updates so the supersedence FK target exists.
262
- * CASCADE-SET-NULL on `superseded_by` handles chain repair on re-ingest.
263
- */
264
- applyFactsInTxn(sessionId, factStore, facts) {
265
- const db = this.db;
266
- db.prepare("DELETE FROM facts WHERE source_session_id = ?").run(sessionId);
267
- factStore.insertManyInTxn(facts);
268
- if (facts.length === 0)
269
- return;
270
- const findCollisionStmt = db.prepare(`
271
- SELECT id
272
- FROM facts
273
- WHERE subject = ?
274
- AND predicate = ?
275
- AND superseded_by IS NULL
276
- AND id != ?
277
- ORDER BY created_at DESC
278
- LIMIT 1
279
- `);
280
- const markSupersededStmt = db.prepare("UPDATE facts SET superseded_by = ? WHERE id = ?");
281
- for (const fact of facts) {
282
- const prior = findCollisionStmt.get(fact.subject, fact.predicate, fact.id);
283
- if (prior)
284
- markSupersededStmt.run(fact.id, prior.id);
285
- }
286
- }
287
295
  /**
288
296
  * Best-effort per-fact embedding. Writes `${subject} ${predicate} ${value}`
289
297
  * embeddings to fact_embeddings via FactStore.upsertEmbedding. Per-fact
@@ -296,7 +304,7 @@ export class SqliteSessionStore {
296
304
  continue;
297
305
  try {
298
306
  const { vector } = await embedder.embed(factText, "document");
299
- factStore.upsertEmbedding(fact.id, vector);
307
+ await factStore.upsertEmbedding(fact.id, vector);
300
308
  }
301
309
  catch {
302
310
  // Per-fact embedding failure must not abort embedding of subsequent
@@ -482,6 +490,7 @@ export class SqliteSessionStore {
482
490
  txn();
483
491
  }
484
492
  // ── insert helpers used by tests / future ingest path ─────────────────
493
+ /** @internal test-only helper; production callers use insertSession(). */
485
494
  insertSessionForTest(session) {
486
495
  const stmt = this.db.prepare(`
487
496
  INSERT INTO sessions (