Skip to content

feat(server): add ACP registry agents - #13801

Open
t3dotgg wants to merge 16 commits into
t3code/acp-runtime-v1from
t3code/acp-registry-v1
Open

t3dotgg wants to merge 16 commits into
t3code/acp-runtime-v1from
t3code/acp-registry-v1

Conversation

@t3dotgg

@t3dotgg t3dotgg commented Sep 26, 2026 •

Copy link
Copy Markdown
Member

Users can't add agents from the ACP Registry on main. That flow only exists on the Orchestrator V2 branch (#2829), which will not land soon.

This ports the registry to main and runs registry agents on the current V1 orchestrator. You can search the registry's ~40 agents (Devin, Kimi CLI, Gemini CLI, Goose, and others), add one, sign in, chat with T3 MCP tools, and remove it.

Stacked on #13784.

What changed

  • Registry infra from V2. Contracts, the catalog (search, prepare, inspect, resolve, managed-binary uninstall), the probe, the runtime coordinator, the sign-in flow and sign-in state, the catalog layer, and the driver. Registered in builtInDrivers.ts; the hydration and server.ts share one catalog.
  • New generic V1 adapter (provider/Layers/AcpRegistryAdapter.ts), based on the V1 Antigravity adapter with behavior ported from V2's AcpAdapterV2, AcpRegistryAdapterV2, and DevinAcp:
    • Permission requests follow the thread's runtime mode through AcpClientPolicy (Supervised asks, Auto-accept edits asks for non-edits, Auto and Full access approve).
    • Form elicitations become T3 questions, except MCP tool-approval forms, which become approvals; URL elicitations go to the coordinator and show as "Continue authentication" on the provider card.
    • Stored model, agent options, mode picks, and the Plan toggle are applied before each prompt.
    • T3 MCP through AcpT3Mcp (stdio bridge and MCP-over-ACP).
    • Devin keeps V2's per-agent exception: client terminals gated by the runtime mode, and tool titles from its metadata.
  • 4 RPCs: search, prepare, uninstall managed binary, accept URL auth.
  • Web: registry search and "Enter manually" in the Add provider dialog, a sign-in step after adding, the shared sign-in section on registry instances (browser, terminal, and credential methods, plus sign out), managed-file cleanup on remove, and agent icons in the pickers, sidebar, palette, and settings.
  • Mobile: agent icons in the model pickers, thread rows, and environment settings.
  • Docs: docs/user/providers-acp.md, linked from the index, install, and permission modes pages.

Coverage of open single-provider PRs

  • #13645 Devin CLI: covered by the devin registry entry.
  • #12920 Kimi Code: covered by the kimi entry for chat. That PR's text generation and swarm tool rows are not.
  • #13670 Prime Agent: not in the registry, so not covered.

V2 compatibility

  • Same as V2: contracts/acpRegistry.ts (+test), AcpRegistryAuth, AcpRegistryAuthenticationState, AcpRegistryCatalog layer, web AcpRegistryIcon, AcpRegistrySearchStep, ProviderAuthenticationSection, ProviderAuthTerminal, AddProviderInstanceWizardSteps (all with tests), providerInstanceDisplay, and the registry model-retention rule in ProviderRegistry.
  • Small deltas:
    • AcpRegistrySupport.ts (+test): isAcpRegistryError is private (knip). A fetched registry index now serves search and prepare for 5 minutes instead of a refetch on every search, and a cached index that replaces a failed fetch counts as fresh too. Review fixes: an archive command resolves inside its staging directory before chmod; installed npm and uv commands resolve only in the managed bin directory; the install lock is refreshed every minute; install errors keep only the last 4,000 characters of stderr; and auto distribution prefers a package runner the environment has. V2 should take these changes.
    • AcpRegistryProbe.ts and AcpRegistryRuntimeCoordinator.ts: session management (list, delete, providers, logout RPC) and withSessionMutation removed. The probe and live configuration also report supportsPlanMode, which the driver uses to show Plan only for agents with a plan mode.
    • AcpRegistryDriver.ts: builds the V1 adapter, drops acpSessionManagement and the nativeSessions / configurableProviders snapshot fields, sets supportsConversationRollback: false, and hides Plan until the agent reports a plan mode. Live configuration from a past session no longer marks an unauthenticated or uninstalled agent ready (V2 should take this).
    • Contracts: ServerProvider gains only iconUrl, setup.documentationUrl, auth.action, auth.canLogout. rpc.ts gains only the 4 RPCs above.
    • ProviderWizardAuthenticationStep.tsx: waits for the new instance's snapshot before it subscribes to sign-in state. AddProviderInstanceDialog.logic.ts keeps main's step labels.
    • AddProviderInstanceDialog.tsx, ProviderSettingsPanel.tsx, ProviderInstanceCard.tsx: registry parts added to main's versions, not V2's rewrites.
  • New on main only: the V1 adapter and its service shape.
  • When V2 merges main: take V2's side for the shared files, re-add the session-management exports, and drop AcpRegistryAdapter.ts (Services and Layers) along with the V1 adapters. acpRegistry.ts and the registry settings schema are identical, so persisted instances carry over.

Gaps

  • V2 session management (list, import, delete native sessions; configure providers; the separate logout RPC). Sign out works through the shared sign-in flow.
  • Mobile has no provider settings screen on main, so adding and signing in happen on web or desktop.
  • Devin subagents show as tool calls. The adapter does not advertise Devin's subagent and message-grouping capabilities.
  • The Mistral Vibe retry notice and rate-limit class from V2 are not ported.
  • Managed registry commands are not added to the integrated terminal's PATH, and the acp-mcp-call terminal fallback is not wired (main's agent instructions do not mention it yet).

Testing

  • vp test run on the ported registry tests (support, probe, coordinator, auth, auth state, driver), the new adapter test, ProviderRegistry, ProviderInstanceRegistryLive, providerCompatibility, RpcAuthorization, and server.test: 12 files, 362 passed. The adapter test runs a real ACP mock agent over both the v1 and v2 wires: a turn with stored model and mode picks, a Supervised approval, auto-approval in Full access, a form elicitation, and T3 MCP plus Devin's client terminals.
  • Web: 13 files, 306 passed (search step, icons, dialog logic and routing, settings panel, pickers, sidebar, palette). Contracts 6, client-runtime 20, mobile 13 passed.
  • tsc --noEmit for contracts, client-runtime, server, web, and mobile. vp lint and vp fmt on changed files (no new warnings). knip exports for server, web, client-runtime, and contracts, plus files and dependencies.
  • Not run: a real registry agent or a browser pass.

Made by Claude Opus 5.5 (1M context) in Claude Code, orchestrated from T3 Code.

🤖 Generated with Claude Code

Closes discussions

@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:XXL 1,000+ changed lines (additions + deletions). labels Sep 26, 2026
Comment thread apps/server/src/provider/acp/AcpRegistrySupport.ts
Comment thread apps/server/src/provider/acp/AcpRegistrySupport.ts Outdated
Comment thread apps/server/src/provider/Drivers/AcpRegistryDriver.ts
@github-actions

github-actions Bot commented Sep 26, 2026 •

Copy link
Copy Markdown
Contributor

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

ℹ️ No successful main baseline artifact is available yet. This run establishes the initial measurement.

Provider Metric Main baseline This PR Impact PR ceiling
Codex Total thread wire — 13.5 KiB — 15.1 KiB ✅
Codex Thread snapshot wire — 7.1 KiB — 7.3 KiB ✅
Codex Live turn WebSocket wire — 6.5 KiB — 7.8 KiB ✅
Codex Live turn WebSocket decoded — 56.3 KiB — 66.4 KiB ✅
Codex Live turn messages — 10 — 21 ✅
Claude Total thread wire — 13.5 KiB — 15.1 KiB ✅
Claude Thread snapshot wire — 7.1 KiB — 7.3 KiB ✅
Claude Live turn WebSocket wire — 6.5 KiB — 7.8 KiB ✅
Claude Live turn WebSocket decoded — 57.0 KiB — 66.4 KiB ✅
Claude Live turn messages — 9 — 21 ✅

Baseline: unavailable · PR result: c36ec3c · Source CI: success

Scenario and decoded snapshot size

10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.

  • Codex decoded thread snapshot: 114.0 KiB
  • Claude decoded thread snapshot: 114.7 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

Comment thread apps/server/src/provider/acp/AcpRegistrySupport.ts
Comment thread apps/server/src/provider/acp/AcpRegistrySupport.ts
Comment thread apps/server/src/provider/Drivers/AcpRegistryDriver.ts Outdated
Comment thread apps/server/src/provider/Drivers/AcpRegistryDriver.ts
Comment thread apps/server/src/provider/acp/AcpRegistrySupport.ts
Comment thread apps/server/src/provider/Layers/AcpRegistryAdapter.ts Outdated
Comment thread apps/server/src/ws.ts
Comment thread apps/web/src/components/settings/ProviderAuthenticationSection.tsx
Comment thread apps/server/src/provider/acp/AcpRegistryRuntimeCoordinator.ts
Comment thread apps/mobile/src/components/ProviderIcon.tsx
@macroscopeapp

macroscopeapp Bot commented Sep 26, 2026 •

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This PR introduces a substantial production capability that installs and runs third-party ACP agents, adds authentication and permission flows, changes product defaults, and spans server, client, and public contract layers. An unresolved high-severity session-lifecycle finding further warrants human review before merge.

Not approved because:

  • 1 blocking correctness issue found at or above your repo's Minimum Blocking Severity

No code changes detected at c36ec3c. Prior analysis still applies.

Adjust the Minimum Blocking Severity for this repo — including turning it Off — in Settings. You can add or adjust custom eligibility rules. Learn more.

Comment thread apps/server/src/provider/Layers/AcpRegistryAdapter.ts
Comment thread apps/server/src/provider/Layers/AcpRegistryAdapter.ts
@t3dotgg
t3dotgg force-pushed the t3code/acp-registry-v1 branch from 7eb2cc3 to d09d259 Compare September 26, 2026 08:25
Comment thread apps/server/src/provider/acp/AcpRegistryAuth.ts
Comment thread apps/server/src/provider/Layers/AcpRegistryAdapter.ts
Comment thread apps/server/src/provider/acp/AcpRegistrySupport.ts
Comment thread apps/server/src/ws.ts
Comment thread apps/server/src/provider/Layers/AcpRegistryAdapter.ts Outdated
Comment thread apps/server/src/provider/Layers/AcpRegistryAdapter.ts Outdated
Comment thread apps/server/src/provider/acp/AcpRegistryProbe.ts
@t3dotgg
t3dotgg force-pushed the t3code/acp-registry-v1 branch from d09d259 to 57614a5 Compare September 26, 2026 09:56
Comment thread apps/server/src/provider/Services/AcpRegistryAdapter.ts
@macroscopeapp

macroscopeapp Bot commented Sep 26, 2026

Copy link
Copy Markdown
Contributor

Correction to my Effect Service Conventions review comment on Services/AcpRegistryAdapter.ts: I overlooked that per-instance adapters in this repository intentionally use shape-only modules (for example, GrokAdapter.ts), rather than Context.Service tags. The new adapter follows that convention; please disregard my finding. I withdraw that request.

Posted via Macroscope — Effect Service Conventions

Comment thread apps/server/src/provider/acp/AcpRegistrySupport.ts
Comment thread apps/server/src/provider/acp/AcpRegistrySupport.ts Outdated
Comment thread apps/server/src/provider/acp/AcpRegistrySupport.ts
Comment thread apps/server/src/provider/Layers/AcpRegistryAdapter.ts Outdated
@t3dotgg
t3dotgg force-pushed the t3code/acp-registry-v1 branch from e99a569 to 6d1ffd1 Compare September 26, 2026 10:21
Comment thread apps/server/src/provider/acp/AcpRegistryRuntimeCoordinator.ts
Comment thread apps/server/src/provider/Layers/AcpRegistryAdapter.ts
t3dotgg and others added 11 commits September 26, 2026 03:37
Users can search the official ACP Registry, add an agent (Devin, Kimi CLI,
Gemini CLI, and others), sign in, run it on the V1 orchestrator with T3 MCP,
and remove it again.

- Port V2's registry infra: contracts, catalog (search, prepare,
  inspect, resolve, managed-binary uninstall), probe, runtime
  coordinator, sign-in flow, sign-in state, and the driver.
- Add a generic V1 ACP adapter for registry agents. It answers
  permission requests by the thread's runtime mode, maps form
  elicitations to questions and URL elicitations to the coordinator,
  applies stored model, option, mode, and plan picks, and gives the
  agent T3 MCP through AcpT3Mcp. Devin keeps V2's client terminals.
- Web: registry search and prepare in the add-provider dialog, a
  sign-in step, the shared sign-in section for registry instances,
  managed-file cleanup on remove, and registry agent icons.
- Mobile: registry agent icons in the model pickers and settings.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Supervised mode now shows MCP tool-call approvals as approvals. Before,
  an elicitation with no form fields was declined without asking, and one
  with fields became a question whose "false" answer still accepted.
- A cancelled question emits user-input.resolved, so it leaves the thread.
- Stale approval and question answers now report "Unknown pending ...
  request", which the reactor needs to close them.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The reference check compared the raw stored agent id, but the form stores
untrimmed input and the driver trims it. Removing one instance could then
delete binaries that a second instance of the same agent still runs.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Stop answered pending approvals and questions but left a URL sign-in open.
The agent kept waiting on it for up to 10 minutes after the turn ended,
and the provider card kept offering "Continue authentication". Cancelling
a turn now answers the sign-in with cancel, as ACP expects.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Auto and Full access picked the agent's allow_always option first. An
agent that remembers that grant would not ask again after the thread
switched to Supervised. Policy approvals now pick allow_once first.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Every search, including each debounced keystroke, fetched the full
registry index again. The catalog now serves all callers from the last
network fetch for five minutes. A disk fallback does not count as fresh,
so a failed fetch still retries on the next search.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Plan showed for every registry agent. For agents without a plan or
architect mode it did nothing, so the agent ran normally while the user
thought it was planning. The probe and live session now report whether
the agent has a plan mode, using the same rule the adapter uses to
switch, and the snapshot hides Plan until one of them says so.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Use acpAutoApprovalOptionId from AcpClientPolicy instead of a local
option list, and cover Auto-accept edits asking before MCP tool calls.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Resolve an archive command inside its staging directory before chmod,
  so a link in the archive cannot change the mode of an outside file.
- Look up an installed npm or uv command only in the managed bin
  directory, not in a same-named command elsewhere on PATH.
- Refresh the install lock every minute, so another process cannot take
  a live lock as stale during a long download.
- Keep only the last 4,000 characters of installer stderr in errors.
- Auto distribution prefers a package runner the environment has, so an
  agent with npx and uvx recipes works on a host with only uv.
- A cached index that stands in for a failed fetch counts as fresh, so
  offline searches do not wait on the network each time.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Fixed choices no longer take typed answers, array fields with item
choices become multi-select questions and send string arrays, and a
fraction for an integer field is left out instead of sent.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
t3dotgg and others added 5 commits September 26, 2026 03:37
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…n-in

Live configuration from an earlier session marked every later snapshot
ready and dropped its message, even when a new probe reported failed
sign-in or local inspection failed. It now promotes the status only for
an enabled, installed agent that is not unauthenticated.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…nt icon

Thread rows drew the generic ACP glyph because the row's provider
instance had no icon URL, and a selected model outside the provider's
list lost the icon too.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…..tools

The containment check rejected any relative path starting with "..",
so a command inside a directory such as ..tools was refused. Only a
".." segment leaves the install root.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…mpt lock

A turn queued behind a model change read the session model before the
lock, then wrote that stale model back to the session and its turn
metadata.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@t3dotgg
t3dotgg force-pushed the t3code/acp-registry-v1 branch from 6d1ffd1 to c36ec3c Compare September 26, 2026 10:38
Comment thread apps/server/src/provider/acp/AcpRegistryAuth.ts

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL 1,000+ changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant