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 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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentgui",
3
- "version": "1.0.808",
3
+ "version": "1.0.810",
4
4
  "description": "Multi-agent ACP client with real-time communication",
5
5
  "type": "module",
6
6
  "main": "electron/main.js",
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();