@omnicross/daemon 0.4.2 → 0.4.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -63,21 +63,23 @@ var import_node_path35 = require("path");
63
63
  var import_audit_types = require("@omnicross/contracts/audit-types");
64
64
  var import_billing_types = require("@omnicross/contracts/billing-types");
65
65
  var import_core7 = require("@omnicross/core");
66
- var import_GeminiCodeAssistProjectResolver2 = require("@omnicross/core/auth/GeminiCodeAssistProjectResolver");
66
+ var import_GeminiCodeAssistProjectResolver6 = require("@omnicross/core/auth/GeminiCodeAssistProjectResolver");
67
67
  var import_ApiKeyPoolService = require("@omnicross/core/completion/ApiKeyPoolService");
68
68
  var import_outbound_api10 = require("@omnicross/core/outbound-api");
69
69
  var import_subscriptionRegistryPort = require("@omnicross/core/outbound-api/subscriptionRegistryPort");
70
70
  var import_SubscriptionAccountHealth4 = require("@omnicross/core/pipeline/SubscriptionAccountHealth");
71
- var import_AccountAllowanceStore10 = require("@omnicross/core/pipeline/AccountAllowanceStore");
71
+ var import_AccountAllowanceStore11 = require("@omnicross/core/pipeline/AccountAllowanceStore");
72
72
  var import_AccountAllowanceScheduling5 = require("@omnicross/core/pipeline/AccountAllowanceScheduling");
73
- var import_upstreamFetch16 = require("@omnicross/core/pipeline/upstreamFetch");
73
+ var import_upstreamFetch18 = require("@omnicross/core/pipeline/upstreamFetch");
74
74
  var import_SubscriptionIdentityStore3 = require("@omnicross/core/provider-proxy/identity/SubscriptionIdentityStore");
75
75
  var import_gemini_code_assist_resolver = require("@omnicross/core/ports/gemini-code-assist-resolver");
76
+ var import_antigravityFailover = require("@omnicross/core/transformer/transformers/antigravityFailover");
77
+ var import_openCodeGoHeaders2 = require("@omnicross/core/provider-proxy/identity/openCodeGoHeaders");
76
78
  var import_provider_proxy4 = require("@omnicross/core/provider-proxy");
77
79
  var import_cli_launcher2 = require("@omnicross/cli-launcher");
78
80
  var import_outbound_api11 = require("@omnicross/core/outbound-api");
79
81
  var import_usage2 = require("@omnicross/core/usage");
80
- var import_subscriptions12 = require("@omnicross/subscriptions");
82
+ var import_subscriptions13 = require("@omnicross/subscriptions");
81
83
 
82
84
  // src/admin/accountsCodexOAuth.ts
83
85
  var import_node_crypto = __toESM(require("crypto"), 1);
@@ -439,7 +441,7 @@ function handleCopilotOAuthStatus(sessionId, deps) {
439
441
  }
440
442
 
441
443
  // src/allowance/AccountAllowanceService.ts
442
- var import_AccountAllowanceStore8 = require("@omnicross/core/pipeline/AccountAllowanceStore");
444
+ var import_AccountAllowanceStore9 = require("@omnicross/core/pipeline/AccountAllowanceStore");
443
445
  var import_AccountAllowanceScheduling = require("@omnicross/core/pipeline/AccountAllowanceScheduling");
444
446
 
445
447
  // src/allowance/ClaudeAllowanceCollector.ts
@@ -1809,9 +1811,321 @@ var GeminiAllowanceCollector = class {
1809
1811
  }
1810
1812
  };
1811
1813
 
1812
- // src/allowance/OpenCodeGoAllowanceCollector.ts
1814
+ // src/allowance/AntigravityAllowanceCollector.ts
1815
+ var import_GeminiCodeAssistProjectResolver2 = require("@omnicross/core/auth/GeminiCodeAssistProjectResolver");
1816
+ var import_antigravityQuotaFamily = require("@omnicross/core/pipeline/antigravityQuotaFamily");
1813
1817
  var import_AccountAllowanceStore7 = require("@omnicross/core/pipeline/AccountAllowanceStore");
1814
1818
  var import_upstreamFetch7 = require("@omnicross/core/pipeline/upstreamFetch");
1819
+ var import_antigravityIdentity = require("@omnicross/core/transformer/transformers/antigravityIdentity");
1820
+ var ANTIGRAVITY_ALLOWANCE_CACHE_MS = 5 * 6e4;
1821
+ var RETRIEVE_USER_QUOTA_SUMMARY_PATH = "/v1internal:retrieveUserQuotaSummary";
1822
+ var FETCH_AVAILABLE_MODELS_PATH = "/v1internal:fetchAvailableModels";
1823
+ var ANTIGRAVITY_DISCOVERY_DENYLIST = /* @__PURE__ */ new Set([
1824
+ "chat_20706",
1825
+ "chat_23310",
1826
+ "gemini-2.5-pro"
1827
+ ]);
1828
+ function isRecord5(value) {
1829
+ return !!value && typeof value === "object" && !Array.isArray(value);
1830
+ }
1831
+ function secondsUntil7(instant, now) {
1832
+ if (!instant) return void 0;
1833
+ return Math.max(0, Math.floor((Date.parse(instant) - now) / 1e3));
1834
+ }
1835
+ var WINDOW_LABELS = {
1836
+ "five-hour": "5 Hour",
1837
+ weekly: "Weekly",
1838
+ daily: "Daily"
1839
+ };
1840
+ function classifyWindowId(...sources) {
1841
+ for (const source of sources) {
1842
+ if (!source) continue;
1843
+ const text = source.toLowerCase();
1844
+ if (text.includes("week") || text.includes("7d") || /7[\s_-]*day/.test(text)) return "weekly";
1845
+ if (text.includes("5h") || text.includes("five hour") || /5[\s_-]*hour/.test(text)) return "five-hour";
1846
+ if (text.includes("day") || text.includes("daily") || text.includes("24h")) return "daily";
1847
+ }
1848
+ return void 0;
1849
+ }
1850
+ function inferWindowFromReset(resetsAt, now) {
1851
+ if (resetsAt !== void 0 && Date.parse(resetsAt) - now > 24 * 60 * 60 * 1e3) return "weekly";
1852
+ return "daily";
1853
+ }
1854
+ function clampFraction(value) {
1855
+ if (value === void 0 || !Number.isFinite(value)) return void 0;
1856
+ return Math.min(1, Math.max(0, value));
1857
+ }
1858
+ function usedPercentFromFraction(fraction) {
1859
+ const clamped = clampFraction(fraction);
1860
+ if (clamped === void 0) return null;
1861
+ return Math.round((1 - clamped) * 1e3) / 10;
1862
+ }
1863
+ function toResetsAt(resetTime) {
1864
+ if (!resetTime || !Number.isFinite(Date.parse(resetTime))) return void 0;
1865
+ return new Date(Date.parse(resetTime)).toISOString();
1866
+ }
1867
+ function parseAntigravityQuotaSummary(payload, now) {
1868
+ if (!isRecord5(payload)) return null;
1869
+ const groups = Array.isArray(payload["groups"]) ? payload["groups"] : [];
1870
+ const topBuckets = Array.isArray(payload["buckets"]) ? payload["buckets"] : [];
1871
+ const hasGrouped = groups.some((group) => Array.isArray(group.buckets) && group.buckets.length > 0);
1872
+ if (!hasGrouped && topBuckets.length === 0) return null;
1873
+ const windows = /* @__PURE__ */ new Map();
1874
+ const addBucket = (bucket, groupName) => {
1875
+ const families = (0, import_antigravityQuotaFamily.antigravityCounterFamiliesForBucketId)(bucket.bucketId, groupName);
1876
+ if (families.length === 0) return;
1877
+ const resetsAt = toResetsAt(bucket.resetTime);
1878
+ const windowId = classifyWindowId(bucket.window, bucket.displayName, bucket.bucketId) ?? (resetsAt !== void 0 ? inferWindowFromReset(resetsAt, now) : void 0);
1879
+ if (windowId === void 0) return;
1880
+ const usedPercent = usedPercentFromFraction(bucket.remainingFraction) ?? (bucket.disabled === true || bucket.resetTime ? bucket.disabled === true ? 100 : null : null);
1881
+ for (const family of families) {
1882
+ const id = `antigravity:${family}:${windowId}`;
1883
+ const candidate = {
1884
+ id,
1885
+ label: `${WINDOW_LABELS[windowId]} (${family})`,
1886
+ scope: "model-family",
1887
+ // The window carries the MODEL family (gemini/claude/gpt-oss) — the
1888
+ // scheduling gate compares it against the requested model's family.
1889
+ modelFamily: import_antigravityQuotaFamily.ANTIGRAVITY_COUNTER_TO_MODEL_FAMILY[family],
1890
+ usedPercent,
1891
+ ...resetsAt !== void 0 ? { resetsAt } : {},
1892
+ remainingSeconds: secondsUntil7(resetsAt, now),
1893
+ state: "fresh",
1894
+ ...bucket.disabled === true ? { disabled: true } : {}
1895
+ };
1896
+ const existing = windows.get(id);
1897
+ if (!existing || candidate.disabled === true || existing.disabled !== true && (candidate.usedPercent ?? -1) > (existing.usedPercent ?? -1)) {
1898
+ windows.set(id, candidate);
1899
+ }
1900
+ }
1901
+ };
1902
+ if (hasGrouped) {
1903
+ for (const group of groups) {
1904
+ for (const bucket of group.buckets ?? []) addBucket(bucket, group.displayName);
1905
+ }
1906
+ } else {
1907
+ for (const bucket of topBuckets) addBucket(bucket);
1908
+ }
1909
+ const result = [...windows.values()];
1910
+ return result.length > 0 ? result : null;
1911
+ }
1912
+ function legacyQuotaInfos(model) {
1913
+ const out = [];
1914
+ const source = {
1915
+ ...model.apiProvider ? { apiProvider: model.apiProvider } : {},
1916
+ ...model.modelProvider ? { modelProvider: model.modelProvider } : {}
1917
+ };
1918
+ const add = (value, windowDefault) => {
1919
+ if (!value) return;
1920
+ const list = Array.isArray(value) ? value : [value];
1921
+ for (const info of list) {
1922
+ out.push({ ...source, ...windowDefault ? { windowId: windowDefault } : {}, ...info });
1923
+ }
1924
+ };
1925
+ add(model.quotaInfo);
1926
+ add(model.quotaInfos);
1927
+ add(model.dailyQuotaInfo, "daily");
1928
+ add(model.dailyQuotaInfos, "daily");
1929
+ add(model.weeklyQuotaInfo, "weekly");
1930
+ add(model.weeklyQuotaInfos, "weekly");
1931
+ return out;
1932
+ }
1933
+ function legacyCounterFamily(info) {
1934
+ switch (info.modelProvider ?? info.apiProvider) {
1935
+ case "MODEL_PROVIDER_ANTHROPIC":
1936
+ case "API_PROVIDER_ANTHROPIC_VERTEX":
1937
+ return "anthropic";
1938
+ case "MODEL_PROVIDER_GOOGLE":
1939
+ case "API_PROVIDER_GOOGLE_GEMINI":
1940
+ return "google";
1941
+ case "MODEL_PROVIDER_OPENAI":
1942
+ case "API_PROVIDER_OPENAI_VERTEX":
1943
+ return "openai";
1944
+ default:
1945
+ return void 0;
1946
+ }
1947
+ }
1948
+ function parseAntigravityLegacyQuota(payload, now) {
1949
+ if (!isRecord5(payload)) return null;
1950
+ const models = payload["models"];
1951
+ if (!isRecord5(models)) return null;
1952
+ const windows = /* @__PURE__ */ new Map();
1953
+ for (const info of Object.values(models).flatMap(legacyQuotaInfos)) {
1954
+ const family = legacyCounterFamily(info);
1955
+ if (!family) continue;
1956
+ const resetsAt = toResetsAt(info.resetTime);
1957
+ const windowId = classifyWindowId(info.windowId, info.windowLabel) ?? (resetsAt !== void 0 ? inferWindowFromReset(resetsAt, now) : void 0);
1958
+ if (windowId === void 0) continue;
1959
+ const id = `antigravity:${family}:${windowId}`;
1960
+ const candidate = {
1961
+ id,
1962
+ label: `${WINDOW_LABELS[windowId]} (${family})`,
1963
+ scope: "model-family",
1964
+ modelFamily: import_antigravityQuotaFamily.ANTIGRAVITY_COUNTER_TO_MODEL_FAMILY[family],
1965
+ usedPercent: usedPercentFromFraction(info.remainingFraction),
1966
+ ...resetsAt !== void 0 ? { resetsAt } : {},
1967
+ remainingSeconds: secondsUntil7(resetsAt, now),
1968
+ state: "fresh"
1969
+ };
1970
+ const existing = windows.get(id);
1971
+ if (!existing || (candidate.usedPercent ?? -1) > (existing.usedPercent ?? -1)) {
1972
+ windows.set(id, candidate);
1973
+ }
1974
+ }
1975
+ const result = [...windows.values()];
1976
+ return result.length > 0 ? result : null;
1977
+ }
1978
+ var AntigravityAllowanceCollector = class {
1979
+ constructor(credentials, store = (0, import_AccountAllowanceStore7.getSharedAccountAllowanceStore)(), fetchImpl = (url, init, accountId) => (0, import_upstreamFetch7.fetchUpstream)(url, init, { providerId: "antigravity", accountId, redactBodies: true }), now = Date.now) {
1980
+ this.credentials = credentials;
1981
+ this.store = store;
1982
+ this.fetchImpl = fetchImpl;
1983
+ this.now = now;
1984
+ }
1985
+ credentials;
1986
+ store;
1987
+ fetchImpl;
1988
+ now;
1989
+ inFlight = /* @__PURE__ */ new Map();
1990
+ async collectMany(accounts, options = {}) {
1991
+ const settled = await Promise.allSettled(
1992
+ accounts.map((account) => this.collect(account, options))
1993
+ );
1994
+ return settled.flatMap((result) => result.status === "fulfilled" ? [result.value] : []);
1995
+ }
1996
+ collect(account, options = {}) {
1997
+ const now = this.now();
1998
+ if (account.tokens.authMethod !== "oauth") {
1999
+ const existing = this.store.get("antigravity", account.id, now);
2000
+ if (existing?.windows.every((window) => window.state === "unsupported")) {
2001
+ return Promise.resolve(existing);
2002
+ }
2003
+ const snapshot = this.unsupportedSnapshot(account.id, now);
2004
+ this.store.set(snapshot);
2005
+ return Promise.resolve(snapshot);
2006
+ }
2007
+ const cached = this.store.get("antigravity", account.id, now);
2008
+ if (!options.force && cached && this.isCacheValid(cached, now, options.refreshAheadMs)) {
2009
+ return Promise.resolve(cached);
2010
+ }
2011
+ const running = this.inFlight.get(account.id);
2012
+ if (running) return running;
2013
+ const promise = this.fetchAccount(account.id).catch(() => this.failureSnapshot(account.id, "antigravity_usage_request_failed", this.now())).finally(() => this.inFlight.delete(account.id));
2014
+ this.inFlight.set(account.id, promise);
2015
+ return promise;
2016
+ }
2017
+ isCacheValid(snapshot, now, refreshAheadMs) {
2018
+ if (snapshot.windows.every((window) => window.state === "unsupported")) return true;
2019
+ const expiresAt = snapshot.expiresAt ? Date.parse(snapshot.expiresAt) : 0;
2020
+ const ahead = typeof refreshAheadMs === "number" && Number.isFinite(refreshAheadMs) ? Math.max(0, refreshAheadMs) : 0;
2021
+ return Number.isFinite(expiresAt) && expiresAt > now + ahead;
2022
+ }
2023
+ async fetchAccount(accountId) {
2024
+ let accessToken = await this.credentials.getAccessTokenForAccount("antigravity", accountId);
2025
+ if (!accessToken) return this.failureSnapshot(accountId, "antigravity_usage_token_unavailable", this.now());
2026
+ let response = await this.request(accountId, accessToken, RETRIEVE_USER_QUOTA_SUMMARY_PATH, {
2027
+ project: void 0
2028
+ });
2029
+ if (response.status === 401 || response.status === 403) {
2030
+ const refreshed = await this.credentials.refreshAccountToken("antigravity", accountId);
2031
+ if (!refreshed) return this.failureSnapshot(accountId, "antigravity_usage_unauthorized", this.now());
2032
+ accessToken = await this.credentials.getAccessTokenForAccount("antigravity", accountId);
2033
+ if (!accessToken) return this.failureSnapshot(accountId, "antigravity_usage_token_unavailable", this.now());
2034
+ response = await this.request(accountId, accessToken, RETRIEVE_USER_QUOTA_SUMMARY_PATH, {
2035
+ project: void 0
2036
+ });
2037
+ if (response.status === 401 || response.status === 403) {
2038
+ return this.failureSnapshot(accountId, "antigravity_usage_unauthorized", this.now());
2039
+ }
2040
+ }
2041
+ if (response.ok) {
2042
+ const payload = await response.json().catch(() => null);
2043
+ const windows = parseAntigravityQuotaSummary(payload, this.now());
2044
+ if (windows) {
2045
+ const snapshot2 = this.snapshot(accountId, windows);
2046
+ this.store.set(snapshot2);
2047
+ return snapshot2;
2048
+ }
2049
+ }
2050
+ const legacy = await this.request(accountId, accessToken, FETCH_AVAILABLE_MODELS_PATH, {});
2051
+ if (!legacy.ok) {
2052
+ return this.failureSnapshot(accountId, "antigravity_usage_http_error", this.now());
2053
+ }
2054
+ const legacyPayload = await legacy.json().catch(() => null);
2055
+ const legacyWindows = parseAntigravityLegacyQuota(legacyPayload, this.now());
2056
+ if (!legacyWindows) {
2057
+ return this.failureSnapshot(accountId, "antigravity_usage_invalid_response", this.now());
2058
+ }
2059
+ const snapshot = this.snapshot(accountId, legacyWindows);
2060
+ this.store.set(snapshot);
2061
+ return snapshot;
2062
+ }
2063
+ /** One upstream round-trip with the antigravity/hub masquerade UA. */
2064
+ request(accountId, accessToken, path2, body) {
2065
+ return this.fetchImpl(`${import_GeminiCodeAssistProjectResolver2.ANTIGRAVITY_CODE_ASSIST_ENDPOINT}${path2}`, {
2066
+ method: "POST",
2067
+ headers: {
2068
+ Authorization: `Bearer ${accessToken}`,
2069
+ Accept: "application/json",
2070
+ "Content-Type": "application/json",
2071
+ "User-Agent": (0, import_antigravityIdentity.getAntigravityUserAgent)()
2072
+ },
2073
+ body: JSON.stringify(body),
2074
+ signal: AbortSignal.timeout(15e3)
2075
+ }, accountId);
2076
+ }
2077
+ snapshot(accountId, windows, now = this.now()) {
2078
+ return {
2079
+ providerId: "antigravity",
2080
+ accountId,
2081
+ source: "oauth-usage-api",
2082
+ observedAt: new Date(now).toISOString(),
2083
+ expiresAt: new Date(now + ANTIGRAVITY_ALLOWANCE_CACHE_MS).toISOString(),
2084
+ windows
2085
+ };
2086
+ }
2087
+ failureSnapshot(accountId, code, now) {
2088
+ const existing = this.store.get("antigravity", accountId, now);
2089
+ const snapshot = existing ? {
2090
+ ...existing,
2091
+ expiresAt: new Date(now + ANTIGRAVITY_ALLOWANCE_CACHE_MS).toISOString(),
2092
+ windows: existing.windows.map((window) => ({
2093
+ ...window,
2094
+ state: window.state === "unsupported" ? "unsupported" : window.usedPercent !== null || window.resetsAt || window.disabled ? "stale" : "unavailable"
2095
+ })),
2096
+ lastErrorCode: code
2097
+ } : {
2098
+ providerId: "antigravity",
2099
+ accountId,
2100
+ source: "oauth-usage-api",
2101
+ observedAt: new Date(now).toISOString(),
2102
+ expiresAt: new Date(now + ANTIGRAVITY_ALLOWANCE_CACHE_MS).toISOString(),
2103
+ windows: [
2104
+ { id: "antigravity-quota", label: "Antigravity quota", scope: "all", usedPercent: null, state: "unavailable" }
2105
+ ],
2106
+ lastErrorCode: code
2107
+ };
2108
+ this.store.set(snapshot);
2109
+ return snapshot;
2110
+ }
2111
+ unsupportedSnapshot(accountId, now) {
2112
+ return {
2113
+ providerId: "antigravity",
2114
+ accountId,
2115
+ source: "oauth-usage-api",
2116
+ observedAt: new Date(now).toISOString(),
2117
+ windows: [
2118
+ { id: "antigravity-quota", label: "Antigravity quota", scope: "all", usedPercent: null, state: "unsupported" }
2119
+ ],
2120
+ lastErrorCode: "antigravity_usage_unsupported_auth"
2121
+ };
2122
+ }
2123
+ };
2124
+
2125
+ // src/allowance/OpenCodeGoAllowanceCollector.ts
2126
+ var import_AccountAllowanceStore8 = require("@omnicross/core/pipeline/AccountAllowanceStore");
2127
+ var import_upstreamFetch8 = require("@omnicross/core/pipeline/upstreamFetch");
2128
+ var import_openCodeGoHeaders = require("@omnicross/core/provider-proxy/identity/openCodeGoHeaders");
1815
2129
  var import_subscriptions7 = require("@omnicross/subscriptions");
1816
2130
  var OPENCODEGO_ALLOWANCE_CACHE_MS = 5 * 6e4;
1817
2131
  var OPENCODEGO_DEFAULT_GO_BASE = "https://opencode.ai/zen/go";
@@ -1825,7 +2139,7 @@ function isoInstant2(value) {
1825
2139
  const time = Date.parse(value);
1826
2140
  return Number.isFinite(time) ? new Date(time).toISOString() : void 0;
1827
2141
  }
1828
- function secondsUntil7(instant, now) {
2142
+ function secondsUntil8(instant, now) {
1829
2143
  if (!instant) return void 0;
1830
2144
  return Math.max(0, Math.floor((Date.parse(instant) - now) / 1e3));
1831
2145
  }
@@ -1840,12 +2154,12 @@ function windowFromPayload3(id, label, minutes, payload, now) {
1840
2154
  usedPercent,
1841
2155
  windowMinutes: minutes,
1842
2156
  ...resetsAt !== void 0 ? { resetsAt } : {},
1843
- remainingSeconds: secondsUntil7(resetsAt, now),
2157
+ remainingSeconds: secondsUntil8(resetsAt, now),
1844
2158
  state: usedPercent !== null || resetsAt ? "fresh" : "unavailable"
1845
2159
  };
1846
2160
  }
1847
2161
  var OpenCodeGoAllowanceCollector = class {
1848
- constructor(credentials, store = (0, import_AccountAllowanceStore7.getSharedAccountAllowanceStore)(), fetchImpl = (url, init, accountId) => (0, import_upstreamFetch7.fetchUpstream)(url, init, { providerId: "opencodego", accountId, redactBodies: true }), now = Date.now) {
2162
+ constructor(credentials, store = (0, import_AccountAllowanceStore8.getSharedAccountAllowanceStore)(), fetchImpl = (url, init, accountId) => (0, import_upstreamFetch8.fetchUpstream)(url, init, { providerId: "opencodego", accountId, redactBodies: true }), now = Date.now) {
1849
2163
  this.credentials = credentials;
1850
2164
  this.store = store;
1851
2165
  this.fetchImpl = fetchImpl;
@@ -1878,7 +2192,14 @@ var OpenCodeGoAllowanceCollector = class {
1878
2192
  const base = account.tokens.baseUrl ? (0, import_subscriptions7.normalizeOpenCodeGoBaseUrl)(account.tokens.baseUrl) : OPENCODEGO_DEFAULT_GO_BASE;
1879
2193
  const response = await this.fetchImpl(`${base}/v1/usage`, {
1880
2194
  method: "GET",
1881
- headers: { Authorization: `Bearer ${apiKey}`, Accept: "application/json" },
2195
+ // opencodego-egress-identity: the background poll identifies itself with
2196
+ // the same configured/default UA the relay carries (no session header —
2197
+ // a poll has no conversation).
2198
+ headers: {
2199
+ Authorization: `Bearer ${apiKey}`,
2200
+ Accept: "application/json",
2201
+ "User-Agent": (0, import_openCodeGoHeaders.getOpenCodeGoUserAgent)()
2202
+ },
1882
2203
  signal: AbortSignal.timeout(15e3)
1883
2204
  }, account.id);
1884
2205
  if (response.status === 401 || response.status === 403) {
@@ -1950,7 +2271,7 @@ function codexUnavailable(accountId, now) {
1950
2271
  };
1951
2272
  }
1952
2273
  var AccountAllowanceService = class {
1953
- constructor(credentials, store = (0, import_AccountAllowanceStore8.getSharedAccountAllowanceStore)(), collector, codexCollector, kimiCollector, opencodegoCollector, grokCollector, copilotCollector, geminiCollector, now = Date.now) {
2274
+ constructor(credentials, store = (0, import_AccountAllowanceStore9.getSharedAccountAllowanceStore)(), collector, codexCollector, kimiCollector, opencodegoCollector, grokCollector, copilotCollector, geminiCollector, antigravityCollector, now = Date.now) {
1954
2275
  this.credentials = credentials;
1955
2276
  this.store = store;
1956
2277
  this.now = now;
@@ -1961,6 +2282,7 @@ var AccountAllowanceService = class {
1961
2282
  this.grokCollector = grokCollector ?? new GrokAllowanceCollector(credentials, store);
1962
2283
  this.copilotCollector = copilotCollector ?? new CopilotAllowanceCollector(credentials, store);
1963
2284
  this.geminiCollector = geminiCollector ?? new GeminiAllowanceCollector(credentials, store);
2285
+ this.antigravityCollector = antigravityCollector ?? new AntigravityAllowanceCollector(credentials, store);
1964
2286
  }
1965
2287
  credentials;
1966
2288
  store;
@@ -1972,6 +2294,7 @@ var AccountAllowanceService = class {
1972
2294
  copilotCollector;
1973
2295
  opencodegoCollector;
1974
2296
  geminiCollector;
2297
+ antigravityCollector;
1975
2298
  /**
1976
2299
  * Read all/filtered snapshots. Claude's and Codex's five-minute caches are
1977
2300
  * refreshed lazily on read (Codex polls `/backend-api/wham/usage`; the
@@ -2020,6 +2343,11 @@ var AccountAllowanceService = class {
2020
2343
  (account) => !filter.accountId || account.id === filter.accountId
2021
2344
  );
2022
2345
  if (wantsGemini) await this.geminiCollector.collectMany(geminiAccounts);
2346
+ const wantsAntigravity = !filter.providerId || filter.providerId === "antigravity";
2347
+ const antigravityAccounts = (config.antigravityAccounts ?? []).filter(
2348
+ (account) => !filter.accountId || account.id === filter.accountId
2349
+ );
2350
+ if (wantsAntigravity) await this.antigravityCollector.collectMany(antigravityAccounts);
2023
2351
  const known = /* @__PURE__ */ new Set();
2024
2352
  if (wantsClaude) for (const account of claudeAccounts) known.add(`claude\0${account.id}`);
2025
2353
  if (wantsCodex) for (const account of codexAccounts) known.add(`codex\0${account.id}`);
@@ -2028,6 +2356,7 @@ var AccountAllowanceService = class {
2028
2356
  if (wantsGrok) for (const account of grokAccounts) known.add(`grok\0${account.id}`);
2029
2357
  if (wantsCopilot) for (const account of copilotAccounts) known.add(`copilot\0${account.id}`);
2030
2358
  if (wantsGemini) for (const account of geminiAccounts) known.add(`gemini\0${account.id}`);
2359
+ if (wantsAntigravity) for (const account of antigravityAccounts) known.add(`antigravity\0${account.id}`);
2031
2360
  return this.store.list(filter).filter((snapshot) => known.has(`${snapshot.providerId}\0${snapshot.accountId}`));
2032
2361
  }
2033
2362
  knownAccounts(config) {
@@ -2038,7 +2367,8 @@ var AccountAllowanceService = class {
2038
2367
  ...(config.opencodegoAccounts ?? []).map((account) => ({ providerId: "opencodego", accountId: account.id })),
2039
2368
  ...(config.grokAccounts ?? []).map((account) => ({ providerId: "grok", accountId: account.id })),
2040
2369
  ...(config.copilotAccounts ?? []).map((account) => ({ providerId: "copilot", accountId: account.id })),
2041
- ...(config.geminiAccounts ?? []).map((account) => ({ providerId: "gemini", accountId: account.id }))
2370
+ ...(config.geminiAccounts ?? []).map((account) => ({ providerId: "gemini", accountId: account.id })),
2371
+ ...(config.antigravityAccounts ?? []).map((account) => ({ providerId: "antigravity", accountId: account.id }))
2042
2372
  ];
2043
2373
  }
2044
2374
  /** Force-refresh Claude usage for one account or every stored Claude account. */
@@ -2108,6 +2438,15 @@ var AccountAllowanceService = class {
2108
2438
  );
2109
2439
  return this.geminiCollector.collectMany(accounts, { force: true });
2110
2440
  }
2441
+ /** Force-refresh Antigravity usage (quotaSummary dual buckets) for one/all accounts. */
2442
+ async refreshAntigravity(accountId) {
2443
+ const config = await this.credentials.getFullConfig();
2444
+ this.store.pruneToKnownAccounts(this.knownAccounts(config));
2445
+ const accounts = (config.antigravityAccounts ?? []).filter(
2446
+ (account) => !accountId || account.id === accountId
2447
+ );
2448
+ return this.antigravityCollector.collectMany(accounts, { force: true });
2449
+ }
2111
2450
  /**
2112
2451
  * Keep Claude + Codex + Kimi snapshots warm for allowance-aware routing. All
2113
2452
  * collectors preserve their cache + per-account in-flight coalescing; a tick
@@ -2125,6 +2464,7 @@ var AccountAllowanceService = class {
2125
2464
  await this.grokCollector.collectMany(config.grokAccounts ?? [], { refreshAheadMs });
2126
2465
  await this.copilotCollector.collectMany(config.copilotAccounts ?? [], { refreshAheadMs });
2127
2466
  await this.geminiCollector.collectMany(config.geminiAccounts ?? [], { refreshAheadMs });
2467
+ await this.antigravityCollector.collectMany(config.antigravityAccounts ?? [], { refreshAheadMs });
2128
2468
  }
2129
2469
  /** Remove a cache row as soon as an account is deleted by the admin path. */
2130
2470
  removeAccountSnapshot(providerId, accountId) {
@@ -2219,7 +2559,7 @@ var ClaudeAllowanceRefreshScheduler = class {
2219
2559
  var import_node_crypto2 = require("crypto");
2220
2560
  var import_node_fs = require("fs");
2221
2561
  var import_node_path = require("path");
2222
- var import_AccountAllowanceStore9 = require("@omnicross/core/pipeline/AccountAllowanceStore");
2562
+ var import_AccountAllowanceStore10 = require("@omnicross/core/pipeline/AccountAllowanceStore");
2223
2563
  var ACCOUNT_ALLOWANCE_CACHE_VERSION = 1;
2224
2564
  var MAX_PERSISTED_ALLOWANCE_SNAPSHOTS = 256;
2225
2565
  var MAX_ALLOWANCE_CACHE_BYTES = 1e6;
@@ -2248,7 +2588,7 @@ var JsonAccountAllowancePersistence = class {
2248
2588
  save(snapshots) {
2249
2589
  const rows = [];
2250
2590
  for (const snapshot of snapshots) {
2251
- const normalized2 = (0, import_AccountAllowanceStore9.normalizeAccountAllowanceSnapshot)(snapshot);
2591
+ const normalized2 = (0, import_AccountAllowanceStore10.normalizeAccountAllowanceSnapshot)(snapshot);
2252
2592
  if (!normalized2) continue;
2253
2593
  rows.push(normalized2);
2254
2594
  if (rows.length >= MAX_PERSISTED_ALLOWANCE_SNAPSHOTS) break;
@@ -2531,7 +2871,7 @@ var import_outbound_api5 = require("@omnicross/core/outbound-api");
2531
2871
  var import_image_generation_types = require("@omnicross/contracts/image-generation-types");
2532
2872
  var import_AccountAllowanceScheduling2 = require("@omnicross/core/pipeline/AccountAllowanceScheduling");
2533
2873
  var import_SubscriptionAccountHealth = require("@omnicross/core/pipeline/SubscriptionAccountHealth");
2534
- var import_upstreamFetch10 = require("@omnicross/core/pipeline/upstreamFetch");
2874
+ var import_upstreamFetch12 = require("@omnicross/core/pipeline/upstreamFetch");
2535
2875
  var import_core3 = require("@omnicross/core");
2536
2876
 
2537
2877
  // src/image-generation/imagesConfigValidation.ts
@@ -3131,7 +3471,11 @@ var TOKEN_FIELDS = {
3131
3471
  claude: ["accessToken", "refreshToken"],
3132
3472
  codex: ["accessToken", "refreshToken", "idToken"],
3133
3473
  gemini: ["accessToken", "refreshToken"],
3134
- opencodego: ["apiKey"]
3474
+ opencodego: ["apiKey"],
3475
+ kimi: ["accessToken", "refreshToken"],
3476
+ grok: ["accessToken", "refreshToken"],
3477
+ copilot: ["accessToken", "refreshToken"],
3478
+ antigravity: ["accessToken", "refreshToken"]
3135
3479
  };
3136
3480
  function transformTokenBlock(block, fields, fn) {
3137
3481
  const next = { ...block };
@@ -3203,6 +3547,19 @@ function resolveAdminConfig(admin) {
3203
3547
  token: typeof admin?.token === "string" && admin.token.length > 0 ? admin.token : void 0
3204
3548
  };
3205
3549
  }
3550
+ function validateAntigravity(raw) {
3551
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return void 0;
3552
+ const a = raw;
3553
+ if (typeof a["sandboxFailover"] !== "boolean") return void 0;
3554
+ return { sandboxFailover: a["sandboxFailover"] };
3555
+ }
3556
+ function validateOpenCodeGo(raw) {
3557
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return void 0;
3558
+ const o = raw;
3559
+ const ua = o["userAgent"];
3560
+ if (typeof ua !== "string" || ua.trim().length === 0) return void 0;
3561
+ return { userAgent: ua.trim() };
3562
+ }
3206
3563
  function validateUsage(raw) {
3207
3564
  if (!raw || typeof raw !== "object" || Array.isArray(raw)) return void 0;
3208
3565
  const u = raw;
@@ -3496,7 +3853,9 @@ function validateConfig(raw) {
3496
3853
  const admin = validateAdmin(obj["admin"]);
3497
3854
  const logging = validateLogging(obj["logging"]);
3498
3855
  const usage = validateUsage(obj["usage"]);
3499
- return { providers, server, admin, logging };
3856
+ const antigravity = validateAntigravity(obj["antigravity"]);
3857
+ const opencodego = validateOpenCodeGo(obj["opencodego"]);
3858
+ return { providers, server, admin, logging, usage, antigravity, opencodego };
3500
3859
  }
3501
3860
  var secretBox = null;
3502
3861
  function setSecretBox(box) {
@@ -4517,11 +4876,11 @@ function preserveOutboundProxySecrets(incoming, current) {
4517
4876
  }
4518
4877
 
4519
4878
  // src/proxy/upstreamProxyResolver.ts
4520
- var import_upstreamFetch8 = require("@omnicross/core/pipeline/upstreamFetch");
4879
+ var import_upstreamFetch9 = require("@omnicross/core/pipeline/upstreamFetch");
4521
4880
  var serverProxy;
4522
4881
  function setServerProxyConfig(proxy) {
4523
4882
  serverProxy = proxy;
4524
- (0, import_upstreamFetch8.bumpUpstreamProxyGeneration)();
4883
+ (0, import_upstreamFetch9.bumpUpstreamProxyGeneration)();
4525
4884
  }
4526
4885
  function getServerProxyConfig() {
4527
4886
  return serverProxy;
@@ -4588,8 +4947,169 @@ function createUpstreamProxyResolver(src = {}) {
4588
4947
  };
4589
4948
  }
4590
4949
 
4591
- // src/admin/accountsOAuth.ts
4950
+ // src/admin/accountsAntigravityOAuth.ts
4951
+ var import_GeminiCodeAssistProjectResolver3 = require("@omnicross/core/auth/GeminiCodeAssistProjectResolver");
4592
4952
  var import_subscriptions8 = require("@omnicross/subscriptions");
4953
+ function err5(status, message) {
4954
+ return { status, body: { error: { type: "admin_api_error", message } } };
4955
+ }
4956
+ var DEFAULT_ANTIGRAVITY_OAUTH_TTL_MS = 10 * 6e4;
4957
+ function handleAntigravityOAuthStart(deps) {
4958
+ if (deps.antigravitySessions.isBusy()) {
4959
+ return err5(
4960
+ 409,
4961
+ "an antigravity sign-in is already in progress (loopback 127.0.0.1:51121 is held) \u2014 finish it in the browser or wait for it to time out"
4962
+ );
4963
+ }
4964
+ const { authUrl, state } = import_subscriptions8.antigravityOAuth.generateAuthParams();
4965
+ const { sessionId, signal } = deps.antigravitySessions.begin();
4966
+ void runAntigravityLoopback(sessionId, state, signal, deps);
4967
+ return { status: 200, body: { authUrl, sessionId } };
4968
+ }
4969
+ async function runAntigravityLoopback(sessionId, state, signal, deps) {
4970
+ const isPending = () => !signal.aborted && deps.antigravitySessions.get(sessionId)?.status === "pending";
4971
+ try {
4972
+ const code = await deps.antigravityAwaitLoopback(state, void 0, signal);
4973
+ if (!isPending()) return;
4974
+ const exchangeFetch = deps.oauthExchangeFetch("antigravity");
4975
+ const result = await import_subscriptions8.antigravityOAuth.exchangeCodeForTokens(code, exchangeFetch);
4976
+ if (!isPending()) return;
4977
+ const expiresAt = new Date(Date.now() + result.expiresIn * 1e3).toISOString();
4978
+ const email = await import_subscriptions8.antigravityOAuth.fetchUserEmail(result.accessToken, exchangeFetch);
4979
+ if (!isPending()) return;
4980
+ const projectId = await (0, import_GeminiCodeAssistProjectResolver3.getAntigravityProjectResolver)().resolveProject(result.accessToken);
4981
+ if (!isPending()) return;
4982
+ const block = {
4983
+ authMethod: "oauth",
4984
+ status: "authorized",
4985
+ accessToken: result.accessToken,
4986
+ refreshToken: result.refreshToken,
4987
+ expiresAt,
4988
+ ...email ? { email } : {},
4989
+ ...projectId ? { projectId } : {},
4990
+ lastRefreshedAt: (/* @__PURE__ */ new Date()).toISOString()
4991
+ };
4992
+ await deps.subscriptionAccountAppender.appendProviderAccount("antigravity", block);
4993
+ if (isPending()) deps.antigravitySessions.settle(sessionId, "done");
4994
+ } catch (e) {
4995
+ if (!isPending()) return;
4996
+ const reason = e instanceof Error ? e.message : "antigravity sign-in failed";
4997
+ deps.antigravitySessions.settle(sessionId, "error", reason);
4998
+ }
4999
+ }
5000
+ function handleAntigravityOAuthCancel(sessionId, deps) {
5001
+ if (!deps.antigravitySessions.cancel(sessionId)) {
5002
+ return err5(404, "unknown or expired antigravity sign-in session");
5003
+ }
5004
+ return { status: 200, body: { ok: true } };
5005
+ }
5006
+ function handleAntigravityOAuthStatus(sessionId, deps) {
5007
+ const s = deps.antigravitySessions.get(sessionId);
5008
+ if (!s) return err5(404, "unknown or expired antigravity sign-in session");
5009
+ return { status: 200, body: { state: s.status, ...s.error ? { message: s.error } : {} } };
5010
+ }
5011
+
5012
+ // src/allowance/AntigravityModelDiscovery.ts
5013
+ var import_canonical_models = require("@omnicross/contracts/canonical-models");
5014
+ var import_subscription_model_catalog = require("@omnicross/contracts/subscription-model-catalog");
5015
+ var import_GeminiCodeAssistProjectResolver4 = require("@omnicross/core/auth/GeminiCodeAssistProjectResolver");
5016
+ var import_upstreamFetch10 = require("@omnicross/core/pipeline/upstreamFetch");
5017
+ var import_antigravityIdentity2 = require("@omnicross/core/transformer/transformers/antigravityIdentity");
5018
+ function isRecord6(value) {
5019
+ return !!value && typeof value === "object" && !Array.isArray(value);
5020
+ }
5021
+ function optionalString(value) {
5022
+ return typeof value === "string" && value.length > 0 ? value : void 0;
5023
+ }
5024
+ function optionalNumber(value) {
5025
+ return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : void 0;
5026
+ }
5027
+ function optionalBoolean(value) {
5028
+ return typeof value === "boolean" ? value : void 0;
5029
+ }
5030
+ function parseAntigravityAvailableModels(payload) {
5031
+ if (!isRecord6(payload)) return [];
5032
+ const models = payload["models"];
5033
+ if (!isRecord6(models)) return [];
5034
+ const out = [];
5035
+ for (const [id, raw] of Object.entries(models)) {
5036
+ if (ANTIGRAVITY_DISCOVERY_DENYLIST.has(id)) continue;
5037
+ if (!isRecord6(raw)) continue;
5038
+ if (raw["isInternal"] === true) continue;
5039
+ out.push({
5040
+ id,
5041
+ ...optionalString(raw["displayName"]) ? { displayName: optionalString(raw["displayName"]) } : {},
5042
+ ...optionalBoolean(raw["supportsImages"]) !== void 0 ? { supportsImages: optionalBoolean(raw["supportsImages"]) } : {},
5043
+ ...optionalBoolean(raw["supportsThinking"]) !== void 0 ? { supportsThinking: optionalBoolean(raw["supportsThinking"]) } : {},
5044
+ ...optionalNumber(raw["thinkingBudget"]) !== void 0 ? { thinkingBudget: optionalNumber(raw["thinkingBudget"]) } : {},
5045
+ ...optionalNumber(raw["maxTokens"]) !== void 0 ? { maxTokens: optionalNumber(raw["maxTokens"]) } : {},
5046
+ ...optionalNumber(raw["maxOutputTokens"]) !== void 0 ? { maxOutputTokens: optionalNumber(raw["maxOutputTokens"]) } : {}
5047
+ });
5048
+ }
5049
+ out.sort((a, b) => a.id.localeCompare(b.id));
5050
+ return out;
5051
+ }
5052
+ function mergeAntigravityCatalog(discovered, log = (line) => console.warn(line), staticIds = import_subscription_model_catalog.SUBSCRIPTION_MODEL_CATALOG.antigravity) {
5053
+ const entries = staticIds.map((id) => {
5054
+ const capabilities = (0, import_canonical_models.lookupCanonicalCapabilities)(id);
5055
+ return {
5056
+ id,
5057
+ origin: "static",
5058
+ displayName: id,
5059
+ ...capabilities?.vision !== void 0 ? { supportsImages: capabilities.vision } : {},
5060
+ ...capabilities?.reasoning !== void 0 ? { supportsThinking: capabilities.reasoning } : {},
5061
+ ...capabilities?.thinkingTokenLimit ? { thinkingBudget: capabilities.thinkingTokenLimit.max } : {},
5062
+ // Discovery calls the context window maxTokens, not the output ceiling.
5063
+ ...capabilities?.contextLength !== void 0 ? { maxTokens: capabilities.contextLength } : {},
5064
+ ...capabilities?.maxTokens !== void 0 ? { maxOutputTokens: capabilities.maxTokens } : {}
5065
+ };
5066
+ });
5067
+ const staticSet = new Set(staticIds);
5068
+ for (const model of discovered) {
5069
+ if (staticSet.has(model.id)) {
5070
+ log(
5071
+ `[AntigravityModelDiscovery] dynamic model '${model.id}' conflicts with the static catalog \u2014 static entry kept`
5072
+ );
5073
+ continue;
5074
+ }
5075
+ entries.push({ ...model, origin: "discovered" });
5076
+ }
5077
+ return entries;
5078
+ }
5079
+ async function fetchAntigravityAvailableModels(accessToken, fetchImpl = (url, init) => (0, import_upstreamFetch10.fetchUpstream)(url, init, { providerId: "antigravity", redactBodies: true })) {
5080
+ let response;
5081
+ try {
5082
+ response = await fetchImpl(`${import_GeminiCodeAssistProjectResolver4.ANTIGRAVITY_CODE_ASSIST_ENDPOINT}/v1internal:fetchAvailableModels`, {
5083
+ method: "POST",
5084
+ headers: {
5085
+ Authorization: `Bearer ${accessToken}`,
5086
+ Accept: "application/json",
5087
+ "Content-Type": "application/json",
5088
+ "User-Agent": (0, import_antigravityIdentity2.getAntigravityUserAgent)()
5089
+ },
5090
+ body: JSON.stringify({}),
5091
+ signal: AbortSignal.timeout(15e3)
5092
+ });
5093
+ } catch {
5094
+ return null;
5095
+ }
5096
+ if (!response.ok) return null;
5097
+ const payload = await response.json().catch(() => null);
5098
+ if (!isRecord6(payload) || !isRecord6(payload["models"])) return null;
5099
+ return parseAntigravityAvailableModels(payload);
5100
+ }
5101
+ async function handleAntigravityModelsRoute(deps) {
5102
+ const accessToken = await deps.resolveAntigravityAccessToken().catch(() => null);
5103
+ const discovered = accessToken ? await fetchAntigravityAvailableModels(accessToken, deps.fetchImpl) : null;
5104
+ const models = mergeAntigravityCatalog(discovered ?? []);
5105
+ return {
5106
+ status: 200,
5107
+ body: { models, discovered: discovered !== null }
5108
+ };
5109
+ }
5110
+
5111
+ // src/admin/accountsOAuth.ts
5112
+ var import_subscriptions9 = require("@omnicross/subscriptions");
4593
5113
 
4594
5114
  // src/admin/accountsWrite.ts
4595
5115
  var VALID_PROVIDER_IDS = [
@@ -4599,7 +5119,8 @@ var VALID_PROVIDER_IDS = [
4599
5119
  "opencodego",
4600
5120
  "kimi",
4601
5121
  "grok",
4602
- "copilot"
5122
+ "copilot",
5123
+ "antigravity"
4603
5124
  ];
4604
5125
  function asSubscriptionProviderId(id) {
4605
5126
  return VALID_PROVIDER_IDS.includes(id) ? id : null;
@@ -4781,7 +5302,7 @@ function validateCopilot(body) {
4781
5302
  ]);
4782
5303
  return out;
4783
5304
  }
4784
- function validateOpenCodeGo(body) {
5305
+ function validateOpenCodeGo2(body) {
4785
5306
  const authMethod = str(body["authMethod"]);
4786
5307
  const status = str(body["status"]);
4787
5308
  if (authMethod !== "manual") return null;
@@ -4815,7 +5336,7 @@ function validateTokenBody(providerId, body) {
4815
5336
  case "gemini":
4816
5337
  return validateGemini(body);
4817
5338
  case "opencodego":
4818
- return validateOpenCodeGo(body);
5339
+ return validateOpenCodeGo2(body);
4819
5340
  case "kimi":
4820
5341
  return validateKimi(body);
4821
5342
  case "grok":
@@ -4851,37 +5372,37 @@ async function statusEntryFor(reader, providerId) {
4851
5372
 
4852
5373
  // src/admin/accountsOAuth.ts
4853
5374
  var OAUTH_HTTP_PROVIDERS = /* @__PURE__ */ new Set(["claude", "gemini"]);
4854
- function err5(status, message) {
5375
+ function err6(status, message) {
4855
5376
  return { status, body: { error: { type: "admin_api_error", message } } };
4856
5377
  }
4857
5378
  function handleOAuthStart(providerId, deps) {
4858
5379
  if (!OAUTH_HTTP_PROVIDERS.has(providerId)) {
4859
- return err5(400, `oauth not available for provider '${providerId}'`);
5380
+ return err6(400, `oauth not available for provider '${providerId}'`);
4860
5381
  }
4861
- const flow = providerId === "claude" ? import_subscriptions8.claudeOAuth : import_subscriptions8.geminiOAuth;
5382
+ const flow = providerId === "claude" ? import_subscriptions9.claudeOAuth : import_subscriptions9.geminiOAuth;
4862
5383
  const { authUrl, codeVerifier, state } = flow.generateAuthParams();
4863
5384
  const sessionId = deps.oauthSessions.put({ providerId, codeVerifier, state });
4864
5385
  return { status: 200, body: { authUrl, sessionId } };
4865
5386
  }
4866
5387
  async function handleOAuthComplete(providerId, body, deps) {
4867
5388
  if (!OAUTH_HTTP_PROVIDERS.has(providerId)) {
4868
- return err5(400, `oauth not available for provider '${providerId}'`);
5389
+ return err6(400, `oauth not available for provider '${providerId}'`);
4869
5390
  }
4870
5391
  const sessionId = typeof body["sessionId"] === "string" ? body["sessionId"] : "";
4871
5392
  const rawCode = typeof body["code"] === "string" ? body["code"] : "";
4872
- if (!sessionId) return err5(400, "oauth complete requires { sessionId }");
4873
- if (!rawCode) return err5(400, "oauth complete requires { code }");
5393
+ if (!sessionId) return err6(400, "oauth complete requires { sessionId }");
5394
+ if (!rawCode) return err6(400, "oauth complete requires { code }");
4874
5395
  const session = deps.oauthSessions.peek(sessionId);
4875
- if (!session) return err5(410, "oauth session is unknown, expired, or already used");
5396
+ if (!session) return err6(410, "oauth session is unknown, expired, or already used");
4876
5397
  if (session.providerId !== providerId) {
4877
- return err5(400, `oauth session does not match provider '${providerId}'`);
5398
+ return err6(400, `oauth session does not match provider '${providerId}'`);
4878
5399
  }
4879
5400
  let code = rawCode.trim();
4880
5401
  if (providerId === "claude") {
4881
5402
  const [splitCode, pastedState] = code.split("#");
4882
- if (!splitCode) return err5(400, "no authorization code was provided");
5403
+ if (!splitCode) return err6(400, "no authorization code was provided");
4883
5404
  if (pastedState && pastedState !== session.state) {
4884
- return err5(400, "oauth state did not match (possible CSRF) \u2014 aborting");
5405
+ return err6(400, "oauth state did not match (possible CSRF) \u2014 aborting");
4885
5406
  }
4886
5407
  code = splitCode;
4887
5408
  }
@@ -4891,7 +5412,7 @@ async function handleOAuthComplete(providerId, body, deps) {
4891
5412
  block = providerId === "claude" ? await exchangeClaude(code, session.codeVerifier, session.state, exchangeFetch) : await exchangeGemini(code, session.codeVerifier, exchangeFetch);
4892
5413
  } catch (exchangeError) {
4893
5414
  const reason = exchangeError instanceof Error ? exchangeError.message : "token exchange failed";
4894
- return err5(502, `oauth token exchange failed for '${providerId}': ${reason}`);
5415
+ return err6(502, `oauth token exchange failed for '${providerId}': ${reason}`);
4895
5416
  }
4896
5417
  deps.oauthSessions.consume(sessionId);
4897
5418
  const label = typeof body["label"] === "string" && body["label"].trim() ? body["label"].trim() : void 0;
@@ -4900,7 +5421,7 @@ async function handleOAuthComplete(providerId, body, deps) {
4900
5421
  return { status: 200, body: status ? { account: status } : { ok: true } };
4901
5422
  }
4902
5423
  async function exchangeClaude(code, codeVerifier, state, exchangeFetch) {
4903
- const result = await import_subscriptions8.claudeOAuth.exchangeCodeForTokens(
5424
+ const result = await import_subscriptions9.claudeOAuth.exchangeCodeForTokens(
4904
5425
  { authorizationCode: code, codeVerifier, state },
4905
5426
  exchangeFetch
4906
5427
  );
@@ -4916,7 +5437,7 @@ async function exchangeClaude(code, codeVerifier, state, exchangeFetch) {
4916
5437
  };
4917
5438
  }
4918
5439
  async function exchangeGemini(code, codeVerifier, exchangeFetch) {
4919
- const result = await import_subscriptions8.geminiOAuth.exchangeCodeForTokens(code, codeVerifier, exchangeFetch);
5440
+ const result = await import_subscriptions9.geminiOAuth.exchangeCodeForTokens(code, codeVerifier, exchangeFetch);
4920
5441
  const expiresAt = new Date(Date.now() + result.expiresIn * 1e3).toISOString();
4921
5442
  return {
4922
5443
  authMethod: "oauth",
@@ -5221,8 +5742,8 @@ function errBody(message) {
5221
5742
  return { error: { type: "admin_api_error", message } };
5222
5743
  }
5223
5744
  var defaultCommandRunner = (command) => new Promise((resolve10) => {
5224
- (0, import_node_child_process.exec)(command, { timeout: 18e4 }, (err8, _stdout, stderr) => {
5225
- if (err8) resolve10({ ok: false, error: stderr.trim() || err8.message });
5745
+ (0, import_node_child_process.exec)(command, { timeout: 18e4 }, (err9, _stdout, stderr) => {
5746
+ if (err9) resolve10({ ok: false, error: stderr.trim() || err9.message });
5226
5747
  else resolve10({ ok: true });
5227
5748
  });
5228
5749
  });
@@ -5268,8 +5789,8 @@ async function handleCliLaunch(cli, body, ctx) {
5268
5789
  providerId: typeof body["providerId"] === "string" ? body["providerId"] : void 0,
5269
5790
  model: typeof body["model"] === "string" ? body["model"] : void 0
5270
5791
  });
5271
- } catch (err8) {
5272
- return { status: 400, body: errBody(err8 instanceof Error ? err8.message : "no launch target") };
5792
+ } catch (err9) {
5793
+ return { status: 400, body: errBody(err9 instanceof Error ? err9.message : "no launch target") };
5273
5794
  }
5274
5795
  const id = (0, import_node_crypto7.randomUUID)();
5275
5796
  let leaseId2;
@@ -5297,9 +5818,9 @@ async function handleCliLaunch(cli, body, ctx) {
5297
5818
  } else {
5298
5819
  launch = await buildLaunchEnv(cli, ctx.llmConfig, target);
5299
5820
  }
5300
- } catch (err8) {
5301
- const status = err8 instanceof import_provider_proxy2.RouteLeaseError ? err8.status : 400;
5302
- return { status, body: errBody(err8 instanceof Error ? err8.message : "failed to build launch env") };
5821
+ } catch (err9) {
5822
+ const status = err9 instanceof import_provider_proxy2.RouteLeaseError ? err9.status : 400;
5823
+ return { status, body: errBody(err9 instanceof Error ? err9.message : "failed to build launch env") };
5303
5824
  }
5304
5825
  const cwd = typeof body["cwd"] === "string" && body["cwd"].trim() ? body["cwd"].trim() : void 0;
5305
5826
  const opener = ctx.opener ?? defaultTerminalOpener;
@@ -5327,9 +5848,9 @@ async function handleCliLaunch(cli, body, ctx) {
5327
5848
  onFailure: onSessionEnd
5328
5849
  });
5329
5850
  if (cleanup) openerCleanup = cleanup;
5330
- } catch (err8) {
5851
+ } catch (err9) {
5331
5852
  onSessionEnd();
5332
- return { status: 500, body: errBody(err8 instanceof Error ? err8.message : "failed to open terminal") };
5853
+ return { status: 500, body: errBody(err9 instanceof Error ? err9.message : "failed to open terminal") };
5333
5854
  }
5334
5855
  if (ended) {
5335
5856
  openerCleanup?.();
@@ -5570,7 +6091,7 @@ function classifySearchFailure(stage, code) {
5570
6091
  }
5571
6092
 
5572
6093
  // src/search/SearchAssembly.ts
5573
- var import_upstreamFetch9 = require("@omnicross/core/pipeline/upstreamFetch");
6094
+ var import_upstreamFetch11 = require("@omnicross/core/pipeline/upstreamFetch");
5574
6095
  var import_search = require("@omnicross/core/search");
5575
6096
  var import_api2 = require("@omnicross/core/search/api");
5576
6097
  var import_http2 = require("@omnicross/core/search/http");
@@ -5588,7 +6109,7 @@ function searchPolicyFrom(config) {
5588
6109
  };
5589
6110
  }
5590
6111
  function resolveSearchUpstreamDispatcher(url) {
5591
- return (0, import_upstreamFetch9.resolveUpstreamDispatcher)({ url });
6112
+ return (0, import_upstreamFetch11.resolveUpstreamDispatcher)({ url });
5592
6113
  }
5593
6114
  var searchUpstreamProxyConfig = createUpstreamProxyResolver();
5594
6115
  function resolveSearchUpstreamProxyConfig(url) {
@@ -5870,7 +6391,7 @@ async function handleSearchQuery(req, res, deps) {
5870
6391
  // src/admin/searchAdminView.ts
5871
6392
  var API_KEY_PROVIDERS = /* @__PURE__ */ new Set(["tavily", "jina", "zhipu", "z.ai"]);
5872
6393
  var BASIC_AUTH_PROVIDERS = /* @__PURE__ */ new Set(["searxng"]);
5873
- function isRecord5(value) {
6394
+ function isRecord7(value) {
5874
6395
  return value !== null && typeof value === "object" && !Array.isArray(value);
5875
6396
  }
5876
6397
  function redactSearchServerConfig(search) {
@@ -5920,13 +6441,13 @@ function resolveSecretField(entry, field, stored) {
5920
6441
  else delete entry[field];
5921
6442
  }
5922
6443
  function preserveSearchSecrets(incoming, current) {
5923
- if (!isRecord5(incoming)) return incoming;
6444
+ if (!isRecord7(incoming)) return incoming;
5924
6445
  const section = { ...incoming };
5925
6446
  const providersValue = section["providers"];
5926
- if (!isRecord5(providersValue)) return section;
6447
+ if (!isRecord7(providersValue)) return section;
5927
6448
  const providers = {};
5928
6449
  for (const [id, entryValue] of Object.entries(providersValue)) {
5929
- if (!isRecord5(entryValue)) {
6450
+ if (!isRecord7(entryValue)) {
5930
6451
  providers[id] = entryValue;
5931
6452
  continue;
5932
6453
  }
@@ -6004,7 +6525,7 @@ function parseKeyPolicyBody(body) {
6004
6525
  var ENDPOINTS = /* @__PURE__ */ new Set(["chat", "responses", "messages", "gemini"]);
6005
6526
  var TARGET_KINDS = /* @__PURE__ */ new Set(["account", "account-group", "account-pool", "provider"]);
6006
6527
  var FALLBACKS = /* @__PURE__ */ new Set(["next", "fail", "global"]);
6007
- function isRecord6(value) {
6528
+ function isRecord8(value) {
6008
6529
  return !!value && typeof value === "object" && !Array.isArray(value);
6009
6530
  }
6010
6531
  function nonBlank(value) {
@@ -6024,7 +6545,7 @@ function validateGatewayBindingsSegment(patch) {
6024
6545
  const ids = /* @__PURE__ */ new Set();
6025
6546
  raw.forEach((entry, index) => {
6026
6547
  const path2 = `bindings[${index}]`;
6027
- if (!isRecord6(entry)) {
6548
+ if (!isRecord8(entry)) {
6028
6549
  errors.push(`${path2} must be an object`);
6029
6550
  return;
6030
6551
  }
@@ -6053,12 +6574,12 @@ function validateGatewayBindingsSegment(patch) {
6053
6574
  } else if (entry.modelMappings.length > 100) {
6054
6575
  errors.push(`${path2}.modelMappings cannot contain more than 100 entries`);
6055
6576
  } else if (entry.modelMappings.some(
6056
- (mapping) => !isRecord6(mapping) || !nonBlank(mapping.source) || !nonBlank(mapping.target)
6577
+ (mapping) => !isRecord8(mapping) || !nonBlank(mapping.source) || !nonBlank(mapping.target)
6057
6578
  )) {
6058
6579
  errors.push(`${path2}.modelMappings must contain non-empty source and target strings`);
6059
6580
  }
6060
6581
  }
6061
- if (!isRecord6(entry.target) || !TARGET_KINDS.has(String(entry.target.kind))) {
6582
+ if (!isRecord8(entry.target) || !TARGET_KINDS.has(String(entry.target.kind))) {
6062
6583
  errors.push(`${path2}.target is invalid`);
6063
6584
  } else {
6064
6585
  if (!nonBlank(entry.target.providerId)) errors.push(`${path2}.target.providerId is required`);
@@ -6073,7 +6594,7 @@ function validateGatewayBindingsSegment(patch) {
6073
6594
  }
6074
6595
  }
6075
6596
  if (entry.modelMap !== void 0) {
6076
- if (!isRecord6(entry.modelMap) || Object.values(entry.modelMap).some((value) => typeof value !== "string")) {
6597
+ if (!isRecord8(entry.modelMap) || Object.values(entry.modelMap).some((value) => typeof value !== "string")) {
6077
6598
  errors.push(`${path2}.modelMap must contain string values`);
6078
6599
  }
6079
6600
  }
@@ -6374,7 +6895,12 @@ var PROVIDER_KEYS = {
6374
6895
  },
6375
6896
  kimi: { block: "kimi", accounts: "kimiAccounts", active: "activeKimiAccountId" },
6376
6897
  grok: { block: "grok", accounts: "grokAccounts", active: "activeGrokAccountId" },
6377
- copilot: { block: "copilot", accounts: "copilotAccounts", active: "activeCopilotAccountId" }
6898
+ copilot: { block: "copilot", accounts: "copilotAccounts", active: "activeCopilotAccountId" },
6899
+ antigravity: {
6900
+ block: "antigravity",
6901
+ accounts: "antigravityAccounts",
6902
+ active: "activeAntigravityAccountId"
6903
+ }
6378
6904
  };
6379
6905
  function clone(value) {
6380
6906
  return JSON.parse(JSON.stringify(value));
@@ -6896,7 +7422,7 @@ async function applyImport(packString, passphrase, mode, deps, parseProviderInpu
6896
7422
  }
6897
7423
 
6898
7424
  // src/admin/adminMigration.ts
6899
- function err6(status, message) {
7425
+ function err7(status, message) {
6900
7426
  return { status, body: { error: { type: "admin_api_error", message } } };
6901
7427
  }
6902
7428
  async function handleExport(body, deps) {
@@ -6906,30 +7432,30 @@ async function handleExport(body, deps) {
6906
7432
  return { status: 200, body: { pack, version: BUNDLE_VERSION } };
6907
7433
  } catch (error) {
6908
7434
  if (error instanceof WeakPassphraseError) {
6909
- return err6(400, error.message);
7435
+ return err7(400, error.message);
6910
7436
  }
6911
- return err6(500, "failed to build the migration pack");
7437
+ return err7(500, "failed to build the migration pack");
6912
7438
  }
6913
7439
  }
6914
7440
  async function handleImport(body, deps) {
6915
7441
  const blob = typeof body["blob"] === "string" ? body["blob"] : "";
6916
7442
  const passphrase = typeof body["passphrase"] === "string" ? body["passphrase"] : "";
6917
7443
  const mode = body["mode"] === "overwrite" ? "overwrite" : "merge";
6918
- if (!blob) return err6(400, "import requires { blob }");
7444
+ if (!blob) return err7(400, "import requires { blob }");
6919
7445
  try {
6920
7446
  const counts = await applyImport(blob, passphrase, mode, deps, deps.parseProviderInput);
6921
7447
  return { status: 200, body: counts };
6922
7448
  } catch (error) {
6923
7449
  if (error instanceof WeakPassphraseError) {
6924
- return err6(400, error.message);
7450
+ return err7(400, error.message);
6925
7451
  }
6926
- return err6(400, error instanceof Error ? error.message : "import failed");
7452
+ return err7(400, error instanceof Error ? error.message : "import failed");
6927
7453
  }
6928
7454
  }
6929
7455
 
6930
7456
  // src/admin/usagePricing.ts
6931
7457
  var import_usage = require("@omnicross/core/usage");
6932
- var err7 = (status, message) => ({
7458
+ var err8 = (status, message) => ({
6933
7459
  status,
6934
7460
  body: { error: { type: "admin_api_error", message } }
6935
7461
  });
@@ -6942,7 +7468,7 @@ function parseRange(query2) {
6942
7468
  const startTs = parseFiniteInt(query2.get("startTs"));
6943
7469
  const endTs = parseFiniteInt(query2.get("endTs"));
6944
7470
  if (startTs === null || endTs === null) {
6945
- return err7(400, "startTs and endTs are required finite-integer unix-millis query params");
7471
+ return err8(400, "startTs and endTs are required finite-integer unix-millis query params");
6946
7472
  }
6947
7473
  return { startTs, endTs };
6948
7474
  }
@@ -6967,14 +7493,14 @@ async function handleUsageGet(view, query2, deps) {
6967
7493
  case "timeseries": {
6968
7494
  const bucket = query2.get("bucket");
6969
7495
  if (bucket !== "hour" && bucket !== "day" && bucket !== "month") {
6970
- return err7(400, "bucket must be one of 'hour', 'day', 'month'");
7496
+ return err8(400, "bucket must be one of 'hour', 'day', 'month'");
6971
7497
  }
6972
7498
  const now = Date.now();
6973
7499
  const clamped = { startTs: range.startTs, endTs: Math.min(range.endTs, now) };
6974
7500
  if (clamped.startTs < clamped.endTs) {
6975
7501
  const projected = Math.ceil((clamped.endTs - clamped.startTs) / BUCKET_SPAN_MS[bucket]) + 1;
6976
7502
  if (projected > MAX_TIMESERIES_BUCKETS) {
6977
- return err7(
7503
+ return err8(
6978
7504
  400,
6979
7505
  `requested range projects ~${projected} '${bucket}' buckets (max ${MAX_TIMESERIES_BUCKETS}); narrow the range or use a coarser bucket`
6980
7506
  );
@@ -6997,7 +7523,7 @@ async function handleUsageGet(view, query2, deps) {
6997
7523
  };
6998
7524
  }
6999
7525
  default:
7000
- return err7(404, `unknown usage view '${view ?? ""}'`);
7526
+ return err8(404, `unknown usage view '${view ?? ""}'`);
7001
7527
  }
7002
7528
  }
7003
7529
  function poolKeyLabels(cfg) {
@@ -7046,7 +7572,7 @@ async function handlePricingList(deps) {
7046
7572
  async function handlePricingUpsert(body, deps) {
7047
7573
  const input = parsePricingEntryInput(body);
7048
7574
  if (!input) {
7049
- return err7(400, "invalid pricing entry (providerId, modelId, finite numeric inputPricePer1m/outputPricePer1m required)");
7575
+ return err8(400, "invalid pricing entry (providerId, modelId, finite numeric inputPricePer1m/outputPricePer1m required)");
7050
7576
  }
7051
7577
  const entry = await deps.pricingEngine.upsertManual(input);
7052
7578
  return { status: 200, body: { entry } };
@@ -7055,7 +7581,7 @@ async function handlePricingDelete(query2, deps) {
7055
7581
  const providerId = query2.get("providerId")?.trim() ?? "";
7056
7582
  const modelId = query2.get("modelId")?.trim() ?? "";
7057
7583
  if (!providerId || !modelId) {
7058
- return err7(400, "delete requires providerId and modelId query params");
7584
+ return err8(400, "delete requires providerId and modelId query params");
7059
7585
  }
7060
7586
  const deleted = await deps.pricingStore.delete(providerId, modelId);
7061
7587
  if (deleted) await deps.pricingEngine.invalidateCache();
@@ -7075,13 +7601,13 @@ async function handlePricingFetchLatest(deps) {
7075
7601
  }
7076
7602
  };
7077
7603
  } catch (e) {
7078
- return err7(502, `pricing-source fetch failed: ${e instanceof Error ? e.message : String(e)}`);
7604
+ return err8(502, `pricing-source fetch failed: ${e instanceof Error ? e.message : String(e)}`);
7079
7605
  }
7080
7606
  }
7081
7607
  async function handlePricingResolveConflicts(body, deps) {
7082
7608
  const raw = body["resolutions"];
7083
7609
  if (!Array.isArray(raw)) {
7084
- return err7(400, "resolve-conflicts requires { resolutions: [...] }");
7610
+ return err8(400, "resolve-conflicts requires { resolutions: [...] }");
7085
7611
  }
7086
7612
  const currentRows = await deps.pricingStore.getAll();
7087
7613
  const userEditedKeys = new Set(
@@ -7091,21 +7617,21 @@ async function handlePricingResolveConflicts(body, deps) {
7091
7617
  const pendingIncoming = /* @__PURE__ */ new Map();
7092
7618
  let staleCount = 0;
7093
7619
  for (const item of raw) {
7094
- if (!item || typeof item !== "object") return err7(400, "invalid resolution entry");
7620
+ if (!item || typeof item !== "object") return err8(400, "invalid resolution entry");
7095
7621
  const r = item;
7096
7622
  const action = r["action"];
7097
7623
  if (action !== "overwrite" && action !== "skip") {
7098
- return err7(400, "resolution action must be 'overwrite' or 'skip'");
7624
+ return err8(400, "resolution action must be 'overwrite' or 'skip'");
7099
7625
  }
7100
7626
  const providerId = typeof r["providerId"] === "string" && r["providerId"].trim() ? r["providerId"].trim() : "";
7101
7627
  const modelId = typeof r["modelId"] === "string" && r["modelId"].trim() ? r["modelId"].trim() : "";
7102
7628
  if (!providerId || !modelId) {
7103
- return err7(400, "each resolution requires top-level providerId and modelId");
7629
+ return err8(400, "each resolution requires top-level providerId and modelId");
7104
7630
  }
7105
7631
  const incoming = parsePricingEntryInput(r["incoming"]);
7106
- if (!incoming) return err7(400, "each resolution must echo a valid incoming pricing entry");
7632
+ if (!incoming) return err8(400, "each resolution must echo a valid incoming pricing entry");
7107
7633
  if (incoming.providerId !== providerId || incoming.modelId !== modelId) {
7108
- return err7(400, "resolution providerId/modelId must match the echoed incoming entry");
7634
+ return err8(400, "resolution providerId/modelId must match the echoed incoming entry");
7109
7635
  }
7110
7636
  const key = `${providerId}::${modelId}`;
7111
7637
  if (action === "overwrite" && !userEditedKeys.has(key)) {
@@ -7150,7 +7676,7 @@ function query(req) {
7150
7676
  }
7151
7677
  function allowanceProvider(value) {
7152
7678
  if (!value) return void 0;
7153
- return value === "claude" || value === "codex" || value === "kimi" || value === "opencodego" || value === "grok" || value === "copilot" || value === "gemini" ? value : null;
7679
+ return value === "claude" || value === "codex" || value === "kimi" || value === "opencodego" || value === "grok" || value === "copilot" || value === "gemini" || value === "antigravity" ? value : null;
7154
7680
  }
7155
7681
  async function handleAccountAllowanceApi(req, res, method, rest, service) {
7156
7682
  if (!service) return writeError2(res, 501, "account allowance service is not available");
@@ -7227,6 +7753,16 @@ async function handleAccountAllowanceApi(req, res, method, rest, service) {
7227
7753
  }
7228
7754
  return writeJson3(res, 200, { allowances: allowances2 });
7229
7755
  }
7756
+ if (requestedProvider === "antigravity") {
7757
+ if (!service.refreshAntigravity) {
7758
+ return writeError2(res, 501, "antigravity allowance refresh is not available");
7759
+ }
7760
+ const allowances2 = await service.refreshAntigravity(accountId);
7761
+ if (accountId && allowances2.length === 0) {
7762
+ return writeError2(res, 404, `Antigravity account '${accountId}' not found`);
7763
+ }
7764
+ return writeJson3(res, 200, { allowances: allowances2 });
7765
+ }
7230
7766
  if (requestedProvider === "gemini") {
7231
7767
  if (!service.refreshGemini) {
7232
7768
  return writeError2(res, 501, "gemini allowance refresh is not available");
@@ -7381,7 +7917,7 @@ async function handleAdminApi(req, res, path2, deps) {
7381
7917
  case "server":
7382
7918
  return await handleServer(req, res, method, deps);
7383
7919
  case "images":
7384
- return await handleImages(res, method, rest, deps);
7920
+ return await handleImages(req, res, method, rest, deps);
7385
7921
  case "search":
7386
7922
  return await handleSearchAdmin(req, res, method, rest, deps);
7387
7923
  case "accounts":
@@ -7407,8 +7943,8 @@ async function handleAdminApi(req, res, path2, deps) {
7407
7943
  default:
7408
7944
  return writeJsonError(res, 404, `unknown admin resource '${resource}'`);
7409
7945
  }
7410
- } catch (err8) {
7411
- writeJsonError(res, 500, err8 instanceof Error ? err8.message : String(err8));
7946
+ } catch (err9) {
7947
+ writeJsonError(res, 500, err9 instanceof Error ? err9.message : String(err9));
7412
7948
  }
7413
7949
  }
7414
7950
  function requestQuery(req) {
@@ -7583,7 +8119,7 @@ async function handleDiscoverModels(res, id, cfg) {
7583
8119
  const headers = { Accept: "application/json" };
7584
8120
  if (resolvedKey) headers["Authorization"] = `Bearer ${resolvedKey}`;
7585
8121
  Object.assign(headers, expandRowExtraHeaders(row));
7586
- const response = await (0, import_upstreamFetch10.fetchUpstream)(url, { method: "GET", headers }, { providerId: "byo" });
8122
+ const response = await (0, import_upstreamFetch12.fetchUpstream)(url, { method: "GET", headers }, { providerId: "byo" });
7587
8123
  if (!response.ok) {
7588
8124
  const text = await response.text().catch(() => "");
7589
8125
  let message = text.slice(0, 300);
@@ -7600,8 +8136,8 @@ async function handleDiscoverModels(res, id, cfg) {
7600
8136
  const data = await response.json();
7601
8137
  const models = Array.isArray(data?.data) ? data.data.map((m) => typeof m?.id === "string" ? m.id : "").filter((m) => m.length > 0) : [];
7602
8138
  return writeJson4(res, 200, { models });
7603
- } catch (err8) {
7604
- const message = err8 instanceof Error ? err8.message : String(err8);
8139
+ } catch (err9) {
8140
+ const message = err9 instanceof Error ? err9.message : String(err9);
7605
8141
  return writeJson4(res, 200, { models: [], error: `discovery failed: ${message}` });
7606
8142
  }
7607
8143
  }
@@ -7643,7 +8179,7 @@ async function handleTestModel(req, res, id, cfg) {
7643
8179
  Object.assign(headers, expandRowExtraHeaders(row));
7644
8180
  const startedAt = Date.now();
7645
8181
  try {
7646
- const response = await (0, import_upstreamFetch10.fetchUpstream)(
8182
+ const response = await (0, import_upstreamFetch12.fetchUpstream)(
7647
8183
  url,
7648
8184
  { method: "POST", headers, body: JSON.stringify(payload) },
7649
8185
  { providerId: "byo" }
@@ -7665,8 +8201,8 @@ async function handleTestModel(req, res, id, cfg) {
7665
8201
  latencyMs,
7666
8202
  sample: extractSampleText(text, row.apiFormat)
7667
8203
  });
7668
- } catch (err8) {
7669
- const message = err8 instanceof Error ? err8.message : String(err8);
8204
+ } catch (err9) {
8205
+ const message = err9 instanceof Error ? err9.message : String(err9);
7670
8206
  return writeJson4(res, 200, { ok: false, latencyMs: Date.now() - startedAt, message });
7671
8207
  }
7672
8208
  }
@@ -8251,8 +8787,8 @@ function imageConfigurationAuditFields(previous, next) {
8251
8787
  const after = next ?? import_outbound_api5.DEFAULT_IMAGES_SERVER_CONFIG;
8252
8788
  const fields = [];
8253
8789
  if (before.enabled !== after.enabled) fields.push("enablement");
8254
- if (before.provider !== after.provider) fields.push("provider");
8255
- if (before.defaultModel !== after.defaultModel || !sameConfigValue(before.modelAliases, after.modelAliases)) fields.push("model");
8790
+ if (!sameConfigValue(before.models, after.models)) fields.push("provider");
8791
+ if (before.defaultModel !== after.defaultModel || !sameConfigValue(before.aliases, after.aliases) || !sameConfigValue(before.codex, after.codex)) fields.push("model");
8256
8792
  if (!sameConfigValue(before.account, after.account)) fields.push("account");
8257
8793
  if (!sameConfigValue(before.queue, after.queue)) fields.push("queue");
8258
8794
  if (!sameConfigValue(before.temporary, after.temporary)) fields.push("temporary");
@@ -8456,6 +8992,12 @@ async function handleAccounts(req, res, method, rest, deps) {
8456
8992
  deps.accountAllowanceService
8457
8993
  );
8458
8994
  }
8995
+ if (method === "GET" && rest[0] === "antigravity" && rest[1] === "models") {
8996
+ const result = await handleAntigravityModelsRoute({
8997
+ resolveAntigravityAccessToken: deps.resolveAntigravityAccessToken ?? (async () => null)
8998
+ });
8999
+ return writeJson4(res, result.status, result.body);
9000
+ }
8459
9001
  if (method === "GET" && rest.length === 0) {
8460
9002
  const accounts = await deps.subscriptionAccounts.listAll();
8461
9003
  const providerAccounts = await deps.subscriptionTokenWriter.listSanitizedAccounts();
@@ -8481,12 +9023,12 @@ async function handleAccounts(req, res, method, rest, deps) {
8481
9023
  }
8482
9024
  return writeJson4(res, 200, { ok: true, affected: result.affected });
8483
9025
  }
8484
- if (method === "GET" && (rest[0] === "codex" || rest[0] === "kimi" || rest[0] === "grok" || rest[0] === "copilot") && rest[1] === "oauth" && rest[3] === "status") {
8485
- const result = rest[0] === "codex" ? handleCodexOAuthStatus(rest[2], deps) : rest[0] === "kimi" ? handleKimiOAuthStatus(rest[2], deps) : rest[0] === "grok" ? handleGrokOAuthStatus(rest[2], deps) : handleCopilotOAuthStatus(rest[2], deps);
9026
+ if (method === "GET" && (rest[0] === "codex" || rest[0] === "kimi" || rest[0] === "grok" || rest[0] === "copilot" || rest[0] === "antigravity") && rest[1] === "oauth" && rest[3] === "status") {
9027
+ const result = rest[0] === "codex" ? handleCodexOAuthStatus(rest[2], deps) : rest[0] === "kimi" ? handleKimiOAuthStatus(rest[2], deps) : rest[0] === "grok" ? handleGrokOAuthStatus(rest[2], deps) : rest[0] === "copilot" ? handleCopilotOAuthStatus(rest[2], deps) : handleAntigravityOAuthStatus(rest[2], deps);
8486
9028
  return writeJson4(res, result.status, result.body);
8487
9029
  }
8488
- if (method === "DELETE" && (rest[0] === "codex" || rest[0] === "kimi" || rest[0] === "grok" || rest[0] === "copilot") && rest[1] === "oauth" && rest[2]) {
8489
- const result = rest[0] === "codex" ? handleCodexOAuthCancel(rest[2], deps) : rest[0] === "kimi" ? handleKimiOAuthCancel(rest[2], deps) : rest[0] === "grok" ? handleGrokOAuthCancel(rest[2], deps) : handleCopilotOAuthCancel(rest[2], deps);
9030
+ if (method === "DELETE" && (rest[0] === "codex" || rest[0] === "kimi" || rest[0] === "grok" || rest[0] === "copilot" || rest[0] === "antigravity") && rest[1] === "oauth" && rest[2]) {
9031
+ const result = rest[0] === "codex" ? handleCodexOAuthCancel(rest[2], deps) : rest[0] === "kimi" ? handleKimiOAuthCancel(rest[2], deps) : rest[0] === "grok" ? handleGrokOAuthCancel(rest[2], deps) : rest[0] === "copilot" ? handleCopilotOAuthCancel(rest[2], deps) : handleAntigravityOAuthCancel(rest[2], deps);
8490
9032
  return writeJson4(res, result.status, result.body);
8491
9033
  }
8492
9034
  if (method === "GET" && rest.length === 3 && rest[2] === "diagnostics") {
@@ -8556,6 +9098,10 @@ async function handleAccounts(req, res, method, rest, deps) {
8556
9098
  const result2 = await handleCopilotOAuthStart(deps, body2["enterpriseUrl"]);
8557
9099
  return writeJson4(res, result2.status, result2.body);
8558
9100
  }
9101
+ if (providerId === "antigravity") {
9102
+ const result2 = handleAntigravityOAuthStart(deps);
9103
+ return writeJson4(res, result2.status, result2.body);
9104
+ }
8559
9105
  const result = handleOAuthStart(providerId, deps);
8560
9106
  return writeJson4(res, result.status, result.body);
8561
9107
  }
@@ -8918,7 +9464,41 @@ function imageEndpointUrls(base) {
8918
9464
  edits: `${base}/v1/images/edits`
8919
9465
  }) : null;
8920
9466
  }
8921
- async function handleImages(res, method, rest, deps) {
9467
+ function imageProviderEvidence(images, capabilities) {
9468
+ const evidenceAt = safeStatusTimestamp(capabilities?.oldestEvidenceAt);
9469
+ const resolvedAt = safeStatusTimestamp(capabilities?.resolvedAt);
9470
+ if (evidenceAt === void 0 || resolvedAt === void 0) return null;
9471
+ const expiresAt = evidenceAt <= Number.MAX_SAFE_INTEGER - images.evidenceTtlMs ? evidenceAt + images.evidenceTtlMs : void 0;
9472
+ return Object.freeze({
9473
+ verifiedAt: evidenceAt,
9474
+ ageMs: Math.max(0, resolvedAt - evidenceAt),
9475
+ ...expiresAt !== void 0 ? { expiresAt } : {}
9476
+ });
9477
+ }
9478
+ async function handleImagesVerifyLive(req, res, deps) {
9479
+ const verifier = deps.imageLiveVerifier;
9480
+ if (!verifier) {
9481
+ return writeJsonError(res, 501, "Images live verification is not available");
9482
+ }
9483
+ const serverConfig = await (0, import_outbound_api5.loadServerConfig)(deps.settingsStore);
9484
+ const images = serverConfig.images ?? import_outbound_api5.DEFAULT_IMAGES_SERVER_CONFIG;
9485
+ req.resume();
9486
+ const controller = new AbortController();
9487
+ req.on("close", () => controller.abort());
9488
+ const result = await verifier.verifyLive(images, controller.signal);
9489
+ const antigravityRouted = Object.values(images.models).includes("antigravity-subscription");
9490
+ return writeJson4(res, 200, {
9491
+ ...result,
9492
+ ...antigravityRouted ? { antigravityDeferred: true } : {}
9493
+ });
9494
+ }
9495
+ async function handleImages(req, res, method, rest, deps) {
9496
+ if (rest.length === 1 && rest[0] === "verify-live") {
9497
+ if (method !== "POST") {
9498
+ return writeJsonError(res, 405, `method ${method} not allowed on Images verify-live`);
9499
+ }
9500
+ return handleImagesVerifyLive(req, res, deps);
9501
+ }
8922
9502
  if (rest.length !== 1 || rest[0] !== "capabilities") {
8923
9503
  return writeJsonError(res, 404, "unknown Images admin resource");
8924
9504
  }
@@ -8933,14 +9513,14 @@ async function handleImages(res, method, rest, deps) {
8933
9513
  const capability = await reader.inspectCapability(IMAGE_ADMIN_STATUS_TENANT);
8934
9514
  const resources = safeRuntimeResources(reader.resourceStatus());
8935
9515
  const outbound = deps.outboundApiServer.getStatus();
8936
- const evidenceAt = safeStatusTimestamp(capability.capabilities?.oldestEvidenceAt);
8937
- const resolvedAt = safeStatusTimestamp(capability.capabilities?.resolvedAt);
8938
- const expiresAt = evidenceAt !== void 0 && evidenceAt <= Number.MAX_SAFE_INTEGER - images.evidenceTtlMs ? evidenceAt + images.evidenceTtlMs : void 0;
8939
- const evidence = evidenceAt !== void 0 && resolvedAt !== void 0 ? Object.freeze({
8940
- verifiedAt: evidenceAt,
8941
- ageMs: Math.max(0, resolvedAt - evidenceAt),
8942
- ...expiresAt !== void 0 ? { expiresAt } : {}
8943
- }) : null;
9516
+ const evidence = imageProviderEvidence(images, capability.capabilities);
9517
+ const providers = (capability.providers ?? []).map((provider) => Object.freeze({
9518
+ providerId: provider.providerId,
9519
+ available: provider.available === true,
9520
+ reason: provider.available ? null : safeImageCapabilityReason(provider.reason),
9521
+ models: Object.freeze([...provider.models]),
9522
+ evidence: imageProviderEvidence(images, provider.capabilities)
9523
+ }));
8944
9524
  const draining = lifecycle.draining.map((generation) => Object.freeze({
8945
9525
  generationId: safeImageGenerationId(generation.generationId),
8946
9526
  enabled: generation.enabled,
@@ -8950,7 +9530,7 @@ async function handleImages(res, method, rest, deps) {
8950
9530
  return writeJson4(res, 200, {
8951
9531
  configured: {
8952
9532
  enabled: images.enabled,
8953
- provider: images.provider,
9533
+ provider: images.models[images.defaultModel] ?? "codex-subscription",
8954
9534
  model: images.defaultModel,
8955
9535
  remoteUrlsEnabled: images.remote.enabled,
8956
9536
  referenceTtlMs: images.references.ttlMs
@@ -8961,6 +9541,7 @@ async function handleImages(res, method, rest, deps) {
8961
9541
  evidence,
8962
9542
  features: safeCapabilityValues(capability.capabilities, images.defaultModel)
8963
9543
  },
9544
+ providers,
8964
9545
  runtime: {
8965
9546
  disposed: lifecycle.disposed,
8966
9547
  generationId: safeImageGenerationId(lifecycle.current.generationId),
@@ -9050,12 +9631,12 @@ async function handlePlayground(req, res, method, deps) {
9050
9631
  const payload = body["body"];
9051
9632
  const status = deps.outboundApiServer.getStatus();
9052
9633
  if (!status.running || !status.port) return writeJsonError(res, 503, "outbound server not running");
9053
- const path2 = resolvePlaygroundPath(endpoint, isRecord7(payload) ? payload : {});
9634
+ const path2 = resolvePlaygroundPath(endpoint, isRecord9(payload) ? payload : {});
9054
9635
  if (!path2) return writeJsonError(res, 400, `unknown endpoint '${endpoint}'`);
9055
9636
  const upstreamBody = typeof payload === "string" ? payload : JSON.stringify(payload ?? {});
9056
9637
  await proxyToOutbound(res, status.port, path2, key, upstreamBody);
9057
9638
  }
9058
- function isRecord7(v) {
9639
+ function isRecord9(v) {
9059
9640
  return !!v && typeof v === "object" && !Array.isArray(v);
9060
9641
  }
9061
9642
  function proxyToOutbound(res, outboundPort, path2, key, body) {
@@ -9084,8 +9665,8 @@ function proxyToOutbound(res, outboundPort, path2, key, body) {
9084
9665
  });
9085
9666
  }
9086
9667
  );
9087
- upstream.on("error", (err8) => {
9088
- if (!res.headersSent) writeJsonError(res, 502, `playground proxy failed: ${err8.message}`);
9668
+ upstream.on("error", (err9) => {
9669
+ if (!res.headersSent) writeJsonError(res, 502, `playground proxy failed: ${err9.message}`);
9089
9670
  else res.end();
9090
9671
  resolve10();
9091
9672
  });
@@ -9191,7 +9772,7 @@ async function handleUiStatic(req, res, urlPath, uiDist) {
9191
9772
  }
9192
9773
 
9193
9774
  // src/admin/version.ts
9194
- var DAEMON_VERSION = true ? "0.4.2" : "0.0.0-dev";
9775
+ var DAEMON_VERSION = true ? "0.4.4" : "0.0.0-dev";
9195
9776
 
9196
9777
  // src/admin/AdminServer.ts
9197
9778
  var LOOPBACK_ADDR = "127.0.0.1";
@@ -9234,13 +9815,13 @@ var AdminServer = class {
9234
9815
  const server = import_node_http2.default.createServer((req, res) => {
9235
9816
  this.onRequest(req, res);
9236
9817
  });
9237
- const onError = (err8) => {
9238
- if (err8.code === "EADDRINUSE" && port !== 0) {
9818
+ const onError = (err9) => {
9819
+ if (err9.code === "EADDRINUSE" && port !== 0) {
9239
9820
  server.removeListener("error", onError);
9240
9821
  this.listen(bindAddr, 0).then(resolve10, reject);
9241
9822
  return;
9242
9823
  }
9243
- reject(err8);
9824
+ reject(err9);
9244
9825
  };
9245
9826
  server.on("error", onError);
9246
9827
  server.listen(port, bindAddr, () => {
@@ -9258,8 +9839,8 @@ var AdminServer = class {
9258
9839
  }
9259
9840
  /** Per-request handler: auth gate (when a token is set) → routing. */
9260
9841
  onRequest(req, res) {
9261
- void this.dispatch(req, res).catch((err8) => {
9262
- const message = err8 instanceof Error ? err8.message : String(err8);
9842
+ void this.dispatch(req, res).catch((err9) => {
9843
+ const message = err9 instanceof Error ? err9.message : String(err9);
9263
9844
  this.deps.logger.error("[AdminServer] unhandled error:", message);
9264
9845
  if (!res.headersSent) {
9265
9846
  res.writeHead(500, { "Content-Type": "application/json" });
@@ -9482,7 +10063,10 @@ var HTML_HEADERS = {
9482
10063
  function pageHtml(message) {
9483
10064
  return `<!doctype html><meta charset="utf-8"><title>omnicross login</title><body style="font-family:sans-serif;padding:2rem"><h2>${message}</h2><p>You can close this window and return to the terminal.</p></body>`;
9484
10065
  }
9485
- function awaitLoopbackCode(expectedState, timeoutMs = DEFAULT_TIMEOUT_MS, signal) {
10066
+ function awaitLoopbackCode(expectedState, timeoutMs = DEFAULT_TIMEOUT_MS, signal, binding = {}) {
10067
+ const port = binding.port ?? LOOPBACK_PORT;
10068
+ const callbackPath = binding.path ?? CALLBACK_PATH;
10069
+ const label = binding.label ?? "codex";
9486
10070
  return new Promise((resolve10, reject) => {
9487
10071
  let settled = false;
9488
10072
  const finish = (server2, fn) => {
@@ -9493,8 +10077,8 @@ function awaitLoopbackCode(expectedState, timeoutMs = DEFAULT_TIMEOUT_MS, signal
9493
10077
  server2.close();
9494
10078
  };
9495
10079
  const server = (0, import_node_http3.createServer)((req, res) => {
9496
- const url = new URL(req.url ?? "", `http://${LOOPBACK_HOST}:${LOOPBACK_PORT}`);
9497
- if (url.pathname !== CALLBACK_PATH) {
10080
+ const url = new URL(req.url ?? "", `http://${LOOPBACK_HOST}:${port}`);
10081
+ if (url.pathname !== callbackPath) {
9498
10082
  res.writeHead(404, HTML_HEADERS);
9499
10083
  res.end(pageHtml("Not found"));
9500
10084
  return;
@@ -9523,25 +10107,25 @@ function awaitLoopbackCode(expectedState, timeoutMs = DEFAULT_TIMEOUT_MS, signal
9523
10107
  return;
9524
10108
  }
9525
10109
  signal?.addEventListener("abort", abort, { once: true });
9526
- server.on("error", (err8) => {
10110
+ server.on("error", (err9) => {
9527
10111
  if (settled) return;
9528
10112
  settled = true;
9529
10113
  clearTimeout(timer);
9530
- if (err8.code === "EADDRINUSE") {
10114
+ if (err9.code === "EADDRINUSE") {
9531
10115
  reject(
9532
10116
  new Error(
9533
- `login: cannot bind ${LOOPBACK_HOST}:${LOOPBACK_PORT} (address in use) \u2014 another codex login or process is holding the port`
10117
+ `login: cannot bind ${LOOPBACK_HOST}:${port} (address in use) \u2014 another ${label} login or process is holding the port`
9534
10118
  )
9535
10119
  );
9536
10120
  } else {
9537
- reject(err8);
10121
+ reject(err9);
9538
10122
  }
9539
10123
  });
9540
10124
  const timer = setTimeout(() => {
9541
10125
  finish(server, () => reject(new Error(`login: timed out after ${Math.round(timeoutMs / 1e3)}s waiting for the callback`)));
9542
10126
  }, timeoutMs);
9543
10127
  if (typeof timer.unref === "function") timer.unref();
9544
- server.listen(LOOPBACK_PORT, LOOPBACK_HOST);
10128
+ server.listen(port, LOOPBACK_HOST);
9545
10129
  });
9546
10130
  }
9547
10131
 
@@ -9611,7 +10195,7 @@ function createPoolKeysLoader(getProviderRow, autoDisabled) {
9611
10195
 
9612
10196
  // src/allowance/ProviderKeyQuotaService.ts
9613
10197
  var import_core4 = require("@omnicross/core");
9614
- var import_upstreamFetch11 = require("@omnicross/core/pipeline/upstreamFetch");
10198
+ var import_upstreamFetch13 = require("@omnicross/core/pipeline/upstreamFetch");
9615
10199
 
9616
10200
  // src/allowance/ProviderKeyQuota.ts
9617
10201
  var MINUTE_MS3 = 6e4;
@@ -9640,11 +10224,11 @@ function isoInstant3(value) {
9640
10224
  }
9641
10225
  return void 0;
9642
10226
  }
9643
- function secondsUntil8(instant, now) {
10227
+ function secondsUntil9(instant, now) {
9644
10228
  if (!instant) return void 0;
9645
10229
  return Math.max(0, Math.floor((Date.parse(instant) - now) / 1e3));
9646
10230
  }
9647
- function isRecord8(value) {
10231
+ function isRecord10(value) {
9648
10232
  return !!value && typeof value === "object" && !Array.isArray(value);
9649
10233
  }
9650
10234
  function detectProviderKeyQuotaAdapter(baseUrl) {
@@ -9711,17 +10295,17 @@ function zaiWindowIdLabel(durationMs) {
9711
10295
  return { id: "quota", label: "Quota" };
9712
10296
  }
9713
10297
  function parseZaiQuotaPayload(payload, now) {
9714
- if (!isRecord8(payload)) return null;
9715
- const data = isRecord8(payload["data"]) ? payload["data"] : payload;
10298
+ if (!isRecord10(payload)) return null;
10299
+ const data = isRecord10(payload["data"]) ? payload["data"] : payload;
9716
10300
  if (payload["success"] === false) return null;
9717
10301
  const limits = Array.isArray(data["limits"]) ? data["limits"] : [];
9718
10302
  const byWindow = /* @__PURE__ */ new Map();
9719
10303
  for (const raw of limits) {
9720
- if (!isRecord8(raw)) continue;
10304
+ if (!isRecord10(raw)) continue;
9721
10305
  const item = raw;
9722
10306
  if (item.type === void 0) continue;
9723
10307
  const details = raw["usageDetails"];
9724
- if (Array.isArray(details) && details.some((d) => isRecord8(d) && d["modelCode"] === "zread")) {
10308
+ if (Array.isArray(details) && details.some((d) => isRecord10(d) && d["modelCode"] === "zread")) {
9725
10309
  continue;
9726
10310
  }
9727
10311
  const durationMs = zaiWindowDurationMs(item);
@@ -9740,7 +10324,7 @@ function parseZaiQuotaPayload(payload, now) {
9740
10324
  usedPercent,
9741
10325
  ...durationMs !== void 0 ? { windowMinutes: Math.round(durationMs / MINUTE_MS3) } : {},
9742
10326
  ...resetsAt !== void 0 ? { resetsAt } : {},
9743
- remainingSeconds: secondsUntil8(resetsAt, now),
10327
+ remainingSeconds: secondsUntil9(resetsAt, now),
9744
10328
  state: "fresh"
9745
10329
  };
9746
10330
  const existing = byWindow.get(id);
@@ -9754,7 +10338,7 @@ function parseZaiQuotaPayload(payload, now) {
9754
10338
  var MINIMAX_STATUS_EXHAUSTED = 2;
9755
10339
  var MINIMAX_SHARED_BUCKET = "general";
9756
10340
  function parseMiniMaxBucket(value) {
9757
- if (!isRecord8(value)) return null;
10341
+ if (!isRecord10(value)) return null;
9758
10342
  const modelName = typeof value["model_name"] === "string" ? value["model_name"].trim() : "";
9759
10343
  if (!modelName) return null;
9760
10344
  const instant = (v) => {
@@ -9781,14 +10365,14 @@ function minimaxWindow(id, label, windowMinutes, resetsAtMs, remainingPercent, s
9781
10365
  usedPercent,
9782
10366
  ...windowMinutes !== void 0 ? { windowMinutes } : {},
9783
10367
  ...resetsAt !== void 0 ? { resetsAt } : {},
9784
- remainingSeconds: secondsUntil8(resetsAt, now),
10368
+ remainingSeconds: secondsUntil9(resetsAt, now),
9785
10369
  state: usedPercent !== null ? "fresh" : "unavailable"
9786
10370
  };
9787
10371
  }
9788
10372
  function parseMiniMaxTokenPlanPayload(payload, now) {
9789
- if (!isRecord8(payload)) return null;
10373
+ if (!isRecord10(payload)) return null;
9790
10374
  const baseResp = payload["base_resp"];
9791
- if (!isRecord8(baseResp) || baseResp["status_code"] !== 0) return null;
10375
+ if (!isRecord10(baseResp) || baseResp["status_code"] !== 0) return null;
9792
10376
  const buckets = Array.isArray(payload["model_remains"]) ? payload["model_remains"] : [];
9793
10377
  let general = null;
9794
10378
  for (const raw of buckets) {
@@ -9821,11 +10405,11 @@ function parseMiniMaxTokenPlanPayload(payload, now) {
9821
10405
  ];
9822
10406
  }
9823
10407
  function parseUmansUsagePayload(payload, now) {
9824
- if (!isRecord8(payload)) return null;
9825
- const limits = isRecord8(payload["limits"]) ? payload["limits"] : void 0;
9826
- const requests = limits && isRecord8(limits["requests"]) ? limits["requests"] : void 0;
9827
- const usage = isRecord8(payload["usage"]) ? payload["usage"] : void 0;
9828
- const window = isRecord8(payload["window"]) ? payload["window"] : void 0;
10408
+ if (!isRecord10(payload)) return null;
10409
+ const limits = isRecord10(payload["limits"]) ? payload["limits"] : void 0;
10410
+ const requests = limits && isRecord10(limits["requests"]) ? limits["requests"] : void 0;
10411
+ const usage = isRecord10(payload["usage"]) ? payload["usage"] : void 0;
10412
+ const window = isRecord10(payload["window"]) ? payload["window"] : void 0;
9829
10413
  const hardCap = finiteNumber5(requests?.["hard_cap"]);
9830
10414
  const softLimit = finiteNumber5(requests?.["limit"]);
9831
10415
  const requestsInWindow = finiteNumber5(usage?.["requests_in_window"]);
@@ -9846,15 +10430,15 @@ function parseUmansUsagePayload(payload, now) {
9846
10430
  usedPercent,
9847
10431
  windowMinutes: 5 * 60,
9848
10432
  ...resetsAt !== void 0 ? { resetsAt } : {},
9849
- remainingSeconds: secondsUntil8(resetsAt, now),
10433
+ remainingSeconds: secondsUntil9(resetsAt, now),
9850
10434
  state: "fresh"
9851
10435
  }
9852
10436
  ];
9853
10437
  }
9854
10438
  function parseSyntheticQuotasPayload(payload, now) {
9855
- if (!isRecord8(payload)) return null;
9856
- const fiveHour = isRecord8(payload["rollingFiveHourLimit"]) ? payload["rollingFiveHourLimit"] : void 0;
9857
- const weekly = isRecord8(payload["weeklyTokenLimit"]) ? payload["weeklyTokenLimit"] : void 0;
10439
+ if (!isRecord10(payload)) return null;
10440
+ const fiveHour = isRecord10(payload["rollingFiveHourLimit"]) ? payload["rollingFiveHourLimit"] : void 0;
10441
+ const weekly = isRecord10(payload["weeklyTokenLimit"]) ? payload["weeklyTokenLimit"] : void 0;
9858
10442
  const windows = [];
9859
10443
  if (fiveHour) {
9860
10444
  const max = finiteNumber5(fiveHour["max"]);
@@ -9868,7 +10452,7 @@ function parseSyntheticQuotasPayload(payload, now) {
9868
10452
  usedPercent,
9869
10453
  windowMinutes: 5 * 60,
9870
10454
  ...resetsAt !== void 0 ? { resetsAt } : {},
9871
- remainingSeconds: secondsUntil8(resetsAt, now),
10455
+ remainingSeconds: secondsUntil9(resetsAt, now),
9872
10456
  state: usedPercent !== null || resetsAt ? "fresh" : "unavailable"
9873
10457
  });
9874
10458
  }
@@ -9883,7 +10467,7 @@ function parseSyntheticQuotasPayload(payload, now) {
9883
10467
  usedPercent,
9884
10468
  windowMinutes: 7 * 24 * 60,
9885
10469
  ...resetsAt !== void 0 ? { resetsAt } : {},
9886
- remainingSeconds: secondsUntil8(resetsAt, now),
10470
+ remainingSeconds: secondsUntil9(resetsAt, now),
9887
10471
  state: usedPercent !== null || resetsAt ? "fresh" : "unavailable"
9888
10472
  });
9889
10473
  }
@@ -9895,12 +10479,12 @@ var CLINE_WINDOW_CONFIG = {
9895
10479
  monthly: { id: "thirty-day", label: "30 days", minutes: 30 * 24 * 60 }
9896
10480
  };
9897
10481
  function parseClinePassUsageLimitsPayload(payload, now) {
9898
- if (!isRecord8(payload)) return null;
9899
- const data = isRecord8(payload["data"]) ? payload["data"] : payload;
10482
+ if (!isRecord10(payload)) return null;
10483
+ const data = isRecord10(payload["data"]) ? payload["data"] : payload;
9900
10484
  const limits = Array.isArray(data["limits"]) ? data["limits"] : [];
9901
10485
  const windows = [];
9902
10486
  for (const raw of limits) {
9903
- if (!isRecord8(raw)) continue;
10487
+ if (!isRecord10(raw)) continue;
9904
10488
  const config = CLINE_WINDOW_CONFIG[typeof raw["type"] === "string" ? raw["type"] : ""];
9905
10489
  if (!config) continue;
9906
10490
  const usedPercent = finitePercent4(raw["percentUsed"]);
@@ -9913,7 +10497,7 @@ function parseClinePassUsageLimitsPayload(payload, now) {
9913
10497
  usedPercent,
9914
10498
  windowMinutes: config.minutes,
9915
10499
  ...resetsAt !== void 0 ? { resetsAt } : {},
9916
- remainingSeconds: secondsUntil8(resetsAt, now),
10500
+ remainingSeconds: secondsUntil9(resetsAt, now),
9917
10501
  state: "fresh"
9918
10502
  });
9919
10503
  }
@@ -9952,7 +10536,7 @@ function rowKeyEntries(row) {
9952
10536
  return [];
9953
10537
  }
9954
10538
  var ProviderKeyQuotaService = class {
9955
- constructor(box, fetchImpl = (url, init) => (0, import_upstreamFetch11.fetchUpstream)(url, init, { redactBodies: true }), now = Date.now) {
10539
+ constructor(box, fetchImpl = (url, init) => (0, import_upstreamFetch13.fetchUpstream)(url, init, { redactBodies: true }), now = Date.now) {
9956
10540
  this.box = box;
9957
10541
  this.fetchImpl = fetchImpl;
9958
10542
  this.now = now;
@@ -10088,7 +10672,7 @@ function defaultBillingDir(configPath) {
10088
10672
  // src/image-generation/ImageDoctorService.ts
10089
10673
  var import_image_generation = require("@omnicross/core/image-generation");
10090
10674
  var import_outbound_api7 = require("@omnicross/core/outbound-api");
10091
- var import_subscriptions9 = require("@omnicross/subscriptions");
10675
+ var import_subscriptions10 = require("@omnicross/subscriptions");
10092
10676
 
10093
10677
  // src/image-generation/FileCodexImageCapabilityEvidenceSource.ts
10094
10678
  var import_node_crypto13 = require("crypto");
@@ -10526,16 +11110,16 @@ function createImageDoctorService(options) {
10526
11110
  paths,
10527
11111
  ttlMs: config.evidenceTtlMs
10528
11112
  }));
10529
- const createLiveVerifier = options.createLiveVerifier ?? ((strategy, config) => (0, import_subscriptions9.createCodexImageLiveVerifier)({
11113
+ const createLiveVerifier = options.createLiveVerifier ?? ((strategy, config) => (0, import_subscriptions10.createCodexImageLiveVerifier)({
10530
11114
  authStrategy: strategy,
10531
11115
  generationTimeoutMs: config.queue.generationTimeoutMs
10532
11116
  }));
10533
- const readAccount = async () => {
10534
- const codex = (await options.subscriptionAccounts.listAll()).find((entry) => entry.providerId === "codex");
11117
+ const readAccount = async (providerId) => {
11118
+ const entry = (await options.subscriptionAccounts.listAll()).find((candidate) => candidate.providerId === providerId);
10535
11119
  return Object.freeze({
10536
- present: codex !== void 0,
10537
- usable: codex?.credentialStatus.ok === true,
10538
- reason: codex === void 0 ? "missing" : codex.credentialStatus.ok ? "ready" : "unavailable"
11120
+ present: entry !== void 0,
11121
+ usable: entry?.credentialStatus.ok === true,
11122
+ reason: entry === void 0 ? "missing" : entry.credentialStatus.ok ? "ready" : "unavailable"
10539
11123
  });
10540
11124
  };
10541
11125
  const activePaths = () => options.storageCatalog.active().resolver;
@@ -10573,6 +11157,7 @@ function createImageDoctorService(options) {
10573
11157
  } catch {
10574
11158
  storesValid = false;
10575
11159
  }
11160
+ const antigravityAccount = await readAccount("antigravity");
10576
11161
  const rows = await options.keyDb.outboundApiKeysList();
10577
11162
  let legacyRows = 0;
10578
11163
  let invalidRows = 0;
@@ -10589,7 +11174,7 @@ function createImageDoctorService(options) {
10589
11174
  invalidRows += 1;
10590
11175
  }
10591
11176
  }
10592
- const account = await readAccount();
11177
+ const account = await readAccount("codex");
10593
11178
  let evidence;
10594
11179
  let evidenceStore;
10595
11180
  try {
@@ -10603,10 +11188,11 @@ function createImageDoctorService(options) {
10603
11188
  return Object.freeze({
10604
11189
  config: Object.freeze({
10605
11190
  enabled: config.enabled,
10606
- provider: config.provider,
11191
+ provider: config.models[config.defaultModel] ?? "codex-subscription",
10607
11192
  model: config.defaultModel,
10608
11193
  valid: configErrors.length === 0,
10609
- errorCount: configErrors.length
11194
+ errorCount: configErrors.length,
11195
+ routedProviders: Object.freeze([...new Set(Object.values(config.models))])
10610
11196
  }),
10611
11197
  roots: Object.freeze({
10612
11198
  valid: verifiedAreas === ROOT_AREAS.length,
@@ -10631,12 +11217,13 @@ function createImageDoctorService(options) {
10631
11217
  imagesAuthorizedRows
10632
11218
  }),
10633
11219
  account,
11220
+ antigravityAccount,
10634
11221
  evidence: Object.freeze(evidence)
10635
11222
  });
10636
11223
  },
10637
11224
  verifyLive: async (config, signal) => {
10638
11225
  if (!config.enabled) return Object.freeze({ ok: false, code: "images_disabled" });
10639
- const account = await readAccount();
11226
+ const account = await readAccount("codex");
10640
11227
  if (!account.usable) {
10641
11228
  return Object.freeze({ ok: false, code: "codex_account_unavailable" });
10642
11229
  }
@@ -10888,7 +11475,7 @@ var ImageCleanupService = class {
10888
11475
  var import_node_crypto16 = require("crypto");
10889
11476
  var import_image_generation5 = require("@omnicross/core/image-generation");
10890
11477
  var import_outbound_api8 = require("@omnicross/core/outbound-api");
10891
- var import_subscriptions10 = require("@omnicross/subscriptions");
11478
+ var import_subscriptions11 = require("@omnicross/subscriptions");
10892
11479
 
10893
11480
  // src/image-generation/ImageApiRuntimeResolver.ts
10894
11481
  var import_node_crypto14 = require("crypto");
@@ -10916,10 +11503,11 @@ function createTrustedImageApiRuntimeResolver(options) {
10916
11503
  throw new TypeError("enabled image remote loading requires a proven resolver");
10917
11504
  }
10918
11505
  const hmacKey = Buffer.from(options.hmacKey);
10919
- const modelAliases = new Map(Object.entries(options.config.modelAliases));
11506
+ const modelAliases = new Map(Object.entries(options.config.aliases));
11507
+ const modelRoutes = new Map(Object.entries(options.config.models));
10920
11508
  const limits = Object.freeze({ ...options.config.limits });
10921
- const providerId = options.config.provider;
10922
11509
  const defaultModel = options.config.defaultModel;
11510
+ const providerId = modelRoutes.get(defaultModel) ?? "codex-subscription";
10923
11511
  const referenceStore = options.referenceStore;
10924
11512
  const retention = Object.freeze({
10925
11513
  enabled: true,
@@ -10940,6 +11528,7 @@ function createTrustedImageApiRuntimeResolver(options) {
10940
11528
  providerId,
10941
11529
  defaultModel,
10942
11530
  modelAliases,
11531
+ modelRoutes,
10943
11532
  limits,
10944
11533
  ...preferredAccountId ? { preferredAccountId } : {},
10945
11534
  ...preferredAccountGroup ? { preferredAccountGroup } : {},
@@ -11341,7 +11930,9 @@ var GENERATION_ID = /^[A-Za-z0-9][A-Za-z0-9_.:-]{0,127}$/u;
11341
11930
  function snapshotConfig(config) {
11342
11931
  return {
11343
11932
  ...config,
11344
- modelAliases: { ...config.modelAliases },
11933
+ models: { ...config.models },
11934
+ aliases: { ...config.aliases },
11935
+ codex: { ...config.codex },
11345
11936
  account: { ...config.account },
11346
11937
  queue: { ...config.queue },
11347
11938
  temporary: { ...config.temporary },
@@ -11375,10 +11966,15 @@ function createImageRuntimeGeneration(options) {
11375
11966
  }
11376
11967
  });
11377
11968
  }
11378
- const authStrategy = options.subscriptionAccounts.getStrategy("codex");
11379
- if (!authStrategy || authStrategy.providerId !== "codex") {
11969
+ const routedProviders = [...new Set(Object.values(config.models))];
11970
+ const codexStrategy = routedProviders.includes("codex-subscription") ? options.subscriptionAccounts.getStrategy("codex") : void 0;
11971
+ if (routedProviders.includes("codex-subscription") && (!codexStrategy || codexStrategy.providerId !== "codex")) {
11380
11972
  throw new TypeError("enabled image runtime requires the Codex subscription strategy");
11381
11973
  }
11974
+ const antigravityStrategy = routedProviders.includes("antigravity-subscription") ? options.subscriptionAccounts.getStrategy("antigravity") : void 0;
11975
+ if (routedProviders.includes("antigravity-subscription") && (!antigravityStrategy || antigravityStrategy.providerId !== "antigravity")) {
11976
+ throw new TypeError("enabled image runtime requires the Antigravity subscription strategy");
11977
+ }
11382
11978
  const privateHmacKey = options.privateHmacKey ? Buffer.from(options.privateHmacKey) : loadOrCreateImageTenantHmacSalt(options.storage.paths, import_node_crypto16.randomBytes);
11383
11979
  if (privateHmacKey.byteLength !== 32) {
11384
11980
  privateHmacKey.fill(0);
@@ -11413,23 +12009,32 @@ function createImageRuntimeGeneration(options) {
11413
12009
  if (options.testOnlySyntheticVerifiedProvider && options.testOnlySyntheticVerifiedProvider.label !== "synthetic-verified-image-provider-test-only") {
11414
12010
  throw new TypeError("synthetic verified image provider test seam label is invalid");
11415
12011
  }
11416
- const provider = options.testOnlySyntheticVerifiedProvider ? options.testOnlySyntheticVerifiedProvider.createProvider({
12012
+ const providers = options.testOnlySyntheticVerifiedProvider ? [options.testOnlySyntheticVerifiedProvider.createProvider({
11417
12013
  generationId: options.generationId,
11418
12014
  scheduler,
11419
12015
  now: options.now ?? Date.now,
11420
12016
  referenceStore: options.storage.referenceStore,
11421
12017
  stateStore: options.storage.stateStore
11422
- }) : (0, import_subscriptions10.createCodexSubscriptionImageProvider)({
11423
- authStrategy,
12018
+ })] : routedProviders.map((providerId) => providerId === "codex-subscription" ? (0, import_subscriptions11.createCodexSubscriptionImageProvider)({
12019
+ authStrategy: codexStrategy,
11424
12020
  evidenceSource: generationEvidenceSource,
11425
12021
  executionScheduler: scheduler,
11426
12022
  generationTimeoutMs: config.queue.generationTimeoutMs,
12023
+ now: options.now,
12024
+ wire: {
12025
+ imageModel: config.codex.imageModel,
12026
+ carrierModel: config.codex.carrierModel
12027
+ }
12028
+ }) : (0, import_subscriptions11.createAntigravitySubscriptionImageProvider)({
12029
+ authStrategy: antigravityStrategy,
12030
+ executionScheduler: scheduler,
12031
+ generationTimeoutMs: config.queue.generationTimeoutMs,
11427
12032
  now: options.now
11428
- });
11429
- if (provider.id !== config.provider) {
12033
+ }));
12034
+ if (providers.length === 1 && providers[0].id !== "codex-subscription") {
11430
12035
  throw new TypeError("synthetic verified image provider id must match configured provider");
11431
12036
  }
11432
- const providerRegistry = new import_image_generation5.ImageProviderRegistry([provider]);
12037
+ const providerRegistry = new import_image_generation5.ImageProviderRegistry(providers);
11433
12038
  const orchestrator = new import_image_generation5.ImageOrchestrator({
11434
12039
  registry: providerRegistry,
11435
12040
  referenceStore: options.storage.referenceStore,
@@ -11451,35 +12056,72 @@ function createImageRuntimeGeneration(options) {
11451
12056
  ...options.createCallId ? { createCallId: options.createCallId } : {},
11452
12057
  ...options.now ? { now: options.now } : {}
11453
12058
  });
12059
+ const defaultProviderId = config.models[config.defaultModel] ?? "codex-subscription";
12060
+ const inspectOneProvider = async (providerId, apiKeyId) => {
12061
+ const capabilities = await orchestrator.getCapabilities(providerId, {
12062
+ requestId: `${options.generationId}:capability-inspection`,
12063
+ tenantId: apiKeyId,
12064
+ signal: new AbortController().signal,
12065
+ sessionKey: `outbound:images:${apiKeyId}`,
12066
+ ...config.account.id ? { preferredAccountId: config.account.id } : {},
12067
+ ...config.account.group ? { preferredAccountGroup: config.account.group } : {},
12068
+ boundAccountFallbackPolicy: config.account.fallback
12069
+ });
12070
+ return capabilities;
12071
+ };
11454
12072
  const inspectCapability = async (apiKeyId) => {
11455
- try {
11456
- const capabilities = await orchestrator.getCapabilities(config.provider, {
11457
- requestId: `${options.generationId}:capability-inspection`,
11458
- tenantId: apiKeyId,
11459
- signal: new AbortController().signal,
11460
- sessionKey: `outbound:images:${apiKeyId}`,
11461
- ...config.account.id ? { preferredAccountId: config.account.id } : {},
11462
- ...config.account.group ? { preferredAccountGroup: config.account.group } : {},
11463
- boundAccountFallbackPolicy: config.account.fallback
11464
- });
11465
- const available = capabilities.available === true && capabilities.generate === true && capabilities.models.includes(config.defaultModel);
11466
- return Object.freeze({
11467
- enabled: true,
11468
- available,
11469
- providerId: config.provider,
11470
- model: config.defaultModel,
11471
- ...!available ? { reason: capabilities.reason ?? "runtime_unavailable" } : {},
11472
- capabilities
11473
- });
11474
- } catch (error) {
12073
+ const providerCapabilities = /* @__PURE__ */ new Map();
12074
+ let defaultProviderError;
12075
+ const providerRows = [];
12076
+ for (const providerId of [...new Set(Object.values(config.models))]) {
12077
+ try {
12078
+ const capabilities2 = await inspectOneProvider(providerId, apiKeyId);
12079
+ providerCapabilities.set(providerId, capabilities2);
12080
+ const affirmed = capabilities2.available === true && capabilities2.generate === true;
12081
+ providerRows.push({
12082
+ providerId,
12083
+ available: affirmed,
12084
+ ...!affirmed ? { reason: capabilities2.reason ?? "runtime_unavailable" } : {},
12085
+ models: affirmed ? Object.entries(config.models).filter(([model, modelProvider]) => modelProvider === providerId && capabilities2.models.includes(model)).map(([model]) => model) : [],
12086
+ capabilities: capabilities2
12087
+ });
12088
+ } catch (error) {
12089
+ if (providerId === defaultProviderId) defaultProviderError = error;
12090
+ providerRows.push({
12091
+ providerId,
12092
+ available: false,
12093
+ reason: error instanceof import_image_generation5.ImageGenerationError && (error.code === "upstream_auth_required" || error.code === "invalid_api_key") ? "account_unverified" : "runtime_unavailable",
12094
+ models: []
12095
+ });
12096
+ }
12097
+ }
12098
+ const providers2 = Object.freeze(providerRows);
12099
+ const routedModels = Object.freeze(
12100
+ providerRows.flatMap((row) => row.available ? row.models : [])
12101
+ );
12102
+ const capabilities = providerCapabilities.get(defaultProviderId);
12103
+ if (!capabilities) {
11475
12104
  return Object.freeze({
11476
12105
  enabled: true,
11477
12106
  available: false,
11478
- providerId: config.provider,
12107
+ providerId: defaultProviderId,
11479
12108
  model: config.defaultModel,
11480
- reason: error instanceof import_image_generation5.ImageGenerationError && (error.code === "upstream_auth_required" || error.code === "invalid_api_key") ? "account_unverified" : "runtime_unavailable"
12109
+ routedModels,
12110
+ providers: providers2,
12111
+ reason: defaultProviderError instanceof import_image_generation5.ImageGenerationError && (defaultProviderError.code === "upstream_auth_required" || defaultProviderError.code === "invalid_api_key") ? "account_unverified" : "runtime_unavailable"
11481
12112
  });
11482
12113
  }
12114
+ const available = capabilities.available === true && capabilities.generate === true && capabilities.models.includes(config.defaultModel);
12115
+ return Object.freeze({
12116
+ enabled: true,
12117
+ available,
12118
+ providerId: defaultProviderId,
12119
+ model: config.defaultModel,
12120
+ routedModels,
12121
+ providers: providers2,
12122
+ ...!available ? { reason: capabilities.reason ?? "runtime_unavailable" } : {},
12123
+ capabilities
12124
+ });
11483
12125
  };
11484
12126
  const resolverToDispose = runtimeResolver;
11485
12127
  const schedulerToDispose = scheduler;
@@ -11517,7 +12159,7 @@ function createImageRuntimeGeneration(options) {
11517
12159
  imageApi,
11518
12160
  hosted,
11519
12161
  hostedRuntime: Object.freeze({
11520
- providerId: config.provider,
12162
+ providerId: defaultProviderId,
11521
12163
  imageModel: config.defaultModel,
11522
12164
  referenceTtlMs: config.references.ttlMs,
11523
12165
  maxOutputBytes: config.limits.maxOutputBytes,
@@ -14460,6 +15102,9 @@ var ImageRuntimeManager = class {
14460
15102
  }
14461
15103
  async listAvailableModels(apiKeyId) {
14462
15104
  const inspection = await this.inspectCapability(apiKeyId);
15105
+ if (inspection.routedModels !== void 0) {
15106
+ return Object.freeze([...inspection.routedModels]);
15107
+ }
14463
15108
  return inspection.available && inspection.model === "gpt-image-2" ? Object.freeze([inspection.model]) : Object.freeze([]);
14464
15109
  }
14465
15110
  resourceStatus() {
@@ -16647,11 +17292,12 @@ var JsonVoucherDb = class {
16647
17292
  // src/ports/JsonSubscriptionCredentialStore.ts
16648
17293
  var import_node_fs24 = require("fs");
16649
17294
  var import_node_path24 = require("path");
17295
+ var import_GeminiCodeAssistProjectResolver5 = require("@omnicross/core/auth/GeminiCodeAssistProjectResolver");
16650
17296
  var import_SubscriptionAccountHealth2 = require("@omnicross/core/pipeline/SubscriptionAccountHealth");
16651
17297
  var import_AccountAllowanceScheduling3 = require("@omnicross/core/pipeline/AccountAllowanceScheduling");
16652
- var import_upstreamFetch12 = require("@omnicross/core/pipeline/upstreamFetch");
17298
+ var import_upstreamFetch14 = require("@omnicross/core/pipeline/upstreamFetch");
16653
17299
  var import_SubscriptionIdentityStore2 = require("@omnicross/core/provider-proxy/identity/SubscriptionIdentityStore");
16654
- var import_subscriptions11 = require("@omnicross/subscriptions");
17300
+ var import_subscriptions12 = require("@omnicross/subscriptions");
16655
17301
 
16656
17302
  // src/ports/account-sync.ts
16657
17303
  function viewOf(tokens) {
@@ -16799,7 +17445,7 @@ var JsonSubscriptionCredentialStore = class {
16799
17445
  * a plaintext token pair into `upstream-trace.jsonl`.
16800
17446
  */
16801
17447
  buildRefreshFetch(providerId, accountId) {
16802
- return this.fetchImpl ?? ((url, init) => (0, import_upstreamFetch12.fetchUpstream)(url, init, { providerId, accountId, redactBodies: true }));
17448
+ return this.fetchImpl ?? ((url, init) => (0, import_upstreamFetch14.fetchUpstream)(url, init, { providerId, accountId, redactBodies: true }));
16803
17449
  }
16804
17450
  /**
16805
17451
  * In-flight refresh coalescing. OAuth refresh tokens are
@@ -16840,7 +17486,7 @@ var JsonSubscriptionCredentialStore = class {
16840
17486
  * other hot reads. Never returns token material.
16841
17487
  */
16842
17488
  getAccountProxy(providerId, accountId) {
16843
- if (providerId !== "claude" && providerId !== "codex" && providerId !== "gemini" && providerId !== "opencodego" && providerId !== "kimi" && providerId !== "grok" && providerId !== "copilot") {
17489
+ if (providerId !== "claude" && providerId !== "codex" && providerId !== "gemini" && providerId !== "opencodego" && providerId !== "kimi" && providerId !== "grok" && providerId !== "copilot" && providerId !== "antigravity") {
16844
17490
  return void 0;
16845
17491
  }
16846
17492
  return getAccountProxy(this.readConfig(), providerId, accountId);
@@ -16859,7 +17505,7 @@ var JsonSubscriptionCredentialStore = class {
16859
17505
  const fingerprintOn = identityStore.isEnabled();
16860
17506
  const now = Date.now();
16861
17507
  const out = {};
16862
- for (const provider of ["claude", "codex", "gemini", "opencodego", "kimi", "grok", "copilot"]) {
17508
+ for (const provider of ["claude", "codex", "gemini", "opencodego", "kimi", "grok", "copilot", "antigravity"]) {
16863
17509
  const sanitized = sanitizeAccounts(config, provider);
16864
17510
  if (sanitized.length === 0) continue;
16865
17511
  for (const account of sanitized) {
@@ -16925,7 +17571,7 @@ var JsonSubscriptionCredentialStore = class {
16925
17571
  this.materializeMigration(config);
16926
17572
  const refreshFetch = this.buildRefreshFetch("claude", capturedId);
16927
17573
  try {
16928
- const result = await import_subscriptions11.claudeOAuth.refreshAccessToken(claude.refreshToken, refreshFetch);
17574
+ const result = await import_subscriptions12.claudeOAuth.refreshAccessToken(claude.refreshToken, refreshFetch);
16929
17575
  const expiresAt = new Date(Date.now() + result.expiresIn * 1e3).toISOString();
16930
17576
  const next = {
16931
17577
  ...claude,
@@ -16960,7 +17606,7 @@ var JsonSubscriptionCredentialStore = class {
16960
17606
  this.materializeMigration(config);
16961
17607
  const refreshFetch = this.buildRefreshFetch("codex", capturedId);
16962
17608
  try {
16963
- const result = await import_subscriptions11.codexOAuth.refreshAccessToken(codex.refreshToken, refreshFetch);
17609
+ const result = await import_subscriptions12.codexOAuth.refreshAccessToken(codex.refreshToken, refreshFetch);
16964
17610
  const expiresAt = new Date(Date.now() + result.expiresIn * 1e3).toISOString();
16965
17611
  const next = {
16966
17612
  ...codex,
@@ -16998,7 +17644,7 @@ var JsonSubscriptionCredentialStore = class {
16998
17644
  this.materializeMigration(config);
16999
17645
  const refreshFetch = this.buildRefreshFetch("gemini", capturedId);
17000
17646
  try {
17001
- const result = await import_subscriptions11.geminiOAuth.refreshAccessToken(gemini.refreshToken, refreshFetch);
17647
+ const result = await import_subscriptions12.geminiOAuth.refreshAccessToken(gemini.refreshToken, refreshFetch);
17002
17648
  const expiresAt = new Date(Date.now() + result.expiresIn * 1e3).toISOString();
17003
17649
  const next = {
17004
17650
  ...gemini,
@@ -17034,10 +17680,10 @@ var JsonSubscriptionCredentialStore = class {
17034
17680
  this.materializeMigration(config);
17035
17681
  const refreshFetch = this.buildRefreshFetch("kimi", capturedId);
17036
17682
  try {
17037
- const result = await import_subscriptions11.kimiOAuth.refreshAccessToken(
17683
+ const result = await import_subscriptions12.kimiOAuth.refreshAccessToken(
17038
17684
  kimi.refreshToken,
17039
17685
  refreshFetch,
17040
- import_subscriptions11.kimiOAuth.kimiFingerprintHeaders(kimi.deviceId)
17686
+ import_subscriptions12.kimiOAuth.kimiFingerprintHeaders(kimi.deviceId)
17041
17687
  );
17042
17688
  const expiresAt = new Date(Date.now() + result.expiresIn * 1e3).toISOString();
17043
17689
  const next = {
@@ -17074,8 +17720,8 @@ var JsonSubscriptionCredentialStore = class {
17074
17720
  this.materializeMigration(config);
17075
17721
  const refreshFetch = this.buildRefreshFetch("grok", capturedId);
17076
17722
  try {
17077
- const tokenEndpoint = await import_subscriptions11.grokOAuth.resolveGrokTokenEndpoint(refreshFetch);
17078
- const result = await import_subscriptions11.grokOAuth.refreshGrokAccessToken(grok.refreshToken, tokenEndpoint, refreshFetch);
17723
+ const tokenEndpoint = await import_subscriptions12.grokOAuth.resolveGrokTokenEndpoint(refreshFetch);
17724
+ const result = await import_subscriptions12.grokOAuth.refreshGrokAccessToken(grok.refreshToken, tokenEndpoint, refreshFetch);
17079
17725
  const expiresAt = new Date(Date.now() + result.expiresIn * 1e3).toISOString();
17080
17726
  const next = {
17081
17727
  ...grok,
@@ -17118,6 +17764,76 @@ var JsonSubscriptionCredentialStore = class {
17118
17764
  return false;
17119
17765
  });
17120
17766
  }
17767
+ /**
17768
+ * Refresh the Antigravity (Google) OAuth access token. Like gemini, the
17769
+ * Google token endpoint does NOT return a refresh_token on refresh, so this
17770
+ * writes ONLY access+expiresAt (+status/lastRefreshedAt) and DELIBERATELY
17771
+ * preserves the stored `refreshToken` — plus the account's `projectId`
17772
+ * (a handshake product; the post-refresh re-validation is the refresh
17773
+ * scheduler's hook, not this write) and `email`. HONEST `false` when no
17774
+ * refresh_token.
17775
+ */
17776
+ async refreshAntigravityToken() {
17777
+ return this.coalesce("antigravity:active", async () => {
17778
+ const config = this.readConfig();
17779
+ const active = getActiveAccount(config, "antigravity");
17780
+ const antigravity = active?.tokens;
17781
+ if (!active || !antigravity?.refreshToken) return false;
17782
+ const capturedId = active.id;
17783
+ this.materializeMigration(config);
17784
+ const refreshFetch = this.buildRefreshFetch("antigravity", capturedId);
17785
+ try {
17786
+ const result = await import_subscriptions12.antigravityOAuth.refreshAccessToken(antigravity.refreshToken, refreshFetch);
17787
+ const expiresAt = new Date(Date.now() + result.expiresIn * 1e3).toISOString();
17788
+ const next = {
17789
+ ...antigravity,
17790
+ // KEEP the existing refreshToken/projectId/email.
17791
+ accessToken: result.accessToken,
17792
+ expiresAt,
17793
+ status: "authorized",
17794
+ lastRefreshedAt: (/* @__PURE__ */ new Date()).toISOString(),
17795
+ errorMessage: void 0
17796
+ };
17797
+ this.writeBackById("antigravity", capturedId, next);
17798
+ await this.revalidateAntigravityProject(capturedId);
17799
+ return true;
17800
+ } catch (error) {
17801
+ this.markExpiredById("antigravity", capturedId, antigravity, error);
17802
+ return false;
17803
+ }
17804
+ });
17805
+ }
17806
+ /**
17807
+ * Post-refresh project re-validation hook (antigravity design D8): after a
17808
+ * successful antigravity token refresh, re-run the Code Assist project
17809
+ * handshake and write the (possibly rotated) `projectId` back to the account.
17810
+ * A handshake FAILURE keeps the stored projectId untouched (logged) so the
17811
+ * account keeps serving with the last-known-good project until a later
17812
+ * refresh succeeds. Returns whether the handshake produced a project.
17813
+ */
17814
+ async revalidateAntigravityProject(accountId) {
17815
+ const before = getAccountById(this.readConfig(), "antigravity", accountId);
17816
+ const accessToken = before?.tokens?.accessToken;
17817
+ if (!accessToken) return false;
17818
+ try {
17819
+ const projectId = await (0, import_GeminiCodeAssistProjectResolver5.getAntigravityProjectResolver)().resolveProject(accessToken);
17820
+ if (projectId !== void 0) {
17821
+ const config = this.readConfig();
17822
+ const account = getAccountById(config, "antigravity", accountId);
17823
+ const tokens = account?.tokens;
17824
+ if (account && tokens?.accessToken === accessToken && tokens.projectId !== projectId) {
17825
+ this.writeBackById("antigravity", accountId, { ...tokens, projectId });
17826
+ }
17827
+ return true;
17828
+ }
17829
+ return false;
17830
+ } catch (error) {
17831
+ console.warn(
17832
+ `[JsonSubscriptionCredentialStore] antigravity project re-validation failed for account ${accountId}: ` + (error instanceof Error ? error.message : String(error))
17833
+ );
17834
+ return false;
17835
+ }
17836
+ }
17121
17837
  /**
17122
17838
  * Refresh a SPECIFIC managed account by id (background scheduler sweep and
17123
17839
  * account-pool resolution). It uses only that account's stored refresh
@@ -17146,6 +17862,7 @@ var JsonSubscriptionCredentialStore = class {
17146
17862
  };
17147
17863
  if (refreshed.idToken) next.idToken = refreshed.idToken;
17148
17864
  this.writeBackById(provider, id, next);
17865
+ if (provider === "antigravity") await this.revalidateAntigravityProject(id);
17149
17866
  return true;
17150
17867
  } catch (error) {
17151
17868
  this.markExpiredById(provider, id, captured, error);
@@ -17170,7 +17887,7 @@ var JsonSubscriptionCredentialStore = class {
17170
17887
  }
17171
17888
  const oauth = account.tokens;
17172
17889
  if (!oauth.accessToken) return null;
17173
- if (providerId === "codex" || providerId === "gemini" || providerId === "kimi" || providerId === "grok" || providerId === "copilot") {
17890
+ if (providerId === "codex" || providerId === "gemini" || providerId === "kimi" || providerId === "grok" || providerId === "copilot" || providerId === "antigravity") {
17174
17891
  const expiresAtMs = oauth.expiresAt ? Date.parse(oauth.expiresAt) : 0;
17175
17892
  const expiringSoon = expiresAtMs > 0 && Date.now() >= expiresAtMs - ACCOUNT_REFRESH_LEAD_MS;
17176
17893
  if (expiringSoon && oauth.refreshToken) {
@@ -17263,10 +17980,10 @@ var JsonSubscriptionCredentialStore = class {
17263
17980
  if (provider === "kimi") {
17264
17981
  const account = accountId ? getAccountById(this.readConfig(), "kimi", accountId) : void 0;
17265
17982
  const deviceId = account?.tokens?.deviceId;
17266
- const r2 = await import_subscriptions11.kimiOAuth.refreshAccessToken(
17983
+ const r2 = await import_subscriptions12.kimiOAuth.refreshAccessToken(
17267
17984
  refreshToken,
17268
17985
  refreshFetch,
17269
- import_subscriptions11.kimiOAuth.kimiFingerprintHeaders(deviceId)
17986
+ import_subscriptions12.kimiOAuth.kimiFingerprintHeaders(deviceId)
17270
17987
  );
17271
17988
  return {
17272
17989
  accessToken: r2.accessToken,
@@ -17275,8 +17992,8 @@ var JsonSubscriptionCredentialStore = class {
17275
17992
  };
17276
17993
  }
17277
17994
  if (provider === "grok") {
17278
- const tokenEndpoint = await import_subscriptions11.grokOAuth.resolveGrokTokenEndpoint(refreshFetch);
17279
- const r2 = await import_subscriptions11.grokOAuth.refreshGrokAccessToken(refreshToken, tokenEndpoint, refreshFetch);
17995
+ const tokenEndpoint = await import_subscriptions12.grokOAuth.resolveGrokTokenEndpoint(refreshFetch);
17996
+ const r2 = await import_subscriptions12.grokOAuth.refreshGrokAccessToken(refreshToken, tokenEndpoint, refreshFetch);
17280
17997
  return {
17281
17998
  accessToken: r2.accessToken,
17282
17999
  refreshToken: r2.refreshToken,
@@ -17286,7 +18003,14 @@ var JsonSubscriptionCredentialStore = class {
17286
18003
  if (provider === "copilot") {
17287
18004
  throw new Error("GitHub Copilot tokens cannot be refreshed \u2014 re-authenticate the account");
17288
18005
  }
17289
- const flow = provider === "claude" ? import_subscriptions11.claudeOAuth : provider === "codex" ? import_subscriptions11.codexOAuth : import_subscriptions11.geminiOAuth;
18006
+ if (provider === "antigravity") {
18007
+ const r2 = await import_subscriptions12.antigravityOAuth.refreshAccessToken(refreshToken, refreshFetch);
18008
+ return {
18009
+ accessToken: r2.accessToken,
18010
+ expiresAt: new Date(Date.now() + r2.expiresIn * 1e3).toISOString()
18011
+ };
18012
+ }
18013
+ const flow = provider === "claude" ? import_subscriptions12.claudeOAuth : provider === "codex" ? import_subscriptions12.codexOAuth : import_subscriptions12.geminiOAuth;
17290
18014
  const r = await flow.refreshAccessToken(refreshToken, refreshFetch);
17291
18015
  return {
17292
18016
  accessToken: r.accessToken,
@@ -17529,7 +18253,7 @@ var JsonSubscriptionCredentialStore = class {
17529
18253
  };
17530
18254
 
17531
18255
  // src/AccountHealthProbeScheduler.ts
17532
- var import_upstreamFetch13 = require("@omnicross/core/pipeline/upstreamFetch");
18256
+ var import_upstreamFetch15 = require("@omnicross/core/pipeline/upstreamFetch");
17533
18257
 
17534
18258
  // src/probe/CodexGenerationProbe.ts
17535
18259
  var import_codexCliHeaders = require("@omnicross/core/provider-proxy/identity/codexCliHeaders");
@@ -17681,7 +18405,11 @@ var PROVIDER_PROBE_PLANS = {
17681
18405
  // The Copilot quota endpoint (copilot_internal/user) is a verified FREE
17682
18406
  // authed GET but lives on api.github.com with its own auth dialect and a
17683
18407
  // monthly-only window — the allowance collector owns the health surface.
17684
- copilot: { kind: "local" }
18408
+ copilot: { kind: "local" },
18409
+ // Antigravity's quota endpoints are POST RPCs on daily-cloudcode-pa (not a
18410
+ // cheap GET) and need the antigravity/hub UA — the allowance collector owns
18411
+ // the health surface; the probe stays local.
18412
+ antigravity: { kind: "local" }
17685
18413
  };
17686
18414
  function probePlanFor(providerId) {
17687
18415
  return PROVIDER_PROBE_PLANS[providerId] ?? { kind: "local" };
@@ -17703,7 +18431,7 @@ var AccountHealthProbeScheduler = class {
17703
18431
  this.logger = logger;
17704
18432
  this.config = config;
17705
18433
  this.now = opts.now ?? Date.now;
17706
- this.fetchImpl = opts.fetchImpl ?? import_upstreamFetch13.fetchUpstream;
18434
+ this.fetchImpl = opts.fetchImpl ?? import_upstreamFetch15.fetchUpstream;
17707
18435
  this.sleep = opts.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
17708
18436
  this.planFor = opts.planFor ?? probePlanFor;
17709
18437
  }
@@ -19401,7 +20129,7 @@ var AuditWriter = class {
19401
20129
  var import_node_fs33 = require("fs");
19402
20130
  var import_node_crypto24 = require("crypto");
19403
20131
  var import_node_path33 = require("path");
19404
- var import_upstreamFetch14 = require("@omnicross/core/pipeline/upstreamFetch");
20132
+ var import_upstreamFetch16 = require("@omnicross/core/pipeline/upstreamFetch");
19405
20133
 
19406
20134
  // src/billing/billingFiles.ts
19407
20135
  var BILLING_FILE_RE = /^billing-(\d{4})-(\d{2})-(\d{2})\.jsonl$/;
@@ -19424,7 +20152,7 @@ var BillingPublisher = class {
19424
20152
  constructor(billingDir, logger, opts = {}) {
19425
20153
  this.billingDir = billingDir;
19426
20154
  this.logger = logger;
19427
- this.fetchImpl = opts.fetchImpl ?? ((url, init) => (0, import_upstreamFetch14.fetchUpstream)(url, init));
20155
+ this.fetchImpl = opts.fetchImpl ?? ((url, init) => (0, import_upstreamFetch16.fetchUpstream)(url, init));
19428
20156
  this.defer = opts.defer ?? ((fn) => setTimeout(fn, 0));
19429
20157
  this.timeoutMs = opts.timeoutMs ?? BILLING_POST_TIMEOUT_MS;
19430
20158
  this.now = opts.now ?? Date.now;
@@ -19674,7 +20402,7 @@ var BillingRetrySweeper = class {
19674
20402
  // src/TokenRefreshScheduler.ts
19675
20403
  var REFRESH_LEAD_MS2 = 5 * 6e4;
19676
20404
  var SWEEP_INTERVAL_MS5 = 6e4;
19677
- var OAUTH_PROVIDERS2 = ["claude", "codex", "gemini", "kimi", "grok", "copilot"];
20405
+ var OAUTH_PROVIDERS2 = ["claude", "codex", "gemini", "kimi", "grok", "copilot", "antigravity"];
19678
20406
  var TokenRefreshScheduler = class {
19679
20407
  constructor(store, logger, intervalMs = SWEEP_INTERVAL_MS5, leadMs = REFRESH_LEAD_MS2) {
19680
20408
  this.store = store;
@@ -19765,6 +20493,8 @@ var TokenRefreshScheduler = class {
19765
20493
  // never reaches this — the branch exists for union totality.
19766
20494
  case "copilot":
19767
20495
  return this.store.refreshCopilotToken();
20496
+ case "antigravity":
20497
+ return this.store.refreshAntigravityToken();
19768
20498
  }
19769
20499
  }
19770
20500
  };
@@ -19841,7 +20571,7 @@ function createRouteLeaseSubscriptionPreflight(credentials) {
19841
20571
 
19842
20572
  // src/webhook/WebhookDispatcher.ts
19843
20573
  var import_node_crypto25 = require("crypto");
19844
- var import_upstreamFetch15 = require("@omnicross/core/pipeline/upstreamFetch");
20574
+ var import_upstreamFetch17 = require("@omnicross/core/pipeline/upstreamFetch");
19845
20575
  var WEBHOOK_MAX_ATTEMPTS = 3;
19846
20576
  var WEBHOOK_QUEUE_MAX = 1e3;
19847
20577
  var WEBHOOK_SEND_TIMEOUT_MS = 1e4;
@@ -19861,7 +20591,7 @@ var WebhookDispatcher = class {
19861
20591
  sleep;
19862
20592
  now;
19863
20593
  constructor(opts = {}) {
19864
- this.fetchImpl = opts.fetchImpl ?? ((url, init) => (0, import_upstreamFetch15.fetchUpstream)(url, init));
20594
+ this.fetchImpl = opts.fetchImpl ?? ((url, init) => (0, import_upstreamFetch17.fetchUpstream)(url, init));
19865
20595
  this.logger = opts.logger;
19866
20596
  this.maxAttempts = opts.maxAttempts ?? WEBHOOK_MAX_ATTEMPTS;
19867
20597
  this.queueMax = opts.queueMax ?? WEBHOOK_QUEUE_MAX;
@@ -19947,8 +20677,8 @@ var WebhookDispatcher = class {
19947
20677
  signal: AbortSignal.timeout(this.timeoutMs)
19948
20678
  });
19949
20679
  return res.ok ? { ok: true, status: res.status } : { ok: false, status: res.status };
19950
- } catch (err8) {
19951
- return { ok: false, error: err8 instanceof Error ? err8.message : String(err8) };
20680
+ } catch (err9) {
20681
+ return { ok: false, error: err9 instanceof Error ? err9.message : String(err9) };
19952
20682
  }
19953
20683
  }
19954
20684
  /**
@@ -20090,12 +20820,12 @@ function buildDaemon(config, paths) {
20090
20820
  setSecretBox(secretBox3);
20091
20821
  setSecretBox2(secretBox3);
20092
20822
  const decryptedConfig = decryptConfigSecrets(config, secretBox3);
20093
- const accountAllowanceStore = new import_AccountAllowanceStore10.AccountAllowanceStore(
20823
+ const accountAllowanceStore = new import_AccountAllowanceStore11.AccountAllowanceStore(
20094
20824
  Date.now,
20095
20825
  void 0,
20096
20826
  new JsonAccountAllowancePersistence(defaultAccountAllowancePath(paths.configPath))
20097
20827
  );
20098
- (0, import_AccountAllowanceStore10.setSharedAccountAllowanceStore)(accountAllowanceStore);
20828
+ (0, import_AccountAllowanceStore11.setSharedAccountAllowanceStore)(accountAllowanceStore);
20099
20829
  (0, import_AccountAllowanceScheduling5.getSharedAccountAllowanceScheduling)().configure(
20100
20830
  (0, import_outbound_api10.normalizeServerConfig)(decryptedConfig.server).allowanceScheduling
20101
20831
  );
@@ -20120,20 +20850,22 @@ function buildDaemon(config, paths) {
20120
20850
  claudeAllowanceRefreshScheduler.configure(
20121
20851
  (0, import_outbound_api10.normalizeServerConfig)(decryptedConfig.server).allowanceScheduling
20122
20852
  );
20123
- const subscriptionAccounts = new import_subscriptions12.SubscriptionAccountService(credentialStore);
20124
- (0, import_subscriptions12.setSubscriptionAccountService)(subscriptionAccounts);
20125
- const subscriptionRegistry = new import_subscriptions12.SubscriptionProviderRegistry(
20853
+ const subscriptionAccounts = new import_subscriptions13.SubscriptionAccountService(credentialStore);
20854
+ (0, import_subscriptions13.setSubscriptionAccountService)(subscriptionAccounts);
20855
+ const subscriptionRegistry = new import_subscriptions13.SubscriptionProviderRegistry(
20126
20856
  subscriptionAccounts,
20127
20857
  credentialStore
20128
20858
  );
20129
- (0, import_subscriptions12.setSubscriptionProviderRegistry)(subscriptionRegistry);
20859
+ (0, import_subscriptions13.setSubscriptionProviderRegistry)(subscriptionRegistry);
20130
20860
  setServerProxyConfig(decryptedConfig.server?.proxy);
20131
- (0, import_upstreamFetch16.setUpstreamProxyResolver)(
20861
+ (0, import_upstreamFetch18.setUpstreamProxyResolver)(
20132
20862
  createUpstreamProxyResolver({
20133
20863
  getAccountProxy: (providerId, accountId) => credentialStore.getAccountProxy(providerId, accountId)
20134
20864
  })
20135
20865
  );
20136
- (0, import_gemini_code_assist_resolver.setGeminiCodeAssistResolver)((0, import_GeminiCodeAssistProjectResolver2.getGeminiCodeAssistProjectResolver)());
20866
+ (0, import_gemini_code_assist_resolver.setGeminiCodeAssistResolver)((0, import_GeminiCodeAssistProjectResolver6.getGeminiCodeAssistProjectResolver)());
20867
+ (0, import_antigravityFailover.setAntigravitySandboxFailover)(decryptedConfig.antigravity?.sandboxFailover === true);
20868
+ (0, import_openCodeGoHeaders2.setOpenCodeGoUserAgent)(decryptedConfig.opencodego?.userAgent ?? null);
20137
20869
  const autoDisableStore = new AutoDisableStore();
20138
20870
  const providerKeyQuotaService = new ProviderKeyQuotaService(secretBox3);
20139
20871
  const apiKeyPool = new import_ApiKeyPoolService.ApiKeyPoolService(
@@ -20152,7 +20884,7 @@ function buildDaemon(config, paths) {
20152
20884
  const pricingEngine = new import_usage2.PricingEngine(pricingStore, logger, {
20153
20885
  // Catalog egress follows the same global/env proxy policy as every other
20154
20886
  // daemon upstream call; no provider/account override applies here.
20155
- fetchImpl: ((input, init) => (0, import_upstreamFetch16.fetchUpstream)(String(input), init ?? {}))
20887
+ fetchImpl: ((input, init) => (0, import_upstreamFetch18.fetchUpstream)(String(input), init ?? {}))
20156
20888
  });
20157
20889
  const pricingRefreshScheduler = new PricingRefreshScheduler(
20158
20890
  pricingEngine,
@@ -20394,6 +21126,7 @@ function buildDaemon(config, paths) {
20394
21126
  outboundApiServer,
20395
21127
  imageRuntimeConfig,
20396
21128
  imageRuntimeStatus: paths.imageRuntimeStatus ?? imageRuntimeManager,
21129
+ imageLiveVerifier: paths.imageLiveVerifier ?? imageDoctor,
20397
21130
  imageConfigAudit: paths.imageConfigAudit ?? ((record) => {
20398
21131
  imageObservability.recordConfigurationAudit(record);
20399
21132
  }),
@@ -20437,7 +21170,7 @@ function buildDaemon(config, paths) {
20437
21170
  // — `server.proxy.byProvider[...]` was silently skipped — and the call was
20438
21171
  // excluded from the upstream trace, so a failing login left no evidence.
20439
21172
  // `redactBodies` keeps the code/verifier + minted token out of that trace.
20440
- oauthExchangeFetch: paths.oauthExchangeFetch ? () => paths.oauthExchangeFetch : (providerId) => (url, init) => (0, import_upstreamFetch16.fetchUpstream)(url, init, { providerId, redactBodies: true }),
21173
+ oauthExchangeFetch: paths.oauthExchangeFetch ? () => paths.oauthExchangeFetch : (providerId) => (url, init) => (0, import_upstreamFetch18.fetchUpstream)(url, init, { providerId, redactBodies: true }),
20441
21174
  subscriptionAccountAppender: credentialStore,
20442
21175
  // Codex interactive OAuth (app-parity-2 child 5) — the async loopback flow store
20443
21176
  // + the one-shot 127.0.0.1:1455 listener. Token captured + persisted daemon-side;
@@ -20452,6 +21185,21 @@ function buildDaemon(config, paths) {
20452
21185
  // Grok interactive OAuth — the same async DEVICE-CODE shape as kimi.
20453
21186
  grokSessions: new CodexOAuthSessionStore(),
20454
21187
  copilotSessions: new CodexOAuthSessionStore(),
21188
+ // Antigravity interactive OAuth — the async LOOPBACK flow store + the
21189
+ // one-shot 127.0.0.1:51121 listener (same shape as codex; test seam below).
21190
+ antigravitySessions: new CodexOAuthSessionStore(),
21191
+ antigravityAwaitLoopback: paths.antigravityAwaitLoopback ?? ((state, timeoutMs, signal) => awaitLoopbackCode(state, timeoutMs, signal, {
21192
+ port: 51121,
21193
+ path: "/oauth-callback",
21194
+ label: "antigravity"
21195
+ })),
21196
+ // The dynamic model-catalog probe's token source (the ACTIVE antigravity
21197
+ // account; refreshed by the by-id near-expiry seam inside the lookup).
21198
+ resolveAntigravityAccessToken: async () => {
21199
+ const config2 = await credentialStore.getFullConfig();
21200
+ const activeId = config2.activeAntigravityAccountId ?? config2.antigravityAccounts?.[0]?.id;
21201
+ return activeId ? credentialStore.getAccessTokenForAccount("antigravity", activeId) : null;
21202
+ },
20455
21203
  // Migration pack (app-parity child 6, design D2/D3) — the concrete credential
20456
21204
  // store provides BOTH the full DECRYPTED read (`getFullConfig`, export) and
20457
21205
  // the multi-account append (`appendProviderAccount`, import re-encrypts at-
@@ -20510,7 +21258,7 @@ function buildDaemon(config, paths) {
20510
21258
  });
20511
21259
  const webhookDispatcher = new WebhookDispatcher({
20512
21260
  logger,
20513
- fetchImpl: (url, init) => (0, import_upstreamFetch16.fetchUpstream)(url, init)
21261
+ fetchImpl: (url, init) => (0, import_upstreamFetch18.fetchUpstream)(url, init)
20514
21262
  });
20515
21263
  setWebhookRuntime(webhookDispatcher, (0, import_SubscriptionAccountHealth4.getSharedAccountHealth)());
20516
21264
  const auditWriter = new AuditWriter(auditDir, logger);
@@ -20590,9 +21338,9 @@ function resetDaemonSingletonsForTests() {
20590
21338
  (0, import_provider_proxy4.__resetProviderProxyForTests)();
20591
21339
  (0, import_outbound_api10.__resetOutboundApiServerForTests)();
20592
21340
  (0, import_subscriptionRegistryPort.setSubscriptionRegistryForOutbound)(null);
20593
- (0, import_subscriptions12.setSubscriptionProviderRegistry)(null);
20594
- (0, import_subscriptions12.setSubscriptionAccountService)(null);
20595
- (0, import_upstreamFetch16.setUpstreamProxyResolver)(null);
21341
+ (0, import_subscriptions13.setSubscriptionProviderRegistry)(null);
21342
+ (0, import_subscriptions13.setSubscriptionAccountService)(null);
21343
+ (0, import_upstreamFetch18.setUpstreamProxyResolver)(null);
20596
21344
  setServerProxyConfig(void 0);
20597
21345
  (0, import_gemini_code_assist_resolver.setGeminiCodeAssistResolver)(null);
20598
21346
  setSecretBox(null);
@@ -20601,7 +21349,7 @@ function resetDaemonSingletonsForTests() {
20601
21349
  resetAuditRuntimeForTests();
20602
21350
  resetBillingRuntimeForTests();
20603
21351
  (0, import_SubscriptionIdentityStore3.__resetSharedIdentityStoreForTests)();
20604
- (0, import_AccountAllowanceStore10.__resetSharedAccountAllowanceStoreForTests)();
21352
+ (0, import_AccountAllowanceStore11.__resetSharedAccountAllowanceStoreForTests)();
20605
21353
  (0, import_AccountAllowanceScheduling5.__resetSharedAccountAllowanceSchedulingForTests)();
20606
21354
  (0, import_usage2.__resetSharedUsageThroughputTrackerForTests)();
20607
21355
  }