agentgui 1.0.474 → 1.0.480
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 +93 -8
- package/package.json +1 -1
- package/server.js +3 -1
- package/static/css/tools-popup.css +22 -0
- package/static/js/tools-manager.js +12 -0
package/lib/tool-manager.js
CHANGED
|
@@ -14,14 +14,72 @@ const TOOLS = [
|
|
|
14
14
|
|
|
15
15
|
const statusCache = new Map();
|
|
16
16
|
const installLocks = new Map();
|
|
17
|
+
const versionCache = new Map();
|
|
17
18
|
|
|
18
19
|
const getTool = (id) => TOOLS.find(t => t.id === id);
|
|
19
20
|
|
|
21
|
+
const getNodeModulesPath = () => {
|
|
22
|
+
const __dirname = path.dirname(new URL(import.meta.url).pathname);
|
|
23
|
+
return path.join(__dirname, '..', 'node_modules');
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const getInstalledVersion = (pkg) => {
|
|
27
|
+
try {
|
|
28
|
+
const nodeModulesPath = getNodeModulesPath();
|
|
29
|
+
const pkgJsonPath = path.join(nodeModulesPath, pkg, 'package.json');
|
|
30
|
+
if (fs.existsSync(pkgJsonPath)) {
|
|
31
|
+
const pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf-8'));
|
|
32
|
+
return pkgJson.version;
|
|
33
|
+
}
|
|
34
|
+
} catch (_) {}
|
|
35
|
+
return null;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const getPublishedVersion = async (pkg) => {
|
|
39
|
+
try {
|
|
40
|
+
const cacheKey = `published-${pkg}`;
|
|
41
|
+
const cached = versionCache.get(cacheKey);
|
|
42
|
+
if (cached && Date.now() - cached.timestamp < 3600000) {
|
|
43
|
+
return cached.version;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const cmd = isWindows ? 'npm.cmd' : 'npm';
|
|
47
|
+
const result = await new Promise((resolve) => {
|
|
48
|
+
const proc = spawn(cmd, ['view', pkg, 'version'], {
|
|
49
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
50
|
+
timeout: 5000,
|
|
51
|
+
shell: isWindows
|
|
52
|
+
});
|
|
53
|
+
let stdout = '';
|
|
54
|
+
proc.stdout.on('data', (d) => { stdout += d.toString(); });
|
|
55
|
+
const timer = setTimeout(() => {
|
|
56
|
+
try { proc.kill('SIGKILL'); } catch (_) {}
|
|
57
|
+
resolve(null);
|
|
58
|
+
}, 5000);
|
|
59
|
+
proc.on('close', (code) => {
|
|
60
|
+
clearTimeout(timer);
|
|
61
|
+
resolve(code === 0 ? stdout.trim() : null);
|
|
62
|
+
});
|
|
63
|
+
proc.on('error', () => {
|
|
64
|
+
clearTimeout(timer);
|
|
65
|
+
resolve(null);
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
if (result) {
|
|
70
|
+
versionCache.set(cacheKey, { version: result, timestamp: Date.now() });
|
|
71
|
+
}
|
|
72
|
+
return result;
|
|
73
|
+
} catch (_) {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
|
|
20
78
|
const checkToolInstalled = (pkg) => {
|
|
21
79
|
try {
|
|
22
|
-
const
|
|
23
|
-
const
|
|
24
|
-
return fs.existsSync(
|
|
80
|
+
const nodeModulesPath = getNodeModulesPath();
|
|
81
|
+
const nodeModulesPackagePath = path.join(nodeModulesPath, pkg);
|
|
82
|
+
return fs.existsSync(nodeModulesPackagePath);
|
|
25
83
|
} catch (_) {
|
|
26
84
|
return false;
|
|
27
85
|
}
|
|
@@ -30,7 +88,7 @@ const checkToolInstalled = (pkg) => {
|
|
|
30
88
|
const checkToolViaBunx = async (pkg) => {
|
|
31
89
|
try {
|
|
32
90
|
const cmd = isWindows ? 'bunx.cmd' : 'bunx';
|
|
33
|
-
|
|
91
|
+
const checkResult = await new Promise((resolve) => {
|
|
34
92
|
const proc = spawn(cmd, [pkg, '--version'], {
|
|
35
93
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
36
94
|
timeout: 10000,
|
|
@@ -42,7 +100,8 @@ const checkToolViaBunx = async (pkg) => {
|
|
|
42
100
|
const timer = setTimeout(() => {
|
|
43
101
|
try { proc.kill('SIGKILL'); } catch (_) {}
|
|
44
102
|
const installed = checkToolInstalled(pkg);
|
|
45
|
-
|
|
103
|
+
const installedVersion = getInstalledVersion(pkg);
|
|
104
|
+
resolve({ installed, isUpToDate: installed, upgradeNeeded: false, output: 'timeout', installedVersion });
|
|
46
105
|
}, 10000);
|
|
47
106
|
proc.on('close', (code) => {
|
|
48
107
|
clearTimeout(timer);
|
|
@@ -50,16 +109,36 @@ const checkToolViaBunx = async (pkg) => {
|
|
|
50
109
|
const installed = code === 0 || checkToolInstalled(pkg);
|
|
51
110
|
const upgradeNeeded = output.includes('Upgrading') || output.includes('upgrade');
|
|
52
111
|
const isUpToDate = installed && !upgradeNeeded;
|
|
53
|
-
|
|
112
|
+
const installedVersion = getInstalledVersion(pkg);
|
|
113
|
+
resolve({ installed, isUpToDate, upgradeNeeded, output, installedVersion });
|
|
54
114
|
});
|
|
55
115
|
proc.on('error', () => {
|
|
56
116
|
clearTimeout(timer);
|
|
57
117
|
const installed = checkToolInstalled(pkg);
|
|
58
|
-
|
|
118
|
+
const installedVersion = getInstalledVersion(pkg);
|
|
119
|
+
resolve({ installed, isUpToDate: false, upgradeNeeded: false, output: '', installedVersion });
|
|
59
120
|
});
|
|
60
121
|
});
|
|
122
|
+
|
|
123
|
+
const publishedVersion = await getPublishedVersion(pkg);
|
|
124
|
+
const compareVersions = (v1, v2) => {
|
|
125
|
+
if (!v1 || !v2) return false;
|
|
126
|
+
const parts1 = v1.split('.').map(Number);
|
|
127
|
+
const parts2 = v2.split('.').map(Number);
|
|
128
|
+
for (let i = 0; i < Math.max(parts1.length, parts2.length); i++) {
|
|
129
|
+
const p1 = parts1[i] || 0;
|
|
130
|
+
const p2 = parts2[i] || 0;
|
|
131
|
+
if (p1 < p2) return true;
|
|
132
|
+
if (p1 > p2) return false;
|
|
133
|
+
}
|
|
134
|
+
return false;
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
const needsUpdate = checkResult.installed && publishedVersion && compareVersions(checkResult.installedVersion, publishedVersion);
|
|
138
|
+
return { ...checkResult, publishedVersion, upgradeNeeded: needsUpdate };
|
|
61
139
|
} catch (_) {
|
|
62
|
-
|
|
140
|
+
const installedVersion = getInstalledVersion(pkg);
|
|
141
|
+
return { installed: checkToolInstalled(pkg), isUpToDate: false, upgradeNeeded: false, output: '', installedVersion, publishedVersion: null };
|
|
63
142
|
}
|
|
64
143
|
};
|
|
65
144
|
|
|
@@ -92,6 +171,8 @@ export async function checkToolStatusAsync(toolId) {
|
|
|
92
171
|
installed: cached.installed,
|
|
93
172
|
isUpToDate: cached.isUpToDate,
|
|
94
173
|
upgradeNeeded: cached.upgradeNeeded,
|
|
174
|
+
installedVersion: cached.installedVersion,
|
|
175
|
+
publishedVersion: cached.publishedVersion,
|
|
95
176
|
timestamp: cached.timestamp
|
|
96
177
|
};
|
|
97
178
|
}
|
|
@@ -102,6 +183,8 @@ export async function checkToolStatusAsync(toolId) {
|
|
|
102
183
|
installed: result.installed,
|
|
103
184
|
isUpToDate: result.isUpToDate,
|
|
104
185
|
upgradeNeeded: result.upgradeNeeded,
|
|
186
|
+
installedVersion: result.installedVersion,
|
|
187
|
+
publishedVersion: result.publishedVersion,
|
|
105
188
|
timestamp: Date.now()
|
|
106
189
|
};
|
|
107
190
|
|
|
@@ -178,6 +261,8 @@ export function getAllTools() {
|
|
|
178
261
|
installed: cached?.installed ?? false,
|
|
179
262
|
isUpToDate: cached?.isUpToDate ?? false,
|
|
180
263
|
upgradeNeeded: cached?.upgradeNeeded ?? false,
|
|
264
|
+
installedVersion: cached?.installedVersion ?? null,
|
|
265
|
+
publishedVersion: cached?.publishedVersion ?? null,
|
|
181
266
|
timestamp: cached?.timestamp ?? 0
|
|
182
267
|
};
|
|
183
268
|
});
|
package/package.json
CHANGED
package/server.js
CHANGED
|
@@ -1792,7 +1792,9 @@ const server = http.createServer(async (req, res) => {
|
|
|
1792
1792
|
status: t.installed ? (t.isUpToDate ? 'installed' : 'needs_update') : 'not_installed',
|
|
1793
1793
|
isUpToDate: t.isUpToDate,
|
|
1794
1794
|
upgradeNeeded: t.upgradeNeeded,
|
|
1795
|
-
hasUpdate: t.upgradeNeeded && t.installed
|
|
1795
|
+
hasUpdate: t.upgradeNeeded && t.installed,
|
|
1796
|
+
installedVersion: t.installedVersion,
|
|
1797
|
+
publishedVersion: t.publishedVersion
|
|
1796
1798
|
}));
|
|
1797
1799
|
sendJSON(req, res, 200, { tools: result });
|
|
1798
1800
|
return;
|
|
@@ -314,3 +314,25 @@
|
|
|
314
314
|
font-size: 0.875rem;
|
|
315
315
|
margin-bottom: 0.5rem;
|
|
316
316
|
}
|
|
317
|
+
|
|
318
|
+
.tool-versions {
|
|
319
|
+
display: flex;
|
|
320
|
+
flex-direction: column;
|
|
321
|
+
gap: 0.25rem;
|
|
322
|
+
font-size: 0.75rem;
|
|
323
|
+
color: var(--color-text-secondary);
|
|
324
|
+
background: var(--color-bg-secondary);
|
|
325
|
+
padding: 0.5rem;
|
|
326
|
+
border-radius: 0.25rem;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
.tool-version-item {
|
|
330
|
+
display: flex;
|
|
331
|
+
align-items: center;
|
|
332
|
+
gap: 0.375rem;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
.tool-version-item strong {
|
|
336
|
+
color: var(--color-text-primary);
|
|
337
|
+
font-weight: 600;
|
|
338
|
+
}
|
|
@@ -162,6 +162,17 @@
|
|
|
162
162
|
var statusClass = getStatusClass(tool);
|
|
163
163
|
var isInstalling = tool.status === 'installing' || tool.status === 'updating';
|
|
164
164
|
var hasAction = !tool.installed || tool.hasUpdate || tool.status === 'failed';
|
|
165
|
+
var versionInfo = '';
|
|
166
|
+
if (tool.installedVersion || tool.publishedVersion) {
|
|
167
|
+
versionInfo = '<div class="tool-versions">';
|
|
168
|
+
if (tool.installedVersion) {
|
|
169
|
+
versionInfo += '<span class="tool-version-item">Installed: <strong>' + esc(tool.installedVersion) + '</strong></span>';
|
|
170
|
+
}
|
|
171
|
+
if (tool.publishedVersion) {
|
|
172
|
+
versionInfo += '<span class="tool-version-item">Published: <strong>' + esc(tool.publishedVersion) + '</strong></span>';
|
|
173
|
+
}
|
|
174
|
+
versionInfo += '</div>';
|
|
175
|
+
}
|
|
165
176
|
|
|
166
177
|
return '<div class="tool-item">' +
|
|
167
178
|
'<div class="tool-header">' +
|
|
@@ -171,6 +182,7 @@
|
|
|
171
182
|
'<span>' + getStatusText(tool) + '</span>' +
|
|
172
183
|
'</span>' +
|
|
173
184
|
'</div>' +
|
|
185
|
+
versionInfo +
|
|
174
186
|
(tool.description ? '<div class="tool-details">' + esc(tool.description) + '</div>' : '') +
|
|
175
187
|
(isInstalling && tool.progress !== undefined ?
|
|
176
188
|
'<div class="tool-progress-container">' +
|