agentgui 1.0.640 → 1.0.642

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,8 +10,8 @@ function getSpawnOptions(cwd, additionalOptions = {}) {
10
10
  if (!options.env) {
11
11
  options.env = { ...process.env };
12
12
  }
13
- // Allow spawning claude inside another claude session
14
- delete options.env.CLAUDECODE;
13
+ // Keep CLAUDECODE for plugin support (gm plugin requires this)
14
+ // Don't delete it as it prevents plugins from loading
15
15
  return options;
16
16
  }
17
17
 
@@ -613,7 +613,7 @@ registry.register({
613
613
  closeStdin: true, // must close stdin or claude 2.1.72 hangs waiting for input in --print mode
614
614
  useJsonRpcStdin: false,
615
615
  supportedFeatures: ['streaming', 'resume', 'system-prompt', 'permissions-skip'],
616
- spawnEnv: { MAX_THINKING_TOKENS: '0', AGENTGUI_SUBPROCESS: '1' },
616
+ spawnEnv: { MAX_THINKING_TOKENS: '0' },
617
617
 
618
618
  buildArgs(prompt, config) {
619
619
  const {
@@ -1,7 +1,7 @@
1
1
  import fs from 'fs';
2
2
  import os from 'os';
3
3
  import path from 'path';
4
- import { execSync, spawn } from 'child_process';
4
+ import { execSync, spawn, spawnSync } from 'child_process';
5
5
 
6
6
  function err(code, message) { const e = new Error(message); e.code = code; throw e; }
7
7
 
@@ -268,65 +268,47 @@ export function register(router, deps) {
268
268
  }
269
269
  });
270
270
 
271
- router.handle('agent.subagents', async (p) => {
272
- const { id } = p;
273
- if (!id) err(400, 'Missing agent id');
274
-
275
- // For Claude Code, read skills from ~/.claude/skills directory
276
- if (id === 'cli-claude') {
277
- const skillsDir = path.join(os.homedir(), '.claude', 'skills');
278
- try {
279
- const entries = fs.readdirSync(skillsDir, { withFileTypes: true });
280
- const skills = entries
281
- .filter(e => e.isDirectory() || e.isSymbolicLink())
282
- .map(e => {
283
- // Try to read SKILL.md to get the actual name
284
- const md = path.join(skillsDir, e.name, 'SKILL.md');
285
- let name = e.name;
286
- try {
287
- const content = fs.readFileSync(md, 'utf-8');
288
- const m = content.match(/^name:\s*(.+)$/m);
289
- if (m) name = m[1].trim();
290
- } catch (_) {
291
- // Fallback: format the directory name as the skill name
292
- name = e.name
293
- .split(/[\-_]/)
294
- .map(w => w.charAt(0).toUpperCase() + w.slice(1))
295
- .join(' ');
296
- }
297
- return { id: e.name, name };
298
- })
299
- .sort((a, b) => a.name.localeCompare(b.name));
300
-
301
- if (skills.length > 0) {
302
- console.log(`[agent.subagents] Found ${skills.length} Claude Code skills:`, skills.map(s => s.name).join(', '));
303
- return { subAgents: skills };
304
- }
305
- return { subAgents: [] };
306
- } catch (err) {
307
- console.error(`[agent.subagents] Error reading skills directory:`, err.message);
308
- return { subAgents: [] };
309
- }
310
- }
311
-
312
- // Map CLI agent IDs to their corresponding plugin sub-agents
313
- const subAgentMap = {
314
- 'cli-opencode': [{ id: 'gm-oc', name: 'GM OpenCode' }],
315
- 'cli-gemini': [{ id: 'gm-gc', name: 'GM Gemini' }],
316
- 'cli-kilo': [{ id: 'gm-kilo', name: 'GM Kilo' }],
317
- 'cli-codex': []
318
- };
319
-
320
- const subAgents = subAgentMap[id] || [];
321
-
322
- // Filter to only installed sub-agents
323
- try {
324
- const tools = await toolManager.getAllToolsAsync();
325
- const installedPlugins = new Set(tools.filter(t => t.category === 'plugin' && t.installed).map(t => t.id));
326
- const availableSubAgents = subAgents.filter(sa => installedPlugins.has(sa.id));
327
- return { subAgents: availableSubAgents };
328
- } catch (e) {
329
- return { subAgents };
330
- }
271
+ router.handle('agent.subagents', async (p) => {
272
+ const { id } = p;
273
+ if (!id) err(400, 'Missing agent id');
274
+
275
+ // Claude Code: run 'claude agents list' and parse output
276
+ if (id === 'claude-code' || id === 'cli-claude') {
277
+ const spawnEnv = { ...process.env };
278
+ delete spawnEnv.CLAUDECODE;
279
+ const result = spawnSync('claude', ['agents', 'list'], {
280
+ encoding: 'utf-8', timeout: 10000, stdio: ['pipe', 'pipe', 'pipe'],
281
+ env: spawnEnv
282
+ });
283
+ if (result.status !== 0 || !result.stdout) return { subAgents: [] };
284
+ const output = result.stdout.trim();
285
+ // Output format: ' agentId · model' lines under section headers
286
+ const agents = [];
287
+ for (const line of output.split('\n').filter(l => l.trim())) {
288
+ const match = line.match(/^ (\S+)\s+·/);
289
+ if (match) {
290
+ const id = match[1];
291
+ agents.push({ id, name: id });
292
+ }
293
+ }
294
+ console.log('[agent.subagents] claude agents list found:', agents.map(a => a.id).join(', '));
295
+ return { subAgents: agents };
296
+ }
297
+
298
+ // ACP agents: hardcoded map filtered by installed tools
299
+ const subAgentMap = {
300
+ 'opencode': [{ id: 'gm-oc', name: 'GM OpenCode' }],
301
+ 'cli-opencode': [{ id: 'gm-oc', name: 'GM OpenCode' }],
302
+ 'gemini': [{ id: 'gm-gc', name: 'GM Gemini' }],
303
+ 'cli-gemini': [{ id: 'gm-gc', name: 'GM Gemini' }],
304
+ 'kilo': [{ id: 'gm-kilo', name: 'GM Kilo' }],
305
+ 'cli-kilo': [{ id: 'gm-kilo', name: 'GM Kilo' }],
306
+ 'codex': [],
307
+ 'cli-codex': []
308
+ };
309
+ const subAgents = subAgentMap[id] || [];
310
+ const tools = await toolManager.getAllToolsAsync();
311
+ const installed = new Set(tools.filter(t => t.category === 'plugin' && t.installed).map(t => t.id));
312
+ return { subAgents: subAgents.filter(sa => installed.has(sa.id)) };
331
313
  });
332
314
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentgui",
3
- "version": "1.0.640",
3
+ "version": "1.0.642",
4
4
  "description": "Multi-agent ACP client with real-time communication",
5
5
  "type": "module",
6
6
  "main": "server.js",
package/server.js CHANGED
@@ -534,9 +534,12 @@ function discoverAgents() {
534
534
  console.log(`[discoverAgents] Skipping CLI wrapper ${wrapper.id} (ACP agent ${wrapper.acpId} not found)`);
535
535
  }
536
536
  }
537
- console.log('[discoverAgents] Final agent count:', agents.length, 'Agent IDs:', agents.map(a => a.id).join(', '));
537
+ // Remove raw ACP agents that have a cli-wrapper (avoid duplicates in UI)
538
+ const wrappedAcpIds = new Set(cliWrappers.filter(w => agents.some(a => a.id === w.acpId)).map(w => w.acpId));
539
+ const filtered = agents.filter(a => !wrappedAcpIds.has(a.id));
540
+ console.log('[discoverAgents] Final agent count:', filtered.length, 'Agent IDs:', filtered.map(a => a.id).join(', '));
538
541
 
539
- return agents;
542
+ return filtered;
540
543
  }
541
544
 
542
545
  // Function to discover agents from external ACP servers
package/static/index.html CHANGED
@@ -1120,9 +1120,6 @@
1120
1120
  .message { max-width: 95%; }
1121
1121
  .messages-wrapper { padding: 0.375rem 0.5rem; }
1122
1122
  .input-section { padding: 0.5rem; padding-bottom: calc(0.5rem + env(safe-area-inset-bottom)); }
1123
- .cli-selector { display: none !important; }
1124
- .sub-agent-selector { display: none !important; }
1125
- .model-selector { display: none !important; }
1126
1123
  }
1127
1124
 
1128
1125
  /* ===== SCROLLBAR STYLING ===== */
@@ -442,10 +442,10 @@ class AgentGUIClient {
442
442
 
443
443
  if (this.ui.agentSelector) {
444
444
  this.ui.agentSelector.addEventListener('change', () => {
445
- // Load models for the selected sub-agent
446
- const selectedSubAgentId = this.ui.agentSelector.value;
447
- if (selectedSubAgentId) {
448
- this.loadModelsForAgent(selectedSubAgentId);
445
+ // Load models for parent CLI agent when sub-agent changes
446
+ const parentAgentId = this.ui.cliSelector?.value;
447
+ if (parentAgentId) {
448
+ this.loadModelsForAgent(parentAgentId);
449
449
  }
450
450
  if (!this._agentLocked) {
451
451
  this.saveAgentAndModelToConversation();
@@ -2076,7 +2076,7 @@ class AgentGUIClient {
2076
2076
  // Auto-select first sub-agent and load its models
2077
2077
  const firstSubAgentId = subAgents[0].id;
2078
2078
  this.ui.agentSelector.value = firstSubAgentId;
2079
- this.loadModelsForAgent(firstSubAgentId);
2079
+ this.loadModelsForAgent(cliAgentId); // models keyed to parent agent
2080
2080
  } else {
2081
2081
  console.log(`[Agent Selector] No sub-agents found for ${cliAgentId}`);
2082
2082
  // Load models for the CLI agent itself (fallback for agents without sub-agents)