[AAASM-4746] ♻️ (adapters): De-duplicate google_adk/pydantic_ai parallel adapters - #271
Conversation
Extract the async tool-governance flow (arg serialization, verdict normalization, pending-approval round-trip, deny-by-raise, spawn-scoped original call, result recording) that Google ADK and Pydantic AI adapters duplicated verbatim into one framework-agnostic helper. Preserves the AAASM-4734 fail-closed-under-enforce contract by threading enforce and reusing the CrewAI _missing_interceptor_decision fallback. Refs AAASM-4746
Replace the adapter's local copies of the async tool-governance flow and its leaf helpers with the shared _shared.tool_governance module; the patched run_async now supplies only the framework-specific invoke_original callable. Shared helpers are re-imported (and listed in __all__) so the adapter's unit tests still reach them through this module. Behavior unchanged. Refs AAASM-4746
Replace the adapter's local copies of the async tool-governance flow and its leaf helpers with the shared _shared.tool_governance module; both the Tool._run and toolset call_tool patches now supply only a framework-specific invoke_original callable. Shared helpers are re-imported (and listed in __all__) so the adapter's unit tests still reach them through this module. Behavior unchanged. Refs AAASM-4746
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
|
Claude Code — automated reviewCI: All green — and SonarCloud gate now OK (new-code duplication resolved), retiring the acceptance-tier waiver from #269 at its root. |
Claude Code — review result (final pass)CI: all checks green. Scope: matches the ticket. Side effects: none — green full-suite CI validates no existing-function/business-logic breakage. Front-End: no FE/dashboard code touched, so no Playwright validation applies. Verdict: ✅ ready to approve & merge. Review comments: github-code-quality bot flagged 2 "statement has no effect" on |



Description
Pure refactor that de-duplicates the near-identical parallel adapters
agent_assembly/adapters/google_adk/patch.pyandagent_assembly/adapters/pydantic_ai/patch.py. SonarCloud reported cross-fileduplicated blocks (up to ~126 lines) between them — the root of the waived
SonarCloud new-dup on PR #269.
The shared async tool-governance flow (arg serialization, verdict
normalization, the
pendingapproval round-trip, deny-by-raise, thespawn-context-scoped original call, and result recording) plus its leaf helpers
are extracted into a new private module
agent_assembly/adapters/_shared/tool_governance.py, exposing a singlerun_governed_async_tool(...)orchestrator that each adapter drives via aframework-specific
invoke_originalcallable. Each adapter now keeps only itsown glue: class loaders, patched-flag constants,
_resolve_agent_id/_resolve_run_id, the agent-run/toolset patches, and the per-adapter processagent-id global.
The
openai_agentsadapter was intentionally left out of the extraction: itsdeny path returns a string to the model (rather than raising), wraps the flow in
a governance-error try/except, and records-before-return — sharing it would
change observable behavior, so it stays on its own copy.
Behavior is unchanged. The AAASM-4734 fail-closed-under-enforce fix is
preserved exactly:
enforceis threaded into the shared flow and acheck_tool_start-less interceptor still falls back to_missing_interceptor_decision, so all four adapters continue to deny underenforce on an unrecognized verdict / missing
check_tool_start. Shared helpersare re-imported into each adapter module (and listed in
__all__) so theexisting unit tests, which reach these helpers through the adapter module, keep
working untouched.
Duplication removed:
google_adk/patch.py405 → 248 lines,pydantic_ai/patch.py620 → 431 lines (−346 duplicated lines total); the shared flow now lives in one
244-line module.
Type of Change
Breaking Changes
Related Issues
Testing
is unchanged and exercises the shared flow through both adapters.
.venv/bin/python -m pytest test/unit/adapters -q→ 379 passed, 3 skipped (matches the pre-refactor baseline).
ruff check,ruff format --check, and per-filemypyare clean on all touched files.Checklist
Fixes AAASM-4746