fix(acp): eliminate end_turn latency from blocking token-cost fallback - #387
Conversation
Review: PR #387 — fix(acp): eliminate end_turn latency from blocking token-cost fallbackI read the diff, the surrounding source, and verified the external API behavior (tokonomics 1.2.18 and anyenv/httpx internals). The root-cause diagnosis is sound and the latency bound is real, but there are several concerns — two of them structural. MAJOR1. The prefetch does not seed the cache keys the runtime actually looks up, so the first turn still downloads — and the 0.2s guard permanently zeroes the model. In the exact scenario this PR targets (host unreachable at startup → prefetch fails), the first runtime fallback is the first network attempt. It exceeds the 0.2s timeout → Suggested fix: seed the prefetch with the colon-form strings the runtime actually emits (or derive them from the pool's models), and/or have the fallback pass 2. The prefetch task is untimed and will delay server shutdown by up to ~5s. MINOR3. The negative cache never expires and conflates "transient timeout" with "not found". 4. Telemetry rule violation — background task with no span. 5. Check-then-act race on the negative cache. 6. The two prefetch probes are redundant/misleading. 7. The prefetch adds a real-network dependency to every server start, including spawned test servers. NITS
Positive
|
|
Review posted to #387 (comment). Summary of the review: MAJOR
MINOR — negative cache never expires and conflates timeout with not-found; background task violates the telemetry span rule; check-then-act race on the negative cache; redundant/misleading prefetch probes; prefetch adds a real-network dependency to every server start (incl. spawned e2e servers). Nits — changelog trailing newline; Verified independently: tokonomics 1.2.18 cache internals, anyio task-group exit semantics, |

Problem
On turn completion, ACP servers delay sending
end_turnby several seconds. Root cause:TokenCost.from_usageruns before theStreamCompleteEventis emitted (cost must be attached to the turn-final event). For models absent from the localgenai_pricespricing snapshot (e.g.MiniMax-H3raisingLookupError), the tokonomics fallback performs a blocking, untimed download of the ~1 MB LiteLLM pricing table from GitHub. Measured 3.657s stall when the host is unreachable, and the failure was never cached — every subsequent turn retried the download.Fix
BaseServer.startnow launchesprefetch_token_cost_cachein the background, seeding the process-wide tokonomics pricing cache once at startup so runtime lookups are memory hits.asyncio.timeout(0.2); failed models are negatively cached (module-level_COST_FALLBACK_FAILED), degrading cost to0instead of blocking end_turn. Worst case adds at most 0.2s to a single turn.tests/messaging/test_token_cost_fallback.pycovers the fast path, failure negative-caching (call count == 1), timeout guard, prefetch seeding, and prefetch error suppression.Verification
pytest tests/messaging/test_token_cost_fallback.py -v— 5 passedtest_runusage_corrections.py+test_acp_turn_hooks.py— 12 passedruff check— clean;mypy --strict— clean; pre-commit (ruff-format, ruff, ty, commitizen) — passed