feat(compat): AdapterPair pattern + v2.5 sync_creatives (stage 4)#661
Closed
bokelley wants to merge 1 commit into
Closed
feat(compat): AdapterPair pattern + v2.5 sync_creatives (stage 4)#661bokelley wants to merge 1 commit into
bokelley wants to merge 1 commit into
Conversation
fc7dd4c to
d0c1944
Compare
df85e26 to
afa8455
Compare
Stage 4 of the versioned-schema-validation port. Replaces the heuristic ``spec_compat_hooks()`` model with a typed per-tool adapter registry. What changed: * New package ``adcp.compat.legacy`` with the ``AdapterPair`` dataclass, registry (``get_legacy_adapter`` / ``list_legacy_adapter_tools``), and the ``LEGACY_ADAPTER_VERSIONS`` constant. Mirrors the TS SDK's ``src/lib/adapters/legacy/v2-5/``. * First concrete adapter: ``adcp.compat.legacy.v2_5.sync_creatives``. Three wire-shape coercions (bare-string ``format_id`` → structured, ``asset_type`` inference, ``image``-without-dims → ``url`` demotion). * ``validation.envelope.SUPPORTED_WIRE_VERSIONS`` now includes legacy versions, so ``detect_wire_version`` accepts both native and legacy claims. * ``create_tool_caller`` routes legacy-versioned requests through the adapter: ``adapt_request`` runs *after* version detection and *before* current-schema validation, so a buggy translator surfaces as ``INVALID_REQUEST`` with a field-level pointer. A legacy version with no adapter for the requested tool raises ``INVALID_REQUEST``. * Response side: optional ``normalize_response`` callable runs after current-schema validation. ``sync_creatives`` has the same response shape across v2.5/v3 so leaves it ``None``. Deferred (Stage 4b): real v2.5 schema bundle. Upstream CDN doesn't ship v2.5 tarballs; the JS SDK pins a GitHub commit SHA. Wire that fetch in a follow-up. Today the adapter validates against the v3 output only. Tests (25 new): registry contract, every v2.5 sync_creatives coercion via the public adapter surface, end-to-end dispatcher routing including missing-adapter and adapter-raises cases. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
afa8455 to
0eb2b06
Compare
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.
Stacked on #660 (which is stacked on #659).
Summary
Stage 4 of the versioned-schema-validation port. Replaces the heuristic
spec_compat_hooks()model with a typed per-tool adapter registry.adcp.compat.legacywithAdapterPairdataclass, registry, andLEGACY_ADAPTER_VERSIONS = (\"2.5\",)— mirrors the TS SDK'ssrc/lib/adapters/legacy/v2-5/.adcp.compat.legacy.v2_5.sync_creatives. Three wire-shape coercions: bareformat_id→ structured,asset_typeinference,image-without-dims →urldemotion.create_tool_callerroutes legacy-versioned requests through the adapter before current-schema validation. Missing adapter for a tool at a legacy version →INVALID_REQUESTbefore handler dispatch.Why this works
The adapter sits between wire decoding and current-schema validation. A v2.5 buyer sends their wire shape, the adapter rewrites it to v3 shape, and the existing v3 schema + Pydantic model validation runs. A buggy translator surfaces as
INVALID_REQUESTwith a field-level pointer — the same error mode adopters already know — instead of leaking through as opaque data.Response side runs
normalize_response(if the adapter declares one) after validation, so the buyer sees their expected shape.sync_creativesdoesn't need this; later adapters (preview_creative) will.Deferred to Stage 4b
Real v2.5 schema bundle. Upstream CDN (
adcontextprotocol.org/protocol/) doesn't ship v2.5 tarballs; the JS SDK pins to a GitHub commit SHA. Wire that fetch in a follow-up. Today the adapter validates against v3 output only.Test plan
pytest tests/— 4453 passed (one unrelated flaky timing test deselected)ruff check+mypyStage 5 will
Port the remaining v2.5 adapters (
get_products,create_media_buy,update_media_buy,list_creative_formats,preview_creative) and add a deprecation warning onspec_compat_hooks()pointing at the new layer.🤖 Generated with Claude Code