agentgui 1.0.914 → 1.0.915

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/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ ## [1.0.908] - manual audit fixes: server retry idempotency, cli-version detection, cleanup FK ordering, refresh-all path
2
+
3
+ - server.js: `onServerListenStart` one-shot guard prevents `onServerReady` + `loadPluginExtensions` from re-firing when EADDRINUSE retry succeeds — previously every retry re-ran autoProvision/installGMAgentConfigs/setIntervals causing 100+ duplicate provision passes and stacked timers
4
+ - lib/tool-version-check.js: bumped `getCliVersion` execSync timeout from 1000ms to 15000ms; bumped `checkCliInstalled` `where` timeout from 3000ms to 10000ms — Windows cmd.exe + node CLI cold-start regularly exceeds 1s/3s, leaving opencode/gemini/kilo/agent-browser with `installedVersion: null` despite being installed
5
+ - lib/db-queries-cleanup.js: reordered cleanup transaction — child rows (chunks, stream_updates) now deleted before their parent sessions; was causing FOREIGN KEY constraint failed on every `[cleanup] Initial DB cleanup complete` invocation and on the 6h periodic cleanup, silently aborting the whole transaction
6
+ - lib/routes-tools.js: `POST /api/tools/refresh-all` now calls `toolManager.refreshAllToolsAsync()` (which clears statusCache) instead of `getAllTools()` which returned stale cached values — refresh button was a no-op
7
+
1
8
  ## [Unreleased] - implement 247420 brand-bible chrome on main shell
2
9
 
3
10
  - index.html: header brand line reads `247420 / agentgui / <leaf>`; sidebar brand line reads `247420 / agentgui` — mono slash `/` in muted color, matches canonical app-topbar pattern from c:/dev/design
@@ -6,15 +6,16 @@ export function addCleanupQueries(q, db, prep, generateId) {
6
6
 
7
7
  const cleanupStmt = db.transaction(() => {
8
8
  prep('DELETE FROM events WHERE created_at < ?').run(thirtyDaysAgo);
9
- prep('DELETE FROM sessions WHERE completed_at IS NOT NULL AND completed_at < ?').run(thirtyDaysAgo);
10
9
  prep('DELETE FROM idempotencyKeys WHERE (created_at + ttl) < ?').run(now);
11
10
 
12
- prep('DELETE FROM chunks WHERE sessionId IN (SELECT id FROM sessions WHERE completed_at IS NOT NULL AND completed_at < ?)').run(sevenDaysAgo);
13
- prep('DELETE FROM stream_updates WHERE sessionId IN (SELECT id FROM sessions WHERE completed_at IS NOT NULL AND completed_at < ?)').run(sevenDaysAgo);
11
+ prep('DELETE FROM chunks WHERE sessionId IN (SELECT id FROM sessions WHERE completed_at IS NOT NULL AND completed_at < ?)').run(thirtyDaysAgo);
12
+ prep('DELETE FROM stream_updates WHERE sessionId IN (SELECT id FROM sessions WHERE completed_at IS NOT NULL AND completed_at < ?)').run(thirtyDaysAgo);
14
13
 
15
14
  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);
16
15
  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);
17
16
 
17
+ prep('DELETE FROM sessions WHERE completed_at IS NOT NULL AND completed_at < ?').run(thirtyDaysAgo);
18
+
18
19
  prep('DELETE FROM voice_cache WHERE expires_at <= ?').run(now);
19
20
 
20
21
  const deletedConvIds = prep("SELECT id FROM conversations WHERE status = 'deleted' AND updated_at < ?").all(sevenDaysAgo).map(r => r.id);
@@ -67,12 +67,11 @@ export function register(deps) {
67
67
  sendJSON(req, res, 200, { refreshing: true, toolCount: 4 });
68
68
  broadcastSync({ type: 'tools_refresh_started' });
69
69
  setImmediate(async () => {
70
- const tools = toolManager.getAllTools();
70
+ const tools = await toolManager.refreshAllToolsAsync();
71
71
  for (const tool of tools) {
72
72
  queries.updateToolStatus(tool.id, { status: tool.installed ? 'installed' : 'not_installed', version: tool.installedVersion, last_check_at: Date.now() });
73
- if (tool.installed) {
74
- const status = await toolManager.checkToolStatusAsync(tool.id);
75
- if (status?.upgradeNeeded) queries.updateToolStatus(tool.id, { update_available: 1, latest_version: status.publishedVersion });
73
+ if (tool.installed && tool.upgradeNeeded) {
74
+ queries.updateToolStatus(tool.id, { update_available: 1, latest_version: tool.publishedVersion });
76
75
  }
77
76
  }
78
77
  broadcastSync({ type: 'tools_refresh_complete', data: tools });
@@ -141,7 +141,7 @@ export function checkCliInstalled(pkg) {
141
141
  const cmd = isWindows ? 'where' : 'which';
142
142
  const bin = BIN_MAP[pkg];
143
143
  if (bin) {
144
- execSync(`${cmd} ${bin}`, { stdio: 'pipe', timeout: 3000, windowsHide: true });
144
+ execSync(`${cmd} ${bin}`, { stdio: 'pipe', timeout: 10000, windowsHide: true });
145
145
  return true;
146
146
  }
147
147
  } catch (_) {}
@@ -154,7 +154,7 @@ export function getCliVersion(pkg) {
154
154
  if (!bin) return null;
155
155
  try {
156
156
  const versionFlag = pkg === 'agent-browser' ? '-V' : '--version';
157
- const out = execSync(`${bin} ${versionFlag}`, { stdio: 'pipe', timeout: 1000, encoding: 'utf8', windowsHide: true });
157
+ const out = execSync(`${bin} ${versionFlag}`, { stdio: 'pipe', timeout: 15000, encoding: 'utf8', windowsHide: true });
158
158
  const match = out.match(/(\d+\.\d+\.\d+)/);
159
159
  if (match) {
160
160
  console.log(`[tool-manager] CLI ${pkg} (${bin}) version: ${match[1]}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentgui",
3
- "version": "1.0.914",
3
+ "version": "1.0.915",
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
@@ -169,11 +169,19 @@ process.on('SIGINT', () => {
169
169
  process.exit(0);
170
170
  });
171
171
 
172
+ let _serverReadyFired = false;
173
+ const onServerListenStart = () => {
174
+ if (_serverReadyFired) return;
175
+ _serverReadyFired = true;
176
+ onServerReady();
177
+ loadPluginExtensions();
178
+ };
179
+
172
180
  server.on('error', (err) => {
173
181
  if (err.code === 'EADDRINUSE') {
174
182
  console.error(`Port ${PORT} already in use. Waiting 3 seconds before retry...`);
175
183
  setTimeout(() => {
176
- server.listen(PORT, onServerReady);
184
+ server.listen(PORT, onServerListenStart);
177
185
  }, 3000);
178
186
  } else {
179
187
  console.error('[SERVER] Error (contained):', err.message);
@@ -194,7 +202,4 @@ const { onServerReady, getJsonlWatcher } = createOnServerReady({
194
202
  performAgentHealthCheck, pm2Manager, pm2Subscribers, recoverStaleSessions
195
203
  });
196
204
 
197
- server.listen(PORT, () => {
198
- onServerReady();
199
- loadPluginExtensions();
200
- });
205
+ server.listen(PORT, onServerListenStart);