@codemcp/workflows-core 3.1.21-fix-build-after-monorepo.0 → 3.1.21

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.
@@ -1,4 +1,4 @@
1
1
 
2
- > @codemcp/workflows-core@3.1.21-fix-build-after-monorepo.0 build /home/runner/work/responsible-vibe-mcp/responsible-vibe-mcp/packages/core
2
+ > @codemcp/workflows-core@3.1.21 build /home/runner/work/responsible-vibe-mcp/responsible-vibe-mcp/packages/core
3
3
  > tsc -p tsconfig.build.json
4
4
 
@@ -2,7 +2,7 @@
2
2
  * Database Manager
3
3
  *
4
4
  * Handles SQLite database operations for conversation state persistence.
5
- * Uses better-sqlite3 for reliable cross-platform native bindings.
5
+ * Uses @sqlite.org/sqlite-wasm for reliable cross-platform WebAssembly bindings.
6
6
  */
7
7
  import type { ConversationState, InteractionLog } from './types.js';
8
8
  /**
@@ -10,12 +10,21 @@ import type { ConversationState, InteractionLog } from './types.js';
10
10
  */
11
11
  export declare class Database {
12
12
  private db;
13
+ private sqlite3;
13
14
  private dbPath;
14
15
  constructor(dbPath: string);
15
16
  /**
16
17
  * Initialize database connection and create tables
17
18
  */
18
19
  initialize(): Promise<void>;
20
+ /**
21
+ * Load database content from file
22
+ */
23
+ private loadFromFile;
24
+ /**
25
+ * Save database content to file
26
+ */
27
+ private saveToFile;
19
28
  /**
20
29
  * Create database tables if they don't exist
21
30
  */
@@ -25,39 +34,39 @@ export declare class Database {
25
34
  */
26
35
  saveConversationState(state: ConversationState): Promise<void>;
27
36
  /**
28
- * Load conversation state from database
29
- */
30
- loadConversationState(conversationId: string): Promise<ConversationState | null>;
31
- /**
32
- * Get conversation state by ID (alias for loadConversationState)
37
+ * Get conversation state by ID
33
38
  */
34
39
  getConversationState(conversationId: string): Promise<ConversationState | null>;
35
40
  /**
36
- * List all conversation states
41
+ * Get all conversation states
37
42
  */
38
- listConversationStates(): Promise<ConversationState[]>;
43
+ getAllConversationStates(): Promise<ConversationState[]>;
39
44
  /**
40
45
  * Delete conversation state
41
46
  */
42
47
  deleteConversationState(conversationId: string): Promise<boolean>;
43
48
  /**
44
- * Log an interaction to the database
49
+ * Log interaction
45
50
  */
46
51
  logInteraction(log: InteractionLog): Promise<void>;
47
52
  /**
48
- * Get interactions by conversation ID
53
+ * Get interaction logs for a conversation
54
+ */
55
+ getInteractionLogs(conversationId: string): Promise<InteractionLog[]>;
56
+ /**
57
+ * Get interaction logs for a conversation (alias for compatibility)
49
58
  */
50
59
  getInteractionsByConversationId(conversationId: string): Promise<InteractionLog[]>;
51
60
  /**
52
- * Soft delete interaction logs by marking them as reset
61
+ * Soft delete interaction logs (for compatibility - actually deletes them)
53
62
  */
54
63
  softDeleteInteractionLogs(conversationId: string): Promise<void>;
55
64
  /**
56
- * Close database connection
65
+ * Reset conversation state (for testing)
57
66
  */
58
- close(): Promise<void>;
67
+ resetConversationState(conversationId: string): Promise<void>;
59
68
  /**
60
- * Check if database is initialized
69
+ * Close database connection
61
70
  */
62
- isInitialized(): boolean;
71
+ close(): Promise<void>;
63
72
  }
package/dist/database.js CHANGED
@@ -2,9 +2,9 @@
2
2
  * Database Manager
3
3
  *
4
4
  * Handles SQLite database operations for conversation state persistence.
5
- * Uses better-sqlite3 for reliable cross-platform native bindings.
5
+ * Uses @sqlite.org/sqlite-wasm for reliable cross-platform WebAssembly bindings.
6
6
  */
7
- import BetterSqlite3 from 'better-sqlite3';
7
+ import sqlite3InitModule from '@sqlite.org/sqlite-wasm';
8
8
  import { mkdir } from 'node:fs/promises';
9
9
  import { dirname } from 'node:path';
10
10
  import { createLogger } from './logger.js';
@@ -14,6 +14,7 @@ const logger = createLogger('Database');
14
14
  */
15
15
  export class Database {
16
16
  db = null;
17
+ sqlite3 = null;
17
18
  dbPath;
18
19
  constructor(dbPath) {
19
20
  this.dbPath = dbPath;
@@ -23,15 +24,19 @@ export class Database {
23
24
  */
24
25
  async initialize() {
25
26
  try {
26
- // Ensure directory exists
27
- const dbDir = dirname(this.dbPath);
28
- await mkdir(dbDir, { recursive: true });
29
- logger.debug('Database directory ensured', { dbDir });
30
- // Create database connection
31
- this.db = new BetterSqlite3(this.dbPath);
32
- logger.debug('Database connection established');
27
+ // Initialize SQLite WASM
28
+ this.sqlite3 = await sqlite3InitModule();
29
+ // Always use in-memory database (sqlite-wasm Node.js limitation)
30
+ this.db = new this.sqlite3.oo1.DB();
31
+ logger.debug('Database connection established (in-memory)', {
32
+ originalPath: this.dbPath,
33
+ });
33
34
  // Create tables
34
35
  await this.createTables();
36
+ // Load existing data from file if it exists
37
+ if (this.dbPath !== ':memory:' && this.dbPath) {
38
+ await this.loadFromFile();
39
+ }
35
40
  logger.info('Database initialized successfully', { dbPath: this.dbPath });
36
41
  }
37
42
  catch (error) {
@@ -39,6 +44,76 @@ export class Database {
39
44
  throw error;
40
45
  }
41
46
  }
47
+ /**
48
+ * Load database content from file
49
+ */
50
+ async loadFromFile() {
51
+ if (!this.db || !this.dbPath || this.dbPath === ':memory:') {
52
+ return;
53
+ }
54
+ try {
55
+ const { readFile, access } = await import('node:fs/promises');
56
+ await access(this.dbPath);
57
+ const data = await readFile(this.dbPath);
58
+ if (data.length > 0) {
59
+ // Close current in-memory DB and create new one from file data
60
+ this.db.close();
61
+ // Create new DB and deserialize data into it
62
+ //eslint-disable-next-line @typescript-eslint/no-non-null-assertion
63
+ this.db = new this.sqlite3.oo1.DB();
64
+ if (!this.db.pointer) {
65
+ throw new Error('Failed to create database');
66
+ }
67
+ // Convert Buffer to Uint8Array
68
+ const uint8Data = new Uint8Array(data);
69
+ //eslint-disable-next-line @typescript-eslint/no-non-null-assertion
70
+ const wasmPtr = this.sqlite3.wasm.allocFromTypedArray(uint8Data);
71
+ //eslint-disable-next-line @typescript-eslint/no-non-null-assertion
72
+ this.sqlite3.capi.sqlite3_deserialize(this.db.pointer, 'main', wasmPtr, data.length, data.length, 0x01 // SQLITE_DESERIALIZE_FREEONCLOSE
73
+ );
74
+ logger.debug('Loaded database from file', {
75
+ dbPath: this.dbPath,
76
+ size: data.length,
77
+ });
78
+ }
79
+ }
80
+ catch {
81
+ // File doesn't exist - that's OK for new databases
82
+ logger.debug('No existing database file to load', {
83
+ dbPath: this.dbPath,
84
+ });
85
+ }
86
+ }
87
+ /**
88
+ * Save database content to file
89
+ */
90
+ async saveToFile() {
91
+ if (!this.db || !this.dbPath || this.dbPath === ':memory:') {
92
+ return;
93
+ }
94
+ try {
95
+ const { writeFile } = await import('node:fs/promises');
96
+ const dbDir = dirname(this.dbPath);
97
+ await mkdir(dbDir, { recursive: true });
98
+ // Export database to Uint8Array and save to file
99
+ if (!this.db.pointer) {
100
+ throw new Error('Database pointer is invalid');
101
+ }
102
+ //eslint-disable-next-line @typescript-eslint/no-non-null-assertion
103
+ const data = this.sqlite3.capi.sqlite3_js_db_export(this.db.pointer);
104
+ await writeFile(this.dbPath, data);
105
+ logger.debug('Saved database to file', {
106
+ dbPath: this.dbPath,
107
+ size: data.length,
108
+ });
109
+ }
110
+ catch (error) {
111
+ logger.warn('Failed to save database to file', {
112
+ error: error,
113
+ dbPath: this.dbPath,
114
+ });
115
+ }
116
+ }
42
117
  /**
43
118
  * Create database tables if they don't exist
44
119
  */
@@ -69,14 +144,12 @@ export class Database {
69
144
  responseData TEXT NOT NULL,
70
145
  currentPhase TEXT NOT NULL,
71
146
  timestamp TEXT NOT NULL,
72
- isReset INTEGER DEFAULT 0,
73
- resetAt TEXT,
74
147
  FOREIGN KEY (conversationId) REFERENCES conversation_state(conversationId)
75
148
  )
76
149
  `;
77
150
  this.db.exec(createConversationStateTable);
78
151
  this.db.exec(createInteractionLogTable);
79
- logger.debug('Tables created successfully');
152
+ logger.debug('Database tables created');
80
153
  }
81
154
  /**
82
155
  * Save conversation state to database
@@ -85,84 +158,86 @@ export class Database {
85
158
  if (!this.db) {
86
159
  throw new Error('Database not initialized');
87
160
  }
88
- const stmt = this.db.prepare(`
89
- INSERT OR REPLACE INTO conversation_state
90
- (conversationId, projectPath, gitBranch, currentPhase, planFilePath, workflowName,
91
- gitCommitConfig, requireReviewsBeforePhaseTransition, createdAt, updatedAt)
92
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
93
- `);
94
- stmt.run(state.conversationId, state.projectPath, state.gitBranch, state.currentPhase, state.planFilePath, state.workflowName, state.gitCommitConfig ? JSON.stringify(state.gitCommitConfig) : null, state.requireReviewsBeforePhaseTransition ? 1 : 0, state.createdAt, state.updatedAt);
161
+ this.db.exec({
162
+ sql: `INSERT OR REPLACE INTO conversation_state
163
+ (conversationId, projectPath, gitBranch, currentPhase, planFilePath, workflowName,
164
+ gitCommitConfig, requireReviewsBeforePhaseTransition, createdAt, updatedAt)
165
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
166
+ bind: [
167
+ state.conversationId,
168
+ state.projectPath,
169
+ state.gitBranch,
170
+ state.currentPhase,
171
+ state.planFilePath,
172
+ state.workflowName,
173
+ state.gitCommitConfig ? JSON.stringify(state.gitCommitConfig) : null,
174
+ state.requireReviewsBeforePhaseTransition ? 1 : 0,
175
+ state.createdAt,
176
+ state.updatedAt,
177
+ ],
178
+ });
179
+ // Persist to file
180
+ await this.saveToFile();
95
181
  logger.debug('Conversation state saved', {
96
182
  conversationId: state.conversationId,
97
- workflowName: state.workflowName,
98
183
  currentPhase: state.currentPhase,
99
184
  });
100
185
  }
101
186
  /**
102
- * Load conversation state from database
187
+ * Get conversation state by ID
103
188
  */
104
- async loadConversationState(conversationId) {
189
+ async getConversationState(conversationId) {
105
190
  if (!this.db) {
106
191
  throw new Error('Database not initialized');
107
192
  }
108
- const stmt = this.db.prepare('SELECT * FROM conversation_state WHERE conversationId = ?');
109
- const row = stmt.get(conversationId);
110
- if (row) {
111
- const state = {
112
- conversationId: row.conversationId,
113
- projectPath: row.projectPath,
114
- gitBranch: row.gitBranch,
115
- currentPhase: row.currentPhase,
116
- planFilePath: row.planFilePath,
117
- workflowName: row.workflowName,
118
- gitCommitConfig: row.gitCommitConfig
119
- ? JSON.parse(row.gitCommitConfig)
120
- : undefined,
121
- requireReviewsBeforePhaseTransition: row.requireReviewsBeforePhaseTransition === 1,
122
- createdAt: row.createdAt,
123
- updatedAt: row.updatedAt,
124
- };
125
- logger.debug('Conversation state loaded', {
126
- conversationId,
127
- workflowName: state.workflowName,
128
- currentPhase: state.currentPhase,
129
- });
130
- return state;
193
+ const result = this.db.exec({
194
+ sql: 'SELECT * FROM conversation_state WHERE conversationId = ?',
195
+ bind: [conversationId],
196
+ returnValue: 'resultRows',
197
+ });
198
+ if (!result || result.length === 0) {
199
+ return null;
131
200
  }
132
- logger.debug('No conversation state found', { conversationId });
133
- return null;
201
+ const row = result[0];
202
+ return {
203
+ conversationId: row[0],
204
+ projectPath: row[1],
205
+ gitBranch: row[2],
206
+ currentPhase: row[3],
207
+ planFilePath: row[4],
208
+ workflowName: row[5],
209
+ gitCommitConfig: row[6] ? JSON.parse(row[6]) : null,
210
+ requireReviewsBeforePhaseTransition: Boolean(row[7]),
211
+ createdAt: row[8],
212
+ updatedAt: row[9],
213
+ };
134
214
  }
135
215
  /**
136
- * Get conversation state by ID (alias for loadConversationState)
216
+ * Get all conversation states
137
217
  */
138
- async getConversationState(conversationId) {
139
- return this.loadConversationState(conversationId);
140
- }
141
- /**
142
- * List all conversation states
143
- */
144
- async listConversationStates() {
218
+ async getAllConversationStates() {
145
219
  if (!this.db) {
146
220
  throw new Error('Database not initialized');
147
221
  }
148
- const stmt = this.db.prepare('SELECT * FROM conversation_state ORDER BY updatedAt DESC');
149
- const rows = stmt.all();
150
- const states = rows.map(row => ({
151
- conversationId: row.conversationId,
152
- projectPath: row.projectPath,
153
- gitBranch: row.gitBranch,
154
- currentPhase: row.currentPhase,
155
- planFilePath: row.planFilePath,
156
- workflowName: row.workflowName,
157
- gitCommitConfig: row.gitCommitConfig
158
- ? JSON.parse(row.gitCommitConfig)
159
- : undefined,
160
- requireReviewsBeforePhaseTransition: row.requireReviewsBeforePhaseTransition === 1,
161
- createdAt: row.createdAt,
162
- updatedAt: row.updatedAt,
222
+ const result = this.db.exec({
223
+ sql: 'SELECT * FROM conversation_state ORDER BY updatedAt DESC',
224
+ returnValue: 'resultRows',
225
+ });
226
+ if (!result) {
227
+ return [];
228
+ }
229
+ return result.map(row => ({
230
+ conversationId: row[0],
231
+ projectPath: row[1],
232
+ gitBranch: row[2],
233
+ currentPhase: row[3],
234
+ planFilePath: row[4],
235
+ workflowName: row[5],
236
+ gitCommitConfig: row[6] ? JSON.parse(row[6]) : null,
237
+ requireReviewsBeforePhaseTransition: Boolean(row[7]),
238
+ createdAt: row[8],
239
+ updatedAt: row[9],
163
240
  }));
164
- logger.debug('Listed conversation states', { count: states.length });
165
- return states;
166
241
  }
167
242
  /**
168
243
  * Delete conversation state
@@ -171,79 +246,103 @@ export class Database {
171
246
  if (!this.db) {
172
247
  throw new Error('Database not initialized');
173
248
  }
174
- const stmt = this.db.prepare('DELETE FROM conversation_state WHERE conversationId = ?');
175
- const result = stmt.run(conversationId);
176
- const deleted = result.changes > 0;
177
- logger.debug('Conversation state deletion', { conversationId, deleted });
178
- return deleted;
249
+ this.db.exec({
250
+ sql: 'DELETE FROM conversation_state WHERE conversationId = ?',
251
+ bind: [conversationId],
252
+ });
253
+ // Persist to file
254
+ await this.saveToFile();
255
+ logger.debug('Conversation state deleted', { conversationId });
256
+ return true;
179
257
  }
180
258
  /**
181
- * Log an interaction to the database
259
+ * Log interaction
182
260
  */
183
261
  async logInteraction(log) {
184
262
  if (!this.db) {
185
263
  throw new Error('Database not initialized');
186
264
  }
187
- const stmt = this.db.prepare(`
188
- INSERT INTO interaction_log
189
- (conversationId, toolName, inputParams, responseData, currentPhase, timestamp, isReset, resetAt)
190
- VALUES (?, ?, ?, ?, ?, ?, ?, ?)
191
- `);
192
- stmt.run(log.conversationId, log.toolName, log.inputParams, log.responseData, log.currentPhase, log.timestamp, log.isReset ? 1 : 0, log.resetAt || null);
265
+ this.db.exec({
266
+ sql: `INSERT INTO interaction_log
267
+ (conversationId, toolName, inputParams, responseData, currentPhase, timestamp)
268
+ VALUES (?, ?, ?, ?, ?, ?)`,
269
+ bind: [
270
+ log.conversationId,
271
+ log.toolName,
272
+ JSON.stringify(log.inputParams),
273
+ JSON.stringify(log.responseData),
274
+ log.currentPhase,
275
+ log.timestamp,
276
+ ],
277
+ });
278
+ // Persist to file
279
+ await this.saveToFile();
193
280
  logger.debug('Interaction logged', {
194
281
  conversationId: log.conversationId,
195
282
  toolName: log.toolName,
196
- timestamp: log.timestamp,
197
283
  });
198
284
  }
199
285
  /**
200
- * Get interactions by conversation ID
286
+ * Get interaction logs for a conversation
201
287
  */
202
- async getInteractionsByConversationId(conversationId) {
288
+ async getInteractionLogs(conversationId) {
203
289
  if (!this.db) {
204
290
  throw new Error('Database not initialized');
205
291
  }
206
- const stmt = this.db.prepare(`
207
- SELECT * FROM interaction_log
208
- WHERE conversationId = ? AND (isReset = 0 OR isReset IS NULL)
209
- ORDER BY timestamp ASC
210
- `);
211
- const rows = stmt.all(conversationId);
212
- const logs = rows.map(row => ({
213
- id: row.id,
214
- conversationId: row.conversationId,
215
- toolName: row.toolName,
216
- inputParams: row.inputParams,
217
- responseData: row.responseData,
218
- currentPhase: row.currentPhase,
219
- timestamp: row.timestamp,
220
- isReset: row.isReset === 1,
221
- resetAt: row.resetAt,
222
- }));
223
- logger.debug('Retrieved interaction logs', {
224
- conversationId,
225
- count: logs.length,
292
+ const result = this.db.exec({
293
+ sql: 'SELECT * FROM interaction_log WHERE conversationId = ? ORDER BY timestamp ASC',
294
+ bind: [conversationId],
295
+ returnValue: 'resultRows',
226
296
  });
227
- return logs;
297
+ if (!result) {
298
+ return [];
299
+ }
300
+ return result.map(row => ({
301
+ id: row[0],
302
+ conversationId: row[1],
303
+ toolName: row[2],
304
+ inputParams: JSON.parse(row[3]),
305
+ responseData: JSON.parse(row[4]),
306
+ currentPhase: row[5],
307
+ timestamp: row[6],
308
+ }));
309
+ }
310
+ /**
311
+ * Get interaction logs for a conversation (alias for compatibility)
312
+ */
313
+ async getInteractionsByConversationId(conversationId) {
314
+ return this.getInteractionLogs(conversationId);
228
315
  }
229
316
  /**
230
- * Soft delete interaction logs by marking them as reset
317
+ * Soft delete interaction logs (for compatibility - actually deletes them)
231
318
  */
232
319
  async softDeleteInteractionLogs(conversationId) {
320
+ if (!this.db) {
321
+ throw new Error('Database not initialized');
322
+ }
323
+ this.db.exec({
324
+ sql: 'DELETE FROM interaction_log WHERE conversationId = ?',
325
+ bind: [conversationId],
326
+ });
327
+ // Persist to file
328
+ await this.saveToFile();
329
+ logger.debug('Interaction logs deleted', { conversationId });
330
+ }
331
+ /**
332
+ * Reset conversation state (for testing)
333
+ */
334
+ async resetConversationState(conversationId) {
233
335
  if (!this.db) {
234
336
  throw new Error('Database not initialized');
235
337
  }
236
338
  const resetAt = new Date().toISOString();
237
- const stmt = this.db.prepare(`
238
- UPDATE interaction_log
239
- SET isReset = 1, resetAt = ?
240
- WHERE conversationId = ? AND (isReset = 0 OR isReset IS NULL)
241
- `);
242
- const result = stmt.run(resetAt, conversationId);
243
- logger.debug('Soft deleted interaction logs', {
244
- conversationId,
245
- affectedRows: result.changes,
339
+ this.db.exec({
340
+ sql: 'UPDATE conversation_state SET updatedAt = ? WHERE conversationId = ?',
341
+ bind: [resetAt, conversationId],
246
342
  });
343
+ // Persist to file
344
+ await this.saveToFile();
345
+ logger.debug('Conversation state reset', { conversationId, resetAt });
247
346
  }
248
347
  /**
249
348
  * Close database connection
@@ -255,11 +354,5 @@ export class Database {
255
354
  logger.debug('Database connection closed');
256
355
  }
257
356
  }
258
- /**
259
- * Check if database is initialized
260
- */
261
- isInitialized() {
262
- return this.db !== null;
263
- }
264
357
  }
265
358
  //# sourceMappingURL=database.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"database.js","sourceRoot":"","sources":["../src/database.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"database.js","sourceRoot":"","sources":["../src/database.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codemcp/workflows-core",
3
- "version": "3.1.21-fix-build-after-monorepo.0",
3
+ "version": "3.1.21",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",
package/src/database.ts CHANGED
@@ -2,10 +2,13 @@
2
2
  * Database Manager
3
3
  *
4
4
  * Handles SQLite database operations for conversation state persistence.
5
- * Uses better-sqlite3 for reliable cross-platform native bindings.
5
+ * Uses @sqlite.org/sqlite-wasm for reliable cross-platform WebAssembly bindings.
6
6
  */
7
7
 
8
- import BetterSqlite3 from 'better-sqlite3';
8
+ import sqlite3InitModule, {
9
+ type Database as SqliteDatabase,
10
+ type Sqlite3Static,
11
+ } from '@sqlite.org/sqlite-wasm';
9
12
  import { mkdir } from 'node:fs/promises';
10
13
  import { dirname } from 'node:path';
11
14
  import { createLogger } from './logger.js';
@@ -17,7 +20,8 @@ const logger = createLogger('Database');
17
20
  * Database connection and operations manager
18
21
  */
19
22
  export class Database {
20
- private db: BetterSqlite3.Database | null = null;
23
+ private db: SqliteDatabase | null = null;
24
+ private sqlite3: Sqlite3Static | null = null;
21
25
  private dbPath: string;
22
26
 
23
27
  constructor(dbPath: string) {
@@ -29,17 +33,23 @@ export class Database {
29
33
  */
30
34
  async initialize(): Promise<void> {
31
35
  try {
32
- // Ensure directory exists
33
- const dbDir = dirname(this.dbPath);
34
- await mkdir(dbDir, { recursive: true });
35
- logger.debug('Database directory ensured', { dbDir });
36
+ // Initialize SQLite WASM
37
+ this.sqlite3 = await sqlite3InitModule();
36
38
 
37
- // Create database connection
38
- this.db = new BetterSqlite3(this.dbPath);
39
- logger.debug('Database connection established');
39
+ // Always use in-memory database (sqlite-wasm Node.js limitation)
40
+ this.db = new this.sqlite3.oo1.DB();
41
+ logger.debug('Database connection established (in-memory)', {
42
+ originalPath: this.dbPath,
43
+ });
40
44
 
41
45
  // Create tables
42
46
  await this.createTables();
47
+
48
+ // Load existing data from file if it exists
49
+ if (this.dbPath !== ':memory:' && this.dbPath) {
50
+ await this.loadFromFile();
51
+ }
52
+
43
53
  logger.info('Database initialized successfully', { dbPath: this.dbPath });
44
54
  } catch (error) {
45
55
  logger.error('Failed to initialize database', error as Error);
@@ -47,6 +57,90 @@ export class Database {
47
57
  }
48
58
  }
49
59
 
60
+ /**
61
+ * Load database content from file
62
+ */
63
+ private async loadFromFile(): Promise<void> {
64
+ if (!this.db || !this.dbPath || this.dbPath === ':memory:') {
65
+ return;
66
+ }
67
+
68
+ try {
69
+ const { readFile, access } = await import('node:fs/promises');
70
+ await access(this.dbPath);
71
+
72
+ const data = await readFile(this.dbPath);
73
+ if (data.length > 0) {
74
+ // Close current in-memory DB and create new one from file data
75
+ this.db.close();
76
+ // Create new DB and deserialize data into it
77
+
78
+ //eslint-disable-next-line @typescript-eslint/no-non-null-assertion
79
+ this.db = new this.sqlite3!.oo1.DB();
80
+ if (!this.db.pointer) {
81
+ throw new Error('Failed to create database');
82
+ }
83
+
84
+ // Convert Buffer to Uint8Array
85
+ const uint8Data = new Uint8Array(data);
86
+
87
+ //eslint-disable-next-line @typescript-eslint/no-non-null-assertion
88
+ const wasmPtr = this.sqlite3!.wasm.allocFromTypedArray(uint8Data);
89
+
90
+ //eslint-disable-next-line @typescript-eslint/no-non-null-assertion
91
+ this.sqlite3!.capi.sqlite3_deserialize(
92
+ this.db.pointer,
93
+ 'main',
94
+ wasmPtr,
95
+ data.length,
96
+ data.length,
97
+ 0x01 // SQLITE_DESERIALIZE_FREEONCLOSE
98
+ );
99
+ logger.debug('Loaded database from file', {
100
+ dbPath: this.dbPath,
101
+ size: data.length,
102
+ });
103
+ }
104
+ } catch {
105
+ // File doesn't exist - that's OK for new databases
106
+ logger.debug('No existing database file to load', {
107
+ dbPath: this.dbPath,
108
+ });
109
+ }
110
+ }
111
+
112
+ /**
113
+ * Save database content to file
114
+ */
115
+ private async saveToFile(): Promise<void> {
116
+ if (!this.db || !this.dbPath || this.dbPath === ':memory:') {
117
+ return;
118
+ }
119
+
120
+ try {
121
+ const { writeFile } = await import('node:fs/promises');
122
+ const dbDir = dirname(this.dbPath);
123
+ await mkdir(dbDir, { recursive: true });
124
+
125
+ // Export database to Uint8Array and save to file
126
+ if (!this.db.pointer) {
127
+ throw new Error('Database pointer is invalid');
128
+ }
129
+ //eslint-disable-next-line @typescript-eslint/no-non-null-assertion
130
+ const data = this.sqlite3!.capi.sqlite3_js_db_export(this.db.pointer);
131
+ await writeFile(this.dbPath, data);
132
+ logger.debug('Saved database to file', {
133
+ dbPath: this.dbPath,
134
+ size: data.length,
135
+ });
136
+ } catch (error) {
137
+ logger.warn('Failed to save database to file', {
138
+ error: error as Error,
139
+ dbPath: this.dbPath,
140
+ });
141
+ }
142
+ }
143
+
50
144
  /**
51
145
  * Create database tables if they don't exist
52
146
  */
@@ -79,15 +173,14 @@ export class Database {
79
173
  responseData TEXT NOT NULL,
80
174
  currentPhase TEXT NOT NULL,
81
175
  timestamp TEXT NOT NULL,
82
- isReset INTEGER DEFAULT 0,
83
- resetAt TEXT,
84
176
  FOREIGN KEY (conversationId) REFERENCES conversation_state(conversationId)
85
177
  )
86
178
  `;
87
179
 
88
180
  this.db.exec(createConversationStateTable);
89
181
  this.db.exec(createInteractionLogTable);
90
- logger.debug('Tables created successfully');
182
+
183
+ logger.debug('Database tables created');
91
184
  }
92
185
 
93
186
  /**
@@ -98,141 +191,98 @@ export class Database {
98
191
  throw new Error('Database not initialized');
99
192
  }
100
193
 
101
- const stmt = this.db.prepare(`
102
- INSERT OR REPLACE INTO conversation_state
103
- (conversationId, projectPath, gitBranch, currentPhase, planFilePath, workflowName,
104
- gitCommitConfig, requireReviewsBeforePhaseTransition, createdAt, updatedAt)
105
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
106
- `);
107
-
108
- stmt.run(
109
- state.conversationId,
110
- state.projectPath,
111
- state.gitBranch,
112
- state.currentPhase,
113
- state.planFilePath,
114
- state.workflowName,
115
- state.gitCommitConfig ? JSON.stringify(state.gitCommitConfig) : null,
116
- state.requireReviewsBeforePhaseTransition ? 1 : 0,
117
- state.createdAt,
118
- state.updatedAt
119
- );
194
+ this.db.exec({
195
+ sql: `INSERT OR REPLACE INTO conversation_state
196
+ (conversationId, projectPath, gitBranch, currentPhase, planFilePath, workflowName,
197
+ gitCommitConfig, requireReviewsBeforePhaseTransition, createdAt, updatedAt)
198
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
199
+ bind: [
200
+ state.conversationId,
201
+ state.projectPath,
202
+ state.gitBranch,
203
+ state.currentPhase,
204
+ state.planFilePath,
205
+ state.workflowName,
206
+ state.gitCommitConfig ? JSON.stringify(state.gitCommitConfig) : null,
207
+ state.requireReviewsBeforePhaseTransition ? 1 : 0,
208
+ state.createdAt,
209
+ state.updatedAt,
210
+ ],
211
+ });
212
+
213
+ // Persist to file
214
+ await this.saveToFile();
120
215
 
121
216
  logger.debug('Conversation state saved', {
122
217
  conversationId: state.conversationId,
123
- workflowName: state.workflowName,
124
218
  currentPhase: state.currentPhase,
125
219
  });
126
220
  }
127
221
 
128
222
  /**
129
- * Load conversation state from database
223
+ * Get conversation state by ID
130
224
  */
131
- async loadConversationState(
225
+ async getConversationState(
132
226
  conversationId: string
133
227
  ): Promise<ConversationState | null> {
134
228
  if (!this.db) {
135
229
  throw new Error('Database not initialized');
136
230
  }
137
231
 
138
- const stmt = this.db.prepare(
139
- 'SELECT * FROM conversation_state WHERE conversationId = ?'
140
- );
141
- const row = stmt.get(conversationId) as
142
- | {
143
- conversationId: string;
144
- projectPath: string;
145
- gitBranch: string;
146
- currentPhase: string;
147
- planFilePath: string;
148
- workflowName: string;
149
- gitCommitConfig: string;
150
- requireReviewsBeforePhaseTransition: number;
151
- createdAt: string;
152
- updatedAt: string;
153
- }
154
- | undefined;
155
-
156
- if (row) {
157
- const state: ConversationState = {
158
- conversationId: row.conversationId,
159
- projectPath: row.projectPath,
160
- gitBranch: row.gitBranch,
161
- currentPhase: row.currentPhase,
162
- planFilePath: row.planFilePath,
163
- workflowName: row.workflowName,
164
- gitCommitConfig: row.gitCommitConfig
165
- ? JSON.parse(row.gitCommitConfig)
166
- : undefined,
167
- requireReviewsBeforePhaseTransition:
168
- row.requireReviewsBeforePhaseTransition === 1,
169
- createdAt: row.createdAt,
170
- updatedAt: row.updatedAt,
171
- };
172
-
173
- logger.debug('Conversation state loaded', {
174
- conversationId,
175
- workflowName: state.workflowName,
176
- currentPhase: state.currentPhase,
177
- });
178
- return state;
179
- }
232
+ const result = this.db.exec({
233
+ sql: 'SELECT * FROM conversation_state WHERE conversationId = ?',
234
+ bind: [conversationId],
235
+ returnValue: 'resultRows',
236
+ });
180
237
 
181
- logger.debug('No conversation state found', { conversationId });
182
- return null;
183
- }
238
+ if (!result || result.length === 0) {
239
+ return null;
240
+ }
184
241
 
185
- /**
186
- * Get conversation state by ID (alias for loadConversationState)
187
- */
188
- async getConversationState(
189
- conversationId: string
190
- ): Promise<ConversationState | null> {
191
- return this.loadConversationState(conversationId);
242
+ const row = result[0];
243
+ return {
244
+ conversationId: row[0] as string,
245
+ projectPath: row[1] as string,
246
+ gitBranch: row[2] as string,
247
+ currentPhase: row[3] as string,
248
+ planFilePath: row[4] as string,
249
+ workflowName: row[5] as string,
250
+ gitCommitConfig: row[6] ? JSON.parse(row[6] as string) : null,
251
+ requireReviewsBeforePhaseTransition: Boolean(row[7]),
252
+ createdAt: row[8] as string,
253
+ updatedAt: row[9] as string,
254
+ };
192
255
  }
193
256
 
194
257
  /**
195
- * List all conversation states
258
+ * Get all conversation states
196
259
  */
197
- async listConversationStates(): Promise<ConversationState[]> {
260
+ async getAllConversationStates(): Promise<ConversationState[]> {
198
261
  if (!this.db) {
199
262
  throw new Error('Database not initialized');
200
263
  }
201
264
 
202
- const stmt = this.db.prepare(
203
- 'SELECT * FROM conversation_state ORDER BY updatedAt DESC'
204
- );
205
- const rows = stmt.all() as {
206
- conversationId: string;
207
- projectPath: string;
208
- gitBranch: string;
209
- currentPhase: string;
210
- planFilePath: string;
211
- workflowName: string;
212
- gitCommitConfig: string;
213
- requireReviewsBeforePhaseTransition: number;
214
- createdAt: string;
215
- updatedAt: string;
216
- }[];
217
-
218
- const states = rows.map(row => ({
219
- conversationId: row.conversationId,
220
- projectPath: row.projectPath,
221
- gitBranch: row.gitBranch,
222
- currentPhase: row.currentPhase,
223
- planFilePath: row.planFilePath,
224
- workflowName: row.workflowName,
225
- gitCommitConfig: row.gitCommitConfig
226
- ? JSON.parse(row.gitCommitConfig)
227
- : undefined,
228
- requireReviewsBeforePhaseTransition:
229
- row.requireReviewsBeforePhaseTransition === 1,
230
- createdAt: row.createdAt,
231
- updatedAt: row.updatedAt,
232
- }));
265
+ const result = this.db.exec({
266
+ sql: 'SELECT * FROM conversation_state ORDER BY updatedAt DESC',
267
+ returnValue: 'resultRows',
268
+ });
233
269
 
234
- logger.debug('Listed conversation states', { count: states.length });
235
- return states;
270
+ if (!result) {
271
+ return [];
272
+ }
273
+
274
+ return result.map(row => ({
275
+ conversationId: row[0] as string,
276
+ projectPath: row[1] as string,
277
+ gitBranch: row[2] as string,
278
+ currentPhase: row[3] as string,
279
+ planFilePath: row[4] as string,
280
+ workflowName: row[5] as string,
281
+ gitCommitConfig: row[6] ? JSON.parse(row[6] as string) : null,
282
+ requireReviewsBeforePhaseTransition: Boolean(row[7]),
283
+ createdAt: row[8] as string,
284
+ updatedAt: row[9] as string,
285
+ }));
236
286
  }
237
287
 
238
288
  /**
@@ -243,114 +293,125 @@ export class Database {
243
293
  throw new Error('Database not initialized');
244
294
  }
245
295
 
246
- const stmt = this.db.prepare(
247
- 'DELETE FROM conversation_state WHERE conversationId = ?'
248
- );
249
- const result = stmt.run(conversationId);
296
+ this.db.exec({
297
+ sql: 'DELETE FROM conversation_state WHERE conversationId = ?',
298
+ bind: [conversationId],
299
+ });
250
300
 
251
- const deleted = result.changes > 0;
252
- logger.debug('Conversation state deletion', { conversationId, deleted });
253
- return deleted;
301
+ // Persist to file
302
+ await this.saveToFile();
303
+
304
+ logger.debug('Conversation state deleted', { conversationId });
305
+ return true;
254
306
  }
255
307
 
256
308
  /**
257
- * Log an interaction to the database
309
+ * Log interaction
258
310
  */
259
311
  async logInteraction(log: InteractionLog): Promise<void> {
260
312
  if (!this.db) {
261
313
  throw new Error('Database not initialized');
262
314
  }
263
315
 
264
- const stmt = this.db.prepare(`
265
- INSERT INTO interaction_log
266
- (conversationId, toolName, inputParams, responseData, currentPhase, timestamp, isReset, resetAt)
267
- VALUES (?, ?, ?, ?, ?, ?, ?, ?)
268
- `);
269
-
270
- stmt.run(
271
- log.conversationId,
272
- log.toolName,
273
- log.inputParams,
274
- log.responseData,
275
- log.currentPhase,
276
- log.timestamp,
277
- log.isReset ? 1 : 0,
278
- log.resetAt || null
279
- );
316
+ this.db.exec({
317
+ sql: `INSERT INTO interaction_log
318
+ (conversationId, toolName, inputParams, responseData, currentPhase, timestamp)
319
+ VALUES (?, ?, ?, ?, ?, ?)`,
320
+ bind: [
321
+ log.conversationId,
322
+ log.toolName,
323
+ JSON.stringify(log.inputParams),
324
+ JSON.stringify(log.responseData),
325
+ log.currentPhase,
326
+ log.timestamp,
327
+ ],
328
+ });
329
+
330
+ // Persist to file
331
+ await this.saveToFile();
280
332
 
281
333
  logger.debug('Interaction logged', {
282
334
  conversationId: log.conversationId,
283
335
  toolName: log.toolName,
284
- timestamp: log.timestamp,
285
336
  });
286
337
  }
287
338
 
288
339
  /**
289
- * Get interactions by conversation ID
340
+ * Get interaction logs for a conversation
341
+ */
342
+ async getInteractionLogs(conversationId: string): Promise<InteractionLog[]> {
343
+ if (!this.db) {
344
+ throw new Error('Database not initialized');
345
+ }
346
+
347
+ const result = this.db.exec({
348
+ sql: 'SELECT * FROM interaction_log WHERE conversationId = ? ORDER BY timestamp ASC',
349
+ bind: [conversationId],
350
+ returnValue: 'resultRows',
351
+ });
352
+
353
+ if (!result) {
354
+ return [];
355
+ }
356
+
357
+ return result.map(row => ({
358
+ id: row[0] as number,
359
+ conversationId: row[1] as string,
360
+ toolName: row[2] as string,
361
+ inputParams: JSON.parse(row[3] as string),
362
+ responseData: JSON.parse(row[4] as string),
363
+ currentPhase: row[5] as string,
364
+ timestamp: row[6] as string,
365
+ }));
366
+ }
367
+
368
+ /**
369
+ * Get interaction logs for a conversation (alias for compatibility)
290
370
  */
291
371
  async getInteractionsByConversationId(
292
372
  conversationId: string
293
373
  ): Promise<InteractionLog[]> {
374
+ return this.getInteractionLogs(conversationId);
375
+ }
376
+
377
+ /**
378
+ * Soft delete interaction logs (for compatibility - actually deletes them)
379
+ */
380
+ async softDeleteInteractionLogs(conversationId: string): Promise<void> {
294
381
  if (!this.db) {
295
382
  throw new Error('Database not initialized');
296
383
  }
297
384
 
298
- const stmt = this.db.prepare(`
299
- SELECT * FROM interaction_log
300
- WHERE conversationId = ? AND (isReset = 0 OR isReset IS NULL)
301
- ORDER BY timestamp ASC
302
- `);
303
- const rows = stmt.all(conversationId) as {
304
- id: number;
305
- conversationId: string;
306
- toolName: string;
307
- inputParams: string;
308
- responseData: string;
309
- currentPhase: string;
310
- timestamp: string;
311
- isReset: number;
312
- resetAt: string;
313
- }[];
314
-
315
- const logs = rows.map(row => ({
316
- id: row.id,
317
- conversationId: row.conversationId,
318
- toolName: row.toolName,
319
- inputParams: row.inputParams,
320
- responseData: row.responseData,
321
- currentPhase: row.currentPhase,
322
- timestamp: row.timestamp,
323
- isReset: row.isReset === 1,
324
- resetAt: row.resetAt,
325
- }));
326
-
327
- logger.debug('Retrieved interaction logs', {
328
- conversationId,
329
- count: logs.length,
385
+ this.db.exec({
386
+ sql: 'DELETE FROM interaction_log WHERE conversationId = ?',
387
+ bind: [conversationId],
330
388
  });
331
- return logs;
389
+
390
+ // Persist to file
391
+ await this.saveToFile();
392
+
393
+ logger.debug('Interaction logs deleted', { conversationId });
332
394
  }
333
395
 
334
396
  /**
335
- * Soft delete interaction logs by marking them as reset
397
+ * Reset conversation state (for testing)
336
398
  */
337
- async softDeleteInteractionLogs(conversationId: string): Promise<void> {
399
+ async resetConversationState(conversationId: string): Promise<void> {
338
400
  if (!this.db) {
339
401
  throw new Error('Database not initialized');
340
402
  }
341
403
 
342
404
  const resetAt = new Date().toISOString();
343
- const stmt = this.db.prepare(`
344
- UPDATE interaction_log
345
- SET isReset = 1, resetAt = ?
346
- WHERE conversationId = ? AND (isReset = 0 OR isReset IS NULL)
347
- `);
348
-
349
- const result = stmt.run(resetAt, conversationId);
350
- logger.debug('Soft deleted interaction logs', {
351
- conversationId,
352
- affectedRows: result.changes,
405
+
406
+ this.db.exec({
407
+ sql: 'UPDATE conversation_state SET updatedAt = ? WHERE conversationId = ?',
408
+ bind: [resetAt, conversationId],
353
409
  });
410
+
411
+ // Persist to file
412
+ await this.saveToFile();
413
+
414
+ logger.debug('Conversation state reset', { conversationId, resetAt });
354
415
  }
355
416
 
356
417
  /**
@@ -363,11 +424,4 @@ export class Database {
363
424
  logger.debug('Database connection closed');
364
425
  }
365
426
  }
366
-
367
- /**
368
- * Check if database is initialized
369
- */
370
- isInitialized(): boolean {
371
- return this.db !== null;
372
- }
373
427
  }