agentgui 1.0.429 → 1.0.431

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.
@@ -10,6 +10,25 @@ function getSpawnOptions(cwd, additionalOptions = {}) {
10
10
  return options;
11
11
  }
12
12
 
13
+ function resolveCommand(command, npxPackage) {
14
+ const whichCmd = isWindows ? 'where' : 'which';
15
+ const check = spawnSync(whichCmd, [command], { encoding: 'utf-8', timeout: 3000 });
16
+ if (check.status === 0 && (check.stdout || '').trim()) {
17
+ return { cmd: command, prefixArgs: [] };
18
+ }
19
+ if (npxPackage) {
20
+ const npxCheck = spawnSync(whichCmd, ['npx'], { encoding: 'utf-8', timeout: 3000 });
21
+ if (npxCheck.status === 0) {
22
+ return { cmd: 'npx', prefixArgs: ['--yes', npxPackage] };
23
+ }
24
+ const bunxCheck = spawnSync(whichCmd, ['bunx'], { encoding: 'utf-8', timeout: 3000 });
25
+ if (bunxCheck.status === 0) {
26
+ return { cmd: 'bunx', prefixArgs: [npxPackage] };
27
+ }
28
+ }
29
+ return { cmd: command, prefixArgs: [] };
30
+ }
31
+
13
32
  /**
14
33
  * Agent Framework
15
34
  * Extensible registry for AI agent CLI integrations
@@ -30,6 +49,7 @@ class AgentRunner {
30
49
  this.requiresAdapter = config.requiresAdapter || false;
31
50
  this.adapterCommand = config.adapterCommand || null;
32
51
  this.adapterArgs = config.adapterArgs || [];
52
+ this.npxPackage = config.npxPackage || null;
33
53
  }
34
54
 
35
55
  defaultBuildArgs(prompt, config) {
@@ -226,9 +246,15 @@ class AgentRunner {
226
246
  onError = null
227
247
  } = config;
228
248
 
229
- const cmd = this.requiresAdapter && this.adapterCommand ? this.adapterCommand : this.command;
230
- const baseArgs = this.requiresAdapter && this.adapterCommand ? this.adapterArgs : this.buildArgs(prompt, config);
231
- const args = [...baseArgs];
249
+ let cmd, args;
250
+ if (this.requiresAdapter && this.adapterCommand) {
251
+ cmd = this.adapterCommand;
252
+ args = [...this.adapterArgs];
253
+ } else {
254
+ const resolved = resolveCommand(this.command, this.npxPackage);
255
+ cmd = resolved.cmd;
256
+ args = [...resolved.prefixArgs, ...this.buildArgs(prompt, config)];
257
+ }
232
258
 
233
259
  const proc = spawn(cmd, args, getSpawnOptions(cwd));
234
260
 
@@ -494,7 +520,8 @@ class AgentRegistry {
494
520
  command: a.command,
495
521
  protocol: a.protocol,
496
522
  requiresAdapter: a.requiresAdapter,
497
- supportedFeatures: a.supportedFeatures
523
+ supportedFeatures: a.supportedFeatures,
524
+ npxPackage: a.npxPackage
498
525
  }));
499
526
  }
500
527
 
@@ -503,11 +530,21 @@ class AgentRegistry {
503
530
  try {
504
531
  const whichCmd = isWindows ? 'where' : 'which';
505
532
  const which = spawnSync(whichCmd, [agent.command], { encoding: 'utf-8', timeout: 3000 });
506
- if (which.status !== 0) return false;
507
- const binPath = (which.stdout || '').trim().split('\n')[0].trim();
508
- if (!binPath) return false;
509
- const check = spawnSync(binPath, ['--version'], { encoding: 'utf-8', timeout: 10000, shell: isWindows });
510
- return check.status === 0 && (check.stdout || '').trim().length > 0;
533
+ if (which.status === 0) {
534
+ const binPath = (which.stdout || '').trim().split('\n')[0].trim();
535
+ if (binPath) {
536
+ const check = spawnSync(binPath, ['--version'], { encoding: 'utf-8', timeout: 10000, shell: isWindows });
537
+ if (check.status === 0 && (check.stdout || '').trim().length > 0) return true;
538
+ }
539
+ }
540
+ const a = this.agents.get(agent.id);
541
+ if (a && a.npxPackage) {
542
+ const npxCheck = spawnSync(whichCmd, ['npx'], { encoding: 'utf-8', timeout: 3000 });
543
+ if (npxCheck.status === 0) return true;
544
+ const bunxCheck = spawnSync(whichCmd, ['bunx'], { encoding: 'utf-8', timeout: 3000 });
545
+ if (bunxCheck.status === 0) return true;
546
+ }
547
+ return false;
511
548
  } catch {
512
549
  return false;
513
550
  }
@@ -571,6 +608,7 @@ registry.register({
571
608
  command: 'opencode',
572
609
  protocol: 'acp',
573
610
  supportsStdin: false,
611
+ npxPackage: 'opencode-ai',
574
612
  supportedFeatures: ['streaming', 'resume', 'acp-protocol'],
575
613
 
576
614
  buildArgs(prompt, config) {
@@ -923,6 +961,7 @@ registry.register({
923
961
  command: 'gemini',
924
962
  protocol: 'acp',
925
963
  supportsStdin: false,
964
+ npxPackage: '@google/gemini-cli',
926
965
  supportedFeatures: ['streaming', 'resume', 'acp-protocol'],
927
966
  buildArgs(prompt, config) {
928
967
  const args = ['--experimental-acp', '--yolo'];
@@ -1085,6 +1124,7 @@ registry.register({
1085
1124
  command: 'kilo',
1086
1125
  protocol: 'acp',
1087
1126
  supportsStdin: false,
1127
+ npxPackage: '@kilocode/cli',
1088
1128
  supportedFeatures: ['streaming', 'resume', 'acp-protocol', 'models'],
1089
1129
 
1090
1130
  buildArgs(prompt, config) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentgui",
3
- "version": "1.0.429",
3
+ "version": "1.0.431",
4
4
  "description": "Multi-agent ACP client with real-time communication",
5
5
  "type": "module",
6
6
  "main": "server.js",
package/server.js CHANGED
@@ -384,9 +384,9 @@ function discoverAgents() {
384
384
  const agents = [];
385
385
  const binaries = [
386
386
  { cmd: 'claude', id: 'claude-code', name: 'Claude Code', icon: 'C', protocol: 'cli' },
387
- { cmd: 'opencode', id: 'opencode', name: 'OpenCode', icon: 'O', protocol: 'acp' },
388
- { cmd: 'gemini', id: 'gemini', name: 'Gemini CLI', icon: 'G', protocol: 'acp' },
389
- { cmd: 'kilo', id: 'kilo', name: 'Kilo Code', icon: 'K', protocol: 'acp' },
387
+ { cmd: 'opencode', id: 'opencode', name: 'OpenCode', icon: 'O', protocol: 'acp', npxPackage: 'opencode-ai' },
388
+ { cmd: 'gemini', id: 'gemini', name: 'Gemini CLI', icon: 'G', protocol: 'acp', npxPackage: '@google/gemini-cli' },
389
+ { cmd: 'kilo', id: 'kilo', name: 'Kilo Code', icon: 'K', protocol: 'acp', npxPackage: '@kilocode/cli' },
390
390
  { cmd: 'goose', id: 'goose', name: 'Goose', icon: 'g', protocol: 'acp' },
391
391
  { cmd: 'openhands', id: 'openhands', name: 'OpenHands', icon: 'H', protocol: 'acp' },
392
392
  { cmd: 'augment', id: 'augment', name: 'Augment Code', icon: 'A', protocol: 'acp' },
@@ -400,13 +400,11 @@ function discoverAgents() {
400
400
  ];
401
401
  for (const bin of binaries) {
402
402
  const result = findCommand(bin.cmd);
403
- if (result) agents.push({
404
- id: bin.id,
405
- name: bin.name,
406
- icon: bin.icon,
407
- path: result,
408
- protocol: bin.protocol
409
- });
403
+ if (result) {
404
+ agents.push({ id: bin.id, name: bin.name, icon: bin.icon, path: result, protocol: bin.protocol });
405
+ } else if (bin.npxPackage) {
406
+ agents.push({ id: bin.id, name: bin.name, icon: bin.icon, path: null, protocol: bin.protocol, npxPackage: bin.npxPackage, npxLaunchable: true });
407
+ }
410
408
  }
411
409
  return agents;
412
410
  }
@@ -444,87 +442,8 @@ function modelIdToLabel(id) {
444
442
  return base.replace(/-/g, ' ').replace(/\b\w/g, c => c.toUpperCase());
445
443
  }
446
444
 
447
- async function fetchClaudeModelsFromAPI() {
448
- const apiKey = process.env.ANTHROPIC_API_KEY;
449
- if (!apiKey) return null;
450
- try {
451
- const https = await import('https');
452
- return new Promise((resolve) => {
453
- const req = https.default.request({
454
- hostname: 'api.anthropic.com', path: '/v1/models', method: 'GET',
455
- headers: { 'x-api-key': apiKey, 'anthropic-version': '2023-06-01' },
456
- timeout: 8000
457
- }, (res) => {
458
- let body = '';
459
- res.on('data', d => body += d);
460
- res.on('end', () => {
461
- try {
462
- const data = JSON.parse(body);
463
- const items = (data.data || []).filter(m => m.id && m.id.startsWith('claude-'));
464
- if (items.length === 0) return resolve(null);
465
- const models = items.map(m => ({ id: m.id, label: m.display_name || modelIdToLabel(m.id) }));
466
- resolve(models);
467
- } catch { resolve(null); }
468
- });
469
- });
470
- req.on('error', () => resolve(null));
471
- req.on('timeout', () => { req.destroy(); resolve(null); });
472
- req.end();
473
- });
474
- } catch { return null; }
475
- }
476
-
477
- async function fetchGeminiModelsFromAPI() {
478
- const apiKey = process.env.GOOGLE_GENAI_API_KEY;
479
- if (!apiKey) return null;
480
- try {
481
- const https = await import('https');
482
- return new Promise((resolve) => {
483
- const req = https.default.request({
484
- hostname: 'generativelanguage.googleapis.com',
485
- path: '/v1beta/models?key=' + apiKey,
486
- method: 'GET',
487
- timeout: 8000
488
- }, (res) => {
489
- let body = '';
490
- res.on('data', d => body += d);
491
- res.on('end', () => {
492
- try {
493
- const data = JSON.parse(body);
494
- const items = (data.models || []).filter(m => m.name && m.name.includes('gemini'));
495
- if (items.length === 0) return resolve(null);
496
- const models = items.map(m => {
497
- const modelId = m.name.replace(/^models\//, '');
498
- return { id: modelId, label: modelId.replace(/-/g, ' ').replace(/\b\w/g, c => c.toUpperCase()) };
499
- });
500
- resolve(models);
501
- } catch { resolve(null); }
502
- });
503
- });
504
- req.on('error', () => resolve(null));
505
- req.on('timeout', () => { req.destroy(); resolve(null); });
506
- req.end();
507
- });
508
- } catch { return null; }
509
- }
510
-
511
- async function getModelsForAgent(agentId) {
512
- const cached = modelCache.get(agentId);
513
- if (cached && Date.now() - cached.timestamp < 3600000) {
514
- return cached.models;
515
- }
516
-
517
- let models = null;
518
-
519
- if (agentId === 'claude-code') {
520
- models = await fetchClaudeModelsFromAPI();
521
- } else if (agentId === 'gemini') {
522
- models = await fetchGeminiModelsFromAPI();
523
- }
524
-
525
- const result = models || [];
526
- modelCache.set(agentId, { models: result, timestamp: Date.now() });
527
- return result;
445
+ async function getModelsForAgent() {
446
+ return [];
528
447
  }
529
448
 
530
449
  const GEMINI_SCOPES = [