diff --git a/agent/auxiliary_key_rotation.py b/agent/auxiliary_key_rotation.py index 7bdb5a403c..eb365f9026 100644 --- a/agent/auxiliary_key_rotation.py +++ b/agent/auxiliary_key_rotation.py @@ -1,7 +1,6 @@ """Rotate the published auxiliary main-runtime key after a credential refresh. -Split from ``agent.auxiliary_client`` (facade size cap). It reads the facade's runtime-main state -at call time, so the late import below always sees the current legacy mirror values. +Split from ``agent.auxiliary_client`` (facade size cap). """ from __future__ import annotations @@ -15,16 +14,10 @@ def rotate_runtime_main_api_key(old: Any, new: Any) -> None: A refresh can run inside a request worker's copied Context, where rebinding the ContextVar would stay invisible to the turn thread; the published dict is shared, so mutating it is not. """ - from agent.auxiliary_client import ( - _RUNTIME_MAIN_COMPAT_SNAPSHOT, _MAIN_RUNTIME_FIELDS, _RUNTIME_MAIN_CONTEXT, _normalize_api_key, - _publish_runtime_main_mirrors, - ) + from agent.auxiliary_client import _RUNTIME_MAIN_CONTEXT, _normalize_api_key + # The legacy mirrors are left alone: _compat_runtime_main() ignores them while they equal the compat + # snapshot, and republishing from here cannot tell which runtime published them. runtime = _RUNTIME_MAIN_CONTEXT.get() if isinstance(runtime, dict) and runtime.get("api_key") == old: - # Only the runtime the mirrors were published from may republish them: a scoped runtime (or another - # session's) that happens to share the old key must not overwrite them with its own route. - published = tuple(runtime.get(field, "") for field in _MAIN_RUNTIME_FIELDS) == _RUNTIME_MAIN_COMPAT_SNAPSHOT runtime["api_key"] = _normalize_api_key(new) - if published: - _publish_runtime_main_mirrors(tuple(runtime.get(field, "") for field in _MAIN_RUNTIME_FIELDS)) diff --git a/tests/agent/test_anthropic_third_party_oauth_guard.py b/tests/agent/test_anthropic_third_party_oauth_guard.py index c0a12db674..c84f1b40a3 100644 --- a/tests/agent/test_anthropic_third_party_oauth_guard.py +++ b/tests/agent/test_anthropic_third_party_oauth_guard.py @@ -205,16 +205,12 @@ class TestOAuthFlagOnRefresh: "anthropic", agent.model, runtime.get("base_url", ""), runtime.get("api_key"), "anthropic_messages", ) assert seen["api_key"] == new - # A scoped runtime (normalized copy) rotates in place but never reaches the legacy mirrors. - with aux.scoped_runtime_main({"provider": "anthropic", "api_key": old, "model": "m"}): - rotate_runtime_main_api_key(old, new) - assert aux._RUNTIME_MAIN_CONTEXT.get()["api_key"] == new - assert (aux._RUNTIME_MAIN_MODEL, aux._RUNTIME_MAIN_API_KEY) == (agent.model, new) - # Even a scope sharing the still-published old key must not republish its own route. - aux.set_runtime_main("anthropic", agent.model, api_key=old, api_mode="anthropic_messages") - with aux.scoped_runtime_main({"provider": "anthropic", "api_key": old, "model": "m"}): - rotate_runtime_main_api_key(old, new) + # A scoped runtime rotates in place; the legacy mirrors are never republished by a rotation. + with aux.scoped_runtime_main({"provider": "anthropic", "api_key": new, "model": "m"}): + rotate_runtime_main_api_key(new, "sk-ant...cccc") + assert aux._RUNTIME_MAIN_CONTEXT.get()["api_key"] == "sk-ant...cccc" assert (aux._RUNTIME_MAIN_MODEL, aux._RUNTIME_MAIN_API_KEY) == (agent.model, old) + assert aux._compat_runtime_main() is None # unchanged mirrors never become a runtime input finally: aux.clear_runtime_main()