Skip to content

Add generic ACP active-turn steering - #4425

Closed
IEatCodeDaily wants to merge 1 commit into
getpaseo:mainfrom
IEatCodeDaily:fix/generic-acp-active-turn-steer
Closed

IEatCodeDaily wants to merge 1 commit into
getpaseo:mainfrom
IEatCodeDaily:fix/generic-acp-active-turn-steer

Conversation

@IEatCodeDaily

Copy link
Copy Markdown

Summary

  • add opt-in active-turn steering for generic ACP providers through params.activeTurnSteerCommand
  • forward accepted steering as a concurrent ACP prompt without canceling the foreground turn
  • preserve interrupt-and-replace fallback for providers that do not opt in, stale turns, and structured prompts
  • document the custom-provider setting

Root cause

Paseo's provider-neutral manager supports steerActiveTurn, but the generic ACP adapter did not implement it because standard ACP has no steering method. Hermes exposes in-place steering through /steer, so Paseo unnecessarily canceled and replaced Hermes turns.

Configuration

"params": { "activeTurnSteerCommand": "/steer" }

Verification

  • focused ACP suites: 105 passed
  • clean npm run build:server
  • full workspace typecheck through pre-commit: passed
  • lint and format checks: passed
  • isolated daemon on port 16767: a Hermes turn running sleep 20 accepted a mid-turn correction, preserved the tool call, emitted the correction once, and finished with STEERED DONE

Production Paseo on port 6767 was not modified or restarted.

@greptile-apps

greptile-apps Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Adds opt-in active-turn steering for generic ACP providers by forwarding a configured slash command as a concurrent ACP prompt.

  • Validates and propagates params.activeTurnSteerCommand through generic ACP client and session creation/resume.
  • Retains unavailable results for unconfigured providers, stale turns, and structured prompts.
  • Documents the custom-provider setting and adds focused adapter coverage.
  • Permission cleanup currently occurs before steering delivery is known to have succeeded, and the new test bypasses the public session lifecycle.

Confidence Score: 4/5

The PR is not yet safe to merge because a failed steering request can still cancel pending permissions, and the explicit repository testing requirement must also be satisfied.

The steering path performs an irreversible permission side effect before its fallible ACP prompt succeeds, so delivery failure can alter the foreground turn without applying the requested correction; the added test also bypasses the public lifecycle and does not protect this behavior.

Files Needing Attention: packages/server/src/server/agent/providers/acp-agent.ts, packages/server/src/server/agent/providers/acp-agent.test.ts

Important Files Changed

Filename Overview
packages/server/src/server/agent/providers/acp-agent.ts Adds concurrent ACP steering, but clears pending permissions before successful steering delivery is established.
packages/server/src/server/agent/providers/generic-acp-agent.ts Validates the optional steering command and forwards it through the generic ACP client.
packages/server/src/server/agent/providers/acp-agent.test.ts Adds steering coverage by mutating and asserting private session internals rather than exercising the caller-facing lifecycle.
docs/custom-providers.md Documents opt-in slash-command steering and its provider compatibility requirement.

Reviews (1): Last reviewed commit: "feat(acp): support opt-in active-turn st..." | Re-trigger Greptile

Comment on lines +1908 to +1913
if (options.clearPendingPermissions) {
for (const pending of this.pendingPermissions.values()) {
pending.resolve({ outcome: { outcome: "cancelled" } });
}
this.pendingPermissions.clear();
}

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.

P1 Permissions Cancelled Before Steering

When steering a turn that is waiting for permission, this code cancels every pending permission before the concurrent ACP prompt has been accepted. If connection.prompt rejects, the manager reports the steering failure without falling back to interrupt-and-replace, but the original turn has already received cancelled permission outcomes. It may therefore continue down a denial path even though the requested correction was never delivered. Queue the steer successfully before clearing pending permissions, as the other steering adapters do.

Knowledge Base Used: Agent and workspace lifecycle

Comment on lines +172 to +175
internals.sessionId = "session-1";
internals.activeForegroundTurnId = "turn-1";
internals.activeTurnSteerCommand = "/steer";
internals.connection = { prompt };

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.

P2 Test Bypasses Session Lifecycle

The test reaches through ACPSteerInternals to set the session ID, active turn, configuration, and connection, and it later asserts the private activeForegroundTurnId field on line 188. This violates the repository requirement that tests cross the same interface as callers. It also bypasses startTurn and the concurrent ACP request lifecycle that this feature needs to verify. This repository requirement must be satisfied before merging; establish the active turn through the session API and observe behavior through a typed ACP fake or integration harness.

Rule Used: # Code Review Pattern Reference: Slop, Tests, Feat... (source)

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

@boudra

boudra commented Sep 8, 2026

Copy link
Copy Markdown
Collaborator

Closing in favor of the Hermes steering implementation in #4154, which remains open.

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.

2 participants