Skip to content

feat: replace single agent config with a roster, allow ad-hoc ACP agents#161

Merged
liam-russell merged 4 commits into
mainfrom
claude/agent-roster
Jul 7, 2026
Merged

feat: replace single agent config with a roster, allow ad-hoc ACP agents#161
liam-russell merged 4 commits into
mainfrom
claude/agent-roster

Conversation

@liam-russell

Copy link
Copy Markdown
Contributor

Type

  • feat — new feature or user-visible capability
  • fix — bug fix
  • perf — performance improvement
  • chore — dependency bump, tooling, no user-facing change
  • docs — documentation only
  • refactor — internal change, no behavior change

Summary

  • Replaced the single configured AI agent with a named roster: add multiple agents (presets or custom commands), pick a default, and switch between them from Settings → AI Agents.
  • Any agent can now be flagged as ACP-capable ("Speaks ACP") to unlock Integrated (Chat tab) mode, instead of being limited to the five hardcoded presets (Claude Code, Gemini, Codex, Kiro, Cursor) — those presets still default to ACP-capable automatically.
  • Each roster agent supports its own environment variables (API keys, base URLs, etc.), so a custom or proxied agent doesn't need global env pollution.
  • The agent Test button now performs a real ACP initialize handshake for ACP-flagged agents and reports the agent's name, version, and negotiated capabilities.
  • Added JSON import/export of agent definitions so a team can share a working custom-agent config.
  • Existing single-agent settings are migrated automatically into the new roster the first time the app reads them — no user action needed.

Why

Closes #143. The previous config only supported one agent at a time and hardcoded which commands could use Integrated/ACP mode, blocking obscure or internal ACP-speaking CLIs (Snowflake CoCo, internal wrappers, etc.) and blocking the fan-out flow (#137) from ever using more than one agent.

Screenshots / recordings

Not captured — this environment doesn't have a way to drive the packaged Electron renderer through the available browser-preview tooling (it's not a plain web app on a static port). The new Settings → AI Agents UI (roster list, per-agent edit panel with env vars/mode/ACP checkbox, Test button, Import/Export) was instead verified end-to-end via the WebdriverIO E2E suite against a real built Electron app (see Test plan) — all agent-related specs pass, including editing/saving/testing an agent row and the Integrated-mode toggle.

Breaking changes

  • IPC contract: agent:get/agent:save were replaced by agent:rosterGet/agent:rosterSave (whole-roster read/write). agent:launch, agent:test, agent:acpAdapterStatus, and chat:start now take an agentId/agent-shaped argument instead of implicitly reading the single stored AgentConfig. These are internal Electron IPC channels, not a public API, but any local script poking window.api.getAgentConfig()/saveAgentConfig() directly will need to switch to getAgentRoster()/saveAgentRoster().
  • Config DB: the legacy agentConfig setting key is left in place (untouched) and migrated into a new agentRoster key on first read after upgrading — no data loss, but a downgrade to a pre-roster build would silently ignore any roster edits made after upgrading (since it reads the untouched legacy key).

Test plan

  • Added/updated unit tests:
    • packages/database/src/__tests__/agents.test.ts — roster persistence, defaulting, and migration from the legacy single-agent config (valid, corrupted, wrong-shape, and non-ACP-recognized-command cases).
    • app/src/main/ipc/__tests__/agent-test.test.tsgetAcpLaunchSpecForAgent (recognized preset vs. ad-hoc acp: true assertion vs. unrecognized+unflagged), plus a real end-to-end ACP initialize handshake against the minimal example agent shipped in @agentclientprotocol/sdk (no credentials needed), proving the handshake path and capability reporting actually work.
    • app/src/main/ipc/__tests__/acp-adapter-status.test.ts and __tests__/project-idea-generator.test.ts updated for the roster-based API.
  • Updated E2E specs (e2e/specs/agent-workflow.spec.ts, e2e/specs/new-from-idea-workflow.spec.ts) to seed a one-entry roster instead of a single agent config, and to use the new per-row roster UI test ids.
  • Ran locally and all green:
    • pnpm lint
    • pnpm typecheck
    • pnpm test (unit tests across all packages + the full WebdriverIO E2E suite, including agent-workflow.spec.ts's "agent launch workflow" and "agent settings" suites)
    • pnpm knip --exclude exports,types (no new dead code)

Deferred (per issue scope): per-fan-out-subtask agent choice (#137) and role defaults (#151) — the roster and agentId plumbing added here should make both straightforward follow-ups.

Introduces AgentRoster/AgentRosterEntry ({name, command, args, env,
mode, acp}) in place of the single AgentConfig, migrating the legacy
setting into a one-entry roster on first read. Presets remain quick-add
buttons; any command can now be flagged acp: true to unlock Integrated
mode instead of being gated by the hardcoded ACP_PRESET_TOKENS
allowlist (which still supplies the default for recognized presets).

agent:test now performs a real ACP `initialize` handshake for
acp-flagged agents and reports the agent's name/version/capabilities.
agent:launch, chat:start, and the new-project-idea generator all take
an optional agentId and resolve against the roster's default agent.
Settings gained a full roster UI (add/edit/delete/set default,
per-agent env vars, JSON import/export).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR upgrades SproutGit’s coding-agent configuration from a single stored agent to a named agent roster, enabling multiple presets/custom agents, per-agent environment variables, ad-hoc ACP capability flags, and roster-wide import/export. It updates the Electron IPC contract and wiring so agent launch, agent testing, ACP adapter status, and integrated chat mode can target a specific roster entry (or fall back to the roster default).

Changes:

  • Introduces new roster types (AgentRoster, AgentRosterEntry, AgentTestInput) and extends tool test results to optionally include ACP handshake info.
  • Replaces single-agent config DB storage with agentRoster (including legacy agentConfig migration), and updates IPC/preload/renderer flows to use roster APIs and agentId.
  • Expands agent:test to run a real ACP initialize handshake for ACP-flagged agents and report negotiated capabilities; updates unit + E2E tests accordingly.

Reviewed changes

Copilot reviewed 20 out of 20 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
packages/types/src/tools.ts Extends ToolTestResult with optional ACP handshake info payload.
packages/types/src/ipc.ts Replaces single-agent IPC channels with roster channels; adds agentId plumbing to relevant calls.
packages/types/src/agents.ts Adds roster/entry/test-input/handshake types; re-docs legacy AgentConfig as migration-only.
packages/database/src/index.ts Re-exports new roster persistence + resolution helpers.
packages/database/src/agents.ts Implements roster storage, legacy migration, ACP recognition helper, and agent resolution logic.
packages/database/src/tests/agents.test.ts Updates DB tests for roster seeding, persistence, migration, validation, and resolution helper.
e2e/specs/new-from-idea-workflow.spec.ts Seeds an agent roster for E2E instead of the legacy single-agent config.
e2e/specs/agent-workflow.spec.ts Updates E2E agent workflow to use roster APIs, new test ids, and SPROUTGIT_AGENT semantics.
app/src/renderer/workspace/WorktreeSidebar.tsx Updates Settings UI copy to reference “AI Agents” (plural).
app/src/renderer/settings/AISection.tsx Updates copy to reflect roster-based agents configuration.
app/src/renderer/settings/AgentsSection.tsx Replaces single-agent editor row with roster list UI, per-agent edit/test, per-agent env vars, import/export.
app/src/renderer/routes/workspace.tsx Switches workspace agent gating/launch behavior to roster default agent selection and agentId launch.
app/src/renderer/routes/index.tsx Switches HomeView “New from idea” gating to roster default agent presence.
app/src/preload/index.ts Updates preload API surface to roster get/save, parameterized agent test, and adapter status by agentId.
app/src/main/ipc/project-idea-generator.ts Uses roster default agent and merges per-agent env into generator invocation.
app/src/main/ipc/chat.ts Uses roster-selected agent for chat start; uses ACP launch spec per agent and merges per-agent env.
app/src/main/ipc/agents.ts Adds roster IPC handlers, per-agent launch env/id, ACP launch-spec-by-agent, and ACP handshake test path.
app/src/main/ipc/tests/project-idea-generator.test.ts Updates mocks and expectations for roster-based agent selection and error copy.
app/src/main/ipc/tests/agent-test.test.ts Updates tests for new agent:test input shape and adds end-to-end ACP initialize handshake coverage.
app/src/main/ipc/tests/acp-adapter-status.test.ts Updates adapter-status tests to use roster storage and required agentId.

Comment thread app/src/renderer/settings/AgentsSection.tsx
Comment thread packages/database/src/agents.ts
liam-russell and others added 3 commits July 7, 2026 20:04
# Conflicts:
#	app/src/main/ipc/agents.ts
#	app/src/renderer/routes/index.tsx
#	app/src/renderer/routes/workspace.tsx
# Conflicts:
#	app/src/renderer/routes/workspace.tsx
#	packages/types/src/ipc.ts
useAgentConfig, useScaffoldKickoff, useWorkspaceUiPersistence, useTerminalManager
and two e2e specs (agent-sessions-dashboard, demo-gif) were edited during the
main merges to use the roster API but never staged, so the previous merge
commits silently reverted to main's pre-roster versions — caught by CI's
typecheck failure (getAgentConfig/AgentConfig no longer exist).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@liam-russell
liam-russell merged commit 6a15b41 into main Jul 7, 2026
15 checks passed
@liam-russell
liam-russell deleted the claude/agent-roster branch July 7, 2026 10:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Agent roster + ad-hoc ACP agents: configure any ACP-speaking CLI, not just known presets

2 participants