agentgui 1.0.649 → 1.0.651

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
@@ -1111,6 +1111,7 @@ export const queries = {
1111
1111
  prep('DELETE FROM stream_updates');
1112
1112
  prep('DELETE FROM chunks');
1113
1113
  prep('DELETE FROM events');
1114
+ prep('DELETE FROM voice_cache');
1114
1115
  prep('DELETE FROM sessions');
1115
1116
  prep('DELETE FROM messages');
1116
1117
  prep('DELETE FROM conversations');
@@ -203,6 +203,10 @@ class AgentRunner {
203
203
 
204
204
  proc.on('close', (code) => {
205
205
  clearTimeout(timeoutHandle);
206
+ // Close stdin when process exits - it was kept open for steering during execution
207
+ if (proc.stdin && !proc.stdin.destroyed) {
208
+ try { proc.stdin.end(); } catch (e) {}
209
+ }
206
210
  if (timedOut) return;
207
211
 
208
212
  if (authError) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentgui",
3
- "version": "1.0.649",
3
+ "version": "1.0.651",
4
4
  "description": "Multi-agent ACP client with real-time communication",
5
5
  "type": "module",
6
6
  "main": "server.js",
package/server.js CHANGED
@@ -4643,89 +4643,41 @@ server.on('error', (err) => {
4643
4643
  }
4644
4644
  });
4645
4645
 
4646
+ // On startup: mark all active/pending sessions as interrupted (server was down, they didn't complete).
4647
+ // Then resumeInterruptedStreams will pick up recent ones for auto-resume.
4646
4648
  function recoverStaleSessions() {
4647
4649
  try {
4648
- const now = Date.now();
4649
- const RESUME_WINDOW_MS = 600000; // 10 minutes
4650
-
4651
- const resumable = new Set();
4652
- const resumableConvs = queries.getResumableConversations ? queries.getResumableConversations(RESUME_WINDOW_MS) : [];
4653
- for (const conv of resumableConvs) {
4654
- resumable.add(conv.id); // All agent types are resumable
4655
- }
4656
-
4657
- const staleSessions = queries.getActiveSessions ? queries.getActiveSessions() : [];
4658
- let markedCount = 0;
4650
+ const RESUME_WINDOW_MS = 600000;
4651
+ const cutoff = Date.now() - RESUME_WINDOW_MS;
4652
+ const staleSessions = queries.getActiveSessions();
4659
4653
  for (const session of staleSessions) {
4660
- if (activeExecutions.has(session.conversationId)) continue;
4661
- if (resumable.has(session.conversationId)) continue;
4662
4654
  queries.updateSession(session.id, {
4663
- status: 'error',
4655
+ status: session.started_at > cutoff ? 'interrupted' : 'error',
4664
4656
  error: 'Server restarted',
4665
- completed_at: now
4657
+ completed_at: Date.now()
4666
4658
  });
4667
- markedCount++;
4668
4659
  }
4669
- if (markedCount > 0) {
4670
- console.log(`[RECOVERY] Marked ${markedCount} stale session(s) as error`);
4671
- }
4672
-
4673
- const streamingConvs = queries.getStreamingConversations ? queries.getStreamingConversations() : [];
4674
- let clearedCount = 0;
4675
- for (const conv of streamingConvs) {
4676
- if (activeExecutions.has(conv.id)) continue;
4677
- if (resumable.has(conv.id)) continue;
4678
- queries.setIsStreaming(conv.id, false);
4679
- clearedCount++;
4680
- }
4681
- if (clearedCount > 0) {
4682
- console.log(`[RECOVERY] Cleared isStreaming flag on ${clearedCount} stale conversation(s)`);
4683
- }
4684
- if (resumable.size > 0) {
4685
- console.log(`[RECOVERY] Found ${resumable.size} resumable conversation(s)`);
4660
+ // Clear all isStreaming flags - nothing is running yet
4661
+ queries.clearAllStreamingFlags();
4662
+ if (staleSessions.length > 0) {
4663
+ console.log(`[RECOVERY] Marked ${staleSessions.length} stale session(s); cleared streaming flags`);
4686
4664
  }
4687
4665
  } catch (err) {
4688
- console.error('[RECOVERY] Stale session recovery error:', err.message);
4666
+ console.error('[RECOVERY] Error:', err.message);
4689
4667
  }
4690
4668
  }
4691
4669
 
4670
+ // Resume conversations with recently interrupted sessions (started within 10 min).
4692
4671
  async function resumeInterruptedStreams() {
4693
4672
  try {
4694
- const RESUME_WINDOW_MS = 600000; // Only resume sessions active within the last 10 minutes
4695
- const cutoff = Date.now() - RESUME_WINDOW_MS;
4696
-
4697
- // Get conversations marked as streaming in database (isStreaming=1)
4698
- // Fall back to getResumableConversations if isStreaming is not being used
4699
- let toResume = [];
4700
-
4701
- // Primary: Check database isStreaming flag for conversations still marked as active
4702
- // Exclude conversations whose last session completed or started more than 10 min ago
4703
- const streamingConvs = queries.getConversations().filter(c => {
4704
- if (c.isStreaming !== 1) return false;
4705
- const lastSession = queries.getLatestSession(c.id);
4706
- if (!lastSession) return false;
4707
- if (lastSession.status === 'complete') return false;
4708
- // Only resume if session started within the last 10 minutes
4709
- return lastSession.started_at > cutoff;
4710
- });
4711
-
4712
- if (streamingConvs.length > 0) {
4713
- toResume = streamingConvs;
4714
- } else {
4715
- // Fallback: Use session-based resumable conversations (already filtered by 10 min)
4716
- toResume = queries.getResumableConversations ? queries.getResumableConversations(RESUME_WINDOW_MS) : [];
4717
- }
4718
-
4673
+ const toResume = queries.getResumableConversations(600000);
4719
4674
  if (toResume.length === 0) return;
4720
-
4721
4675
  console.log(`[RESUME] Resuming ${toResume.length} interrupted conversation(s)`);
4722
-
4723
4676
  for (let i = 0; i < toResume.length; i++) {
4724
4677
  const conv = toResume[i];
4725
4678
  try {
4726
- const previousSessions = [...queries.getSessionsByStatus(conv.id, 'active'), ...queries.getSessionsByStatus(conv.id, 'pending')];
4727
- const previousSessionId = previousSessions.length > 0 ? previousSessions[0].id : null;
4728
- await resumeConversation(conv.id, previousSessionId, 'Server restarted, resuming');
4679
+ const lastSession = queries.getLatestSession(conv.id);
4680
+ await resumeConversation(conv.id, lastSession?.id || null, 'Server restarted');
4729
4681
  if (i < toResume.length - 1) await new Promise(r => setTimeout(r, 200));
4730
4682
  } catch (err) {
4731
4683
  console.error(`[RESUME] Failed to resume conv ${conv.id}: ${err.message}`);
@@ -4733,7 +4685,7 @@ async function resumeInterruptedStreams() {
4733
4685
  }
4734
4686
  }
4735
4687
  } catch (err) {
4736
- console.error('[RESUME] Error during stream resumption:', err.message);
4688
+ console.error('[RESUME] Error:', err.message);
4737
4689
  }
4738
4690
  }
4739
4691
 
@@ -1453,7 +1453,7 @@ class AgentGUIClient {
1453
1453
  this.enableControls();
1454
1454
  }
1455
1455
 
1456
- async handleAllConversationsDeleted(data) {
1456
+ handleAllConversationsDeleted(data) {
1457
1457
  window.ConversationState?.clear('all_deleted');
1458
1458
  this.state.currentConversation = null;
1459
1459
  this.state.conversations = [];
@@ -1462,10 +1462,6 @@ class AgentGUIClient {
1462
1462
  this.conversationListCache = { data: [], timestamp: 0, ttl: 30000 };
1463
1463
  this.draftPrompts.clear();
1464
1464
  window.dispatchEvent(new CustomEvent('conversation-deselected'));
1465
- if (window.conversationManager) {
1466
- this.state.currentConversation = null;
1467
- await window.conversationManager.loadConversations();
1468
- }
1469
1465
  const outputEl = document.getElementById('output');
1470
1466
  if (outputEl) outputEl.innerHTML = '';
1471
1467
  }