Skip to content

Commit cf92d18

Browse files
committed
polish antigravity direct provider
1 parent bd092cf commit cf92d18

8 files changed

Lines changed: 52 additions & 31 deletions

File tree

src/auth/antigravity.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,12 @@ mod tests {
616616
);
617617
}
618618

619+
#[test]
620+
fn client_metadata_uses_backend_accepted_platform() {
621+
assert_eq!(metadata_platform(), "PLATFORM_UNSPECIFIED");
622+
assert!(client_metadata_header().contains("\"platform\":\"PLATFORM_UNSPECIFIED\""));
623+
}
624+
619625
#[test]
620626
fn extract_project_id_supports_string_or_object() {
621627
assert_eq!(

src/cli/provider_init.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1041,7 +1041,7 @@ pub async fn login_and_bootstrap_provider(
10411041
disable_subscription_runtime_mode();
10421042
unlock_model_provider();
10431043
crate::env::set_var("JCODE_ACTIVE_PROVIDER", "antigravity");
1044-
Arc::new(provider::antigravity::AntigravityCliProvider::new())
1044+
Arc::new(provider::antigravity::AntigravityProvider::new())
10451045
}
10461046
LoginProviderTarget::Google => {
10471047
anyhow::bail!("Google login cannot be used as a model provider bootstrap");
@@ -1263,10 +1263,10 @@ async fn init_provider_with_options(
12631263
ProviderChoice::Antigravity => {
12641264
disable_subscription_runtime_mode();
12651265
ensure_antigravity_auth_allowed_for_explicit_choice()?;
1266-
init_notice("Using Antigravity CLI provider (experimental)");
1266+
init_notice("Using Antigravity provider (experimental)");
12671267
unlock_model_provider();
12681268
crate::env::set_var("JCODE_ACTIVE_PROVIDER", "antigravity");
1269-
Arc::new(provider::antigravity::AntigravityCliProvider::new())
1269+
Arc::new(provider::antigravity::AntigravityProvider::new())
12701270
}
12711271
ProviderChoice::Google => {
12721272
disable_subscription_runtime_mode();

src/provider/accessors.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ impl MultiProvider {
2222
.clone()
2323
}
2424

25-
pub(super) fn antigravity_provider(&self) -> Option<Arc<antigravity::AntigravityCliProvider>> {
25+
pub(super) fn antigravity_provider(&self) -> Option<Arc<antigravity::AntigravityProvider>> {
2626
self.antigravity
2727
.read()
2828
.unwrap_or_else(|poisoned| poisoned.into_inner())

src/provider/antigravity.rs

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -351,13 +351,13 @@ fn catalog_is_stale(fetched_at_rfc3339: &str) -> bool {
351351
>= CATALOG_REFRESH_TTL_HOURS
352352
}
353353

354-
pub struct AntigravityCliProvider {
354+
pub struct AntigravityProvider {
355355
client: reqwest::Client,
356356
model: Arc<RwLock<String>>,
357357
fetched_catalog: Arc<RwLock<Vec<CatalogModel>>>,
358358
}
359359

360-
impl Clone for AntigravityCliProvider {
360+
impl Clone for AntigravityProvider {
361361
fn clone(&self) -> Self {
362362
Self {
363363
client: self.client.clone(),
@@ -367,7 +367,7 @@ impl Clone for AntigravityCliProvider {
367367
}
368368
}
369369

370-
impl AntigravityCliProvider {
370+
impl AntigravityProvider {
371371
fn persisted_catalog_path() -> Result<std::path::PathBuf> {
372372
Ok(crate::storage::app_config_dir()?.join("antigravity_models_cache.json"))
373373
}
@@ -486,18 +486,13 @@ impl AntigravityCliProvider {
486486
async fn fetch_available_models(&self) -> Result<Vec<CatalogModel>> {
487487
let mut tokens = antigravity_auth::load_or_refresh_tokens().await?;
488488

489-
if let Ok(models) = self
490-
.fetch_available_models_with_project(&tokens.access_token, None)
491-
.await
492-
&& !models.is_empty()
493-
{
494-
return Ok(models);
495-
}
496-
497-
if let Some(project_id) = tokens.project_id.clone()
498-
&& !project_id.trim().is_empty()
489+
if let Some(project_id) = tokens
490+
.project_id
491+
.as_deref()
492+
.map(str::trim)
493+
.filter(|value| !value.is_empty())
499494
&& let Ok(models) = self
500-
.fetch_available_models_with_project(&tokens.access_token, Some(&project_id))
495+
.fetch_available_models_with_project(&tokens.access_token, Some(project_id))
501496
.await
502497
&& !models.is_empty()
503498
{
@@ -507,9 +502,13 @@ impl AntigravityCliProvider {
507502
if let Ok(project_id) = antigravity_auth::fetch_project_id(&tokens.access_token).await {
508503
tokens.project_id = Some(project_id.clone());
509504
let _ = antigravity_auth::save_tokens(&tokens);
510-
return self
505+
if let Ok(models) = self
511506
.fetch_available_models_with_project(&tokens.access_token, Some(&project_id))
512-
.await;
507+
.await
508+
&& !models.is_empty()
509+
{
510+
return Ok(models);
511+
}
513512
}
514513

515514
self.fetch_available_models_with_project(&tokens.access_token, None)
@@ -593,14 +592,14 @@ impl AntigravityCliProvider {
593592
}
594593
}
595594

596-
impl Default for AntigravityCliProvider {
595+
impl Default for AntigravityProvider {
597596
fn default() -> Self {
598597
Self::new()
599598
}
600599
}
601600

602601
#[async_trait]
603-
impl Provider for AntigravityCliProvider {
602+
impl Provider for AntigravityProvider {
604603
async fn complete(
605604
&self,
606605
messages: &[Message],

src/provider/antigravity_tests.rs

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ fn parse_fetch_available_models_response_discovers_metadata_and_priority_order()
1818
"displayName": "Gemini 3.1 Pro (High)",
1919
"quotaInfo": { "remainingFraction": 0.25 }
2020
},
21+
"gemini-3-flash": {
22+
"displayName": "Gemini 3 Flash",
23+
"quotaInfo": { "remainingFraction": 0, "resetTime": "2026-04-24T21:53:26Z" }
24+
},
2125
"gpt-oss-120b-medium": {}
2226
}
2327
}))
@@ -32,11 +36,23 @@ fn parse_fetch_available_models_response_discovers_metadata_and_priority_order()
3236
Some("Claude Opus 4.6 (Thinking)")
3337
);
3438
assert_eq!(parsed[1].remaining_fraction_milli, Some(250));
39+
let flash = parsed
40+
.iter()
41+
.find(|model| model.id == "gemini-3-flash")
42+
.expect("gemini flash model");
43+
assert!(!flash.available);
44+
assert_eq!(flash.remaining_fraction_milli, Some(0));
45+
}
46+
47+
#[test]
48+
fn client_metadata_uses_backend_accepted_platform() {
49+
assert_eq!(metadata_platform(), "PLATFORM_UNSPECIFIED");
50+
assert!(client_metadata_header().contains("\"platform\":\"PLATFORM_UNSPECIFIED\""));
3551
}
3652

3753
#[test]
3854
fn available_models_display_includes_dynamic_cache_and_current_override() {
39-
let provider = AntigravityCliProvider::new();
55+
let provider = AntigravityProvider::new();
4056
*provider.fetched_catalog.write().expect("catalog lock") = vec![
4157
CatalogModel {
4258
id: "claude-opus-4-6-thinking".to_string(),
@@ -81,7 +97,7 @@ fn available_models_display_seeds_from_persisted_catalog() {
8197
let previous = std::env::var_os("JCODE_HOME");
8298
crate::env::set_var("JCODE_HOME", temp.path());
8399

84-
let path = AntigravityCliProvider::persisted_catalog_path().expect("catalog path");
100+
let path = AntigravityProvider::persisted_catalog_path().expect("catalog path");
85101
crate::storage::write_json(
86102
&path,
87103
&PersistedCatalog {
@@ -102,7 +118,7 @@ fn available_models_display_seeds_from_persisted_catalog() {
102118
)
103119
.expect("write persisted catalog");
104120

105-
let provider = AntigravityCliProvider::new();
121+
let provider = AntigravityProvider::new();
106122
assert!(
107123
provider
108124
.available_models_display()
@@ -143,7 +159,7 @@ fn catalog_stale_handles_invalid_timestamp() {
143159

144160
#[tokio::test]
145161
async fn complete_uses_native_https_transport_not_cli_subprocess() {
146-
let provider = AntigravityCliProvider::new();
162+
let provider = AntigravityProvider::new();
147163
let mut stream = provider
148164
.complete(&[], &[], "say hello", None)
149165
.await

src/provider/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -580,8 +580,8 @@ pub struct MultiProvider {
580580
openai: RwLock<Option<Arc<openai::OpenAIProvider>>>,
581581
/// GitHub Copilot API provider (direct API, hot-swappable after login)
582582
copilot_api: RwLock<Option<Arc<copilot::CopilotApiProvider>>>,
583-
/// Antigravity provider (CLI-backed, hot-swappable after login)
584-
antigravity: RwLock<Option<Arc<antigravity::AntigravityCliProvider>>>,
583+
/// Antigravity provider (direct HTTPS, hot-swappable after login)
584+
antigravity: RwLock<Option<Arc<antigravity::AntigravityProvider>>>,
585585
/// Gemini provider (hot-swappable after login)
586586
gemini: RwLock<Option<Arc<gemini::GeminiProvider>>>,
587587
/// Cursor provider (native/direct API, hot-swappable after login)
@@ -1746,7 +1746,7 @@ impl Provider for MultiProvider {
17461746
.antigravity
17471747
.write()
17481748
.unwrap_or_else(|poisoned| poisoned.into_inner()) =
1749-
Some(Arc::new(antigravity::AntigravityCliProvider::new()));
1749+
Some(Arc::new(antigravity::AntigravityProvider::new()));
17501750
}
17511751

17521752
let already_has_gemini = self.gemini_provider().is_some();

src/provider/startup.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ impl MultiProvider {
149149
};
150150

151151
let antigravity_provider = if has_antigravity_creds {
152-
Some(Arc::new(antigravity::AntigravityCliProvider::new()))
152+
Some(Arc::new(antigravity::AntigravityProvider::new()))
153153
} else {
154154
None
155155
};

src/provider/tests/auth_refresh.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,7 @@ fn test_multi_provider_antigravity_routes_do_not_include_legacy_duplicate_entrie
401401
anthropic: RwLock::new(None),
402402
openai: RwLock::new(None),
403403
copilot_api: RwLock::new(None),
404-
antigravity: RwLock::new(Some(Arc::new(antigravity::AntigravityCliProvider::new()))),
404+
antigravity: RwLock::new(Some(Arc::new(antigravity::AntigravityProvider::new()))),
405405
gemini: RwLock::new(None),
406406
cursor: RwLock::new(None),
407407
openrouter: RwLock::new(None),

0 commit comments

Comments
 (0)