mirror of
https://github.com/openai/codex.git
synced 2026-11-13 14:46:14 +00:00
Scope model catalog caches to the current provider and auth identity (#43906)
## Why Switching providers or authentication could reuse a previous identity's model catalog, including its default service tier. An in-flight refresh could also overwrite a newer account's catalog after cache storage completed. ## What changed - Require a matching provider and auth identity for disk and in-memory catalog reuse. Treat legacy entries without an identity as cache misses and fall back to bundled metadata when the in-memory identity no longer matches. - Recheck identity after fetching and storing a catalog before publishing it. - Renew cache freshness only when the client version, identity, and ETag match the stored entry. - Update cache fixtures to include the configured provider and auth identity. ## Testing Add regression coverage for provider and auth switches, credential rotation, legacy and mismatched cache entries, conditional TTL renewal, and an account switch during cache storage. Verify that API-key requests do not inherit a ChatGPT catalog's default `service_tier`, while explicit tier selection still works. GitOrigin-RevId: e15d7ffff238d951d7a1c6a68381cbb479994146
This commit is contained in:
1 parent
4fd2c460dd
commit
f046cf35df
35 files changed
+733
-143
No files matched your search
@@ -97,7 +97,7 @@ supports_websockets = false
|
||||
"#
|
||||
))
|
||||
.write(codex_home.path())?;
|
||||
write_models_cache(codex_home.path())?;
|
||||
write_models_cache(codex_home.path()).await?;
|
||||
let mut app_server = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.with_env_overrides(&[("OPENAI_API_KEY", None)])
|
||||
|
||||
@@ -416,7 +416,7 @@ async fn set_auth_token_updates_account_and_notifies() -> Result<()> {
|
||||
..Default::default()
|
||||
},
|
||||
)?;
|
||||
write_models_cache(codex_home.path())?;
|
||||
write_models_cache(codex_home.path()).await?;
|
||||
|
||||
let access_token = encode_id_token(
|
||||
&ChatGptIdTokenClaims::new()
|
||||
@@ -499,7 +499,7 @@ async fn account_read_refresh_token_is_noop_in_external_mode() -> Result<()> {
|
||||
..Default::default()
|
||||
},
|
||||
)?;
|
||||
write_models_cache(codex_home.path())?;
|
||||
write_models_cache(codex_home.path()).await?;
|
||||
|
||||
let access_token = encode_id_token(
|
||||
&ChatGptIdTokenClaims::new()
|
||||
@@ -611,7 +611,7 @@ async fn external_auth_refreshes_on_unauthorized() -> Result<()> {
|
||||
..Default::default()
|
||||
},
|
||||
)?;
|
||||
write_models_cache(codex_home.path())?;
|
||||
write_models_cache(codex_home.path()).await?;
|
||||
|
||||
let success_sse = responses::sse(vec![
|
||||
responses::ev_response_created("resp-turn"),
|
||||
@@ -726,7 +726,7 @@ async fn external_auth_refresh_error_fails_turn() -> Result<()> {
|
||||
..Default::default()
|
||||
},
|
||||
)?;
|
||||
write_models_cache(codex_home.path())?;
|
||||
write_models_cache(codex_home.path()).await?;
|
||||
|
||||
let unauthorized = ResponseTemplate::new(401).set_body_json(json!({
|
||||
"error": { "message": "unauthorized" }
|
||||
@@ -837,7 +837,7 @@ async fn external_auth_refresh_mismatched_workspace_fails_turn() -> Result<()> {
|
||||
..Default::default()
|
||||
},
|
||||
)?;
|
||||
write_models_cache(codex_home.path())?;
|
||||
write_models_cache(codex_home.path()).await?;
|
||||
|
||||
let unauthorized = ResponseTemplate::new(401).set_body_json(json!({
|
||||
"error": { "message": "unauthorized" }
|
||||
@@ -953,7 +953,7 @@ async fn external_auth_refresh_invalid_access_token_fails_turn() -> Result<()> {
|
||||
..Default::default()
|
||||
},
|
||||
)?;
|
||||
write_models_cache(codex_home.path())?;
|
||||
write_models_cache(codex_home.path()).await?;
|
||||
|
||||
let unauthorized = ResponseTemplate::new(401).set_body_json(json!({
|
||||
"error": { "message": "unauthorized" }
|
||||
@@ -2003,7 +2003,7 @@ async fn login_account_chatgpt_device_code_returns_error_when_disabled() -> Resu
|
||||
..Default::default()
|
||||
},
|
||||
)?;
|
||||
write_models_cache(codex_home.path())?;
|
||||
write_models_cache(codex_home.path()).await?;
|
||||
mock_device_code_usercode_failure(&mock_server, /*status*/ 404).await;
|
||||
|
||||
let issuer = mock_server.uri();
|
||||
@@ -2059,7 +2059,7 @@ async fn login_account_chatgpt_device_code_succeeds_and_notifies() -> Result<()>
|
||||
..Default::default()
|
||||
},
|
||||
)?;
|
||||
write_models_cache(codex_home.path())?;
|
||||
write_models_cache(codex_home.path()).await?;
|
||||
|
||||
mock_device_code_usercode(&mock_server, /*interval_seconds*/ 0).await;
|
||||
mock_device_code_token_success(&mock_server).await;
|
||||
@@ -2139,7 +2139,7 @@ async fn login_account_chatgpt_device_code_failure_notifies_without_account_upda
|
||||
..Default::default()
|
||||
},
|
||||
)?;
|
||||
write_models_cache(codex_home.path())?;
|
||||
write_models_cache(codex_home.path()).await?;
|
||||
|
||||
mock_device_code_usercode(&mock_server, /*interval_seconds*/ 0).await;
|
||||
mock_device_code_token_failure(&mock_server, /*status*/ 500).await;
|
||||
@@ -2210,7 +2210,7 @@ async fn login_account_chatgpt_device_code_can_be_cancelled() -> Result<()> {
|
||||
..Default::default()
|
||||
},
|
||||
)?;
|
||||
write_models_cache(codex_home.path())?;
|
||||
write_models_cache(codex_home.path()).await?;
|
||||
|
||||
mock_device_code_usercode(&mock_server, /*interval_seconds*/ 1).await;
|
||||
mock_device_code_token_failure(&mock_server, /*status*/ 404).await;
|
||||
|
||||
@@ -56,7 +56,6 @@ async fn attestation_generate_round_trip_adds_header_to_responses_websocket_hand
|
||||
.await;
|
||||
|
||||
let codex_home = TempDir::new()?;
|
||||
write_models_cache(codex_home.path())?;
|
||||
create_chatgpt_websocket_config(
|
||||
codex_home.path(),
|
||||
&websocket_server.uri().replacen("ws://", "http://", 1),
|
||||
@@ -66,6 +65,7 @@ async fn attestation_generate_round_trip_adds_header_to_responses_websocket_hand
|
||||
ChatGptAuthFixture::new("access-chatgpt").plan_type("pro"),
|
||||
AuthCredentialsStoreMode::File,
|
||||
)?;
|
||||
write_models_cache(codex_home.path()).await?;
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
|
||||
@@ -601,7 +601,7 @@ async fn start_function_dynamic_tool_call(call_id: &str) -> Result<PendingDynami
|
||||
let mut model_info =
|
||||
codex_core::test_support::construct_model_info_offline("mock-model", &config);
|
||||
model_info.input_modalities.push(InputModality::Audio);
|
||||
write_models_cache_with_models(codex_home.path(), vec![model_info])?;
|
||||
write_models_cache_with_models(codex_home.path(), vec![model_info]).await?;
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
|
||||
@@ -127,7 +127,7 @@ async fn model_guardian_policy_scores_code_mode_cells(
|
||||
shell: Some(GuardianReviewMode::Adaptive),
|
||||
..Default::default()
|
||||
});
|
||||
write_models_cache_with_models(codex_home.path(), vec![model])?;
|
||||
write_models_cache_with_models(codex_home.path(), vec![model]).await?;
|
||||
let mut app_server = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.build_initialized_with_timeout(TIMEOUT)
|
||||
|
||||
@@ -76,7 +76,7 @@ async fn model_guardian_policy_controls_cua(
|
||||
computer_use: Some(computer_use),
|
||||
..Default::default()
|
||||
});
|
||||
write_models_cache_with_models(codex_home.path(), vec![model])?;
|
||||
write_models_cache_with_models(codex_home.path(), vec![model]).await?;
|
||||
let mut app_server = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.build_initialized_with_timeout(TIMEOUT)
|
||||
|
||||
@@ -284,7 +284,7 @@ async fn inline_review_delegate_runs_strict_guardian_assessment() -> Result<()>
|
||||
let mut model = codex_core::test_support::construct_model_info_offline(MODEL, &config);
|
||||
// Strict MCP approvals must work under the inline delegate's `never` policy.
|
||||
model.node_repl_auto_review_required = true;
|
||||
write_models_cache_with_models(codex_home.path(), vec![model])?;
|
||||
write_models_cache_with_models(codex_home.path(), vec![model]).await?;
|
||||
let mut app = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.build_initialized_with_timeout(TIMEOUT)
|
||||
|
||||
@@ -131,7 +131,7 @@ async fn resumed_thread_does_not_wait_for_guardian_websocket_warmup() -> Result<
|
||||
let config = load_default_config_for_test(&codex_home).await;
|
||||
let mut model = codex_core::test_support::construct_model_info_offline(MODEL, &config);
|
||||
model.node_repl_auto_review_required = true;
|
||||
write_models_cache_with_models(codex_home.path(), vec![model])?;
|
||||
write_models_cache_with_models(codex_home.path(), vec![model]).await?;
|
||||
let thread_id = create_fake_rollout(
|
||||
codex_home.path(),
|
||||
"2025-01-05T12-00-00",
|
||||
@@ -833,7 +833,7 @@ async fn guardian_v2_routes_scoped_tool_approvals(
|
||||
let config = load_default_config_for_test(&codex_home).await;
|
||||
let mut model_info = codex_core::test_support::construct_model_info_offline(MODEL, &config);
|
||||
model_info.node_repl_auto_review_required = true;
|
||||
write_models_cache_with_models(codex_home.path(), vec![model_info])?;
|
||||
write_models_cache_with_models(codex_home.path(), vec![model_info]).await?;
|
||||
}
|
||||
let original_thread_id = match lifecycle {
|
||||
ThreadLifecycle::New
|
||||
@@ -2042,7 +2042,7 @@ async fn first_cua_review_does_not_wait_for_initial_score(
|
||||
let config = load_default_config_for_test(&codex_home).await;
|
||||
let mut model_info = codex_core::test_support::construct_model_info_offline(MODEL, &config);
|
||||
model_info.node_repl_auto_review_required = true;
|
||||
write_models_cache_with_models(codex_home.path(), vec![model_info])?;
|
||||
write_models_cache_with_models(codex_home.path(), vec![model_info]).await?;
|
||||
let mut app_server = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.build_initialized_with_timeout(TIMEOUT)
|
||||
@@ -2128,7 +2128,7 @@ async fn user_approval_skips_async_guardian_without_changing_other_modes() -> Re
|
||||
let config = load_default_config_for_test(&codex_home).await;
|
||||
let mut model_info = codex_core::test_support::construct_model_info_offline(MODEL, &config);
|
||||
model_info.node_repl_auto_review_required = true;
|
||||
write_models_cache_with_models(codex_home.path(), vec![model_info])?;
|
||||
write_models_cache_with_models(codex_home.path(), vec![model_info]).await?;
|
||||
let mut app_server = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.build_initialized_with_timeout(TIMEOUT)
|
||||
|
||||
@@ -314,12 +314,12 @@ async fn guardians_retain_evidence_after_compaction_and_discard_it_after_rollbac
|
||||
info
|
||||
})
|
||||
.collect();
|
||||
write_models_cache_with_models(codex_home.path(), models)?;
|
||||
write_chatgpt_auth(
|
||||
codex_home.path(),
|
||||
ChatGptAuthFixture::new("access-chatgpt").plan_type("pro"),
|
||||
AuthCredentialsStoreMode::File,
|
||||
)?;
|
||||
write_models_cache_with_models(codex_home.path(), models).await?;
|
||||
let mut app_server = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.with_env_overrides(&[("OPENAI_API_KEY", None)])
|
||||
|
||||
@@ -77,7 +77,7 @@ async fn computer_use_scoring_follows_model_review_requirement(
|
||||
let mut reviewed_model =
|
||||
codex_core::test_support::construct_model_info_offline(REVIEWED_MODEL, &config);
|
||||
reviewed_model.node_repl_auto_review_required = true;
|
||||
write_models_cache_with_models(codex_home.path(), vec![ordinary_model, reviewed_model])?;
|
||||
write_models_cache_with_models(codex_home.path(), vec![ordinary_model, reviewed_model]).await?;
|
||||
let mut app_server = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.build_initialized_with_timeout(TIMEOUT)
|
||||
|
||||
@@ -60,7 +60,7 @@ fn model_from_preset(preset: &ModelPreset) -> Model {
|
||||
.collect(),
|
||||
default_reasoning_effort: preset.default_reasoning_effort.clone(),
|
||||
input_modalities: preset.input_modalities.clone(),
|
||||
// `write_models_cache()` round-trips through a simplified ModelInfo fixture that does not
|
||||
// `write_models_cache().await` round-trips through a simplified ModelInfo fixture that does not
|
||||
// preserve personality placeholders in base instructions, so app-server list results from
|
||||
// cache report `supports_personality = false`.
|
||||
// todo(sayan): fix, maybe make roundtrip use ModelInfo only
|
||||
@@ -101,7 +101,7 @@ fn expected_visible_models() -> Vec<Model> {
|
||||
#[tokio::test]
|
||||
async fn list_models_returns_all_models_with_large_limit() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
write_models_cache(codex_home.path())?;
|
||||
write_models_cache(codex_home.path()).await?;
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
@@ -131,7 +131,7 @@ async fn list_models_returns_all_models_with_large_limit() -> Result<()> {
|
||||
#[tokio::test]
|
||||
async fn list_models_includes_hidden_models() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
write_models_cache(codex_home.path())?;
|
||||
write_models_cache(codex_home.path()).await?;
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
@@ -286,7 +286,7 @@ openai_base_url = "{server_uri}/v1"
|
||||
#[tokio::test]
|
||||
async fn list_models_pagination_works() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
write_models_cache(codex_home.path())?;
|
||||
write_models_cache(codex_home.path()).await?;
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
@@ -332,7 +332,7 @@ async fn list_models_pagination_works() -> Result<()> {
|
||||
#[tokio::test]
|
||||
async fn list_models_rejects_invalid_cursor() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
write_models_cache(codex_home.path())?;
|
||||
write_models_cache(codex_home.path()).await?;
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
|
||||
@@ -198,7 +198,7 @@ async fn spawned_subagents_apply_configured_developer_instruction_precedence(
|
||||
config
|
||||
.with_extra_config(&feature_config)
|
||||
.write(codex_home.path())?;
|
||||
write_models_cache(codex_home.path())?;
|
||||
write_models_cache(codex_home.path()).await?;
|
||||
let mut app_server = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.build_initialized()
|
||||
@@ -379,7 +379,7 @@ async fn compacted_full_history_fork_replaces_parent_developer_instructions() ->
|
||||
"[features.multi_agent_v2]\nenabled = true\nsubagent_developer_instructions = {CHILD_INSTRUCTIONS:?}"
|
||||
))
|
||||
.write(codex_home.path())?;
|
||||
write_models_cache(codex_home.path())?;
|
||||
write_models_cache(codex_home.path()).await?;
|
||||
|
||||
let mut app_server = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
@@ -641,7 +641,7 @@ async fn cold_resume_preserves_effective_developer_instructions_for_worker(
|
||||
))
|
||||
.with_extra_config(&feature_config)
|
||||
.write(codex_home.path())?;
|
||||
write_models_cache(codex_home.path())?;
|
||||
write_models_cache(codex_home.path()).await?;
|
||||
|
||||
let (thread_id, child_resume_params, baseline) = {
|
||||
let mut app_server = TestAppServer::builder()
|
||||
|
||||
@@ -48,7 +48,7 @@ async fn account_switch_reloads_telemetry_collectors_and_preserves_trace_context
|
||||
.email(INITIAL_EMAIL),
|
||||
AuthCredentialsStoreMode::File,
|
||||
)?;
|
||||
write_models_cache(codex_home.path())?;
|
||||
write_models_cache(codex_home.path()).await?;
|
||||
|
||||
let mut app_server = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
|
||||
@@ -27,7 +27,7 @@ enum ModelTransport {
|
||||
Websocket,
|
||||
}
|
||||
|
||||
fn write_provider_config(
|
||||
async fn write_provider_config(
|
||||
codex_home: &Path,
|
||||
model_base_url: &str,
|
||||
transport: ModelTransport,
|
||||
@@ -60,7 +60,7 @@ supports_websockets = {supports_websockets}
|
||||
"#
|
||||
);
|
||||
std::fs::write(codex_home.join("config.toml"), config)?;
|
||||
write_models_cache(codex_home)?;
|
||||
write_models_cache(codex_home).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ async fn managed_residency_overrides_provider_headers(transport: ModelTransport)
|
||||
};
|
||||
|
||||
let codex_home = TempDir::new()?;
|
||||
write_provider_config(codex_home.path(), &model_base_url, transport)?;
|
||||
write_provider_config(codex_home.path(), &model_base_url, transport).await?;
|
||||
std::fs::write(
|
||||
codex_home.path().join("requirements.toml"),
|
||||
"enforce_residency = \"us\"\n",
|
||||
|
||||
@@ -47,7 +47,7 @@ async fn fork_before_first_turn_preserves_model_selected_multi_agent_version(
|
||||
let config = load_default_config_for_test(&codex_home).await;
|
||||
let mut model = codex_core::test_support::construct_model_info_offline("mock-model", &config);
|
||||
model.multi_agent_version = Some(MultiAgentVersion::V2);
|
||||
write_models_cache_with_models(codex_home.path(), vec![model])?;
|
||||
write_models_cache_with_models(codex_home.path(), vec![model]).await?;
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.build_initialized()
|
||||
|
||||
@@ -63,7 +63,7 @@ async fn thread_revert_preserves_model_selected_multi_agent_version(restart: boo
|
||||
let config = load_default_config_for_test(&codex_home).await;
|
||||
let mut model = codex_core::test_support::construct_model_info_offline("mock-model", &config);
|
||||
model.multi_agent_version = Some(MultiAgentVersion::V2);
|
||||
write_models_cache_with_models(codex_home.path(), vec![model])?;
|
||||
write_models_cache_with_models(codex_home.path(), vec![model]).await?;
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.build()
|
||||
|
||||
@@ -47,7 +47,7 @@ async fn thread_settings_update_emits_notification_and_updates_future_turns() ->
|
||||
.await;
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
write_models_cache(codex_home.path())?;
|
||||
write_models_cache(codex_home.path()).await?;
|
||||
let (model_id, service_tier_id) = service_tier_model_and_tier_id()?;
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
@@ -289,7 +289,7 @@ async fn thread_settings_update_null_service_tier_uses_default() -> Result<()> {
|
||||
.await;
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
write_models_cache(codex_home.path())?;
|
||||
write_models_cache(codex_home.path()).await?;
|
||||
let (model_id, service_tier_id) = service_tier_model_and_tier_id()?;
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
|
||||
@@ -113,7 +113,7 @@ metrics_exporter = {{ otlp-http = {{ endpoint = "{}/metrics", protocol = "json"
|
||||
.chatgpt_user_id("user-a"),
|
||||
AuthCredentialsStoreMode::File,
|
||||
)?;
|
||||
write_models_cache(home.path())?;
|
||||
write_models_cache(home.path()).await?;
|
||||
let loader_overrides = LoaderOverrides::without_managed_config_for_tests();
|
||||
let config = Arc::new(
|
||||
ConfigBuilder::default()
|
||||
|
||||
@@ -777,7 +777,7 @@ async fn turn_start_emits_thread_scoped_warning_notification_for_trimmed_skills(
|
||||
MockResponsesConfig::new(&server.uri())
|
||||
.enable_feature(Feature::Personality)
|
||||
.write(codex_home.path())?;
|
||||
write_models_cache(codex_home.path())?;
|
||||
write_models_cache(codex_home.path()).await?;
|
||||
let cache_path = codex_home.path().join("models_cache.json");
|
||||
let mut cache: serde_json::Value =
|
||||
serde_json::from_str(&std::fs::read_to_string(&cache_path)?)?;
|
||||
@@ -874,7 +874,7 @@ async fn turn_start_sends_service_tier_id_to_model_request() -> Result<()> {
|
||||
|
||||
let codex_home = TempDir::new()?;
|
||||
MockResponsesConfig::new(&server.uri()).write(codex_home.path())?;
|
||||
write_models_cache(codex_home.path())?;
|
||||
write_models_cache(codex_home.path()).await?;
|
||||
let service_tier_model = all_model_presets()
|
||||
.iter()
|
||||
.find(|preset| preset.show_in_picker && !preset.service_tiers.is_empty())
|
||||
@@ -998,7 +998,7 @@ async fn turn_start_emits_raw_response_completed_with_upstream_usage(
|
||||
|
||||
let codex_home = TempDir::new()?;
|
||||
MockResponsesConfig::new(&server.uri()).write(codex_home.path())?;
|
||||
write_models_cache(codex_home.path())?;
|
||||
write_models_cache(codex_home.path()).await?;
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
@@ -3978,7 +3978,7 @@ async fn turn_start_streams_apply_patch_change_updates_v2() -> Result<()> {
|
||||
.disable_feature(Feature::RemoteModels)
|
||||
.disable_feature(Feature::ShellSnapshot)
|
||||
.write(&codex_home)?;
|
||||
write_models_cache(&codex_home)?;
|
||||
write_models_cache(&codex_home).await?;
|
||||
let cache_path = codex_home.join("models_cache.json");
|
||||
let mut cache: serde_json::Value =
|
||||
serde_json::from_str(&std::fs::read_to_string(&cache_path)?)?;
|
||||
@@ -4368,7 +4368,7 @@ async fn direct_input_to_multi_agent_v2_subagent_is_rejected(
|
||||
.enable_feature(Feature::Goals)
|
||||
.with_root_config(&format!("chatgpt_base_url = \"{}\"", server.uri()))
|
||||
.write(codex_home.path())?;
|
||||
write_models_cache(codex_home.path())?;
|
||||
write_models_cache(codex_home.path()).await?;
|
||||
mount_analytics_capture(&server, codex_home.path()).await?;
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
|
||||
@@ -50,7 +50,7 @@ async fn fresh_context_subagent_inherits_disabled_view_image_and_mcp_tools() ->
|
||||
"[mcp_servers.{TEST_SERVER_NAME}]\nurl = \"{mcp_server_url}/mcp\"\n\n[features.multi_agent_v2]\nenabled = true"
|
||||
))
|
||||
.write(codex_home.path())?;
|
||||
write_models_cache(codex_home.path())?;
|
||||
write_models_cache(codex_home.path()).await?;
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
|
||||
Reference in new issue
Block a user