diff --git a/apps/desktop-tauri/src/components/MenuCardDetails.tsx b/apps/desktop-tauri/src/components/MenuCardDetails.tsx
index 7cd5ca78f0..5051fb56c4 100644
--- a/apps/desktop-tauri/src/components/MenuCardDetails.tsx
+++ b/apps/desktop-tauri/src/components/MenuCardDetails.tsx
@@ -4,6 +4,7 @@ import type {
DailyCostPoint,
ProviderDisplayDetail,
PaceSnapshot,
+ ProviderInventoryItem,
ProviderChartData,
ProviderLocalUsageSummary,
ProviderUsageSnapshot,
@@ -595,6 +596,14 @@ export default function MenuCardDetails({
)}
+ {!provider.error && hasDisplayDetails && (
+
+ {provider.displayDetails?.map((detail, index) => (
+
+ ))}
+
+ )}
+
{wayfinderUsage && !compactOverview && }
{!compactOverview && hasMetrics && hasCost &&
}
diff --git a/rust/src/cli/diagnose.rs b/rust/src/cli/diagnose.rs
index 10e5ca2c00..2583604bb3 100644
--- a/rust/src/cli/diagnose.rs
+++ b/rust/src/cli/diagnose.rs
@@ -83,6 +83,10 @@ struct ProviderDiagnosticFetchAttempt {
kind: String,
was_available: bool,
error_category: Option,
+ #[serde(skip_serializing_if = "Option::is_none")]
+ strategy_id: Option,
+ #[serde(skip_serializing_if = "Option::is_none")]
+ strategy_outcome: Option,
}
#[derive(Debug, Serialize)]
@@ -199,6 +203,8 @@ async fn collect_provider_diagnostic(
kind: source_mode_name(source_mode).to_string(),
was_available: true,
error_category: None,
+ strategy_id: final_strategy_id(provider_id, Some(&result.source_label)),
+ strategy_outcome: final_strategy_outcome(provider_id, true),
}],
)
}
@@ -215,6 +221,8 @@ async fn collect_provider_diagnostic(
kind: source_mode_name(source_mode).to_string(),
was_available: false,
error_category: Some(category.to_string()),
+ strategy_id: None,
+ strategy_outcome: final_strategy_outcome(provider_id, false),
}],
)
}
@@ -360,6 +368,19 @@ fn cost_present(cost: Option<&CostSnapshot>) -> bool {
cost.is_some()
}
+fn final_strategy_id(provider_id: ProviderId, source_label: Option<&str>) -> Option {
+ (provider_id == ProviderId::Antigravity)
+ .then_some(source_label)
+ .flatten()
+ .and_then(crate::providers::antigravity::strategy_from_source_label)
+ .map(|strategy| strategy.as_str().to_owned())
+}
+
+fn final_strategy_outcome(provider_id: ProviderId, succeeded: bool) -> Option {
+ (provider_id == ProviderId::Antigravity)
+ .then(|| if succeeded { "success" } else { "error" }.to_string())
+}
+
fn source_mode_name(mode: SourceMode) -> &'static str {
match mode {
SourceMode::Auto => "auto",
@@ -413,6 +434,28 @@ mod tests {
assert_eq!(source_mode_name(SourceMode::Cli), "cli");
}
+ #[test]
+ fn antigravity_diagnostics_report_only_the_final_strategy() {
+ assert_eq!(
+ final_strategy_id(ProviderId::Antigravity, Some("cli")),
+ Some("cli".to_string())
+ );
+ assert_eq!(
+ final_strategy_outcome(ProviderId::Antigravity, true),
+ Some("success".to_string())
+ );
+ assert_eq!(
+ final_strategy_outcome(ProviderId::Antigravity, false),
+ Some("error".to_string())
+ );
+ assert_eq!(
+ final_strategy_id(ProviderId::Antigravity, Some("unknown")),
+ None
+ );
+ assert_eq!(final_strategy_id(ProviderId::Grok, Some("cli")), None);
+ assert_eq!(final_strategy_outcome(ProviderId::Grok, true), None);
+ }
+
#[test]
fn diagnostic_usage_summary_does_not_export_identity_values() {
let usage = UsageSnapshot::new(RateWindow::new(42.0))
diff --git a/rust/src/providers/antigravity/cli_fallback.rs b/rust/src/providers/antigravity/cli_fallback.rs
index feef3606eb..ed3572358d 100644
--- a/rust/src/providers/antigravity/cli_fallback.rs
+++ b/rust/src/providers/antigravity/cli_fallback.rs
@@ -169,7 +169,10 @@ async fn fetch_print_usage(binary: &Path) -> Result AsyncCommand {
diff --git a/rust/src/providers/antigravity/mod.rs b/rust/src/providers/antigravity/mod.rs
index 9496275814..5f35764663 100755
--- a/rust/src/providers/antigravity/mod.rs
+++ b/rust/src/providers/antigravity/mod.rs
@@ -69,6 +69,32 @@ pub struct AntigravityProvider {
metadata: ProviderMetadata,
}
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub(crate) enum AntigravityStrategyId {
+ Local,
+ Cli,
+ Offline,
+}
+
+impl AntigravityStrategyId {
+ pub(crate) const fn as_str(self) -> &'static str {
+ match self {
+ Self::Local => "local",
+ Self::Cli => "cli",
+ Self::Offline => "offline",
+ }
+ }
+}
+
+pub(crate) fn strategy_from_source_label(source_label: &str) -> Option {
+ match source_label {
+ "local" => Some(AntigravityStrategyId::Local),
+ "cli" => Some(AntigravityStrategyId::Cli),
+ "offline" => Some(AntigravityStrategyId::Offline),
+ _ => None,
+ }
+}
+
/// Return a regex that matches `-- ` or `--=`.
fn flag_re(flag: &str) -> Regex {
Regex::new(&format!("--{f}(?:\\s+|\\s*=\\s*)(\\S+)", f = flag)).expect("valid flag pattern")
@@ -411,7 +437,7 @@ impl AntigravityProvider {
{
legacy_status::apply_user_identity(&mut snapshot, &identity);
}
- return Ok(Self::fetch_result(snapshot, "local"));
+ return Ok(Self::fetch_result(snapshot, AntigravityStrategyId::Local));
}
Err(error) => tracing::debug!(
%error,
@@ -444,11 +470,14 @@ impl AntigravityProvider {
let response: UserStatusResponse = serde_json::from_slice(&bytes)
.map_err(|e| ProviderError::Parse(format!("Failed to parse response: {e}")))?;
self.parse_user_status(response)
- .map(|usage| Self::fetch_result(usage, "local"))
+ .map(|usage| Self::fetch_result(usage, AntigravityStrategyId::Local))
}
- pub(super) fn fetch_result(usage: UsageSnapshot, source_label: &str) -> ProviderFetchResult {
- ProviderFetchResult::new(Self::with_cadence_labels(usage), source_label)
+ pub(super) fn fetch_result(
+ usage: UsageSnapshot,
+ strategy: AntigravityStrategyId,
+ ) -> ProviderFetchResult {
+ ProviderFetchResult::new(Self::with_cadence_labels(usage), strategy.as_str())
}
async fn try_print_usage_fallback(&self) -> Result