agentgui 1.0.808 → 1.0.810
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/database.js +16 -0
- package/lib/db-queries.js +51 -0
- package/package.json +1 -1
- package/server.js +6 -0
package/database.js
CHANGED
|
@@ -40,6 +40,7 @@ try {
|
|
|
40
40
|
db.run('PRAGMA cache_size = -64000');
|
|
41
41
|
db.run('PRAGMA mmap_size = 268435456');
|
|
42
42
|
db.run('PRAGMA temp_store = MEMORY');
|
|
43
|
+
db.run('PRAGMA auto_vacuum = INCREMENTAL');
|
|
43
44
|
} catch (e) {
|
|
44
45
|
try {
|
|
45
46
|
const sqlite3 = require('better-sqlite3');
|
|
@@ -52,6 +53,7 @@ try {
|
|
|
52
53
|
db.pragma('cache_size = -64000');
|
|
53
54
|
db.pragma('mmap_size = 268435456');
|
|
54
55
|
db.pragma('temp_store = MEMORY');
|
|
56
|
+
db.pragma('auto_vacuum = INCREMENTAL');
|
|
55
57
|
} catch (e2) {
|
|
56
58
|
throw new Error('SQLite database is required. Please run with bun (recommended) or install better-sqlite3: npm install better-sqlite3');
|
|
57
59
|
}
|
|
@@ -612,6 +614,20 @@ try {
|
|
|
612
614
|
console.error('[Migration] FTS5 error:', err.message);
|
|
613
615
|
}
|
|
614
616
|
|
|
617
|
+
// One-time: enable incremental auto_vacuum on existing databases (requires VACUUM to activate)
|
|
618
|
+
try {
|
|
619
|
+
const autoVacuum = db.prepare('PRAGMA auto_vacuum').get();
|
|
620
|
+
const mode = autoVacuum?.auto_vacuum ?? autoVacuum;
|
|
621
|
+
if (mode !== 2) { // 2 = INCREMENTAL
|
|
622
|
+
console.log('[Migration] Enabling incremental auto_vacuum (one-time VACUUM)...');
|
|
623
|
+
db.exec('PRAGMA auto_vacuum = INCREMENTAL');
|
|
624
|
+
db.exec('VACUUM');
|
|
625
|
+
console.log('[Migration] VACUUM complete, auto_vacuum = INCREMENTAL enabled');
|
|
626
|
+
}
|
|
627
|
+
} catch (err) {
|
|
628
|
+
console.error('[Migration] auto_vacuum setup error:', err.message);
|
|
629
|
+
}
|
|
630
|
+
|
|
615
631
|
const stmtCache = new Map();
|
|
616
632
|
function prep(sql) {
|
|
617
633
|
let s = stmtCache.get(sql);
|
package/lib/db-queries.js
CHANGED
|
@@ -600,15 +600,66 @@ export function createQueries(db, prep, generateId) {
|
|
|
600
600
|
|
|
601
601
|
cleanup() {
|
|
602
602
|
const thirtyDaysAgo = Date.now() - (30 * 24 * 60 * 60 * 1000);
|
|
603
|
+
const sevenDaysAgo = Date.now() - (7 * 24 * 60 * 60 * 1000);
|
|
603
604
|
const now = Date.now();
|
|
604
605
|
|
|
605
606
|
const cleanupStmt = db.transaction(() => {
|
|
607
|
+
// Core tables - time-based retention
|
|
606
608
|
prep('DELETE FROM events WHERE created_at < ?').run(thirtyDaysAgo);
|
|
607
609
|
prep('DELETE FROM sessions WHERE completed_at IS NOT NULL AND completed_at < ?').run(thirtyDaysAgo);
|
|
608
610
|
prep('DELETE FROM idempotencyKeys WHERE (created_at + ttl) < ?').run(now);
|
|
611
|
+
|
|
612
|
+
// Chunks and stream_updates: completed sessions >7 days
|
|
613
|
+
prep('DELETE FROM chunks WHERE sessionId IN (SELECT id FROM sessions WHERE completed_at IS NOT NULL AND completed_at < ?)').run(sevenDaysAgo);
|
|
614
|
+
prep('DELETE FROM stream_updates WHERE sessionId IN (SELECT id FROM sessions WHERE completed_at IS NOT NULL AND completed_at < ?)').run(sevenDaysAgo);
|
|
615
|
+
|
|
616
|
+
// Chunks and stream_updates: orphaned (session missing or stuck non-completed >7 days)
|
|
617
|
+
prep('DELETE FROM chunks WHERE created_at < ? AND sessionId NOT IN (SELECT id FROM sessions WHERE completed_at IS NULL AND started_at >= ?)').run(sevenDaysAgo, sevenDaysAgo);
|
|
618
|
+
prep('DELETE FROM stream_updates WHERE created_at < ? AND sessionId NOT IN (SELECT id FROM sessions WHERE completed_at IS NULL AND started_at >= ?)').run(sevenDaysAgo, sevenDaysAgo);
|
|
619
|
+
|
|
620
|
+
// Clean expired voice cache
|
|
621
|
+
prep('DELETE FROM voice_cache WHERE expires_at <= ?').run(now);
|
|
622
|
+
|
|
623
|
+
// Hard-delete soft-deleted conversations and their orphaned data after 7 days
|
|
624
|
+
const deletedConvIds = prep("SELECT id FROM conversations WHERE status = 'deleted' AND updated_at < ?").all(sevenDaysAgo).map(r => r.id);
|
|
625
|
+
for (const cid of deletedConvIds) {
|
|
626
|
+
prep('DELETE FROM stream_updates WHERE conversationId = ?').run(cid);
|
|
627
|
+
prep('DELETE FROM chunks WHERE conversationId = ?').run(cid);
|
|
628
|
+
prep('DELETE FROM events WHERE conversationId = ?').run(cid);
|
|
629
|
+
prep('DELETE FROM sessions WHERE conversationId = ?').run(cid);
|
|
630
|
+
prep('DELETE FROM messages WHERE conversationId = ?').run(cid);
|
|
631
|
+
prep('DELETE FROM voice_cache WHERE conversationId = ?').run(cid);
|
|
632
|
+
prep('DELETE FROM thread_states WHERE thread_id = ?').run(cid);
|
|
633
|
+
prep('DELETE FROM checkpoints WHERE thread_id = ?').run(cid);
|
|
634
|
+
prep('DELETE FROM run_metadata WHERE thread_id = ?').run(cid);
|
|
635
|
+
prep('DELETE FROM conversations WHERE id = ?').run(cid);
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
// ACP tables: prune old thread_states, checkpoints, run_metadata (30 days)
|
|
639
|
+
prep('DELETE FROM thread_states WHERE created_at < ?').run(thirtyDaysAgo);
|
|
640
|
+
prep('DELETE FROM checkpoints WHERE created_at < ?').run(thirtyDaysAgo);
|
|
641
|
+
prep('DELETE FROM run_metadata WHERE created_at < ? AND status NOT IN (?, ?)').run(thirtyDaysAgo, 'active', 'pending');
|
|
642
|
+
|
|
643
|
+
// Workflow runs older than 30 days
|
|
644
|
+
prep('DELETE FROM workflow_runs WHERE created_at < ?').run(thirtyDaysAgo);
|
|
645
|
+
|
|
646
|
+
// Tool install history: keep last 50 per tool
|
|
647
|
+
const toolIds = prep('SELECT DISTINCT tool_id FROM tool_install_history').all().map(r => r.tool_id);
|
|
648
|
+
for (const tid of toolIds) {
|
|
649
|
+
prep(`DELETE FROM tool_install_history WHERE tool_id = ? AND id NOT IN (
|
|
650
|
+
SELECT id FROM tool_install_history WHERE tool_id = ? ORDER BY created_at DESC LIMIT 50
|
|
651
|
+
)`).run(tid, tid);
|
|
652
|
+
}
|
|
609
653
|
});
|
|
610
654
|
|
|
611
655
|
cleanupStmt();
|
|
656
|
+
|
|
657
|
+
// Incremental VACUUM to reclaim space without blocking (WAL-safe)
|
|
658
|
+
try {
|
|
659
|
+
db.exec('PRAGMA incremental_vacuum(1000)');
|
|
660
|
+
} catch (_) {
|
|
661
|
+
// incremental_vacuum requires auto_vacuum=INCREMENTAL, fall through
|
|
662
|
+
}
|
|
612
663
|
},
|
|
613
664
|
|
|
614
665
|
setIdempotencyKey(key, value) {
|
package/package.json
CHANGED
package/server.js
CHANGED
|
@@ -3171,6 +3171,12 @@ function onServerReady() {
|
|
|
3171
3171
|
recoverStaleSessions();
|
|
3172
3172
|
warmAssetCache();
|
|
3173
3173
|
|
|
3174
|
+
// Run DB cleanup on startup and every 6 hours
|
|
3175
|
+
try { queries.cleanup(); console.log('[cleanup] Initial DB cleanup complete'); } catch (e) { console.error('[cleanup] Error:', e.message); }
|
|
3176
|
+
setInterval(() => {
|
|
3177
|
+
try { queries.cleanup(); console.log('[cleanup] Scheduled DB cleanup complete'); } catch (e) { console.error('[cleanup] Error:', e.message); }
|
|
3178
|
+
}, 6 * 60 * 60 * 1000);
|
|
3179
|
+
|
|
3174
3180
|
try {
|
|
3175
3181
|
jsonlWatcher = new JsonlWatcher({ broadcastSync, queries, ownedSessionIds });
|
|
3176
3182
|
jsonlWatcher.start();
|