agentgui 1.0.809 → 1.0.811

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,21 @@ 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
+ // VACUUM skipped intentionally — full VACUUM on large DBs blocks server startup
625
+ // INCREMENTAL auto_vacuum will apply to new pages going forward
626
+ console.log('[Migration] auto_vacuum = INCREMENTAL enabled (VACUUM skipped)');
627
+ }
628
+ } catch (err) {
629
+ console.error('[Migration] auto_vacuum setup error:', err.message);
630
+ }
631
+
615
632
  const stmtCache = new Map();
616
633
  function prep(sql) {
617
634
  let s = stmtCache.get(sql);
package/lib/db-queries.js CHANGED
@@ -598,24 +598,69 @@ export function createQueries(db, prep, generateId) {
598
598
  }
599
599
  },
600
600
 
601
- cleanup() {
602
- const thirtyDaysAgo = Date.now() - (30 * 24 * 60 * 60 * 1000);
603
- const sevenDaysAgo = Date.now() - (7 * 24 * 60 * 60 * 1000);
604
- const now = Date.now();
605
-
606
- const cleanupStmt = db.transaction(() => {
607
- prep('DELETE FROM events WHERE created_at < ?').run(thirtyDaysAgo);
608
- prep('DELETE FROM sessions WHERE completed_at IS NOT NULL AND completed_at < ?').run(thirtyDaysAgo);
609
- prep('DELETE FROM idempotencyKeys WHERE (created_at + ttl) < ?').run(now);
610
- // Prune chunks and stream_updates for completed sessions older than 7 days
611
- prep('DELETE FROM chunks WHERE sessionId IN (SELECT id FROM sessions WHERE completed_at IS NOT NULL AND completed_at < ?)').run(sevenDaysAgo);
612
- prep('DELETE FROM stream_updates WHERE sessionId IN (SELECT id FROM sessions WHERE completed_at IS NOT NULL AND completed_at < ?)').run(sevenDaysAgo);
613
- // Clean expired voice cache
614
- prep('DELETE FROM voice_cache WHERE expires_at <= ?').run(now);
615
- });
616
-
617
- cleanupStmt();
618
- },
601
+ cleanup() {
602
+ const thirtyDaysAgo = Date.now() - (30 * 24 * 60 * 60 * 1000);
603
+ const sevenDaysAgo = Date.now() - (7 * 24 * 60 * 60 * 1000);
604
+ const now = Date.now();
605
+
606
+ const cleanupStmt = db.transaction(() => {
607
+ // Core tables - time-based retention
608
+ prep('DELETE FROM events WHERE created_at < ?').run(thirtyDaysAgo);
609
+ prep('DELETE FROM sessions WHERE completed_at IS NOT NULL AND completed_at < ?').run(thirtyDaysAgo);
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
+ }
653
+ });
654
+
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
+ }
663
+ },
619
664
 
620
665
  setIdempotencyKey(key, value) {
621
666
  const now = Date.now();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentgui",
3
- "version": "1.0.809",
3
+ "version": "1.0.811",
4
4
  "description": "Multi-agent ACP client with real-time communication",
5
5
  "type": "module",
6
6
  "main": "electron/main.js",