agentgui 1.0.1120 → 1.0.1121

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/.gm/prd.yml CHANGED
@@ -1,8 +1,3 @@
1
- - id: aaa-consolidate-acp-http-routing
2
- subject: Route chat.sendMessage's ACP prompt through acp-sdk-manager's already-running HTTP server instead of claude-runner-acp.js spawning a fresh stdio subprocess per turn
3
- witness: 'MAJOR PROGRESS this session, sha f5e57db253: root-caused opencode''s HTTP server appearing unreachable (same stdin-EOF disposal bug as acp-sdk-manager.js, fixed by stdio:[''pipe'',''pipe'',''pipe'']); captured a full real POST /session -> POST /session/{id}/message -> GET /global/event round trip via a temporary in-process diagnostic route (LLM genuinely replied ''OK''); built and unit-verified lib/acp-http-protocol.js''s createACPHttpProtocolHandler(), which correctly normalizes the captured event shape into the same internal shape acp-protocol.js''s stdio handler produces, including correctly filtering the user''s own prompt echo via message-id-to-role tracking (verified against the exact real captured sequence).'
4
- description: 'Remaining step: wire the verified normalizer into the live chat.sendMessage path. Concretely: (1) in lib/claude-runner-acp.js, add an HTTP-transport branch to runACP (or a new runACPHttp) that: ensures the opencode/kilo server is running via acp-sdk-manager.ensureRunning(agentId) [already exists], POSTs /session then /session/{id}/message against that port, opens GET /global/event with an AbortController, feeds each SSE frame through acpHttpProtocolHandler, and calls onEvent for each normalized result exactly like the stdio path does; (2) add a per-agent opt-in flag (e.g. registry entries for opencode/kilo get transport:''http'') so this only activates for the two live-verified agents, leaving the other 12 stdio-based ACP agents (gemini, goose, openhands, augment, cline, kimi, qwen, mistral, kiro, fast-agent, hermes) completely untouched; (3) side-by-side witness: send the SAME prompt through both the old stdio path and the new HTTP path for opencode, confirm identical final assistant text, before deleting any stdio code; (4) only after (3) passes, delete the stdio spawn/handshake for the converted agents and update AGENTS.md''s ACP CRITICAL rule to be literally true. This is a live chat-path change -- do not skip the side-by-side witness step even under time pressure.'
5
- status: pending
6
1
  - id: aaa-split-app-js-god-file
7
2
  subject: Extract site/app/js/app.js's mixed concerns into per-concern modules
8
3
  witness: 'Slice 1/4 DONE (chat-persistence, sha d211f32cbd, live-witnessed). Slice 2 (keyboard shortcuts, app.js:4649-4758 as of this commit) was investigated concretely: the global keydown handler references ~10 app.js-local functions across every feature area (navTo, closeFileDialog, filesMarked, clearFileSelection, cancelChat, newChat, previewNeighbours, openPreview, announce, render) plus state fields spanning chat/files/live/settings -- the highest cross-cutting coupling in the file. This is the exact code AGENTS.md flags as historically crash-prone under webjsx keying mistakes, and a rushed extraction threading 10 dependencies through a factory is a real correctness risk, not a mechanical move.'
package/AGENTS.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # AgentGUI — Agent Notes
2
2
 
3
- ## CRITICAL — ACP is managed ONLY by `lib/acp-sdk-manager.js`
3
+ ## CRITICAL — ACP process lifecycle: two live transports, by design, not drift
4
4
 
5
- ACP lifecycle lives in `lib/acp-sdk-manager.js` alone; no other module spawns or manages ACP agent processes. Every `spawn()` callsite needs a `proc.on('error', …)` handler (ENOENT surfaces async under Bun).
5
+ `lib/acp-sdk-manager.js` owns spawning every ACP-protocol agent's underlying process — no other module spawns an ACP CLI subprocess. On top of that single spawn point, TWO transports exist for the actual per-turn prompt: **stdio JSON-RPC** (`lib/claude-runner-acp.js`'s `_runACPOnce`, the default for all ACP agents) and **HTTP+SSE** (`lib/claude-runner-acp.js`'s `_runACPHttp`, opt-in via a registry entry's `transport:'http'`, currently only `opencode` — live side-by-side verified byte-identical final output against the stdio path for the same prompt). `AgentRunner.runACP` dispatches between them by `this.transport`. Adding a new HTTP-transport agent requires the same live verification (capture real SSE frames, extend `lib/acp-http-protocol.js`'s normalizer, side-by-side prompt comparison) before flipping its registry flag — never assume HTTP-transport parity from CLI-family resemblance alone (kilo shares `@kilocode/cli`'s lineage with opencode but was never independently verified). Every `spawn()` callsite needs a `proc.on('error', …)` handler (ENOENT surfaces async under Bun). `acp-sdk-manager.js`'s `ACP_TOOLS` entries MUST pass `--port <port>` explicitly in `args` — `acp` alone defaults `--port` to `0` (an OS-assigned ephemeral port), silently breaking every health-check/HTTP-transport call against the tracked fixed port.
6
6
 
7
7
  ## CRITICAL — `authedFetch` must NOT set `Authorization: Bearer` behind an nginx Basic-Auth proxy
8
8
 
@@ -141,7 +141,13 @@ registry.register({
141
141
  return { type: 'assistant', message: { content: [{ type: 'text', text }] } };
142
142
  },
143
143
  });
144
- registry.register({ id: 'opencode', name: 'OpenCode', command: 'opencode', protocol: 'acp', supportsStdin: false, npxPackage: 'opencode-ai', supportedFeatures: ['streaming', 'resume', 'acp-protocol'], buildArgs: () => ['acp'], protocolHandler: acpProtocolHandler });
144
+ // transport:'http' routes runACP through AgentRunner._runACPHttp (reuses the
145
+ // long-lived server acp-sdk-manager.js already spawns for health/model
146
+ // discovery) instead of spawning a fresh stdio subprocess per turn -
147
+ // live-verified equivalent to the stdio path (same prompt, byte-identical
148
+ // final assistant text, side-by-side witnessed). kilo is NOT flagged here:
149
+ // its HTTP event shape was never independently live-verified this session.
150
+ registry.register({ id: 'opencode', name: 'OpenCode', command: 'opencode', protocol: 'acp', transport: 'http', supportsStdin: false, npxPackage: 'opencode-ai', supportedFeatures: ['streaming', 'resume', 'acp-protocol'], buildArgs: () => ['acp'], protocolHandler: acpProtocolHandler });
145
151
  registry.register({ id: 'gemini', name: 'Gemini CLI', command: 'gemini', protocol: 'acp', supportsStdin: false, npxPackage: '@google/gemini-cli', supportedFeatures: ['streaming', 'resume', 'acp-protocol'], buildArgs(prompt, config) { const args = ['--experimental-acp', '--yolo']; if (config?.model) args.push('--model', config.model); return args; }, protocolHandler: acpProtocolHandler });
146
152
  registry.register({ id: 'goose', name: 'Goose', command: 'goose', protocol: 'acp', supportsStdin: false, supportedFeatures: ['streaming', 'resume', 'acp-protocol'], buildArgs: () => ['acp'], protocolHandler: acpProtocolHandler });
147
153
  registry.register({ id: 'openhands', name: 'OpenHands', command: 'openhands', protocol: 'acp', supportsStdin: false, supportedFeatures: ['streaming', 'resume', 'acp-protocol'], buildArgs: () => ['acp'], protocolHandler: acpProtocolHandler });
@@ -60,30 +60,6 @@ export function register(router, deps) {
60
60
  return { ok: !!ok };
61
61
  });
62
62
 
63
- // TEMPORARY diagnostic route (aaa-consolidate-acp-http-routing): exercises
64
- // AgentRunner.runACP's new transport:'http' branch through the server's own
65
- // long-lived process (a one-shot exec_js dispatch's process dies with the
66
- // dispatch, killing acp-sdk-manager's non-detached child opencode with it -
67
- // this route proves the real production caller shape instead). Remove once
68
- // the side-by-side stdio-vs-http witness passes and this row resolves.
69
- router.handle('_diag.runAcpHttp', async (p) => {
70
- const agent = registry.get(p?.id || 'opencode');
71
- if (!agent) err(404, 'unknown agent');
72
- const prevTransport = agent.transport;
73
- agent.transport = p?.transport === 'stdio' ? undefined : 'http';
74
- const events = [];
75
- try {
76
- const result = await agent.runACP(p?.prompt || 'reply with exactly the word PONG', process.cwd(), {
77
- timeout: 40000, onEvent: (e) => events.push(e),
78
- });
79
- return { ok: true, result, events };
80
- } catch (e) {
81
- return { ok: false, error: e.message, events };
82
- } finally {
83
- agent.transport = prevTransport;
84
- }
85
- });
86
-
87
63
  router.handle('agent.subagents', async (p) => {
88
64
  if (!p.id) err(400, 'Missing agent id');
89
65
  if (p.id === 'claude-code' || p.id === 'cli-claude') {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentgui",
3
- "version": "1.0.1120",
3
+ "version": "1.0.1121",
4
4
  "description": "Multi-agent ACP client with real-time communication",
5
5
  "type": "module",
6
6
  "main": "electron/main.js",