Skip to content

feat(acp): add session/set_mode handler#7801

Merged
codefromthecrypt merged 1 commit intomainfrom
adrian/goose-acp-mode
Mar 13, 2026
Merged

feat(acp): add session/set_mode handler#7801
codefromthecrypt merged 1 commit intomainfrom
adrian/goose-acp-mode

Conversation

@codefromthecrypt
Copy link
Collaborator

@codefromthecrypt codefromthecrypt commented Mar 11, 2026

Summary

The ACP server advertises available modes in session/new and session/load responses but has no session/set_mode handler. Zed's mode selector populates from these responses but mode changes are silently ignored. There are no tests for mode validation or error paths, and the server and provider test fixtures diverge: the server fixture uses raw ACP session IDs while the provider fixture uses goose session IDs, preventing shared test coverage.

This adds mode validation and aligns the test fixtures. session/set_mode validates the mode string and session existence, and rejects mode changes since per-session persistence is not yet implemented (#7603). The ExpectedSessionId trait lets server and provider tests share the same test functions. Both paths exercise identical error cases.

Type of Change

  • Bug fix
  • Tests

AI Assistance

  • This PR was created or reviewed with AI assistance

Testing

Zed (ACP)

Kill goose and clear session/log state:

$ pkill -f goose
$ rm -rf ~/.local/state/goose/logs ~/.local/share/goose/sessions
$ rm -rf ~/Library/Logs/Zed/ ~/Library/Application\ Support/Zed/threads/

Build the release binary:

$ just release-binary

Add to ~/.config/zed/settings.json:

"agent_servers": {
  "goose": {
    "type": "custom",
    "command": "/path/to/goose-2/target/release/goose",
    "args": ["acp", "--with-builtin", "developer"],
    "env": {
      "RUST_LOG": "debug"
    }
  }
}

Mode selection (expected rejection):

Open Zed's agent panel. The mode selector (bottom bar, next to model selector) shows "auto" as the default.

  1. Click the mode selector -- all four modes appear (auto, approve, smart_approve, chat) with descriptions
  2. Switch to "approve"
  3. Verify the rejection in goose logs:
$ grep -h "Mode change not supported" ~/.local/state/goose/logs/cli/*/*.log
{"timestamp":"...","level":"WARN","fields":{"message":"Sending error response","id":"Number(3)","error":"Error { code: -32602: Invalid params, message: \"Invalid params\", data: Some(String(\"Mode change not supported: session is auto, requested approve\")) }"},"target":"sacp::jsonrpc::outgoing_actor",...}

Related Issues

Prerequisite for #7603

Screenshots

Zed supports mode selection, so I used that.

Before

Goose has no mode selection, just model:

Screenshot 2026-03-13 at 1 18 51 PM

After

The selector briefly shows "approve" then reverts to "auto" -- Zed optimistically updates the UI, then silently reverts when the server returns an error. The error exists until modes are session scoped in #7603

mode selection but disabled

@codefromthecrypt
Copy link
Collaborator Author

this PR is too big, so I will split it into two.

  1. Persist goose mode to memory and DB on change (mode visibility fix for everything)
  2. ACP support of session mode in general (this code has no idea about the DB and leaves only one patch for sync'ing)

@codefromthecrypt codefromthecrypt changed the title fix: persist GooseMode per-session via session DB and ACP Add session/set_mode handler to ACP Mar 13, 2026
@codefromthecrypt codefromthecrypt changed the title Add session/set_mode handler to ACP feat(acp): add session/set_mode handler Mar 13, 2026
@codefromthecrypt codefromthecrypt marked this pull request as ready for review March 13, 2026 05:19
@codefromthecrypt
Copy link
Collaborator Author

fyi I rescoped this PR to the ACP prep part of mode support. I have a local branch ready to add session-scope mode (and persist) that will fix #7603

This is a pre-req as doing both in the same change was too blurry, especially as a lot of the session persistence logic was plumbing to server and the Goose UI (not affecting ACP in really any way).

false
}

async fn update_mode(&self, _session_id: &str, _mode: GooseMode) -> Result<(), ProviderError> {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

so this is a callback which agentic providers can implement to sync their mode for a given session. It is basically the same way permissions integration in ACP works.

}
}

async fn run_with_child(
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

this is mechanically moving around because things were getting hairy in the older layout, especially as we add things like mode and later other things.

@codefromthecrypt
Copy link
Collaborator Author

will rebase after #7843 which will drift it

@codefromthecrypt
Copy link
Collaborator Author

side note: I notice the whole permissions integration is hairy, but there's a lot of code moving around with high frequency. I'd like to let that settle before refactoring, I think with some message types we can avoid some of the duplication mode/permission logic that is handled both in ACP internally and also somewhat similarly in the agent loops.

@codefromthecrypt
Copy link
Collaborator Author

#7854 is the mode mutablility/persistence thing split off from this. it keeps things less coupled.. when both of these are in, connecting acp to updatable mode will be less to review

Add session/set_mode handler that validates the mode string and session
existence, rejecting mode changes until per-session persistence lands
(#7603). Zed mode selector populates from session/new and session/load
responses but previously mode changes were silently ignored.

Extract ExpectedSessionId trait so server and provider tests share
common_tests. Both paths now exercise identical error cases.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
@codefromthecrypt codefromthecrypt added this pull request to the merge queue Mar 13, 2026
Merged via the queue into main with commit 1b05c92 Mar 13, 2026
24 checks passed
@codefromthecrypt codefromthecrypt deleted the adrian/goose-acp-mode branch March 13, 2026 09:37
michaelneale added a commit that referenced this pull request Mar 15, 2026
* origin/main:
  fix: tool confirmation handling for multiple requests (#7856)
  Remove dead OllamaSetup onboarding flow (#7861)
  fix: resolve tokio::sync::Mutex deadlock in recipe retry path (#7832)
  Upgrade Electron 40.6.0 → 41.0.0 (#7851)
  Only show up to 50 lines of source code (#7578)
  fix: stop writing without error when hitting broken pipe for goose session list (#7858)
  feat(acp): add session/set_mode handler (#7801)
  Keep messages in sync (#7850)
  More acp tools (#7843)
lifeizhou-ap added a commit that referenced this pull request Mar 16, 2026
* main: (191 commits)
  fix: add tool_choice and parallel_tool_calls to chatgpt_codex provider (#7867)
  fix: tool confirmation handling for multiple requests (#7856)
  Remove dead OllamaSetup onboarding flow (#7861)
  fix: resolve tokio::sync::Mutex deadlock in recipe retry path (#7832)
  Upgrade Electron 40.6.0 → 41.0.0 (#7851)
  Only show up to 50 lines of source code (#7578)
  fix: stop writing without error when hitting broken pipe for goose session list (#7858)
  feat(acp): add session/set_mode handler (#7801)
  Keep messages in sync (#7850)
  More acp tools (#7843)
  fix: skip upgrade-insecure-requests CSP for external HTTP backends (#7714)
  fix(shell): prevent hang when command backgrounds a child process (#7689)
  Remove include from Cargo.toml in goose-mcp (#7838)
  Exit agent loop when tool call JSON fails to parse (#7840)
  chore: remove redundant husky prepare script (#7829)
  Add github actions workflow for unused deps (#7681)
  fix: prevent SSE connection drops from silently truncating responses (#7831)
  doc: Added notes in contribution guide for pnpm (#7833)
  add prefer-offline to pnpm config to skip unnecessary registry lookups (#7828)
  fix: remove dead read handler from DeveloperClient (#7821)
  ...
jh-block added a commit that referenced this pull request Mar 16, 2026
* main: (65 commits)
  feat(otel): propagate session.id to spans and log records (#7490)
  fix(test): add env_lock to is_openai_reasoning_model tests (#7917)
  fix(acp): pass session_id when loading extensions so skills are discovered (#7868)
  updated canonical models (#7920)
  feat(autovisualiser): Migrate the autovisualiser extension to MCP Apps  (#7852)
  fix: add tool_choice and parallel_tool_calls to chatgpt_codex provider (#7867)
  fix: tool confirmation handling for multiple requests (#7856)
  Remove dead OllamaSetup onboarding flow (#7861)
  fix: resolve tokio::sync::Mutex deadlock in recipe retry path (#7832)
  Upgrade Electron 40.6.0 → 41.0.0 (#7851)
  Only show up to 50 lines of source code (#7578)
  fix: stop writing without error when hitting broken pipe for goose session list (#7858)
  feat(acp): add session/set_mode handler (#7801)
  Keep messages in sync (#7850)
  More acp tools (#7843)
  fix: skip upgrade-insecure-requests CSP for external HTTP backends (#7714)
  fix(shell): prevent hang when command backgrounds a child process (#7689)
  Remove include from Cargo.toml in goose-mcp (#7838)
  Exit agent loop when tool call JSON fails to parse (#7840)
  chore: remove redundant husky prepare script (#7829)
  ...
wpfleger96 added a commit that referenced this pull request Mar 16, 2026
…oken-retry

* origin/main: (21 commits)
  Remove java/.ai-usage-marker directory (#7925)
  test(acp): add terminal delegation fixtures and fix shell singleton (#7923)
  fix: bump pctx_code_mode to 0.3.0 for iterator type checking fix (#7892)
  feat: persist GooseMode per-session via session DB (#7854)
  feat(otel): propagate session.id to spans and log records (#7490)
  fix(test): add env_lock to is_openai_reasoning_model tests (#7917)
  fix(acp): pass session_id when loading extensions so skills are discovered (#7868)
  updated canonical models (#7920)
  feat(autovisualiser): Migrate the autovisualiser extension to MCP Apps  (#7852)
  fix: add tool_choice and parallel_tool_calls to chatgpt_codex provider (#7867)
  fix: tool confirmation handling for multiple requests (#7856)
  Remove dead OllamaSetup onboarding flow (#7861)
  fix: resolve tokio::sync::Mutex deadlock in recipe retry path (#7832)
  Upgrade Electron 40.6.0 → 41.0.0 (#7851)
  Only show up to 50 lines of source code (#7578)
  fix: stop writing without error when hitting broken pipe for goose session list (#7858)
  feat(acp): add session/set_mode handler (#7801)
  Keep messages in sync (#7850)
  More acp tools (#7843)
  fix: skip upgrade-insecure-requests CSP for external HTTP backends (#7714)
  ...
wpfleger96 added a commit that referenced this pull request Mar 16, 2026
* origin/main: (72 commits)
  No Check do Check (#7942)
  Log 500 errors and also show error for direct download (#7936)
  fix: retry on authentication failure with credential refresh (#7812)
  Remove java/.ai-usage-marker directory (#7925)
  test(acp): add terminal delegation fixtures and fix shell singleton (#7923)
  fix: bump pctx_code_mode to 0.3.0 for iterator type checking fix (#7892)
  feat: persist GooseMode per-session via session DB (#7854)
  feat(otel): propagate session.id to spans and log records (#7490)
  fix(test): add env_lock to is_openai_reasoning_model tests (#7917)
  fix(acp): pass session_id when loading extensions so skills are discovered (#7868)
  updated canonical models (#7920)
  feat(autovisualiser): Migrate the autovisualiser extension to MCP Apps  (#7852)
  fix: add tool_choice and parallel_tool_calls to chatgpt_codex provider (#7867)
  fix: tool confirmation handling for multiple requests (#7856)
  Remove dead OllamaSetup onboarding flow (#7861)
  fix: resolve tokio::sync::Mutex deadlock in recipe retry path (#7832)
  Upgrade Electron 40.6.0 → 41.0.0 (#7851)
  Only show up to 50 lines of source code (#7578)
  fix: stop writing without error when hitting broken pipe for goose session list (#7858)
  feat(acp): add session/set_mode handler (#7801)
  ...
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