11import type { Database } from "bun:sqlite" ;
22
3+ type PreparedStatement = ReturnType < Database [ "prepare" ] > ;
4+
5+ const insertCompartmentStatements = new WeakMap < Database , PreparedStatement > ( ) ;
6+ const insertFactStatements = new WeakMap < Database , PreparedStatement > ( ) ;
7+
8+ function getInsertCompartmentStatement ( db : Database ) : PreparedStatement {
9+ let stmt = insertCompartmentStatements . get ( db ) ;
10+ if ( ! stmt ) {
11+ stmt = db . prepare (
12+ "INSERT INTO compartments (session_id, sequence, start_message, end_message, start_message_id, end_message_id, title, content, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)" ,
13+ ) ;
14+ insertCompartmentStatements . set ( db , stmt ) ;
15+ }
16+ return stmt ;
17+ }
18+
19+ function getInsertFactStatement ( db : Database ) : PreparedStatement {
20+ let stmt = insertFactStatements . get ( db ) ;
21+ if ( ! stmt ) {
22+ stmt = db . prepare (
23+ "INSERT INTO session_facts (session_id, category, content, created_at, updated_at) VALUES (?, ?, ?, ?, ?)" ,
24+ ) ;
25+ insertFactStatements . set ( db , stmt ) ;
26+ }
27+ return stmt ;
28+ }
29+
330export interface Compartment {
431 id : number ;
532 sessionId : string ;
@@ -84,6 +111,40 @@ export interface CompartmentInput {
84111 content : string ;
85112}
86113
114+ function insertCompartmentRows (
115+ db : Database ,
116+ sessionId : string ,
117+ compartments : CompartmentInput [ ] ,
118+ now : number ,
119+ ) : void {
120+ const stmt = getInsertCompartmentStatement ( db ) ;
121+ for ( const compartment of compartments ) {
122+ stmt . run (
123+ sessionId ,
124+ compartment . sequence ,
125+ compartment . startMessage ,
126+ compartment . endMessage ,
127+ compartment . startMessageId ,
128+ compartment . endMessageId ,
129+ compartment . title ,
130+ compartment . content ,
131+ now ,
132+ ) ;
133+ }
134+ }
135+
136+ function insertFactRows (
137+ db : Database ,
138+ sessionId : string ,
139+ facts : Array < { category : string ; content : string } > ,
140+ now : number ,
141+ ) : void {
142+ const stmt = getInsertFactStatement ( db ) ;
143+ for ( const fact of facts ) {
144+ stmt . run ( sessionId , fact . category , fact . content , now , now ) ;
145+ }
146+ }
147+
87148function toCompartment ( row : CompartmentRow ) : Compartment {
88149 return {
89150 id : row . id ,
@@ -135,22 +196,7 @@ export function replaceAllCompartments(
135196 const now = Date . now ( ) ;
136197 db . transaction ( ( ) => {
137198 db . prepare ( "DELETE FROM compartments WHERE session_id = ?" ) . run ( sessionId ) ;
138- const stmt = db . prepare (
139- "INSERT INTO compartments (session_id, sequence, start_message, end_message, start_message_id, end_message_id, title, content, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)" ,
140- ) ;
141- for ( const c of compartments ) {
142- stmt . run (
143- sessionId ,
144- c . sequence ,
145- c . startMessage ,
146- c . endMessage ,
147- c . startMessageId ,
148- c . endMessageId ,
149- c . title ,
150- c . content ,
151- now ,
152- ) ;
153- }
199+ insertCompartmentRows ( db , sessionId , compartments , now ) ;
154200 } ) ( ) ;
155201}
156202
@@ -167,22 +213,7 @@ export function appendCompartments(
167213 if ( compartments . length === 0 ) return ;
168214 const now = Date . now ( ) ;
169215 db . transaction ( ( ) => {
170- const stmt = db . prepare (
171- "INSERT INTO compartments (session_id, sequence, start_message, end_message, start_message_id, end_message_id, title, content, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)" ,
172- ) ;
173- for ( const c of compartments ) {
174- stmt . run (
175- sessionId ,
176- c . sequence ,
177- c . startMessage ,
178- c . endMessage ,
179- c . startMessageId ,
180- c . endMessageId ,
181- c . title ,
182- c . content ,
183- now ,
184- ) ;
185- }
216+ insertCompartmentRows ( db , sessionId , compartments , now ) ;
186217 } ) ( ) ;
187218}
188219
@@ -199,12 +230,7 @@ export function replaceSessionFacts(
199230 const now = Date . now ( ) ;
200231 db . transaction ( ( ) => {
201232 db . prepare ( "DELETE FROM session_facts WHERE session_id = ?" ) . run ( sessionId ) ;
202- const stmt = db . prepare (
203- "INSERT INTO session_facts (session_id, category, content, created_at, updated_at) VALUES (?, ?, ?, ?, ?)" ,
204- ) ;
205- for ( const f of facts ) {
206- stmt . run ( sessionId , f . category , f . content , now , now ) ;
207- }
233+ insertFactRows ( db , sessionId , facts , now ) ;
208234 // Clear cached memory block so next injection renders fresh
209235 db . prepare (
210236 "UPDATE session_meta SET memory_block_cache = '', memory_block_count = 0 WHERE session_id = ?" ,
@@ -231,29 +257,8 @@ export function replaceAllCompartmentState(
231257 db . prepare ( "DELETE FROM compartments WHERE session_id = ?" ) . run ( sessionId ) ;
232258 db . prepare ( "DELETE FROM session_facts WHERE session_id = ?" ) . run ( sessionId ) ;
233259
234- const compartmentStmt = db . prepare (
235- "INSERT INTO compartments (session_id, sequence, start_message, end_message, start_message_id, end_message_id, title, content, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)" ,
236- ) ;
237- for ( const c of compartments ) {
238- compartmentStmt . run (
239- sessionId ,
240- c . sequence ,
241- c . startMessage ,
242- c . endMessage ,
243- c . startMessageId ,
244- c . endMessageId ,
245- c . title ,
246- c . content ,
247- now ,
248- ) ;
249- }
250-
251- const factStmt = db . prepare (
252- "INSERT INTO session_facts (session_id, category, content, created_at, updated_at) VALUES (?, ?, ?, ?, ?)" ,
253- ) ;
254- for ( const f of facts ) {
255- factStmt . run ( sessionId , f . category , f . content , now , now ) ;
256- }
260+ insertCompartmentRows ( db , sessionId , compartments , now ) ;
261+ insertFactRows ( db , sessionId , facts , now ) ;
257262
258263 // Clear cached memory block so next injection renders fresh (historian run already busts cache)
259264 db . prepare (
@@ -401,29 +406,8 @@ export function promoteRecompStaging(
401406 db . prepare ( "DELETE FROM compartments WHERE session_id = ?" ) . run ( sessionId ) ;
402407 db . prepare ( "DELETE FROM session_facts WHERE session_id = ?" ) . run ( sessionId ) ;
403408
404- const compartmentStmt = db . prepare (
405- "INSERT INTO compartments (session_id, sequence, start_message, end_message, start_message_id, end_message_id, title, content, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)" ,
406- ) ;
407- for ( const c of staging . compartments ) {
408- compartmentStmt . run (
409- sessionId ,
410- c . sequence ,
411- c . startMessage ,
412- c . endMessage ,
413- c . startMessageId ,
414- c . endMessageId ,
415- c . title ,
416- c . content ,
417- now ,
418- ) ;
419- }
420-
421- const factStmt = db . prepare (
422- "INSERT INTO session_facts (session_id, category, content, created_at, updated_at) VALUES (?, ?, ?, ?, ?)" ,
423- ) ;
424- for ( const f of staging . facts ) {
425- factStmt . run ( sessionId , f . category , f . content , now , now ) ;
426- }
409+ insertCompartmentRows ( db , sessionId , staging . compartments , now ) ;
410+ insertFactRows ( db , sessionId , staging . facts , now ) ;
427411
428412 // Clear staging
429413 db . prepare ( "DELETE FROM recomp_compartments WHERE session_id = ?" ) . run ( sessionId ) ;
0 commit comments