Allow configuring GCP project and location in provider settings (#56560)

## Why

Deriving a Vertex AI endpoint previously required environment variables. Allow the project and location to be specified directly in GCP provider configuration.

## What changed

- Add `model_providers.gcp.project_id` and `model_providers.gcp.location`, with each taking precedence over its corresponding environment variable. Keep `global` as the default location and preserve explicit `base_url` overrides.
- Validate configured endpoint fields and preserve them through thread configuration serialization.
- Apply built-in GCP defaults, including default command authentication, when checking managed provider requirements so unchanged requirements are accepted.

## Testing

Add coverage for endpoint precedence, invalid explicit configuration, provider construction, thread configuration round trips, and managed GCP requirement checks, including repeated model listing.

GitOrigin-RevId: c3704bcc0b7d4872374e2cae623fd24d75fb02b4
This commit is contained in:
alexsong-oai
2026-10-23 18:50:54 +00:00
committed by copyberry
parent 7848e3393c
commit 970111f6cb
23 changed files with 315 additions and 51 deletions
+3 -16
View File
@@ -25,6 +25,7 @@ use codex_config::ResidencyRequirement;
use codex_config::SandboxModeRequirement;
use codex_config::Sourced;
use codex_config::ThreadConfigLoader;
use codex_config::apply_default_gcp_auth;
use codex_config::config_toml::CircuitBreakAction;
use codex_config::config_toml::ConfigToml;
use codex_config::config_toml::DEFAULT_PROJECT_DOC_MAX_BYTES;
@@ -101,7 +102,6 @@ use codex_protocol::MemoryVersion;
use codex_protocol::config_types::AltScreenMode;
use codex_protocol::config_types::AutoCompactTokenLimitScope;
use codex_protocol::config_types::ForcedLoginMethod;
use codex_protocol::config_types::ModelProviderAuthInfo;
use codex_protocol::config_types::Personality;
use codex_protocol::config_types::ReasoningSummary;
use codex_protocol::config_types::SERVICE_TIER_DEFAULT_REQUEST_VALUE;
@@ -3995,21 +3995,8 @@ impl Config {
merge_configured_model_providers(built_in_model_providers(openai_base_url), cfg.model_providers)
.map_err(|message| std::io::Error::new(std::io::ErrorKind::InvalidData, message))?;
if let Some(provider) = model_providers.get_mut(GCP_PROVIDER_ID)
&& provider.auth.is_none()
{
// Registry construction must not depend on the process cwd, which may be deleted.
provider.auth = Some(ModelProviderAuthInfo {
command: if cfg!(windows) { "gcloud.cmd" } else { "gcloud" }.to_string(),
args: vec![
"auth".into(),
"application-default".into(),
"print-access-token".into(),
],
timeout_ms: std::num::NonZeroU64::new(30_000).unwrap_or(std::num::NonZeroU64::MIN),
refresh_interval_ms: 3_000_000,
cwd: resolved_cwd.clone(),
});
if let Some(provider) = model_providers.get_mut(GCP_PROVIDER_ID) {
apply_default_gcp_auth(provider, &resolved_cwd);
}
let model_provider_id = config_layer_stack.required_model_provider().map(str::to_string)