feat(console): agent console shell + per-endpoint chat (agent-consoles slice 2) - #67
Merged
Merged
Conversation
…nsoles slice 1) (#66) ADR agent-consoles Part B: generalize the single `remote.toml` connection into a registry of named `/acp` endpoints and rekey the live-connection state per agent, so Studio can reach N agents instead of one. - crates/acp-tunnel/config.rs: add `AgentEndpoint` (name + url/token/cwd + `management` flag) and `AgentRegistry` (`[[agent]]` in agents.toml). Explicit fields + a `conn()` accessor reuse `RemoteConfig` validation as one source of truth (no serde-flatten, which is order-fragile under toml). `from_legacy` adopts a `remote.toml` as one `management = true` entry. Structural `validate` (unique non-empty names, ≤1 management). Unit-tested. - src-tauri/remote.rs: `Remote` is now `HashMap<name, RemoteState>` — each agent console has its own task/status/reconnect. `oab` reverse-MCP tools are declared only when the endpoint is `management` (least privilege, Part A); an ordinary agent console runs chat-only. `remote-status` / `agent-update` events carry an `agent` field so the UI can route per console. `agents.toml` preferred, legacy `remote.toml` adopted when absent. `disconnect_all` on app teardown. - src-tauri/lib.rs: remote_connect/disconnect + agent_prompt/cancel take an optional `agent` (None ⇒ management, so the current single-console UI is unchanged); new `remote_agents` command lists the registry + live status for the slice-2 selector. Backend-only; the frontend still drives the management endpoint. Desktop crate is built by the bundle-macos CI job (GTK libs absent locally). Co-authored-by: Orca <orca@openab.dev> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…les slice 2 · pt2)
Turns the chat panel into the per-endpoint primitive the ADR calls for and adds
the agent-console shell on top of it (ADR agent-consoles Parts A/C):
- chatPanel.ts: extract the management chat wiring (transcript, one-turn queue,
streaming spinner, stop/copy) into `createChatPanel({agent, source, mock})`.
Each panel owns its own state + DOM listeners (AbortController-scoped) and is
keyed by endpoint name; `onChunk`/`onTurnEnd`/`setConnected` feed it events.
- main.ts: the management console now mounts this primitive. One `agent-update`
/`remote-status` subscription routes each event to the owning panel by name
(`chatPanels` map); the management endpoint's name is learned from the registry.
- agentConsole.ts: selector over `remote_agents` + a per-agent console that dials
on open (`remote_connect(agent)`), tears down on close, shows read-only config,
and mounts a chat panel bound to that agent. One console open at a time.
- render.ts: pure `agentListHtml` + `agentConsoleHeaderHtml`.
- index.html: the agents section (selector + console with its own chat region).
Read-only per ADR §6 — the file editor's write path waits on the openab `fs/*`
wire (slices 3–4). Reverse-MCP `oab` stays gated to the management binding.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- render.test.ts: cover `agentListHtml` (openable vs management vs unconfigured rows, open-marking, escaping) and `agentConsoleHeaderHtml` (identity/target/ status, no token leak, read-only note). 75 tests green. - styles.css: the agents selector + open-console layout, reusing the chat-wrap and identity `id-field` primitives so the surfaces read as one system. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Slice 2 of 4 for the agent-consoles ADR (#49), stacked on the merged slice 1 (#66). Slice 1 generalized the backend into a per-agent endpoint registry +
RemoteStatekeyed by agent. This slice builds the frontend: the chat panel becomes a reusable per-endpoint primitive, and an agent-console shell (selector + read-only config + per-agent chat) sits on top of it — the ADR's Part A/C surface.Frontend-only; the Rust side is untouched (slice 1's
remote_agents/ per-agentremote_connect/agent_promptcommands are what this consumes).Changes
console/src/chatPanel.ts(new) — extract the management chat wiring intocreateChatPanel({agent, source, mock}): transcript, one-turn-at-a-time queue, streaming spinner, stop/copy. Each panel owns its own state + DOM listeners (AbortController-scoped) and is keyed by endpoint name;onChunk/onTurnEnd/setConnectedfeed it events.console/src/agentConsole.ts(new) — the shell: a selector overremote_agents+ a per-agent console that dials on open (remote_connect(agent)), tears down on close (remote_disconnect(agent)), shows read-only config (name/url/cwd/status — never the token), and mounts a chat panel bound to that agent. One console open at a time (ADR §7 bounded fan-out).console/src/main.ts— the management console now mounts the same primitive. A singleagent-update/remote-statussubscription routes each event to the owning panel by endpoint name (chatPanelsmap); the management endpoint's name is learned from the registry.console/src/render.ts— pureagentListHtml+agentConsoleHeaderHtml.console/src/{types,source,fixtures}.ts—AgentEndpointView;remoteAgents()+ optionalagentparam threaded through connect/disconnect/prompt/cancel;FIXTURE_AGENTSfor the browser build.index.html/styles.css— the agents section (selector + console with its own chat region), reusingchat-wrapand the identityid-fieldprimitives.Scope / ADR fidelity
fs/*wire (slices 3–4). The console ships chat + read-only config today, exactly as the ADR sequences it.oabpublication stays gated to the management binding (backend, slice 1).AgentEndpointViewand never rendered.Testing
npm run buildgreen (tsc --noEmit+vite build, 49 modules).vitest run— 75 tests green, incl. 13 new render cases (selector rows: openable / management / unconfigured / open-marking / escaping; console header: identity/target/status, no-token-leak, read-only note).Stacked slices to follow: 3 (remote file-editor read path), 4 (write/apply behind the upstream
fs/*wire).🤖 Generated with Claude Code