feat(pydantic-acp): auth recovery, public session bootstrap, and clean agent-error propagation#22
Open
arthrod wants to merge 1 commit into
Open
Conversation
…agate real agent errors Hardens the pydantic-acp ACP client/provider so an unusable ACP agent fails legibly instead of silently, and adds the session-bootstrap surface the bridge was missing. Added - Auth recovery: AcpProvider captures initialize's auth_methods and, when session/new is rejected with auth_required (-32000), runs the ACP authenticate flow (an advertised method, or an explicit auth_method_id=) and retries session creation once. Such agents were previously unrecoverable. - Public session bootstrap: AcpProvider.ensure_session() and AcpProvider.set_session_mode() bootstrap a session and select a session mode without sending a prompt turn, so callers no longer reach into the private _ensure_session. - Opt-in AcpProvider(raise_on_empty_turn=True) raises UnexpectedModelBehavior with an ACP-specific diagnostic when a text-output turn yields no visible text. Default False preserves the existing empty-response contract. Fixed - request_prompt propagates the agent's real error (rate limit, auth rejection, upstream API failure) by unwrapping single-child anyio TaskGroup BaseExceptionGroups and dropping TaskGroup __context__ noise, instead of surfacing an opaque "ExceptionGroup: unhandled errors in a TaskGroup". Synchronized workspace bump 1.5.0 -> 1.6.0 with CHANGELOG entry. pydantic-acp client.py is at 100% line and branch coverage; make check (ruff + ty + basedpyright), make tests, make check-coverage, and pre-commit all pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CweysdtvG97d28xrbeF9BM
10 tasks
Member
|
I'll check today, thanks for contribution. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Hardens the
pydantic-acpACP client/provider so an unusable ACP agent fails legibly instead of silently, and adds the session-bootstrap surface the bridge was missing. Single commit offmain; ships as synchronized release 1.5.0 → 1.6.0.Motivation: driving real stdio ACP agents (Claude Code, GLM, dirac, vibe, grok, …) surfaced three gaps where a broken/unauthenticated/throttled agent produced an empty turn or an opaque
ExceptionGroupwith no indication of the real cause, and no public way to bring a session up before prompting.Added
AcpProvidercapturesinitialize'sauth_methodsand, whensession/newis rejected withauth_required(-32000), runs the ACPauthenticateflow — an advertised method, or an explicitauth_method_id=— and retries session creation once. Agents that gatesession/newon authentication were previously unrecoverable.AcpProvider.ensure_session()andAcpProvider.set_session_mode()bootstrap a session and select a session mode without sending a prompt turn, so callers no longer reach into the private_ensure_session.AcpProvider(raise_on_empty_turn=True)raisesUnexpectedModelBehaviorwith an ACP-specific message when a text-output turn yields no visible text. DefaultFalsepreserves the existing empty-response contract (and its test).Fixed
request_promptpropagates the agent's real error (rate limit, auth rejection, upstream API failure) by unwrapping single-child anyio TaskGroupBaseExceptionGroups and dropping TaskGroup__context__noise, instead of surfacing an opaqueExceptionGroup: unhandled errors in a TaskGroup.asyncio.CancelledErroris re-raised untouched.Fixes # (n/a)
Type of change
Checklist:
[1.6.0])Verification
make check— ruff, ty, basedpyright all cleanmake tests— 694 passedmake check-coverage— thresholds satisfied;pydantic_acp/client.pyat 100% line + branch (added anauthenticate/ensure_session/set_session_mode/raise_on_empty_turn/unwrap/CancelledErrortest set)uv run pre-commit run --all-files— all hooks pass, including version-ahead-of-PyPI1.6.0bump viabump.sh(version files + root extras) + CHANGELOG entry🤖 Generated with Claude Code