Skip to content

fix: delegate default model selection to providers#48

Merged
ebarti merged 1 commit into
mainfrom
agent/stack-08-provider-native-models
Jul 10, 2026
Merged

fix: delegate default model selection to providers#48
ebarti merged 1 commit into
mainfrom
agent/stack-08-provider-native-models

Conversation

@ebarti

@ebarti ebarti commented Jul 10, 2026

Copy link
Copy Markdown
Owner

What

  • delegates the no-override model choice to each provider instead of pinning library-owned names
  • preserves one precedence chain: task field > legacy metadata > constructor override > provider-native
  • omits vendor model kwargs when selection is provider-native
  • records model_source on every provider result and records model only when known
  • keeps default_model= as an explicit migration override
  • makes configured model allow-lists fail closed when provider-native selection cannot be verified

Why

Hard-coded adapter defaults age faster than the SDK and can override supported provider configuration. The SDK-evolution docs already described Claude and Antigravity as provider-native, but the adapters silently forced stale model names.

Root cause

Model resolution treated the library constructor default as mandatory rather than an optional override, and result metadata could not distinguish task, metadata, constructor, and provider-native selection.

Compatibility

This is an intentional pre-1.0 behavior change. Applications that need the prior pin can pass the same value through default_model=; task and metadata overrides keep their existing precedence.

Checks

  • ruff check src tests
  • strict mypy
  • full all-extras suite: 396 passed, 3 skipped
  • model-policy coverage run: 356 passed, 3 skipped; 91.00% coverage
  • installed SDK contracts: 23 passed
  • uv lock --check
  • uv build

Stack

@ebarti ebarti force-pushed the agent/stack-07-runtime-readiness branch from b18fd9b to 4bcfab9 Compare July 10, 2026 22:46
ebarti added a commit that referenced this pull request Jul 10, 2026
## What

- separates side-effect-free package availability from explicit async
execution readiness
- adds `RuntimeReadiness`, `ReadinessStatus`, optional
`RuntimeReadinessProvider`, and bounded `check_readiness()`
- exposes readiness through the registry, AgentKit, provider
diagnostics, and live smoke path
- probes Claude credential signals without claiming local/provider
chains are verified
- probes Codex through the supported account API with guaranteed
temporary-client cleanup
- probes Antigravity API-key/ADC setup off the event loop and converts
timeout/failure into secret-safe diagnostics

## Why

`availability()` mixed package presence with potentially blocking
credential discovery. In particular, Antigravity could read files or
contact Google metadata services from a synchronous setup check, while
Claude/Codex package success was easy to misread as execution readiness.

## Root cause

One diagnostic type represented two different questions: “is the adapter
installed?” and “is enough setup present to attempt a provider call?”
Provider authentication mechanisms also differ in how safely they can be
probed.

## Semantics

- `availability()`: synchronous, package-only, side-effect-free
- `READY_TO_ATTEMPT`: setup signal confirmed, not a guarantee of
execution
- `NOT_READY`: a concrete package/credential problem was established
- `INDETERMINATE`: provider-owned/local chains, timeout, or probe
failure require caller policy
- readiness remains an optional extension, so the `AgentRuntime`
protocol is unchanged

## Checks

- `ruff check src tests`
- strict `mypy`
- full suite: 380 passed, 3 skipped in the all-extras verification
environment
- delegated run: 371 passed, 12 skipped; 90.92% coverage
- `uv lock --check`
- `uv build` plus wheel/sdist content inspection

## Stack

- Base: #46
- Next: #48
Base automatically changed from agent/stack-07-runtime-readiness to main July 10, 2026 22:47
@ebarti ebarti force-pushed the agent/stack-08-provider-native-models branch from 1fe7c21 to 530d4f6 Compare July 10, 2026 22:47
@ebarti ebarti marked this pull request as ready for review July 10, 2026 22:47
@ebarti ebarti merged commit efd5153 into main Jul 10, 2026
11 checks passed
@ebarti ebarti deleted the agent/stack-08-provider-native-models branch July 10, 2026 22:48
ebarti added a commit that referenced this pull request Jul 10, 2026
## Stack

- Base: #48
- Next: none — stack halted after this PR as requested

## What this fixes

The runtime protocol advertised cancellation, but every provider adapter
implemented it as a no-op, and tasks had no portable execution deadline.
That left callers unable to bound startup, process-reuse queueing, or
in-flight provider work.

## Changes

- add keyword-only, timezone-aware `AgentTask.deadline`
- add `AgentKit.run(timeout=...)` as a finite non-negative
seconds/`timedelta` convenience
- add `AgentTaskTimeoutError` and `FinishReason.TIMED_OUT`
- add immutable `CancellationReceipt` and explicit cancellation
dispositions
- make built-in Claude, Codex, Antigravity, and fake runtimes
cancellation-aware
- make `AgentKit.cancel()` target active cached runtimes without
constructing new ones
- preserve legacy third-party runtimes whose `cancel()` returns `None`
- document cancellation's non-rollback semantics

## Adversarial race hardening

Independent reproductions found concurrency defects beyond the initial
green suite. Follow-up commits now:

- bind cancellation to the exact asyncio task generation
- reserve same-id tombstones while legacy task-id hooks settle,
preventing ABA cancellation
- remove cancellable lock windows from registration/unregistration
- keep cancellation effective if the `AgentKit.cancel()` caller is
cancelled
- make completion-race receipts truthful
- make timeout causality win once the deadline fires and emit at most
one terminal
- skip misleading started events for already-expired tasks
- give provider/operation teardown a bounded five-second grace period
- quarantine runtime instances while detached cleanup remains pending,
rejecting overlap and recovering automatically when cleanup settles
- validate deadline runtime types deliberately instead of leaking
`AttributeError`

## Verification

- all-extras full suite: 418 passed, 3 skipped
- core-only full suite: 409 passed, 12 skipped
- all-extras coverage: 90.33% (minimum 85%)
- focused race/control suite: 22 passed
- final independent quarantine reproductions: 3 passed; no pending-task
warnings
- `uv run ruff check .`
- strict `mypy`
- `uv lock --check`
- `uv build`
- `git diff --check`

## Stack health

All 11 required GitHub checks pass on `bcd080c`; the opt-in
upstream-latest workflow is skipped by design.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant