Skip to content

feat(phai): add refresh_session ACP method for sandboxes#1717

Merged
skoob13 merged 2 commits into
mainfrom
feat/refresh-method-for-sandboxes
Apr 17, 2026
Merged

feat(phai): add refresh_session ACP method for sandboxes#1717
skoob13 merged 2 commits into
mainfrom
feat/refresh-method-for-sandboxes

Conversation

@skoob13
Copy link
Copy Markdown
Contributor

@skoob13 skoob13 commented Apr 17, 2026

Problem

Sandbox agent-servers need a way to refresh a Claude session's MCP server config between turns — for example, to swap in freshly-minted OAuth credentials on a pre-prompt TTL check — without tearing down the whole session and losing conversation history.

Changes

  • Add _posthog/refresh_session custom ACP extension method (request/response, not notification) so the caller can await completion before sending the next prompt.
  • Implement ClaudeAcpAgent.extMethod() for the Claude adapter: interrupts the running Query, ends the input stream, and builds a new Query with updated mcpServers using resume (not sessionId) so conversation history is preserved.
  • Use the resume+rebuild pattern instead of query.setMcpServers() because the latter can non-deterministically surface plugin-installed MCPs over the CLI-supplied ones; passing mcpServers via query() options guarantees overwrite.
  • Refactor isNotification in acp-extensions.ts to share matching logic with a new isMethod helper, and add a POSTHOG_METHODS registry.
  • Reject refresh attempts while a prompt turn is in flight.

How did you test this code?

  • New unit tests in packages/agent/src/acp-extensions.test.ts cover isNotification/isMethod including the __posthog/ double-prefix case.
  • New unit tests in packages/agent/src/adapters/claude/claude-agent.refresh.test.ts verify that refresh_session:
    • throws methodNotFound for unknown ext methods,
    • rejects while a prompt is running,
    • swaps query/input/queryOptions and preserves session-level state (accumulated usage, notification history),
    • builds the new query() call with resume instead of sessionId and the new MCP server set.

Publish to changelog?

no

@skoob13 skoob13 requested a review from a team April 17, 2026 15:48
Copy link
Copy Markdown
Contributor

@tatoalo tatoalo left a comment

Choose a reason for hiding this comment

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

lfg

- Abort the old AbortController before awaiting interrupt() so stuck HTTP
  requests can't deadlock the refresh; allocate a fresh controller for the
  new Query and update session.abortController so closeSession still works.
- Reject refresh when session.modelId is on the MCP-exclusion list (e.g.
  claude-haiku-4-5), matching the guard in handleNewSession.
- Reject payloads with no refreshable fields or a non-array mcpServers so
  caller bugs surface loudly instead of returning a phantom success.
- Replace spread + delete sessionId with destructuring.
- Expand tests: payload validation, unsupported-model, initialization
  timeout (fake timers), AbortController identity swap, MCP metadata
  refetch for the new Query.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@skoob13 skoob13 merged commit d8b0d76 into main Apr 17, 2026
15 checks passed
@skoob13 skoob13 deleted the feat/refresh-method-for-sandboxes branch April 17, 2026 16:46
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