Skip to content

feat: pool ACP provider runtimes - #186

Open
Waishnav wants to merge 12 commits into
codex/subagent-runtime-opencodefrom
codex/subagent-runtime-acp
Open

feat: pool ACP provider runtimes#186
Waishnav wants to merge 12 commits into
codex/subagent-runtime-opencodefrom
codex/subagent-runtime-acp

Conversation

@Waishnav

@Waishnav Waishnav commented Aug 11, 2026

Copy link
Copy Markdown
Owner

Cursor and Copilot ACP connections support multiple sessions on one long-lived connection. This stacked change adds shared ACP runtimes with capability-aware session resume and close behavior, session-level model/thinking configuration, permission selection, and process crash invalidation for each provider independently.

Summary by CodeRabbit

  • New Features

    • Added local-agent support for Cursor and Copilot.
    • Supports creating, resuming, reusing, and closing agent sessions.
    • Added model and thinking configuration controls.
    • Added permission selection based on write mode.
    • Improved provider command resolution and runtime process management.
  • Tests

    • Added comprehensive coverage for session handling, configuration, permissions, command resolution, and runtime liveness.

@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: ebdf229c-c616-44f3-8345-cba4273333b5

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This change adds ACP-backed local-agent support for Cursor and Copilot. It manages executable discovery, child processes, ACP sessions, streamed responses, configuration overrides, permission selection, session reuse, resumption, cleanup, and runtime liveness.

Changes

ACP local-agent support

Layer / File(s) Summary
Runtime and session lifecycle
src/local-agent-acp.ts, src/local-agent-acp.test.ts
AcpRuntime manages ACP connections, sessions, streamed updates, bounded queues, stderr tails, release, resume, and process shutdown. Tests cover creation, reuse, resumption, closure, and liveness.
Provider launch and adapter wiring
src/local-agent-acp.ts, src/local-agent-adapters.ts, src/local-agent-acp.test.ts
AcpLocalAgentDriver resolves and launches Cursor and Copilot executables with provider-specific arguments. The adapter registry selects this driver for both providers.
Session configuration and permission policies
src/local-agent-acp.ts, src/local-agent-acp.test.ts
Model and thinking overrides validate advertised ACP options. Permission selection handles read-only, allowed, full-access, and sandboxed Copilot modes.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant LocalAgentAdapters
  participant AcpLocalAgentDriver
  participant AcpRuntime
  participant ACPProcess
  participant ACPConnection
  LocalAgentAdapters->>AcpLocalAgentDriver: create Cursor or Copilot driver
  AcpLocalAgentDriver->>ACPProcess: resolve and spawn provider executable
  AcpLocalAgentDriver->>ACPConnection: initialize ACP connection
  AcpRuntime->>ACPConnection: create or resume session
  ACPConnection->>ACPProcess: send prompt and configuration
  ACPProcess-->>ACPConnection: stream agent updates
  ACPConnection-->>AcpRuntime: deliver session updates
  AcpRuntime-->>AcpLocalAgentDriver: return final response
Loading

Possibly related PRs

  • Waishnav/devspace#55: Adds the ACP Cursor/Copilot runtime and adapter integration used by local-agent profiles and CLI flows.
  • Waishnav/devspace#60: Adds ACP configuration helpers for model and thinking settings.
  • Waishnav/devspace#83: Refactors local-agent adapters around ACP lifecycle, streaming, permissions, and sessions.

Poem

A rabbit saw processes hop,
With sessions that never would stop.
Cursor and Copilot streamed light,
Permissions kept actions just right.
“ACP!” cried the hare,
“Clean shutdown everywhere!”

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: pooled ACP provider runtimes for Cursor and Copilot.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/subagent-runtime-acp

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Aug 11, 2026

Copy link
Copy Markdown

Greptile Summary

The PR adds pooled ACP runtimes for Cursor and Copilot, including shared process lifecycle management and capability-aware sessions.

  • Adds ACP session creation, reuse, resume, configuration, permission handling, and cleanup.
  • Integrates Cursor and Copilot ACP drivers into local-agent driver selection.
  • Adds coverage for session behavior, permissions, command resolution, and runtime liveness.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
src/local-agent-acp.ts Implements pooled ACP process and session lifecycle, configuration, permissions, command resolution, bounded stderr consumption, and local cleanup.
src/local-agent-acp.test.ts Exercises session reuse and resume, configuration overrides, permission selection, command arguments, cleanup, and liveness.
src/local-agent-adapters.ts Routes Cursor and Copilot providers through the new ACP driver.

Sequence Diagram

sequenceDiagram
  participant Pool as Runtime Pool
  participant Runtime as ACP Runtime
  participant Provider as Cursor/Copilot ACP
  Pool->>Runtime: acquire pooled runtime
  Runtime->>Provider: session/new or session/resume
  Runtime->>Provider: session/set_config_option
  Runtime->>Provider: session/prompt
  Provider-->>Runtime: session updates and response
  Runtime-->>Pool: final response and session ID
  Pool->>Runtime: releaseSession
  Runtime->>Provider: session/close when supported
Loading

Reviews (2): Last reviewed commit: "fix: fail closed on Copilot ACP permissi..." | Re-trigger Greptile

Comment thread src/local-agent-acp.ts Outdated
Comment thread src/local-agent-acp.ts

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 51416e33f2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/local-agent-acp.ts
}
}

export class AcpLocalAgentDriver implements LocalAgentDriver {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Register the pooled ACP driver

This exported driver never becomes reachable from the production subagent path: LocalAgentManager is constructed from createLocalAgentDrivers() in src/local-agent-adapters.ts, and a repo-wide search shows no import or registration of AcpLocalAgentDriver, so Cursor/Copilot still use the old per-run ACP adapter and no pooled ACP connection is used. Please wire this driver into the driver factory when enabling the runtime pool.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

No change in this layer: ACP registration is intentionally completed by the final integration layer (#188), which registers Cursor and Copilot through AcpLocalAgentDriver. This intermediate PR isolates the pooled ACP runtime.

Comment thread src/local-agent-acp.ts Outdated
mcpServers: [],
});
this.queues.set(input.providerSessionId, { values: [] });
await this.configureSession(input.providerSessionId, input, response);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve config metadata across resumed ACP sessions

When continuing a stored Cursor/Copilot session that has a profile model or thinking value, LocalAgentManager sends those values again, but session/resume is allowed to return an empty result once the session is ready. Passing that empty resume response into configureSession makes resolveAcp*ConfigUpdate throw ACP server does not expose a model/thinking option before the prompt is sent; cache the config IDs/state from session creation or skip reconfiguration when resume does not include config options.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Addressed in 5c76011. On a cold resume, persisted model/thinking state no longer requires resume to re-advertise config metadata. A genuinely new per-turn override still fails closed if the provider exposes no config option to apply it, avoiding a silently ignored override.

@Waishnav
Waishnav force-pushed the codex/subagent-runtime-acp branch from 51416e3 to e8d6187 Compare August 11, 2026 18:28
@Waishnav
Waishnav force-pushed the codex/subagent-runtime-acp branch from e8d6187 to 9e39ad5 Compare August 11, 2026 19:08
@Waishnav
Waishnav force-pushed the codex/subagent-runtime-acp branch from b224c0f to ca72c35 Compare August 12, 2026 03:44
@Waishnav
Waishnav force-pushed the codex/subagent-runtime-acp branch from 4bab3cb to 15e0fae Compare August 12, 2026 04:20
@Waishnav
Waishnav force-pushed the codex/subagent-runtime-acp branch from 15e0fae to e132c6b Compare August 12, 2026 04:24
@Waishnav
Waishnav force-pushed the codex/subagent-runtime-acp branch from 54ca5d9 to 1f852ed Compare August 12, 2026 04:29
@Waishnav
Waishnav force-pushed the codex/subagent-runtime-acp branch from 1f852ed to 561c9e8 Compare August 12, 2026 04:44
@Waishnav
Waishnav force-pushed the codex/subagent-runtime-acp branch 2 times, most recently from 2889f8e to dc65494 Compare August 12, 2026 05:19
@Waishnav
Waishnav force-pushed the codex/subagent-runtime-acp branch from dc65494 to 71b298d Compare August 12, 2026 05:25
@Waishnav
Waishnav force-pushed the codex/subagent-runtime-acp branch from 71b298d to 821f7de Compare August 12, 2026 05:26
@Waishnav
Waishnav force-pushed the codex/subagent-runtime-acp branch from 821f7de to 32b61c3 Compare August 12, 2026 05:27
@Waishnav
Waishnav force-pushed the codex/subagent-runtime-acp branch from 32b61c3 to 1077fa9 Compare August 12, 2026 05:32

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🧹 Nitpick comments (3)
src/local-agent-acp.test.ts (1)

160-171: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Cover the Cursor write-mode variants.

The assertions cover Cursor only for writeMode: "allowed". Copilot covers three modes. The Cursor branch adds --mode plan for read_only and --sandbox disabled --force for full_access. These flags control sandboxing, so assert them.

💚 Proposed additional assertions
 assert.deepEqual(acpCommandArgs("cursor", cachedContext), [
   "acp", "--sandbox", "enabled", "--workspace", "/tmp/project",
 ]);
+assert.deepEqual(acpCommandArgs("cursor", { ...cachedContext, writeMode: "read_only" }), [
+  "acp", "--sandbox", "enabled", "--workspace", "/tmp/project", "--mode", "plan",
+]);
+assert.deepEqual(acpCommandArgs("cursor", { ...cachedContext, writeMode: "full_access" }), [
+  "acp", "--sandbox", "disabled", "--workspace", "/tmp/project", "--force",
+]);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/local-agent-acp.test.ts` around lines 160 - 171, Extend the assertions
around acpCommandArgs("cursor", cachedContext) to cover writeMode "read_only"
and "full_access". Verify that read_only adds "--mode", "plan", while
full_access uses "--sandbox", "disabled", and "--force", preserving the existing
allowed-mode assertion.
src/local-agent-acp.ts (1)

20-23: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Remove the duplicated launch arguments and the unused runtime options.

ACP_COMMANDS carries the subcommand (acp, --acp), and acpCommandArgs repeats it at Line 387 and Line 398. Only the executable name is read from ACP_COMMANDS (Line 246, Line 365). The two sources can drift.

AcpRuntimeOptions.command and AcpRuntimeOptions.args are assigned by createRuntime but never read by AcpRuntime. Either expose them for diagnostics or drop them from the options type.

Also applies to: 43-54, 383-406

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/local-agent-acp.ts` around lines 20 - 23, Remove subcommand entries from
ACP_COMMANDS so it maps each AcpProvider only to its executable, and update the
acpCommandArgs construction to use that executable mapping without duplicating
launch arguments. Remove AcpRuntimeOptions.command and AcpRuntimeOptions.args
from the type and from createRuntime assignments, since AcpRuntime never reads
them.
src/local-agent-adapters.ts (1)

64-65: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Route ACP execution through AcpLocalAgentDriver.

The legacy cursor/copilot adapter remains exported and ignores writeMode. No production caller currently uses it, but a future caller could bypass the Copilot permission policy. Remove this path or reuse the driver policy.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/local-agent-acp.ts`:
- Around line 360-379: Update resolveAcpCommand and its related executable
resolution path to test candidate availability with a filesystem permission
check such as fs.accessSync(candidate, fs.constants.X_OK), rather than calling
executableExists. Ensure PATH discovery never executes candidates, while
preserving the existing command selection, platform extension handling, and
undefined results for unavailable commands.
- Around line 92-102: Update run and the per-session queue handling to serialize
concurrent turns for the same sessionId, or reject a second run while one is
active. Ensure each session/prompt request exclusively owns its notification
updates so queue.values clearing and splicing cannot lose or mix chunks between
turns, while preserving concurrency across different sessions.
- Around line 291-311: Update the ACP initialization flow in createRuntime to
race connection.agent.request(methods.agent.initialize, ...) against a timeout,
ensuring timeout rejection reaches the existing catch block for child
termination and stderrTail attachment. Replace the hardcoded clientInfo version
with the version read from the package manifest.
- Around line 116-123: Update releaseSession to gate the session/close request
only on this.capabilities.close and this.isAlive(); remove the resume capability
requirement while preserving the existing cleanup and request behavior.
- Around line 224-226: Update additionalDirectoryParams and the related
resume/close capability checks to treat capabilities.additionalDirectories as
enabled only when its value is true, keeping detection consistent across all
call sites. When enabled, populate additionalDirectories with the actual allowed
directories; otherwise omit the parameter and capability entirely.

---

Nitpick comments:
In `@src/local-agent-acp.test.ts`:
- Around line 160-171: Extend the assertions around acpCommandArgs("cursor",
cachedContext) to cover writeMode "read_only" and "full_access". Verify that
read_only adds "--mode", "plan", while full_access uses "--sandbox", "disabled",
and "--force", preserving the existing allowed-mode assertion.

In `@src/local-agent-acp.ts`:
- Around line 20-23: Remove subcommand entries from ACP_COMMANDS so it maps each
AcpProvider only to its executable, and update the acpCommandArgs construction
to use that executable mapping without duplicating launch arguments. Remove
AcpRuntimeOptions.command and AcpRuntimeOptions.args from the type and from
createRuntime assignments, since AcpRuntime never reads them.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 389972bc-938c-40be-819d-bc4ecbb28808

📥 Commits

Reviewing files that changed from the base of the PR and between d1e388a and 1077fa9.

📒 Files selected for processing (3)
  • src/local-agent-acp.test.ts
  • src/local-agent-acp.ts
  • src/local-agent-adapters.ts

Comment thread src/local-agent-acp.ts Outdated
Comment thread src/local-agent-acp.ts
Comment thread src/local-agent-acp.ts
Comment thread src/local-agent-acp.ts
Comment thread src/local-agent-acp.ts
@Waishnav
Waishnav force-pushed the codex/subagent-runtime-acp branch from 1077fa9 to 8ca3f2e Compare August 13, 2026 07:56
@Waishnav Waishnav closed this Aug 13, 2026
@Waishnav Waishnav reopened this Aug 13, 2026
@Waishnav
Waishnav force-pushed the codex/subagent-runtime-acp branch from 8ca3f2e to 4f6618b Compare August 17, 2026 13:40
@Waishnav
Waishnav force-pushed the codex/subagent-runtime-acp branch from 5c76011 to d48a195 Compare August 17, 2026 13:49
@Waishnav
Waishnav force-pushed the codex/subagent-runtime-acp branch from d48a195 to eac2264 Compare August 17, 2026 13:54
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.

1 participant