feat: replace single agent config with a roster, allow ad-hoc ACP agents#161
Merged
Conversation
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>
Contributor
There was a problem hiding this comment.
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 legacyagentConfigmigration), and updates IPC/preload/renderer flows to use roster APIs andagentId. - Expands
agent:testto run a real ACPinitializehandshake 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. |
# 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>
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.
Type
Summary
initializehandshake for ACP-flagged agents and reports the agent's name, version, and negotiated capabilities.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
agent:get/agent:savewere replaced byagent:rosterGet/agent:rosterSave(whole-roster read/write).agent:launch,agent:test,agent:acpAdapterStatus, andchat:startnow take anagentId/agent-shaped argument instead of implicitly reading the single storedAgentConfig. These are internal Electron IPC channels, not a public API, but any local script pokingwindow.api.getAgentConfig()/saveAgentConfig()directly will need to switch togetAgentRoster()/saveAgentRoster().agentConfigsetting key is left in place (untouched) and migrated into a newagentRosterkey 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
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.ts—getAcpLaunchSpecForAgent(recognized preset vs. ad-hocacp: trueassertion vs. unrecognized+unflagged), plus a real end-to-end ACPinitializehandshake 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.tsand__tests__/project-idea-generator.test.tsupdated for the roster-based API.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.pnpm lintpnpm typecheckpnpm test(unit tests across all packages + the full WebdriverIO E2E suite, includingagent-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
agentIdplumbing added here should make both straightforward follow-ups.