agentgui 1.0.785 → 1.0.787

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
@@ -289,7 +289,7 @@ function migrateFromJson() {
289
289
  // Ensure value is always valid JSON string
290
290
  const valueStr = typeof entry.value === 'string' ? entry.value : JSON.stringify(entry.value || {});
291
291
  // Ensure ttl is a number
292
- const ttl = typeof entry.ttl === 'number' ? entry.ttl : (entry.ttl ? parseInt(entry.ttl) : null);
292
+ const ttl = typeof entry.ttl === 'number' ? entry.ttl : (entry.ttl ? parseInt(entry.ttl) : 0);
293
293
  db.prepare(
294
294
  `INSERT OR REPLACE INTO idempotencyKeys (key, value, created_at, ttl) VALUES (?, ?, ?, ?)`
295
295
  ).run(key, valueStr, entry.created_at, ttl);
@@ -99,11 +99,11 @@ class AgentRunner {
99
99
  console.log(`[${this.id}] Spawned PID ${proc.pid} closeStdin=${this.closeStdin}`);
100
100
 
101
101
  if (config.onPid) {
102
- try { config.onPid(proc.pid); } catch (e) {}
102
+ try { config.onPid(proc.pid); } catch (e) { console.error(`[${this.id}] onPid callback failed:`, e.message); }
103
103
  }
104
104
 
105
105
  if (config.onProcess) {
106
- try { config.onProcess(proc); } catch (e) {}
106
+ try { config.onProcess(proc); } catch (e) { console.error(`[${this.id}] onProcess callback failed:`, e.message); }
107
107
  }
108
108
 
109
109
  let jsonBuffer = '';
@@ -298,11 +298,11 @@ class AgentRunner {
298
298
  const proc = spawn(cmd, args, spawnOpts);
299
299
 
300
300
  if (config.onPid) {
301
- try { config.onPid(proc.pid); } catch (e) {}
301
+ try { config.onPid(proc.pid); } catch (e) { console.error(`[${this.id}] onPid callback failed:`, e.message); }
302
302
  }
303
303
 
304
304
  if (config.onProcess) {
305
- try { config.onProcess(proc); } catch (e) {}
305
+ try { config.onProcess(proc); } catch (e) { console.error(`[${this.id}] onProcess callback failed:`, e.message); }
306
306
  }
307
307
 
308
308
  const outputs = [];
@@ -75,7 +75,8 @@ export async function startCodexOAuth(req, { PORT, BASE_URL }) {
75
75
  const mode = remote ? 'remote' : 'local';
76
76
  codexOAuthPending = { pkce, redirectUri, state: csrfToken };
77
77
  codexOAuthState = { status: 'pending', error: null, email: null };
78
- setTimeout(() => {
78
+ if (codexOAuthPending._timeout) clearTimeout(codexOAuthPending._timeout);
79
+ codexOAuthPending._timeout = setTimeout(() => {
79
80
  if (codexOAuthState.status === 'pending') {
80
81
  codexOAuthState = { status: 'error', error: 'Authentication timed out', email: null };
81
82
  codexOAuthPending = null;
@@ -86,6 +87,7 @@ export async function startCodexOAuth(req, { PORT, BASE_URL }) {
86
87
 
87
88
  export async function exchangeCodexOAuthCode(code, stateParam) {
88
89
  if (!codexOAuthPending) throw new Error('No pending OAuth flow. Please start authentication again.');
90
+ if (codexOAuthPending._timeout) { clearTimeout(codexOAuthPending._timeout); codexOAuthPending._timeout = null; }
89
91
  const { pkce, redirectUri, state: expectedCsrf } = codexOAuthPending;
90
92
  const { csrfToken } = decodeOAuthState(stateParam);
91
93
  if (csrfToken !== expectedCsrf) {
@@ -105,7 +105,8 @@ export async function startGeminiOAuth(req, { PORT, BASE_URL, rootDir }) {
105
105
  const mode = useCustomClient ? 'custom' : (remote ? 'cli-remote' : 'cli-local');
106
106
  geminiOAuthPending = { client, redirectUri, state: csrfToken };
107
107
  geminiOAuthState = { status: 'pending', error: null, email: null };
108
- setTimeout(() => {
108
+ if (geminiOAuthPending._timeout) clearTimeout(geminiOAuthPending._timeout);
109
+ geminiOAuthPending._timeout = setTimeout(() => {
109
110
  if (geminiOAuthState.status === 'pending') {
110
111
  geminiOAuthState = { status: 'error', error: 'Authentication timed out', email: null };
111
112
  geminiOAuthPending = null;
@@ -116,6 +117,7 @@ export async function startGeminiOAuth(req, { PORT, BASE_URL, rootDir }) {
116
117
 
117
118
  export async function exchangeGeminiOAuthCode(code, stateParam) {
118
119
  if (!geminiOAuthPending) throw new Error('No pending OAuth flow. Please start authentication again.');
120
+ if (geminiOAuthPending._timeout) { clearTimeout(geminiOAuthPending._timeout); geminiOAuthPending._timeout = null; }
119
121
  const { client, redirectUri, state: expectedCsrf } = geminiOAuthPending;
120
122
  const { csrfToken } = decodeOAuthState(stateParam);
121
123
  if (csrfToken !== expectedCsrf) {
@@ -63,6 +63,8 @@ export function register(router, deps) {
63
63
  });
64
64
 
65
65
  router.handle('conv.del', (p) => {
66
+ cleanupExecution(p.id);
67
+ execMachine.remove(p.id);
66
68
  if (!queries.deleteConversation(p.id)) notFound();
67
69
  getJsonlWatcher()?.removeConversation(p.id);
68
70
  broadcastSync({ type: 'conversation_deleted', conversationId: p.id });
@@ -70,6 +72,9 @@ export function register(router, deps) {
70
72
  });
71
73
 
72
74
  router.handle('conv.del.all', (p) => {
75
+ // Clean up all execution machine actors
76
+ const convs = queries.getConversationsList();
77
+ for (const c of convs) { cleanupExecution(c.id); execMachine.remove(c.id); }
73
78
  if (!queries.deleteAllConversations()) fail(500, 'Failed to delete all conversations');
74
79
  getJsonlWatcher()?.removeAllConversations();
75
80
  broadcastSync({ type: 'all_conversations_deleted', timestamp: Date.now() });
@@ -92,6 +92,7 @@ export function register(router, deps) {
92
92
  const session = startExecution(p.id, message, agentId, model, p.content, subAgent);
93
93
  return { message, session, idempotencyKey };
94
94
  }
95
+ broadcastSync({ type: 'message_created', conversationId: p.id, message, timestamp: Date.now() });
95
96
  const qp = enqueue(p.id, p.content, agentId, model, message.id, subAgent);
96
97
  return { message, queued: true, queuePosition: qp, idempotencyKey };
97
98
  });
@@ -111,6 +112,7 @@ export function register(router, deps) {
111
112
  const session = startExecution(p.id, userMessage, agentId, model, prompt, subAgent);
112
113
  return { message: userMessage, session, streamId: session.id };
113
114
  }
115
+ broadcastSync({ type: 'message_created', conversationId: p.id, message: userMessage, timestamp: Date.now() });
114
116
  const qp = enqueue(p.id, prompt, agentId, model, userMessage.id, subAgent);
115
117
  const seq = getNextQueueSeq(p.id);
116
118
  broadcastSync({ type: 'queue_status', conversationId: p.id, queueLength: execMachine.getQueue(p.id).length, seq, timestamp: Date.now() });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentgui",
3
- "version": "1.0.785",
3
+ "version": "1.0.787",
4
4
  "description": "Multi-agent ACP client with real-time communication",
5
5
  "type": "module",
6
6
  "main": "electron/main.js",
@@ -2837,6 +2837,7 @@ class AgentGUIClient {
2837
2837
  }
2838
2838
 
2839
2839
  const cached = this.conversationCache.get(conversationId);
2840
+ if (cached) { this.conversationCache.delete(conversationId); this.conversationCache.set(conversationId, cached); }
2840
2841
  if (cached && (Date.now() - cached.timestamp) < 300000) {
2841
2842
  const outputEl = document.getElementById('output');
2842
2843
  if (outputEl) {