agentgui 1.0.520 → 1.0.522
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/lib/tool-manager.js +18 -100
- package/package.json +1 -1
- package/static/js/client.js +33 -14
package/lib/tool-manager.js
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
import { spawn } from 'child_process';
|
|
2
|
-
import { execSync } from 'child_process';
|
|
3
2
|
import os from 'os';
|
|
4
3
|
import fs from 'fs';
|
|
5
4
|
import path from 'path';
|
|
6
5
|
|
|
7
6
|
const isWindows = os.platform() === 'win32';
|
|
8
7
|
const TOOLS = [
|
|
9
|
-
{ id: 'gm-oc', name: '
|
|
10
|
-
{ id: 'gm-gc', name: '
|
|
11
|
-
{ id: 'gm-kilo', name: '
|
|
12
|
-
{ id: 'gm-cc', name: '
|
|
8
|
+
{ id: 'gm-oc', name: 'gm-oc', pkg: 'gm-oc', pluginId: 'gm-oc' },
|
|
9
|
+
{ id: 'gm-gc', name: 'gm-gc', pkg: 'gm-gc', pluginId: 'gm' },
|
|
10
|
+
{ id: 'gm-kilo', name: 'gm-kilo', pkg: 'gm-kilo', pluginId: 'gm-kilo' },
|
|
11
|
+
{ id: 'gm-cc', name: 'gm-cc', pkg: 'gm-cc', pluginId: 'gm-cc' },
|
|
13
12
|
];
|
|
14
13
|
|
|
15
14
|
const statusCache = new Map();
|
|
@@ -18,11 +17,6 @@ const versionCache = new Map();
|
|
|
18
17
|
|
|
19
18
|
const getTool = (id) => TOOLS.find(t => t.id === id);
|
|
20
19
|
|
|
21
|
-
const getNodeModulesPath = () => {
|
|
22
|
-
const __dirname = path.dirname(new URL(import.meta.url).pathname);
|
|
23
|
-
return path.join(__dirname, '..', 'node_modules');
|
|
24
|
-
};
|
|
25
|
-
|
|
26
20
|
const getInstalledVersion = (pkg, pluginId = null) => {
|
|
27
21
|
try {
|
|
28
22
|
const homeDir = os.homedir();
|
|
@@ -86,45 +80,6 @@ const getInstalledVersion = (pkg, pluginId = null) => {
|
|
|
86
80
|
return null;
|
|
87
81
|
};
|
|
88
82
|
|
|
89
|
-
const getCliToolVersion = async (pkg) => {
|
|
90
|
-
try {
|
|
91
|
-
const cliName = pkg.split('/').pop();
|
|
92
|
-
const nodeModulesPath = getNodeModulesPath();
|
|
93
|
-
const cliBinPath = path.join(nodeModulesPath, '.bin', cliName);
|
|
94
|
-
|
|
95
|
-
if (fs.existsSync(cliBinPath)) {
|
|
96
|
-
const result = await new Promise((resolve) => {
|
|
97
|
-
const proc = spawn(cliBinPath, ['--version'], {
|
|
98
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
|
99
|
-
timeout: 5000,
|
|
100
|
-
shell: isWindows
|
|
101
|
-
});
|
|
102
|
-
let stdout = '';
|
|
103
|
-
proc.stdout.on('data', (d) => { stdout += d.toString(); });
|
|
104
|
-
const timer = setTimeout(() => {
|
|
105
|
-
try { proc.kill('SIGKILL'); } catch (_) {}
|
|
106
|
-
resolve(null);
|
|
107
|
-
}, 5000);
|
|
108
|
-
proc.on('close', (code) => {
|
|
109
|
-
clearTimeout(timer);
|
|
110
|
-
if (code === 0) {
|
|
111
|
-
const version = stdout.trim().split(/[\s\(]/)[0];
|
|
112
|
-
resolve(version && version.match(/^\d+\.\d+/) ? version : null);
|
|
113
|
-
} else {
|
|
114
|
-
resolve(null);
|
|
115
|
-
}
|
|
116
|
-
});
|
|
117
|
-
proc.on('error', () => {
|
|
118
|
-
clearTimeout(timer);
|
|
119
|
-
resolve(null);
|
|
120
|
-
});
|
|
121
|
-
});
|
|
122
|
-
return result;
|
|
123
|
-
}
|
|
124
|
-
} catch (_) {}
|
|
125
|
-
return null;
|
|
126
|
-
};
|
|
127
|
-
|
|
128
83
|
const getPublishedVersion = async (pkg) => {
|
|
129
84
|
try {
|
|
130
85
|
const cacheKey = `published-${pkg}`;
|
|
@@ -165,35 +120,15 @@ const getPublishedVersion = async (pkg) => {
|
|
|
165
120
|
}
|
|
166
121
|
};
|
|
167
122
|
|
|
168
|
-
const checkToolInstalled = (
|
|
123
|
+
const checkToolInstalled = (pluginId) => {
|
|
169
124
|
try {
|
|
170
125
|
const homeDir = os.homedir();
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
if (fs.existsSync(path.join(homeDir, '.
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
// Check OpenCode agents
|
|
178
|
-
if (fs.existsSync(path.join(homeDir, '.config', 'opencode', 'agents', pkg))) {
|
|
179
|
-
return true;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
// Check Gemini CLI agents (always stored as 'gm' directory)
|
|
183
|
-
if (fs.existsSync(path.join(homeDir, '.gemini', 'extensions', 'gm'))) {
|
|
184
|
-
return true;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
// Check Kilo agents
|
|
188
|
-
if (fs.existsSync(path.join(homeDir, '.config', 'kilo', 'agents', pkg))) {
|
|
189
|
-
return true;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
// Check node_modules as fallback
|
|
193
|
-
const nodeModulesPath = getNodeModulesPath();
|
|
194
|
-
if (fs.existsSync(path.join(nodeModulesPath, pkg))) {
|
|
195
|
-
return true;
|
|
196
|
-
}
|
|
126
|
+
if (fs.existsSync(path.join(homeDir, '.claude', 'plugins', pluginId))) return true;
|
|
127
|
+
if (fs.existsSync(path.join(homeDir, '.gemini', 'extensions', pluginId))) return true;
|
|
128
|
+
if (fs.existsSync(path.join(homeDir, '.config', 'opencode', 'agents', pluginId + '.md'))) return true;
|
|
129
|
+
if (fs.existsSync(path.join(homeDir, '.config', 'kilo', 'agents', pluginId + '.md'))) return true;
|
|
130
|
+
if (fs.existsSync(path.join(homeDir, '.config', 'opencode', 'agents', 'gm.md'))) return true;
|
|
131
|
+
if (fs.existsSync(path.join(homeDir, '.config', 'kilo', 'agents', 'gm.md'))) return true;
|
|
197
132
|
} catch (_) {}
|
|
198
133
|
return false;
|
|
199
134
|
};
|
|
@@ -213,12 +148,10 @@ const compareVersions = (v1, v2) => {
|
|
|
213
148
|
|
|
214
149
|
const checkToolViaBunx = async (pkg, pluginId = null) => {
|
|
215
150
|
try {
|
|
216
|
-
const
|
|
151
|
+
const actualPluginId = pluginId || pkg;
|
|
152
|
+
const installed = checkToolInstalled(actualPluginId);
|
|
217
153
|
const installedVersion = getInstalledVersion(pkg, pluginId);
|
|
218
154
|
const publishedVersion = await getPublishedVersion(pkg);
|
|
219
|
-
|
|
220
|
-
// Determine if update is needed by comparing versions
|
|
221
|
-
// Do NOT run bunx --version as it triggers installation/upgrade
|
|
222
155
|
const needsUpdate = installed && publishedVersion && compareVersions(installedVersion, publishedVersion);
|
|
223
156
|
const isUpToDate = installed && !needsUpdate;
|
|
224
157
|
|
|
@@ -231,8 +164,9 @@ const checkToolViaBunx = async (pkg, pluginId = null) => {
|
|
|
231
164
|
publishedVersion
|
|
232
165
|
};
|
|
233
166
|
} catch (_) {
|
|
234
|
-
const
|
|
235
|
-
|
|
167
|
+
const actualPluginId = pluginId || pkg;
|
|
168
|
+
const installedVersion = getInstalledVersion(pkg, pluginId);
|
|
169
|
+
return { installed: checkToolInstalled(actualPluginId), isUpToDate: false, upgradeNeeded: false, output: '', installedVersion, publishedVersion: null };
|
|
236
170
|
}
|
|
237
171
|
};
|
|
238
172
|
|
|
@@ -382,14 +316,8 @@ export async function install(toolId, onProgress) {
|
|
|
382
316
|
versionCache.clear();
|
|
383
317
|
|
|
384
318
|
const version = getInstalledVersion(tool.pkg, tool.pluginId);
|
|
385
|
-
if (!version) {
|
|
386
|
-
console.warn(`[tool-manager] Install succeeded but version detection failed for ${toolId}. Attempting CLI check...`);
|
|
387
|
-
const cliVersion = await getCliToolVersion(tool.pkg);
|
|
388
|
-
const freshStatus = await checkToolStatusAsync(toolId);
|
|
389
|
-
return { success: true, error: null, version: cliVersion || 'unknown', ...freshStatus };
|
|
390
|
-
}
|
|
391
319
|
const freshStatus = await checkToolStatusAsync(toolId);
|
|
392
|
-
return { success: true, error: null, version, ...freshStatus };
|
|
320
|
+
return { success: true, error: null, version: version || freshStatus.publishedVersion || 'unknown', ...freshStatus };
|
|
393
321
|
}
|
|
394
322
|
return result;
|
|
395
323
|
} finally {
|
|
@@ -408,22 +336,12 @@ export async function update(toolId, onProgress) {
|
|
|
408
336
|
try {
|
|
409
337
|
const result = await spawnBunxProc(tool.pkg, onProgress);
|
|
410
338
|
if (result.success) {
|
|
411
|
-
// Give the filesystem a moment to settle after bunx update
|
|
412
339
|
await new Promise(r => setTimeout(r, 500));
|
|
413
|
-
|
|
414
|
-
// Aggressively clear all version caches to force fresh detection
|
|
415
340
|
statusCache.delete(toolId);
|
|
416
341
|
versionCache.clear();
|
|
417
|
-
|
|
418
342
|
const version = getInstalledVersion(tool.pkg, tool.pluginId);
|
|
419
|
-
if (!version) {
|
|
420
|
-
console.warn(`[tool-manager] Update succeeded but version detection failed for ${toolId}. Attempting CLI check...`);
|
|
421
|
-
const cliVersion = await getCliToolVersion(tool.pkg);
|
|
422
|
-
const freshStatus = await checkToolStatusAsync(toolId);
|
|
423
|
-
return { success: true, error: null, version: cliVersion || 'unknown', ...freshStatus };
|
|
424
|
-
}
|
|
425
343
|
const freshStatus = await checkToolStatusAsync(toolId);
|
|
426
|
-
return { success: true, error: null, version, ...freshStatus };
|
|
344
|
+
return { success: true, error: null, version: version || freshStatus.publishedVersion || 'unknown', ...freshStatus };
|
|
427
345
|
}
|
|
428
346
|
return result;
|
|
429
347
|
} finally {
|
package/package.json
CHANGED
package/static/js/client.js
CHANGED
|
@@ -494,21 +494,19 @@ class AgentGUIClient {
|
|
|
494
494
|
|
|
495
495
|
let isRecording = false;
|
|
496
496
|
|
|
497
|
-
|
|
498
|
-
e.preventDefault();
|
|
497
|
+
const handleStartRecording = async () => {
|
|
499
498
|
if (isRecording) return;
|
|
500
|
-
isRecording = true;
|
|
501
499
|
chatMicBtn.classList.add('recording');
|
|
502
500
|
const result = await window.STTHandler.startRecording();
|
|
503
|
-
if (
|
|
504
|
-
isRecording =
|
|
501
|
+
if (result.success) {
|
|
502
|
+
isRecording = true;
|
|
503
|
+
} else {
|
|
505
504
|
chatMicBtn.classList.remove('recording');
|
|
506
505
|
alert('Microphone access denied: ' + result.error);
|
|
507
506
|
}
|
|
508
|
-
}
|
|
507
|
+
};
|
|
509
508
|
|
|
510
|
-
|
|
511
|
-
e.preventDefault();
|
|
509
|
+
const handleStopRecording = async () => {
|
|
512
510
|
if (!isRecording) return;
|
|
513
511
|
isRecording = false;
|
|
514
512
|
chatMicBtn.classList.remove('recording');
|
|
@@ -520,16 +518,37 @@ class AgentGUIClient {
|
|
|
520
518
|
} else {
|
|
521
519
|
alert('Transcription failed: ' + result.error);
|
|
522
520
|
}
|
|
521
|
+
};
|
|
522
|
+
|
|
523
|
+
chatMicBtn.addEventListener('mousedown', async (e) => {
|
|
524
|
+
e.preventDefault();
|
|
525
|
+
await handleStartRecording();
|
|
526
|
+
});
|
|
527
|
+
|
|
528
|
+
chatMicBtn.addEventListener('mouseup', async (e) => {
|
|
529
|
+
e.preventDefault();
|
|
530
|
+
await handleStopRecording();
|
|
523
531
|
});
|
|
524
532
|
|
|
525
533
|
chatMicBtn.addEventListener('mouseleave', async (e) => {
|
|
526
534
|
if (isRecording) {
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
535
|
+
await handleStopRecording();
|
|
536
|
+
}
|
|
537
|
+
});
|
|
538
|
+
|
|
539
|
+
chatMicBtn.addEventListener('touchstart', async (e) => {
|
|
540
|
+
e.preventDefault();
|
|
541
|
+
await handleStartRecording();
|
|
542
|
+
});
|
|
543
|
+
|
|
544
|
+
chatMicBtn.addEventListener('touchend', async (e) => {
|
|
545
|
+
e.preventDefault();
|
|
546
|
+
await handleStopRecording();
|
|
547
|
+
});
|
|
548
|
+
|
|
549
|
+
chatMicBtn.addEventListener('touchcancel', async (e) => {
|
|
550
|
+
if (isRecording) {
|
|
551
|
+
await handleStopRecording();
|
|
533
552
|
}
|
|
534
553
|
});
|
|
535
554
|
}
|