Refactor database integration to use bun:sqlite instead of better-sqlite3
- Updated import statements across multiple files to use bun:sqlite. - Changed database query methods from `prepare` to `query` for consistency. - Removed dependency on better-sqlite3 from package.json and adjusted package.json to specify bun as the engine. - Modified hook installation process to eliminate unnecessary dependency installation. - Updated migration scripts to align with bun:sqlite's API.
This commit is contained in:
@@ -136,12 +136,11 @@ Perfect for developers who want their AI assistant to remember project context,
|
||||
<!-- Prerequisites -->
|
||||
### :bangbang: Prerequisites
|
||||
|
||||
This project requires Node.js and works best with Claude Code
|
||||
This project requires Bun runtime and works best with Claude Code
|
||||
|
||||
- Node.js >= 18.0.0
|
||||
- Bun >= 1.0.0 (required for SQLite support)
|
||||
- Claude Code with MCP support
|
||||
- macOS/Linux (POSIX-compliant system)
|
||||
- Bun >= 1.0.0 (optional, for development)
|
||||
|
||||
<!-- Installation -->
|
||||
### :gear: Installation
|
||||
|
||||
@@ -43,10 +43,11 @@ async function build() {
|
||||
const buildCommand = [
|
||||
'bun build',
|
||||
'src/bin/cli.ts',
|
||||
'--target=node',
|
||||
'--target=bun',
|
||||
'--outfile=dist/claude-mem.min.js',
|
||||
'--minify',
|
||||
'--external @anthropic-ai/claude-agent-sdk',
|
||||
'--external bun:sqlite',
|
||||
`--define __DEFAULT_PACKAGE_VERSION__='"${version}"'`
|
||||
].join(' ');
|
||||
|
||||
@@ -58,10 +59,13 @@ async function build() {
|
||||
// Add shebang to output
|
||||
console.log('\n📝 Adding shebang...');
|
||||
const distFile = 'dist/claude-mem.min.js';
|
||||
const content = fs.readFileSync(distFile, 'utf-8');
|
||||
if (!content.startsWith('#!/usr/bin/env node')) {
|
||||
fs.writeFileSync(distFile, `#!/usr/bin/env node\n${content}`);
|
||||
}
|
||||
let content = fs.readFileSync(distFile, 'utf-8');
|
||||
|
||||
// Remove any existing shebangs
|
||||
content = content.replace(/^#!.*\n/gm, '');
|
||||
|
||||
// Add the bun shebang
|
||||
fs.writeFileSync(distFile, `#!/usr/bin/env bun\n${content}`);
|
||||
console.log('✓ Shebang added');
|
||||
|
||||
// Make executable
|
||||
|
||||
Vendored
+193
-194
File diff suppressed because one or more lines are too long
@@ -10,7 +10,7 @@
|
||||
import { spawn } from 'child_process';
|
||||
import { join, dirname } from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
import Database from 'better-sqlite3';
|
||||
import { Database } from 'bun:sqlite';
|
||||
import os from 'os';
|
||||
import fs from 'fs';
|
||||
|
||||
@@ -320,7 +320,7 @@ export function createStreamingSession(db, { claude_session_id, project, user_pr
|
||||
const timestamp = started_at || new Date().toISOString();
|
||||
const epoch = new Date(timestamp).getTime();
|
||||
|
||||
const stmt = db.prepare(`
|
||||
const stmt = db.query(`
|
||||
INSERT INTO streaming_sessions (
|
||||
claude_session_id, project, user_prompt, started_at, started_at_epoch, status
|
||||
) VALUES (?, ?, ?, ?, ?, 'active')
|
||||
@@ -328,7 +328,7 @@ export function createStreamingSession(db, { claude_session_id, project, user_pr
|
||||
|
||||
const info = stmt.run(claude_session_id, project, user_prompt || null, timestamp, epoch);
|
||||
|
||||
return db.prepare('SELECT * FROM streaming_sessions WHERE id = ?').get(info.lastInsertRowid);
|
||||
return db.query('SELECT * FROM streaming_sessions WHERE id = ?').get(info.lastInsertRowid);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -372,7 +372,7 @@ export function updateStreamingSession(db, id, updates) {
|
||||
|
||||
values.push(id);
|
||||
|
||||
const stmt = db.prepare(`
|
||||
const stmt = db.query(`
|
||||
UPDATE streaming_sessions
|
||||
SET ${parts.join(', ')}
|
||||
WHERE id = ?
|
||||
@@ -380,7 +380,7 @@ export function updateStreamingSession(db, id, updates) {
|
||||
|
||||
stmt.run(...values);
|
||||
|
||||
return db.prepare('SELECT * FROM streaming_sessions WHERE id = ?').get(id);
|
||||
return db.query('SELECT * FROM streaming_sessions WHERE id = ?').get(id);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -389,7 +389,7 @@ export function updateStreamingSession(db, id, updates) {
|
||||
export function getActiveStreamingSessionsForProject(db, project) {
|
||||
ensureStreamingSessionsTable(db);
|
||||
|
||||
const stmt = db.prepare(`
|
||||
const stmt = db.query(`
|
||||
SELECT * FROM streaming_sessions
|
||||
WHERE project = ? AND status = 'active'
|
||||
ORDER BY started_at_epoch DESC
|
||||
@@ -405,7 +405,7 @@ export function markStreamingSessionCompleted(db, id) {
|
||||
const timestamp = new Date().toISOString();
|
||||
const epoch = Date.now();
|
||||
|
||||
const stmt = db.prepare(`
|
||||
const stmt = db.query(`
|
||||
UPDATE streaming_sessions
|
||||
SET status = ?,
|
||||
completed_at = ?,
|
||||
@@ -417,7 +417,7 @@ export function markStreamingSessionCompleted(db, id) {
|
||||
|
||||
stmt.run('completed', timestamp, epoch, timestamp, epoch, id);
|
||||
|
||||
return db.prepare('SELECT * FROM streaming_sessions WHERE id = ?').get(id);
|
||||
return db.query('SELECT * FROM streaming_sessions WHERE id = ?').get(id);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -459,7 +459,7 @@ export function acquireSessionLock(db, sdkSessionId, lockOwner) {
|
||||
const timestamp = new Date().toISOString();
|
||||
const epoch = Date.now();
|
||||
|
||||
const stmt = db.prepare(`
|
||||
const stmt = db.query(`
|
||||
INSERT INTO session_locks (sdk_session_id, locked_by, locked_at, locked_at_epoch)
|
||||
VALUES (?, ?, ?, ?)
|
||||
`);
|
||||
@@ -478,7 +478,7 @@ export function acquireSessionLock(db, sdkSessionId, lockOwner) {
|
||||
export function releaseSessionLock(db, sdkSessionId) {
|
||||
ensureSessionLocksTable(db);
|
||||
|
||||
const stmt = db.prepare(`
|
||||
const stmt = db.query(`
|
||||
DELETE FROM session_locks
|
||||
WHERE sdk_session_id = ?
|
||||
`);
|
||||
@@ -494,7 +494,7 @@ export function cleanupStaleLocks(db) {
|
||||
|
||||
const fiveMinutesAgo = Date.now() - (5 * 60 * 1000);
|
||||
|
||||
const stmt = db.prepare(`
|
||||
const stmt = db.query(`
|
||||
DELETE FROM session_locks
|
||||
WHERE locked_at_epoch < ?
|
||||
`);
|
||||
|
||||
+1
-2
@@ -30,7 +30,7 @@
|
||||
},
|
||||
"type": "module",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
"bun": ">=1.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"claude-mem": "./dist/claude-mem.min.js"
|
||||
@@ -44,7 +44,6 @@
|
||||
"dependencies": {
|
||||
"@anthropic-ai/claude-agent-sdk": "^0.1.0",
|
||||
"@clack/prompts": "^0.11.0",
|
||||
"better-sqlite3": "^11.8.1",
|
||||
"boxen": "^8.0.1",
|
||||
"chalk": "^5.6.0",
|
||||
"commander": "^14.0.0",
|
||||
|
||||
+2
-15
@@ -262,25 +262,12 @@ function writeHookFiles(timeout: number = 180000): void {
|
||||
};
|
||||
writeFileSync(join(runtimeHooksDir, 'config.json'), JSON.stringify(hookConfig, null, 2));
|
||||
|
||||
// Create package.json and install dependencies in hooks directory
|
||||
// Create package.json in hooks directory (no dependencies needed with bun:sqlite)
|
||||
const hookPackageJson = {
|
||||
name: "claude-mem-hooks",
|
||||
type: "module",
|
||||
dependencies: {
|
||||
"better-sqlite3": "^11.8.0"
|
||||
}
|
||||
type: "module"
|
||||
};
|
||||
writeFileSync(join(runtimeHooksDir, 'package.json'), JSON.stringify(hookPackageJson, null, 2));
|
||||
|
||||
// Install dependencies
|
||||
try {
|
||||
execSync('npm install --silent', {
|
||||
cwd: runtimeHooksDir,
|
||||
stdio: 'pipe'
|
||||
});
|
||||
} catch (error) {
|
||||
// Silent fail - hooks might still work if better-sqlite3 is globally available
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,22 +1,25 @@
|
||||
import Database from 'better-sqlite3';
|
||||
import { Database as BunDatabase } from 'bun:sqlite';
|
||||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
import { PathDiscovery } from '../path-discovery.js';
|
||||
|
||||
// Type alias for better-sqlite3 compatibility
|
||||
type Database = BunDatabase;
|
||||
|
||||
export interface Migration {
|
||||
version: number;
|
||||
up: (db: Database.Database) => void;
|
||||
down?: (db: Database.Database) => void;
|
||||
up: (db: Database) => void;
|
||||
down?: (db: Database) => void;
|
||||
}
|
||||
|
||||
let dbInstance: Database.Database | null = null;
|
||||
let dbInstance: Database | null = null;
|
||||
|
||||
/**
|
||||
* SQLite Database singleton with migration support and optimized settings
|
||||
*/
|
||||
export class DatabaseManager {
|
||||
private static instance: DatabaseManager;
|
||||
private db: Database.Database | null = null;
|
||||
private db: Database | null = null;
|
||||
private migrations: Migration[] = [];
|
||||
|
||||
static getInstance(): DatabaseManager {
|
||||
@@ -38,7 +41,7 @@ export class DatabaseManager {
|
||||
/**
|
||||
* Initialize database connection with optimized settings
|
||||
*/
|
||||
async initialize(): Promise<Database.Database> {
|
||||
async initialize(): Promise<Database> {
|
||||
if (this.db) {
|
||||
return this.db;
|
||||
}
|
||||
@@ -48,15 +51,15 @@ export class DatabaseManager {
|
||||
fs.mkdirSync(dataDir, { recursive: true });
|
||||
|
||||
const dbPath = path.join(dataDir, 'claude-mem.db');
|
||||
this.db = new Database(dbPath);
|
||||
|
||||
this.db = new BunDatabase(dbPath, { create: true, readwrite: true });
|
||||
|
||||
// Apply optimized SQLite settings
|
||||
this.db.pragma('journal_mode = WAL');
|
||||
this.db.pragma('synchronous = NORMAL');
|
||||
this.db.pragma('foreign_keys = ON');
|
||||
this.db.pragma('temp_store = memory');
|
||||
this.db.pragma('mmap_size = 268435456'); // 256MB
|
||||
this.db.pragma('cache_size = 10000');
|
||||
this.db.run('PRAGMA journal_mode = WAL');
|
||||
this.db.run('PRAGMA synchronous = NORMAL');
|
||||
this.db.run('PRAGMA foreign_keys = ON');
|
||||
this.db.run('PRAGMA temp_store = memory');
|
||||
this.db.run('PRAGMA mmap_size = 268435456'); // 256MB
|
||||
this.db.run('PRAGMA cache_size = 10000');
|
||||
|
||||
// Initialize schema_versions table
|
||||
this.initializeSchemaVersions();
|
||||
@@ -71,7 +74,7 @@ export class DatabaseManager {
|
||||
/**
|
||||
* Get the current database connection
|
||||
*/
|
||||
getConnection(): Database.Database {
|
||||
getConnection(): Database {
|
||||
if (!this.db) {
|
||||
throw new Error('Database not initialized. Call initialize() first.');
|
||||
}
|
||||
@@ -81,7 +84,7 @@ export class DatabaseManager {
|
||||
/**
|
||||
* Execute a function within a transaction
|
||||
*/
|
||||
withTransaction<T>(fn: (db: Database.Database) => T): T {
|
||||
withTransaction<T>(fn: (db: Database) => T): T {
|
||||
const db = this.getConnection();
|
||||
const transaction = db.transaction(fn);
|
||||
return transaction(db);
|
||||
@@ -104,7 +107,7 @@ export class DatabaseManager {
|
||||
private initializeSchemaVersions(): void {
|
||||
if (!this.db) return;
|
||||
|
||||
this.db.exec(`
|
||||
this.db.run(`
|
||||
CREATE TABLE IF NOT EXISTS schema_versions (
|
||||
id INTEGER PRIMARY KEY,
|
||||
version INTEGER UNIQUE NOT NULL,
|
||||
@@ -119,23 +122,20 @@ export class DatabaseManager {
|
||||
private async runMigrations(): Promise<void> {
|
||||
if (!this.db) return;
|
||||
|
||||
const appliedVersions = this.db
|
||||
.prepare('SELECT version FROM schema_versions ORDER BY version')
|
||||
.all()
|
||||
.map((row: any) => row.version);
|
||||
const query = this.db.query('SELECT version FROM schema_versions ORDER BY version');
|
||||
const appliedVersions = query.all().map((row: any) => row.version);
|
||||
|
||||
const maxApplied = appliedVersions.length > 0 ? Math.max(...appliedVersions) : 0;
|
||||
|
||||
for (const migration of this.migrations) {
|
||||
if (migration.version > maxApplied) {
|
||||
console.log(`Applying migration ${migration.version}...`);
|
||||
|
||||
|
||||
const transaction = this.db.transaction(() => {
|
||||
migration.up(this.db!);
|
||||
|
||||
this.db!
|
||||
.prepare('INSERT INTO schema_versions (version, applied_at) VALUES (?, ?)')
|
||||
.run(migration.version, new Date().toISOString());
|
||||
|
||||
const insertQuery = this.db!.query('INSERT INTO schema_versions (version, applied_at) VALUES (?, ?)');
|
||||
insertQuery.run(migration.version, new Date().toISOString());
|
||||
});
|
||||
|
||||
transaction();
|
||||
@@ -150,9 +150,8 @@ export class DatabaseManager {
|
||||
getCurrentVersion(): number {
|
||||
if (!this.db) return 0;
|
||||
|
||||
const result = this.db
|
||||
.prepare('SELECT MAX(version) as version FROM schema_versions')
|
||||
.get() as { version: number } | undefined;
|
||||
const query = this.db.query('SELECT MAX(version) as version FROM schema_versions');
|
||||
const result = query.get() as { version: number } | undefined;
|
||||
|
||||
return result?.version || 0;
|
||||
}
|
||||
@@ -161,7 +160,7 @@ export class DatabaseManager {
|
||||
/**
|
||||
* Get the global database instance (for compatibility)
|
||||
*/
|
||||
export function getDatabase(): Database.Database {
|
||||
export function getDatabase(): Database {
|
||||
if (!dbInstance) {
|
||||
throw new Error('Database not initialized. Call DatabaseManager.getInstance().initialize() first.');
|
||||
}
|
||||
@@ -171,9 +170,9 @@ export function getDatabase(): Database.Database {
|
||||
/**
|
||||
* Initialize and get database manager
|
||||
*/
|
||||
export async function initializeDatabase(): Promise<Database.Database> {
|
||||
export async function initializeDatabase(): Promise<Database> {
|
||||
const manager = DatabaseManager.getInstance();
|
||||
return await manager.initialize();
|
||||
}
|
||||
|
||||
export { Database };
|
||||
export { BunDatabase as Database };
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Database } from 'better-sqlite3';
|
||||
import { Database } from 'bun:sqlite';
|
||||
import { getDatabase } from './Database.js';
|
||||
import { DiagnosticRow, DiagnosticInput, normalizeTimestamp } from './types.js';
|
||||
|
||||
@@ -18,7 +18,7 @@ export class DiagnosticsStore {
|
||||
create(input: DiagnosticInput): DiagnosticRow {
|
||||
const { isoString, epoch } = normalizeTimestamp(input.created_at);
|
||||
|
||||
const stmt = this.db.prepare(`
|
||||
const stmt = this.db.query(`
|
||||
INSERT INTO diagnostics (
|
||||
session_id, message, severity, created_at, created_at_epoch, project, origin
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?)
|
||||
@@ -41,7 +41,7 @@ export class DiagnosticsStore {
|
||||
* Get diagnostic by primary key
|
||||
*/
|
||||
getById(id: number): DiagnosticRow | null {
|
||||
const stmt = this.db.prepare('SELECT * FROM diagnostics WHERE id = ?');
|
||||
const stmt = this.db.query('SELECT * FROM diagnostics WHERE id = ?');
|
||||
return stmt.get(id) as DiagnosticRow || null;
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ export class DiagnosticsStore {
|
||||
* Get diagnostics for a specific session
|
||||
*/
|
||||
getBySessionId(sessionId: string): DiagnosticRow[] {
|
||||
const stmt = this.db.prepare(`
|
||||
const stmt = this.db.query(`
|
||||
SELECT * FROM diagnostics
|
||||
WHERE session_id = ?
|
||||
ORDER BY created_at_epoch DESC
|
||||
@@ -61,7 +61,7 @@ export class DiagnosticsStore {
|
||||
* Get recent diagnostics for a project
|
||||
*/
|
||||
getRecentForProject(project: string, limit = 10): DiagnosticRow[] {
|
||||
const stmt = this.db.prepare(`
|
||||
const stmt = this.db.query(`
|
||||
SELECT * FROM diagnostics
|
||||
WHERE project = ?
|
||||
ORDER BY created_at_epoch DESC
|
||||
@@ -74,7 +74,7 @@ export class DiagnosticsStore {
|
||||
* Get recent diagnostics across all projects
|
||||
*/
|
||||
getRecent(limit = 10): DiagnosticRow[] {
|
||||
const stmt = this.db.prepare(`
|
||||
const stmt = this.db.query(`
|
||||
SELECT * FROM diagnostics
|
||||
ORDER BY created_at_epoch DESC
|
||||
LIMIT ?
|
||||
@@ -90,7 +90,7 @@ export class DiagnosticsStore {
|
||||
? 'SELECT * FROM diagnostics WHERE severity = ? ORDER BY created_at_epoch DESC LIMIT ?'
|
||||
: 'SELECT * FROM diagnostics WHERE severity = ? ORDER BY created_at_epoch DESC';
|
||||
|
||||
const stmt = this.db.prepare(query);
|
||||
const stmt = this.db.query(query);
|
||||
const params = limit ? [severity, limit] : [severity];
|
||||
return stmt.all(...params) as DiagnosticRow[];
|
||||
}
|
||||
@@ -103,7 +103,7 @@ export class DiagnosticsStore {
|
||||
? 'SELECT * FROM diagnostics WHERE origin = ? ORDER BY created_at_epoch DESC LIMIT ?'
|
||||
: 'SELECT * FROM diagnostics WHERE origin = ? ORDER BY created_at_epoch DESC';
|
||||
|
||||
const stmt = this.db.prepare(query);
|
||||
const stmt = this.db.query(query);
|
||||
const params = limit ? [origin, limit] : [origin];
|
||||
return stmt.all(...params) as DiagnosticRow[];
|
||||
}
|
||||
@@ -123,7 +123,7 @@ export class DiagnosticsStore {
|
||||
sql += ' ORDER BY created_at_epoch DESC LIMIT ?';
|
||||
params.push(limit);
|
||||
|
||||
const stmt = this.db.prepare(sql);
|
||||
const stmt = this.db.query(sql);
|
||||
return stmt.all(...params) as DiagnosticRow[];
|
||||
}
|
||||
|
||||
@@ -131,7 +131,7 @@ export class DiagnosticsStore {
|
||||
* Count total diagnostics
|
||||
*/
|
||||
count(): number {
|
||||
const stmt = this.db.prepare('SELECT COUNT(*) as count FROM diagnostics');
|
||||
const stmt = this.db.query('SELECT COUNT(*) as count FROM diagnostics');
|
||||
const result = stmt.get() as { count: number };
|
||||
return result.count;
|
||||
}
|
||||
@@ -140,7 +140,7 @@ export class DiagnosticsStore {
|
||||
* Count diagnostics by project
|
||||
*/
|
||||
countByProject(project: string): number {
|
||||
const stmt = this.db.prepare('SELECT COUNT(*) as count FROM diagnostics WHERE project = ?');
|
||||
const stmt = this.db.query('SELECT COUNT(*) as count FROM diagnostics WHERE project = ?');
|
||||
const result = stmt.get(project) as { count: number };
|
||||
return result.count;
|
||||
}
|
||||
@@ -149,7 +149,7 @@ export class DiagnosticsStore {
|
||||
* Count diagnostics by severity
|
||||
*/
|
||||
countBySeverity(severity: 'info' | 'warn' | 'error'): number {
|
||||
const stmt = this.db.prepare('SELECT COUNT(*) as count FROM diagnostics WHERE severity = ?');
|
||||
const stmt = this.db.query('SELECT COUNT(*) as count FROM diagnostics WHERE severity = ?');
|
||||
const result = stmt.get(severity) as { count: number };
|
||||
return result.count;
|
||||
}
|
||||
@@ -165,7 +165,7 @@ export class DiagnosticsStore {
|
||||
|
||||
const { isoString, epoch } = normalizeTimestamp(input.created_at || existing.created_at);
|
||||
|
||||
const stmt = this.db.prepare(`
|
||||
const stmt = this.db.query(`
|
||||
UPDATE diagnostics SET
|
||||
message = ?, severity = ?, created_at = ?, created_at_epoch = ?, project = ?, origin = ?
|
||||
WHERE id = ?
|
||||
@@ -188,7 +188,7 @@ export class DiagnosticsStore {
|
||||
* Delete a diagnostic by ID
|
||||
*/
|
||||
deleteById(id: number): boolean {
|
||||
const stmt = this.db.prepare('DELETE FROM diagnostics WHERE id = ?');
|
||||
const stmt = this.db.query('DELETE FROM diagnostics WHERE id = ?');
|
||||
const info = stmt.run(id);
|
||||
return info.changes > 0;
|
||||
}
|
||||
@@ -197,7 +197,7 @@ export class DiagnosticsStore {
|
||||
* Delete diagnostics by session_id
|
||||
*/
|
||||
deleteBySessionId(sessionId: string): number {
|
||||
const stmt = this.db.prepare('DELETE FROM diagnostics WHERE session_id = ?');
|
||||
const stmt = this.db.query('DELETE FROM diagnostics WHERE session_id = ?');
|
||||
const info = stmt.run(sessionId);
|
||||
return info.changes;
|
||||
}
|
||||
@@ -206,7 +206,7 @@ export class DiagnosticsStore {
|
||||
* Get unique projects from diagnostics
|
||||
*/
|
||||
getUniqueProjects(): string[] {
|
||||
const stmt = this.db.prepare('SELECT DISTINCT project FROM diagnostics ORDER BY project');
|
||||
const stmt = this.db.query('SELECT DISTINCT project FROM diagnostics ORDER BY project');
|
||||
const rows = stmt.all() as { project: string }[];
|
||||
return rows.map(row => row.project);
|
||||
}
|
||||
@@ -215,7 +215,7 @@ export class DiagnosticsStore {
|
||||
* Get diagnostic summary stats
|
||||
*/
|
||||
getStats(): { total: number; info: number; warn: number; error: number } {
|
||||
const stmt = this.db.prepare(`
|
||||
const stmt = this.db.query(`
|
||||
SELECT
|
||||
COUNT(*) as total,
|
||||
COUNT(CASE WHEN severity = 'info' THEN 1 END) as info,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Database } from 'better-sqlite3';
|
||||
import { Database } from 'bun:sqlite';
|
||||
import { getDatabase } from './Database.js';
|
||||
import { MemoryRow, MemoryInput, normalizeTimestamp } from './types.js';
|
||||
|
||||
@@ -18,7 +18,7 @@ export class MemoryStore {
|
||||
create(input: MemoryInput): MemoryRow {
|
||||
const { isoString, epoch } = normalizeTimestamp(input.created_at);
|
||||
|
||||
const stmt = this.db.prepare(`
|
||||
const stmt = this.db.query(`
|
||||
INSERT INTO memories (
|
||||
session_id, text, document_id, keywords, created_at, created_at_epoch,
|
||||
project, archive_basename, origin, title, subtitle, facts, concepts, files_touched
|
||||
@@ -64,7 +64,7 @@ export class MemoryStore {
|
||||
* Get memory by primary key
|
||||
*/
|
||||
getById(id: number): MemoryRow | null {
|
||||
const stmt = this.db.prepare('SELECT * FROM memories WHERE id = ?');
|
||||
const stmt = this.db.query('SELECT * FROM memories WHERE id = ?');
|
||||
return stmt.get(id) as MemoryRow || null;
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ export class MemoryStore {
|
||||
* Get memory by document_id
|
||||
*/
|
||||
getByDocumentId(documentId: string): MemoryRow | null {
|
||||
const stmt = this.db.prepare('SELECT * FROM memories WHERE document_id = ?');
|
||||
const stmt = this.db.query('SELECT * FROM memories WHERE document_id = ?');
|
||||
return stmt.get(documentId) as MemoryRow || null;
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ export class MemoryStore {
|
||||
* Check if a document_id already exists
|
||||
*/
|
||||
hasDocumentId(documentId: string): boolean {
|
||||
const stmt = this.db.prepare('SELECT 1 FROM memories WHERE document_id = ? LIMIT 1');
|
||||
const stmt = this.db.query('SELECT 1 FROM memories WHERE document_id = ? LIMIT 1');
|
||||
return Boolean(stmt.get(documentId));
|
||||
}
|
||||
|
||||
@@ -88,7 +88,7 @@ export class MemoryStore {
|
||||
* Get memories for a specific session
|
||||
*/
|
||||
getBySessionId(sessionId: string): MemoryRow[] {
|
||||
const stmt = this.db.prepare(`
|
||||
const stmt = this.db.query(`
|
||||
SELECT * FROM memories
|
||||
WHERE session_id = ?
|
||||
ORDER BY created_at_epoch DESC
|
||||
@@ -100,7 +100,7 @@ export class MemoryStore {
|
||||
* Get recent memories for a project
|
||||
*/
|
||||
getRecentForProject(project: string, limit = 10): MemoryRow[] {
|
||||
const stmt = this.db.prepare(`
|
||||
const stmt = this.db.query(`
|
||||
SELECT * FROM memories
|
||||
WHERE project = ?
|
||||
ORDER BY created_at_epoch DESC
|
||||
@@ -113,7 +113,7 @@ export class MemoryStore {
|
||||
* Get recent memories across all projects
|
||||
*/
|
||||
getRecent(limit = 10): MemoryRow[] {
|
||||
const stmt = this.db.prepare(`
|
||||
const stmt = this.db.query(`
|
||||
SELECT * FROM memories
|
||||
ORDER BY created_at_epoch DESC
|
||||
LIMIT ?
|
||||
@@ -136,7 +136,7 @@ export class MemoryStore {
|
||||
sql += ' ORDER BY created_at_epoch DESC LIMIT ?';
|
||||
params.push(limit);
|
||||
|
||||
const stmt = this.db.prepare(sql);
|
||||
const stmt = this.db.query(sql);
|
||||
return stmt.all(...params) as MemoryRow[];
|
||||
}
|
||||
|
||||
@@ -155,7 +155,7 @@ export class MemoryStore {
|
||||
sql += ' ORDER BY created_at_epoch DESC LIMIT ?';
|
||||
params.push(limit);
|
||||
|
||||
const stmt = this.db.prepare(sql);
|
||||
const stmt = this.db.query(sql);
|
||||
return stmt.all(...params) as MemoryRow[];
|
||||
}
|
||||
|
||||
@@ -167,7 +167,7 @@ export class MemoryStore {
|
||||
? 'SELECT * FROM memories WHERE origin = ? ORDER BY created_at_epoch DESC LIMIT ?'
|
||||
: 'SELECT * FROM memories WHERE origin = ? ORDER BY created_at_epoch DESC';
|
||||
|
||||
const stmt = this.db.prepare(query);
|
||||
const stmt = this.db.query(query);
|
||||
const params = limit ? [origin, limit] : [origin];
|
||||
return stmt.all(...params) as MemoryRow[];
|
||||
}
|
||||
@@ -176,7 +176,7 @@ export class MemoryStore {
|
||||
* Get recent memories for a project filtered by origin
|
||||
*/
|
||||
getRecentForProjectByOrigin(project: string, origin: string, limit = 10): MemoryRow[] {
|
||||
const stmt = this.db.prepare(`
|
||||
const stmt = this.db.query(`
|
||||
SELECT * FROM memories
|
||||
WHERE project = ? AND origin = ?
|
||||
ORDER BY created_at_epoch DESC
|
||||
@@ -189,7 +189,7 @@ export class MemoryStore {
|
||||
* Get last N memories for a project, sorted oldest to newest
|
||||
*/
|
||||
getLastNForProject(project: string, limit = 10): MemoryRow[] {
|
||||
const stmt = this.db.prepare(`
|
||||
const stmt = this.db.query(`
|
||||
SELECT * FROM (
|
||||
SELECT * FROM memories
|
||||
WHERE project = ?
|
||||
@@ -205,7 +205,7 @@ export class MemoryStore {
|
||||
* Count total memories
|
||||
*/
|
||||
count(): number {
|
||||
const stmt = this.db.prepare('SELECT COUNT(*) as count FROM memories');
|
||||
const stmt = this.db.query('SELECT COUNT(*) as count FROM memories');
|
||||
const result = stmt.get() as { count: number };
|
||||
return result.count;
|
||||
}
|
||||
@@ -214,7 +214,7 @@ export class MemoryStore {
|
||||
* Count memories by project
|
||||
*/
|
||||
countByProject(project: string): number {
|
||||
const stmt = this.db.prepare('SELECT COUNT(*) as count FROM memories WHERE project = ?');
|
||||
const stmt = this.db.query('SELECT COUNT(*) as count FROM memories WHERE project = ?');
|
||||
const result = stmt.get(project) as { count: number };
|
||||
return result.count;
|
||||
}
|
||||
@@ -230,7 +230,7 @@ export class MemoryStore {
|
||||
|
||||
const { isoString, epoch } = normalizeTimestamp(input.created_at || existing.created_at);
|
||||
|
||||
const stmt = this.db.prepare(`
|
||||
const stmt = this.db.query(`
|
||||
UPDATE memories SET
|
||||
text = ?, document_id = ?, keywords = ?, created_at = ?, created_at_epoch = ?,
|
||||
project = ?, archive_basename = ?, origin = ?, title = ?, subtitle = ?, facts = ?,
|
||||
@@ -262,7 +262,7 @@ export class MemoryStore {
|
||||
* Delete a memory by ID
|
||||
*/
|
||||
deleteById(id: number): boolean {
|
||||
const stmt = this.db.prepare('DELETE FROM memories WHERE id = ?');
|
||||
const stmt = this.db.query('DELETE FROM memories WHERE id = ?');
|
||||
const info = stmt.run(id);
|
||||
return info.changes > 0;
|
||||
}
|
||||
@@ -271,7 +271,7 @@ export class MemoryStore {
|
||||
* Delete memories by session_id
|
||||
*/
|
||||
deleteBySessionId(sessionId: string): number {
|
||||
const stmt = this.db.prepare('DELETE FROM memories WHERE session_id = ?');
|
||||
const stmt = this.db.query('DELETE FROM memories WHERE session_id = ?');
|
||||
const info = stmt.run(sessionId);
|
||||
return info.changes;
|
||||
}
|
||||
@@ -280,7 +280,7 @@ export class MemoryStore {
|
||||
* Get unique projects from memories
|
||||
*/
|
||||
getUniqueProjects(): string[] {
|
||||
const stmt = this.db.prepare('SELECT DISTINCT project FROM memories ORDER BY project');
|
||||
const stmt = this.db.query('SELECT DISTINCT project FROM memories ORDER BY project');
|
||||
const rows = stmt.all() as { project: string }[];
|
||||
return rows.map(row => row.project);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Database } from 'better-sqlite3';
|
||||
import { Database } from 'bun:sqlite';
|
||||
import { getDatabase } from './Database.js';
|
||||
import { OverviewRow, OverviewInput, normalizeTimestamp } from './types.js';
|
||||
|
||||
@@ -18,7 +18,7 @@ export class OverviewStore {
|
||||
create(input: OverviewInput): OverviewRow {
|
||||
const { isoString, epoch } = normalizeTimestamp(input.created_at);
|
||||
|
||||
const stmt = this.db.prepare(`
|
||||
const stmt = this.db.query(`
|
||||
INSERT INTO overviews (
|
||||
session_id, content, created_at, created_at_epoch, project, origin
|
||||
) VALUES (?, ?, ?, ?, ?, ?)
|
||||
@@ -51,7 +51,7 @@ export class OverviewStore {
|
||||
* Get overview by primary key
|
||||
*/
|
||||
getById(id: number): OverviewRow | null {
|
||||
const stmt = this.db.prepare('SELECT * FROM overviews WHERE id = ?');
|
||||
const stmt = this.db.query('SELECT * FROM overviews WHERE id = ?');
|
||||
return stmt.get(id) as OverviewRow || null;
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ export class OverviewStore {
|
||||
* Get overview by session_id
|
||||
*/
|
||||
getBySessionId(sessionId: string): OverviewRow | null {
|
||||
const stmt = this.db.prepare('SELECT * FROM overviews WHERE session_id = ?');
|
||||
const stmt = this.db.query('SELECT * FROM overviews WHERE session_id = ?');
|
||||
return stmt.get(sessionId) as OverviewRow || null;
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ export class OverviewStore {
|
||||
* Get recent overviews for a project
|
||||
*/
|
||||
getRecentForProject(project: string, limit = 5): OverviewRow[] {
|
||||
const stmt = this.db.prepare(`
|
||||
const stmt = this.db.query(`
|
||||
SELECT * FROM overviews
|
||||
WHERE project = ?
|
||||
ORDER BY created_at_epoch DESC
|
||||
@@ -80,7 +80,7 @@ export class OverviewStore {
|
||||
* Get all overviews for a project (oldest to newest)
|
||||
*/
|
||||
getAllForProject(project: string): OverviewRow[] {
|
||||
const stmt = this.db.prepare(`
|
||||
const stmt = this.db.query(`
|
||||
SELECT * FROM overviews
|
||||
WHERE project = ?
|
||||
ORDER BY created_at_epoch ASC
|
||||
@@ -92,7 +92,7 @@ export class OverviewStore {
|
||||
* Get recent overviews across all projects
|
||||
*/
|
||||
getRecent(limit = 5): OverviewRow[] {
|
||||
const stmt = this.db.prepare(`
|
||||
const stmt = this.db.query(`
|
||||
SELECT * FROM overviews
|
||||
ORDER BY created_at_epoch DESC
|
||||
LIMIT ?
|
||||
@@ -115,7 +115,7 @@ export class OverviewStore {
|
||||
sql += ' ORDER BY created_at_epoch DESC LIMIT ?';
|
||||
params.push(limit);
|
||||
|
||||
const stmt = this.db.prepare(sql);
|
||||
const stmt = this.db.query(sql);
|
||||
return stmt.all(...params) as OverviewRow[];
|
||||
}
|
||||
|
||||
@@ -127,7 +127,7 @@ export class OverviewStore {
|
||||
? 'SELECT * FROM overviews WHERE origin = ? ORDER BY created_at_epoch DESC LIMIT ?'
|
||||
: 'SELECT * FROM overviews WHERE origin = ? ORDER BY created_at_epoch DESC';
|
||||
|
||||
const stmt = this.db.prepare(query);
|
||||
const stmt = this.db.query(query);
|
||||
const params = limit ? [origin, limit] : [origin];
|
||||
return stmt.all(...params) as OverviewRow[];
|
||||
}
|
||||
@@ -136,7 +136,7 @@ export class OverviewStore {
|
||||
* Count total overviews
|
||||
*/
|
||||
count(): number {
|
||||
const stmt = this.db.prepare('SELECT COUNT(*) as count FROM overviews');
|
||||
const stmt = this.db.query('SELECT COUNT(*) as count FROM overviews');
|
||||
const result = stmt.get() as { count: number };
|
||||
return result.count;
|
||||
}
|
||||
@@ -145,7 +145,7 @@ export class OverviewStore {
|
||||
* Count overviews by project
|
||||
*/
|
||||
countByProject(project: string): number {
|
||||
const stmt = this.db.prepare('SELECT COUNT(*) as count FROM overviews WHERE project = ?');
|
||||
const stmt = this.db.query('SELECT COUNT(*) as count FROM overviews WHERE project = ?');
|
||||
const result = stmt.get(project) as { count: number };
|
||||
return result.count;
|
||||
}
|
||||
@@ -161,7 +161,7 @@ export class OverviewStore {
|
||||
|
||||
const { isoString, epoch } = normalizeTimestamp(input.created_at || existing.created_at);
|
||||
|
||||
const stmt = this.db.prepare(`
|
||||
const stmt = this.db.query(`
|
||||
UPDATE overviews SET
|
||||
content = ?, created_at = ?, created_at_epoch = ?, project = ?, origin = ?
|
||||
WHERE id = ?
|
||||
@@ -183,7 +183,7 @@ export class OverviewStore {
|
||||
* Delete an overview by ID
|
||||
*/
|
||||
deleteById(id: number): boolean {
|
||||
const stmt = this.db.prepare('DELETE FROM overviews WHERE id = ?');
|
||||
const stmt = this.db.query('DELETE FROM overviews WHERE id = ?');
|
||||
const info = stmt.run(id);
|
||||
return info.changes > 0;
|
||||
}
|
||||
@@ -192,7 +192,7 @@ export class OverviewStore {
|
||||
* Delete overview by session_id
|
||||
*/
|
||||
deleteBySessionId(sessionId: string): boolean {
|
||||
const stmt = this.db.prepare('DELETE FROM overviews WHERE session_id = ?');
|
||||
const stmt = this.db.query('DELETE FROM overviews WHERE session_id = ?');
|
||||
const info = stmt.run(sessionId);
|
||||
return info.changes > 0;
|
||||
}
|
||||
@@ -201,7 +201,7 @@ export class OverviewStore {
|
||||
* Get unique projects from overviews
|
||||
*/
|
||||
getUniqueProjects(): string[] {
|
||||
const stmt = this.db.prepare('SELECT DISTINCT project FROM overviews ORDER BY project');
|
||||
const stmt = this.db.query('SELECT DISTINCT project FROM overviews ORDER BY project');
|
||||
const rows = stmt.all() as { project: string }[];
|
||||
return rows.map(row => row.project);
|
||||
}
|
||||
@@ -210,7 +210,7 @@ export class OverviewStore {
|
||||
* Get most recent overview for a specific project
|
||||
*/
|
||||
getByProject(project: string): OverviewRow | null {
|
||||
const stmt = this.db.prepare(`
|
||||
const stmt = this.db.query(`
|
||||
SELECT * FROM overviews
|
||||
WHERE project = ?
|
||||
ORDER BY created_at_epoch DESC
|
||||
@@ -234,7 +234,7 @@ export class OverviewStore {
|
||||
* Delete overview by project name
|
||||
*/
|
||||
deleteByProject(project: string): boolean {
|
||||
const stmt = this.db.prepare('DELETE FROM overviews WHERE project = ?');
|
||||
const stmt = this.db.query('DELETE FROM overviews WHERE project = ?');
|
||||
const info = stmt.run(project);
|
||||
return info.changes > 0;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Database } from 'better-sqlite3';
|
||||
import { Database } from 'bun:sqlite';
|
||||
import { getDatabase } from './Database.js';
|
||||
import { SessionRow, SessionInput, normalizeTimestamp } from './types.js';
|
||||
|
||||
@@ -18,7 +18,7 @@ export class SessionStore {
|
||||
create(input: SessionInput): SessionRow {
|
||||
const { isoString, epoch } = normalizeTimestamp(input.created_at);
|
||||
|
||||
const stmt = this.db.prepare(`
|
||||
const stmt = this.db.query(`
|
||||
INSERT INTO sessions (
|
||||
session_id, project, created_at, created_at_epoch, source,
|
||||
archive_path, archive_bytes, archive_checksum, archived_at, metadata_json
|
||||
@@ -63,7 +63,7 @@ export class SessionStore {
|
||||
|
||||
const { isoString, epoch } = normalizeTimestamp(input.created_at || existing.created_at);
|
||||
|
||||
const stmt = this.db.prepare(`
|
||||
const stmt = this.db.query(`
|
||||
UPDATE sessions SET
|
||||
project = ?, created_at = ?, created_at_epoch = ?, source = ?,
|
||||
archive_path = ?, archive_bytes = ?, archive_checksum = ?, archived_at = ?, metadata_json = ?
|
||||
@@ -90,7 +90,7 @@ export class SessionStore {
|
||||
* Get session by primary key
|
||||
*/
|
||||
getById(id: number): SessionRow | null {
|
||||
const stmt = this.db.prepare('SELECT * FROM sessions WHERE id = ?');
|
||||
const stmt = this.db.query('SELECT * FROM sessions WHERE id = ?');
|
||||
return stmt.get(id) as SessionRow || null;
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ export class SessionStore {
|
||||
* Get session by session_id
|
||||
*/
|
||||
getBySessionId(sessionId: string): SessionRow | null {
|
||||
const stmt = this.db.prepare('SELECT * FROM sessions WHERE session_id = ?');
|
||||
const stmt = this.db.query('SELECT * FROM sessions WHERE session_id = ?');
|
||||
return stmt.get(sessionId) as SessionRow || null;
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ export class SessionStore {
|
||||
* Check if a session exists by session_id
|
||||
*/
|
||||
has(sessionId: string): boolean {
|
||||
const stmt = this.db.prepare('SELECT 1 FROM sessions WHERE session_id = ? LIMIT 1');
|
||||
const stmt = this.db.query('SELECT 1 FROM sessions WHERE session_id = ? LIMIT 1');
|
||||
return Boolean(stmt.get(sessionId));
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ export class SessionStore {
|
||||
* Get all session_ids as a Set (useful for import-history)
|
||||
*/
|
||||
getAllSessionIds(): Set<string> {
|
||||
const stmt = this.db.prepare('SELECT session_id FROM sessions');
|
||||
const stmt = this.db.query('SELECT session_id FROM sessions');
|
||||
const rows = stmt.all() as { session_id: string }[];
|
||||
return new Set(rows.map(row => row.session_id));
|
||||
}
|
||||
@@ -123,7 +123,7 @@ export class SessionStore {
|
||||
* Get recent sessions for a project
|
||||
*/
|
||||
getRecentForProject(project: string, limit = 5): SessionRow[] {
|
||||
const stmt = this.db.prepare(`
|
||||
const stmt = this.db.query(`
|
||||
SELECT * FROM sessions
|
||||
WHERE project = ?
|
||||
ORDER BY created_at_epoch DESC
|
||||
@@ -136,7 +136,7 @@ export class SessionStore {
|
||||
* Get recent sessions across all projects
|
||||
*/
|
||||
getRecent(limit = 5): SessionRow[] {
|
||||
const stmt = this.db.prepare(`
|
||||
const stmt = this.db.query(`
|
||||
SELECT * FROM sessions
|
||||
ORDER BY created_at_epoch DESC
|
||||
LIMIT ?
|
||||
@@ -152,7 +152,7 @@ export class SessionStore {
|
||||
? 'SELECT * FROM sessions WHERE source = ? ORDER BY created_at_epoch DESC LIMIT ?'
|
||||
: 'SELECT * FROM sessions WHERE source = ? ORDER BY created_at_epoch DESC';
|
||||
|
||||
const stmt = this.db.prepare(query);
|
||||
const stmt = this.db.query(query);
|
||||
const params = limit ? [source, limit] : [source];
|
||||
return stmt.all(...params) as SessionRow[];
|
||||
}
|
||||
@@ -161,7 +161,7 @@ export class SessionStore {
|
||||
* Count total sessions
|
||||
*/
|
||||
count(): number {
|
||||
const stmt = this.db.prepare('SELECT COUNT(*) as count FROM sessions');
|
||||
const stmt = this.db.query('SELECT COUNT(*) as count FROM sessions');
|
||||
const result = stmt.get() as { count: number };
|
||||
return result.count;
|
||||
}
|
||||
@@ -170,7 +170,7 @@ export class SessionStore {
|
||||
* Count sessions by project
|
||||
*/
|
||||
countByProject(project: string): number {
|
||||
const stmt = this.db.prepare('SELECT COUNT(*) as count FROM sessions WHERE project = ?');
|
||||
const stmt = this.db.query('SELECT COUNT(*) as count FROM sessions WHERE project = ?');
|
||||
const result = stmt.get(project) as { count: number };
|
||||
return result.count;
|
||||
}
|
||||
@@ -179,7 +179,7 @@ export class SessionStore {
|
||||
* Delete a session by ID (cascades to related records)
|
||||
*/
|
||||
deleteById(id: number): boolean {
|
||||
const stmt = this.db.prepare('DELETE FROM sessions WHERE id = ?');
|
||||
const stmt = this.db.query('DELETE FROM sessions WHERE id = ?');
|
||||
const info = stmt.run(id);
|
||||
return info.changes > 0;
|
||||
}
|
||||
@@ -188,7 +188,7 @@ export class SessionStore {
|
||||
* Delete a session by session_id (cascades to related records)
|
||||
*/
|
||||
deleteBySessionId(sessionId: string): boolean {
|
||||
const stmt = this.db.prepare('DELETE FROM sessions WHERE session_id = ?');
|
||||
const stmt = this.db.query('DELETE FROM sessions WHERE session_id = ?');
|
||||
const info = stmt.run(sessionId);
|
||||
return info.changes > 0;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Database } from 'better-sqlite3';
|
||||
import { Database } from 'bun:sqlite';
|
||||
import { getDatabase } from './Database.js';
|
||||
import { normalizeTimestamp } from './types.js';
|
||||
|
||||
@@ -61,7 +61,7 @@ export class StreamingSessionStore {
|
||||
create(input: StreamingSessionInput): StreamingSessionRow {
|
||||
const { isoString, epoch } = normalizeTimestamp(input.started_at);
|
||||
|
||||
const stmt = this.db.prepare(`
|
||||
const stmt = this.db.query(`
|
||||
INSERT INTO streaming_sessions (
|
||||
claude_session_id, project, user_prompt, started_at, started_at_epoch, status
|
||||
) VALUES (?, ?, ?, ?, ?, 'active')
|
||||
@@ -121,7 +121,7 @@ export class StreamingSessionStore {
|
||||
|
||||
values.push(id);
|
||||
|
||||
const stmt = this.db.prepare(`
|
||||
const stmt = this.db.query(`
|
||||
UPDATE streaming_sessions
|
||||
SET ${parts.join(', ')}
|
||||
WHERE id = ?
|
||||
@@ -148,7 +148,7 @@ export class StreamingSessionStore {
|
||||
* Get streaming session by internal ID
|
||||
*/
|
||||
getById(id: number): StreamingSessionRow | null {
|
||||
const stmt = this.db.prepare('SELECT * FROM streaming_sessions WHERE id = ?');
|
||||
const stmt = this.db.query('SELECT * FROM streaming_sessions WHERE id = ?');
|
||||
return stmt.get(id) as StreamingSessionRow || null;
|
||||
}
|
||||
|
||||
@@ -156,7 +156,7 @@ export class StreamingSessionStore {
|
||||
* Get streaming session by Claude session ID
|
||||
*/
|
||||
getByClaudeSessionId(claudeSessionId: string): StreamingSessionRow | null {
|
||||
const stmt = this.db.prepare('SELECT * FROM streaming_sessions WHERE claude_session_id = ?');
|
||||
const stmt = this.db.query('SELECT * FROM streaming_sessions WHERE claude_session_id = ?');
|
||||
return stmt.get(claudeSessionId) as StreamingSessionRow || null;
|
||||
}
|
||||
|
||||
@@ -164,7 +164,7 @@ export class StreamingSessionStore {
|
||||
* Get streaming session by SDK session ID
|
||||
*/
|
||||
getBySdkSessionId(sdkSessionId: string): StreamingSessionRow | null {
|
||||
const stmt = this.db.prepare('SELECT * FROM streaming_sessions WHERE sdk_session_id = ?');
|
||||
const stmt = this.db.query('SELECT * FROM streaming_sessions WHERE sdk_session_id = ?');
|
||||
return stmt.get(sdkSessionId) as StreamingSessionRow || null;
|
||||
}
|
||||
|
||||
@@ -172,7 +172,7 @@ export class StreamingSessionStore {
|
||||
* Check if a streaming session exists by Claude session ID
|
||||
*/
|
||||
has(claudeSessionId: string): boolean {
|
||||
const stmt = this.db.prepare('SELECT 1 FROM streaming_sessions WHERE claude_session_id = ? LIMIT 1');
|
||||
const stmt = this.db.query('SELECT 1 FROM streaming_sessions WHERE claude_session_id = ? LIMIT 1');
|
||||
return Boolean(stmt.get(claudeSessionId));
|
||||
}
|
||||
|
||||
@@ -180,7 +180,7 @@ export class StreamingSessionStore {
|
||||
* Get active streaming sessions for a project
|
||||
*/
|
||||
getActiveForProject(project: string): StreamingSessionRow[] {
|
||||
const stmt = this.db.prepare(`
|
||||
const stmt = this.db.query(`
|
||||
SELECT * FROM streaming_sessions
|
||||
WHERE project = ? AND status = 'active'
|
||||
ORDER BY started_at_epoch DESC
|
||||
@@ -192,7 +192,7 @@ export class StreamingSessionStore {
|
||||
* Get all active streaming sessions
|
||||
*/
|
||||
getAllActive(): StreamingSessionRow[] {
|
||||
const stmt = this.db.prepare(`
|
||||
const stmt = this.db.query(`
|
||||
SELECT * FROM streaming_sessions
|
||||
WHERE status = 'active'
|
||||
ORDER BY started_at_epoch DESC
|
||||
@@ -204,7 +204,7 @@ export class StreamingSessionStore {
|
||||
* Get recent streaming sessions (completed or failed)
|
||||
*/
|
||||
getRecent(limit = 10): StreamingSessionRow[] {
|
||||
const stmt = this.db.prepare(`
|
||||
const stmt = this.db.query(`
|
||||
SELECT * FROM streaming_sessions
|
||||
ORDER BY started_at_epoch DESC
|
||||
LIMIT ?
|
||||
@@ -236,7 +236,7 @@ export class StreamingSessionStore {
|
||||
* Delete a streaming session by ID
|
||||
*/
|
||||
deleteById(id: number): boolean {
|
||||
const stmt = this.db.prepare('DELETE FROM streaming_sessions WHERE id = ?');
|
||||
const stmt = this.db.query('DELETE FROM streaming_sessions WHERE id = ?');
|
||||
const info = stmt.run(id);
|
||||
return info.changes > 0;
|
||||
}
|
||||
@@ -245,7 +245,7 @@ export class StreamingSessionStore {
|
||||
* Delete a streaming session by Claude session ID
|
||||
*/
|
||||
deleteByClaudeSessionId(claudeSessionId: string): boolean {
|
||||
const stmt = this.db.prepare('DELETE FROM streaming_sessions WHERE claude_session_id = ?');
|
||||
const stmt = this.db.query('DELETE FROM streaming_sessions WHERE claude_session_id = ?');
|
||||
const info = stmt.run(claudeSessionId);
|
||||
return info.changes > 0;
|
||||
}
|
||||
@@ -255,7 +255,7 @@ export class StreamingSessionStore {
|
||||
*/
|
||||
cleanupOldSessions(daysOld = 30): number {
|
||||
const cutoffEpoch = Date.now() - (daysOld * 24 * 60 * 60 * 1000);
|
||||
const stmt = this.db.prepare(`
|
||||
const stmt = this.db.query(`
|
||||
DELETE FROM streaming_sessions
|
||||
WHERE status IN ('completed', 'failed')
|
||||
AND completed_at_epoch < ?
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Database } from 'better-sqlite3';
|
||||
import { Database } from 'bun:sqlite';
|
||||
import { getDatabase } from './Database.js';
|
||||
import {
|
||||
TranscriptEventInput,
|
||||
@@ -22,7 +22,7 @@ export class TranscriptEventStore {
|
||||
upsert(event: TranscriptEventInput): TranscriptEventRow {
|
||||
const { isoString, epoch } = normalizeTimestamp(event.captured_at);
|
||||
|
||||
const stmt = this.db.prepare(`
|
||||
const stmt = this.db.query(`
|
||||
INSERT INTO transcript_events (
|
||||
session_id,
|
||||
project,
|
||||
@@ -72,7 +72,7 @@ export class TranscriptEventStore {
|
||||
* Get event by session and index
|
||||
*/
|
||||
getBySessionAndIndex(sessionId: string, eventIndex: number): TranscriptEventRow | null {
|
||||
const stmt = this.db.prepare(`
|
||||
const stmt = this.db.query(`
|
||||
SELECT * FROM transcript_events
|
||||
WHERE session_id = ? AND event_index = ?
|
||||
`);
|
||||
@@ -83,7 +83,7 @@ export class TranscriptEventStore {
|
||||
* Get highest event_index stored for a session
|
||||
*/
|
||||
getMaxEventIndex(sessionId: string): number {
|
||||
const stmt = this.db.prepare(`
|
||||
const stmt = this.db.query(`
|
||||
SELECT MAX(event_index) as max_event_index
|
||||
FROM transcript_events
|
||||
WHERE session_id = ?
|
||||
@@ -96,7 +96,7 @@ export class TranscriptEventStore {
|
||||
* List recent events for a session
|
||||
*/
|
||||
listBySession(sessionId: string, limit = 200, offset = 0): TranscriptEventRow[] {
|
||||
const stmt = this.db.prepare(`
|
||||
const stmt = this.db.query(`
|
||||
SELECT * FROM transcript_events
|
||||
WHERE session_id = ?
|
||||
ORDER BY event_index ASC
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Database } from 'better-sqlite3';
|
||||
import { Database } from 'bun:sqlite';
|
||||
import { Migration } from './Database.js';
|
||||
|
||||
/**
|
||||
@@ -6,9 +6,9 @@ import { Migration } from './Database.js';
|
||||
*/
|
||||
export const migration001: Migration = {
|
||||
version: 1,
|
||||
up: (db: Database.Database) => {
|
||||
up: (db: Database) => {
|
||||
// Sessions table - core session tracking
|
||||
db.exec(`
|
||||
db.run(`
|
||||
CREATE TABLE IF NOT EXISTS sessions (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
session_id TEXT UNIQUE NOT NULL,
|
||||
@@ -29,7 +29,7 @@ export const migration001: Migration = {
|
||||
`);
|
||||
|
||||
// Memories table - compressed memory chunks
|
||||
db.exec(`
|
||||
db.run(`
|
||||
CREATE TABLE IF NOT EXISTS memories (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
session_id TEXT NOT NULL,
|
||||
@@ -53,7 +53,7 @@ export const migration001: Migration = {
|
||||
`);
|
||||
|
||||
// Overviews table - session summaries (one per project)
|
||||
db.exec(`
|
||||
db.run(`
|
||||
CREATE TABLE IF NOT EXISTS overviews (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
session_id TEXT NOT NULL,
|
||||
@@ -73,7 +73,7 @@ export const migration001: Migration = {
|
||||
`);
|
||||
|
||||
// Diagnostics table - system health and debug info
|
||||
db.exec(`
|
||||
db.run(`
|
||||
CREATE TABLE IF NOT EXISTS diagnostics (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
session_id TEXT,
|
||||
@@ -93,7 +93,7 @@ export const migration001: Migration = {
|
||||
`);
|
||||
|
||||
// Transcript events table - raw conversation events
|
||||
db.exec(`
|
||||
db.run(`
|
||||
CREATE TABLE IF NOT EXISTS transcript_events (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
session_id TEXT NOT NULL,
|
||||
@@ -116,8 +116,8 @@ export const migration001: Migration = {
|
||||
console.log('✅ Created all database tables successfully');
|
||||
},
|
||||
|
||||
down: (db: Database.Database) => {
|
||||
db.exec(`
|
||||
down: (db: Database) => {
|
||||
db.run(`
|
||||
DROP TABLE IF EXISTS transcript_events;
|
||||
DROP TABLE IF EXISTS diagnostics;
|
||||
DROP TABLE IF EXISTS overviews;
|
||||
@@ -132,9 +132,9 @@ export const migration001: Migration = {
|
||||
*/
|
||||
export const migration002: Migration = {
|
||||
version: 2,
|
||||
up: (db: Database.Database) => {
|
||||
up: (db: Database) => {
|
||||
// Add new columns for hierarchical memory structure
|
||||
db.exec(`
|
||||
db.run(`
|
||||
ALTER TABLE memories ADD COLUMN title TEXT;
|
||||
ALTER TABLE memories ADD COLUMN subtitle TEXT;
|
||||
ALTER TABLE memories ADD COLUMN facts TEXT;
|
||||
@@ -143,7 +143,7 @@ export const migration002: Migration = {
|
||||
`);
|
||||
|
||||
// Create indexes for the new fields to improve search performance
|
||||
db.exec(`
|
||||
db.run(`
|
||||
CREATE INDEX IF NOT EXISTS idx_memories_title ON memories(title);
|
||||
CREATE INDEX IF NOT EXISTS idx_memories_concepts ON memories(concepts);
|
||||
`);
|
||||
@@ -151,7 +151,7 @@ export const migration002: Migration = {
|
||||
console.log('✅ Added hierarchical memory fields to memories table');
|
||||
},
|
||||
|
||||
down: (db: Database.Database) => {
|
||||
down: (db: Database) => {
|
||||
// Note: SQLite doesn't support DROP COLUMN in all versions
|
||||
// In production, we'd need to recreate the table without these columns
|
||||
// For now, we'll just log a warning
|
||||
@@ -165,9 +165,9 @@ export const migration002: Migration = {
|
||||
*/
|
||||
export const migration003: Migration = {
|
||||
version: 3,
|
||||
up: (db: Database.Database) => {
|
||||
up: (db: Database) => {
|
||||
// Streaming sessions table - tracks active SDK compression sessions
|
||||
db.exec(`
|
||||
db.run(`
|
||||
CREATE TABLE IF NOT EXISTS streaming_sessions (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
claude_session_id TEXT UNIQUE NOT NULL,
|
||||
@@ -195,8 +195,8 @@ export const migration003: Migration = {
|
||||
console.log('✅ Created streaming_sessions table for real-time session tracking');
|
||||
},
|
||||
|
||||
down: (db: Database.Database) => {
|
||||
db.exec(`
|
||||
down: (db: Database) => {
|
||||
db.run(`
|
||||
DROP TABLE IF EXISTS streaming_sessions;
|
||||
`);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user