@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/cli.cjs +1193 -281
- package/dist/cli.js +1141 -221
- package/dist/index.cjs +986 -238
- package/dist/index.d.cts +1588 -1386
- package/dist/index.d.ts +1588 -1386
- package/dist/index.js +954 -199
- package/package.json +6 -6
package/dist/cli.js
CHANGED
|
@@ -930,7 +930,11 @@ var TOKEN_FIELDS = {
|
|
|
930
930
|
claude: ["accessToken", "refreshToken"],
|
|
931
931
|
codex: ["accessToken", "refreshToken", "idToken"],
|
|
932
932
|
gemini: ["accessToken", "refreshToken"],
|
|
933
|
-
opencodego: ["apiKey"]
|
|
933
|
+
opencodego: ["apiKey"],
|
|
934
|
+
kimi: ["accessToken", "refreshToken"],
|
|
935
|
+
grok: ["accessToken", "refreshToken"],
|
|
936
|
+
copilot: ["accessToken", "refreshToken"],
|
|
937
|
+
antigravity: ["accessToken", "refreshToken"]
|
|
934
938
|
};
|
|
935
939
|
function transformTokenBlock(block, fields, fn) {
|
|
936
940
|
const next = { ...block };
|
|
@@ -1170,16 +1174,18 @@ import { setSubscriptionRegistryForOutbound } from "@omnicross/core/outbound-api
|
|
|
1170
1174
|
import { getSharedAccountHealth as getSharedAccountHealth4 } from "@omnicross/core/pipeline/SubscriptionAccountHealth";
|
|
1171
1175
|
import {
|
|
1172
1176
|
__resetSharedAccountAllowanceStoreForTests,
|
|
1173
|
-
AccountAllowanceStore as
|
|
1177
|
+
AccountAllowanceStore as AccountAllowanceStore10,
|
|
1174
1178
|
setSharedAccountAllowanceStore
|
|
1175
1179
|
} from "@omnicross/core/pipeline/AccountAllowanceStore";
|
|
1176
1180
|
import {
|
|
1177
1181
|
__resetSharedAccountAllowanceSchedulingForTests,
|
|
1178
1182
|
getSharedAccountAllowanceScheduling as getSharedAccountAllowanceScheduling5
|
|
1179
1183
|
} from "@omnicross/core/pipeline/AccountAllowanceScheduling";
|
|
1180
|
-
import { fetchUpstream as
|
|
1184
|
+
import { fetchUpstream as fetchUpstream16, setUpstreamProxyResolver } from "@omnicross/core/pipeline/upstreamFetch";
|
|
1181
1185
|
import { __resetSharedIdentityStoreForTests } from "@omnicross/core/provider-proxy/identity/SubscriptionIdentityStore";
|
|
1182
1186
|
import { setGeminiCodeAssistResolver } from "@omnicross/core/ports/gemini-code-assist-resolver";
|
|
1187
|
+
import { setAntigravitySandboxFailover } from "@omnicross/core/transformer/transformers/antigravityFailover";
|
|
1188
|
+
import { setOpenCodeGoUserAgent } from "@omnicross/core/provider-proxy/identity/openCodeGoHeaders";
|
|
1183
1189
|
import {
|
|
1184
1190
|
__resetProviderProxyForTests,
|
|
1185
1191
|
createNativeResponsesHostedImageIngress,
|
|
@@ -1563,7 +1569,7 @@ function handleCopilotOAuthStatus(sessionId, deps) {
|
|
|
1563
1569
|
|
|
1564
1570
|
// src/allowance/AccountAllowanceService.ts
|
|
1565
1571
|
import {
|
|
1566
|
-
getSharedAccountAllowanceStore as
|
|
1572
|
+
getSharedAccountAllowanceStore as getSharedAccountAllowanceStore9
|
|
1567
1573
|
} from "@omnicross/core/pipeline/AccountAllowanceStore";
|
|
1568
1574
|
import {
|
|
1569
1575
|
getSharedAccountAllowanceScheduling
|
|
@@ -2953,11 +2959,328 @@ var GeminiAllowanceCollector = class {
|
|
|
2953
2959
|
}
|
|
2954
2960
|
};
|
|
2955
2961
|
|
|
2956
|
-
// src/allowance/
|
|
2962
|
+
// src/allowance/AntigravityAllowanceCollector.ts
|
|
2963
|
+
import { ANTIGRAVITY_CODE_ASSIST_ENDPOINT } from "@omnicross/core/auth/GeminiCodeAssistProjectResolver";
|
|
2964
|
+
import {
|
|
2965
|
+
ANTIGRAVITY_COUNTER_TO_MODEL_FAMILY,
|
|
2966
|
+
antigravityCounterFamiliesForBucketId
|
|
2967
|
+
} from "@omnicross/core/pipeline/antigravityQuotaFamily";
|
|
2957
2968
|
import {
|
|
2958
2969
|
getSharedAccountAllowanceStore as getSharedAccountAllowanceStore7
|
|
2959
2970
|
} from "@omnicross/core/pipeline/AccountAllowanceStore";
|
|
2960
2971
|
import { fetchUpstream as fetchUpstream7 } from "@omnicross/core/pipeline/upstreamFetch";
|
|
2972
|
+
import { getAntigravityUserAgent } from "@omnicross/core/transformer/transformers/antigravityIdentity";
|
|
2973
|
+
var ANTIGRAVITY_ALLOWANCE_CACHE_MS = 5 * 6e4;
|
|
2974
|
+
var RETRIEVE_USER_QUOTA_SUMMARY_PATH = "/v1internal:retrieveUserQuotaSummary";
|
|
2975
|
+
var FETCH_AVAILABLE_MODELS_PATH = "/v1internal:fetchAvailableModels";
|
|
2976
|
+
var ANTIGRAVITY_DISCOVERY_DENYLIST = /* @__PURE__ */ new Set([
|
|
2977
|
+
"chat_20706",
|
|
2978
|
+
"chat_23310",
|
|
2979
|
+
"gemini-2.5-pro"
|
|
2980
|
+
]);
|
|
2981
|
+
function isRecord5(value) {
|
|
2982
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
2983
|
+
}
|
|
2984
|
+
function secondsUntil7(instant, now) {
|
|
2985
|
+
if (!instant) return void 0;
|
|
2986
|
+
return Math.max(0, Math.floor((Date.parse(instant) - now) / 1e3));
|
|
2987
|
+
}
|
|
2988
|
+
var WINDOW_LABELS = {
|
|
2989
|
+
"five-hour": "5 Hour",
|
|
2990
|
+
weekly: "Weekly",
|
|
2991
|
+
daily: "Daily"
|
|
2992
|
+
};
|
|
2993
|
+
function classifyWindowId(...sources) {
|
|
2994
|
+
for (const source of sources) {
|
|
2995
|
+
if (!source) continue;
|
|
2996
|
+
const text = source.toLowerCase();
|
|
2997
|
+
if (text.includes("week") || text.includes("7d") || /7[\s_-]*day/.test(text)) return "weekly";
|
|
2998
|
+
if (text.includes("5h") || text.includes("five hour") || /5[\s_-]*hour/.test(text)) return "five-hour";
|
|
2999
|
+
if (text.includes("day") || text.includes("daily") || text.includes("24h")) return "daily";
|
|
3000
|
+
}
|
|
3001
|
+
return void 0;
|
|
3002
|
+
}
|
|
3003
|
+
function inferWindowFromReset(resetsAt, now) {
|
|
3004
|
+
if (resetsAt !== void 0 && Date.parse(resetsAt) - now > 24 * 60 * 60 * 1e3) return "weekly";
|
|
3005
|
+
return "daily";
|
|
3006
|
+
}
|
|
3007
|
+
function clampFraction(value) {
|
|
3008
|
+
if (value === void 0 || !Number.isFinite(value)) return void 0;
|
|
3009
|
+
return Math.min(1, Math.max(0, value));
|
|
3010
|
+
}
|
|
3011
|
+
function usedPercentFromFraction(fraction) {
|
|
3012
|
+
const clamped = clampFraction(fraction);
|
|
3013
|
+
if (clamped === void 0) return null;
|
|
3014
|
+
return Math.round((1 - clamped) * 1e3) / 10;
|
|
3015
|
+
}
|
|
3016
|
+
function toResetsAt(resetTime) {
|
|
3017
|
+
if (!resetTime || !Number.isFinite(Date.parse(resetTime))) return void 0;
|
|
3018
|
+
return new Date(Date.parse(resetTime)).toISOString();
|
|
3019
|
+
}
|
|
3020
|
+
function parseAntigravityQuotaSummary(payload, now) {
|
|
3021
|
+
if (!isRecord5(payload)) return null;
|
|
3022
|
+
const groups = Array.isArray(payload["groups"]) ? payload["groups"] : [];
|
|
3023
|
+
const topBuckets = Array.isArray(payload["buckets"]) ? payload["buckets"] : [];
|
|
3024
|
+
const hasGrouped = groups.some((group) => Array.isArray(group.buckets) && group.buckets.length > 0);
|
|
3025
|
+
if (!hasGrouped && topBuckets.length === 0) return null;
|
|
3026
|
+
const windows = /* @__PURE__ */ new Map();
|
|
3027
|
+
const addBucket = (bucket, groupName) => {
|
|
3028
|
+
const families = antigravityCounterFamiliesForBucketId(bucket.bucketId, groupName);
|
|
3029
|
+
if (families.length === 0) return;
|
|
3030
|
+
const resetsAt = toResetsAt(bucket.resetTime);
|
|
3031
|
+
const windowId = classifyWindowId(bucket.window, bucket.displayName, bucket.bucketId) ?? (resetsAt !== void 0 ? inferWindowFromReset(resetsAt, now) : void 0);
|
|
3032
|
+
if (windowId === void 0) return;
|
|
3033
|
+
const usedPercent = usedPercentFromFraction(bucket.remainingFraction) ?? (bucket.disabled === true || bucket.resetTime ? bucket.disabled === true ? 100 : null : null);
|
|
3034
|
+
for (const family of families) {
|
|
3035
|
+
const id = `antigravity:${family}:${windowId}`;
|
|
3036
|
+
const candidate = {
|
|
3037
|
+
id,
|
|
3038
|
+
label: `${WINDOW_LABELS[windowId]} (${family})`,
|
|
3039
|
+
scope: "model-family",
|
|
3040
|
+
// The window carries the MODEL family (gemini/claude/gpt-oss) — the
|
|
3041
|
+
// scheduling gate compares it against the requested model's family.
|
|
3042
|
+
modelFamily: ANTIGRAVITY_COUNTER_TO_MODEL_FAMILY[family],
|
|
3043
|
+
usedPercent,
|
|
3044
|
+
...resetsAt !== void 0 ? { resetsAt } : {},
|
|
3045
|
+
remainingSeconds: secondsUntil7(resetsAt, now),
|
|
3046
|
+
state: "fresh",
|
|
3047
|
+
...bucket.disabled === true ? { disabled: true } : {}
|
|
3048
|
+
};
|
|
3049
|
+
const existing = windows.get(id);
|
|
3050
|
+
if (!existing || candidate.disabled === true || existing.disabled !== true && (candidate.usedPercent ?? -1) > (existing.usedPercent ?? -1)) {
|
|
3051
|
+
windows.set(id, candidate);
|
|
3052
|
+
}
|
|
3053
|
+
}
|
|
3054
|
+
};
|
|
3055
|
+
if (hasGrouped) {
|
|
3056
|
+
for (const group of groups) {
|
|
3057
|
+
for (const bucket of group.buckets ?? []) addBucket(bucket, group.displayName);
|
|
3058
|
+
}
|
|
3059
|
+
} else {
|
|
3060
|
+
for (const bucket of topBuckets) addBucket(bucket);
|
|
3061
|
+
}
|
|
3062
|
+
const result = [...windows.values()];
|
|
3063
|
+
return result.length > 0 ? result : null;
|
|
3064
|
+
}
|
|
3065
|
+
function legacyQuotaInfos(model) {
|
|
3066
|
+
const out = [];
|
|
3067
|
+
const source = {
|
|
3068
|
+
...model.apiProvider ? { apiProvider: model.apiProvider } : {},
|
|
3069
|
+
...model.modelProvider ? { modelProvider: model.modelProvider } : {}
|
|
3070
|
+
};
|
|
3071
|
+
const add = (value, windowDefault) => {
|
|
3072
|
+
if (!value) return;
|
|
3073
|
+
const list = Array.isArray(value) ? value : [value];
|
|
3074
|
+
for (const info of list) {
|
|
3075
|
+
out.push({ ...source, ...windowDefault ? { windowId: windowDefault } : {}, ...info });
|
|
3076
|
+
}
|
|
3077
|
+
};
|
|
3078
|
+
add(model.quotaInfo);
|
|
3079
|
+
add(model.quotaInfos);
|
|
3080
|
+
add(model.dailyQuotaInfo, "daily");
|
|
3081
|
+
add(model.dailyQuotaInfos, "daily");
|
|
3082
|
+
add(model.weeklyQuotaInfo, "weekly");
|
|
3083
|
+
add(model.weeklyQuotaInfos, "weekly");
|
|
3084
|
+
return out;
|
|
3085
|
+
}
|
|
3086
|
+
function legacyCounterFamily(info) {
|
|
3087
|
+
switch (info.modelProvider ?? info.apiProvider) {
|
|
3088
|
+
case "MODEL_PROVIDER_ANTHROPIC":
|
|
3089
|
+
case "API_PROVIDER_ANTHROPIC_VERTEX":
|
|
3090
|
+
return "anthropic";
|
|
3091
|
+
case "MODEL_PROVIDER_GOOGLE":
|
|
3092
|
+
case "API_PROVIDER_GOOGLE_GEMINI":
|
|
3093
|
+
return "google";
|
|
3094
|
+
case "MODEL_PROVIDER_OPENAI":
|
|
3095
|
+
case "API_PROVIDER_OPENAI_VERTEX":
|
|
3096
|
+
return "openai";
|
|
3097
|
+
default:
|
|
3098
|
+
return void 0;
|
|
3099
|
+
}
|
|
3100
|
+
}
|
|
3101
|
+
function parseAntigravityLegacyQuota(payload, now) {
|
|
3102
|
+
if (!isRecord5(payload)) return null;
|
|
3103
|
+
const models = payload["models"];
|
|
3104
|
+
if (!isRecord5(models)) return null;
|
|
3105
|
+
const windows = /* @__PURE__ */ new Map();
|
|
3106
|
+
for (const info of Object.values(models).flatMap(legacyQuotaInfos)) {
|
|
3107
|
+
const family = legacyCounterFamily(info);
|
|
3108
|
+
if (!family) continue;
|
|
3109
|
+
const resetsAt = toResetsAt(info.resetTime);
|
|
3110
|
+
const windowId = classifyWindowId(info.windowId, info.windowLabel) ?? (resetsAt !== void 0 ? inferWindowFromReset(resetsAt, now) : void 0);
|
|
3111
|
+
if (windowId === void 0) continue;
|
|
3112
|
+
const id = `antigravity:${family}:${windowId}`;
|
|
3113
|
+
const candidate = {
|
|
3114
|
+
id,
|
|
3115
|
+
label: `${WINDOW_LABELS[windowId]} (${family})`,
|
|
3116
|
+
scope: "model-family",
|
|
3117
|
+
modelFamily: ANTIGRAVITY_COUNTER_TO_MODEL_FAMILY[family],
|
|
3118
|
+
usedPercent: usedPercentFromFraction(info.remainingFraction),
|
|
3119
|
+
...resetsAt !== void 0 ? { resetsAt } : {},
|
|
3120
|
+
remainingSeconds: secondsUntil7(resetsAt, now),
|
|
3121
|
+
state: "fresh"
|
|
3122
|
+
};
|
|
3123
|
+
const existing = windows.get(id);
|
|
3124
|
+
if (!existing || (candidate.usedPercent ?? -1) > (existing.usedPercent ?? -1)) {
|
|
3125
|
+
windows.set(id, candidate);
|
|
3126
|
+
}
|
|
3127
|
+
}
|
|
3128
|
+
const result = [...windows.values()];
|
|
3129
|
+
return result.length > 0 ? result : null;
|
|
3130
|
+
}
|
|
3131
|
+
var AntigravityAllowanceCollector = class {
|
|
3132
|
+
constructor(credentials, store = getSharedAccountAllowanceStore7(), fetchImpl = (url, init, accountId) => fetchUpstream7(url, init, { providerId: "antigravity", accountId, redactBodies: true }), now = Date.now) {
|
|
3133
|
+
this.credentials = credentials;
|
|
3134
|
+
this.store = store;
|
|
3135
|
+
this.fetchImpl = fetchImpl;
|
|
3136
|
+
this.now = now;
|
|
3137
|
+
}
|
|
3138
|
+
credentials;
|
|
3139
|
+
store;
|
|
3140
|
+
fetchImpl;
|
|
3141
|
+
now;
|
|
3142
|
+
inFlight = /* @__PURE__ */ new Map();
|
|
3143
|
+
async collectMany(accounts, options = {}) {
|
|
3144
|
+
const settled = await Promise.allSettled(
|
|
3145
|
+
accounts.map((account) => this.collect(account, options))
|
|
3146
|
+
);
|
|
3147
|
+
return settled.flatMap((result) => result.status === "fulfilled" ? [result.value] : []);
|
|
3148
|
+
}
|
|
3149
|
+
collect(account, options = {}) {
|
|
3150
|
+
const now = this.now();
|
|
3151
|
+
if (account.tokens.authMethod !== "oauth") {
|
|
3152
|
+
const existing = this.store.get("antigravity", account.id, now);
|
|
3153
|
+
if (existing?.windows.every((window) => window.state === "unsupported")) {
|
|
3154
|
+
return Promise.resolve(existing);
|
|
3155
|
+
}
|
|
3156
|
+
const snapshot = this.unsupportedSnapshot(account.id, now);
|
|
3157
|
+
this.store.set(snapshot);
|
|
3158
|
+
return Promise.resolve(snapshot);
|
|
3159
|
+
}
|
|
3160
|
+
const cached = this.store.get("antigravity", account.id, now);
|
|
3161
|
+
if (!options.force && cached && this.isCacheValid(cached, now, options.refreshAheadMs)) {
|
|
3162
|
+
return Promise.resolve(cached);
|
|
3163
|
+
}
|
|
3164
|
+
const running = this.inFlight.get(account.id);
|
|
3165
|
+
if (running) return running;
|
|
3166
|
+
const promise = this.fetchAccount(account.id).catch(() => this.failureSnapshot(account.id, "antigravity_usage_request_failed", this.now())).finally(() => this.inFlight.delete(account.id));
|
|
3167
|
+
this.inFlight.set(account.id, promise);
|
|
3168
|
+
return promise;
|
|
3169
|
+
}
|
|
3170
|
+
isCacheValid(snapshot, now, refreshAheadMs) {
|
|
3171
|
+
if (snapshot.windows.every((window) => window.state === "unsupported")) return true;
|
|
3172
|
+
const expiresAt = snapshot.expiresAt ? Date.parse(snapshot.expiresAt) : 0;
|
|
3173
|
+
const ahead = typeof refreshAheadMs === "number" && Number.isFinite(refreshAheadMs) ? Math.max(0, refreshAheadMs) : 0;
|
|
3174
|
+
return Number.isFinite(expiresAt) && expiresAt > now + ahead;
|
|
3175
|
+
}
|
|
3176
|
+
async fetchAccount(accountId) {
|
|
3177
|
+
let accessToken = await this.credentials.getAccessTokenForAccount("antigravity", accountId);
|
|
3178
|
+
if (!accessToken) return this.failureSnapshot(accountId, "antigravity_usage_token_unavailable", this.now());
|
|
3179
|
+
let response = await this.request(accountId, accessToken, RETRIEVE_USER_QUOTA_SUMMARY_PATH, {
|
|
3180
|
+
project: void 0
|
|
3181
|
+
});
|
|
3182
|
+
if (response.status === 401 || response.status === 403) {
|
|
3183
|
+
const refreshed = await this.credentials.refreshAccountToken("antigravity", accountId);
|
|
3184
|
+
if (!refreshed) return this.failureSnapshot(accountId, "antigravity_usage_unauthorized", this.now());
|
|
3185
|
+
accessToken = await this.credentials.getAccessTokenForAccount("antigravity", accountId);
|
|
3186
|
+
if (!accessToken) return this.failureSnapshot(accountId, "antigravity_usage_token_unavailable", this.now());
|
|
3187
|
+
response = await this.request(accountId, accessToken, RETRIEVE_USER_QUOTA_SUMMARY_PATH, {
|
|
3188
|
+
project: void 0
|
|
3189
|
+
});
|
|
3190
|
+
if (response.status === 401 || response.status === 403) {
|
|
3191
|
+
return this.failureSnapshot(accountId, "antigravity_usage_unauthorized", this.now());
|
|
3192
|
+
}
|
|
3193
|
+
}
|
|
3194
|
+
if (response.ok) {
|
|
3195
|
+
const payload = await response.json().catch(() => null);
|
|
3196
|
+
const windows = parseAntigravityQuotaSummary(payload, this.now());
|
|
3197
|
+
if (windows) {
|
|
3198
|
+
const snapshot2 = this.snapshot(accountId, windows);
|
|
3199
|
+
this.store.set(snapshot2);
|
|
3200
|
+
return snapshot2;
|
|
3201
|
+
}
|
|
3202
|
+
}
|
|
3203
|
+
const legacy = await this.request(accountId, accessToken, FETCH_AVAILABLE_MODELS_PATH, {});
|
|
3204
|
+
if (!legacy.ok) {
|
|
3205
|
+
return this.failureSnapshot(accountId, "antigravity_usage_http_error", this.now());
|
|
3206
|
+
}
|
|
3207
|
+
const legacyPayload = await legacy.json().catch(() => null);
|
|
3208
|
+
const legacyWindows = parseAntigravityLegacyQuota(legacyPayload, this.now());
|
|
3209
|
+
if (!legacyWindows) {
|
|
3210
|
+
return this.failureSnapshot(accountId, "antigravity_usage_invalid_response", this.now());
|
|
3211
|
+
}
|
|
3212
|
+
const snapshot = this.snapshot(accountId, legacyWindows);
|
|
3213
|
+
this.store.set(snapshot);
|
|
3214
|
+
return snapshot;
|
|
3215
|
+
}
|
|
3216
|
+
/** One upstream round-trip with the antigravity/hub masquerade UA. */
|
|
3217
|
+
request(accountId, accessToken, path2, body) {
|
|
3218
|
+
return this.fetchImpl(`${ANTIGRAVITY_CODE_ASSIST_ENDPOINT}${path2}`, {
|
|
3219
|
+
method: "POST",
|
|
3220
|
+
headers: {
|
|
3221
|
+
Authorization: `Bearer ${accessToken}`,
|
|
3222
|
+
Accept: "application/json",
|
|
3223
|
+
"Content-Type": "application/json",
|
|
3224
|
+
"User-Agent": getAntigravityUserAgent()
|
|
3225
|
+
},
|
|
3226
|
+
body: JSON.stringify(body),
|
|
3227
|
+
signal: AbortSignal.timeout(15e3)
|
|
3228
|
+
}, accountId);
|
|
3229
|
+
}
|
|
3230
|
+
snapshot(accountId, windows, now = this.now()) {
|
|
3231
|
+
return {
|
|
3232
|
+
providerId: "antigravity",
|
|
3233
|
+
accountId,
|
|
3234
|
+
source: "oauth-usage-api",
|
|
3235
|
+
observedAt: new Date(now).toISOString(),
|
|
3236
|
+
expiresAt: new Date(now + ANTIGRAVITY_ALLOWANCE_CACHE_MS).toISOString(),
|
|
3237
|
+
windows
|
|
3238
|
+
};
|
|
3239
|
+
}
|
|
3240
|
+
failureSnapshot(accountId, code, now) {
|
|
3241
|
+
const existing = this.store.get("antigravity", accountId, now);
|
|
3242
|
+
const snapshot = existing ? {
|
|
3243
|
+
...existing,
|
|
3244
|
+
expiresAt: new Date(now + ANTIGRAVITY_ALLOWANCE_CACHE_MS).toISOString(),
|
|
3245
|
+
windows: existing.windows.map((window) => ({
|
|
3246
|
+
...window,
|
|
3247
|
+
state: window.state === "unsupported" ? "unsupported" : window.usedPercent !== null || window.resetsAt || window.disabled ? "stale" : "unavailable"
|
|
3248
|
+
})),
|
|
3249
|
+
lastErrorCode: code
|
|
3250
|
+
} : {
|
|
3251
|
+
providerId: "antigravity",
|
|
3252
|
+
accountId,
|
|
3253
|
+
source: "oauth-usage-api",
|
|
3254
|
+
observedAt: new Date(now).toISOString(),
|
|
3255
|
+
expiresAt: new Date(now + ANTIGRAVITY_ALLOWANCE_CACHE_MS).toISOString(),
|
|
3256
|
+
windows: [
|
|
3257
|
+
{ id: "antigravity-quota", label: "Antigravity quota", scope: "all", usedPercent: null, state: "unavailable" }
|
|
3258
|
+
],
|
|
3259
|
+
lastErrorCode: code
|
|
3260
|
+
};
|
|
3261
|
+
this.store.set(snapshot);
|
|
3262
|
+
return snapshot;
|
|
3263
|
+
}
|
|
3264
|
+
unsupportedSnapshot(accountId, now) {
|
|
3265
|
+
return {
|
|
3266
|
+
providerId: "antigravity",
|
|
3267
|
+
accountId,
|
|
3268
|
+
source: "oauth-usage-api",
|
|
3269
|
+
observedAt: new Date(now).toISOString(),
|
|
3270
|
+
windows: [
|
|
3271
|
+
{ id: "antigravity-quota", label: "Antigravity quota", scope: "all", usedPercent: null, state: "unsupported" }
|
|
3272
|
+
],
|
|
3273
|
+
lastErrorCode: "antigravity_usage_unsupported_auth"
|
|
3274
|
+
};
|
|
3275
|
+
}
|
|
3276
|
+
};
|
|
3277
|
+
|
|
3278
|
+
// src/allowance/OpenCodeGoAllowanceCollector.ts
|
|
3279
|
+
import {
|
|
3280
|
+
getSharedAccountAllowanceStore as getSharedAccountAllowanceStore8
|
|
3281
|
+
} from "@omnicross/core/pipeline/AccountAllowanceStore";
|
|
3282
|
+
import { fetchUpstream as fetchUpstream8 } from "@omnicross/core/pipeline/upstreamFetch";
|
|
3283
|
+
import { getOpenCodeGoUserAgent } from "@omnicross/core/provider-proxy/identity/openCodeGoHeaders";
|
|
2961
3284
|
import { normalizeOpenCodeGoBaseUrl } from "@omnicross/subscriptions";
|
|
2962
3285
|
var OPENCODEGO_ALLOWANCE_CACHE_MS = 5 * 6e4;
|
|
2963
3286
|
var OPENCODEGO_DEFAULT_GO_BASE = "https://opencode.ai/zen/go";
|
|
@@ -2971,7 +3294,7 @@ function isoInstant2(value) {
|
|
|
2971
3294
|
const time = Date.parse(value);
|
|
2972
3295
|
return Number.isFinite(time) ? new Date(time).toISOString() : void 0;
|
|
2973
3296
|
}
|
|
2974
|
-
function
|
|
3297
|
+
function secondsUntil8(instant, now) {
|
|
2975
3298
|
if (!instant) return void 0;
|
|
2976
3299
|
return Math.max(0, Math.floor((Date.parse(instant) - now) / 1e3));
|
|
2977
3300
|
}
|
|
@@ -2986,12 +3309,12 @@ function windowFromPayload3(id, label, minutes, payload, now) {
|
|
|
2986
3309
|
usedPercent,
|
|
2987
3310
|
windowMinutes: minutes,
|
|
2988
3311
|
...resetsAt !== void 0 ? { resetsAt } : {},
|
|
2989
|
-
remainingSeconds:
|
|
3312
|
+
remainingSeconds: secondsUntil8(resetsAt, now),
|
|
2990
3313
|
state: usedPercent !== null || resetsAt ? "fresh" : "unavailable"
|
|
2991
3314
|
};
|
|
2992
3315
|
}
|
|
2993
3316
|
var OpenCodeGoAllowanceCollector = class {
|
|
2994
|
-
constructor(credentials, store =
|
|
3317
|
+
constructor(credentials, store = getSharedAccountAllowanceStore8(), fetchImpl = (url, init, accountId) => fetchUpstream8(url, init, { providerId: "opencodego", accountId, redactBodies: true }), now = Date.now) {
|
|
2995
3318
|
this.credentials = credentials;
|
|
2996
3319
|
this.store = store;
|
|
2997
3320
|
this.fetchImpl = fetchImpl;
|
|
@@ -3024,7 +3347,14 @@ var OpenCodeGoAllowanceCollector = class {
|
|
|
3024
3347
|
const base = account.tokens.baseUrl ? normalizeOpenCodeGoBaseUrl(account.tokens.baseUrl) : OPENCODEGO_DEFAULT_GO_BASE;
|
|
3025
3348
|
const response = await this.fetchImpl(`${base}/v1/usage`, {
|
|
3026
3349
|
method: "GET",
|
|
3027
|
-
|
|
3350
|
+
// opencodego-egress-identity: the background poll identifies itself with
|
|
3351
|
+
// the same configured/default UA the relay carries (no session header —
|
|
3352
|
+
// a poll has no conversation).
|
|
3353
|
+
headers: {
|
|
3354
|
+
Authorization: `Bearer ${apiKey}`,
|
|
3355
|
+
Accept: "application/json",
|
|
3356
|
+
"User-Agent": getOpenCodeGoUserAgent()
|
|
3357
|
+
},
|
|
3028
3358
|
signal: AbortSignal.timeout(15e3)
|
|
3029
3359
|
}, account.id);
|
|
3030
3360
|
if (response.status === 401 || response.status === 403) {
|
|
@@ -3096,7 +3426,7 @@ function codexUnavailable(accountId, now) {
|
|
|
3096
3426
|
};
|
|
3097
3427
|
}
|
|
3098
3428
|
var AccountAllowanceService = class {
|
|
3099
|
-
constructor(credentials, store =
|
|
3429
|
+
constructor(credentials, store = getSharedAccountAllowanceStore9(), collector, codexCollector, kimiCollector, opencodegoCollector, grokCollector, copilotCollector, geminiCollector, antigravityCollector, now = Date.now) {
|
|
3100
3430
|
this.credentials = credentials;
|
|
3101
3431
|
this.store = store;
|
|
3102
3432
|
this.now = now;
|
|
@@ -3107,6 +3437,7 @@ var AccountAllowanceService = class {
|
|
|
3107
3437
|
this.grokCollector = grokCollector ?? new GrokAllowanceCollector(credentials, store);
|
|
3108
3438
|
this.copilotCollector = copilotCollector ?? new CopilotAllowanceCollector(credentials, store);
|
|
3109
3439
|
this.geminiCollector = geminiCollector ?? new GeminiAllowanceCollector(credentials, store);
|
|
3440
|
+
this.antigravityCollector = antigravityCollector ?? new AntigravityAllowanceCollector(credentials, store);
|
|
3110
3441
|
}
|
|
3111
3442
|
credentials;
|
|
3112
3443
|
store;
|
|
@@ -3118,6 +3449,7 @@ var AccountAllowanceService = class {
|
|
|
3118
3449
|
copilotCollector;
|
|
3119
3450
|
opencodegoCollector;
|
|
3120
3451
|
geminiCollector;
|
|
3452
|
+
antigravityCollector;
|
|
3121
3453
|
/**
|
|
3122
3454
|
* Read all/filtered snapshots. Claude's and Codex's five-minute caches are
|
|
3123
3455
|
* refreshed lazily on read (Codex polls `/backend-api/wham/usage`; the
|
|
@@ -3166,6 +3498,11 @@ var AccountAllowanceService = class {
|
|
|
3166
3498
|
(account) => !filter.accountId || account.id === filter.accountId
|
|
3167
3499
|
);
|
|
3168
3500
|
if (wantsGemini) await this.geminiCollector.collectMany(geminiAccounts);
|
|
3501
|
+
const wantsAntigravity = !filter.providerId || filter.providerId === "antigravity";
|
|
3502
|
+
const antigravityAccounts = (config.antigravityAccounts ?? []).filter(
|
|
3503
|
+
(account) => !filter.accountId || account.id === filter.accountId
|
|
3504
|
+
);
|
|
3505
|
+
if (wantsAntigravity) await this.antigravityCollector.collectMany(antigravityAccounts);
|
|
3169
3506
|
const known = /* @__PURE__ */ new Set();
|
|
3170
3507
|
if (wantsClaude) for (const account of claudeAccounts) known.add(`claude\0${account.id}`);
|
|
3171
3508
|
if (wantsCodex) for (const account of codexAccounts) known.add(`codex\0${account.id}`);
|
|
@@ -3174,6 +3511,7 @@ var AccountAllowanceService = class {
|
|
|
3174
3511
|
if (wantsGrok) for (const account of grokAccounts) known.add(`grok\0${account.id}`);
|
|
3175
3512
|
if (wantsCopilot) for (const account of copilotAccounts) known.add(`copilot\0${account.id}`);
|
|
3176
3513
|
if (wantsGemini) for (const account of geminiAccounts) known.add(`gemini\0${account.id}`);
|
|
3514
|
+
if (wantsAntigravity) for (const account of antigravityAccounts) known.add(`antigravity\0${account.id}`);
|
|
3177
3515
|
return this.store.list(filter).filter((snapshot) => known.has(`${snapshot.providerId}\0${snapshot.accountId}`));
|
|
3178
3516
|
}
|
|
3179
3517
|
knownAccounts(config) {
|
|
@@ -3184,7 +3522,8 @@ var AccountAllowanceService = class {
|
|
|
3184
3522
|
...(config.opencodegoAccounts ?? []).map((account) => ({ providerId: "opencodego", accountId: account.id })),
|
|
3185
3523
|
...(config.grokAccounts ?? []).map((account) => ({ providerId: "grok", accountId: account.id })),
|
|
3186
3524
|
...(config.copilotAccounts ?? []).map((account) => ({ providerId: "copilot", accountId: account.id })),
|
|
3187
|
-
...(config.geminiAccounts ?? []).map((account) => ({ providerId: "gemini", accountId: account.id }))
|
|
3525
|
+
...(config.geminiAccounts ?? []).map((account) => ({ providerId: "gemini", accountId: account.id })),
|
|
3526
|
+
...(config.antigravityAccounts ?? []).map((account) => ({ providerId: "antigravity", accountId: account.id }))
|
|
3188
3527
|
];
|
|
3189
3528
|
}
|
|
3190
3529
|
/** Force-refresh Claude usage for one account or every stored Claude account. */
|
|
@@ -3254,6 +3593,15 @@ var AccountAllowanceService = class {
|
|
|
3254
3593
|
);
|
|
3255
3594
|
return this.geminiCollector.collectMany(accounts, { force: true });
|
|
3256
3595
|
}
|
|
3596
|
+
/** Force-refresh Antigravity usage (quotaSummary dual buckets) for one/all accounts. */
|
|
3597
|
+
async refreshAntigravity(accountId) {
|
|
3598
|
+
const config = await this.credentials.getFullConfig();
|
|
3599
|
+
this.store.pruneToKnownAccounts(this.knownAccounts(config));
|
|
3600
|
+
const accounts = (config.antigravityAccounts ?? []).filter(
|
|
3601
|
+
(account) => !accountId || account.id === accountId
|
|
3602
|
+
);
|
|
3603
|
+
return this.antigravityCollector.collectMany(accounts, { force: true });
|
|
3604
|
+
}
|
|
3257
3605
|
/**
|
|
3258
3606
|
* Keep Claude + Codex + Kimi snapshots warm for allowance-aware routing. All
|
|
3259
3607
|
* collectors preserve their cache + per-account in-flight coalescing; a tick
|
|
@@ -3271,6 +3619,7 @@ var AccountAllowanceService = class {
|
|
|
3271
3619
|
await this.grokCollector.collectMany(config.grokAccounts ?? [], { refreshAheadMs });
|
|
3272
3620
|
await this.copilotCollector.collectMany(config.copilotAccounts ?? [], { refreshAheadMs });
|
|
3273
3621
|
await this.geminiCollector.collectMany(config.geminiAccounts ?? [], { refreshAheadMs });
|
|
3622
|
+
await this.antigravityCollector.collectMany(config.antigravityAccounts ?? [], { refreshAheadMs });
|
|
3274
3623
|
}
|
|
3275
3624
|
/** Remove a cache row as soon as an account is deleted by the admin path. */
|
|
3276
3625
|
removeAccountSnapshot(providerId, accountId) {
|
|
@@ -3700,7 +4049,7 @@ import {
|
|
|
3700
4049
|
} from "@omnicross/contracts/image-generation-types";
|
|
3701
4050
|
import { getSharedAccountAllowanceScheduling as getSharedAccountAllowanceScheduling2 } from "@omnicross/core/pipeline/AccountAllowanceScheduling";
|
|
3702
4051
|
import { getSharedAccountHealth } from "@omnicross/core/pipeline/SubscriptionAccountHealth";
|
|
3703
|
-
import { fetchUpstream as
|
|
4052
|
+
import { fetchUpstream as fetchUpstream10 } from "@omnicross/core/pipeline/upstreamFetch";
|
|
3704
4053
|
import { mergeExtraHeaders } from "@omnicross/core";
|
|
3705
4054
|
|
|
3706
4055
|
// src/image-generation/imagesConfigValidation.ts
|
|
@@ -4034,6 +4383,19 @@ function resolveAdminConfig(admin) {
|
|
|
4034
4383
|
token: typeof admin?.token === "string" && admin.token.length > 0 ? admin.token : void 0
|
|
4035
4384
|
};
|
|
4036
4385
|
}
|
|
4386
|
+
function validateAntigravity(raw) {
|
|
4387
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return void 0;
|
|
4388
|
+
const a = raw;
|
|
4389
|
+
if (typeof a["sandboxFailover"] !== "boolean") return void 0;
|
|
4390
|
+
return { sandboxFailover: a["sandboxFailover"] };
|
|
4391
|
+
}
|
|
4392
|
+
function validateOpenCodeGo(raw) {
|
|
4393
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return void 0;
|
|
4394
|
+
const o = raw;
|
|
4395
|
+
const ua = o["userAgent"];
|
|
4396
|
+
if (typeof ua !== "string" || ua.trim().length === 0) return void 0;
|
|
4397
|
+
return { userAgent: ua.trim() };
|
|
4398
|
+
}
|
|
4037
4399
|
function validateUsage(raw) {
|
|
4038
4400
|
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return void 0;
|
|
4039
4401
|
const u = raw;
|
|
@@ -4327,7 +4689,9 @@ function validateConfig(raw) {
|
|
|
4327
4689
|
const admin = validateAdmin(obj["admin"]);
|
|
4328
4690
|
const logging = validateLogging(obj["logging"]);
|
|
4329
4691
|
const usage = validateUsage(obj["usage"]);
|
|
4330
|
-
|
|
4692
|
+
const antigravity = validateAntigravity(obj["antigravity"]);
|
|
4693
|
+
const opencodego = validateOpenCodeGo(obj["opencodego"]);
|
|
4694
|
+
return { providers, server, admin, logging, usage, antigravity, opencodego };
|
|
4331
4695
|
}
|
|
4332
4696
|
var secretBox = null;
|
|
4333
4697
|
function setSecretBox(box) {
|
|
@@ -5455,6 +5819,167 @@ function createUpstreamProxyResolver(src = {}) {
|
|
|
5455
5819
|
};
|
|
5456
5820
|
}
|
|
5457
5821
|
|
|
5822
|
+
// src/admin/accountsAntigravityOAuth.ts
|
|
5823
|
+
import { getAntigravityProjectResolver } from "@omnicross/core/auth/GeminiCodeAssistProjectResolver";
|
|
5824
|
+
import { antigravityOAuth } from "@omnicross/subscriptions";
|
|
5825
|
+
function err5(status, message) {
|
|
5826
|
+
return { status, body: { error: { type: "admin_api_error", message } } };
|
|
5827
|
+
}
|
|
5828
|
+
var DEFAULT_ANTIGRAVITY_OAUTH_TTL_MS = 10 * 6e4;
|
|
5829
|
+
function handleAntigravityOAuthStart(deps) {
|
|
5830
|
+
if (deps.antigravitySessions.isBusy()) {
|
|
5831
|
+
return err5(
|
|
5832
|
+
409,
|
|
5833
|
+
"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"
|
|
5834
|
+
);
|
|
5835
|
+
}
|
|
5836
|
+
const { authUrl, state } = antigravityOAuth.generateAuthParams();
|
|
5837
|
+
const { sessionId, signal } = deps.antigravitySessions.begin();
|
|
5838
|
+
void runAntigravityLoopback(sessionId, state, signal, deps);
|
|
5839
|
+
return { status: 200, body: { authUrl, sessionId } };
|
|
5840
|
+
}
|
|
5841
|
+
async function runAntigravityLoopback(sessionId, state, signal, deps) {
|
|
5842
|
+
const isPending = () => !signal.aborted && deps.antigravitySessions.get(sessionId)?.status === "pending";
|
|
5843
|
+
try {
|
|
5844
|
+
const code = await deps.antigravityAwaitLoopback(state, void 0, signal);
|
|
5845
|
+
if (!isPending()) return;
|
|
5846
|
+
const exchangeFetch = deps.oauthExchangeFetch("antigravity");
|
|
5847
|
+
const result = await antigravityOAuth.exchangeCodeForTokens(code, exchangeFetch);
|
|
5848
|
+
if (!isPending()) return;
|
|
5849
|
+
const expiresAt = new Date(Date.now() + result.expiresIn * 1e3).toISOString();
|
|
5850
|
+
const email = await antigravityOAuth.fetchUserEmail(result.accessToken, exchangeFetch);
|
|
5851
|
+
if (!isPending()) return;
|
|
5852
|
+
const projectId = await getAntigravityProjectResolver().resolveProject(result.accessToken);
|
|
5853
|
+
if (!isPending()) return;
|
|
5854
|
+
const block = {
|
|
5855
|
+
authMethod: "oauth",
|
|
5856
|
+
status: "authorized",
|
|
5857
|
+
accessToken: result.accessToken,
|
|
5858
|
+
refreshToken: result.refreshToken,
|
|
5859
|
+
expiresAt,
|
|
5860
|
+
...email ? { email } : {},
|
|
5861
|
+
...projectId ? { projectId } : {},
|
|
5862
|
+
lastRefreshedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
5863
|
+
};
|
|
5864
|
+
await deps.subscriptionAccountAppender.appendProviderAccount("antigravity", block);
|
|
5865
|
+
if (isPending()) deps.antigravitySessions.settle(sessionId, "done");
|
|
5866
|
+
} catch (e) {
|
|
5867
|
+
if (!isPending()) return;
|
|
5868
|
+
const reason = e instanceof Error ? e.message : "antigravity sign-in failed";
|
|
5869
|
+
deps.antigravitySessions.settle(sessionId, "error", reason);
|
|
5870
|
+
}
|
|
5871
|
+
}
|
|
5872
|
+
function handleAntigravityOAuthCancel(sessionId, deps) {
|
|
5873
|
+
if (!deps.antigravitySessions.cancel(sessionId)) {
|
|
5874
|
+
return err5(404, "unknown or expired antigravity sign-in session");
|
|
5875
|
+
}
|
|
5876
|
+
return { status: 200, body: { ok: true } };
|
|
5877
|
+
}
|
|
5878
|
+
function handleAntigravityOAuthStatus(sessionId, deps) {
|
|
5879
|
+
const s = deps.antigravitySessions.get(sessionId);
|
|
5880
|
+
if (!s) return err5(404, "unknown or expired antigravity sign-in session");
|
|
5881
|
+
return { status: 200, body: { state: s.status, ...s.error ? { message: s.error } : {} } };
|
|
5882
|
+
}
|
|
5883
|
+
|
|
5884
|
+
// src/allowance/AntigravityModelDiscovery.ts
|
|
5885
|
+
import { lookupCanonicalCapabilities } from "@omnicross/contracts/canonical-models";
|
|
5886
|
+
import { SUBSCRIPTION_MODEL_CATALOG } from "@omnicross/contracts/subscription-model-catalog";
|
|
5887
|
+
import { ANTIGRAVITY_CODE_ASSIST_ENDPOINT as ANTIGRAVITY_CODE_ASSIST_ENDPOINT2 } from "@omnicross/core/auth/GeminiCodeAssistProjectResolver";
|
|
5888
|
+
import { fetchUpstream as fetchUpstream9 } from "@omnicross/core/pipeline/upstreamFetch";
|
|
5889
|
+
import { getAntigravityUserAgent as getAntigravityUserAgent2 } from "@omnicross/core/transformer/transformers/antigravityIdentity";
|
|
5890
|
+
function isRecord6(value) {
|
|
5891
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
5892
|
+
}
|
|
5893
|
+
function optionalString(value) {
|
|
5894
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
5895
|
+
}
|
|
5896
|
+
function optionalNumber(value) {
|
|
5897
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : void 0;
|
|
5898
|
+
}
|
|
5899
|
+
function optionalBoolean(value) {
|
|
5900
|
+
return typeof value === "boolean" ? value : void 0;
|
|
5901
|
+
}
|
|
5902
|
+
function parseAntigravityAvailableModels(payload) {
|
|
5903
|
+
if (!isRecord6(payload)) return [];
|
|
5904
|
+
const models = payload["models"];
|
|
5905
|
+
if (!isRecord6(models)) return [];
|
|
5906
|
+
const out = [];
|
|
5907
|
+
for (const [id, raw] of Object.entries(models)) {
|
|
5908
|
+
if (ANTIGRAVITY_DISCOVERY_DENYLIST.has(id)) continue;
|
|
5909
|
+
if (!isRecord6(raw)) continue;
|
|
5910
|
+
if (raw["isInternal"] === true) continue;
|
|
5911
|
+
out.push({
|
|
5912
|
+
id,
|
|
5913
|
+
...optionalString(raw["displayName"]) ? { displayName: optionalString(raw["displayName"]) } : {},
|
|
5914
|
+
...optionalBoolean(raw["supportsImages"]) !== void 0 ? { supportsImages: optionalBoolean(raw["supportsImages"]) } : {},
|
|
5915
|
+
...optionalBoolean(raw["supportsThinking"]) !== void 0 ? { supportsThinking: optionalBoolean(raw["supportsThinking"]) } : {},
|
|
5916
|
+
...optionalNumber(raw["thinkingBudget"]) !== void 0 ? { thinkingBudget: optionalNumber(raw["thinkingBudget"]) } : {},
|
|
5917
|
+
...optionalNumber(raw["maxTokens"]) !== void 0 ? { maxTokens: optionalNumber(raw["maxTokens"]) } : {},
|
|
5918
|
+
...optionalNumber(raw["maxOutputTokens"]) !== void 0 ? { maxOutputTokens: optionalNumber(raw["maxOutputTokens"]) } : {}
|
|
5919
|
+
});
|
|
5920
|
+
}
|
|
5921
|
+
out.sort((a, b) => a.id.localeCompare(b.id));
|
|
5922
|
+
return out;
|
|
5923
|
+
}
|
|
5924
|
+
function mergeAntigravityCatalog(discovered, log = (line) => console.warn(line), staticIds = SUBSCRIPTION_MODEL_CATALOG.antigravity) {
|
|
5925
|
+
const entries = staticIds.map((id) => {
|
|
5926
|
+
const capabilities = lookupCanonicalCapabilities(id);
|
|
5927
|
+
return {
|
|
5928
|
+
id,
|
|
5929
|
+
origin: "static",
|
|
5930
|
+
displayName: id,
|
|
5931
|
+
...capabilities?.vision !== void 0 ? { supportsImages: capabilities.vision } : {},
|
|
5932
|
+
...capabilities?.reasoning !== void 0 ? { supportsThinking: capabilities.reasoning } : {},
|
|
5933
|
+
...capabilities?.thinkingTokenLimit ? { thinkingBudget: capabilities.thinkingTokenLimit.max } : {},
|
|
5934
|
+
// Discovery calls the context window maxTokens, not the output ceiling.
|
|
5935
|
+
...capabilities?.contextLength !== void 0 ? { maxTokens: capabilities.contextLength } : {},
|
|
5936
|
+
...capabilities?.maxTokens !== void 0 ? { maxOutputTokens: capabilities.maxTokens } : {}
|
|
5937
|
+
};
|
|
5938
|
+
});
|
|
5939
|
+
const staticSet = new Set(staticIds);
|
|
5940
|
+
for (const model of discovered) {
|
|
5941
|
+
if (staticSet.has(model.id)) {
|
|
5942
|
+
log(
|
|
5943
|
+
`[AntigravityModelDiscovery] dynamic model '${model.id}' conflicts with the static catalog \u2014 static entry kept`
|
|
5944
|
+
);
|
|
5945
|
+
continue;
|
|
5946
|
+
}
|
|
5947
|
+
entries.push({ ...model, origin: "discovered" });
|
|
5948
|
+
}
|
|
5949
|
+
return entries;
|
|
5950
|
+
}
|
|
5951
|
+
async function fetchAntigravityAvailableModels(accessToken, fetchImpl = (url, init) => fetchUpstream9(url, init, { providerId: "antigravity", redactBodies: true })) {
|
|
5952
|
+
let response;
|
|
5953
|
+
try {
|
|
5954
|
+
response = await fetchImpl(`${ANTIGRAVITY_CODE_ASSIST_ENDPOINT2}/v1internal:fetchAvailableModels`, {
|
|
5955
|
+
method: "POST",
|
|
5956
|
+
headers: {
|
|
5957
|
+
Authorization: `Bearer ${accessToken}`,
|
|
5958
|
+
Accept: "application/json",
|
|
5959
|
+
"Content-Type": "application/json",
|
|
5960
|
+
"User-Agent": getAntigravityUserAgent2()
|
|
5961
|
+
},
|
|
5962
|
+
body: JSON.stringify({}),
|
|
5963
|
+
signal: AbortSignal.timeout(15e3)
|
|
5964
|
+
});
|
|
5965
|
+
} catch {
|
|
5966
|
+
return null;
|
|
5967
|
+
}
|
|
5968
|
+
if (!response.ok) return null;
|
|
5969
|
+
const payload = await response.json().catch(() => null);
|
|
5970
|
+
if (!isRecord6(payload) || !isRecord6(payload["models"])) return null;
|
|
5971
|
+
return parseAntigravityAvailableModels(payload);
|
|
5972
|
+
}
|
|
5973
|
+
async function handleAntigravityModelsRoute(deps) {
|
|
5974
|
+
const accessToken = await deps.resolveAntigravityAccessToken().catch(() => null);
|
|
5975
|
+
const discovered = accessToken ? await fetchAntigravityAvailableModels(accessToken, deps.fetchImpl) : null;
|
|
5976
|
+
const models = mergeAntigravityCatalog(discovered ?? []);
|
|
5977
|
+
return {
|
|
5978
|
+
status: 200,
|
|
5979
|
+
body: { models, discovered: discovered !== null }
|
|
5980
|
+
};
|
|
5981
|
+
}
|
|
5982
|
+
|
|
5458
5983
|
// src/admin/accountsOAuth.ts
|
|
5459
5984
|
import { claudeOAuth, geminiOAuth } from "@omnicross/subscriptions";
|
|
5460
5985
|
|
|
@@ -5466,7 +5991,8 @@ var VALID_PROVIDER_IDS = [
|
|
|
5466
5991
|
"opencodego",
|
|
5467
5992
|
"kimi",
|
|
5468
5993
|
"grok",
|
|
5469
|
-
"copilot"
|
|
5994
|
+
"copilot",
|
|
5995
|
+
"antigravity"
|
|
5470
5996
|
];
|
|
5471
5997
|
function asSubscriptionProviderId(id) {
|
|
5472
5998
|
return VALID_PROVIDER_IDS.includes(id) ? id : null;
|
|
@@ -5648,7 +6174,7 @@ function validateCopilot(body) {
|
|
|
5648
6174
|
]);
|
|
5649
6175
|
return out;
|
|
5650
6176
|
}
|
|
5651
|
-
function
|
|
6177
|
+
function validateOpenCodeGo2(body) {
|
|
5652
6178
|
const authMethod = str(body["authMethod"]);
|
|
5653
6179
|
const status = str(body["status"]);
|
|
5654
6180
|
if (authMethod !== "manual") return null;
|
|
@@ -5682,7 +6208,7 @@ function validateTokenBody(providerId, body) {
|
|
|
5682
6208
|
case "gemini":
|
|
5683
6209
|
return validateGemini(body);
|
|
5684
6210
|
case "opencodego":
|
|
5685
|
-
return
|
|
6211
|
+
return validateOpenCodeGo2(body);
|
|
5686
6212
|
case "kimi":
|
|
5687
6213
|
return validateKimi(body);
|
|
5688
6214
|
case "grok":
|
|
@@ -5718,12 +6244,12 @@ async function statusEntryFor(reader, providerId) {
|
|
|
5718
6244
|
|
|
5719
6245
|
// src/admin/accountsOAuth.ts
|
|
5720
6246
|
var OAUTH_HTTP_PROVIDERS = /* @__PURE__ */ new Set(["claude", "gemini"]);
|
|
5721
|
-
function
|
|
6247
|
+
function err6(status, message) {
|
|
5722
6248
|
return { status, body: { error: { type: "admin_api_error", message } } };
|
|
5723
6249
|
}
|
|
5724
6250
|
function handleOAuthStart(providerId, deps) {
|
|
5725
6251
|
if (!OAUTH_HTTP_PROVIDERS.has(providerId)) {
|
|
5726
|
-
return
|
|
6252
|
+
return err6(400, `oauth not available for provider '${providerId}'`);
|
|
5727
6253
|
}
|
|
5728
6254
|
const flow = providerId === "claude" ? claudeOAuth : geminiOAuth;
|
|
5729
6255
|
const { authUrl, codeVerifier, state } = flow.generateAuthParams();
|
|
@@ -5732,23 +6258,23 @@ function handleOAuthStart(providerId, deps) {
|
|
|
5732
6258
|
}
|
|
5733
6259
|
async function handleOAuthComplete(providerId, body, deps) {
|
|
5734
6260
|
if (!OAUTH_HTTP_PROVIDERS.has(providerId)) {
|
|
5735
|
-
return
|
|
6261
|
+
return err6(400, `oauth not available for provider '${providerId}'`);
|
|
5736
6262
|
}
|
|
5737
6263
|
const sessionId = typeof body["sessionId"] === "string" ? body["sessionId"] : "";
|
|
5738
6264
|
const rawCode = typeof body["code"] === "string" ? body["code"] : "";
|
|
5739
|
-
if (!sessionId) return
|
|
5740
|
-
if (!rawCode) return
|
|
6265
|
+
if (!sessionId) return err6(400, "oauth complete requires { sessionId }");
|
|
6266
|
+
if (!rawCode) return err6(400, "oauth complete requires { code }");
|
|
5741
6267
|
const session = deps.oauthSessions.peek(sessionId);
|
|
5742
|
-
if (!session) return
|
|
6268
|
+
if (!session) return err6(410, "oauth session is unknown, expired, or already used");
|
|
5743
6269
|
if (session.providerId !== providerId) {
|
|
5744
|
-
return
|
|
6270
|
+
return err6(400, `oauth session does not match provider '${providerId}'`);
|
|
5745
6271
|
}
|
|
5746
6272
|
let code = rawCode.trim();
|
|
5747
6273
|
if (providerId === "claude") {
|
|
5748
6274
|
const [splitCode, pastedState] = code.split("#");
|
|
5749
|
-
if (!splitCode) return
|
|
6275
|
+
if (!splitCode) return err6(400, "no authorization code was provided");
|
|
5750
6276
|
if (pastedState && pastedState !== session.state) {
|
|
5751
|
-
return
|
|
6277
|
+
return err6(400, "oauth state did not match (possible CSRF) \u2014 aborting");
|
|
5752
6278
|
}
|
|
5753
6279
|
code = splitCode;
|
|
5754
6280
|
}
|
|
@@ -5758,7 +6284,7 @@ async function handleOAuthComplete(providerId, body, deps) {
|
|
|
5758
6284
|
block = providerId === "claude" ? await exchangeClaude(code, session.codeVerifier, session.state, exchangeFetch) : await exchangeGemini(code, session.codeVerifier, exchangeFetch);
|
|
5759
6285
|
} catch (exchangeError) {
|
|
5760
6286
|
const reason = exchangeError instanceof Error ? exchangeError.message : "token exchange failed";
|
|
5761
|
-
return
|
|
6287
|
+
return err6(502, `oauth token exchange failed for '${providerId}': ${reason}`);
|
|
5762
6288
|
}
|
|
5763
6289
|
deps.oauthSessions.consume(sessionId);
|
|
5764
6290
|
const label = typeof body["label"] === "string" && body["label"].trim() ? body["label"].trim() : void 0;
|
|
@@ -6096,8 +6622,8 @@ function errBody(message) {
|
|
|
6096
6622
|
return { error: { type: "admin_api_error", message } };
|
|
6097
6623
|
}
|
|
6098
6624
|
var defaultCommandRunner = (command) => new Promise((resolve11) => {
|
|
6099
|
-
exec(command, { timeout: 18e4 }, (
|
|
6100
|
-
if (
|
|
6625
|
+
exec(command, { timeout: 18e4 }, (err9, _stdout, stderr) => {
|
|
6626
|
+
if (err9) resolve11({ ok: false, error: stderr.trim() || err9.message });
|
|
6101
6627
|
else resolve11({ ok: true });
|
|
6102
6628
|
});
|
|
6103
6629
|
});
|
|
@@ -6143,8 +6669,8 @@ async function handleCliLaunch(cli, body, ctx) {
|
|
|
6143
6669
|
providerId: typeof body["providerId"] === "string" ? body["providerId"] : void 0,
|
|
6144
6670
|
model: typeof body["model"] === "string" ? body["model"] : void 0
|
|
6145
6671
|
});
|
|
6146
|
-
} catch (
|
|
6147
|
-
return { status: 400, body: errBody(
|
|
6672
|
+
} catch (err9) {
|
|
6673
|
+
return { status: 400, body: errBody(err9 instanceof Error ? err9.message : "no launch target") };
|
|
6148
6674
|
}
|
|
6149
6675
|
const id = randomUUID2();
|
|
6150
6676
|
let leaseId2;
|
|
@@ -6172,9 +6698,9 @@ async function handleCliLaunch(cli, body, ctx) {
|
|
|
6172
6698
|
} else {
|
|
6173
6699
|
launch = await buildLaunchEnv(cli, ctx.llmConfig, target);
|
|
6174
6700
|
}
|
|
6175
|
-
} catch (
|
|
6176
|
-
const status =
|
|
6177
|
-
return { status, body: errBody(
|
|
6701
|
+
} catch (err9) {
|
|
6702
|
+
const status = err9 instanceof RouteLeaseError2 ? err9.status : 400;
|
|
6703
|
+
return { status, body: errBody(err9 instanceof Error ? err9.message : "failed to build launch env") };
|
|
6178
6704
|
}
|
|
6179
6705
|
const cwd = typeof body["cwd"] === "string" && body["cwd"].trim() ? body["cwd"].trim() : void 0;
|
|
6180
6706
|
const opener = ctx.opener ?? defaultTerminalOpener;
|
|
@@ -6202,9 +6728,9 @@ async function handleCliLaunch(cli, body, ctx) {
|
|
|
6202
6728
|
onFailure: onSessionEnd
|
|
6203
6729
|
});
|
|
6204
6730
|
if (cleanup) openerCleanup = cleanup;
|
|
6205
|
-
} catch (
|
|
6731
|
+
} catch (err9) {
|
|
6206
6732
|
onSessionEnd();
|
|
6207
|
-
return { status: 500, body: errBody(
|
|
6733
|
+
return { status: 500, body: errBody(err9 instanceof Error ? err9.message : "failed to open terminal") };
|
|
6208
6734
|
}
|
|
6209
6735
|
if (ended) {
|
|
6210
6736
|
openerCleanup?.();
|
|
@@ -6767,7 +7293,7 @@ async function handleSearchQuery(req, res, deps) {
|
|
|
6767
7293
|
// src/admin/searchAdminView.ts
|
|
6768
7294
|
var API_KEY_PROVIDERS = /* @__PURE__ */ new Set(["tavily", "jina", "zhipu", "z.ai"]);
|
|
6769
7295
|
var BASIC_AUTH_PROVIDERS = /* @__PURE__ */ new Set(["searxng"]);
|
|
6770
|
-
function
|
|
7296
|
+
function isRecord7(value) {
|
|
6771
7297
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
6772
7298
|
}
|
|
6773
7299
|
function redactSearchServerConfig(search) {
|
|
@@ -6817,13 +7343,13 @@ function resolveSecretField(entry, field, stored) {
|
|
|
6817
7343
|
else delete entry[field];
|
|
6818
7344
|
}
|
|
6819
7345
|
function preserveSearchSecrets(incoming, current) {
|
|
6820
|
-
if (!
|
|
7346
|
+
if (!isRecord7(incoming)) return incoming;
|
|
6821
7347
|
const section = { ...incoming };
|
|
6822
7348
|
const providersValue = section["providers"];
|
|
6823
|
-
if (!
|
|
7349
|
+
if (!isRecord7(providersValue)) return section;
|
|
6824
7350
|
const providers = {};
|
|
6825
7351
|
for (const [id, entryValue] of Object.entries(providersValue)) {
|
|
6826
|
-
if (!
|
|
7352
|
+
if (!isRecord7(entryValue)) {
|
|
6827
7353
|
providers[id] = entryValue;
|
|
6828
7354
|
continue;
|
|
6829
7355
|
}
|
|
@@ -6901,7 +7427,7 @@ function parseKeyPolicyBody(body) {
|
|
|
6901
7427
|
var ENDPOINTS = /* @__PURE__ */ new Set(["chat", "responses", "messages", "gemini"]);
|
|
6902
7428
|
var TARGET_KINDS = /* @__PURE__ */ new Set(["account", "account-group", "account-pool", "provider"]);
|
|
6903
7429
|
var FALLBACKS = /* @__PURE__ */ new Set(["next", "fail", "global"]);
|
|
6904
|
-
function
|
|
7430
|
+
function isRecord8(value) {
|
|
6905
7431
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
6906
7432
|
}
|
|
6907
7433
|
function nonBlank(value) {
|
|
@@ -6921,7 +7447,7 @@ function validateGatewayBindingsSegment(patch) {
|
|
|
6921
7447
|
const ids = /* @__PURE__ */ new Set();
|
|
6922
7448
|
raw.forEach((entry, index) => {
|
|
6923
7449
|
const path2 = `bindings[${index}]`;
|
|
6924
|
-
if (!
|
|
7450
|
+
if (!isRecord8(entry)) {
|
|
6925
7451
|
errors.push(`${path2} must be an object`);
|
|
6926
7452
|
return;
|
|
6927
7453
|
}
|
|
@@ -6950,12 +7476,12 @@ function validateGatewayBindingsSegment(patch) {
|
|
|
6950
7476
|
} else if (entry.modelMappings.length > 100) {
|
|
6951
7477
|
errors.push(`${path2}.modelMappings cannot contain more than 100 entries`);
|
|
6952
7478
|
} else if (entry.modelMappings.some(
|
|
6953
|
-
(mapping) => !
|
|
7479
|
+
(mapping) => !isRecord8(mapping) || !nonBlank(mapping.source) || !nonBlank(mapping.target)
|
|
6954
7480
|
)) {
|
|
6955
7481
|
errors.push(`${path2}.modelMappings must contain non-empty source and target strings`);
|
|
6956
7482
|
}
|
|
6957
7483
|
}
|
|
6958
|
-
if (!
|
|
7484
|
+
if (!isRecord8(entry.target) || !TARGET_KINDS.has(String(entry.target.kind))) {
|
|
6959
7485
|
errors.push(`${path2}.target is invalid`);
|
|
6960
7486
|
} else {
|
|
6961
7487
|
if (!nonBlank(entry.target.providerId)) errors.push(`${path2}.target.providerId is required`);
|
|
@@ -6970,7 +7496,7 @@ function validateGatewayBindingsSegment(patch) {
|
|
|
6970
7496
|
}
|
|
6971
7497
|
}
|
|
6972
7498
|
if (entry.modelMap !== void 0) {
|
|
6973
|
-
if (!
|
|
7499
|
+
if (!isRecord8(entry.modelMap) || Object.values(entry.modelMap).some((value) => typeof value !== "string")) {
|
|
6974
7500
|
errors.push(`${path2}.modelMap must contain string values`);
|
|
6975
7501
|
}
|
|
6976
7502
|
}
|
|
@@ -7267,7 +7793,12 @@ var PROVIDER_KEYS = {
|
|
|
7267
7793
|
},
|
|
7268
7794
|
kimi: { block: "kimi", accounts: "kimiAccounts", active: "activeKimiAccountId" },
|
|
7269
7795
|
grok: { block: "grok", accounts: "grokAccounts", active: "activeGrokAccountId" },
|
|
7270
|
-
copilot: { block: "copilot", accounts: "copilotAccounts", active: "activeCopilotAccountId" }
|
|
7796
|
+
copilot: { block: "copilot", accounts: "copilotAccounts", active: "activeCopilotAccountId" },
|
|
7797
|
+
antigravity: {
|
|
7798
|
+
block: "antigravity",
|
|
7799
|
+
accounts: "antigravityAccounts",
|
|
7800
|
+
active: "activeAntigravityAccountId"
|
|
7801
|
+
}
|
|
7271
7802
|
};
|
|
7272
7803
|
function clone(value) {
|
|
7273
7804
|
return JSON.parse(JSON.stringify(value));
|
|
@@ -7789,7 +8320,7 @@ async function applyImport(packString, passphrase, mode, deps, parseProviderInpu
|
|
|
7789
8320
|
}
|
|
7790
8321
|
|
|
7791
8322
|
// src/admin/adminMigration.ts
|
|
7792
|
-
function
|
|
8323
|
+
function err7(status, message) {
|
|
7793
8324
|
return { status, body: { error: { type: "admin_api_error", message } } };
|
|
7794
8325
|
}
|
|
7795
8326
|
async function handleExport(body, deps) {
|
|
@@ -7799,30 +8330,30 @@ async function handleExport(body, deps) {
|
|
|
7799
8330
|
return { status: 200, body: { pack, version: BUNDLE_VERSION } };
|
|
7800
8331
|
} catch (error) {
|
|
7801
8332
|
if (error instanceof WeakPassphraseError) {
|
|
7802
|
-
return
|
|
8333
|
+
return err7(400, error.message);
|
|
7803
8334
|
}
|
|
7804
|
-
return
|
|
8335
|
+
return err7(500, "failed to build the migration pack");
|
|
7805
8336
|
}
|
|
7806
8337
|
}
|
|
7807
8338
|
async function handleImport(body, deps) {
|
|
7808
8339
|
const blob = typeof body["blob"] === "string" ? body["blob"] : "";
|
|
7809
8340
|
const passphrase = typeof body["passphrase"] === "string" ? body["passphrase"] : "";
|
|
7810
8341
|
const mode = body["mode"] === "overwrite" ? "overwrite" : "merge";
|
|
7811
|
-
if (!blob) return
|
|
8342
|
+
if (!blob) return err7(400, "import requires { blob }");
|
|
7812
8343
|
try {
|
|
7813
8344
|
const counts = await applyImport(blob, passphrase, mode, deps, deps.parseProviderInput);
|
|
7814
8345
|
return { status: 200, body: counts };
|
|
7815
8346
|
} catch (error) {
|
|
7816
8347
|
if (error instanceof WeakPassphraseError) {
|
|
7817
|
-
return
|
|
8348
|
+
return err7(400, error.message);
|
|
7818
8349
|
}
|
|
7819
|
-
return
|
|
8350
|
+
return err7(400, error instanceof Error ? error.message : "import failed");
|
|
7820
8351
|
}
|
|
7821
8352
|
}
|
|
7822
8353
|
|
|
7823
8354
|
// src/admin/usagePricing.ts
|
|
7824
8355
|
import { getSharedUsageThroughputTracker } from "@omnicross/core/usage";
|
|
7825
|
-
var
|
|
8356
|
+
var err8 = (status, message) => ({
|
|
7826
8357
|
status,
|
|
7827
8358
|
body: { error: { type: "admin_api_error", message } }
|
|
7828
8359
|
});
|
|
@@ -7835,7 +8366,7 @@ function parseRange(query2) {
|
|
|
7835
8366
|
const startTs = parseFiniteInt(query2.get("startTs"));
|
|
7836
8367
|
const endTs = parseFiniteInt(query2.get("endTs"));
|
|
7837
8368
|
if (startTs === null || endTs === null) {
|
|
7838
|
-
return
|
|
8369
|
+
return err8(400, "startTs and endTs are required finite-integer unix-millis query params");
|
|
7839
8370
|
}
|
|
7840
8371
|
return { startTs, endTs };
|
|
7841
8372
|
}
|
|
@@ -7860,14 +8391,14 @@ async function handleUsageGet(view, query2, deps) {
|
|
|
7860
8391
|
case "timeseries": {
|
|
7861
8392
|
const bucket = query2.get("bucket");
|
|
7862
8393
|
if (bucket !== "hour" && bucket !== "day" && bucket !== "month") {
|
|
7863
|
-
return
|
|
8394
|
+
return err8(400, "bucket must be one of 'hour', 'day', 'month'");
|
|
7864
8395
|
}
|
|
7865
8396
|
const now = Date.now();
|
|
7866
8397
|
const clamped = { startTs: range.startTs, endTs: Math.min(range.endTs, now) };
|
|
7867
8398
|
if (clamped.startTs < clamped.endTs) {
|
|
7868
8399
|
const projected = Math.ceil((clamped.endTs - clamped.startTs) / BUCKET_SPAN_MS[bucket]) + 1;
|
|
7869
8400
|
if (projected > MAX_TIMESERIES_BUCKETS) {
|
|
7870
|
-
return
|
|
8401
|
+
return err8(
|
|
7871
8402
|
400,
|
|
7872
8403
|
`requested range projects ~${projected} '${bucket}' buckets (max ${MAX_TIMESERIES_BUCKETS}); narrow the range or use a coarser bucket`
|
|
7873
8404
|
);
|
|
@@ -7890,7 +8421,7 @@ async function handleUsageGet(view, query2, deps) {
|
|
|
7890
8421
|
};
|
|
7891
8422
|
}
|
|
7892
8423
|
default:
|
|
7893
|
-
return
|
|
8424
|
+
return err8(404, `unknown usage view '${view ?? ""}'`);
|
|
7894
8425
|
}
|
|
7895
8426
|
}
|
|
7896
8427
|
function poolKeyLabels(cfg) {
|
|
@@ -7939,7 +8470,7 @@ async function handlePricingList(deps) {
|
|
|
7939
8470
|
async function handlePricingUpsert(body, deps) {
|
|
7940
8471
|
const input = parsePricingEntryInput(body);
|
|
7941
8472
|
if (!input) {
|
|
7942
|
-
return
|
|
8473
|
+
return err8(400, "invalid pricing entry (providerId, modelId, finite numeric inputPricePer1m/outputPricePer1m required)");
|
|
7943
8474
|
}
|
|
7944
8475
|
const entry = await deps.pricingEngine.upsertManual(input);
|
|
7945
8476
|
return { status: 200, body: { entry } };
|
|
@@ -7948,7 +8479,7 @@ async function handlePricingDelete(query2, deps) {
|
|
|
7948
8479
|
const providerId = query2.get("providerId")?.trim() ?? "";
|
|
7949
8480
|
const modelId = query2.get("modelId")?.trim() ?? "";
|
|
7950
8481
|
if (!providerId || !modelId) {
|
|
7951
|
-
return
|
|
8482
|
+
return err8(400, "delete requires providerId and modelId query params");
|
|
7952
8483
|
}
|
|
7953
8484
|
const deleted = await deps.pricingStore.delete(providerId, modelId);
|
|
7954
8485
|
if (deleted) await deps.pricingEngine.invalidateCache();
|
|
@@ -7968,13 +8499,13 @@ async function handlePricingFetchLatest(deps) {
|
|
|
7968
8499
|
}
|
|
7969
8500
|
};
|
|
7970
8501
|
} catch (e) {
|
|
7971
|
-
return
|
|
8502
|
+
return err8(502, `pricing-source fetch failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
7972
8503
|
}
|
|
7973
8504
|
}
|
|
7974
8505
|
async function handlePricingResolveConflicts(body, deps) {
|
|
7975
8506
|
const raw = body["resolutions"];
|
|
7976
8507
|
if (!Array.isArray(raw)) {
|
|
7977
|
-
return
|
|
8508
|
+
return err8(400, "resolve-conflicts requires { resolutions: [...] }");
|
|
7978
8509
|
}
|
|
7979
8510
|
const currentRows = await deps.pricingStore.getAll();
|
|
7980
8511
|
const userEditedKeys = new Set(
|
|
@@ -7984,21 +8515,21 @@ async function handlePricingResolveConflicts(body, deps) {
|
|
|
7984
8515
|
const pendingIncoming = /* @__PURE__ */ new Map();
|
|
7985
8516
|
let staleCount = 0;
|
|
7986
8517
|
for (const item of raw) {
|
|
7987
|
-
if (!item || typeof item !== "object") return
|
|
8518
|
+
if (!item || typeof item !== "object") return err8(400, "invalid resolution entry");
|
|
7988
8519
|
const r = item;
|
|
7989
8520
|
const action = r["action"];
|
|
7990
8521
|
if (action !== "overwrite" && action !== "skip") {
|
|
7991
|
-
return
|
|
8522
|
+
return err8(400, "resolution action must be 'overwrite' or 'skip'");
|
|
7992
8523
|
}
|
|
7993
8524
|
const providerId = typeof r["providerId"] === "string" && r["providerId"].trim() ? r["providerId"].trim() : "";
|
|
7994
8525
|
const modelId = typeof r["modelId"] === "string" && r["modelId"].trim() ? r["modelId"].trim() : "";
|
|
7995
8526
|
if (!providerId || !modelId) {
|
|
7996
|
-
return
|
|
8527
|
+
return err8(400, "each resolution requires top-level providerId and modelId");
|
|
7997
8528
|
}
|
|
7998
8529
|
const incoming = parsePricingEntryInput(r["incoming"]);
|
|
7999
|
-
if (!incoming) return
|
|
8530
|
+
if (!incoming) return err8(400, "each resolution must echo a valid incoming pricing entry");
|
|
8000
8531
|
if (incoming.providerId !== providerId || incoming.modelId !== modelId) {
|
|
8001
|
-
return
|
|
8532
|
+
return err8(400, "resolution providerId/modelId must match the echoed incoming entry");
|
|
8002
8533
|
}
|
|
8003
8534
|
const key = `${providerId}::${modelId}`;
|
|
8004
8535
|
if (action === "overwrite" && !userEditedKeys.has(key)) {
|
|
@@ -8043,7 +8574,7 @@ function query(req) {
|
|
|
8043
8574
|
}
|
|
8044
8575
|
function allowanceProvider(value) {
|
|
8045
8576
|
if (!value) return void 0;
|
|
8046
|
-
return value === "claude" || value === "codex" || value === "kimi" || value === "opencodego" || value === "grok" || value === "copilot" || value === "gemini" ? value : null;
|
|
8577
|
+
return value === "claude" || value === "codex" || value === "kimi" || value === "opencodego" || value === "grok" || value === "copilot" || value === "gemini" || value === "antigravity" ? value : null;
|
|
8047
8578
|
}
|
|
8048
8579
|
async function handleAccountAllowanceApi(req, res, method, rest, service) {
|
|
8049
8580
|
if (!service) return writeError2(res, 501, "account allowance service is not available");
|
|
@@ -8120,6 +8651,16 @@ async function handleAccountAllowanceApi(req, res, method, rest, service) {
|
|
|
8120
8651
|
}
|
|
8121
8652
|
return writeJson3(res, 200, { allowances: allowances2 });
|
|
8122
8653
|
}
|
|
8654
|
+
if (requestedProvider === "antigravity") {
|
|
8655
|
+
if (!service.refreshAntigravity) {
|
|
8656
|
+
return writeError2(res, 501, "antigravity allowance refresh is not available");
|
|
8657
|
+
}
|
|
8658
|
+
const allowances2 = await service.refreshAntigravity(accountId);
|
|
8659
|
+
if (accountId && allowances2.length === 0) {
|
|
8660
|
+
return writeError2(res, 404, `Antigravity account '${accountId}' not found`);
|
|
8661
|
+
}
|
|
8662
|
+
return writeJson3(res, 200, { allowances: allowances2 });
|
|
8663
|
+
}
|
|
8123
8664
|
if (requestedProvider === "gemini") {
|
|
8124
8665
|
if (!service.refreshGemini) {
|
|
8125
8666
|
return writeError2(res, 501, "gemini allowance refresh is not available");
|
|
@@ -8277,7 +8818,7 @@ async function handleAdminApi(req, res, path2, deps) {
|
|
|
8277
8818
|
case "server":
|
|
8278
8819
|
return await handleServer(req, res, method, deps);
|
|
8279
8820
|
case "images":
|
|
8280
|
-
return await handleImages(res, method, rest, deps);
|
|
8821
|
+
return await handleImages(req, res, method, rest, deps);
|
|
8281
8822
|
case "search":
|
|
8282
8823
|
return await handleSearchAdmin(req, res, method, rest, deps);
|
|
8283
8824
|
case "accounts":
|
|
@@ -8303,8 +8844,8 @@ async function handleAdminApi(req, res, path2, deps) {
|
|
|
8303
8844
|
default:
|
|
8304
8845
|
return writeJsonError(res, 404, `unknown admin resource '${resource}'`);
|
|
8305
8846
|
}
|
|
8306
|
-
} catch (
|
|
8307
|
-
writeJsonError(res, 500,
|
|
8847
|
+
} catch (err9) {
|
|
8848
|
+
writeJsonError(res, 500, err9 instanceof Error ? err9.message : String(err9));
|
|
8308
8849
|
}
|
|
8309
8850
|
}
|
|
8310
8851
|
function requestQuery(req) {
|
|
@@ -8479,7 +9020,7 @@ async function handleDiscoverModels(res, id, cfg) {
|
|
|
8479
9020
|
const headers = { Accept: "application/json" };
|
|
8480
9021
|
if (resolvedKey) headers["Authorization"] = `Bearer ${resolvedKey}`;
|
|
8481
9022
|
Object.assign(headers, expandRowExtraHeaders(row));
|
|
8482
|
-
const response = await
|
|
9023
|
+
const response = await fetchUpstream10(url, { method: "GET", headers }, { providerId: "byo" });
|
|
8483
9024
|
if (!response.ok) {
|
|
8484
9025
|
const text = await response.text().catch(() => "");
|
|
8485
9026
|
let message = text.slice(0, 300);
|
|
@@ -8496,8 +9037,8 @@ async function handleDiscoverModels(res, id, cfg) {
|
|
|
8496
9037
|
const data = await response.json();
|
|
8497
9038
|
const models = Array.isArray(data?.data) ? data.data.map((m) => typeof m?.id === "string" ? m.id : "").filter((m) => m.length > 0) : [];
|
|
8498
9039
|
return writeJson4(res, 200, { models });
|
|
8499
|
-
} catch (
|
|
8500
|
-
const message =
|
|
9040
|
+
} catch (err9) {
|
|
9041
|
+
const message = err9 instanceof Error ? err9.message : String(err9);
|
|
8501
9042
|
return writeJson4(res, 200, { models: [], error: `discovery failed: ${message}` });
|
|
8502
9043
|
}
|
|
8503
9044
|
}
|
|
@@ -8539,7 +9080,7 @@ async function handleTestModel(req, res, id, cfg) {
|
|
|
8539
9080
|
Object.assign(headers, expandRowExtraHeaders(row));
|
|
8540
9081
|
const startedAt = Date.now();
|
|
8541
9082
|
try {
|
|
8542
|
-
const response = await
|
|
9083
|
+
const response = await fetchUpstream10(
|
|
8543
9084
|
url,
|
|
8544
9085
|
{ method: "POST", headers, body: JSON.stringify(payload) },
|
|
8545
9086
|
{ providerId: "byo" }
|
|
@@ -8561,8 +9102,8 @@ async function handleTestModel(req, res, id, cfg) {
|
|
|
8561
9102
|
latencyMs,
|
|
8562
9103
|
sample: extractSampleText(text, row.apiFormat)
|
|
8563
9104
|
});
|
|
8564
|
-
} catch (
|
|
8565
|
-
const message =
|
|
9105
|
+
} catch (err9) {
|
|
9106
|
+
const message = err9 instanceof Error ? err9.message : String(err9);
|
|
8566
9107
|
return writeJson4(res, 200, { ok: false, latencyMs: Date.now() - startedAt, message });
|
|
8567
9108
|
}
|
|
8568
9109
|
}
|
|
@@ -9147,8 +9688,8 @@ function imageConfigurationAuditFields(previous, next) {
|
|
|
9147
9688
|
const after = next ?? DEFAULT_IMAGES_SERVER_CONFIG;
|
|
9148
9689
|
const fields = [];
|
|
9149
9690
|
if (before.enabled !== after.enabled) fields.push("enablement");
|
|
9150
|
-
if (before.
|
|
9151
|
-
if (before.defaultModel !== after.defaultModel || !sameConfigValue(before.
|
|
9691
|
+
if (!sameConfigValue(before.models, after.models)) fields.push("provider");
|
|
9692
|
+
if (before.defaultModel !== after.defaultModel || !sameConfigValue(before.aliases, after.aliases) || !sameConfigValue(before.codex, after.codex)) fields.push("model");
|
|
9152
9693
|
if (!sameConfigValue(before.account, after.account)) fields.push("account");
|
|
9153
9694
|
if (!sameConfigValue(before.queue, after.queue)) fields.push("queue");
|
|
9154
9695
|
if (!sameConfigValue(before.temporary, after.temporary)) fields.push("temporary");
|
|
@@ -9352,6 +9893,12 @@ async function handleAccounts(req, res, method, rest, deps) {
|
|
|
9352
9893
|
deps.accountAllowanceService
|
|
9353
9894
|
);
|
|
9354
9895
|
}
|
|
9896
|
+
if (method === "GET" && rest[0] === "antigravity" && rest[1] === "models") {
|
|
9897
|
+
const result = await handleAntigravityModelsRoute({
|
|
9898
|
+
resolveAntigravityAccessToken: deps.resolveAntigravityAccessToken ?? (async () => null)
|
|
9899
|
+
});
|
|
9900
|
+
return writeJson4(res, result.status, result.body);
|
|
9901
|
+
}
|
|
9355
9902
|
if (method === "GET" && rest.length === 0) {
|
|
9356
9903
|
const accounts = await deps.subscriptionAccounts.listAll();
|
|
9357
9904
|
const providerAccounts = await deps.subscriptionTokenWriter.listSanitizedAccounts();
|
|
@@ -9377,12 +9924,12 @@ async function handleAccounts(req, res, method, rest, deps) {
|
|
|
9377
9924
|
}
|
|
9378
9925
|
return writeJson4(res, 200, { ok: true, affected: result.affected });
|
|
9379
9926
|
}
|
|
9380
|
-
if (method === "GET" && (rest[0] === "codex" || rest[0] === "kimi" || rest[0] === "grok" || rest[0] === "copilot") && rest[1] === "oauth" && rest[3] === "status") {
|
|
9381
|
-
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);
|
|
9927
|
+
if (method === "GET" && (rest[0] === "codex" || rest[0] === "kimi" || rest[0] === "grok" || rest[0] === "copilot" || rest[0] === "antigravity") && rest[1] === "oauth" && rest[3] === "status") {
|
|
9928
|
+
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);
|
|
9382
9929
|
return writeJson4(res, result.status, result.body);
|
|
9383
9930
|
}
|
|
9384
|
-
if (method === "DELETE" && (rest[0] === "codex" || rest[0] === "kimi" || rest[0] === "grok" || rest[0] === "copilot") && rest[1] === "oauth" && rest[2]) {
|
|
9385
|
-
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);
|
|
9931
|
+
if (method === "DELETE" && (rest[0] === "codex" || rest[0] === "kimi" || rest[0] === "grok" || rest[0] === "copilot" || rest[0] === "antigravity") && rest[1] === "oauth" && rest[2]) {
|
|
9932
|
+
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);
|
|
9386
9933
|
return writeJson4(res, result.status, result.body);
|
|
9387
9934
|
}
|
|
9388
9935
|
if (method === "GET" && rest.length === 3 && rest[2] === "diagnostics") {
|
|
@@ -9452,6 +9999,10 @@ async function handleAccounts(req, res, method, rest, deps) {
|
|
|
9452
9999
|
const result2 = await handleCopilotOAuthStart(deps, body2["enterpriseUrl"]);
|
|
9453
10000
|
return writeJson4(res, result2.status, result2.body);
|
|
9454
10001
|
}
|
|
10002
|
+
if (providerId === "antigravity") {
|
|
10003
|
+
const result2 = handleAntigravityOAuthStart(deps);
|
|
10004
|
+
return writeJson4(res, result2.status, result2.body);
|
|
10005
|
+
}
|
|
9455
10006
|
const result = handleOAuthStart(providerId, deps);
|
|
9456
10007
|
return writeJson4(res, result.status, result.body);
|
|
9457
10008
|
}
|
|
@@ -9814,7 +10365,41 @@ function imageEndpointUrls(base) {
|
|
|
9814
10365
|
edits: `${base}/v1/images/edits`
|
|
9815
10366
|
}) : null;
|
|
9816
10367
|
}
|
|
9817
|
-
|
|
10368
|
+
function imageProviderEvidence(images, capabilities) {
|
|
10369
|
+
const evidenceAt = safeStatusTimestamp(capabilities?.oldestEvidenceAt);
|
|
10370
|
+
const resolvedAt = safeStatusTimestamp(capabilities?.resolvedAt);
|
|
10371
|
+
if (evidenceAt === void 0 || resolvedAt === void 0) return null;
|
|
10372
|
+
const expiresAt = evidenceAt <= Number.MAX_SAFE_INTEGER - images.evidenceTtlMs ? evidenceAt + images.evidenceTtlMs : void 0;
|
|
10373
|
+
return Object.freeze({
|
|
10374
|
+
verifiedAt: evidenceAt,
|
|
10375
|
+
ageMs: Math.max(0, resolvedAt - evidenceAt),
|
|
10376
|
+
...expiresAt !== void 0 ? { expiresAt } : {}
|
|
10377
|
+
});
|
|
10378
|
+
}
|
|
10379
|
+
async function handleImagesVerifyLive(req, res, deps) {
|
|
10380
|
+
const verifier = deps.imageLiveVerifier;
|
|
10381
|
+
if (!verifier) {
|
|
10382
|
+
return writeJsonError(res, 501, "Images live verification is not available");
|
|
10383
|
+
}
|
|
10384
|
+
const serverConfig = await loadServerConfig3(deps.settingsStore);
|
|
10385
|
+
const images = serverConfig.images ?? DEFAULT_IMAGES_SERVER_CONFIG;
|
|
10386
|
+
req.resume();
|
|
10387
|
+
const controller = new AbortController();
|
|
10388
|
+
req.on("close", () => controller.abort());
|
|
10389
|
+
const result = await verifier.verifyLive(images, controller.signal);
|
|
10390
|
+
const antigravityRouted = Object.values(images.models).includes("antigravity-subscription");
|
|
10391
|
+
return writeJson4(res, 200, {
|
|
10392
|
+
...result,
|
|
10393
|
+
...antigravityRouted ? { antigravityDeferred: true } : {}
|
|
10394
|
+
});
|
|
10395
|
+
}
|
|
10396
|
+
async function handleImages(req, res, method, rest, deps) {
|
|
10397
|
+
if (rest.length === 1 && rest[0] === "verify-live") {
|
|
10398
|
+
if (method !== "POST") {
|
|
10399
|
+
return writeJsonError(res, 405, `method ${method} not allowed on Images verify-live`);
|
|
10400
|
+
}
|
|
10401
|
+
return handleImagesVerifyLive(req, res, deps);
|
|
10402
|
+
}
|
|
9818
10403
|
if (rest.length !== 1 || rest[0] !== "capabilities") {
|
|
9819
10404
|
return writeJsonError(res, 404, "unknown Images admin resource");
|
|
9820
10405
|
}
|
|
@@ -9829,14 +10414,14 @@ async function handleImages(res, method, rest, deps) {
|
|
|
9829
10414
|
const capability = await reader.inspectCapability(IMAGE_ADMIN_STATUS_TENANT);
|
|
9830
10415
|
const resources = safeRuntimeResources(reader.resourceStatus());
|
|
9831
10416
|
const outbound = deps.outboundApiServer.getStatus();
|
|
9832
|
-
const
|
|
9833
|
-
const
|
|
9834
|
-
|
|
9835
|
-
|
|
9836
|
-
|
|
9837
|
-
|
|
9838
|
-
|
|
9839
|
-
})
|
|
10417
|
+
const evidence = imageProviderEvidence(images, capability.capabilities);
|
|
10418
|
+
const providers = (capability.providers ?? []).map((provider) => Object.freeze({
|
|
10419
|
+
providerId: provider.providerId,
|
|
10420
|
+
available: provider.available === true,
|
|
10421
|
+
reason: provider.available ? null : safeImageCapabilityReason(provider.reason),
|
|
10422
|
+
models: Object.freeze([...provider.models]),
|
|
10423
|
+
evidence: imageProviderEvidence(images, provider.capabilities)
|
|
10424
|
+
}));
|
|
9840
10425
|
const draining = lifecycle.draining.map((generation) => Object.freeze({
|
|
9841
10426
|
generationId: safeImageGenerationId(generation.generationId),
|
|
9842
10427
|
enabled: generation.enabled,
|
|
@@ -9846,7 +10431,7 @@ async function handleImages(res, method, rest, deps) {
|
|
|
9846
10431
|
return writeJson4(res, 200, {
|
|
9847
10432
|
configured: {
|
|
9848
10433
|
enabled: images.enabled,
|
|
9849
|
-
provider: images.
|
|
10434
|
+
provider: images.models[images.defaultModel] ?? "codex-subscription",
|
|
9850
10435
|
model: images.defaultModel,
|
|
9851
10436
|
remoteUrlsEnabled: images.remote.enabled,
|
|
9852
10437
|
referenceTtlMs: images.references.ttlMs
|
|
@@ -9857,6 +10442,7 @@ async function handleImages(res, method, rest, deps) {
|
|
|
9857
10442
|
evidence,
|
|
9858
10443
|
features: safeCapabilityValues(capability.capabilities, images.defaultModel)
|
|
9859
10444
|
},
|
|
10445
|
+
providers,
|
|
9860
10446
|
runtime: {
|
|
9861
10447
|
disposed: lifecycle.disposed,
|
|
9862
10448
|
generationId: safeImageGenerationId(lifecycle.current.generationId),
|
|
@@ -9946,12 +10532,12 @@ async function handlePlayground(req, res, method, deps) {
|
|
|
9946
10532
|
const payload = body["body"];
|
|
9947
10533
|
const status = deps.outboundApiServer.getStatus();
|
|
9948
10534
|
if (!status.running || !status.port) return writeJsonError(res, 503, "outbound server not running");
|
|
9949
|
-
const path2 = resolvePlaygroundPath(endpoint,
|
|
10535
|
+
const path2 = resolvePlaygroundPath(endpoint, isRecord9(payload) ? payload : {});
|
|
9950
10536
|
if (!path2) return writeJsonError(res, 400, `unknown endpoint '${endpoint}'`);
|
|
9951
10537
|
const upstreamBody = typeof payload === "string" ? payload : JSON.stringify(payload ?? {});
|
|
9952
10538
|
await proxyToOutbound(res, status.port, path2, key, upstreamBody);
|
|
9953
10539
|
}
|
|
9954
|
-
function
|
|
10540
|
+
function isRecord9(v) {
|
|
9955
10541
|
return !!v && typeof v === "object" && !Array.isArray(v);
|
|
9956
10542
|
}
|
|
9957
10543
|
function proxyToOutbound(res, outboundPort, path2, key, body) {
|
|
@@ -9980,8 +10566,8 @@ function proxyToOutbound(res, outboundPort, path2, key, body) {
|
|
|
9980
10566
|
});
|
|
9981
10567
|
}
|
|
9982
10568
|
);
|
|
9983
|
-
upstream.on("error", (
|
|
9984
|
-
if (!res.headersSent) writeJsonError(res, 502, `playground proxy failed: ${
|
|
10569
|
+
upstream.on("error", (err9) => {
|
|
10570
|
+
if (!res.headersSent) writeJsonError(res, 502, `playground proxy failed: ${err9.message}`);
|
|
9985
10571
|
else res.end();
|
|
9986
10572
|
resolve11();
|
|
9987
10573
|
});
|
|
@@ -10086,7 +10672,7 @@ async function handleUiStatic(req, res, urlPath, uiDist) {
|
|
|
10086
10672
|
}
|
|
10087
10673
|
|
|
10088
10674
|
// src/admin/version.ts
|
|
10089
|
-
var DAEMON_VERSION = true ? "0.4.
|
|
10675
|
+
var DAEMON_VERSION = true ? "0.4.4" : "0.0.0-dev";
|
|
10090
10676
|
|
|
10091
10677
|
// src/admin/AdminServer.ts
|
|
10092
10678
|
var LOOPBACK_ADDR = "127.0.0.1";
|
|
@@ -10129,13 +10715,13 @@ var AdminServer = class {
|
|
|
10129
10715
|
const server = http2.createServer((req, res) => {
|
|
10130
10716
|
this.onRequest(req, res);
|
|
10131
10717
|
});
|
|
10132
|
-
const onError = (
|
|
10133
|
-
if (
|
|
10718
|
+
const onError = (err9) => {
|
|
10719
|
+
if (err9.code === "EADDRINUSE" && port !== 0) {
|
|
10134
10720
|
server.removeListener("error", onError);
|
|
10135
10721
|
this.listen(bindAddr, 0).then(resolve11, reject);
|
|
10136
10722
|
return;
|
|
10137
10723
|
}
|
|
10138
|
-
reject(
|
|
10724
|
+
reject(err9);
|
|
10139
10725
|
};
|
|
10140
10726
|
server.on("error", onError);
|
|
10141
10727
|
server.listen(port, bindAddr, () => {
|
|
@@ -10153,8 +10739,8 @@ var AdminServer = class {
|
|
|
10153
10739
|
}
|
|
10154
10740
|
/** Per-request handler: auth gate (when a token is set) → routing. */
|
|
10155
10741
|
onRequest(req, res) {
|
|
10156
|
-
void this.dispatch(req, res).catch((
|
|
10157
|
-
const message =
|
|
10742
|
+
void this.dispatch(req, res).catch((err9) => {
|
|
10743
|
+
const message = err9 instanceof Error ? err9.message : String(err9);
|
|
10158
10744
|
this.deps.logger.error("[AdminServer] unhandled error:", message);
|
|
10159
10745
|
if (!res.headersSent) {
|
|
10160
10746
|
res.writeHead(500, { "Content-Type": "application/json" });
|
|
@@ -10377,7 +10963,10 @@ var HTML_HEADERS = {
|
|
|
10377
10963
|
function pageHtml(message) {
|
|
10378
10964
|
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>`;
|
|
10379
10965
|
}
|
|
10380
|
-
function awaitLoopbackCode(expectedState, timeoutMs = DEFAULT_TIMEOUT_MS, signal) {
|
|
10966
|
+
function awaitLoopbackCode(expectedState, timeoutMs = DEFAULT_TIMEOUT_MS, signal, binding = {}) {
|
|
10967
|
+
const port = binding.port ?? LOOPBACK_PORT;
|
|
10968
|
+
const callbackPath = binding.path ?? CALLBACK_PATH;
|
|
10969
|
+
const label = binding.label ?? "codex";
|
|
10381
10970
|
return new Promise((resolve11, reject) => {
|
|
10382
10971
|
let settled = false;
|
|
10383
10972
|
const finish = (server2, fn) => {
|
|
@@ -10388,8 +10977,8 @@ function awaitLoopbackCode(expectedState, timeoutMs = DEFAULT_TIMEOUT_MS, signal
|
|
|
10388
10977
|
server2.close();
|
|
10389
10978
|
};
|
|
10390
10979
|
const server = createServer2((req, res) => {
|
|
10391
|
-
const url = new URL(req.url ?? "", `http://${LOOPBACK_HOST}:${
|
|
10392
|
-
if (url.pathname !==
|
|
10980
|
+
const url = new URL(req.url ?? "", `http://${LOOPBACK_HOST}:${port}`);
|
|
10981
|
+
if (url.pathname !== callbackPath) {
|
|
10393
10982
|
res.writeHead(404, HTML_HEADERS);
|
|
10394
10983
|
res.end(pageHtml("Not found"));
|
|
10395
10984
|
return;
|
|
@@ -10418,25 +11007,25 @@ function awaitLoopbackCode(expectedState, timeoutMs = DEFAULT_TIMEOUT_MS, signal
|
|
|
10418
11007
|
return;
|
|
10419
11008
|
}
|
|
10420
11009
|
signal?.addEventListener("abort", abort, { once: true });
|
|
10421
|
-
server.on("error", (
|
|
11010
|
+
server.on("error", (err9) => {
|
|
10422
11011
|
if (settled) return;
|
|
10423
11012
|
settled = true;
|
|
10424
11013
|
clearTimeout(timer);
|
|
10425
|
-
if (
|
|
11014
|
+
if (err9.code === "EADDRINUSE") {
|
|
10426
11015
|
reject(
|
|
10427
11016
|
new Error(
|
|
10428
|
-
`login: cannot bind ${LOOPBACK_HOST}:${
|
|
11017
|
+
`login: cannot bind ${LOOPBACK_HOST}:${port} (address in use) \u2014 another ${label} login or process is holding the port`
|
|
10429
11018
|
)
|
|
10430
11019
|
);
|
|
10431
11020
|
} else {
|
|
10432
|
-
reject(
|
|
11021
|
+
reject(err9);
|
|
10433
11022
|
}
|
|
10434
11023
|
});
|
|
10435
11024
|
const timer = setTimeout(() => {
|
|
10436
11025
|
finish(server, () => reject(new Error(`login: timed out after ${Math.round(timeoutMs / 1e3)}s waiting for the callback`)));
|
|
10437
11026
|
}, timeoutMs);
|
|
10438
11027
|
if (typeof timer.unref === "function") timer.unref();
|
|
10439
|
-
server.listen(
|
|
11028
|
+
server.listen(port, LOOPBACK_HOST);
|
|
10440
11029
|
});
|
|
10441
11030
|
}
|
|
10442
11031
|
|
|
@@ -10506,7 +11095,7 @@ function createPoolKeysLoader(getProviderRow, autoDisabled) {
|
|
|
10506
11095
|
|
|
10507
11096
|
// src/allowance/ProviderKeyQuotaService.ts
|
|
10508
11097
|
import { mergeExtraHeaders as mergeExtraHeaders2 } from "@omnicross/core";
|
|
10509
|
-
import { fetchUpstream as
|
|
11098
|
+
import { fetchUpstream as fetchUpstream11 } from "@omnicross/core/pipeline/upstreamFetch";
|
|
10510
11099
|
|
|
10511
11100
|
// src/allowance/ProviderKeyQuota.ts
|
|
10512
11101
|
var MINUTE_MS3 = 6e4;
|
|
@@ -10535,11 +11124,11 @@ function isoInstant3(value) {
|
|
|
10535
11124
|
}
|
|
10536
11125
|
return void 0;
|
|
10537
11126
|
}
|
|
10538
|
-
function
|
|
11127
|
+
function secondsUntil9(instant, now) {
|
|
10539
11128
|
if (!instant) return void 0;
|
|
10540
11129
|
return Math.max(0, Math.floor((Date.parse(instant) - now) / 1e3));
|
|
10541
11130
|
}
|
|
10542
|
-
function
|
|
11131
|
+
function isRecord10(value) {
|
|
10543
11132
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
10544
11133
|
}
|
|
10545
11134
|
function detectProviderKeyQuotaAdapter(baseUrl) {
|
|
@@ -10606,17 +11195,17 @@ function zaiWindowIdLabel(durationMs) {
|
|
|
10606
11195
|
return { id: "quota", label: "Quota" };
|
|
10607
11196
|
}
|
|
10608
11197
|
function parseZaiQuotaPayload(payload, now) {
|
|
10609
|
-
if (!
|
|
10610
|
-
const data =
|
|
11198
|
+
if (!isRecord10(payload)) return null;
|
|
11199
|
+
const data = isRecord10(payload["data"]) ? payload["data"] : payload;
|
|
10611
11200
|
if (payload["success"] === false) return null;
|
|
10612
11201
|
const limits = Array.isArray(data["limits"]) ? data["limits"] : [];
|
|
10613
11202
|
const byWindow = /* @__PURE__ */ new Map();
|
|
10614
11203
|
for (const raw of limits) {
|
|
10615
|
-
if (!
|
|
11204
|
+
if (!isRecord10(raw)) continue;
|
|
10616
11205
|
const item = raw;
|
|
10617
11206
|
if (item.type === void 0) continue;
|
|
10618
11207
|
const details = raw["usageDetails"];
|
|
10619
|
-
if (Array.isArray(details) && details.some((d) =>
|
|
11208
|
+
if (Array.isArray(details) && details.some((d) => isRecord10(d) && d["modelCode"] === "zread")) {
|
|
10620
11209
|
continue;
|
|
10621
11210
|
}
|
|
10622
11211
|
const durationMs = zaiWindowDurationMs(item);
|
|
@@ -10635,7 +11224,7 @@ function parseZaiQuotaPayload(payload, now) {
|
|
|
10635
11224
|
usedPercent,
|
|
10636
11225
|
...durationMs !== void 0 ? { windowMinutes: Math.round(durationMs / MINUTE_MS3) } : {},
|
|
10637
11226
|
...resetsAt !== void 0 ? { resetsAt } : {},
|
|
10638
|
-
remainingSeconds:
|
|
11227
|
+
remainingSeconds: secondsUntil9(resetsAt, now),
|
|
10639
11228
|
state: "fresh"
|
|
10640
11229
|
};
|
|
10641
11230
|
const existing = byWindow.get(id);
|
|
@@ -10649,7 +11238,7 @@ function parseZaiQuotaPayload(payload, now) {
|
|
|
10649
11238
|
var MINIMAX_STATUS_EXHAUSTED = 2;
|
|
10650
11239
|
var MINIMAX_SHARED_BUCKET = "general";
|
|
10651
11240
|
function parseMiniMaxBucket(value) {
|
|
10652
|
-
if (!
|
|
11241
|
+
if (!isRecord10(value)) return null;
|
|
10653
11242
|
const modelName = typeof value["model_name"] === "string" ? value["model_name"].trim() : "";
|
|
10654
11243
|
if (!modelName) return null;
|
|
10655
11244
|
const instant = (v) => {
|
|
@@ -10676,14 +11265,14 @@ function minimaxWindow(id, label, windowMinutes, resetsAtMs, remainingPercent, s
|
|
|
10676
11265
|
usedPercent,
|
|
10677
11266
|
...windowMinutes !== void 0 ? { windowMinutes } : {},
|
|
10678
11267
|
...resetsAt !== void 0 ? { resetsAt } : {},
|
|
10679
|
-
remainingSeconds:
|
|
11268
|
+
remainingSeconds: secondsUntil9(resetsAt, now),
|
|
10680
11269
|
state: usedPercent !== null ? "fresh" : "unavailable"
|
|
10681
11270
|
};
|
|
10682
11271
|
}
|
|
10683
11272
|
function parseMiniMaxTokenPlanPayload(payload, now) {
|
|
10684
|
-
if (!
|
|
11273
|
+
if (!isRecord10(payload)) return null;
|
|
10685
11274
|
const baseResp = payload["base_resp"];
|
|
10686
|
-
if (!
|
|
11275
|
+
if (!isRecord10(baseResp) || baseResp["status_code"] !== 0) return null;
|
|
10687
11276
|
const buckets = Array.isArray(payload["model_remains"]) ? payload["model_remains"] : [];
|
|
10688
11277
|
let general = null;
|
|
10689
11278
|
for (const raw of buckets) {
|
|
@@ -10716,11 +11305,11 @@ function parseMiniMaxTokenPlanPayload(payload, now) {
|
|
|
10716
11305
|
];
|
|
10717
11306
|
}
|
|
10718
11307
|
function parseUmansUsagePayload(payload, now) {
|
|
10719
|
-
if (!
|
|
10720
|
-
const limits =
|
|
10721
|
-
const requests = limits &&
|
|
10722
|
-
const usage =
|
|
10723
|
-
const window =
|
|
11308
|
+
if (!isRecord10(payload)) return null;
|
|
11309
|
+
const limits = isRecord10(payload["limits"]) ? payload["limits"] : void 0;
|
|
11310
|
+
const requests = limits && isRecord10(limits["requests"]) ? limits["requests"] : void 0;
|
|
11311
|
+
const usage = isRecord10(payload["usage"]) ? payload["usage"] : void 0;
|
|
11312
|
+
const window = isRecord10(payload["window"]) ? payload["window"] : void 0;
|
|
10724
11313
|
const hardCap = finiteNumber5(requests?.["hard_cap"]);
|
|
10725
11314
|
const softLimit = finiteNumber5(requests?.["limit"]);
|
|
10726
11315
|
const requestsInWindow = finiteNumber5(usage?.["requests_in_window"]);
|
|
@@ -10741,15 +11330,15 @@ function parseUmansUsagePayload(payload, now) {
|
|
|
10741
11330
|
usedPercent,
|
|
10742
11331
|
windowMinutes: 5 * 60,
|
|
10743
11332
|
...resetsAt !== void 0 ? { resetsAt } : {},
|
|
10744
|
-
remainingSeconds:
|
|
11333
|
+
remainingSeconds: secondsUntil9(resetsAt, now),
|
|
10745
11334
|
state: "fresh"
|
|
10746
11335
|
}
|
|
10747
11336
|
];
|
|
10748
11337
|
}
|
|
10749
11338
|
function parseSyntheticQuotasPayload(payload, now) {
|
|
10750
|
-
if (!
|
|
10751
|
-
const fiveHour =
|
|
10752
|
-
const weekly =
|
|
11339
|
+
if (!isRecord10(payload)) return null;
|
|
11340
|
+
const fiveHour = isRecord10(payload["rollingFiveHourLimit"]) ? payload["rollingFiveHourLimit"] : void 0;
|
|
11341
|
+
const weekly = isRecord10(payload["weeklyTokenLimit"]) ? payload["weeklyTokenLimit"] : void 0;
|
|
10753
11342
|
const windows = [];
|
|
10754
11343
|
if (fiveHour) {
|
|
10755
11344
|
const max = finiteNumber5(fiveHour["max"]);
|
|
@@ -10763,7 +11352,7 @@ function parseSyntheticQuotasPayload(payload, now) {
|
|
|
10763
11352
|
usedPercent,
|
|
10764
11353
|
windowMinutes: 5 * 60,
|
|
10765
11354
|
...resetsAt !== void 0 ? { resetsAt } : {},
|
|
10766
|
-
remainingSeconds:
|
|
11355
|
+
remainingSeconds: secondsUntil9(resetsAt, now),
|
|
10767
11356
|
state: usedPercent !== null || resetsAt ? "fresh" : "unavailable"
|
|
10768
11357
|
});
|
|
10769
11358
|
}
|
|
@@ -10778,7 +11367,7 @@ function parseSyntheticQuotasPayload(payload, now) {
|
|
|
10778
11367
|
usedPercent,
|
|
10779
11368
|
windowMinutes: 7 * 24 * 60,
|
|
10780
11369
|
...resetsAt !== void 0 ? { resetsAt } : {},
|
|
10781
|
-
remainingSeconds:
|
|
11370
|
+
remainingSeconds: secondsUntil9(resetsAt, now),
|
|
10782
11371
|
state: usedPercent !== null || resetsAt ? "fresh" : "unavailable"
|
|
10783
11372
|
});
|
|
10784
11373
|
}
|
|
@@ -10790,12 +11379,12 @@ var CLINE_WINDOW_CONFIG = {
|
|
|
10790
11379
|
monthly: { id: "thirty-day", label: "30 days", minutes: 30 * 24 * 60 }
|
|
10791
11380
|
};
|
|
10792
11381
|
function parseClinePassUsageLimitsPayload(payload, now) {
|
|
10793
|
-
if (!
|
|
10794
|
-
const data =
|
|
11382
|
+
if (!isRecord10(payload)) return null;
|
|
11383
|
+
const data = isRecord10(payload["data"]) ? payload["data"] : payload;
|
|
10795
11384
|
const limits = Array.isArray(data["limits"]) ? data["limits"] : [];
|
|
10796
11385
|
const windows = [];
|
|
10797
11386
|
for (const raw of limits) {
|
|
10798
|
-
if (!
|
|
11387
|
+
if (!isRecord10(raw)) continue;
|
|
10799
11388
|
const config = CLINE_WINDOW_CONFIG[typeof raw["type"] === "string" ? raw["type"] : ""];
|
|
10800
11389
|
if (!config) continue;
|
|
10801
11390
|
const usedPercent = finitePercent4(raw["percentUsed"]);
|
|
@@ -10808,7 +11397,7 @@ function parseClinePassUsageLimitsPayload(payload, now) {
|
|
|
10808
11397
|
usedPercent,
|
|
10809
11398
|
windowMinutes: config.minutes,
|
|
10810
11399
|
...resetsAt !== void 0 ? { resetsAt } : {},
|
|
10811
|
-
remainingSeconds:
|
|
11400
|
+
remainingSeconds: secondsUntil9(resetsAt, now),
|
|
10812
11401
|
state: "fresh"
|
|
10813
11402
|
});
|
|
10814
11403
|
}
|
|
@@ -10847,7 +11436,7 @@ function rowKeyEntries(row) {
|
|
|
10847
11436
|
return [];
|
|
10848
11437
|
}
|
|
10849
11438
|
var ProviderKeyQuotaService = class {
|
|
10850
|
-
constructor(box, fetchImpl = (url, init) =>
|
|
11439
|
+
constructor(box, fetchImpl = (url, init) => fetchUpstream11(url, init, { redactBodies: true }), now = Date.now) {
|
|
10851
11440
|
this.box = box;
|
|
10852
11441
|
this.fetchImpl = fetchImpl;
|
|
10853
11442
|
this.now = now;
|
|
@@ -11421,12 +12010,12 @@ function createImageDoctorService(options) {
|
|
|
11421
12010
|
authStrategy: strategy,
|
|
11422
12011
|
generationTimeoutMs: config.queue.generationTimeoutMs
|
|
11423
12012
|
}));
|
|
11424
|
-
const readAccount = async () => {
|
|
11425
|
-
const
|
|
12013
|
+
const readAccount = async (providerId) => {
|
|
12014
|
+
const entry = (await options.subscriptionAccounts.listAll()).find((candidate) => candidate.providerId === providerId);
|
|
11426
12015
|
return Object.freeze({
|
|
11427
|
-
present:
|
|
11428
|
-
usable:
|
|
11429
|
-
reason:
|
|
12016
|
+
present: entry !== void 0,
|
|
12017
|
+
usable: entry?.credentialStatus.ok === true,
|
|
12018
|
+
reason: entry === void 0 ? "missing" : entry.credentialStatus.ok ? "ready" : "unavailable"
|
|
11430
12019
|
});
|
|
11431
12020
|
};
|
|
11432
12021
|
const activePaths = () => options.storageCatalog.active().resolver;
|
|
@@ -11464,6 +12053,7 @@ function createImageDoctorService(options) {
|
|
|
11464
12053
|
} catch {
|
|
11465
12054
|
storesValid = false;
|
|
11466
12055
|
}
|
|
12056
|
+
const antigravityAccount = await readAccount("antigravity");
|
|
11467
12057
|
const rows = await options.keyDb.outboundApiKeysList();
|
|
11468
12058
|
let legacyRows = 0;
|
|
11469
12059
|
let invalidRows = 0;
|
|
@@ -11480,7 +12070,7 @@ function createImageDoctorService(options) {
|
|
|
11480
12070
|
invalidRows += 1;
|
|
11481
12071
|
}
|
|
11482
12072
|
}
|
|
11483
|
-
const account = await readAccount();
|
|
12073
|
+
const account = await readAccount("codex");
|
|
11484
12074
|
let evidence;
|
|
11485
12075
|
let evidenceStore;
|
|
11486
12076
|
try {
|
|
@@ -11494,10 +12084,11 @@ function createImageDoctorService(options) {
|
|
|
11494
12084
|
return Object.freeze({
|
|
11495
12085
|
config: Object.freeze({
|
|
11496
12086
|
enabled: config.enabled,
|
|
11497
|
-
provider: config.
|
|
12087
|
+
provider: config.models[config.defaultModel] ?? "codex-subscription",
|
|
11498
12088
|
model: config.defaultModel,
|
|
11499
12089
|
valid: configErrors.length === 0,
|
|
11500
|
-
errorCount: configErrors.length
|
|
12090
|
+
errorCount: configErrors.length,
|
|
12091
|
+
routedProviders: Object.freeze([...new Set(Object.values(config.models))])
|
|
11501
12092
|
}),
|
|
11502
12093
|
roots: Object.freeze({
|
|
11503
12094
|
valid: verifiedAreas === ROOT_AREAS.length,
|
|
@@ -11522,12 +12113,13 @@ function createImageDoctorService(options) {
|
|
|
11522
12113
|
imagesAuthorizedRows
|
|
11523
12114
|
}),
|
|
11524
12115
|
account,
|
|
12116
|
+
antigravityAccount,
|
|
11525
12117
|
evidence: Object.freeze(evidence)
|
|
11526
12118
|
});
|
|
11527
12119
|
},
|
|
11528
12120
|
verifyLive: async (config, signal) => {
|
|
11529
12121
|
if (!config.enabled) return Object.freeze({ ok: false, code: "images_disabled" });
|
|
11530
|
-
const account = await readAccount();
|
|
12122
|
+
const account = await readAccount("codex");
|
|
11531
12123
|
if (!account.usable) {
|
|
11532
12124
|
return Object.freeze({ ok: false, code: "codex_account_unavailable" });
|
|
11533
12125
|
}
|
|
@@ -11788,6 +12380,7 @@ import {
|
|
|
11788
12380
|
validateImagesServerConfig as validateImagesServerConfig3
|
|
11789
12381
|
} from "@omnicross/core/outbound-api";
|
|
11790
12382
|
import {
|
|
12383
|
+
createAntigravitySubscriptionImageProvider,
|
|
11791
12384
|
createCodexSubscriptionImageProvider
|
|
11792
12385
|
} from "@omnicross/subscriptions";
|
|
11793
12386
|
|
|
@@ -11819,10 +12412,11 @@ function createTrustedImageApiRuntimeResolver(options) {
|
|
|
11819
12412
|
throw new TypeError("enabled image remote loading requires a proven resolver");
|
|
11820
12413
|
}
|
|
11821
12414
|
const hmacKey = Buffer.from(options.hmacKey);
|
|
11822
|
-
const modelAliases = new Map(Object.entries(options.config.
|
|
12415
|
+
const modelAliases = new Map(Object.entries(options.config.aliases));
|
|
12416
|
+
const modelRoutes = new Map(Object.entries(options.config.models));
|
|
11823
12417
|
const limits = Object.freeze({ ...options.config.limits });
|
|
11824
|
-
const providerId = options.config.provider;
|
|
11825
12418
|
const defaultModel = options.config.defaultModel;
|
|
12419
|
+
const providerId = modelRoutes.get(defaultModel) ?? "codex-subscription";
|
|
11826
12420
|
const referenceStore = options.referenceStore;
|
|
11827
12421
|
const retention = Object.freeze({
|
|
11828
12422
|
enabled: true,
|
|
@@ -11843,6 +12437,7 @@ function createTrustedImageApiRuntimeResolver(options) {
|
|
|
11843
12437
|
providerId,
|
|
11844
12438
|
defaultModel,
|
|
11845
12439
|
modelAliases,
|
|
12440
|
+
modelRoutes,
|
|
11846
12441
|
limits,
|
|
11847
12442
|
...preferredAccountId ? { preferredAccountId } : {},
|
|
11848
12443
|
...preferredAccountGroup ? { preferredAccountGroup } : {},
|
|
@@ -12247,7 +12842,9 @@ var GENERATION_ID = /^[A-Za-z0-9][A-Za-z0-9_.:-]{0,127}$/u;
|
|
|
12247
12842
|
function snapshotConfig(config) {
|
|
12248
12843
|
return {
|
|
12249
12844
|
...config,
|
|
12250
|
-
|
|
12845
|
+
models: { ...config.models },
|
|
12846
|
+
aliases: { ...config.aliases },
|
|
12847
|
+
codex: { ...config.codex },
|
|
12251
12848
|
account: { ...config.account },
|
|
12252
12849
|
queue: { ...config.queue },
|
|
12253
12850
|
temporary: { ...config.temporary },
|
|
@@ -12281,10 +12878,15 @@ function createImageRuntimeGeneration(options) {
|
|
|
12281
12878
|
}
|
|
12282
12879
|
});
|
|
12283
12880
|
}
|
|
12284
|
-
const
|
|
12285
|
-
|
|
12881
|
+
const routedProviders = [...new Set(Object.values(config.models))];
|
|
12882
|
+
const codexStrategy = routedProviders.includes("codex-subscription") ? options.subscriptionAccounts.getStrategy("codex") : void 0;
|
|
12883
|
+
if (routedProviders.includes("codex-subscription") && (!codexStrategy || codexStrategy.providerId !== "codex")) {
|
|
12286
12884
|
throw new TypeError("enabled image runtime requires the Codex subscription strategy");
|
|
12287
12885
|
}
|
|
12886
|
+
const antigravityStrategy = routedProviders.includes("antigravity-subscription") ? options.subscriptionAccounts.getStrategy("antigravity") : void 0;
|
|
12887
|
+
if (routedProviders.includes("antigravity-subscription") && (!antigravityStrategy || antigravityStrategy.providerId !== "antigravity")) {
|
|
12888
|
+
throw new TypeError("enabled image runtime requires the Antigravity subscription strategy");
|
|
12889
|
+
}
|
|
12288
12890
|
const privateHmacKey = options.privateHmacKey ? Buffer.from(options.privateHmacKey) : loadOrCreateImageTenantHmacSalt(options.storage.paths, randomBytes6);
|
|
12289
12891
|
if (privateHmacKey.byteLength !== 32) {
|
|
12290
12892
|
privateHmacKey.fill(0);
|
|
@@ -12319,23 +12921,32 @@ function createImageRuntimeGeneration(options) {
|
|
|
12319
12921
|
if (options.testOnlySyntheticVerifiedProvider && options.testOnlySyntheticVerifiedProvider.label !== "synthetic-verified-image-provider-test-only") {
|
|
12320
12922
|
throw new TypeError("synthetic verified image provider test seam label is invalid");
|
|
12321
12923
|
}
|
|
12322
|
-
const
|
|
12924
|
+
const providers = options.testOnlySyntheticVerifiedProvider ? [options.testOnlySyntheticVerifiedProvider.createProvider({
|
|
12323
12925
|
generationId: options.generationId,
|
|
12324
12926
|
scheduler,
|
|
12325
12927
|
now: options.now ?? Date.now,
|
|
12326
12928
|
referenceStore: options.storage.referenceStore,
|
|
12327
12929
|
stateStore: options.storage.stateStore
|
|
12328
|
-
}) : createCodexSubscriptionImageProvider({
|
|
12329
|
-
authStrategy,
|
|
12930
|
+
})] : routedProviders.map((providerId) => providerId === "codex-subscription" ? createCodexSubscriptionImageProvider({
|
|
12931
|
+
authStrategy: codexStrategy,
|
|
12330
12932
|
evidenceSource: generationEvidenceSource,
|
|
12331
12933
|
executionScheduler: scheduler,
|
|
12332
12934
|
generationTimeoutMs: config.queue.generationTimeoutMs,
|
|
12935
|
+
now: options.now,
|
|
12936
|
+
wire: {
|
|
12937
|
+
imageModel: config.codex.imageModel,
|
|
12938
|
+
carrierModel: config.codex.carrierModel
|
|
12939
|
+
}
|
|
12940
|
+
}) : createAntigravitySubscriptionImageProvider({
|
|
12941
|
+
authStrategy: antigravityStrategy,
|
|
12942
|
+
executionScheduler: scheduler,
|
|
12943
|
+
generationTimeoutMs: config.queue.generationTimeoutMs,
|
|
12333
12944
|
now: options.now
|
|
12334
|
-
});
|
|
12335
|
-
if (
|
|
12945
|
+
}));
|
|
12946
|
+
if (providers.length === 1 && providers[0].id !== "codex-subscription") {
|
|
12336
12947
|
throw new TypeError("synthetic verified image provider id must match configured provider");
|
|
12337
12948
|
}
|
|
12338
|
-
const providerRegistry = new ImageProviderRegistry(
|
|
12949
|
+
const providerRegistry = new ImageProviderRegistry(providers);
|
|
12339
12950
|
const orchestrator = new ImageOrchestrator({
|
|
12340
12951
|
registry: providerRegistry,
|
|
12341
12952
|
referenceStore: options.storage.referenceStore,
|
|
@@ -12357,35 +12968,72 @@ function createImageRuntimeGeneration(options) {
|
|
|
12357
12968
|
...options.createCallId ? { createCallId: options.createCallId } : {},
|
|
12358
12969
|
...options.now ? { now: options.now } : {}
|
|
12359
12970
|
});
|
|
12971
|
+
const defaultProviderId = config.models[config.defaultModel] ?? "codex-subscription";
|
|
12972
|
+
const inspectOneProvider = async (providerId, apiKeyId) => {
|
|
12973
|
+
const capabilities = await orchestrator.getCapabilities(providerId, {
|
|
12974
|
+
requestId: `${options.generationId}:capability-inspection`,
|
|
12975
|
+
tenantId: apiKeyId,
|
|
12976
|
+
signal: new AbortController().signal,
|
|
12977
|
+
sessionKey: `outbound:images:${apiKeyId}`,
|
|
12978
|
+
...config.account.id ? { preferredAccountId: config.account.id } : {},
|
|
12979
|
+
...config.account.group ? { preferredAccountGroup: config.account.group } : {},
|
|
12980
|
+
boundAccountFallbackPolicy: config.account.fallback
|
|
12981
|
+
});
|
|
12982
|
+
return capabilities;
|
|
12983
|
+
};
|
|
12360
12984
|
const inspectCapability = async (apiKeyId) => {
|
|
12361
|
-
|
|
12362
|
-
|
|
12363
|
-
|
|
12364
|
-
|
|
12365
|
-
|
|
12366
|
-
|
|
12367
|
-
|
|
12368
|
-
|
|
12369
|
-
|
|
12370
|
-
|
|
12371
|
-
|
|
12372
|
-
|
|
12373
|
-
|
|
12374
|
-
|
|
12375
|
-
|
|
12376
|
-
|
|
12377
|
-
|
|
12378
|
-
|
|
12379
|
-
|
|
12380
|
-
|
|
12985
|
+
const providerCapabilities = /* @__PURE__ */ new Map();
|
|
12986
|
+
let defaultProviderError;
|
|
12987
|
+
const providerRows = [];
|
|
12988
|
+
for (const providerId of [...new Set(Object.values(config.models))]) {
|
|
12989
|
+
try {
|
|
12990
|
+
const capabilities2 = await inspectOneProvider(providerId, apiKeyId);
|
|
12991
|
+
providerCapabilities.set(providerId, capabilities2);
|
|
12992
|
+
const affirmed = capabilities2.available === true && capabilities2.generate === true;
|
|
12993
|
+
providerRows.push({
|
|
12994
|
+
providerId,
|
|
12995
|
+
available: affirmed,
|
|
12996
|
+
...!affirmed ? { reason: capabilities2.reason ?? "runtime_unavailable" } : {},
|
|
12997
|
+
models: affirmed ? Object.entries(config.models).filter(([model, modelProvider]) => modelProvider === providerId && capabilities2.models.includes(model)).map(([model]) => model) : [],
|
|
12998
|
+
capabilities: capabilities2
|
|
12999
|
+
});
|
|
13000
|
+
} catch (error) {
|
|
13001
|
+
if (providerId === defaultProviderId) defaultProviderError = error;
|
|
13002
|
+
providerRows.push({
|
|
13003
|
+
providerId,
|
|
13004
|
+
available: false,
|
|
13005
|
+
reason: error instanceof ImageGenerationError4 && (error.code === "upstream_auth_required" || error.code === "invalid_api_key") ? "account_unverified" : "runtime_unavailable",
|
|
13006
|
+
models: []
|
|
13007
|
+
});
|
|
13008
|
+
}
|
|
13009
|
+
}
|
|
13010
|
+
const providers2 = Object.freeze(providerRows);
|
|
13011
|
+
const routedModels = Object.freeze(
|
|
13012
|
+
providerRows.flatMap((row) => row.available ? row.models : [])
|
|
13013
|
+
);
|
|
13014
|
+
const capabilities = providerCapabilities.get(defaultProviderId);
|
|
13015
|
+
if (!capabilities) {
|
|
12381
13016
|
return Object.freeze({
|
|
12382
13017
|
enabled: true,
|
|
12383
13018
|
available: false,
|
|
12384
|
-
providerId:
|
|
13019
|
+
providerId: defaultProviderId,
|
|
12385
13020
|
model: config.defaultModel,
|
|
12386
|
-
|
|
13021
|
+
routedModels,
|
|
13022
|
+
providers: providers2,
|
|
13023
|
+
reason: defaultProviderError instanceof ImageGenerationError4 && (defaultProviderError.code === "upstream_auth_required" || defaultProviderError.code === "invalid_api_key") ? "account_unverified" : "runtime_unavailable"
|
|
12387
13024
|
});
|
|
12388
13025
|
}
|
|
13026
|
+
const available = capabilities.available === true && capabilities.generate === true && capabilities.models.includes(config.defaultModel);
|
|
13027
|
+
return Object.freeze({
|
|
13028
|
+
enabled: true,
|
|
13029
|
+
available,
|
|
13030
|
+
providerId: defaultProviderId,
|
|
13031
|
+
model: config.defaultModel,
|
|
13032
|
+
routedModels,
|
|
13033
|
+
providers: providers2,
|
|
13034
|
+
...!available ? { reason: capabilities.reason ?? "runtime_unavailable" } : {},
|
|
13035
|
+
capabilities
|
|
13036
|
+
});
|
|
12389
13037
|
};
|
|
12390
13038
|
const resolverToDispose = runtimeResolver;
|
|
12391
13039
|
const schedulerToDispose = scheduler;
|
|
@@ -12423,7 +13071,7 @@ function createImageRuntimeGeneration(options) {
|
|
|
12423
13071
|
imageApi,
|
|
12424
13072
|
hosted,
|
|
12425
13073
|
hostedRuntime: Object.freeze({
|
|
12426
|
-
providerId:
|
|
13074
|
+
providerId: defaultProviderId,
|
|
12427
13075
|
imageModel: config.defaultModel,
|
|
12428
13076
|
referenceTtlMs: config.references.ttlMs,
|
|
12429
13077
|
maxOutputBytes: config.limits.maxOutputBytes,
|
|
@@ -15420,6 +16068,9 @@ var ImageRuntimeManager = class {
|
|
|
15420
16068
|
}
|
|
15421
16069
|
async listAvailableModels(apiKeyId) {
|
|
15422
16070
|
const inspection = await this.inspectCapability(apiKeyId);
|
|
16071
|
+
if (inspection.routedModels !== void 0) {
|
|
16072
|
+
return Object.freeze([...inspection.routedModels]);
|
|
16073
|
+
}
|
|
15423
16074
|
return inspection.available && inspection.model === "gpt-image-2" ? Object.freeze([inspection.model]) : Object.freeze([]);
|
|
15424
16075
|
}
|
|
15425
16076
|
resourceStatus() {
|
|
@@ -17635,11 +18286,13 @@ var JsonVoucherDb = class {
|
|
|
17635
18286
|
// src/ports/JsonSubscriptionCredentialStore.ts
|
|
17636
18287
|
import { existsSync as existsSync24, mkdirSync as mkdirSync6, readFileSync as readFileSync20, renameSync as renameSync13 } from "fs";
|
|
17637
18288
|
import { dirname as dirname15 } from "path";
|
|
18289
|
+
import { getAntigravityProjectResolver as getAntigravityProjectResolver2 } from "@omnicross/core/auth/GeminiCodeAssistProjectResolver";
|
|
17638
18290
|
import { getSharedAccountHealth as getSharedAccountHealth2 } from "@omnicross/core/pipeline/SubscriptionAccountHealth";
|
|
17639
18291
|
import { getSharedAccountAllowanceScheduling as getSharedAccountAllowanceScheduling3 } from "@omnicross/core/pipeline/AccountAllowanceScheduling";
|
|
17640
|
-
import { fetchUpstream as
|
|
18292
|
+
import { fetchUpstream as fetchUpstream12 } from "@omnicross/core/pipeline/upstreamFetch";
|
|
17641
18293
|
import { getSharedIdentityStore as getSharedIdentityStore2 } from "@omnicross/core/provider-proxy/identity/SubscriptionIdentityStore";
|
|
17642
18294
|
import {
|
|
18295
|
+
antigravityOAuth as antigravityOAuth2,
|
|
17643
18296
|
claudeOAuth as claudeOAuth2,
|
|
17644
18297
|
codexOAuth as codexOAuth2,
|
|
17645
18298
|
geminiOAuth as geminiOAuth2,
|
|
@@ -17793,7 +18446,7 @@ var JsonSubscriptionCredentialStore = class {
|
|
|
17793
18446
|
* a plaintext token pair into `upstream-trace.jsonl`.
|
|
17794
18447
|
*/
|
|
17795
18448
|
buildRefreshFetch(providerId, accountId) {
|
|
17796
|
-
return this.fetchImpl ?? ((url, init) =>
|
|
18449
|
+
return this.fetchImpl ?? ((url, init) => fetchUpstream12(url, init, { providerId, accountId, redactBodies: true }));
|
|
17797
18450
|
}
|
|
17798
18451
|
/**
|
|
17799
18452
|
* In-flight refresh coalescing. OAuth refresh tokens are
|
|
@@ -17834,7 +18487,7 @@ var JsonSubscriptionCredentialStore = class {
|
|
|
17834
18487
|
* other hot reads. Never returns token material.
|
|
17835
18488
|
*/
|
|
17836
18489
|
getAccountProxy(providerId, accountId) {
|
|
17837
|
-
if (providerId !== "claude" && providerId !== "codex" && providerId !== "gemini" && providerId !== "opencodego" && providerId !== "kimi" && providerId !== "grok" && providerId !== "copilot") {
|
|
18490
|
+
if (providerId !== "claude" && providerId !== "codex" && providerId !== "gemini" && providerId !== "opencodego" && providerId !== "kimi" && providerId !== "grok" && providerId !== "copilot" && providerId !== "antigravity") {
|
|
17838
18491
|
return void 0;
|
|
17839
18492
|
}
|
|
17840
18493
|
return getAccountProxy(this.readConfig(), providerId, accountId);
|
|
@@ -17853,7 +18506,7 @@ var JsonSubscriptionCredentialStore = class {
|
|
|
17853
18506
|
const fingerprintOn = identityStore.isEnabled();
|
|
17854
18507
|
const now = Date.now();
|
|
17855
18508
|
const out = {};
|
|
17856
|
-
for (const provider of ["claude", "codex", "gemini", "opencodego", "kimi", "grok", "copilot"]) {
|
|
18509
|
+
for (const provider of ["claude", "codex", "gemini", "opencodego", "kimi", "grok", "copilot", "antigravity"]) {
|
|
17857
18510
|
const sanitized = sanitizeAccounts(config, provider);
|
|
17858
18511
|
if (sanitized.length === 0) continue;
|
|
17859
18512
|
for (const account of sanitized) {
|
|
@@ -18112,6 +18765,76 @@ var JsonSubscriptionCredentialStore = class {
|
|
|
18112
18765
|
return false;
|
|
18113
18766
|
});
|
|
18114
18767
|
}
|
|
18768
|
+
/**
|
|
18769
|
+
* Refresh the Antigravity (Google) OAuth access token. Like gemini, the
|
|
18770
|
+
* Google token endpoint does NOT return a refresh_token on refresh, so this
|
|
18771
|
+
* writes ONLY access+expiresAt (+status/lastRefreshedAt) and DELIBERATELY
|
|
18772
|
+
* preserves the stored `refreshToken` — plus the account's `projectId`
|
|
18773
|
+
* (a handshake product; the post-refresh re-validation is the refresh
|
|
18774
|
+
* scheduler's hook, not this write) and `email`. HONEST `false` when no
|
|
18775
|
+
* refresh_token.
|
|
18776
|
+
*/
|
|
18777
|
+
async refreshAntigravityToken() {
|
|
18778
|
+
return this.coalesce("antigravity:active", async () => {
|
|
18779
|
+
const config = this.readConfig();
|
|
18780
|
+
const active = getActiveAccount(config, "antigravity");
|
|
18781
|
+
const antigravity = active?.tokens;
|
|
18782
|
+
if (!active || !antigravity?.refreshToken) return false;
|
|
18783
|
+
const capturedId = active.id;
|
|
18784
|
+
this.materializeMigration(config);
|
|
18785
|
+
const refreshFetch = this.buildRefreshFetch("antigravity", capturedId);
|
|
18786
|
+
try {
|
|
18787
|
+
const result = await antigravityOAuth2.refreshAccessToken(antigravity.refreshToken, refreshFetch);
|
|
18788
|
+
const expiresAt = new Date(Date.now() + result.expiresIn * 1e3).toISOString();
|
|
18789
|
+
const next = {
|
|
18790
|
+
...antigravity,
|
|
18791
|
+
// KEEP the existing refreshToken/projectId/email.
|
|
18792
|
+
accessToken: result.accessToken,
|
|
18793
|
+
expiresAt,
|
|
18794
|
+
status: "authorized",
|
|
18795
|
+
lastRefreshedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
18796
|
+
errorMessage: void 0
|
|
18797
|
+
};
|
|
18798
|
+
this.writeBackById("antigravity", capturedId, next);
|
|
18799
|
+
await this.revalidateAntigravityProject(capturedId);
|
|
18800
|
+
return true;
|
|
18801
|
+
} catch (error) {
|
|
18802
|
+
this.markExpiredById("antigravity", capturedId, antigravity, error);
|
|
18803
|
+
return false;
|
|
18804
|
+
}
|
|
18805
|
+
});
|
|
18806
|
+
}
|
|
18807
|
+
/**
|
|
18808
|
+
* Post-refresh project re-validation hook (antigravity design D8): after a
|
|
18809
|
+
* successful antigravity token refresh, re-run the Code Assist project
|
|
18810
|
+
* handshake and write the (possibly rotated) `projectId` back to the account.
|
|
18811
|
+
* A handshake FAILURE keeps the stored projectId untouched (logged) so the
|
|
18812
|
+
* account keeps serving with the last-known-good project until a later
|
|
18813
|
+
* refresh succeeds. Returns whether the handshake produced a project.
|
|
18814
|
+
*/
|
|
18815
|
+
async revalidateAntigravityProject(accountId) {
|
|
18816
|
+
const before = getAccountById(this.readConfig(), "antigravity", accountId);
|
|
18817
|
+
const accessToken = before?.tokens?.accessToken;
|
|
18818
|
+
if (!accessToken) return false;
|
|
18819
|
+
try {
|
|
18820
|
+
const projectId = await getAntigravityProjectResolver2().resolveProject(accessToken);
|
|
18821
|
+
if (projectId !== void 0) {
|
|
18822
|
+
const config = this.readConfig();
|
|
18823
|
+
const account = getAccountById(config, "antigravity", accountId);
|
|
18824
|
+
const tokens = account?.tokens;
|
|
18825
|
+
if (account && tokens?.accessToken === accessToken && tokens.projectId !== projectId) {
|
|
18826
|
+
this.writeBackById("antigravity", accountId, { ...tokens, projectId });
|
|
18827
|
+
}
|
|
18828
|
+
return true;
|
|
18829
|
+
}
|
|
18830
|
+
return false;
|
|
18831
|
+
} catch (error) {
|
|
18832
|
+
console.warn(
|
|
18833
|
+
`[JsonSubscriptionCredentialStore] antigravity project re-validation failed for account ${accountId}: ` + (error instanceof Error ? error.message : String(error))
|
|
18834
|
+
);
|
|
18835
|
+
return false;
|
|
18836
|
+
}
|
|
18837
|
+
}
|
|
18115
18838
|
/**
|
|
18116
18839
|
* Refresh a SPECIFIC managed account by id (background scheduler sweep and
|
|
18117
18840
|
* account-pool resolution). It uses only that account's stored refresh
|
|
@@ -18140,6 +18863,7 @@ var JsonSubscriptionCredentialStore = class {
|
|
|
18140
18863
|
};
|
|
18141
18864
|
if (refreshed.idToken) next.idToken = refreshed.idToken;
|
|
18142
18865
|
this.writeBackById(provider, id, next);
|
|
18866
|
+
if (provider === "antigravity") await this.revalidateAntigravityProject(id);
|
|
18143
18867
|
return true;
|
|
18144
18868
|
} catch (error) {
|
|
18145
18869
|
this.markExpiredById(provider, id, captured, error);
|
|
@@ -18164,7 +18888,7 @@ var JsonSubscriptionCredentialStore = class {
|
|
|
18164
18888
|
}
|
|
18165
18889
|
const oauth = account.tokens;
|
|
18166
18890
|
if (!oauth.accessToken) return null;
|
|
18167
|
-
if (providerId === "codex" || providerId === "gemini" || providerId === "kimi" || providerId === "grok" || providerId === "copilot") {
|
|
18891
|
+
if (providerId === "codex" || providerId === "gemini" || providerId === "kimi" || providerId === "grok" || providerId === "copilot" || providerId === "antigravity") {
|
|
18168
18892
|
const expiresAtMs = oauth.expiresAt ? Date.parse(oauth.expiresAt) : 0;
|
|
18169
18893
|
const expiringSoon = expiresAtMs > 0 && Date.now() >= expiresAtMs - ACCOUNT_REFRESH_LEAD_MS;
|
|
18170
18894
|
if (expiringSoon && oauth.refreshToken) {
|
|
@@ -18280,6 +19004,13 @@ var JsonSubscriptionCredentialStore = class {
|
|
|
18280
19004
|
if (provider === "copilot") {
|
|
18281
19005
|
throw new Error("GitHub Copilot tokens cannot be refreshed \u2014 re-authenticate the account");
|
|
18282
19006
|
}
|
|
19007
|
+
if (provider === "antigravity") {
|
|
19008
|
+
const r2 = await antigravityOAuth2.refreshAccessToken(refreshToken, refreshFetch);
|
|
19009
|
+
return {
|
|
19010
|
+
accessToken: r2.accessToken,
|
|
19011
|
+
expiresAt: new Date(Date.now() + r2.expiresIn * 1e3).toISOString()
|
|
19012
|
+
};
|
|
19013
|
+
}
|
|
18283
19014
|
const flow = provider === "claude" ? claudeOAuth2 : provider === "codex" ? codexOAuth2 : geminiOAuth2;
|
|
18284
19015
|
const r = await flow.refreshAccessToken(refreshToken, refreshFetch);
|
|
18285
19016
|
return {
|
|
@@ -18523,7 +19254,7 @@ var JsonSubscriptionCredentialStore = class {
|
|
|
18523
19254
|
};
|
|
18524
19255
|
|
|
18525
19256
|
// src/AccountHealthProbeScheduler.ts
|
|
18526
|
-
import { fetchUpstream as
|
|
19257
|
+
import { fetchUpstream as fetchUpstream13 } from "@omnicross/core/pipeline/upstreamFetch";
|
|
18527
19258
|
|
|
18528
19259
|
// src/probe/CodexGenerationProbe.ts
|
|
18529
19260
|
import {
|
|
@@ -18678,7 +19409,11 @@ var PROVIDER_PROBE_PLANS = {
|
|
|
18678
19409
|
// The Copilot quota endpoint (copilot_internal/user) is a verified FREE
|
|
18679
19410
|
// authed GET but lives on api.github.com with its own auth dialect and a
|
|
18680
19411
|
// monthly-only window — the allowance collector owns the health surface.
|
|
18681
|
-
copilot: { kind: "local" }
|
|
19412
|
+
copilot: { kind: "local" },
|
|
19413
|
+
// Antigravity's quota endpoints are POST RPCs on daily-cloudcode-pa (not a
|
|
19414
|
+
// cheap GET) and need the antigravity/hub UA — the allowance collector owns
|
|
19415
|
+
// the health surface; the probe stays local.
|
|
19416
|
+
antigravity: { kind: "local" }
|
|
18682
19417
|
};
|
|
18683
19418
|
function probePlanFor(providerId) {
|
|
18684
19419
|
return PROVIDER_PROBE_PLANS[providerId] ?? { kind: "local" };
|
|
@@ -18700,7 +19435,7 @@ var AccountHealthProbeScheduler = class {
|
|
|
18700
19435
|
this.logger = logger;
|
|
18701
19436
|
this.config = config;
|
|
18702
19437
|
this.now = opts.now ?? Date.now;
|
|
18703
|
-
this.fetchImpl = opts.fetchImpl ??
|
|
19438
|
+
this.fetchImpl = opts.fetchImpl ?? fetchUpstream13;
|
|
18704
19439
|
this.sleep = opts.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
|
|
18705
19440
|
this.planFor = opts.planFor ?? probePlanFor;
|
|
18706
19441
|
}
|
|
@@ -19863,7 +20598,7 @@ var AuditWriter = class {
|
|
|
19863
20598
|
import { appendFileSync as appendFileSync3, mkdirSync as mkdirSync8 } from "fs";
|
|
19864
20599
|
import { createHmac as createHmac5 } from "crypto";
|
|
19865
20600
|
import { join as join27 } from "path";
|
|
19866
|
-
import { fetchUpstream as
|
|
20601
|
+
import { fetchUpstream as fetchUpstream14 } from "@omnicross/core/pipeline/upstreamFetch";
|
|
19867
20602
|
|
|
19868
20603
|
// src/billing/billingFiles.ts
|
|
19869
20604
|
var BILLING_FILE_RE = /^billing-(\d{4})-(\d{2})-(\d{2})\.jsonl$/;
|
|
@@ -19886,7 +20621,7 @@ var BillingPublisher = class {
|
|
|
19886
20621
|
constructor(billingDir, logger, opts = {}) {
|
|
19887
20622
|
this.billingDir = billingDir;
|
|
19888
20623
|
this.logger = logger;
|
|
19889
|
-
this.fetchImpl = opts.fetchImpl ?? ((url, init) =>
|
|
20624
|
+
this.fetchImpl = opts.fetchImpl ?? ((url, init) => fetchUpstream14(url, init));
|
|
19890
20625
|
this.defer = opts.defer ?? ((fn) => setTimeout(fn, 0));
|
|
19891
20626
|
this.timeoutMs = opts.timeoutMs ?? BILLING_POST_TIMEOUT_MS;
|
|
19892
20627
|
this.now = opts.now ?? Date.now;
|
|
@@ -20136,7 +20871,7 @@ var BillingRetrySweeper = class {
|
|
|
20136
20871
|
// src/TokenRefreshScheduler.ts
|
|
20137
20872
|
var REFRESH_LEAD_MS2 = 5 * 6e4;
|
|
20138
20873
|
var SWEEP_INTERVAL_MS5 = 6e4;
|
|
20139
|
-
var OAUTH_PROVIDERS2 = ["claude", "codex", "gemini", "kimi", "grok", "copilot"];
|
|
20874
|
+
var OAUTH_PROVIDERS2 = ["claude", "codex", "gemini", "kimi", "grok", "copilot", "antigravity"];
|
|
20140
20875
|
var TokenRefreshScheduler = class {
|
|
20141
20876
|
constructor(store, logger, intervalMs = SWEEP_INTERVAL_MS5, leadMs = REFRESH_LEAD_MS2) {
|
|
20142
20877
|
this.store = store;
|
|
@@ -20227,6 +20962,8 @@ var TokenRefreshScheduler = class {
|
|
|
20227
20962
|
// never reaches this — the branch exists for union totality.
|
|
20228
20963
|
case "copilot":
|
|
20229
20964
|
return this.store.refreshCopilotToken();
|
|
20965
|
+
case "antigravity":
|
|
20966
|
+
return this.store.refreshAntigravityToken();
|
|
20230
20967
|
}
|
|
20231
20968
|
}
|
|
20232
20969
|
};
|
|
@@ -20305,7 +21042,7 @@ function createRouteLeaseSubscriptionPreflight(credentials) {
|
|
|
20305
21042
|
|
|
20306
21043
|
// src/webhook/WebhookDispatcher.ts
|
|
20307
21044
|
import { createHmac as createHmac6 } from "crypto";
|
|
20308
|
-
import { fetchUpstream as
|
|
21045
|
+
import { fetchUpstream as fetchUpstream15 } from "@omnicross/core/pipeline/upstreamFetch";
|
|
20309
21046
|
var WEBHOOK_MAX_ATTEMPTS = 3;
|
|
20310
21047
|
var WEBHOOK_QUEUE_MAX = 1e3;
|
|
20311
21048
|
var WEBHOOK_SEND_TIMEOUT_MS = 1e4;
|
|
@@ -20325,7 +21062,7 @@ var WebhookDispatcher = class {
|
|
|
20325
21062
|
sleep;
|
|
20326
21063
|
now;
|
|
20327
21064
|
constructor(opts = {}) {
|
|
20328
|
-
this.fetchImpl = opts.fetchImpl ?? ((url, init) =>
|
|
21065
|
+
this.fetchImpl = opts.fetchImpl ?? ((url, init) => fetchUpstream15(url, init));
|
|
20329
21066
|
this.logger = opts.logger;
|
|
20330
21067
|
this.maxAttempts = opts.maxAttempts ?? WEBHOOK_MAX_ATTEMPTS;
|
|
20331
21068
|
this.queueMax = opts.queueMax ?? WEBHOOK_QUEUE_MAX;
|
|
@@ -20411,8 +21148,8 @@ var WebhookDispatcher = class {
|
|
|
20411
21148
|
signal: AbortSignal.timeout(this.timeoutMs)
|
|
20412
21149
|
});
|
|
20413
21150
|
return res.ok ? { ok: true, status: res.status } : { ok: false, status: res.status };
|
|
20414
|
-
} catch (
|
|
20415
|
-
return { ok: false, error:
|
|
21151
|
+
} catch (err9) {
|
|
21152
|
+
return { ok: false, error: err9 instanceof Error ? err9.message : String(err9) };
|
|
20416
21153
|
}
|
|
20417
21154
|
}
|
|
20418
21155
|
/**
|
|
@@ -20549,7 +21286,7 @@ function buildDaemon(config, paths) {
|
|
|
20549
21286
|
setSecretBox(secretBox3);
|
|
20550
21287
|
setSecretBox2(secretBox3);
|
|
20551
21288
|
const decryptedConfig = decryptConfigSecrets(config, secretBox3);
|
|
20552
|
-
const accountAllowanceStore = new
|
|
21289
|
+
const accountAllowanceStore = new AccountAllowanceStore10(
|
|
20553
21290
|
Date.now,
|
|
20554
21291
|
void 0,
|
|
20555
21292
|
new JsonAccountAllowancePersistence(defaultAccountAllowancePath(paths.configPath))
|
|
@@ -20593,6 +21330,8 @@ function buildDaemon(config, paths) {
|
|
|
20593
21330
|
})
|
|
20594
21331
|
);
|
|
20595
21332
|
setGeminiCodeAssistResolver(getGeminiCodeAssistProjectResolver2());
|
|
21333
|
+
setAntigravitySandboxFailover(decryptedConfig.antigravity?.sandboxFailover === true);
|
|
21334
|
+
setOpenCodeGoUserAgent(decryptedConfig.opencodego?.userAgent ?? null);
|
|
20596
21335
|
const autoDisableStore = new AutoDisableStore();
|
|
20597
21336
|
const providerKeyQuotaService = new ProviderKeyQuotaService(secretBox3);
|
|
20598
21337
|
const apiKeyPool = new ApiKeyPoolService(
|
|
@@ -20611,7 +21350,7 @@ function buildDaemon(config, paths) {
|
|
|
20611
21350
|
const pricingEngine = new PricingEngine(pricingStore, logger, {
|
|
20612
21351
|
// Catalog egress follows the same global/env proxy policy as every other
|
|
20613
21352
|
// daemon upstream call; no provider/account override applies here.
|
|
20614
|
-
fetchImpl: ((input, init) =>
|
|
21353
|
+
fetchImpl: ((input, init) => fetchUpstream16(String(input), init ?? {}))
|
|
20615
21354
|
});
|
|
20616
21355
|
const pricingRefreshScheduler = new PricingRefreshScheduler(
|
|
20617
21356
|
pricingEngine,
|
|
@@ -20853,6 +21592,7 @@ function buildDaemon(config, paths) {
|
|
|
20853
21592
|
outboundApiServer,
|
|
20854
21593
|
imageRuntimeConfig,
|
|
20855
21594
|
imageRuntimeStatus: paths.imageRuntimeStatus ?? imageRuntimeManager,
|
|
21595
|
+
imageLiveVerifier: paths.imageLiveVerifier ?? imageDoctor,
|
|
20856
21596
|
imageConfigAudit: paths.imageConfigAudit ?? ((record) => {
|
|
20857
21597
|
imageObservability.recordConfigurationAudit(record);
|
|
20858
21598
|
}),
|
|
@@ -20896,7 +21636,7 @@ function buildDaemon(config, paths) {
|
|
|
20896
21636
|
// — `server.proxy.byProvider[...]` was silently skipped — and the call was
|
|
20897
21637
|
// excluded from the upstream trace, so a failing login left no evidence.
|
|
20898
21638
|
// `redactBodies` keeps the code/verifier + minted token out of that trace.
|
|
20899
|
-
oauthExchangeFetch: paths.oauthExchangeFetch ? () => paths.oauthExchangeFetch : (providerId) => (url, init) =>
|
|
21639
|
+
oauthExchangeFetch: paths.oauthExchangeFetch ? () => paths.oauthExchangeFetch : (providerId) => (url, init) => fetchUpstream16(url, init, { providerId, redactBodies: true }),
|
|
20900
21640
|
subscriptionAccountAppender: credentialStore,
|
|
20901
21641
|
// Codex interactive OAuth (app-parity-2 child 5) — the async loopback flow store
|
|
20902
21642
|
// + the one-shot 127.0.0.1:1455 listener. Token captured + persisted daemon-side;
|
|
@@ -20911,6 +21651,21 @@ function buildDaemon(config, paths) {
|
|
|
20911
21651
|
// Grok interactive OAuth — the same async DEVICE-CODE shape as kimi.
|
|
20912
21652
|
grokSessions: new CodexOAuthSessionStore(),
|
|
20913
21653
|
copilotSessions: new CodexOAuthSessionStore(),
|
|
21654
|
+
// Antigravity interactive OAuth — the async LOOPBACK flow store + the
|
|
21655
|
+
// one-shot 127.0.0.1:51121 listener (same shape as codex; test seam below).
|
|
21656
|
+
antigravitySessions: new CodexOAuthSessionStore(),
|
|
21657
|
+
antigravityAwaitLoopback: paths.antigravityAwaitLoopback ?? ((state, timeoutMs, signal) => awaitLoopbackCode(state, timeoutMs, signal, {
|
|
21658
|
+
port: 51121,
|
|
21659
|
+
path: "/oauth-callback",
|
|
21660
|
+
label: "antigravity"
|
|
21661
|
+
})),
|
|
21662
|
+
// The dynamic model-catalog probe's token source (the ACTIVE antigravity
|
|
21663
|
+
// account; refreshed by the by-id near-expiry seam inside the lookup).
|
|
21664
|
+
resolveAntigravityAccessToken: async () => {
|
|
21665
|
+
const config2 = await credentialStore.getFullConfig();
|
|
21666
|
+
const activeId = config2.activeAntigravityAccountId ?? config2.antigravityAccounts?.[0]?.id;
|
|
21667
|
+
return activeId ? credentialStore.getAccessTokenForAccount("antigravity", activeId) : null;
|
|
21668
|
+
},
|
|
20914
21669
|
// Migration pack (app-parity child 6, design D2/D3) — the concrete credential
|
|
20915
21670
|
// store provides BOTH the full DECRYPTED read (`getFullConfig`, export) and
|
|
20916
21671
|
// the multi-account append (`appendProviderAccount`, import re-encrypts at-
|
|
@@ -20969,7 +21724,7 @@ function buildDaemon(config, paths) {
|
|
|
20969
21724
|
});
|
|
20970
21725
|
const webhookDispatcher = new WebhookDispatcher({
|
|
20971
21726
|
logger,
|
|
20972
|
-
fetchImpl: (url, init) =>
|
|
21727
|
+
fetchImpl: (url, init) => fetchUpstream16(url, init)
|
|
20973
21728
|
});
|
|
20974
21729
|
setWebhookRuntime(webhookDispatcher, getSharedAccountHealth4());
|
|
20975
21730
|
const auditWriter = new AuditWriter(auditDir, logger);
|
|
@@ -21104,15 +21859,59 @@ function buildClaudeDoctorChecks(config) {
|
|
|
21104
21859
|
});
|
|
21105
21860
|
return checks;
|
|
21106
21861
|
}
|
|
21862
|
+
function buildAntigravityDoctorChecks(snapshot) {
|
|
21863
|
+
const checks = [];
|
|
21864
|
+
checks.push({
|
|
21865
|
+
name: "antigravity credential",
|
|
21866
|
+
ok: snapshot.accountCount > 0 && snapshot.hasAccessToken,
|
|
21867
|
+
detail: snapshot.accountCount === 0 ? "no antigravity account stored \u2014 run `omnicross login antigravity`" : `${snapshot.accountCount} account(s)${snapshot.activeEmail ? `, active: ${snapshot.activeEmail}` : ""}${snapshot.hasAccessToken ? "" : " \u2014 the active account has no access token"}`
|
|
21868
|
+
});
|
|
21869
|
+
const expiresAtMs = snapshot.expiresAt ? Date.parse(snapshot.expiresAt) : 0;
|
|
21870
|
+
const expired = snapshot.expired || expiresAtMs > 0 && Date.now() >= expiresAtMs;
|
|
21871
|
+
const expiringSoon = expiresAtMs > 0 && Date.now() >= expiresAtMs - 10 * 6e4;
|
|
21872
|
+
checks.push({
|
|
21873
|
+
name: "token freshness",
|
|
21874
|
+
ok: !expired,
|
|
21875
|
+
warn: !expired && expiringSoon,
|
|
21876
|
+
detail: expired ? "the active account is expired (its last refresh failed \u2014 re-login or fix the refresh path)" : snapshot.expiresAt ? `expires at ${snapshot.expiresAt}${expiringSoon ? " (inside the refresh lead window)" : ""}` : "no expiry recorded (refresh scheduler treats it as non-expiring)"
|
|
21877
|
+
});
|
|
21878
|
+
return checks;
|
|
21879
|
+
}
|
|
21880
|
+
function hasFreshAntigravityQuota(snapshot, now = Date.now()) {
|
|
21881
|
+
if (!snapshot || snapshot.lastErrorCode) return false;
|
|
21882
|
+
if (snapshot.expiresAt && !(Date.parse(snapshot.expiresAt) > now)) return false;
|
|
21883
|
+
return snapshot.windows.some(
|
|
21884
|
+
(window) => window.state === "fresh" && (!window.resetsAt || Date.parse(window.resetsAt) > now) && (window.disabled === true || typeof window.usedPercent === "number" && Number.isFinite(window.usedPercent))
|
|
21885
|
+
);
|
|
21886
|
+
}
|
|
21887
|
+
function buildAntigravityLiveChecks(result) {
|
|
21888
|
+
return [
|
|
21889
|
+
{
|
|
21890
|
+
name: "token refresh (--live)",
|
|
21891
|
+
ok: result.refreshOk,
|
|
21892
|
+
detail: result.refreshOk ? "the active account refreshed successfully" : "refresh failed (see the daemon log)"
|
|
21893
|
+
},
|
|
21894
|
+
{
|
|
21895
|
+
name: "quota collection (--live)",
|
|
21896
|
+
ok: result.quotaOk,
|
|
21897
|
+
detail: result.quotaOk ? "quotaSummary windows collected" : result.detail
|
|
21898
|
+
}
|
|
21899
|
+
];
|
|
21900
|
+
}
|
|
21107
21901
|
function buildImagesDoctorChecks(snapshot) {
|
|
21108
21902
|
const enabled = snapshot.config.enabled;
|
|
21109
|
-
const
|
|
21903
|
+
const routed = snapshot.config.routedProviders ?? ["codex-subscription"];
|
|
21904
|
+
const codexRouted = routed.includes("codex-subscription");
|
|
21905
|
+
const antigravityRouted = routed.includes("antigravity-subscription");
|
|
21906
|
+
const antigravity = snapshot.antigravityAccount ?? { present: false, usable: false, reason: "missing" };
|
|
21907
|
+
const accountOk = !enabled || !codexRouted || snapshot.account.usable;
|
|
21908
|
+
const antigravityOk = !enabled || !antigravityRouted || antigravity.usable;
|
|
21110
21909
|
const evidenceOk = !enabled || snapshot.evidence.valid && snapshot.evidence.freshEntries > 0;
|
|
21111
21910
|
return [
|
|
21112
21911
|
{
|
|
21113
21912
|
name: "normalized Images config",
|
|
21114
21913
|
ok: snapshot.config.valid,
|
|
21115
|
-
detail: snapshot.config.valid ? `enabled=${enabled},
|
|
21914
|
+
detail: snapshot.config.valid ? `enabled=${enabled}, providers=${routed.join("+")}, default=${snapshot.config.model} (${snapshot.config.provider})` : `invalid normalized configuration (${snapshot.config.errorCount} issue(s))`
|
|
21116
21915
|
},
|
|
21117
21916
|
{
|
|
21118
21917
|
name: "private roots",
|
|
@@ -21133,8 +21932,14 @@ function buildImagesDoctorChecks(snapshot) {
|
|
|
21133
21932
|
{
|
|
21134
21933
|
name: "Codex account",
|
|
21135
21934
|
ok: accountOk,
|
|
21136
|
-
warn: !snapshot.account.usable,
|
|
21137
|
-
detail: snapshot.account.usable ? "eligible local credential is present" : `${snapshot.account.reason};
|
|
21935
|
+
warn: enabled && codexRouted && !snapshot.account.usable,
|
|
21936
|
+
detail: !codexRouted ? "not routed by the current model table (no credential required)" : snapshot.account.usable ? "eligible local credential is present" : `${snapshot.account.reason}; codex-routed image models and live verification are unavailable`
|
|
21937
|
+
},
|
|
21938
|
+
{
|
|
21939
|
+
name: "Antigravity account",
|
|
21940
|
+
ok: antigravityOk,
|
|
21941
|
+
warn: enabled && antigravityRouted && !antigravity.usable,
|
|
21942
|
+
detail: !antigravityRouted ? "not routed by the current model table (no credential required)" : antigravity.usable ? "eligible local credential is present (protocol evidence still unverified)" : `${antigravity.reason}; antigravity-routed image models are unavailable`
|
|
21138
21943
|
},
|
|
21139
21944
|
{
|
|
21140
21945
|
name: "cached capability evidence",
|
|
@@ -21149,6 +21954,12 @@ async function runImagesLiveDoctor(config, doctor, signal = new AbortController(
|
|
|
21149
21954
|
" [\u26A0] live Images verification may consume subscription quota; one minimal low-quality PNG request will be sent"
|
|
21150
21955
|
);
|
|
21151
21956
|
const result = await doctor.verifyLive(config.images ?? DEFAULT_IMAGES_SERVER_CONFIG2, signal);
|
|
21957
|
+
const antigravityRouted = Object.values(config.images?.models ?? {}).includes("antigravity-subscription");
|
|
21958
|
+
if (antigravityRouted) {
|
|
21959
|
+
console.info(
|
|
21960
|
+
" [i] live verification covers the Codex wire only; the Antigravity provider has no independent verifier in v1 (its first real request bootstraps)"
|
|
21961
|
+
);
|
|
21962
|
+
}
|
|
21152
21963
|
if (!result.ok) {
|
|
21153
21964
|
console.info(` [\u2717] live Images verification: ${result.code}`);
|
|
21154
21965
|
return false;
|
|
@@ -21283,14 +22094,49 @@ async function runLiveProbe(url, key, fetchImpl = fetch) {
|
|
|
21283
22094
|
status: res.status,
|
|
21284
22095
|
estimateHeader: res.headers.get("x-omnicross-count-estimate")
|
|
21285
22096
|
};
|
|
21286
|
-
} catch (
|
|
22097
|
+
} catch (err9) {
|
|
21287
22098
|
return {
|
|
21288
22099
|
status: null,
|
|
21289
22100
|
estimateHeader: null,
|
|
21290
|
-
error:
|
|
22101
|
+
error: err9 instanceof Error ? err9.message : String(err9)
|
|
21291
22102
|
};
|
|
21292
22103
|
}
|
|
21293
22104
|
}
|
|
22105
|
+
async function runAntigravityDoctor(daemon, live) {
|
|
22106
|
+
const config = await daemon.credentialStore.getFullConfig();
|
|
22107
|
+
const accounts = config.antigravityAccounts ?? [];
|
|
22108
|
+
const activeId = config.activeAntigravityAccountId ?? accounts[0]?.id;
|
|
22109
|
+
const active = accounts.find((account) => account.id === activeId);
|
|
22110
|
+
const snapshot = {
|
|
22111
|
+
accountCount: accounts.length,
|
|
22112
|
+
...active?.tokens.email ? { activeEmail: active.tokens.email } : {},
|
|
22113
|
+
hasAccessToken: Boolean(active?.tokens.accessToken),
|
|
22114
|
+
expired: active?.tokens.status === "expired",
|
|
22115
|
+
...active?.tokens.expiresAt ? { expiresAt: active.tokens.expiresAt } : {}
|
|
22116
|
+
};
|
|
22117
|
+
const checks = buildAntigravityDoctorChecks(snapshot);
|
|
22118
|
+
if (live && active) {
|
|
22119
|
+
const refreshOk = await daemon.credentialStore.refreshAntigravityToken();
|
|
22120
|
+
let quotaOk = false;
|
|
22121
|
+
let detail = "quotaSummary collection produced no usable windows";
|
|
22122
|
+
try {
|
|
22123
|
+
const snapshots = await daemon.accountAllowanceService.refreshAntigravity(active.id);
|
|
22124
|
+
quotaOk = hasFreshAntigravityQuota(snapshots.find((entry) => entry.accountId === active.id));
|
|
22125
|
+
if (!quotaOk) detail = snapshots[0]?.lastErrorCode ?? detail;
|
|
22126
|
+
} catch (error) {
|
|
22127
|
+
detail = error instanceof Error ? error.message : String(error);
|
|
22128
|
+
}
|
|
22129
|
+
checks.push(...buildAntigravityLiveChecks({ refreshOk, quotaOk, detail }));
|
|
22130
|
+
}
|
|
22131
|
+
console.info("omnicross doctor antigravity \u2014 subscription credential health");
|
|
22132
|
+
let hardFailure = false;
|
|
22133
|
+
for (const check of checks) {
|
|
22134
|
+
const mark = check.ok ? check.warn ? "\u26A0" : "\u2713" : "\u2717";
|
|
22135
|
+
if (!check.ok) hardFailure = true;
|
|
22136
|
+
console.info(` [${mark}] ${check.name}: ${check.detail}`);
|
|
22137
|
+
}
|
|
22138
|
+
return hardFailure ? 1 : 0;
|
|
22139
|
+
}
|
|
21294
22140
|
async function runDoctor(argv, fetchImpl = fetch) {
|
|
21295
22141
|
const { values, positionals } = parseArgs2({
|
|
21296
22142
|
args: argv,
|
|
@@ -21304,8 +22150,8 @@ async function runDoctor(argv, fetchImpl = fetch) {
|
|
|
21304
22150
|
allowPositionals: true
|
|
21305
22151
|
});
|
|
21306
22152
|
const subject = positionals[0] ?? "claude";
|
|
21307
|
-
if (subject !== "claude" && subject !== "images" && subject !== "search") {
|
|
21308
|
-
throw new Error(`doctor: unknown subject '${subject}' (supported: 'claude', 'images', 'search')`);
|
|
22153
|
+
if (subject !== "claude" && subject !== "images" && subject !== "search" && subject !== "antigravity") {
|
|
22154
|
+
throw new Error(`doctor: unknown subject '${subject}' (supported: 'claude', 'images', 'search', 'antigravity')`);
|
|
21309
22155
|
}
|
|
21310
22156
|
const configPath = values.config;
|
|
21311
22157
|
if (!configPath) {
|
|
@@ -21328,6 +22174,9 @@ async function runDoctor(argv, fetchImpl = fetch) {
|
|
|
21328
22174
|
runtime: daemon.searchRuntime
|
|
21329
22175
|
});
|
|
21330
22176
|
}
|
|
22177
|
+
if (subject === "antigravity") {
|
|
22178
|
+
return await runAntigravityDoctor(daemon, values.live === true);
|
|
22179
|
+
}
|
|
21331
22180
|
const checks = subject === "images" ? buildImagesDoctorChecks(await daemon.imageDoctor.inspectLocal(
|
|
21332
22181
|
serverConfig.images ?? DEFAULT_IMAGES_SERVER_CONFIG2
|
|
21333
22182
|
)) : buildClaudeDoctorChecks(serverConfig);
|
|
@@ -21697,9 +22546,9 @@ async function runLaunch(argv, deps) {
|
|
|
21697
22546
|
await daemon.llmConfig.ready();
|
|
21698
22547
|
await daemon.migrateUsageStore();
|
|
21699
22548
|
await daemon.providerProxy.start();
|
|
21700
|
-
} catch (
|
|
22549
|
+
} catch (err9) {
|
|
21701
22550
|
await shutdownLaunchDaemon(daemon);
|
|
21702
|
-
throw
|
|
22551
|
+
throw err9;
|
|
21703
22552
|
}
|
|
21704
22553
|
let launch;
|
|
21705
22554
|
try {
|
|
@@ -21707,9 +22556,9 @@ async function runLaunch(argv, deps) {
|
|
|
21707
22556
|
providerId: values.provider,
|
|
21708
22557
|
model: values.model
|
|
21709
22558
|
});
|
|
21710
|
-
} catch (
|
|
22559
|
+
} catch (err9) {
|
|
21711
22560
|
await shutdownLaunchDaemon(daemon);
|
|
21712
|
-
throw
|
|
22561
|
+
throw err9;
|
|
21713
22562
|
}
|
|
21714
22563
|
try {
|
|
21715
22564
|
const plan = buildCliSpawnPlan({
|
|
@@ -21814,9 +22663,9 @@ function spawnCliInherit(plan) {
|
|
|
21814
22663
|
process.removeListener("SIGINT", onSignal);
|
|
21815
22664
|
process.removeListener("SIGTERM", onSignal);
|
|
21816
22665
|
};
|
|
21817
|
-
child.on("error", (
|
|
22666
|
+
child.on("error", (err9) => {
|
|
21818
22667
|
detach();
|
|
21819
|
-
if (
|
|
22668
|
+
if (err9.code === "ENOENT") {
|
|
21820
22669
|
reject(
|
|
21821
22670
|
new Error(
|
|
21822
22671
|
`launch: "${plan.command}" not found on PATH \u2014 install the CLI first.`
|
|
@@ -21824,7 +22673,7 @@ function spawnCliInherit(plan) {
|
|
|
21824
22673
|
);
|
|
21825
22674
|
return;
|
|
21826
22675
|
}
|
|
21827
|
-
reject(
|
|
22676
|
+
reject(err9);
|
|
21828
22677
|
});
|
|
21829
22678
|
child.on("exit", (code, signal) => {
|
|
21830
22679
|
detach();
|
|
@@ -21837,8 +22686,10 @@ function spawnCliInherit(plan) {
|
|
|
21837
22686
|
import { spawn as spawn3 } from "child_process";
|
|
21838
22687
|
import { createInterface as createInterface2 } from "readline";
|
|
21839
22688
|
import { parseArgs as parseArgs7 } from "util";
|
|
21840
|
-
import {
|
|
22689
|
+
import { getAntigravityProjectResolver as getAntigravityProjectResolver3 } from "@omnicross/core/auth/GeminiCodeAssistProjectResolver";
|
|
22690
|
+
import { fetchUpstream as fetchUpstream17, setUpstreamProxyResolver as setUpstreamProxyResolver2 } from "@omnicross/core/pipeline/upstreamFetch";
|
|
21841
22691
|
import {
|
|
22692
|
+
antigravityOAuth as antigravityOAuth3,
|
|
21842
22693
|
claudeOAuth as claudeOAuth3,
|
|
21843
22694
|
codexOAuth as codexOAuth3,
|
|
21844
22695
|
copilotOAuth as copilotOAuth3,
|
|
@@ -21846,7 +22697,7 @@ import {
|
|
|
21846
22697
|
grokOAuth as grokOAuth3,
|
|
21847
22698
|
kimiOAuth as kimiOAuth3
|
|
21848
22699
|
} from "@omnicross/subscriptions";
|
|
21849
|
-
var PROVIDERS2 = ["claude", "codex", "gemini", "kimi", "grok", "copilot"];
|
|
22700
|
+
var PROVIDERS2 = ["claude", "codex", "gemini", "kimi", "grok", "copilot", "antigravity"];
|
|
21850
22701
|
async function runLogin(argv, deps) {
|
|
21851
22702
|
const { values, positionals } = parseArgs7({
|
|
21852
22703
|
args: argv,
|
|
@@ -21877,7 +22728,7 @@ async function runLogin(argv, deps) {
|
|
|
21877
22728
|
const resolved = {
|
|
21878
22729
|
openBrowser: deps?.openBrowser ?? openBrowser,
|
|
21879
22730
|
promptPaste: deps?.promptPaste ?? promptPaste,
|
|
21880
|
-
awaitLoopback: deps?.awaitLoopback ?? ((state) => awaitLoopbackCode(state)),
|
|
22731
|
+
awaitLoopback: deps?.awaitLoopback ?? ((state, timeoutMs, signal, binding) => awaitLoopbackCode(state, timeoutMs, signal, binding)),
|
|
21881
22732
|
awaitKimiDevice: deps?.awaitKimiDevice ?? ((fetchImpl) => runKimiDeviceFlow(fetchImpl, resolvedOpenBrowser)),
|
|
21882
22733
|
awaitGrokDevice: deps?.awaitGrokDevice ?? ((fetchImpl) => runGrokDeviceFlow(fetchImpl, resolvedOpenBrowser)),
|
|
21883
22734
|
awaitCopilotDevice: deps?.awaitCopilotDevice ?? ((fetchImpl, enterpriseUrl) => runCopilotDeviceFlow(fetchImpl, resolvedOpenBrowser, enterpriseUrl)),
|
|
@@ -21889,7 +22740,7 @@ async function runLogin(argv, deps) {
|
|
|
21889
22740
|
setUpstreamProxyResolver2(createUpstreamProxyResolver());
|
|
21890
22741
|
try {
|
|
21891
22742
|
const tokensPath = defaultTokensPath(values.config);
|
|
21892
|
-
const exchangeFetch = resolved.tokensFetch ?? ((url, init) =>
|
|
22743
|
+
const exchangeFetch = resolved.tokensFetch ?? ((url, init) => fetchUpstream17(url, init, { providerId: provider, redactBodies: true }));
|
|
21893
22744
|
const store = new JsonSubscriptionCredentialStore(tokensPath, box, exchangeFetch);
|
|
21894
22745
|
const expiresAt = await runProviderLogin(
|
|
21895
22746
|
provider,
|
|
@@ -21912,6 +22763,7 @@ async function runProviderLogin(provider, store, deps, exchangeFetch, label, ent
|
|
|
21912
22763
|
if (provider === "kimi") return loginKimi(store, deps, exchangeFetch, label);
|
|
21913
22764
|
if (provider === "grok") return loginGrok(store, deps, exchangeFetch, label);
|
|
21914
22765
|
if (provider === "copilot") return loginCopilot(store, deps, exchangeFetch, label, enterpriseUrl);
|
|
22766
|
+
if (provider === "antigravity") return loginAntigravity(store, deps, exchangeFetch, label);
|
|
21915
22767
|
return loginGemini(store, deps, exchangeFetch, label);
|
|
21916
22768
|
}
|
|
21917
22769
|
async function loginCodex(store, deps, exchangeFetch, label) {
|
|
@@ -22105,6 +22957,70 @@ async function loginCopilot(store, deps, exchangeFetch, label, enterpriseUrl) {
|
|
|
22105
22957
|
logMasked("copilot", result.accessToken);
|
|
22106
22958
|
return expiresAt;
|
|
22107
22959
|
}
|
|
22960
|
+
async function loginAntigravity(store, deps, exchangeFetch, label) {
|
|
22961
|
+
const { authUrl, state } = antigravityOAuth3.generateAuthParams();
|
|
22962
|
+
await presentUrl(authUrl, deps);
|
|
22963
|
+
const code = await captureAntigravityCode(deps, state);
|
|
22964
|
+
const result = await antigravityOAuth3.exchangeCodeForTokens(code, exchangeFetch);
|
|
22965
|
+
const expiresAt = new Date(Date.now() + result.expiresIn * 1e3).toISOString();
|
|
22966
|
+
const email = await antigravityOAuth3.fetchUserEmail(result.accessToken, exchangeFetch);
|
|
22967
|
+
console.info("Resolving the Antigravity Cloud Code Assist project...");
|
|
22968
|
+
const projectId = await getAntigravityProjectResolver3().resolveProject(result.accessToken);
|
|
22969
|
+
const block = {
|
|
22970
|
+
authMethod: "oauth",
|
|
22971
|
+
status: "authorized",
|
|
22972
|
+
accessToken: result.accessToken,
|
|
22973
|
+
refreshToken: result.refreshToken,
|
|
22974
|
+
expiresAt,
|
|
22975
|
+
...email ? { email } : {},
|
|
22976
|
+
...projectId ? { projectId } : {},
|
|
22977
|
+
lastRefreshedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
22978
|
+
};
|
|
22979
|
+
await store.appendProviderAccount("antigravity", block, label);
|
|
22980
|
+
logMasked("antigravity", result.accessToken);
|
|
22981
|
+
return expiresAt;
|
|
22982
|
+
}
|
|
22983
|
+
async function captureAntigravityCode(deps, state) {
|
|
22984
|
+
try {
|
|
22985
|
+
return await deps.awaitLoopback(state, void 0, void 0, {
|
|
22986
|
+
port: 51121,
|
|
22987
|
+
path: "/oauth-callback",
|
|
22988
|
+
label: "antigravity"
|
|
22989
|
+
});
|
|
22990
|
+
} catch (loopbackError) {
|
|
22991
|
+
const reason = loopbackError instanceof Error ? loopbackError.message : String(loopbackError);
|
|
22992
|
+
console.warn(`(loopback capture unavailable: ${reason})`);
|
|
22993
|
+
console.info(
|
|
22994
|
+
"Paste fallback: after authorizing, copy the failing redirect URL (or just its code parameter) here."
|
|
22995
|
+
);
|
|
22996
|
+
const pasted = (await deps.promptPaste("Paste the authorization code (or redirect URL): ")).trim();
|
|
22997
|
+
if (!pasted) throw new Error("login: no authorization code was pasted");
|
|
22998
|
+
const { code, state: pastedState } = parseAntigravityPaste(pasted);
|
|
22999
|
+
if (!code) throw new Error("login: the pasted value carried no authorization code");
|
|
23000
|
+
if (pastedState && pastedState !== state) {
|
|
23001
|
+
throw new Error("login: pasted state did not match (possible CSRF) \u2014 aborting");
|
|
23002
|
+
}
|
|
23003
|
+
return code;
|
|
23004
|
+
}
|
|
23005
|
+
}
|
|
23006
|
+
function parseAntigravityPaste(pasted) {
|
|
23007
|
+
if (pasted.includes("://")) {
|
|
23008
|
+
try {
|
|
23009
|
+
const url = new URL(pasted);
|
|
23010
|
+
const code = url.searchParams.get("code") ?? "";
|
|
23011
|
+
const state = url.searchParams.get("state") ?? void 0;
|
|
23012
|
+
return { code, ...state ? { state } : {} };
|
|
23013
|
+
} catch {
|
|
23014
|
+
}
|
|
23015
|
+
}
|
|
23016
|
+
if (/^[?]?code=/.test(pasted)) {
|
|
23017
|
+
const params = new URLSearchParams(pasted.replace(/^\?/, ""));
|
|
23018
|
+
const code = params.get("code") ?? "";
|
|
23019
|
+
const state = params.get("state") ?? void 0;
|
|
23020
|
+
return { code, ...state ? { state } : {} };
|
|
23021
|
+
}
|
|
23022
|
+
return { code: pasted };
|
|
23023
|
+
}
|
|
22108
23024
|
function isLoginProvider(value) {
|
|
22109
23025
|
return PROVIDERS2.includes(value);
|
|
22110
23026
|
}
|
|
@@ -22526,7 +23442,11 @@ var TOKEN_FIELDS2 = {
|
|
|
22526
23442
|
claude: ["accessToken", "refreshToken"],
|
|
22527
23443
|
codex: ["accessToken", "refreshToken", "idToken"],
|
|
22528
23444
|
gemini: ["accessToken", "refreshToken"],
|
|
22529
|
-
opencodego: ["apiKey"]
|
|
23445
|
+
opencodego: ["apiKey"],
|
|
23446
|
+
kimi: ["accessToken", "refreshToken"],
|
|
23447
|
+
grok: ["accessToken", "refreshToken"],
|
|
23448
|
+
copilot: ["accessToken", "refreshToken"],
|
|
23449
|
+
antigravity: ["accessToken", "refreshToken"]
|
|
22530
23450
|
};
|
|
22531
23451
|
function walkTokens(raw, fn) {
|
|
22532
23452
|
const next = { ...raw };
|
|
@@ -22810,7 +23730,7 @@ async function main() {
|
|
|
22810
23730
|
process.exitCode = 1;
|
|
22811
23731
|
}
|
|
22812
23732
|
}
|
|
22813
|
-
main().catch((
|
|
22814
|
-
console.error(
|
|
23733
|
+
main().catch((err9) => {
|
|
23734
|
+
console.error(err9 instanceof Error ? err9.message : String(err9));
|
|
22815
23735
|
process.exitCode = 1;
|
|
22816
23736
|
});
|