agentgui 1.0.436 → 1.0.437
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/ws-handlers-session.js +23 -128
- package/package.json +1 -1
- package/server.js +21 -49
|
@@ -68,71 +68,6 @@ async function acpFetch(port, pth, body = null) {
|
|
|
68
68
|
return res.json();
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
function getApiKey(name) {
|
|
72
|
-
const envMap = {
|
|
73
|
-
anthropic: 'ANTHROPIC_API_KEY',
|
|
74
|
-
google: 'GOOGLE_GENAI_API_KEY',
|
|
75
|
-
openai: 'OPENAI_API_KEY'
|
|
76
|
-
};
|
|
77
|
-
if (process.env[envMap[name]]) return process.env[envMap[name]];
|
|
78
|
-
const configPaths = {
|
|
79
|
-
anthropic: [
|
|
80
|
-
path.join(os.homedir(), '.claude.json'),
|
|
81
|
-
path.join(os.homedir(), '.anthropic.json')
|
|
82
|
-
],
|
|
83
|
-
google: [
|
|
84
|
-
path.join(os.homedir(), '.gemini.json'),
|
|
85
|
-
path.join(os.homedir(), '.config', 'gemini', 'credentials.json')
|
|
86
|
-
],
|
|
87
|
-
openai: [
|
|
88
|
-
path.join(os.homedir(), '.openai.json')
|
|
89
|
-
]
|
|
90
|
-
};
|
|
91
|
-
for (const p of (configPaths[name] || [])) {
|
|
92
|
-
const data = readJson(p);
|
|
93
|
-
if (data) {
|
|
94
|
-
const key = data.api_key || data.apiKey || data.github_token;
|
|
95
|
-
if (key) return key;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
return null;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
async function fetchModelsFromAPI(agentId) {
|
|
102
|
-
if (agentId === 'claude-code') {
|
|
103
|
-
const apiKey = getApiKey('anthropic');
|
|
104
|
-
if (!apiKey) return null;
|
|
105
|
-
try {
|
|
106
|
-
const res = await fetch('https://api.anthropic.com/v1/models', {
|
|
107
|
-
headers: { 'x-api-key': apiKey, 'anthropic-version': '2023-06-01' },
|
|
108
|
-
signal: AbortSignal.timeout(8000)
|
|
109
|
-
});
|
|
110
|
-
if (!res.ok) return null;
|
|
111
|
-
const data = await res.json();
|
|
112
|
-
const items = (data.data || []).filter(m => m.id && m.id.startsWith('claude-'));
|
|
113
|
-
if (items.length === 0) return null;
|
|
114
|
-
return items.map(m => ({ id: m.id, label: m.display_name || m.id.replace(/-/g, ' ').replace(/\b\w/g, c => c.toUpperCase()) }));
|
|
115
|
-
} catch { return null; }
|
|
116
|
-
}
|
|
117
|
-
if (agentId === 'gemini') {
|
|
118
|
-
const apiKey = getApiKey('google');
|
|
119
|
-
if (!apiKey) return null;
|
|
120
|
-
try {
|
|
121
|
-
const res = await fetch(`https://generativelanguage.googleapis.com/v1beta/models?key=${apiKey}`, {
|
|
122
|
-
signal: AbortSignal.timeout(8000)
|
|
123
|
-
});
|
|
124
|
-
if (!res.ok) return null;
|
|
125
|
-
const data = await res.json();
|
|
126
|
-
const items = (data.models || []).filter(m => m.name && m.name.includes('gemini'));
|
|
127
|
-
if (items.length === 0) return null;
|
|
128
|
-
return items.map(m => {
|
|
129
|
-
const id = m.name.replace(/^models\//, '');
|
|
130
|
-
return { id, label: id.replace(/-/g, ' ').replace(/\b\w/g, c => c.toUpperCase()) };
|
|
131
|
-
});
|
|
132
|
-
} catch { return null; }
|
|
133
|
-
}
|
|
134
|
-
return null;
|
|
135
|
-
}
|
|
136
71
|
|
|
137
72
|
export function register(router, deps) {
|
|
138
73
|
const { db, discoveredAgents, modelCache,
|
|
@@ -194,69 +129,29 @@ export function register(router, deps) {
|
|
|
194
129
|
return d;
|
|
195
130
|
});
|
|
196
131
|
|
|
197
|
-
router.handle('agent.models', async (p) => {
|
|
198
|
-
const cached = modelCache.get(p.id);
|
|
199
|
-
if (cached && (Date.now() - cached.ts) < 300000) return { models: cached.models };
|
|
200
|
-
|
|
201
|
-
if (
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
const id = m.id || m;
|
|
221
|
-
if (id) allModels.set(id, m.name || m.label || id);
|
|
222
|
-
}
|
|
223
|
-
try {
|
|
224
|
-
const desc = await acpFetch(port, `/agents/${agentId}/descriptor`);
|
|
225
|
-
const enumVals = desc?.specs?.config?.properties?.model?.enum || desc?.specs?.input?.properties?.model?.enum || [];
|
|
226
|
-
for (const v of enumVals) allModels.set(v, v);
|
|
227
|
-
} catch (_) {}
|
|
228
|
-
}
|
|
229
|
-
if (allModels.size > 0) {
|
|
230
|
-
const models = Array.from(allModels.entries()).map(([id, label]) => ({ id, label }));
|
|
231
|
-
modelCache.set(p.id, { models, ts: Date.now() });
|
|
232
|
-
return { models };
|
|
233
|
-
}
|
|
234
|
-
} catch (_) {}
|
|
235
|
-
}
|
|
236
|
-
const acpAgents = discoveredAgents.filter(x => x.protocol === 'acp' && x.acpPort);
|
|
237
|
-
for (const acpAgent of acpAgents) {
|
|
238
|
-
const port = acpAgent.acpPort;
|
|
239
|
-
try {
|
|
240
|
-
const desc = await acpFetch(port, `/agents/${p.id}/descriptor`);
|
|
241
|
-
if (desc) {
|
|
242
|
-
const enumVals = desc?.specs?.config?.properties?.model?.enum || desc?.specs?.input?.properties?.model?.enum || [];
|
|
243
|
-
if (enumVals.length > 0) {
|
|
244
|
-
const models = enumVals.map(v => ({ id: v, label: v }));
|
|
245
|
-
modelCache.set(p.id, { models, ts: Date.now() });
|
|
246
|
-
return { models };
|
|
247
|
-
}
|
|
248
|
-
const name = desc?.metadata?.ref?.name;
|
|
249
|
-
if (name) { const models = [{ id: p.id, label: name }]; modelCache.set(p.id, { models, ts: Date.now() }); return { models }; }
|
|
250
|
-
}
|
|
251
|
-
} catch (_) {}
|
|
252
|
-
}
|
|
253
|
-
const apiModels = await fetchModelsFromAPI(p.id);
|
|
254
|
-
if (apiModels && apiModels.length > 0) {
|
|
255
|
-
modelCache.set(p.id, { models: apiModels, ts: Date.now() });
|
|
256
|
-
return { models: apiModels };
|
|
257
|
-
}
|
|
258
|
-
return { models: [] };
|
|
259
|
-
});
|
|
132
|
+
router.handle('agent.models', async (p) => {
|
|
133
|
+
const cached = modelCache.get(p.id);
|
|
134
|
+
if (cached && (Date.now() - cached.ts) < 300000) return { models: cached.models };
|
|
135
|
+
let models = [];
|
|
136
|
+
if (p.id === 'claude-code') {
|
|
137
|
+
models = [
|
|
138
|
+
{ id: 'claude-haiku', label: 'Haiku' },
|
|
139
|
+
{ id: 'claude-sonnet', label: 'Sonnet' },
|
|
140
|
+
{ id: 'claude-opus', label: 'Opus' }
|
|
141
|
+
];
|
|
142
|
+
} else {
|
|
143
|
+
const agent = discoveredAgents.find(x => x.id === p.id);
|
|
144
|
+
if (agent?.protocol === 'acp' && agent.acpPort) {
|
|
145
|
+
try {
|
|
146
|
+
const data = await acpFetch(agent.acpPort, '/models');
|
|
147
|
+
const list = data?.data || data?.models || (Array.isArray(data) ? data : []);
|
|
148
|
+
models = list.map(m => ({ id: m.id || m.model_id, label: m.name || m.display_name || m.id || m.model_id })).filter(m => m.id);
|
|
149
|
+
} catch (_) {}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
if (models.length > 0) modelCache.set(p.id, { models, ts: Date.now() });
|
|
153
|
+
return { models };
|
|
154
|
+
});
|
|
260
155
|
|
|
261
156
|
router.handle('agent.search', (p) => db.searchAgents(discoveredAgents, p.query || p));
|
|
262
157
|
|
package/package.json
CHANGED
package/server.js
CHANGED
|
@@ -411,22 +411,13 @@ function discoverAgents() {
|
|
|
411
411
|
|
|
412
412
|
// Function to discover agents from external ACP servers
|
|
413
413
|
async function discoverExternalACPServers() {
|
|
414
|
-
// Default ACP servers to query (excluding local server to prevent recursion)
|
|
415
|
-
const acpServers = [
|
|
416
|
-
'http://localhost:8080', // Common default ACP port
|
|
417
|
-
];
|
|
418
|
-
|
|
419
414
|
const externalAgents = [];
|
|
420
|
-
for (const
|
|
415
|
+
for (const agent of discoveredAgents.filter(a => a.protocol === 'acp' && a.acpPort)) {
|
|
421
416
|
try {
|
|
422
|
-
|
|
423
|
-
const agents = await queryACPServerAgents(serverUrl);
|
|
417
|
+
const agents = await queryACPServerAgents(`http://localhost:${agent.acpPort}`);
|
|
424
418
|
externalAgents.push(...agents);
|
|
425
|
-
} catch (
|
|
426
|
-
console.error(`Failed to query ${serverUrl}:`, error.message);
|
|
427
|
-
}
|
|
419
|
+
} catch (_) {}
|
|
428
420
|
}
|
|
429
|
-
|
|
430
421
|
return externalAgents;
|
|
431
422
|
}
|
|
432
423
|
|
|
@@ -435,53 +426,34 @@ initializeDescriptors(discoveredAgents);
|
|
|
435
426
|
|
|
436
427
|
const modelCache = new Map();
|
|
437
428
|
|
|
438
|
-
function modelIdToLabel(id) {
|
|
439
|
-
const base = id.replace(/^claude-/, '').replace(/-\d{8}$/, '');
|
|
440
|
-
const m = base.match(/^(\w+)-(\d+)(?:-(\d+))?$/);
|
|
441
|
-
if (m) return `${m[1].charAt(0).toUpperCase() + m[1].slice(1)} ${m[3] ? m[2] + '.' + m[3] : m[2]}`;
|
|
442
|
-
return base.replace(/-/g, ' ').replace(/\b\w/g, c => c.toUpperCase());
|
|
443
|
-
}
|
|
444
|
-
|
|
445
429
|
async function getModelsForAgent(agentId) {
|
|
446
430
|
const cached = modelCache.get(agentId);
|
|
447
|
-
if (cached && Date.now() - cached.timestamp <
|
|
448
|
-
let models =
|
|
431
|
+
if (cached && Date.now() - cached.timestamp < 300000) return cached.models;
|
|
432
|
+
let models = [];
|
|
449
433
|
if (agentId === 'claude-code') {
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
const data = await res.json();
|
|
459
|
-
const items = (data.data || []).filter(m => m.id && m.id.startsWith('claude-'));
|
|
460
|
-
if (items.length > 0) models = items.map(m => ({ id: m.id, label: m.display_name || modelIdToLabel(m.id) }));
|
|
461
|
-
}
|
|
462
|
-
} catch (_) {}
|
|
463
|
-
}
|
|
464
|
-
} else if (agentId === 'gemini') {
|
|
465
|
-
const apiKey = process.env.GOOGLE_GENAI_API_KEY;
|
|
466
|
-
if (apiKey) {
|
|
434
|
+
models = [
|
|
435
|
+
{ id: 'claude-haiku', label: 'Haiku' },
|
|
436
|
+
{ id: 'claude-sonnet', label: 'Sonnet' },
|
|
437
|
+
{ id: 'claude-opus', label: 'Opus' }
|
|
438
|
+
];
|
|
439
|
+
} else {
|
|
440
|
+
const agent = discoveredAgents.find(a => a.id === agentId);
|
|
441
|
+
if (agent?.protocol === 'acp' && agent.acpPort) {
|
|
467
442
|
try {
|
|
468
|
-
const res = await fetch(`
|
|
469
|
-
|
|
443
|
+
const res = await fetch(`http://localhost:${agent.acpPort}/models`, {
|
|
444
|
+
headers: { 'Content-Type': 'application/json' },
|
|
445
|
+
signal: AbortSignal.timeout(3000)
|
|
470
446
|
});
|
|
471
447
|
if (res.ok) {
|
|
472
448
|
const data = await res.json();
|
|
473
|
-
const
|
|
474
|
-
|
|
475
|
-
const id = m.name.replace(/^models\//, '');
|
|
476
|
-
return { id, label: id.replace(/-/g, ' ').replace(/\b\w/g, c => c.toUpperCase()) };
|
|
477
|
-
});
|
|
449
|
+
const list = data?.data || data?.models || (Array.isArray(data) ? data : []);
|
|
450
|
+
models = list.map(m => ({ id: m.id || m.model_id, label: m.name || m.display_name || m.id || m.model_id })).filter(m => m.id);
|
|
478
451
|
}
|
|
479
452
|
} catch (_) {}
|
|
480
453
|
}
|
|
481
454
|
}
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
return result;
|
|
455
|
+
modelCache.set(agentId, { models, timestamp: Date.now() });
|
|
456
|
+
return models;
|
|
485
457
|
}
|
|
486
458
|
|
|
487
459
|
const GEMINI_SCOPES = [
|
|
@@ -3851,7 +3823,7 @@ registerConvHandlers(wsRouter, {
|
|
|
3851
3823
|
});
|
|
3852
3824
|
|
|
3853
3825
|
registerSessionHandlers(wsRouter, {
|
|
3854
|
-
db: queries, discoveredAgents,
|
|
3826
|
+
db: queries, discoveredAgents, modelCache,
|
|
3855
3827
|
getAgentDescriptor, activeScripts, broadcastSync,
|
|
3856
3828
|
startGeminiOAuth, geminiOAuthState: () => geminiOAuthState
|
|
3857
3829
|
});
|