mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
refactor: load agent identity runtime eagerly (#19763)
## Summary AgentIdentity auth previously registered the process task lazily behind a `OnceCell`. That meant the auth object could be constructed before its runtime task binding was known. This PR makes AgentIdentity auth load the runtime task at auth load time and stores the resulting process task id directly on the auth object. The model-provider call path can then read a concrete task id instead of handling a missing lazy value. ## Stack 1. [refactor: make auth loading async](https://github.com/openai/codex/pull/19762) (merged) 2. **This PR:** [refactor: load AgentIdentity runtime eagerly](https://github.com/openai/codex/pull/19763) 3. [fix: configure AgentIdentity AuthAPI base URL](https://github.com/openai/codex/pull/19904) 4. [feat: verify AgentIdentity JWTs with JWKS](https://github.com/openai/codex/pull/19764) ## Important call sites | Area | Change | | --- | --- | | `AgentIdentityAuth::load` | Registers the process task during auth loading and stores `process_task_id`. | | `CodexAuth::from_agent_identity_jwt` | Awaits AgentIdentity auth loading. | | model-provider auth | Reads a concrete `process_task_id` instead of an optional lazy value. | | AgentIdentity auth tests | Mock task registration now covers eager runtime allocation. | ## Design decisions AgentIdentity auth now treats task registration as part of constructing a usable auth object. That matches how callers use the value: once auth is present, the model-provider path expects the task-scoped assertion data to be ready. ## Testing Tests: targeted Rust auth test compilation, formatter, scoped Clippy fix, and Bazel lock check.
This commit is contained in:
@@ -9,9 +9,6 @@ use codex_login::ExternalAuth;
|
||||
use codex_login::ExternalAuthRefreshContext;
|
||||
use codex_login::ExternalAuthTokens;
|
||||
use codex_login::TokenData;
|
||||
use codex_login::auth::AgentIdentityAuth;
|
||||
use codex_login::auth::AgentIdentityAuthRecord;
|
||||
use codex_protocol::account::PlanType;
|
||||
use codex_protocol::openai_models::ModelsResponse;
|
||||
use pretty_assertions::assert_eq;
|
||||
use serde_json::json;
|
||||
@@ -237,18 +234,6 @@ c2ln",
|
||||
.expect("auth should be present")
|
||||
}
|
||||
|
||||
fn agent_identity_auth_for_tests() -> CodexAuth {
|
||||
CodexAuth::AgentIdentity(AgentIdentityAuth::new(AgentIdentityAuthRecord {
|
||||
agent_runtime_id: "agent-runtime-id".to_string(),
|
||||
agent_private_key: "agent-private-key".to_string(),
|
||||
account_id: "account-id".to_string(),
|
||||
chatgpt_user_id: "chatgpt-user-id".to_string(),
|
||||
email: "agent@example.com".to_string(),
|
||||
plan_type: PlanType::Pro,
|
||||
chatgpt_account_is_fedramp: false,
|
||||
}))
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn get_model_info_tracks_fallback_usage() {
|
||||
let codex_home = tempdir().expect("temp dir");
|
||||
@@ -713,43 +698,6 @@ async fn refresh_available_models_fetches_with_chatgpt_auth_tokens() {
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn refresh_available_models_fetches_with_agent_identity() {
|
||||
let dynamic_slug = "dynamic-model-only-for-test-agent-identity";
|
||||
let codex_home = tempdir().expect("temp dir");
|
||||
let endpoint = TestModelsEndpoint::new(vec![vec![remote_model(
|
||||
dynamic_slug,
|
||||
"Agent Identity",
|
||||
/*priority*/ 1,
|
||||
)]]);
|
||||
let manager = openai_manager_for_tests_with_auth(
|
||||
codex_home.path().to_path_buf(),
|
||||
endpoint.clone(),
|
||||
Some(AuthManager::from_auth_for_testing(
|
||||
agent_identity_auth_for_tests(),
|
||||
)),
|
||||
);
|
||||
|
||||
manager
|
||||
.refresh_available_models(RefreshStrategy::Online)
|
||||
.await
|
||||
.expect("refresh should fetch with agent identity");
|
||||
|
||||
assert!(
|
||||
manager
|
||||
.get_remote_models()
|
||||
.await
|
||||
.iter()
|
||||
.any(|candidate| candidate.slug == dynamic_slug),
|
||||
"remote refresh should include models fetched with agent identity"
|
||||
);
|
||||
assert_eq!(
|
||||
endpoint.fetch_count(),
|
||||
1,
|
||||
"endpoint should fetch models with agent identity"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_available_models_picks_default_after_hiding_hidden_models() {
|
||||
let manager = static_manager_for_tests(ModelsResponse { models: Vec::new() });
|
||||
@@ -768,35 +716,6 @@ fn build_available_models_picks_default_after_hiding_hidden_models() {
|
||||
assert_eq!(available, vec![expected_hidden, expected_visible]);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn static_manager_treats_agent_identity_as_backend_auth_for_filtering() {
|
||||
let chatgpt_only_model = {
|
||||
let mut model = remote_model("chatgpt-only", "ChatGPT Only", /*priority*/ 0);
|
||||
model.supported_in_api = false;
|
||||
model
|
||||
};
|
||||
let api_model = remote_model("api-model", "API Model", /*priority*/ 1);
|
||||
let manager = StaticModelsManager::new(
|
||||
Some(AuthManager::from_auth_for_testing(
|
||||
agent_identity_auth_for_tests(),
|
||||
)),
|
||||
ModelsResponse {
|
||||
models: vec![chatgpt_only_model, api_model],
|
||||
},
|
||||
CollaborationModesConfig::default(),
|
||||
);
|
||||
|
||||
let agent_identity_models = manager.list_models(RefreshStrategy::Online).await;
|
||||
|
||||
assert_eq!(
|
||||
agent_identity_models
|
||||
.iter()
|
||||
.map(|model| model.model.as_str())
|
||||
.collect::<Vec<_>>(),
|
||||
vec!["chatgpt-only", "api-model"]
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn static_manager_reads_latest_auth_mode() {
|
||||
let auth_manager =
|
||||
|
||||
Reference in New Issue
Block a user