Read deferred-tool hiddenness from visibility, not absence

Merged
DO
3mo ago
+17-2

Closes #572.

test on latest pydantic-ai fails TestCodeMode::test_deferred_capability_loader_stays_native_with_tools_all against current Pydantic AI. This is a stale assertion, not a core regression.

Measured directly against Pydantic AI main (f9cd74f8e), with a deferred capability and CodeMode(tools='all'):

function_tools: ['demo_tool', 'load_capability', 'run_code']
visibility_of('demo_tool'): withheld

The tool is still withheld from the wire — the behaviour #276 protects is intact. What changed is that since the declared/visibility split, function_tools retains hidden declarations and hiddenness is expressed through visibility_of rather than by the name being absent. So the assertion that demo_tool is not in function_tools no longer describes "hidden".

This reads hiddenness from the visibility accessor, guarded behind a runtime-checkable protocol so the test still passes against a Pydantic AI that predates it. Same accommodation already written in #562; lifting it to main on its own so every open branch stops failing this job while that PR is in flight.

Verified: tests/code_mode/ is 130 passed against both the locked Pydantic AI and Pydantic AI main.