Commit Graph

5 Commits

Author SHA1 Message Date
Mark 4917c67c99 fix(showcase): apply the multimodal provider gate to v2 native content
PydanticAI v2's AGUIAdapter.load_messages converts AG-UI attachments to
native content types before the model boundary; v1 delivered the raw AG-UI
part dicts. _NATIVE_CONTENT listed BinaryContent as a flatten fixpoint, so
under v2 inline attachments were waved straight through and the whole
provider gate was skipped:

- inline PDFs were no longer text-extracted, so raw bytes went to OpenAI
- unsupported image subtypes (HEIC/SVG/TIFF) were no longer degraded and
  reached the provider as images, which fails the turn
- missing-mime magic-byte sniffing never ran
- AudioUrl/VideoUrl were neither fixpoints nor classifiable, so they hit
  the fail-loud raise

BinaryContent is no longer treated as a fixpoint. _classify_native_content
maps native content onto the same (kind, scheme, mime, value) tuple the
AG-UI classifier produces, so every existing gate — PDF extraction, image
sniffing, the supported-subtype allow list, the binary choke point —
applies unchanged. audio/* and video/* mimes are named explicitly because
_kind_for routes them to "other", and a missing mime defaults to "image"
so the sniffer runs.

Five test assertions checked that state-backing content was still AG-UI
InputContent, which encoded v1's bridging. They now assert the flatten's
output (ImageUrl) never appears in state, which is the guarantee they were
written to protect. Behaviour is otherwise unchanged: a supported inline
image still flattens to an ImageUrl data URI exactly as on v1.

52/52 python tests pass, up from 42/52. Verified against pydantic-ai
2.22.0.
2026-08-04 23:24:43 +00:00
Mark febd24954c chore(showcase): port pydantic-ai integration to Pydantic AI v2
Server, agents and pins moved to v2. The /multimodal cell is NOT yet
ported — see below.

- requirements.txt: pydantic-ai-slim 2.22.0, ag-ui-protocol 0.1.19. Drops
  the opentelemetry-api<1.44 ceiling; v2 works with otel 1.44.0.
- StateDeps imports move from pydantic_ai.ag_ui to pydantic_ai.ui across
  the 8 agent modules and one test.
- agent_server.py: to_ag_ui() was removed in v2, so a mount_agent() helper
  builds the equivalent Starlette sub-app (single POST / route, matching
  what AGUIApp produced) and mounts it. All 19 paths are byte-identical,
  trailing slashes included, so no TS route changes. deps are constructed
  per request because v2's adapter assigns client state onto deps.state
  instead of replacing the deps object as v1 did.
- test_multimodal_content_mapping.py: importorskip pointed at the removed
  pydantic_ai.ag_ui, which would have skipped all 43 tests green under v2.
  Now targets pydantic_ai.ui.ag_ui and uses the public
  AGUIAdapter.load_messages in place of the v1 private helper.

Verified against pydantic-ai 2.22.0 by driving the real app with
TestClient: 16/19 mounts return 200 SSE with RUN_STARTED..RUN_FINISHED and
no RUN_ERROR. The other 3 (/a2ui_dynamic, /beautiful_chat, /) reach tool
execution and then fail on a raw OpenAI() client constructed inside a tool,
which the harness cannot intercept and aimock handles in CI. Per-request
deps isolation confirmed on /shared_state_read_write: state sent by one
request does not appear in the next.

Known incomplete: multimodal_agent.py does not handle v2's content types.
v2's load_messages emits BinaryContent where v1 emitted ImageUrl, so
_flatten_messages_for_model no longer flattens it, VideoUrl reaches the
unrecognised-part raise, and one binary path raises RuntimeError. 10 of
the 43 multimodal tests fail as a result.
2026-08-04 22:39:42 +00:00
Jordan Ritter 27b5e79a00 test(showcase): cover pydantic-ai multimodal content mapping + degrade paths 2026-06-24 09:16:07 -07:00
github-actions[bot] 691c036789 style: auto-fix formatting 2026-06-19 20:54:20 +00:00
Jordan Ritter 9d66761064 feat(cvdiag): backend instrumentation for pydantic-ai + crewai-crews + agno (L1-D2) 2026-06-18 14:37:10 -07:00