@omnicross/daemon 0.4.1 → 0.4.3
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 +1128 -271
- package/dist/cli.js +1076 -211
- package/dist/index.cjs +921 -228
- package/dist/index.d.cts +186 -10
- package/dist/index.d.ts +186 -10
- package/dist/index.js +889 -189
- package/package.json +6 -6
package/dist/cli.cjs
CHANGED
|
@@ -953,7 +953,11 @@ var TOKEN_FIELDS = {
|
|
|
953
953
|
claude: ["accessToken", "refreshToken"],
|
|
954
954
|
codex: ["accessToken", "refreshToken", "idToken"],
|
|
955
955
|
gemini: ["accessToken", "refreshToken"],
|
|
956
|
-
opencodego: ["apiKey"]
|
|
956
|
+
opencodego: ["apiKey"],
|
|
957
|
+
kimi: ["accessToken", "refreshToken"],
|
|
958
|
+
grok: ["accessToken", "refreshToken"],
|
|
959
|
+
copilot: ["accessToken", "refreshToken"],
|
|
960
|
+
antigravity: ["accessToken", "refreshToken"]
|
|
957
961
|
};
|
|
958
962
|
function transformTokenBlock(block, fields, fn) {
|
|
959
963
|
const next = { ...block };
|
|
@@ -1171,21 +1175,23 @@ var import_node_path36 = require("path");
|
|
|
1171
1175
|
var import_audit_types = require("@omnicross/contracts/audit-types");
|
|
1172
1176
|
var import_billing_types = require("@omnicross/contracts/billing-types");
|
|
1173
1177
|
var import_core7 = require("@omnicross/core");
|
|
1174
|
-
var
|
|
1178
|
+
var import_GeminiCodeAssistProjectResolver6 = require("@omnicross/core/auth/GeminiCodeAssistProjectResolver");
|
|
1175
1179
|
var import_ApiKeyPoolService = require("@omnicross/core/completion/ApiKeyPoolService");
|
|
1176
1180
|
var import_outbound_api10 = require("@omnicross/core/outbound-api");
|
|
1177
1181
|
var import_subscriptionRegistryPort = require("@omnicross/core/outbound-api/subscriptionRegistryPort");
|
|
1178
1182
|
var import_SubscriptionAccountHealth4 = require("@omnicross/core/pipeline/SubscriptionAccountHealth");
|
|
1179
|
-
var
|
|
1183
|
+
var import_AccountAllowanceStore11 = require("@omnicross/core/pipeline/AccountAllowanceStore");
|
|
1180
1184
|
var import_AccountAllowanceScheduling5 = require("@omnicross/core/pipeline/AccountAllowanceScheduling");
|
|
1181
|
-
var
|
|
1185
|
+
var import_upstreamFetch18 = require("@omnicross/core/pipeline/upstreamFetch");
|
|
1182
1186
|
var import_SubscriptionIdentityStore3 = require("@omnicross/core/provider-proxy/identity/SubscriptionIdentityStore");
|
|
1183
1187
|
var import_gemini_code_assist_resolver = require("@omnicross/core/ports/gemini-code-assist-resolver");
|
|
1188
|
+
var import_antigravityFailover = require("@omnicross/core/transformer/transformers/antigravityFailover");
|
|
1189
|
+
var import_openCodeGoHeaders2 = require("@omnicross/core/provider-proxy/identity/openCodeGoHeaders");
|
|
1184
1190
|
var import_provider_proxy4 = require("@omnicross/core/provider-proxy");
|
|
1185
1191
|
var import_cli_launcher2 = require("@omnicross/cli-launcher");
|
|
1186
1192
|
var import_outbound_api11 = require("@omnicross/core/outbound-api");
|
|
1187
1193
|
var import_usage2 = require("@omnicross/core/usage");
|
|
1188
|
-
var
|
|
1194
|
+
var import_subscriptions13 = require("@omnicross/subscriptions");
|
|
1189
1195
|
|
|
1190
1196
|
// src/admin/accountsCodexOAuth.ts
|
|
1191
1197
|
var import_node_crypto3 = __toESM(require("crypto"), 1);
|
|
@@ -1547,7 +1553,7 @@ function handleCopilotOAuthStatus(sessionId, deps) {
|
|
|
1547
1553
|
}
|
|
1548
1554
|
|
|
1549
1555
|
// src/allowance/AccountAllowanceService.ts
|
|
1550
|
-
var
|
|
1556
|
+
var import_AccountAllowanceStore9 = require("@omnicross/core/pipeline/AccountAllowanceStore");
|
|
1551
1557
|
var import_AccountAllowanceScheduling = require("@omnicross/core/pipeline/AccountAllowanceScheduling");
|
|
1552
1558
|
|
|
1553
1559
|
// src/allowance/ClaudeAllowanceCollector.ts
|
|
@@ -2917,9 +2923,321 @@ var GeminiAllowanceCollector = class {
|
|
|
2917
2923
|
}
|
|
2918
2924
|
};
|
|
2919
2925
|
|
|
2920
|
-
// src/allowance/
|
|
2926
|
+
// src/allowance/AntigravityAllowanceCollector.ts
|
|
2927
|
+
var import_GeminiCodeAssistProjectResolver2 = require("@omnicross/core/auth/GeminiCodeAssistProjectResolver");
|
|
2928
|
+
var import_antigravityQuotaFamily = require("@omnicross/core/pipeline/antigravityQuotaFamily");
|
|
2921
2929
|
var import_AccountAllowanceStore7 = require("@omnicross/core/pipeline/AccountAllowanceStore");
|
|
2922
2930
|
var import_upstreamFetch7 = require("@omnicross/core/pipeline/upstreamFetch");
|
|
2931
|
+
var import_antigravityIdentity = require("@omnicross/core/transformer/transformers/antigravityIdentity");
|
|
2932
|
+
var ANTIGRAVITY_ALLOWANCE_CACHE_MS = 5 * 6e4;
|
|
2933
|
+
var RETRIEVE_USER_QUOTA_SUMMARY_PATH = "/v1internal:retrieveUserQuotaSummary";
|
|
2934
|
+
var FETCH_AVAILABLE_MODELS_PATH = "/v1internal:fetchAvailableModels";
|
|
2935
|
+
var ANTIGRAVITY_DISCOVERY_DENYLIST = /* @__PURE__ */ new Set([
|
|
2936
|
+
"chat_20706",
|
|
2937
|
+
"chat_23310",
|
|
2938
|
+
"gemini-2.5-pro"
|
|
2939
|
+
]);
|
|
2940
|
+
function isRecord5(value) {
|
|
2941
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
2942
|
+
}
|
|
2943
|
+
function secondsUntil7(instant, now) {
|
|
2944
|
+
if (!instant) return void 0;
|
|
2945
|
+
return Math.max(0, Math.floor((Date.parse(instant) - now) / 1e3));
|
|
2946
|
+
}
|
|
2947
|
+
var WINDOW_LABELS = {
|
|
2948
|
+
"five-hour": "5 Hour",
|
|
2949
|
+
weekly: "Weekly",
|
|
2950
|
+
daily: "Daily"
|
|
2951
|
+
};
|
|
2952
|
+
function classifyWindowId(...sources) {
|
|
2953
|
+
for (const source of sources) {
|
|
2954
|
+
if (!source) continue;
|
|
2955
|
+
const text = source.toLowerCase();
|
|
2956
|
+
if (text.includes("week") || text.includes("7d") || /7[\s_-]*day/.test(text)) return "weekly";
|
|
2957
|
+
if (text.includes("5h") || text.includes("five hour") || /5[\s_-]*hour/.test(text)) return "five-hour";
|
|
2958
|
+
if (text.includes("day") || text.includes("daily") || text.includes("24h")) return "daily";
|
|
2959
|
+
}
|
|
2960
|
+
return void 0;
|
|
2961
|
+
}
|
|
2962
|
+
function inferWindowFromReset(resetsAt, now) {
|
|
2963
|
+
if (resetsAt !== void 0 && Date.parse(resetsAt) - now > 24 * 60 * 60 * 1e3) return "weekly";
|
|
2964
|
+
return "daily";
|
|
2965
|
+
}
|
|
2966
|
+
function clampFraction(value) {
|
|
2967
|
+
if (value === void 0 || !Number.isFinite(value)) return void 0;
|
|
2968
|
+
return Math.min(1, Math.max(0, value));
|
|
2969
|
+
}
|
|
2970
|
+
function usedPercentFromFraction(fraction) {
|
|
2971
|
+
const clamped = clampFraction(fraction);
|
|
2972
|
+
if (clamped === void 0) return null;
|
|
2973
|
+
return Math.round((1 - clamped) * 1e3) / 10;
|
|
2974
|
+
}
|
|
2975
|
+
function toResetsAt(resetTime) {
|
|
2976
|
+
if (!resetTime || !Number.isFinite(Date.parse(resetTime))) return void 0;
|
|
2977
|
+
return new Date(Date.parse(resetTime)).toISOString();
|
|
2978
|
+
}
|
|
2979
|
+
function parseAntigravityQuotaSummary(payload, now) {
|
|
2980
|
+
if (!isRecord5(payload)) return null;
|
|
2981
|
+
const groups = Array.isArray(payload["groups"]) ? payload["groups"] : [];
|
|
2982
|
+
const topBuckets = Array.isArray(payload["buckets"]) ? payload["buckets"] : [];
|
|
2983
|
+
const hasGrouped = groups.some((group) => Array.isArray(group.buckets) && group.buckets.length > 0);
|
|
2984
|
+
if (!hasGrouped && topBuckets.length === 0) return null;
|
|
2985
|
+
const windows = /* @__PURE__ */ new Map();
|
|
2986
|
+
const addBucket = (bucket, groupName) => {
|
|
2987
|
+
const families = (0, import_antigravityQuotaFamily.antigravityCounterFamiliesForBucketId)(bucket.bucketId, groupName);
|
|
2988
|
+
if (families.length === 0) return;
|
|
2989
|
+
const resetsAt = toResetsAt(bucket.resetTime);
|
|
2990
|
+
const windowId = classifyWindowId(bucket.window, bucket.displayName, bucket.bucketId) ?? (resetsAt !== void 0 ? inferWindowFromReset(resetsAt, now) : void 0);
|
|
2991
|
+
if (windowId === void 0) return;
|
|
2992
|
+
const usedPercent = usedPercentFromFraction(bucket.remainingFraction) ?? (bucket.disabled === true || bucket.resetTime ? bucket.disabled === true ? 100 : null : null);
|
|
2993
|
+
for (const family of families) {
|
|
2994
|
+
const id = `antigravity:${family}:${windowId}`;
|
|
2995
|
+
const candidate = {
|
|
2996
|
+
id,
|
|
2997
|
+
label: `${WINDOW_LABELS[windowId]} (${family})`,
|
|
2998
|
+
scope: "model-family",
|
|
2999
|
+
// The window carries the MODEL family (gemini/claude/gpt-oss) — the
|
|
3000
|
+
// scheduling gate compares it against the requested model's family.
|
|
3001
|
+
modelFamily: import_antigravityQuotaFamily.ANTIGRAVITY_COUNTER_TO_MODEL_FAMILY[family],
|
|
3002
|
+
usedPercent,
|
|
3003
|
+
...resetsAt !== void 0 ? { resetsAt } : {},
|
|
3004
|
+
remainingSeconds: secondsUntil7(resetsAt, now),
|
|
3005
|
+
state: "fresh",
|
|
3006
|
+
...bucket.disabled === true ? { disabled: true } : {}
|
|
3007
|
+
};
|
|
3008
|
+
const existing = windows.get(id);
|
|
3009
|
+
if (!existing || candidate.disabled === true || existing.disabled !== true && (candidate.usedPercent ?? -1) > (existing.usedPercent ?? -1)) {
|
|
3010
|
+
windows.set(id, candidate);
|
|
3011
|
+
}
|
|
3012
|
+
}
|
|
3013
|
+
};
|
|
3014
|
+
if (hasGrouped) {
|
|
3015
|
+
for (const group of groups) {
|
|
3016
|
+
for (const bucket of group.buckets ?? []) addBucket(bucket, group.displayName);
|
|
3017
|
+
}
|
|
3018
|
+
} else {
|
|
3019
|
+
for (const bucket of topBuckets) addBucket(bucket);
|
|
3020
|
+
}
|
|
3021
|
+
const result = [...windows.values()];
|
|
3022
|
+
return result.length > 0 ? result : null;
|
|
3023
|
+
}
|
|
3024
|
+
function legacyQuotaInfos(model) {
|
|
3025
|
+
const out = [];
|
|
3026
|
+
const source = {
|
|
3027
|
+
...model.apiProvider ? { apiProvider: model.apiProvider } : {},
|
|
3028
|
+
...model.modelProvider ? { modelProvider: model.modelProvider } : {}
|
|
3029
|
+
};
|
|
3030
|
+
const add = (value, windowDefault) => {
|
|
3031
|
+
if (!value) return;
|
|
3032
|
+
const list = Array.isArray(value) ? value : [value];
|
|
3033
|
+
for (const info of list) {
|
|
3034
|
+
out.push({ ...source, ...windowDefault ? { windowId: windowDefault } : {}, ...info });
|
|
3035
|
+
}
|
|
3036
|
+
};
|
|
3037
|
+
add(model.quotaInfo);
|
|
3038
|
+
add(model.quotaInfos);
|
|
3039
|
+
add(model.dailyQuotaInfo, "daily");
|
|
3040
|
+
add(model.dailyQuotaInfos, "daily");
|
|
3041
|
+
add(model.weeklyQuotaInfo, "weekly");
|
|
3042
|
+
add(model.weeklyQuotaInfos, "weekly");
|
|
3043
|
+
return out;
|
|
3044
|
+
}
|
|
3045
|
+
function legacyCounterFamily(info) {
|
|
3046
|
+
switch (info.modelProvider ?? info.apiProvider) {
|
|
3047
|
+
case "MODEL_PROVIDER_ANTHROPIC":
|
|
3048
|
+
case "API_PROVIDER_ANTHROPIC_VERTEX":
|
|
3049
|
+
return "anthropic";
|
|
3050
|
+
case "MODEL_PROVIDER_GOOGLE":
|
|
3051
|
+
case "API_PROVIDER_GOOGLE_GEMINI":
|
|
3052
|
+
return "google";
|
|
3053
|
+
case "MODEL_PROVIDER_OPENAI":
|
|
3054
|
+
case "API_PROVIDER_OPENAI_VERTEX":
|
|
3055
|
+
return "openai";
|
|
3056
|
+
default:
|
|
3057
|
+
return void 0;
|
|
3058
|
+
}
|
|
3059
|
+
}
|
|
3060
|
+
function parseAntigravityLegacyQuota(payload, now) {
|
|
3061
|
+
if (!isRecord5(payload)) return null;
|
|
3062
|
+
const models = payload["models"];
|
|
3063
|
+
if (!isRecord5(models)) return null;
|
|
3064
|
+
const windows = /* @__PURE__ */ new Map();
|
|
3065
|
+
for (const info of Object.values(models).flatMap(legacyQuotaInfos)) {
|
|
3066
|
+
const family = legacyCounterFamily(info);
|
|
3067
|
+
if (!family) continue;
|
|
3068
|
+
const resetsAt = toResetsAt(info.resetTime);
|
|
3069
|
+
const windowId = classifyWindowId(info.windowId, info.windowLabel) ?? (resetsAt !== void 0 ? inferWindowFromReset(resetsAt, now) : void 0);
|
|
3070
|
+
if (windowId === void 0) continue;
|
|
3071
|
+
const id = `antigravity:${family}:${windowId}`;
|
|
3072
|
+
const candidate = {
|
|
3073
|
+
id,
|
|
3074
|
+
label: `${WINDOW_LABELS[windowId]} (${family})`,
|
|
3075
|
+
scope: "model-family",
|
|
3076
|
+
modelFamily: import_antigravityQuotaFamily.ANTIGRAVITY_COUNTER_TO_MODEL_FAMILY[family],
|
|
3077
|
+
usedPercent: usedPercentFromFraction(info.remainingFraction),
|
|
3078
|
+
...resetsAt !== void 0 ? { resetsAt } : {},
|
|
3079
|
+
remainingSeconds: secondsUntil7(resetsAt, now),
|
|
3080
|
+
state: "fresh"
|
|
3081
|
+
};
|
|
3082
|
+
const existing = windows.get(id);
|
|
3083
|
+
if (!existing || (candidate.usedPercent ?? -1) > (existing.usedPercent ?? -1)) {
|
|
3084
|
+
windows.set(id, candidate);
|
|
3085
|
+
}
|
|
3086
|
+
}
|
|
3087
|
+
const result = [...windows.values()];
|
|
3088
|
+
return result.length > 0 ? result : null;
|
|
3089
|
+
}
|
|
3090
|
+
var AntigravityAllowanceCollector = class {
|
|
3091
|
+
constructor(credentials, store = (0, import_AccountAllowanceStore7.getSharedAccountAllowanceStore)(), fetchImpl = (url, init, accountId) => (0, import_upstreamFetch7.fetchUpstream)(url, init, { providerId: "antigravity", accountId, redactBodies: true }), now = Date.now) {
|
|
3092
|
+
this.credentials = credentials;
|
|
3093
|
+
this.store = store;
|
|
3094
|
+
this.fetchImpl = fetchImpl;
|
|
3095
|
+
this.now = now;
|
|
3096
|
+
}
|
|
3097
|
+
credentials;
|
|
3098
|
+
store;
|
|
3099
|
+
fetchImpl;
|
|
3100
|
+
now;
|
|
3101
|
+
inFlight = /* @__PURE__ */ new Map();
|
|
3102
|
+
async collectMany(accounts, options = {}) {
|
|
3103
|
+
const settled = await Promise.allSettled(
|
|
3104
|
+
accounts.map((account) => this.collect(account, options))
|
|
3105
|
+
);
|
|
3106
|
+
return settled.flatMap((result) => result.status === "fulfilled" ? [result.value] : []);
|
|
3107
|
+
}
|
|
3108
|
+
collect(account, options = {}) {
|
|
3109
|
+
const now = this.now();
|
|
3110
|
+
if (account.tokens.authMethod !== "oauth") {
|
|
3111
|
+
const existing = this.store.get("antigravity", account.id, now);
|
|
3112
|
+
if (existing?.windows.every((window) => window.state === "unsupported")) {
|
|
3113
|
+
return Promise.resolve(existing);
|
|
3114
|
+
}
|
|
3115
|
+
const snapshot = this.unsupportedSnapshot(account.id, now);
|
|
3116
|
+
this.store.set(snapshot);
|
|
3117
|
+
return Promise.resolve(snapshot);
|
|
3118
|
+
}
|
|
3119
|
+
const cached = this.store.get("antigravity", account.id, now);
|
|
3120
|
+
if (!options.force && cached && this.isCacheValid(cached, now, options.refreshAheadMs)) {
|
|
3121
|
+
return Promise.resolve(cached);
|
|
3122
|
+
}
|
|
3123
|
+
const running = this.inFlight.get(account.id);
|
|
3124
|
+
if (running) return running;
|
|
3125
|
+
const promise = this.fetchAccount(account.id).catch(() => this.failureSnapshot(account.id, "antigravity_usage_request_failed", this.now())).finally(() => this.inFlight.delete(account.id));
|
|
3126
|
+
this.inFlight.set(account.id, promise);
|
|
3127
|
+
return promise;
|
|
3128
|
+
}
|
|
3129
|
+
isCacheValid(snapshot, now, refreshAheadMs) {
|
|
3130
|
+
if (snapshot.windows.every((window) => window.state === "unsupported")) return true;
|
|
3131
|
+
const expiresAt = snapshot.expiresAt ? Date.parse(snapshot.expiresAt) : 0;
|
|
3132
|
+
const ahead = typeof refreshAheadMs === "number" && Number.isFinite(refreshAheadMs) ? Math.max(0, refreshAheadMs) : 0;
|
|
3133
|
+
return Number.isFinite(expiresAt) && expiresAt > now + ahead;
|
|
3134
|
+
}
|
|
3135
|
+
async fetchAccount(accountId) {
|
|
3136
|
+
let accessToken = await this.credentials.getAccessTokenForAccount("antigravity", accountId);
|
|
3137
|
+
if (!accessToken) return this.failureSnapshot(accountId, "antigravity_usage_token_unavailable", this.now());
|
|
3138
|
+
let response = await this.request(accountId, accessToken, RETRIEVE_USER_QUOTA_SUMMARY_PATH, {
|
|
3139
|
+
project: void 0
|
|
3140
|
+
});
|
|
3141
|
+
if (response.status === 401 || response.status === 403) {
|
|
3142
|
+
const refreshed = await this.credentials.refreshAccountToken("antigravity", accountId);
|
|
3143
|
+
if (!refreshed) return this.failureSnapshot(accountId, "antigravity_usage_unauthorized", this.now());
|
|
3144
|
+
accessToken = await this.credentials.getAccessTokenForAccount("antigravity", accountId);
|
|
3145
|
+
if (!accessToken) return this.failureSnapshot(accountId, "antigravity_usage_token_unavailable", this.now());
|
|
3146
|
+
response = await this.request(accountId, accessToken, RETRIEVE_USER_QUOTA_SUMMARY_PATH, {
|
|
3147
|
+
project: void 0
|
|
3148
|
+
});
|
|
3149
|
+
if (response.status === 401 || response.status === 403) {
|
|
3150
|
+
return this.failureSnapshot(accountId, "antigravity_usage_unauthorized", this.now());
|
|
3151
|
+
}
|
|
3152
|
+
}
|
|
3153
|
+
if (response.ok) {
|
|
3154
|
+
const payload = await response.json().catch(() => null);
|
|
3155
|
+
const windows = parseAntigravityQuotaSummary(payload, this.now());
|
|
3156
|
+
if (windows) {
|
|
3157
|
+
const snapshot2 = this.snapshot(accountId, windows);
|
|
3158
|
+
this.store.set(snapshot2);
|
|
3159
|
+
return snapshot2;
|
|
3160
|
+
}
|
|
3161
|
+
}
|
|
3162
|
+
const legacy = await this.request(accountId, accessToken, FETCH_AVAILABLE_MODELS_PATH, {});
|
|
3163
|
+
if (!legacy.ok) {
|
|
3164
|
+
return this.failureSnapshot(accountId, "antigravity_usage_http_error", this.now());
|
|
3165
|
+
}
|
|
3166
|
+
const legacyPayload = await legacy.json().catch(() => null);
|
|
3167
|
+
const legacyWindows = parseAntigravityLegacyQuota(legacyPayload, this.now());
|
|
3168
|
+
if (!legacyWindows) {
|
|
3169
|
+
return this.failureSnapshot(accountId, "antigravity_usage_invalid_response", this.now());
|
|
3170
|
+
}
|
|
3171
|
+
const snapshot = this.snapshot(accountId, legacyWindows);
|
|
3172
|
+
this.store.set(snapshot);
|
|
3173
|
+
return snapshot;
|
|
3174
|
+
}
|
|
3175
|
+
/** One upstream round-trip with the antigravity/hub masquerade UA. */
|
|
3176
|
+
request(accountId, accessToken, path2, body) {
|
|
3177
|
+
return this.fetchImpl(`${import_GeminiCodeAssistProjectResolver2.ANTIGRAVITY_CODE_ASSIST_ENDPOINT}${path2}`, {
|
|
3178
|
+
method: "POST",
|
|
3179
|
+
headers: {
|
|
3180
|
+
Authorization: `Bearer ${accessToken}`,
|
|
3181
|
+
Accept: "application/json",
|
|
3182
|
+
"Content-Type": "application/json",
|
|
3183
|
+
"User-Agent": (0, import_antigravityIdentity.getAntigravityUserAgent)()
|
|
3184
|
+
},
|
|
3185
|
+
body: JSON.stringify(body),
|
|
3186
|
+
signal: AbortSignal.timeout(15e3)
|
|
3187
|
+
}, accountId);
|
|
3188
|
+
}
|
|
3189
|
+
snapshot(accountId, windows, now = this.now()) {
|
|
3190
|
+
return {
|
|
3191
|
+
providerId: "antigravity",
|
|
3192
|
+
accountId,
|
|
3193
|
+
source: "oauth-usage-api",
|
|
3194
|
+
observedAt: new Date(now).toISOString(),
|
|
3195
|
+
expiresAt: new Date(now + ANTIGRAVITY_ALLOWANCE_CACHE_MS).toISOString(),
|
|
3196
|
+
windows
|
|
3197
|
+
};
|
|
3198
|
+
}
|
|
3199
|
+
failureSnapshot(accountId, code, now) {
|
|
3200
|
+
const existing = this.store.get("antigravity", accountId, now);
|
|
3201
|
+
const snapshot = existing ? {
|
|
3202
|
+
...existing,
|
|
3203
|
+
expiresAt: new Date(now + ANTIGRAVITY_ALLOWANCE_CACHE_MS).toISOString(),
|
|
3204
|
+
windows: existing.windows.map((window) => ({
|
|
3205
|
+
...window,
|
|
3206
|
+
state: window.state === "unsupported" ? "unsupported" : window.usedPercent !== null || window.resetsAt || window.disabled ? "stale" : "unavailable"
|
|
3207
|
+
})),
|
|
3208
|
+
lastErrorCode: code
|
|
3209
|
+
} : {
|
|
3210
|
+
providerId: "antigravity",
|
|
3211
|
+
accountId,
|
|
3212
|
+
source: "oauth-usage-api",
|
|
3213
|
+
observedAt: new Date(now).toISOString(),
|
|
3214
|
+
expiresAt: new Date(now + ANTIGRAVITY_ALLOWANCE_CACHE_MS).toISOString(),
|
|
3215
|
+
windows: [
|
|
3216
|
+
{ id: "antigravity-quota", label: "Antigravity quota", scope: "all", usedPercent: null, state: "unavailable" }
|
|
3217
|
+
],
|
|
3218
|
+
lastErrorCode: code
|
|
3219
|
+
};
|
|
3220
|
+
this.store.set(snapshot);
|
|
3221
|
+
return snapshot;
|
|
3222
|
+
}
|
|
3223
|
+
unsupportedSnapshot(accountId, now) {
|
|
3224
|
+
return {
|
|
3225
|
+
providerId: "antigravity",
|
|
3226
|
+
accountId,
|
|
3227
|
+
source: "oauth-usage-api",
|
|
3228
|
+
observedAt: new Date(now).toISOString(),
|
|
3229
|
+
windows: [
|
|
3230
|
+
{ id: "antigravity-quota", label: "Antigravity quota", scope: "all", usedPercent: null, state: "unsupported" }
|
|
3231
|
+
],
|
|
3232
|
+
lastErrorCode: "antigravity_usage_unsupported_auth"
|
|
3233
|
+
};
|
|
3234
|
+
}
|
|
3235
|
+
};
|
|
3236
|
+
|
|
3237
|
+
// src/allowance/OpenCodeGoAllowanceCollector.ts
|
|
3238
|
+
var import_AccountAllowanceStore8 = require("@omnicross/core/pipeline/AccountAllowanceStore");
|
|
3239
|
+
var import_upstreamFetch8 = require("@omnicross/core/pipeline/upstreamFetch");
|
|
3240
|
+
var import_openCodeGoHeaders = require("@omnicross/core/provider-proxy/identity/openCodeGoHeaders");
|
|
2923
3241
|
var import_subscriptions7 = require("@omnicross/subscriptions");
|
|
2924
3242
|
var OPENCODEGO_ALLOWANCE_CACHE_MS = 5 * 6e4;
|
|
2925
3243
|
var OPENCODEGO_DEFAULT_GO_BASE = "https://opencode.ai/zen/go";
|
|
@@ -2933,7 +3251,7 @@ function isoInstant2(value) {
|
|
|
2933
3251
|
const time = Date.parse(value);
|
|
2934
3252
|
return Number.isFinite(time) ? new Date(time).toISOString() : void 0;
|
|
2935
3253
|
}
|
|
2936
|
-
function
|
|
3254
|
+
function secondsUntil8(instant, now) {
|
|
2937
3255
|
if (!instant) return void 0;
|
|
2938
3256
|
return Math.max(0, Math.floor((Date.parse(instant) - now) / 1e3));
|
|
2939
3257
|
}
|
|
@@ -2948,12 +3266,12 @@ function windowFromPayload3(id, label, minutes, payload, now) {
|
|
|
2948
3266
|
usedPercent,
|
|
2949
3267
|
windowMinutes: minutes,
|
|
2950
3268
|
...resetsAt !== void 0 ? { resetsAt } : {},
|
|
2951
|
-
remainingSeconds:
|
|
3269
|
+
remainingSeconds: secondsUntil8(resetsAt, now),
|
|
2952
3270
|
state: usedPercent !== null || resetsAt ? "fresh" : "unavailable"
|
|
2953
3271
|
};
|
|
2954
3272
|
}
|
|
2955
3273
|
var OpenCodeGoAllowanceCollector = class {
|
|
2956
|
-
constructor(credentials, store = (0,
|
|
3274
|
+
constructor(credentials, store = (0, import_AccountAllowanceStore8.getSharedAccountAllowanceStore)(), fetchImpl = (url, init, accountId) => (0, import_upstreamFetch8.fetchUpstream)(url, init, { providerId: "opencodego", accountId, redactBodies: true }), now = Date.now) {
|
|
2957
3275
|
this.credentials = credentials;
|
|
2958
3276
|
this.store = store;
|
|
2959
3277
|
this.fetchImpl = fetchImpl;
|
|
@@ -2986,7 +3304,14 @@ var OpenCodeGoAllowanceCollector = class {
|
|
|
2986
3304
|
const base = account.tokens.baseUrl ? (0, import_subscriptions7.normalizeOpenCodeGoBaseUrl)(account.tokens.baseUrl) : OPENCODEGO_DEFAULT_GO_BASE;
|
|
2987
3305
|
const response = await this.fetchImpl(`${base}/v1/usage`, {
|
|
2988
3306
|
method: "GET",
|
|
2989
|
-
|
|
3307
|
+
// opencodego-egress-identity: the background poll identifies itself with
|
|
3308
|
+
// the same configured/default UA the relay carries (no session header —
|
|
3309
|
+
// a poll has no conversation).
|
|
3310
|
+
headers: {
|
|
3311
|
+
Authorization: `Bearer ${apiKey}`,
|
|
3312
|
+
Accept: "application/json",
|
|
3313
|
+
"User-Agent": (0, import_openCodeGoHeaders.getOpenCodeGoUserAgent)()
|
|
3314
|
+
},
|
|
2990
3315
|
signal: AbortSignal.timeout(15e3)
|
|
2991
3316
|
}, account.id);
|
|
2992
3317
|
if (response.status === 401 || response.status === 403) {
|
|
@@ -3058,7 +3383,7 @@ function codexUnavailable(accountId, now) {
|
|
|
3058
3383
|
};
|
|
3059
3384
|
}
|
|
3060
3385
|
var AccountAllowanceService = class {
|
|
3061
|
-
constructor(credentials, store = (0,
|
|
3386
|
+
constructor(credentials, store = (0, import_AccountAllowanceStore9.getSharedAccountAllowanceStore)(), collector, codexCollector, kimiCollector, opencodegoCollector, grokCollector, copilotCollector, geminiCollector, antigravityCollector, now = Date.now) {
|
|
3062
3387
|
this.credentials = credentials;
|
|
3063
3388
|
this.store = store;
|
|
3064
3389
|
this.now = now;
|
|
@@ -3069,6 +3394,7 @@ var AccountAllowanceService = class {
|
|
|
3069
3394
|
this.grokCollector = grokCollector ?? new GrokAllowanceCollector(credentials, store);
|
|
3070
3395
|
this.copilotCollector = copilotCollector ?? new CopilotAllowanceCollector(credentials, store);
|
|
3071
3396
|
this.geminiCollector = geminiCollector ?? new GeminiAllowanceCollector(credentials, store);
|
|
3397
|
+
this.antigravityCollector = antigravityCollector ?? new AntigravityAllowanceCollector(credentials, store);
|
|
3072
3398
|
}
|
|
3073
3399
|
credentials;
|
|
3074
3400
|
store;
|
|
@@ -3080,6 +3406,7 @@ var AccountAllowanceService = class {
|
|
|
3080
3406
|
copilotCollector;
|
|
3081
3407
|
opencodegoCollector;
|
|
3082
3408
|
geminiCollector;
|
|
3409
|
+
antigravityCollector;
|
|
3083
3410
|
/**
|
|
3084
3411
|
* Read all/filtered snapshots. Claude's and Codex's five-minute caches are
|
|
3085
3412
|
* refreshed lazily on read (Codex polls `/backend-api/wham/usage`; the
|
|
@@ -3128,6 +3455,11 @@ var AccountAllowanceService = class {
|
|
|
3128
3455
|
(account) => !filter.accountId || account.id === filter.accountId
|
|
3129
3456
|
);
|
|
3130
3457
|
if (wantsGemini) await this.geminiCollector.collectMany(geminiAccounts);
|
|
3458
|
+
const wantsAntigravity = !filter.providerId || filter.providerId === "antigravity";
|
|
3459
|
+
const antigravityAccounts = (config.antigravityAccounts ?? []).filter(
|
|
3460
|
+
(account) => !filter.accountId || account.id === filter.accountId
|
|
3461
|
+
);
|
|
3462
|
+
if (wantsAntigravity) await this.antigravityCollector.collectMany(antigravityAccounts);
|
|
3131
3463
|
const known = /* @__PURE__ */ new Set();
|
|
3132
3464
|
if (wantsClaude) for (const account of claudeAccounts) known.add(`claude\0${account.id}`);
|
|
3133
3465
|
if (wantsCodex) for (const account of codexAccounts) known.add(`codex\0${account.id}`);
|
|
@@ -3136,6 +3468,7 @@ var AccountAllowanceService = class {
|
|
|
3136
3468
|
if (wantsGrok) for (const account of grokAccounts) known.add(`grok\0${account.id}`);
|
|
3137
3469
|
if (wantsCopilot) for (const account of copilotAccounts) known.add(`copilot\0${account.id}`);
|
|
3138
3470
|
if (wantsGemini) for (const account of geminiAccounts) known.add(`gemini\0${account.id}`);
|
|
3471
|
+
if (wantsAntigravity) for (const account of antigravityAccounts) known.add(`antigravity\0${account.id}`);
|
|
3139
3472
|
return this.store.list(filter).filter((snapshot) => known.has(`${snapshot.providerId}\0${snapshot.accountId}`));
|
|
3140
3473
|
}
|
|
3141
3474
|
knownAccounts(config) {
|
|
@@ -3146,7 +3479,8 @@ var AccountAllowanceService = class {
|
|
|
3146
3479
|
...(config.opencodegoAccounts ?? []).map((account) => ({ providerId: "opencodego", accountId: account.id })),
|
|
3147
3480
|
...(config.grokAccounts ?? []).map((account) => ({ providerId: "grok", accountId: account.id })),
|
|
3148
3481
|
...(config.copilotAccounts ?? []).map((account) => ({ providerId: "copilot", accountId: account.id })),
|
|
3149
|
-
...(config.geminiAccounts ?? []).map((account) => ({ providerId: "gemini", accountId: account.id }))
|
|
3482
|
+
...(config.geminiAccounts ?? []).map((account) => ({ providerId: "gemini", accountId: account.id })),
|
|
3483
|
+
...(config.antigravityAccounts ?? []).map((account) => ({ providerId: "antigravity", accountId: account.id }))
|
|
3150
3484
|
];
|
|
3151
3485
|
}
|
|
3152
3486
|
/** Force-refresh Claude usage for one account or every stored Claude account. */
|
|
@@ -3216,6 +3550,15 @@ var AccountAllowanceService = class {
|
|
|
3216
3550
|
);
|
|
3217
3551
|
return this.geminiCollector.collectMany(accounts, { force: true });
|
|
3218
3552
|
}
|
|
3553
|
+
/** Force-refresh Antigravity usage (quotaSummary dual buckets) for one/all accounts. */
|
|
3554
|
+
async refreshAntigravity(accountId) {
|
|
3555
|
+
const config = await this.credentials.getFullConfig();
|
|
3556
|
+
this.store.pruneToKnownAccounts(this.knownAccounts(config));
|
|
3557
|
+
const accounts = (config.antigravityAccounts ?? []).filter(
|
|
3558
|
+
(account) => !accountId || account.id === accountId
|
|
3559
|
+
);
|
|
3560
|
+
return this.antigravityCollector.collectMany(accounts, { force: true });
|
|
3561
|
+
}
|
|
3219
3562
|
/**
|
|
3220
3563
|
* Keep Claude + Codex + Kimi snapshots warm for allowance-aware routing. All
|
|
3221
3564
|
* collectors preserve their cache + per-account in-flight coalescing; a tick
|
|
@@ -3233,6 +3576,7 @@ var AccountAllowanceService = class {
|
|
|
3233
3576
|
await this.grokCollector.collectMany(config.grokAccounts ?? [], { refreshAheadMs });
|
|
3234
3577
|
await this.copilotCollector.collectMany(config.copilotAccounts ?? [], { refreshAheadMs });
|
|
3235
3578
|
await this.geminiCollector.collectMany(config.geminiAccounts ?? [], { refreshAheadMs });
|
|
3579
|
+
await this.antigravityCollector.collectMany(config.antigravityAccounts ?? [], { refreshAheadMs });
|
|
3236
3580
|
}
|
|
3237
3581
|
/** Remove a cache row as soon as an account is deleted by the admin path. */
|
|
3238
3582
|
removeAccountSnapshot(providerId, accountId) {
|
|
@@ -3327,7 +3671,7 @@ var ClaudeAllowanceRefreshScheduler = class {
|
|
|
3327
3671
|
var import_node_crypto4 = require("crypto");
|
|
3328
3672
|
var import_node_fs6 = require("fs");
|
|
3329
3673
|
var import_node_path6 = require("path");
|
|
3330
|
-
var
|
|
3674
|
+
var import_AccountAllowanceStore10 = require("@omnicross/core/pipeline/AccountAllowanceStore");
|
|
3331
3675
|
var ACCOUNT_ALLOWANCE_CACHE_VERSION = 1;
|
|
3332
3676
|
var MAX_PERSISTED_ALLOWANCE_SNAPSHOTS = 256;
|
|
3333
3677
|
var MAX_ALLOWANCE_CACHE_BYTES = 1e6;
|
|
@@ -3356,7 +3700,7 @@ var JsonAccountAllowancePersistence = class {
|
|
|
3356
3700
|
save(snapshots) {
|
|
3357
3701
|
const rows = [];
|
|
3358
3702
|
for (const snapshot of snapshots) {
|
|
3359
|
-
const normalized2 = (0,
|
|
3703
|
+
const normalized2 = (0, import_AccountAllowanceStore10.normalizeAccountAllowanceSnapshot)(snapshot);
|
|
3360
3704
|
if (!normalized2) continue;
|
|
3361
3705
|
rows.push(normalized2);
|
|
3362
3706
|
if (rows.length >= MAX_PERSISTED_ALLOWANCE_SNAPSHOTS) break;
|
|
@@ -3632,7 +3976,7 @@ var import_outbound_api5 = require("@omnicross/core/outbound-api");
|
|
|
3632
3976
|
var import_image_generation_types = require("@omnicross/contracts/image-generation-types");
|
|
3633
3977
|
var import_AccountAllowanceScheduling2 = require("@omnicross/core/pipeline/AccountAllowanceScheduling");
|
|
3634
3978
|
var import_SubscriptionAccountHealth = require("@omnicross/core/pipeline/SubscriptionAccountHealth");
|
|
3635
|
-
var
|
|
3979
|
+
var import_upstreamFetch12 = require("@omnicross/core/pipeline/upstreamFetch");
|
|
3636
3980
|
var import_core3 = require("@omnicross/core");
|
|
3637
3981
|
|
|
3638
3982
|
// src/image-generation/imagesConfigValidation.ts
|
|
@@ -3949,6 +4293,19 @@ function resolveAdminConfig(admin) {
|
|
|
3949
4293
|
token: typeof admin?.token === "string" && admin.token.length > 0 ? admin.token : void 0
|
|
3950
4294
|
};
|
|
3951
4295
|
}
|
|
4296
|
+
function validateAntigravity(raw) {
|
|
4297
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return void 0;
|
|
4298
|
+
const a = raw;
|
|
4299
|
+
if (typeof a["sandboxFailover"] !== "boolean") return void 0;
|
|
4300
|
+
return { sandboxFailover: a["sandboxFailover"] };
|
|
4301
|
+
}
|
|
4302
|
+
function validateOpenCodeGo(raw) {
|
|
4303
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return void 0;
|
|
4304
|
+
const o = raw;
|
|
4305
|
+
const ua = o["userAgent"];
|
|
4306
|
+
if (typeof ua !== "string" || ua.trim().length === 0) return void 0;
|
|
4307
|
+
return { userAgent: ua.trim() };
|
|
4308
|
+
}
|
|
3952
4309
|
function validateUsage(raw) {
|
|
3953
4310
|
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return void 0;
|
|
3954
4311
|
const u = raw;
|
|
@@ -4242,7 +4599,9 @@ function validateConfig(raw) {
|
|
|
4242
4599
|
const admin = validateAdmin(obj["admin"]);
|
|
4243
4600
|
const logging = validateLogging(obj["logging"]);
|
|
4244
4601
|
const usage = validateUsage(obj["usage"]);
|
|
4245
|
-
|
|
4602
|
+
const antigravity = validateAntigravity(obj["antigravity"]);
|
|
4603
|
+
const opencodego = validateOpenCodeGo(obj["opencodego"]);
|
|
4604
|
+
return { providers, server, admin, logging, usage, antigravity, opencodego };
|
|
4246
4605
|
}
|
|
4247
4606
|
var secretBox = null;
|
|
4248
4607
|
function setSecretBox(box) {
|
|
@@ -5286,11 +5645,11 @@ function preserveOutboundProxySecrets(incoming, current) {
|
|
|
5286
5645
|
}
|
|
5287
5646
|
|
|
5288
5647
|
// src/proxy/upstreamProxyResolver.ts
|
|
5289
|
-
var
|
|
5648
|
+
var import_upstreamFetch9 = require("@omnicross/core/pipeline/upstreamFetch");
|
|
5290
5649
|
var serverProxy;
|
|
5291
5650
|
function setServerProxyConfig(proxy) {
|
|
5292
5651
|
serverProxy = proxy;
|
|
5293
|
-
(0,
|
|
5652
|
+
(0, import_upstreamFetch9.bumpUpstreamProxyGeneration)();
|
|
5294
5653
|
}
|
|
5295
5654
|
function getServerProxyConfig() {
|
|
5296
5655
|
return serverProxy;
|
|
@@ -5357,8 +5716,169 @@ function createUpstreamProxyResolver(src = {}) {
|
|
|
5357
5716
|
};
|
|
5358
5717
|
}
|
|
5359
5718
|
|
|
5360
|
-
// src/admin/
|
|
5719
|
+
// src/admin/accountsAntigravityOAuth.ts
|
|
5720
|
+
var import_GeminiCodeAssistProjectResolver3 = require("@omnicross/core/auth/GeminiCodeAssistProjectResolver");
|
|
5361
5721
|
var import_subscriptions8 = require("@omnicross/subscriptions");
|
|
5722
|
+
function err5(status, message) {
|
|
5723
|
+
return { status, body: { error: { type: "admin_api_error", message } } };
|
|
5724
|
+
}
|
|
5725
|
+
var DEFAULT_ANTIGRAVITY_OAUTH_TTL_MS = 10 * 6e4;
|
|
5726
|
+
function handleAntigravityOAuthStart(deps) {
|
|
5727
|
+
if (deps.antigravitySessions.isBusy()) {
|
|
5728
|
+
return err5(
|
|
5729
|
+
409,
|
|
5730
|
+
"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"
|
|
5731
|
+
);
|
|
5732
|
+
}
|
|
5733
|
+
const { authUrl, state } = import_subscriptions8.antigravityOAuth.generateAuthParams();
|
|
5734
|
+
const { sessionId, signal } = deps.antigravitySessions.begin();
|
|
5735
|
+
void runAntigravityLoopback(sessionId, state, signal, deps);
|
|
5736
|
+
return { status: 200, body: { authUrl, sessionId } };
|
|
5737
|
+
}
|
|
5738
|
+
async function runAntigravityLoopback(sessionId, state, signal, deps) {
|
|
5739
|
+
const isPending = () => !signal.aborted && deps.antigravitySessions.get(sessionId)?.status === "pending";
|
|
5740
|
+
try {
|
|
5741
|
+
const code = await deps.antigravityAwaitLoopback(state, void 0, signal);
|
|
5742
|
+
if (!isPending()) return;
|
|
5743
|
+
const exchangeFetch = deps.oauthExchangeFetch("antigravity");
|
|
5744
|
+
const result = await import_subscriptions8.antigravityOAuth.exchangeCodeForTokens(code, exchangeFetch);
|
|
5745
|
+
if (!isPending()) return;
|
|
5746
|
+
const expiresAt = new Date(Date.now() + result.expiresIn * 1e3).toISOString();
|
|
5747
|
+
const email = await import_subscriptions8.antigravityOAuth.fetchUserEmail(result.accessToken, exchangeFetch);
|
|
5748
|
+
if (!isPending()) return;
|
|
5749
|
+
const projectId = await (0, import_GeminiCodeAssistProjectResolver3.getAntigravityProjectResolver)().resolveProject(result.accessToken);
|
|
5750
|
+
if (!isPending()) return;
|
|
5751
|
+
const block = {
|
|
5752
|
+
authMethod: "oauth",
|
|
5753
|
+
status: "authorized",
|
|
5754
|
+
accessToken: result.accessToken,
|
|
5755
|
+
refreshToken: result.refreshToken,
|
|
5756
|
+
expiresAt,
|
|
5757
|
+
...email ? { email } : {},
|
|
5758
|
+
...projectId ? { projectId } : {},
|
|
5759
|
+
lastRefreshedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
5760
|
+
};
|
|
5761
|
+
await deps.subscriptionAccountAppender.appendProviderAccount("antigravity", block);
|
|
5762
|
+
if (isPending()) deps.antigravitySessions.settle(sessionId, "done");
|
|
5763
|
+
} catch (e) {
|
|
5764
|
+
if (!isPending()) return;
|
|
5765
|
+
const reason = e instanceof Error ? e.message : "antigravity sign-in failed";
|
|
5766
|
+
deps.antigravitySessions.settle(sessionId, "error", reason);
|
|
5767
|
+
}
|
|
5768
|
+
}
|
|
5769
|
+
function handleAntigravityOAuthCancel(sessionId, deps) {
|
|
5770
|
+
if (!deps.antigravitySessions.cancel(sessionId)) {
|
|
5771
|
+
return err5(404, "unknown or expired antigravity sign-in session");
|
|
5772
|
+
}
|
|
5773
|
+
return { status: 200, body: { ok: true } };
|
|
5774
|
+
}
|
|
5775
|
+
function handleAntigravityOAuthStatus(sessionId, deps) {
|
|
5776
|
+
const s = deps.antigravitySessions.get(sessionId);
|
|
5777
|
+
if (!s) return err5(404, "unknown or expired antigravity sign-in session");
|
|
5778
|
+
return { status: 200, body: { state: s.status, ...s.error ? { message: s.error } : {} } };
|
|
5779
|
+
}
|
|
5780
|
+
|
|
5781
|
+
// src/allowance/AntigravityModelDiscovery.ts
|
|
5782
|
+
var import_canonical_models = require("@omnicross/contracts/canonical-models");
|
|
5783
|
+
var import_subscription_model_catalog = require("@omnicross/contracts/subscription-model-catalog");
|
|
5784
|
+
var import_GeminiCodeAssistProjectResolver4 = require("@omnicross/core/auth/GeminiCodeAssistProjectResolver");
|
|
5785
|
+
var import_upstreamFetch10 = require("@omnicross/core/pipeline/upstreamFetch");
|
|
5786
|
+
var import_antigravityIdentity2 = require("@omnicross/core/transformer/transformers/antigravityIdentity");
|
|
5787
|
+
function isRecord6(value) {
|
|
5788
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
5789
|
+
}
|
|
5790
|
+
function optionalString(value) {
|
|
5791
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
5792
|
+
}
|
|
5793
|
+
function optionalNumber(value) {
|
|
5794
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : void 0;
|
|
5795
|
+
}
|
|
5796
|
+
function optionalBoolean(value) {
|
|
5797
|
+
return typeof value === "boolean" ? value : void 0;
|
|
5798
|
+
}
|
|
5799
|
+
function parseAntigravityAvailableModels(payload) {
|
|
5800
|
+
if (!isRecord6(payload)) return [];
|
|
5801
|
+
const models = payload["models"];
|
|
5802
|
+
if (!isRecord6(models)) return [];
|
|
5803
|
+
const out = [];
|
|
5804
|
+
for (const [id, raw] of Object.entries(models)) {
|
|
5805
|
+
if (ANTIGRAVITY_DISCOVERY_DENYLIST.has(id)) continue;
|
|
5806
|
+
if (!isRecord6(raw)) continue;
|
|
5807
|
+
if (raw["isInternal"] === true) continue;
|
|
5808
|
+
out.push({
|
|
5809
|
+
id,
|
|
5810
|
+
...optionalString(raw["displayName"]) ? { displayName: optionalString(raw["displayName"]) } : {},
|
|
5811
|
+
...optionalBoolean(raw["supportsImages"]) !== void 0 ? { supportsImages: optionalBoolean(raw["supportsImages"]) } : {},
|
|
5812
|
+
...optionalBoolean(raw["supportsThinking"]) !== void 0 ? { supportsThinking: optionalBoolean(raw["supportsThinking"]) } : {},
|
|
5813
|
+
...optionalNumber(raw["thinkingBudget"]) !== void 0 ? { thinkingBudget: optionalNumber(raw["thinkingBudget"]) } : {},
|
|
5814
|
+
...optionalNumber(raw["maxTokens"]) !== void 0 ? { maxTokens: optionalNumber(raw["maxTokens"]) } : {},
|
|
5815
|
+
...optionalNumber(raw["maxOutputTokens"]) !== void 0 ? { maxOutputTokens: optionalNumber(raw["maxOutputTokens"]) } : {}
|
|
5816
|
+
});
|
|
5817
|
+
}
|
|
5818
|
+
out.sort((a, b) => a.id.localeCompare(b.id));
|
|
5819
|
+
return out;
|
|
5820
|
+
}
|
|
5821
|
+
function mergeAntigravityCatalog(discovered, log = (line) => console.warn(line), staticIds = import_subscription_model_catalog.SUBSCRIPTION_MODEL_CATALOG.antigravity) {
|
|
5822
|
+
const entries = staticIds.map((id) => {
|
|
5823
|
+
const capabilities = (0, import_canonical_models.lookupCanonicalCapabilities)(id);
|
|
5824
|
+
return {
|
|
5825
|
+
id,
|
|
5826
|
+
origin: "static",
|
|
5827
|
+
displayName: id,
|
|
5828
|
+
...capabilities?.vision !== void 0 ? { supportsImages: capabilities.vision } : {},
|
|
5829
|
+
...capabilities?.reasoning !== void 0 ? { supportsThinking: capabilities.reasoning } : {},
|
|
5830
|
+
...capabilities?.thinkingTokenLimit ? { thinkingBudget: capabilities.thinkingTokenLimit.max } : {},
|
|
5831
|
+
// Discovery calls the context window maxTokens, not the output ceiling.
|
|
5832
|
+
...capabilities?.contextLength !== void 0 ? { maxTokens: capabilities.contextLength } : {},
|
|
5833
|
+
...capabilities?.maxTokens !== void 0 ? { maxOutputTokens: capabilities.maxTokens } : {}
|
|
5834
|
+
};
|
|
5835
|
+
});
|
|
5836
|
+
const staticSet = new Set(staticIds);
|
|
5837
|
+
for (const model of discovered) {
|
|
5838
|
+
if (staticSet.has(model.id)) {
|
|
5839
|
+
log(
|
|
5840
|
+
`[AntigravityModelDiscovery] dynamic model '${model.id}' conflicts with the static catalog \u2014 static entry kept`
|
|
5841
|
+
);
|
|
5842
|
+
continue;
|
|
5843
|
+
}
|
|
5844
|
+
entries.push({ ...model, origin: "discovered" });
|
|
5845
|
+
}
|
|
5846
|
+
return entries;
|
|
5847
|
+
}
|
|
5848
|
+
async function fetchAntigravityAvailableModels(accessToken, fetchImpl = (url, init) => (0, import_upstreamFetch10.fetchUpstream)(url, init, { providerId: "antigravity", redactBodies: true })) {
|
|
5849
|
+
let response;
|
|
5850
|
+
try {
|
|
5851
|
+
response = await fetchImpl(`${import_GeminiCodeAssistProjectResolver4.ANTIGRAVITY_CODE_ASSIST_ENDPOINT}/v1internal:fetchAvailableModels`, {
|
|
5852
|
+
method: "POST",
|
|
5853
|
+
headers: {
|
|
5854
|
+
Authorization: `Bearer ${accessToken}`,
|
|
5855
|
+
Accept: "application/json",
|
|
5856
|
+
"Content-Type": "application/json",
|
|
5857
|
+
"User-Agent": (0, import_antigravityIdentity2.getAntigravityUserAgent)()
|
|
5858
|
+
},
|
|
5859
|
+
body: JSON.stringify({}),
|
|
5860
|
+
signal: AbortSignal.timeout(15e3)
|
|
5861
|
+
});
|
|
5862
|
+
} catch {
|
|
5863
|
+
return null;
|
|
5864
|
+
}
|
|
5865
|
+
if (!response.ok) return null;
|
|
5866
|
+
const payload = await response.json().catch(() => null);
|
|
5867
|
+
if (!isRecord6(payload) || !isRecord6(payload["models"])) return null;
|
|
5868
|
+
return parseAntigravityAvailableModels(payload);
|
|
5869
|
+
}
|
|
5870
|
+
async function handleAntigravityModelsRoute(deps) {
|
|
5871
|
+
const accessToken = await deps.resolveAntigravityAccessToken().catch(() => null);
|
|
5872
|
+
const discovered = accessToken ? await fetchAntigravityAvailableModels(accessToken, deps.fetchImpl) : null;
|
|
5873
|
+
const models = mergeAntigravityCatalog(discovered ?? []);
|
|
5874
|
+
return {
|
|
5875
|
+
status: 200,
|
|
5876
|
+
body: { models, discovered: discovered !== null }
|
|
5877
|
+
};
|
|
5878
|
+
}
|
|
5879
|
+
|
|
5880
|
+
// src/admin/accountsOAuth.ts
|
|
5881
|
+
var import_subscriptions9 = require("@omnicross/subscriptions");
|
|
5362
5882
|
|
|
5363
5883
|
// src/admin/accountsWrite.ts
|
|
5364
5884
|
var VALID_PROVIDER_IDS = [
|
|
@@ -5368,7 +5888,8 @@ var VALID_PROVIDER_IDS = [
|
|
|
5368
5888
|
"opencodego",
|
|
5369
5889
|
"kimi",
|
|
5370
5890
|
"grok",
|
|
5371
|
-
"copilot"
|
|
5891
|
+
"copilot",
|
|
5892
|
+
"antigravity"
|
|
5372
5893
|
];
|
|
5373
5894
|
function asSubscriptionProviderId(id) {
|
|
5374
5895
|
return VALID_PROVIDER_IDS.includes(id) ? id : null;
|
|
@@ -5550,7 +6071,7 @@ function validateCopilot(body) {
|
|
|
5550
6071
|
]);
|
|
5551
6072
|
return out;
|
|
5552
6073
|
}
|
|
5553
|
-
function
|
|
6074
|
+
function validateOpenCodeGo2(body) {
|
|
5554
6075
|
const authMethod = str(body["authMethod"]);
|
|
5555
6076
|
const status = str(body["status"]);
|
|
5556
6077
|
if (authMethod !== "manual") return null;
|
|
@@ -5584,7 +6105,7 @@ function validateTokenBody(providerId, body) {
|
|
|
5584
6105
|
case "gemini":
|
|
5585
6106
|
return validateGemini(body);
|
|
5586
6107
|
case "opencodego":
|
|
5587
|
-
return
|
|
6108
|
+
return validateOpenCodeGo2(body);
|
|
5588
6109
|
case "kimi":
|
|
5589
6110
|
return validateKimi(body);
|
|
5590
6111
|
case "grok":
|
|
@@ -5620,37 +6141,37 @@ async function statusEntryFor(reader, providerId) {
|
|
|
5620
6141
|
|
|
5621
6142
|
// src/admin/accountsOAuth.ts
|
|
5622
6143
|
var OAUTH_HTTP_PROVIDERS = /* @__PURE__ */ new Set(["claude", "gemini"]);
|
|
5623
|
-
function
|
|
6144
|
+
function err6(status, message) {
|
|
5624
6145
|
return { status, body: { error: { type: "admin_api_error", message } } };
|
|
5625
6146
|
}
|
|
5626
6147
|
function handleOAuthStart(providerId, deps) {
|
|
5627
6148
|
if (!OAUTH_HTTP_PROVIDERS.has(providerId)) {
|
|
5628
|
-
return
|
|
6149
|
+
return err6(400, `oauth not available for provider '${providerId}'`);
|
|
5629
6150
|
}
|
|
5630
|
-
const flow = providerId === "claude" ?
|
|
6151
|
+
const flow = providerId === "claude" ? import_subscriptions9.claudeOAuth : import_subscriptions9.geminiOAuth;
|
|
5631
6152
|
const { authUrl, codeVerifier, state } = flow.generateAuthParams();
|
|
5632
6153
|
const sessionId = deps.oauthSessions.put({ providerId, codeVerifier, state });
|
|
5633
6154
|
return { status: 200, body: { authUrl, sessionId } };
|
|
5634
6155
|
}
|
|
5635
6156
|
async function handleOAuthComplete(providerId, body, deps) {
|
|
5636
6157
|
if (!OAUTH_HTTP_PROVIDERS.has(providerId)) {
|
|
5637
|
-
return
|
|
6158
|
+
return err6(400, `oauth not available for provider '${providerId}'`);
|
|
5638
6159
|
}
|
|
5639
6160
|
const sessionId = typeof body["sessionId"] === "string" ? body["sessionId"] : "";
|
|
5640
6161
|
const rawCode = typeof body["code"] === "string" ? body["code"] : "";
|
|
5641
|
-
if (!sessionId) return
|
|
5642
|
-
if (!rawCode) return
|
|
6162
|
+
if (!sessionId) return err6(400, "oauth complete requires { sessionId }");
|
|
6163
|
+
if (!rawCode) return err6(400, "oauth complete requires { code }");
|
|
5643
6164
|
const session = deps.oauthSessions.peek(sessionId);
|
|
5644
|
-
if (!session) return
|
|
6165
|
+
if (!session) return err6(410, "oauth session is unknown, expired, or already used");
|
|
5645
6166
|
if (session.providerId !== providerId) {
|
|
5646
|
-
return
|
|
6167
|
+
return err6(400, `oauth session does not match provider '${providerId}'`);
|
|
5647
6168
|
}
|
|
5648
6169
|
let code = rawCode.trim();
|
|
5649
6170
|
if (providerId === "claude") {
|
|
5650
6171
|
const [splitCode, pastedState] = code.split("#");
|
|
5651
|
-
if (!splitCode) return
|
|
6172
|
+
if (!splitCode) return err6(400, "no authorization code was provided");
|
|
5652
6173
|
if (pastedState && pastedState !== session.state) {
|
|
5653
|
-
return
|
|
6174
|
+
return err6(400, "oauth state did not match (possible CSRF) \u2014 aborting");
|
|
5654
6175
|
}
|
|
5655
6176
|
code = splitCode;
|
|
5656
6177
|
}
|
|
@@ -5660,7 +6181,7 @@ async function handleOAuthComplete(providerId, body, deps) {
|
|
|
5660
6181
|
block = providerId === "claude" ? await exchangeClaude(code, session.codeVerifier, session.state, exchangeFetch) : await exchangeGemini(code, session.codeVerifier, exchangeFetch);
|
|
5661
6182
|
} catch (exchangeError) {
|
|
5662
6183
|
const reason = exchangeError instanceof Error ? exchangeError.message : "token exchange failed";
|
|
5663
|
-
return
|
|
6184
|
+
return err6(502, `oauth token exchange failed for '${providerId}': ${reason}`);
|
|
5664
6185
|
}
|
|
5665
6186
|
deps.oauthSessions.consume(sessionId);
|
|
5666
6187
|
const label = typeof body["label"] === "string" && body["label"].trim() ? body["label"].trim() : void 0;
|
|
@@ -5669,7 +6190,7 @@ async function handleOAuthComplete(providerId, body, deps) {
|
|
|
5669
6190
|
return { status: 200, body: status ? { account: status } : { ok: true } };
|
|
5670
6191
|
}
|
|
5671
6192
|
async function exchangeClaude(code, codeVerifier, state, exchangeFetch) {
|
|
5672
|
-
const result = await
|
|
6193
|
+
const result = await import_subscriptions9.claudeOAuth.exchangeCodeForTokens(
|
|
5673
6194
|
{ authorizationCode: code, codeVerifier, state },
|
|
5674
6195
|
exchangeFetch
|
|
5675
6196
|
);
|
|
@@ -5685,7 +6206,7 @@ async function exchangeClaude(code, codeVerifier, state, exchangeFetch) {
|
|
|
5685
6206
|
};
|
|
5686
6207
|
}
|
|
5687
6208
|
async function exchangeGemini(code, codeVerifier, exchangeFetch) {
|
|
5688
|
-
const result = await
|
|
6209
|
+
const result = await import_subscriptions9.geminiOAuth.exchangeCodeForTokens(code, codeVerifier, exchangeFetch);
|
|
5689
6210
|
const expiresAt = new Date(Date.now() + result.expiresIn * 1e3).toISOString();
|
|
5690
6211
|
return {
|
|
5691
6212
|
authMethod: "oauth",
|
|
@@ -5990,8 +6511,8 @@ function errBody(message) {
|
|
|
5990
6511
|
return { error: { type: "admin_api_error", message } };
|
|
5991
6512
|
}
|
|
5992
6513
|
var defaultCommandRunner = (command) => new Promise((resolve11) => {
|
|
5993
|
-
(0, import_node_child_process.exec)(command, { timeout: 18e4 }, (
|
|
5994
|
-
if (
|
|
6514
|
+
(0, import_node_child_process.exec)(command, { timeout: 18e4 }, (err9, _stdout, stderr) => {
|
|
6515
|
+
if (err9) resolve11({ ok: false, error: stderr.trim() || err9.message });
|
|
5995
6516
|
else resolve11({ ok: true });
|
|
5996
6517
|
});
|
|
5997
6518
|
});
|
|
@@ -6037,8 +6558,8 @@ async function handleCliLaunch(cli, body, ctx) {
|
|
|
6037
6558
|
providerId: typeof body["providerId"] === "string" ? body["providerId"] : void 0,
|
|
6038
6559
|
model: typeof body["model"] === "string" ? body["model"] : void 0
|
|
6039
6560
|
});
|
|
6040
|
-
} catch (
|
|
6041
|
-
return { status: 400, body: errBody(
|
|
6561
|
+
} catch (err9) {
|
|
6562
|
+
return { status: 400, body: errBody(err9 instanceof Error ? err9.message : "no launch target") };
|
|
6042
6563
|
}
|
|
6043
6564
|
const id = (0, import_node_crypto7.randomUUID)();
|
|
6044
6565
|
let leaseId2;
|
|
@@ -6066,9 +6587,9 @@ async function handleCliLaunch(cli, body, ctx) {
|
|
|
6066
6587
|
} else {
|
|
6067
6588
|
launch = await buildLaunchEnv(cli, ctx.llmConfig, target);
|
|
6068
6589
|
}
|
|
6069
|
-
} catch (
|
|
6070
|
-
const status =
|
|
6071
|
-
return { status, body: errBody(
|
|
6590
|
+
} catch (err9) {
|
|
6591
|
+
const status = err9 instanceof import_provider_proxy2.RouteLeaseError ? err9.status : 400;
|
|
6592
|
+
return { status, body: errBody(err9 instanceof Error ? err9.message : "failed to build launch env") };
|
|
6072
6593
|
}
|
|
6073
6594
|
const cwd = typeof body["cwd"] === "string" && body["cwd"].trim() ? body["cwd"].trim() : void 0;
|
|
6074
6595
|
const opener = ctx.opener ?? defaultTerminalOpener;
|
|
@@ -6096,9 +6617,9 @@ async function handleCliLaunch(cli, body, ctx) {
|
|
|
6096
6617
|
onFailure: onSessionEnd
|
|
6097
6618
|
});
|
|
6098
6619
|
if (cleanup) openerCleanup = cleanup;
|
|
6099
|
-
} catch (
|
|
6620
|
+
} catch (err9) {
|
|
6100
6621
|
onSessionEnd();
|
|
6101
|
-
return { status: 500, body: errBody(
|
|
6622
|
+
return { status: 500, body: errBody(err9 instanceof Error ? err9.message : "failed to open terminal") };
|
|
6102
6623
|
}
|
|
6103
6624
|
if (ended) {
|
|
6104
6625
|
openerCleanup?.();
|
|
@@ -6353,7 +6874,7 @@ async function runSearchLiveChecks(contributions, now = () => (/* @__PURE__ */ n
|
|
|
6353
6874
|
}
|
|
6354
6875
|
|
|
6355
6876
|
// src/search/SearchAssembly.ts
|
|
6356
|
-
var
|
|
6877
|
+
var import_upstreamFetch11 = require("@omnicross/core/pipeline/upstreamFetch");
|
|
6357
6878
|
var import_search = require("@omnicross/core/search");
|
|
6358
6879
|
var import_api2 = require("@omnicross/core/search/api");
|
|
6359
6880
|
var import_http2 = require("@omnicross/core/search/http");
|
|
@@ -6371,7 +6892,7 @@ function searchPolicyFrom(config) {
|
|
|
6371
6892
|
};
|
|
6372
6893
|
}
|
|
6373
6894
|
function resolveSearchUpstreamDispatcher(url) {
|
|
6374
|
-
return (0,
|
|
6895
|
+
return (0, import_upstreamFetch11.resolveUpstreamDispatcher)({ url });
|
|
6375
6896
|
}
|
|
6376
6897
|
var searchUpstreamProxyConfig = createUpstreamProxyResolver();
|
|
6377
6898
|
function resolveSearchUpstreamProxyConfig(url) {
|
|
@@ -6653,7 +7174,7 @@ async function handleSearchQuery(req, res, deps) {
|
|
|
6653
7174
|
// src/admin/searchAdminView.ts
|
|
6654
7175
|
var API_KEY_PROVIDERS = /* @__PURE__ */ new Set(["tavily", "jina", "zhipu", "z.ai"]);
|
|
6655
7176
|
var BASIC_AUTH_PROVIDERS = /* @__PURE__ */ new Set(["searxng"]);
|
|
6656
|
-
function
|
|
7177
|
+
function isRecord7(value) {
|
|
6657
7178
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
6658
7179
|
}
|
|
6659
7180
|
function redactSearchServerConfig(search) {
|
|
@@ -6703,13 +7224,13 @@ function resolveSecretField(entry, field, stored) {
|
|
|
6703
7224
|
else delete entry[field];
|
|
6704
7225
|
}
|
|
6705
7226
|
function preserveSearchSecrets(incoming, current) {
|
|
6706
|
-
if (!
|
|
7227
|
+
if (!isRecord7(incoming)) return incoming;
|
|
6707
7228
|
const section = { ...incoming };
|
|
6708
7229
|
const providersValue = section["providers"];
|
|
6709
|
-
if (!
|
|
7230
|
+
if (!isRecord7(providersValue)) return section;
|
|
6710
7231
|
const providers = {};
|
|
6711
7232
|
for (const [id, entryValue] of Object.entries(providersValue)) {
|
|
6712
|
-
if (!
|
|
7233
|
+
if (!isRecord7(entryValue)) {
|
|
6713
7234
|
providers[id] = entryValue;
|
|
6714
7235
|
continue;
|
|
6715
7236
|
}
|
|
@@ -6787,7 +7308,7 @@ function parseKeyPolicyBody(body) {
|
|
|
6787
7308
|
var ENDPOINTS = /* @__PURE__ */ new Set(["chat", "responses", "messages", "gemini"]);
|
|
6788
7309
|
var TARGET_KINDS = /* @__PURE__ */ new Set(["account", "account-group", "account-pool", "provider"]);
|
|
6789
7310
|
var FALLBACKS = /* @__PURE__ */ new Set(["next", "fail", "global"]);
|
|
6790
|
-
function
|
|
7311
|
+
function isRecord8(value) {
|
|
6791
7312
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
6792
7313
|
}
|
|
6793
7314
|
function nonBlank(value) {
|
|
@@ -6807,7 +7328,7 @@ function validateGatewayBindingsSegment(patch) {
|
|
|
6807
7328
|
const ids = /* @__PURE__ */ new Set();
|
|
6808
7329
|
raw.forEach((entry, index) => {
|
|
6809
7330
|
const path2 = `bindings[${index}]`;
|
|
6810
|
-
if (!
|
|
7331
|
+
if (!isRecord8(entry)) {
|
|
6811
7332
|
errors.push(`${path2} must be an object`);
|
|
6812
7333
|
return;
|
|
6813
7334
|
}
|
|
@@ -6836,12 +7357,12 @@ function validateGatewayBindingsSegment(patch) {
|
|
|
6836
7357
|
} else if (entry.modelMappings.length > 100) {
|
|
6837
7358
|
errors.push(`${path2}.modelMappings cannot contain more than 100 entries`);
|
|
6838
7359
|
} else if (entry.modelMappings.some(
|
|
6839
|
-
(mapping) => !
|
|
7360
|
+
(mapping) => !isRecord8(mapping) || !nonBlank(mapping.source) || !nonBlank(mapping.target)
|
|
6840
7361
|
)) {
|
|
6841
7362
|
errors.push(`${path2}.modelMappings must contain non-empty source and target strings`);
|
|
6842
7363
|
}
|
|
6843
7364
|
}
|
|
6844
|
-
if (!
|
|
7365
|
+
if (!isRecord8(entry.target) || !TARGET_KINDS.has(String(entry.target.kind))) {
|
|
6845
7366
|
errors.push(`${path2}.target is invalid`);
|
|
6846
7367
|
} else {
|
|
6847
7368
|
if (!nonBlank(entry.target.providerId)) errors.push(`${path2}.target.providerId is required`);
|
|
@@ -6856,7 +7377,7 @@ function validateGatewayBindingsSegment(patch) {
|
|
|
6856
7377
|
}
|
|
6857
7378
|
}
|
|
6858
7379
|
if (entry.modelMap !== void 0) {
|
|
6859
|
-
if (!
|
|
7380
|
+
if (!isRecord8(entry.modelMap) || Object.values(entry.modelMap).some((value) => typeof value !== "string")) {
|
|
6860
7381
|
errors.push(`${path2}.modelMap must contain string values`);
|
|
6861
7382
|
}
|
|
6862
7383
|
}
|
|
@@ -7141,7 +7662,12 @@ var PROVIDER_KEYS = {
|
|
|
7141
7662
|
},
|
|
7142
7663
|
kimi: { block: "kimi", accounts: "kimiAccounts", active: "activeKimiAccountId" },
|
|
7143
7664
|
grok: { block: "grok", accounts: "grokAccounts", active: "activeGrokAccountId" },
|
|
7144
|
-
copilot: { block: "copilot", accounts: "copilotAccounts", active: "activeCopilotAccountId" }
|
|
7665
|
+
copilot: { block: "copilot", accounts: "copilotAccounts", active: "activeCopilotAccountId" },
|
|
7666
|
+
antigravity: {
|
|
7667
|
+
block: "antigravity",
|
|
7668
|
+
accounts: "antigravityAccounts",
|
|
7669
|
+
active: "activeAntigravityAccountId"
|
|
7670
|
+
}
|
|
7145
7671
|
};
|
|
7146
7672
|
function clone(value) {
|
|
7147
7673
|
return JSON.parse(JSON.stringify(value));
|
|
@@ -7663,7 +8189,7 @@ async function applyImport(packString, passphrase, mode, deps, parseProviderInpu
|
|
|
7663
8189
|
}
|
|
7664
8190
|
|
|
7665
8191
|
// src/admin/adminMigration.ts
|
|
7666
|
-
function
|
|
8192
|
+
function err7(status, message) {
|
|
7667
8193
|
return { status, body: { error: { type: "admin_api_error", message } } };
|
|
7668
8194
|
}
|
|
7669
8195
|
async function handleExport(body, deps) {
|
|
@@ -7673,30 +8199,30 @@ async function handleExport(body, deps) {
|
|
|
7673
8199
|
return { status: 200, body: { pack, version: BUNDLE_VERSION } };
|
|
7674
8200
|
} catch (error) {
|
|
7675
8201
|
if (error instanceof WeakPassphraseError) {
|
|
7676
|
-
return
|
|
8202
|
+
return err7(400, error.message);
|
|
7677
8203
|
}
|
|
7678
|
-
return
|
|
8204
|
+
return err7(500, "failed to build the migration pack");
|
|
7679
8205
|
}
|
|
7680
8206
|
}
|
|
7681
8207
|
async function handleImport(body, deps) {
|
|
7682
8208
|
const blob = typeof body["blob"] === "string" ? body["blob"] : "";
|
|
7683
8209
|
const passphrase = typeof body["passphrase"] === "string" ? body["passphrase"] : "";
|
|
7684
8210
|
const mode = body["mode"] === "overwrite" ? "overwrite" : "merge";
|
|
7685
|
-
if (!blob) return
|
|
8211
|
+
if (!blob) return err7(400, "import requires { blob }");
|
|
7686
8212
|
try {
|
|
7687
8213
|
const counts = await applyImport(blob, passphrase, mode, deps, deps.parseProviderInput);
|
|
7688
8214
|
return { status: 200, body: counts };
|
|
7689
8215
|
} catch (error) {
|
|
7690
8216
|
if (error instanceof WeakPassphraseError) {
|
|
7691
|
-
return
|
|
8217
|
+
return err7(400, error.message);
|
|
7692
8218
|
}
|
|
7693
|
-
return
|
|
8219
|
+
return err7(400, error instanceof Error ? error.message : "import failed");
|
|
7694
8220
|
}
|
|
7695
8221
|
}
|
|
7696
8222
|
|
|
7697
8223
|
// src/admin/usagePricing.ts
|
|
7698
8224
|
var import_usage = require("@omnicross/core/usage");
|
|
7699
|
-
var
|
|
8225
|
+
var err8 = (status, message) => ({
|
|
7700
8226
|
status,
|
|
7701
8227
|
body: { error: { type: "admin_api_error", message } }
|
|
7702
8228
|
});
|
|
@@ -7709,7 +8235,7 @@ function parseRange(query2) {
|
|
|
7709
8235
|
const startTs = parseFiniteInt(query2.get("startTs"));
|
|
7710
8236
|
const endTs = parseFiniteInt(query2.get("endTs"));
|
|
7711
8237
|
if (startTs === null || endTs === null) {
|
|
7712
|
-
return
|
|
8238
|
+
return err8(400, "startTs and endTs are required finite-integer unix-millis query params");
|
|
7713
8239
|
}
|
|
7714
8240
|
return { startTs, endTs };
|
|
7715
8241
|
}
|
|
@@ -7734,14 +8260,14 @@ async function handleUsageGet(view, query2, deps) {
|
|
|
7734
8260
|
case "timeseries": {
|
|
7735
8261
|
const bucket = query2.get("bucket");
|
|
7736
8262
|
if (bucket !== "hour" && bucket !== "day" && bucket !== "month") {
|
|
7737
|
-
return
|
|
8263
|
+
return err8(400, "bucket must be one of 'hour', 'day', 'month'");
|
|
7738
8264
|
}
|
|
7739
8265
|
const now = Date.now();
|
|
7740
8266
|
const clamped = { startTs: range.startTs, endTs: Math.min(range.endTs, now) };
|
|
7741
8267
|
if (clamped.startTs < clamped.endTs) {
|
|
7742
8268
|
const projected = Math.ceil((clamped.endTs - clamped.startTs) / BUCKET_SPAN_MS[bucket]) + 1;
|
|
7743
8269
|
if (projected > MAX_TIMESERIES_BUCKETS) {
|
|
7744
|
-
return
|
|
8270
|
+
return err8(
|
|
7745
8271
|
400,
|
|
7746
8272
|
`requested range projects ~${projected} '${bucket}' buckets (max ${MAX_TIMESERIES_BUCKETS}); narrow the range or use a coarser bucket`
|
|
7747
8273
|
);
|
|
@@ -7764,7 +8290,7 @@ async function handleUsageGet(view, query2, deps) {
|
|
|
7764
8290
|
};
|
|
7765
8291
|
}
|
|
7766
8292
|
default:
|
|
7767
|
-
return
|
|
8293
|
+
return err8(404, `unknown usage view '${view ?? ""}'`);
|
|
7768
8294
|
}
|
|
7769
8295
|
}
|
|
7770
8296
|
function poolKeyLabels(cfg) {
|
|
@@ -7813,7 +8339,7 @@ async function handlePricingList(deps) {
|
|
|
7813
8339
|
async function handlePricingUpsert(body, deps) {
|
|
7814
8340
|
const input = parsePricingEntryInput(body);
|
|
7815
8341
|
if (!input) {
|
|
7816
|
-
return
|
|
8342
|
+
return err8(400, "invalid pricing entry (providerId, modelId, finite numeric inputPricePer1m/outputPricePer1m required)");
|
|
7817
8343
|
}
|
|
7818
8344
|
const entry = await deps.pricingEngine.upsertManual(input);
|
|
7819
8345
|
return { status: 200, body: { entry } };
|
|
@@ -7822,7 +8348,7 @@ async function handlePricingDelete(query2, deps) {
|
|
|
7822
8348
|
const providerId = query2.get("providerId")?.trim() ?? "";
|
|
7823
8349
|
const modelId = query2.get("modelId")?.trim() ?? "";
|
|
7824
8350
|
if (!providerId || !modelId) {
|
|
7825
|
-
return
|
|
8351
|
+
return err8(400, "delete requires providerId and modelId query params");
|
|
7826
8352
|
}
|
|
7827
8353
|
const deleted = await deps.pricingStore.delete(providerId, modelId);
|
|
7828
8354
|
if (deleted) await deps.pricingEngine.invalidateCache();
|
|
@@ -7842,13 +8368,13 @@ async function handlePricingFetchLatest(deps) {
|
|
|
7842
8368
|
}
|
|
7843
8369
|
};
|
|
7844
8370
|
} catch (e) {
|
|
7845
|
-
return
|
|
8371
|
+
return err8(502, `pricing-source fetch failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
7846
8372
|
}
|
|
7847
8373
|
}
|
|
7848
8374
|
async function handlePricingResolveConflicts(body, deps) {
|
|
7849
8375
|
const raw = body["resolutions"];
|
|
7850
8376
|
if (!Array.isArray(raw)) {
|
|
7851
|
-
return
|
|
8377
|
+
return err8(400, "resolve-conflicts requires { resolutions: [...] }");
|
|
7852
8378
|
}
|
|
7853
8379
|
const currentRows = await deps.pricingStore.getAll();
|
|
7854
8380
|
const userEditedKeys = new Set(
|
|
@@ -7858,21 +8384,21 @@ async function handlePricingResolveConflicts(body, deps) {
|
|
|
7858
8384
|
const pendingIncoming = /* @__PURE__ */ new Map();
|
|
7859
8385
|
let staleCount = 0;
|
|
7860
8386
|
for (const item of raw) {
|
|
7861
|
-
if (!item || typeof item !== "object") return
|
|
8387
|
+
if (!item || typeof item !== "object") return err8(400, "invalid resolution entry");
|
|
7862
8388
|
const r = item;
|
|
7863
8389
|
const action = r["action"];
|
|
7864
8390
|
if (action !== "overwrite" && action !== "skip") {
|
|
7865
|
-
return
|
|
8391
|
+
return err8(400, "resolution action must be 'overwrite' or 'skip'");
|
|
7866
8392
|
}
|
|
7867
8393
|
const providerId = typeof r["providerId"] === "string" && r["providerId"].trim() ? r["providerId"].trim() : "";
|
|
7868
8394
|
const modelId = typeof r["modelId"] === "string" && r["modelId"].trim() ? r["modelId"].trim() : "";
|
|
7869
8395
|
if (!providerId || !modelId) {
|
|
7870
|
-
return
|
|
8396
|
+
return err8(400, "each resolution requires top-level providerId and modelId");
|
|
7871
8397
|
}
|
|
7872
8398
|
const incoming = parsePricingEntryInput(r["incoming"]);
|
|
7873
|
-
if (!incoming) return
|
|
8399
|
+
if (!incoming) return err8(400, "each resolution must echo a valid incoming pricing entry");
|
|
7874
8400
|
if (incoming.providerId !== providerId || incoming.modelId !== modelId) {
|
|
7875
|
-
return
|
|
8401
|
+
return err8(400, "resolution providerId/modelId must match the echoed incoming entry");
|
|
7876
8402
|
}
|
|
7877
8403
|
const key = `${providerId}::${modelId}`;
|
|
7878
8404
|
if (action === "overwrite" && !userEditedKeys.has(key)) {
|
|
@@ -7917,7 +8443,7 @@ function query(req) {
|
|
|
7917
8443
|
}
|
|
7918
8444
|
function allowanceProvider(value) {
|
|
7919
8445
|
if (!value) return void 0;
|
|
7920
|
-
return value === "claude" || value === "codex" || value === "kimi" || value === "opencodego" || value === "grok" || value === "copilot" || value === "gemini" ? value : null;
|
|
8446
|
+
return value === "claude" || value === "codex" || value === "kimi" || value === "opencodego" || value === "grok" || value === "copilot" || value === "gemini" || value === "antigravity" ? value : null;
|
|
7921
8447
|
}
|
|
7922
8448
|
async function handleAccountAllowanceApi(req, res, method, rest, service) {
|
|
7923
8449
|
if (!service) return writeError2(res, 501, "account allowance service is not available");
|
|
@@ -7994,6 +8520,16 @@ async function handleAccountAllowanceApi(req, res, method, rest, service) {
|
|
|
7994
8520
|
}
|
|
7995
8521
|
return writeJson3(res, 200, { allowances: allowances2 });
|
|
7996
8522
|
}
|
|
8523
|
+
if (requestedProvider === "antigravity") {
|
|
8524
|
+
if (!service.refreshAntigravity) {
|
|
8525
|
+
return writeError2(res, 501, "antigravity allowance refresh is not available");
|
|
8526
|
+
}
|
|
8527
|
+
const allowances2 = await service.refreshAntigravity(accountId);
|
|
8528
|
+
if (accountId && allowances2.length === 0) {
|
|
8529
|
+
return writeError2(res, 404, `Antigravity account '${accountId}' not found`);
|
|
8530
|
+
}
|
|
8531
|
+
return writeJson3(res, 200, { allowances: allowances2 });
|
|
8532
|
+
}
|
|
7997
8533
|
if (requestedProvider === "gemini") {
|
|
7998
8534
|
if (!service.refreshGemini) {
|
|
7999
8535
|
return writeError2(res, 501, "gemini allowance refresh is not available");
|
|
@@ -8174,8 +8710,8 @@ async function handleAdminApi(req, res, path2, deps) {
|
|
|
8174
8710
|
default:
|
|
8175
8711
|
return writeJsonError(res, 404, `unknown admin resource '${resource}'`);
|
|
8176
8712
|
}
|
|
8177
|
-
} catch (
|
|
8178
|
-
writeJsonError(res, 500,
|
|
8713
|
+
} catch (err9) {
|
|
8714
|
+
writeJsonError(res, 500, err9 instanceof Error ? err9.message : String(err9));
|
|
8179
8715
|
}
|
|
8180
8716
|
}
|
|
8181
8717
|
function requestQuery(req) {
|
|
@@ -8350,7 +8886,7 @@ async function handleDiscoverModels(res, id, cfg) {
|
|
|
8350
8886
|
const headers = { Accept: "application/json" };
|
|
8351
8887
|
if (resolvedKey) headers["Authorization"] = `Bearer ${resolvedKey}`;
|
|
8352
8888
|
Object.assign(headers, expandRowExtraHeaders(row));
|
|
8353
|
-
const response = await (0,
|
|
8889
|
+
const response = await (0, import_upstreamFetch12.fetchUpstream)(url, { method: "GET", headers }, { providerId: "byo" });
|
|
8354
8890
|
if (!response.ok) {
|
|
8355
8891
|
const text = await response.text().catch(() => "");
|
|
8356
8892
|
let message = text.slice(0, 300);
|
|
@@ -8367,8 +8903,8 @@ async function handleDiscoverModels(res, id, cfg) {
|
|
|
8367
8903
|
const data = await response.json();
|
|
8368
8904
|
const models = Array.isArray(data?.data) ? data.data.map((m) => typeof m?.id === "string" ? m.id : "").filter((m) => m.length > 0) : [];
|
|
8369
8905
|
return writeJson4(res, 200, { models });
|
|
8370
|
-
} catch (
|
|
8371
|
-
const message =
|
|
8906
|
+
} catch (err9) {
|
|
8907
|
+
const message = err9 instanceof Error ? err9.message : String(err9);
|
|
8372
8908
|
return writeJson4(res, 200, { models: [], error: `discovery failed: ${message}` });
|
|
8373
8909
|
}
|
|
8374
8910
|
}
|
|
@@ -8410,7 +8946,7 @@ async function handleTestModel(req, res, id, cfg) {
|
|
|
8410
8946
|
Object.assign(headers, expandRowExtraHeaders(row));
|
|
8411
8947
|
const startedAt = Date.now();
|
|
8412
8948
|
try {
|
|
8413
|
-
const response = await (0,
|
|
8949
|
+
const response = await (0, import_upstreamFetch12.fetchUpstream)(
|
|
8414
8950
|
url,
|
|
8415
8951
|
{ method: "POST", headers, body: JSON.stringify(payload) },
|
|
8416
8952
|
{ providerId: "byo" }
|
|
@@ -8432,8 +8968,8 @@ async function handleTestModel(req, res, id, cfg) {
|
|
|
8432
8968
|
latencyMs,
|
|
8433
8969
|
sample: extractSampleText(text, row.apiFormat)
|
|
8434
8970
|
});
|
|
8435
|
-
} catch (
|
|
8436
|
-
const message =
|
|
8971
|
+
} catch (err9) {
|
|
8972
|
+
const message = err9 instanceof Error ? err9.message : String(err9);
|
|
8437
8973
|
return writeJson4(res, 200, { ok: false, latencyMs: Date.now() - startedAt, message });
|
|
8438
8974
|
}
|
|
8439
8975
|
}
|
|
@@ -9018,8 +9554,8 @@ function imageConfigurationAuditFields(previous, next) {
|
|
|
9018
9554
|
const after = next ?? import_outbound_api5.DEFAULT_IMAGES_SERVER_CONFIG;
|
|
9019
9555
|
const fields = [];
|
|
9020
9556
|
if (before.enabled !== after.enabled) fields.push("enablement");
|
|
9021
|
-
if (before.
|
|
9022
|
-
if (before.defaultModel !== after.defaultModel || !sameConfigValue(before.
|
|
9557
|
+
if (!sameConfigValue(before.models, after.models)) fields.push("provider");
|
|
9558
|
+
if (before.defaultModel !== after.defaultModel || !sameConfigValue(before.aliases, after.aliases) || !sameConfigValue(before.codex, after.codex)) fields.push("model");
|
|
9023
9559
|
if (!sameConfigValue(before.account, after.account)) fields.push("account");
|
|
9024
9560
|
if (!sameConfigValue(before.queue, after.queue)) fields.push("queue");
|
|
9025
9561
|
if (!sameConfigValue(before.temporary, after.temporary)) fields.push("temporary");
|
|
@@ -9223,6 +9759,12 @@ async function handleAccounts(req, res, method, rest, deps) {
|
|
|
9223
9759
|
deps.accountAllowanceService
|
|
9224
9760
|
);
|
|
9225
9761
|
}
|
|
9762
|
+
if (method === "GET" && rest[0] === "antigravity" && rest[1] === "models") {
|
|
9763
|
+
const result = await handleAntigravityModelsRoute({
|
|
9764
|
+
resolveAntigravityAccessToken: deps.resolveAntigravityAccessToken ?? (async () => null)
|
|
9765
|
+
});
|
|
9766
|
+
return writeJson4(res, result.status, result.body);
|
|
9767
|
+
}
|
|
9226
9768
|
if (method === "GET" && rest.length === 0) {
|
|
9227
9769
|
const accounts = await deps.subscriptionAccounts.listAll();
|
|
9228
9770
|
const providerAccounts = await deps.subscriptionTokenWriter.listSanitizedAccounts();
|
|
@@ -9248,12 +9790,12 @@ async function handleAccounts(req, res, method, rest, deps) {
|
|
|
9248
9790
|
}
|
|
9249
9791
|
return writeJson4(res, 200, { ok: true, affected: result.affected });
|
|
9250
9792
|
}
|
|
9251
|
-
if (method === "GET" && (rest[0] === "codex" || rest[0] === "kimi" || rest[0] === "grok" || rest[0] === "copilot") && rest[1] === "oauth" && rest[3] === "status") {
|
|
9252
|
-
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);
|
|
9793
|
+
if (method === "GET" && (rest[0] === "codex" || rest[0] === "kimi" || rest[0] === "grok" || rest[0] === "copilot" || rest[0] === "antigravity") && rest[1] === "oauth" && rest[3] === "status") {
|
|
9794
|
+
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);
|
|
9253
9795
|
return writeJson4(res, result.status, result.body);
|
|
9254
9796
|
}
|
|
9255
|
-
if (method === "DELETE" && (rest[0] === "codex" || rest[0] === "kimi" || rest[0] === "grok" || rest[0] === "copilot") && rest[1] === "oauth" && rest[2]) {
|
|
9256
|
-
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);
|
|
9797
|
+
if (method === "DELETE" && (rest[0] === "codex" || rest[0] === "kimi" || rest[0] === "grok" || rest[0] === "copilot" || rest[0] === "antigravity") && rest[1] === "oauth" && rest[2]) {
|
|
9798
|
+
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);
|
|
9257
9799
|
return writeJson4(res, result.status, result.body);
|
|
9258
9800
|
}
|
|
9259
9801
|
if (method === "GET" && rest.length === 3 && rest[2] === "diagnostics") {
|
|
@@ -9323,6 +9865,10 @@ async function handleAccounts(req, res, method, rest, deps) {
|
|
|
9323
9865
|
const result2 = await handleCopilotOAuthStart(deps, body2["enterpriseUrl"]);
|
|
9324
9866
|
return writeJson4(res, result2.status, result2.body);
|
|
9325
9867
|
}
|
|
9868
|
+
if (providerId === "antigravity") {
|
|
9869
|
+
const result2 = handleAntigravityOAuthStart(deps);
|
|
9870
|
+
return writeJson4(res, result2.status, result2.body);
|
|
9871
|
+
}
|
|
9326
9872
|
const result = handleOAuthStart(providerId, deps);
|
|
9327
9873
|
return writeJson4(res, result.status, result.body);
|
|
9328
9874
|
}
|
|
@@ -9717,7 +10263,7 @@ async function handleImages(res, method, rest, deps) {
|
|
|
9717
10263
|
return writeJson4(res, 200, {
|
|
9718
10264
|
configured: {
|
|
9719
10265
|
enabled: images.enabled,
|
|
9720
|
-
provider: images.
|
|
10266
|
+
provider: images.models[images.defaultModel] ?? "codex-subscription",
|
|
9721
10267
|
model: images.defaultModel,
|
|
9722
10268
|
remoteUrlsEnabled: images.remote.enabled,
|
|
9723
10269
|
referenceTtlMs: images.references.ttlMs
|
|
@@ -9817,12 +10363,12 @@ async function handlePlayground(req, res, method, deps) {
|
|
|
9817
10363
|
const payload = body["body"];
|
|
9818
10364
|
const status = deps.outboundApiServer.getStatus();
|
|
9819
10365
|
if (!status.running || !status.port) return writeJsonError(res, 503, "outbound server not running");
|
|
9820
|
-
const path2 = resolvePlaygroundPath(endpoint,
|
|
10366
|
+
const path2 = resolvePlaygroundPath(endpoint, isRecord9(payload) ? payload : {});
|
|
9821
10367
|
if (!path2) return writeJsonError(res, 400, `unknown endpoint '${endpoint}'`);
|
|
9822
10368
|
const upstreamBody = typeof payload === "string" ? payload : JSON.stringify(payload ?? {});
|
|
9823
10369
|
await proxyToOutbound(res, status.port, path2, key, upstreamBody);
|
|
9824
10370
|
}
|
|
9825
|
-
function
|
|
10371
|
+
function isRecord9(v) {
|
|
9826
10372
|
return !!v && typeof v === "object" && !Array.isArray(v);
|
|
9827
10373
|
}
|
|
9828
10374
|
function proxyToOutbound(res, outboundPort, path2, key, body) {
|
|
@@ -9851,8 +10397,8 @@ function proxyToOutbound(res, outboundPort, path2, key, body) {
|
|
|
9851
10397
|
});
|
|
9852
10398
|
}
|
|
9853
10399
|
);
|
|
9854
|
-
upstream.on("error", (
|
|
9855
|
-
if (!res.headersSent) writeJsonError(res, 502, `playground proxy failed: ${
|
|
10400
|
+
upstream.on("error", (err9) => {
|
|
10401
|
+
if (!res.headersSent) writeJsonError(res, 502, `playground proxy failed: ${err9.message}`);
|
|
9856
10402
|
else res.end();
|
|
9857
10403
|
resolve11();
|
|
9858
10404
|
});
|
|
@@ -9958,7 +10504,7 @@ async function handleUiStatic(req, res, urlPath, uiDist) {
|
|
|
9958
10504
|
}
|
|
9959
10505
|
|
|
9960
10506
|
// src/admin/version.ts
|
|
9961
|
-
var DAEMON_VERSION = true ? "0.4.
|
|
10507
|
+
var DAEMON_VERSION = true ? "0.4.3" : "0.0.0-dev";
|
|
9962
10508
|
|
|
9963
10509
|
// src/admin/AdminServer.ts
|
|
9964
10510
|
var LOOPBACK_ADDR = "127.0.0.1";
|
|
@@ -10001,13 +10547,13 @@ var AdminServer = class {
|
|
|
10001
10547
|
const server = import_node_http2.default.createServer((req, res) => {
|
|
10002
10548
|
this.onRequest(req, res);
|
|
10003
10549
|
});
|
|
10004
|
-
const onError = (
|
|
10005
|
-
if (
|
|
10550
|
+
const onError = (err9) => {
|
|
10551
|
+
if (err9.code === "EADDRINUSE" && port !== 0) {
|
|
10006
10552
|
server.removeListener("error", onError);
|
|
10007
10553
|
this.listen(bindAddr, 0).then(resolve11, reject);
|
|
10008
10554
|
return;
|
|
10009
10555
|
}
|
|
10010
|
-
reject(
|
|
10556
|
+
reject(err9);
|
|
10011
10557
|
};
|
|
10012
10558
|
server.on("error", onError);
|
|
10013
10559
|
server.listen(port, bindAddr, () => {
|
|
@@ -10025,8 +10571,8 @@ var AdminServer = class {
|
|
|
10025
10571
|
}
|
|
10026
10572
|
/** Per-request handler: auth gate (when a token is set) → routing. */
|
|
10027
10573
|
onRequest(req, res) {
|
|
10028
|
-
void this.dispatch(req, res).catch((
|
|
10029
|
-
const message =
|
|
10574
|
+
void this.dispatch(req, res).catch((err9) => {
|
|
10575
|
+
const message = err9 instanceof Error ? err9.message : String(err9);
|
|
10030
10576
|
this.deps.logger.error("[AdminServer] unhandled error:", message);
|
|
10031
10577
|
if (!res.headersSent) {
|
|
10032
10578
|
res.writeHead(500, { "Content-Type": "application/json" });
|
|
@@ -10249,7 +10795,10 @@ var HTML_HEADERS = {
|
|
|
10249
10795
|
function pageHtml(message) {
|
|
10250
10796
|
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>`;
|
|
10251
10797
|
}
|
|
10252
|
-
function awaitLoopbackCode(expectedState, timeoutMs = DEFAULT_TIMEOUT_MS, signal) {
|
|
10798
|
+
function awaitLoopbackCode(expectedState, timeoutMs = DEFAULT_TIMEOUT_MS, signal, binding = {}) {
|
|
10799
|
+
const port = binding.port ?? LOOPBACK_PORT;
|
|
10800
|
+
const callbackPath = binding.path ?? CALLBACK_PATH;
|
|
10801
|
+
const label = binding.label ?? "codex";
|
|
10253
10802
|
return new Promise((resolve11, reject) => {
|
|
10254
10803
|
let settled = false;
|
|
10255
10804
|
const finish = (server2, fn) => {
|
|
@@ -10260,8 +10809,8 @@ function awaitLoopbackCode(expectedState, timeoutMs = DEFAULT_TIMEOUT_MS, signal
|
|
|
10260
10809
|
server2.close();
|
|
10261
10810
|
};
|
|
10262
10811
|
const server = (0, import_node_http3.createServer)((req, res) => {
|
|
10263
|
-
const url = new URL(req.url ?? "", `http://${LOOPBACK_HOST}:${
|
|
10264
|
-
if (url.pathname !==
|
|
10812
|
+
const url = new URL(req.url ?? "", `http://${LOOPBACK_HOST}:${port}`);
|
|
10813
|
+
if (url.pathname !== callbackPath) {
|
|
10265
10814
|
res.writeHead(404, HTML_HEADERS);
|
|
10266
10815
|
res.end(pageHtml("Not found"));
|
|
10267
10816
|
return;
|
|
@@ -10290,25 +10839,25 @@ function awaitLoopbackCode(expectedState, timeoutMs = DEFAULT_TIMEOUT_MS, signal
|
|
|
10290
10839
|
return;
|
|
10291
10840
|
}
|
|
10292
10841
|
signal?.addEventListener("abort", abort, { once: true });
|
|
10293
|
-
server.on("error", (
|
|
10842
|
+
server.on("error", (err9) => {
|
|
10294
10843
|
if (settled) return;
|
|
10295
10844
|
settled = true;
|
|
10296
10845
|
clearTimeout(timer);
|
|
10297
|
-
if (
|
|
10846
|
+
if (err9.code === "EADDRINUSE") {
|
|
10298
10847
|
reject(
|
|
10299
10848
|
new Error(
|
|
10300
|
-
`login: cannot bind ${LOOPBACK_HOST}:${
|
|
10849
|
+
`login: cannot bind ${LOOPBACK_HOST}:${port} (address in use) \u2014 another ${label} login or process is holding the port`
|
|
10301
10850
|
)
|
|
10302
10851
|
);
|
|
10303
10852
|
} else {
|
|
10304
|
-
reject(
|
|
10853
|
+
reject(err9);
|
|
10305
10854
|
}
|
|
10306
10855
|
});
|
|
10307
10856
|
const timer = setTimeout(() => {
|
|
10308
10857
|
finish(server, () => reject(new Error(`login: timed out after ${Math.round(timeoutMs / 1e3)}s waiting for the callback`)));
|
|
10309
10858
|
}, timeoutMs);
|
|
10310
10859
|
if (typeof timer.unref === "function") timer.unref();
|
|
10311
|
-
server.listen(
|
|
10860
|
+
server.listen(port, LOOPBACK_HOST);
|
|
10312
10861
|
});
|
|
10313
10862
|
}
|
|
10314
10863
|
|
|
@@ -10378,7 +10927,7 @@ function createPoolKeysLoader(getProviderRow, autoDisabled) {
|
|
|
10378
10927
|
|
|
10379
10928
|
// src/allowance/ProviderKeyQuotaService.ts
|
|
10380
10929
|
var import_core4 = require("@omnicross/core");
|
|
10381
|
-
var
|
|
10930
|
+
var import_upstreamFetch13 = require("@omnicross/core/pipeline/upstreamFetch");
|
|
10382
10931
|
|
|
10383
10932
|
// src/allowance/ProviderKeyQuota.ts
|
|
10384
10933
|
var MINUTE_MS3 = 6e4;
|
|
@@ -10407,11 +10956,11 @@ function isoInstant3(value) {
|
|
|
10407
10956
|
}
|
|
10408
10957
|
return void 0;
|
|
10409
10958
|
}
|
|
10410
|
-
function
|
|
10959
|
+
function secondsUntil9(instant, now) {
|
|
10411
10960
|
if (!instant) return void 0;
|
|
10412
10961
|
return Math.max(0, Math.floor((Date.parse(instant) - now) / 1e3));
|
|
10413
10962
|
}
|
|
10414
|
-
function
|
|
10963
|
+
function isRecord10(value) {
|
|
10415
10964
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
10416
10965
|
}
|
|
10417
10966
|
function detectProviderKeyQuotaAdapter(baseUrl) {
|
|
@@ -10478,17 +11027,17 @@ function zaiWindowIdLabel(durationMs) {
|
|
|
10478
11027
|
return { id: "quota", label: "Quota" };
|
|
10479
11028
|
}
|
|
10480
11029
|
function parseZaiQuotaPayload(payload, now) {
|
|
10481
|
-
if (!
|
|
10482
|
-
const data =
|
|
11030
|
+
if (!isRecord10(payload)) return null;
|
|
11031
|
+
const data = isRecord10(payload["data"]) ? payload["data"] : payload;
|
|
10483
11032
|
if (payload["success"] === false) return null;
|
|
10484
11033
|
const limits = Array.isArray(data["limits"]) ? data["limits"] : [];
|
|
10485
11034
|
const byWindow = /* @__PURE__ */ new Map();
|
|
10486
11035
|
for (const raw of limits) {
|
|
10487
|
-
if (!
|
|
11036
|
+
if (!isRecord10(raw)) continue;
|
|
10488
11037
|
const item = raw;
|
|
10489
11038
|
if (item.type === void 0) continue;
|
|
10490
11039
|
const details = raw["usageDetails"];
|
|
10491
|
-
if (Array.isArray(details) && details.some((d) =>
|
|
11040
|
+
if (Array.isArray(details) && details.some((d) => isRecord10(d) && d["modelCode"] === "zread")) {
|
|
10492
11041
|
continue;
|
|
10493
11042
|
}
|
|
10494
11043
|
const durationMs = zaiWindowDurationMs(item);
|
|
@@ -10507,7 +11056,7 @@ function parseZaiQuotaPayload(payload, now) {
|
|
|
10507
11056
|
usedPercent,
|
|
10508
11057
|
...durationMs !== void 0 ? { windowMinutes: Math.round(durationMs / MINUTE_MS3) } : {},
|
|
10509
11058
|
...resetsAt !== void 0 ? { resetsAt } : {},
|
|
10510
|
-
remainingSeconds:
|
|
11059
|
+
remainingSeconds: secondsUntil9(resetsAt, now),
|
|
10511
11060
|
state: "fresh"
|
|
10512
11061
|
};
|
|
10513
11062
|
const existing = byWindow.get(id);
|
|
@@ -10521,7 +11070,7 @@ function parseZaiQuotaPayload(payload, now) {
|
|
|
10521
11070
|
var MINIMAX_STATUS_EXHAUSTED = 2;
|
|
10522
11071
|
var MINIMAX_SHARED_BUCKET = "general";
|
|
10523
11072
|
function parseMiniMaxBucket(value) {
|
|
10524
|
-
if (!
|
|
11073
|
+
if (!isRecord10(value)) return null;
|
|
10525
11074
|
const modelName = typeof value["model_name"] === "string" ? value["model_name"].trim() : "";
|
|
10526
11075
|
if (!modelName) return null;
|
|
10527
11076
|
const instant = (v) => {
|
|
@@ -10548,14 +11097,14 @@ function minimaxWindow(id, label, windowMinutes, resetsAtMs, remainingPercent, s
|
|
|
10548
11097
|
usedPercent,
|
|
10549
11098
|
...windowMinutes !== void 0 ? { windowMinutes } : {},
|
|
10550
11099
|
...resetsAt !== void 0 ? { resetsAt } : {},
|
|
10551
|
-
remainingSeconds:
|
|
11100
|
+
remainingSeconds: secondsUntil9(resetsAt, now),
|
|
10552
11101
|
state: usedPercent !== null ? "fresh" : "unavailable"
|
|
10553
11102
|
};
|
|
10554
11103
|
}
|
|
10555
11104
|
function parseMiniMaxTokenPlanPayload(payload, now) {
|
|
10556
|
-
if (!
|
|
11105
|
+
if (!isRecord10(payload)) return null;
|
|
10557
11106
|
const baseResp = payload["base_resp"];
|
|
10558
|
-
if (!
|
|
11107
|
+
if (!isRecord10(baseResp) || baseResp["status_code"] !== 0) return null;
|
|
10559
11108
|
const buckets = Array.isArray(payload["model_remains"]) ? payload["model_remains"] : [];
|
|
10560
11109
|
let general = null;
|
|
10561
11110
|
for (const raw of buckets) {
|
|
@@ -10588,11 +11137,11 @@ function parseMiniMaxTokenPlanPayload(payload, now) {
|
|
|
10588
11137
|
];
|
|
10589
11138
|
}
|
|
10590
11139
|
function parseUmansUsagePayload(payload, now) {
|
|
10591
|
-
if (!
|
|
10592
|
-
const limits =
|
|
10593
|
-
const requests = limits &&
|
|
10594
|
-
const usage =
|
|
10595
|
-
const window =
|
|
11140
|
+
if (!isRecord10(payload)) return null;
|
|
11141
|
+
const limits = isRecord10(payload["limits"]) ? payload["limits"] : void 0;
|
|
11142
|
+
const requests = limits && isRecord10(limits["requests"]) ? limits["requests"] : void 0;
|
|
11143
|
+
const usage = isRecord10(payload["usage"]) ? payload["usage"] : void 0;
|
|
11144
|
+
const window = isRecord10(payload["window"]) ? payload["window"] : void 0;
|
|
10596
11145
|
const hardCap = finiteNumber5(requests?.["hard_cap"]);
|
|
10597
11146
|
const softLimit = finiteNumber5(requests?.["limit"]);
|
|
10598
11147
|
const requestsInWindow = finiteNumber5(usage?.["requests_in_window"]);
|
|
@@ -10613,15 +11162,15 @@ function parseUmansUsagePayload(payload, now) {
|
|
|
10613
11162
|
usedPercent,
|
|
10614
11163
|
windowMinutes: 5 * 60,
|
|
10615
11164
|
...resetsAt !== void 0 ? { resetsAt } : {},
|
|
10616
|
-
remainingSeconds:
|
|
11165
|
+
remainingSeconds: secondsUntil9(resetsAt, now),
|
|
10617
11166
|
state: "fresh"
|
|
10618
11167
|
}
|
|
10619
11168
|
];
|
|
10620
11169
|
}
|
|
10621
11170
|
function parseSyntheticQuotasPayload(payload, now) {
|
|
10622
|
-
if (!
|
|
10623
|
-
const fiveHour =
|
|
10624
|
-
const weekly =
|
|
11171
|
+
if (!isRecord10(payload)) return null;
|
|
11172
|
+
const fiveHour = isRecord10(payload["rollingFiveHourLimit"]) ? payload["rollingFiveHourLimit"] : void 0;
|
|
11173
|
+
const weekly = isRecord10(payload["weeklyTokenLimit"]) ? payload["weeklyTokenLimit"] : void 0;
|
|
10625
11174
|
const windows = [];
|
|
10626
11175
|
if (fiveHour) {
|
|
10627
11176
|
const max = finiteNumber5(fiveHour["max"]);
|
|
@@ -10635,7 +11184,7 @@ function parseSyntheticQuotasPayload(payload, now) {
|
|
|
10635
11184
|
usedPercent,
|
|
10636
11185
|
windowMinutes: 5 * 60,
|
|
10637
11186
|
...resetsAt !== void 0 ? { resetsAt } : {},
|
|
10638
|
-
remainingSeconds:
|
|
11187
|
+
remainingSeconds: secondsUntil9(resetsAt, now),
|
|
10639
11188
|
state: usedPercent !== null || resetsAt ? "fresh" : "unavailable"
|
|
10640
11189
|
});
|
|
10641
11190
|
}
|
|
@@ -10650,7 +11199,7 @@ function parseSyntheticQuotasPayload(payload, now) {
|
|
|
10650
11199
|
usedPercent,
|
|
10651
11200
|
windowMinutes: 7 * 24 * 60,
|
|
10652
11201
|
...resetsAt !== void 0 ? { resetsAt } : {},
|
|
10653
|
-
remainingSeconds:
|
|
11202
|
+
remainingSeconds: secondsUntil9(resetsAt, now),
|
|
10654
11203
|
state: usedPercent !== null || resetsAt ? "fresh" : "unavailable"
|
|
10655
11204
|
});
|
|
10656
11205
|
}
|
|
@@ -10662,12 +11211,12 @@ var CLINE_WINDOW_CONFIG = {
|
|
|
10662
11211
|
monthly: { id: "thirty-day", label: "30 days", minutes: 30 * 24 * 60 }
|
|
10663
11212
|
};
|
|
10664
11213
|
function parseClinePassUsageLimitsPayload(payload, now) {
|
|
10665
|
-
if (!
|
|
10666
|
-
const data =
|
|
11214
|
+
if (!isRecord10(payload)) return null;
|
|
11215
|
+
const data = isRecord10(payload["data"]) ? payload["data"] : payload;
|
|
10667
11216
|
const limits = Array.isArray(data["limits"]) ? data["limits"] : [];
|
|
10668
11217
|
const windows = [];
|
|
10669
11218
|
for (const raw of limits) {
|
|
10670
|
-
if (!
|
|
11219
|
+
if (!isRecord10(raw)) continue;
|
|
10671
11220
|
const config = CLINE_WINDOW_CONFIG[typeof raw["type"] === "string" ? raw["type"] : ""];
|
|
10672
11221
|
if (!config) continue;
|
|
10673
11222
|
const usedPercent = finitePercent4(raw["percentUsed"]);
|
|
@@ -10680,7 +11229,7 @@ function parseClinePassUsageLimitsPayload(payload, now) {
|
|
|
10680
11229
|
usedPercent,
|
|
10681
11230
|
windowMinutes: config.minutes,
|
|
10682
11231
|
...resetsAt !== void 0 ? { resetsAt } : {},
|
|
10683
|
-
remainingSeconds:
|
|
11232
|
+
remainingSeconds: secondsUntil9(resetsAt, now),
|
|
10684
11233
|
state: "fresh"
|
|
10685
11234
|
});
|
|
10686
11235
|
}
|
|
@@ -10719,7 +11268,7 @@ function rowKeyEntries(row) {
|
|
|
10719
11268
|
return [];
|
|
10720
11269
|
}
|
|
10721
11270
|
var ProviderKeyQuotaService = class {
|
|
10722
|
-
constructor(box, fetchImpl = (url, init) => (0,
|
|
11271
|
+
constructor(box, fetchImpl = (url, init) => (0, import_upstreamFetch13.fetchUpstream)(url, init, { redactBodies: true }), now = Date.now) {
|
|
10723
11272
|
this.box = box;
|
|
10724
11273
|
this.fetchImpl = fetchImpl;
|
|
10725
11274
|
this.now = now;
|
|
@@ -10822,7 +11371,7 @@ var ProviderKeyQuotaService = class {
|
|
|
10822
11371
|
// src/image-generation/ImageDoctorService.ts
|
|
10823
11372
|
var import_image_generation = require("@omnicross/core/image-generation");
|
|
10824
11373
|
var import_outbound_api7 = require("@omnicross/core/outbound-api");
|
|
10825
|
-
var
|
|
11374
|
+
var import_subscriptions10 = require("@omnicross/subscriptions");
|
|
10826
11375
|
|
|
10827
11376
|
// src/image-generation/FileCodexImageCapabilityEvidenceSource.ts
|
|
10828
11377
|
var import_node_crypto13 = require("crypto");
|
|
@@ -11260,16 +11809,16 @@ function createImageDoctorService(options) {
|
|
|
11260
11809
|
paths,
|
|
11261
11810
|
ttlMs: config.evidenceTtlMs
|
|
11262
11811
|
}));
|
|
11263
|
-
const createLiveVerifier = options.createLiveVerifier ?? ((strategy, config) => (0,
|
|
11812
|
+
const createLiveVerifier = options.createLiveVerifier ?? ((strategy, config) => (0, import_subscriptions10.createCodexImageLiveVerifier)({
|
|
11264
11813
|
authStrategy: strategy,
|
|
11265
11814
|
generationTimeoutMs: config.queue.generationTimeoutMs
|
|
11266
11815
|
}));
|
|
11267
|
-
const readAccount = async () => {
|
|
11268
|
-
const
|
|
11816
|
+
const readAccount = async (providerId) => {
|
|
11817
|
+
const entry = (await options.subscriptionAccounts.listAll()).find((candidate) => candidate.providerId === providerId);
|
|
11269
11818
|
return Object.freeze({
|
|
11270
|
-
present:
|
|
11271
|
-
usable:
|
|
11272
|
-
reason:
|
|
11819
|
+
present: entry !== void 0,
|
|
11820
|
+
usable: entry?.credentialStatus.ok === true,
|
|
11821
|
+
reason: entry === void 0 ? "missing" : entry.credentialStatus.ok ? "ready" : "unavailable"
|
|
11273
11822
|
});
|
|
11274
11823
|
};
|
|
11275
11824
|
const activePaths = () => options.storageCatalog.active().resolver;
|
|
@@ -11307,6 +11856,7 @@ function createImageDoctorService(options) {
|
|
|
11307
11856
|
} catch {
|
|
11308
11857
|
storesValid = false;
|
|
11309
11858
|
}
|
|
11859
|
+
const antigravityAccount = await readAccount("antigravity");
|
|
11310
11860
|
const rows = await options.keyDb.outboundApiKeysList();
|
|
11311
11861
|
let legacyRows = 0;
|
|
11312
11862
|
let invalidRows = 0;
|
|
@@ -11323,7 +11873,7 @@ function createImageDoctorService(options) {
|
|
|
11323
11873
|
invalidRows += 1;
|
|
11324
11874
|
}
|
|
11325
11875
|
}
|
|
11326
|
-
const account = await readAccount();
|
|
11876
|
+
const account = await readAccount("codex");
|
|
11327
11877
|
let evidence;
|
|
11328
11878
|
let evidenceStore;
|
|
11329
11879
|
try {
|
|
@@ -11337,10 +11887,11 @@ function createImageDoctorService(options) {
|
|
|
11337
11887
|
return Object.freeze({
|
|
11338
11888
|
config: Object.freeze({
|
|
11339
11889
|
enabled: config.enabled,
|
|
11340
|
-
provider: config.
|
|
11890
|
+
provider: config.models[config.defaultModel] ?? "codex-subscription",
|
|
11341
11891
|
model: config.defaultModel,
|
|
11342
11892
|
valid: configErrors.length === 0,
|
|
11343
|
-
errorCount: configErrors.length
|
|
11893
|
+
errorCount: configErrors.length,
|
|
11894
|
+
routedProviders: Object.freeze([...new Set(Object.values(config.models))])
|
|
11344
11895
|
}),
|
|
11345
11896
|
roots: Object.freeze({
|
|
11346
11897
|
valid: verifiedAreas === ROOT_AREAS.length,
|
|
@@ -11365,12 +11916,13 @@ function createImageDoctorService(options) {
|
|
|
11365
11916
|
imagesAuthorizedRows
|
|
11366
11917
|
}),
|
|
11367
11918
|
account,
|
|
11919
|
+
antigravityAccount,
|
|
11368
11920
|
evidence: Object.freeze(evidence)
|
|
11369
11921
|
});
|
|
11370
11922
|
},
|
|
11371
11923
|
verifyLive: async (config, signal) => {
|
|
11372
11924
|
if (!config.enabled) return Object.freeze({ ok: false, code: "images_disabled" });
|
|
11373
|
-
const account = await readAccount();
|
|
11925
|
+
const account = await readAccount("codex");
|
|
11374
11926
|
if (!account.usable) {
|
|
11375
11927
|
return Object.freeze({ ok: false, code: "codex_account_unavailable" });
|
|
11376
11928
|
}
|
|
@@ -11622,7 +12174,7 @@ var ImageCleanupService = class {
|
|
|
11622
12174
|
var import_node_crypto16 = require("crypto");
|
|
11623
12175
|
var import_image_generation5 = require("@omnicross/core/image-generation");
|
|
11624
12176
|
var import_outbound_api8 = require("@omnicross/core/outbound-api");
|
|
11625
|
-
var
|
|
12177
|
+
var import_subscriptions11 = require("@omnicross/subscriptions");
|
|
11626
12178
|
|
|
11627
12179
|
// src/image-generation/ImageApiRuntimeResolver.ts
|
|
11628
12180
|
var import_node_crypto14 = require("crypto");
|
|
@@ -11650,10 +12202,11 @@ function createTrustedImageApiRuntimeResolver(options) {
|
|
|
11650
12202
|
throw new TypeError("enabled image remote loading requires a proven resolver");
|
|
11651
12203
|
}
|
|
11652
12204
|
const hmacKey = Buffer.from(options.hmacKey);
|
|
11653
|
-
const modelAliases = new Map(Object.entries(options.config.
|
|
12205
|
+
const modelAliases = new Map(Object.entries(options.config.aliases));
|
|
12206
|
+
const modelRoutes = new Map(Object.entries(options.config.models));
|
|
11654
12207
|
const limits = Object.freeze({ ...options.config.limits });
|
|
11655
|
-
const providerId = options.config.provider;
|
|
11656
12208
|
const defaultModel = options.config.defaultModel;
|
|
12209
|
+
const providerId = modelRoutes.get(defaultModel) ?? "codex-subscription";
|
|
11657
12210
|
const referenceStore = options.referenceStore;
|
|
11658
12211
|
const retention = Object.freeze({
|
|
11659
12212
|
enabled: true,
|
|
@@ -11674,6 +12227,7 @@ function createTrustedImageApiRuntimeResolver(options) {
|
|
|
11674
12227
|
providerId,
|
|
11675
12228
|
defaultModel,
|
|
11676
12229
|
modelAliases,
|
|
12230
|
+
modelRoutes,
|
|
11677
12231
|
limits,
|
|
11678
12232
|
...preferredAccountId ? { preferredAccountId } : {},
|
|
11679
12233
|
...preferredAccountGroup ? { preferredAccountGroup } : {},
|
|
@@ -12075,7 +12629,9 @@ var GENERATION_ID = /^[A-Za-z0-9][A-Za-z0-9_.:-]{0,127}$/u;
|
|
|
12075
12629
|
function snapshotConfig(config) {
|
|
12076
12630
|
return {
|
|
12077
12631
|
...config,
|
|
12078
|
-
|
|
12632
|
+
models: { ...config.models },
|
|
12633
|
+
aliases: { ...config.aliases },
|
|
12634
|
+
codex: { ...config.codex },
|
|
12079
12635
|
account: { ...config.account },
|
|
12080
12636
|
queue: { ...config.queue },
|
|
12081
12637
|
temporary: { ...config.temporary },
|
|
@@ -12109,10 +12665,15 @@ function createImageRuntimeGeneration(options) {
|
|
|
12109
12665
|
}
|
|
12110
12666
|
});
|
|
12111
12667
|
}
|
|
12112
|
-
const
|
|
12113
|
-
|
|
12668
|
+
const routedProviders = [...new Set(Object.values(config.models))];
|
|
12669
|
+
const codexStrategy = routedProviders.includes("codex-subscription") ? options.subscriptionAccounts.getStrategy("codex") : void 0;
|
|
12670
|
+
if (routedProviders.includes("codex-subscription") && (!codexStrategy || codexStrategy.providerId !== "codex")) {
|
|
12114
12671
|
throw new TypeError("enabled image runtime requires the Codex subscription strategy");
|
|
12115
12672
|
}
|
|
12673
|
+
const antigravityStrategy = routedProviders.includes("antigravity-subscription") ? options.subscriptionAccounts.getStrategy("antigravity") : void 0;
|
|
12674
|
+
if (routedProviders.includes("antigravity-subscription") && (!antigravityStrategy || antigravityStrategy.providerId !== "antigravity")) {
|
|
12675
|
+
throw new TypeError("enabled image runtime requires the Antigravity subscription strategy");
|
|
12676
|
+
}
|
|
12116
12677
|
const privateHmacKey = options.privateHmacKey ? Buffer.from(options.privateHmacKey) : loadOrCreateImageTenantHmacSalt(options.storage.paths, import_node_crypto16.randomBytes);
|
|
12117
12678
|
if (privateHmacKey.byteLength !== 32) {
|
|
12118
12679
|
privateHmacKey.fill(0);
|
|
@@ -12147,23 +12708,32 @@ function createImageRuntimeGeneration(options) {
|
|
|
12147
12708
|
if (options.testOnlySyntheticVerifiedProvider && options.testOnlySyntheticVerifiedProvider.label !== "synthetic-verified-image-provider-test-only") {
|
|
12148
12709
|
throw new TypeError("synthetic verified image provider test seam label is invalid");
|
|
12149
12710
|
}
|
|
12150
|
-
const
|
|
12711
|
+
const providers = options.testOnlySyntheticVerifiedProvider ? [options.testOnlySyntheticVerifiedProvider.createProvider({
|
|
12151
12712
|
generationId: options.generationId,
|
|
12152
12713
|
scheduler,
|
|
12153
12714
|
now: options.now ?? Date.now,
|
|
12154
12715
|
referenceStore: options.storage.referenceStore,
|
|
12155
12716
|
stateStore: options.storage.stateStore
|
|
12156
|
-
}) : (0,
|
|
12157
|
-
authStrategy,
|
|
12717
|
+
})] : routedProviders.map((providerId) => providerId === "codex-subscription" ? (0, import_subscriptions11.createCodexSubscriptionImageProvider)({
|
|
12718
|
+
authStrategy: codexStrategy,
|
|
12158
12719
|
evidenceSource: generationEvidenceSource,
|
|
12159
12720
|
executionScheduler: scheduler,
|
|
12160
12721
|
generationTimeoutMs: config.queue.generationTimeoutMs,
|
|
12722
|
+
now: options.now,
|
|
12723
|
+
wire: {
|
|
12724
|
+
imageModel: config.codex.imageModel,
|
|
12725
|
+
carrierModel: config.codex.carrierModel
|
|
12726
|
+
}
|
|
12727
|
+
}) : (0, import_subscriptions11.createAntigravitySubscriptionImageProvider)({
|
|
12728
|
+
authStrategy: antigravityStrategy,
|
|
12729
|
+
executionScheduler: scheduler,
|
|
12730
|
+
generationTimeoutMs: config.queue.generationTimeoutMs,
|
|
12161
12731
|
now: options.now
|
|
12162
|
-
});
|
|
12163
|
-
if (
|
|
12732
|
+
}));
|
|
12733
|
+
if (providers.length === 1 && providers[0].id !== "codex-subscription") {
|
|
12164
12734
|
throw new TypeError("synthetic verified image provider id must match configured provider");
|
|
12165
12735
|
}
|
|
12166
|
-
const providerRegistry = new import_image_generation5.ImageProviderRegistry(
|
|
12736
|
+
const providerRegistry = new import_image_generation5.ImageProviderRegistry(providers);
|
|
12167
12737
|
const orchestrator = new import_image_generation5.ImageOrchestrator({
|
|
12168
12738
|
registry: providerRegistry,
|
|
12169
12739
|
referenceStore: options.storage.referenceStore,
|
|
@@ -12185,35 +12755,53 @@ function createImageRuntimeGeneration(options) {
|
|
|
12185
12755
|
...options.createCallId ? { createCallId: options.createCallId } : {},
|
|
12186
12756
|
...options.now ? { now: options.now } : {}
|
|
12187
12757
|
});
|
|
12758
|
+
const defaultProviderId = config.models[config.defaultModel] ?? "codex-subscription";
|
|
12759
|
+
const inspectOneProvider = async (providerId, apiKeyId) => {
|
|
12760
|
+
const capabilities = await orchestrator.getCapabilities(providerId, {
|
|
12761
|
+
requestId: `${options.generationId}:capability-inspection`,
|
|
12762
|
+
tenantId: apiKeyId,
|
|
12763
|
+
signal: new AbortController().signal,
|
|
12764
|
+
sessionKey: `outbound:images:${apiKeyId}`,
|
|
12765
|
+
...config.account.id ? { preferredAccountId: config.account.id } : {},
|
|
12766
|
+
...config.account.group ? { preferredAccountGroup: config.account.group } : {},
|
|
12767
|
+
boundAccountFallbackPolicy: config.account.fallback
|
|
12768
|
+
});
|
|
12769
|
+
return capabilities;
|
|
12770
|
+
};
|
|
12188
12771
|
const inspectCapability = async (apiKeyId) => {
|
|
12189
|
-
|
|
12190
|
-
|
|
12191
|
-
|
|
12192
|
-
|
|
12193
|
-
|
|
12194
|
-
|
|
12195
|
-
|
|
12196
|
-
|
|
12197
|
-
|
|
12198
|
-
|
|
12199
|
-
|
|
12200
|
-
|
|
12201
|
-
|
|
12202
|
-
|
|
12203
|
-
providerId: config.provider,
|
|
12204
|
-
model: config.defaultModel,
|
|
12205
|
-
...!available ? { reason: capabilities.reason ?? "runtime_unavailable" } : {},
|
|
12206
|
-
capabilities
|
|
12207
|
-
});
|
|
12208
|
-
} catch (error) {
|
|
12772
|
+
const providerCapabilities = /* @__PURE__ */ new Map();
|
|
12773
|
+
let defaultProviderError;
|
|
12774
|
+
for (const providerId of [...new Set(Object.values(config.models))]) {
|
|
12775
|
+
try {
|
|
12776
|
+
providerCapabilities.set(providerId, await inspectOneProvider(providerId, apiKeyId));
|
|
12777
|
+
} catch (error) {
|
|
12778
|
+
if (providerId === defaultProviderId) defaultProviderError = error;
|
|
12779
|
+
}
|
|
12780
|
+
}
|
|
12781
|
+
const routedModels = Object.freeze(
|
|
12782
|
+
[...providerCapabilities.entries()].flatMap(([providerId, capabilities2]) => capabilities2.available === true && capabilities2.generate === true ? Object.entries(config.models).filter(([model, modelProvider]) => modelProvider === providerId && capabilities2.models.includes(model)).map(([model]) => model) : [])
|
|
12783
|
+
);
|
|
12784
|
+
const capabilities = providerCapabilities.get(defaultProviderId);
|
|
12785
|
+
if (!capabilities) {
|
|
12209
12786
|
return Object.freeze({
|
|
12210
12787
|
enabled: true,
|
|
12211
12788
|
available: false,
|
|
12212
|
-
providerId:
|
|
12789
|
+
providerId: defaultProviderId,
|
|
12213
12790
|
model: config.defaultModel,
|
|
12214
|
-
|
|
12791
|
+
routedModels,
|
|
12792
|
+
reason: defaultProviderError instanceof import_image_generation5.ImageGenerationError && (defaultProviderError.code === "upstream_auth_required" || defaultProviderError.code === "invalid_api_key") ? "account_unverified" : "runtime_unavailable"
|
|
12215
12793
|
});
|
|
12216
12794
|
}
|
|
12795
|
+
const available = capabilities.available === true && capabilities.generate === true && capabilities.models.includes(config.defaultModel);
|
|
12796
|
+
return Object.freeze({
|
|
12797
|
+
enabled: true,
|
|
12798
|
+
available,
|
|
12799
|
+
providerId: defaultProviderId,
|
|
12800
|
+
model: config.defaultModel,
|
|
12801
|
+
routedModels,
|
|
12802
|
+
...!available ? { reason: capabilities.reason ?? "runtime_unavailable" } : {},
|
|
12803
|
+
capabilities
|
|
12804
|
+
});
|
|
12217
12805
|
};
|
|
12218
12806
|
const resolverToDispose = runtimeResolver;
|
|
12219
12807
|
const schedulerToDispose = scheduler;
|
|
@@ -12251,7 +12839,7 @@ function createImageRuntimeGeneration(options) {
|
|
|
12251
12839
|
imageApi,
|
|
12252
12840
|
hosted,
|
|
12253
12841
|
hostedRuntime: Object.freeze({
|
|
12254
|
-
providerId:
|
|
12842
|
+
providerId: defaultProviderId,
|
|
12255
12843
|
imageModel: config.defaultModel,
|
|
12256
12844
|
referenceTtlMs: config.references.ttlMs,
|
|
12257
12845
|
maxOutputBytes: config.limits.maxOutputBytes,
|
|
@@ -15194,6 +15782,9 @@ var ImageRuntimeManager = class {
|
|
|
15194
15782
|
}
|
|
15195
15783
|
async listAvailableModels(apiKeyId) {
|
|
15196
15784
|
const inspection = await this.inspectCapability(apiKeyId);
|
|
15785
|
+
if (inspection.routedModels !== void 0) {
|
|
15786
|
+
return Object.freeze([...inspection.routedModels]);
|
|
15787
|
+
}
|
|
15197
15788
|
return inspection.available && inspection.model === "gpt-image-2" ? Object.freeze([inspection.model]) : Object.freeze([]);
|
|
15198
15789
|
}
|
|
15199
15790
|
resourceStatus() {
|
|
@@ -17381,11 +17972,12 @@ var JsonVoucherDb = class {
|
|
|
17381
17972
|
// src/ports/JsonSubscriptionCredentialStore.ts
|
|
17382
17973
|
var import_node_fs28 = require("fs");
|
|
17383
17974
|
var import_node_path27 = require("path");
|
|
17975
|
+
var import_GeminiCodeAssistProjectResolver5 = require("@omnicross/core/auth/GeminiCodeAssistProjectResolver");
|
|
17384
17976
|
var import_SubscriptionAccountHealth2 = require("@omnicross/core/pipeline/SubscriptionAccountHealth");
|
|
17385
17977
|
var import_AccountAllowanceScheduling3 = require("@omnicross/core/pipeline/AccountAllowanceScheduling");
|
|
17386
|
-
var
|
|
17978
|
+
var import_upstreamFetch14 = require("@omnicross/core/pipeline/upstreamFetch");
|
|
17387
17979
|
var import_SubscriptionIdentityStore2 = require("@omnicross/core/provider-proxy/identity/SubscriptionIdentityStore");
|
|
17388
|
-
var
|
|
17980
|
+
var import_subscriptions12 = require("@omnicross/subscriptions");
|
|
17389
17981
|
|
|
17390
17982
|
// src/ports/account-sync.ts
|
|
17391
17983
|
function viewOf(tokens) {
|
|
@@ -17533,7 +18125,7 @@ var JsonSubscriptionCredentialStore = class {
|
|
|
17533
18125
|
* a plaintext token pair into `upstream-trace.jsonl`.
|
|
17534
18126
|
*/
|
|
17535
18127
|
buildRefreshFetch(providerId, accountId) {
|
|
17536
|
-
return this.fetchImpl ?? ((url, init) => (0,
|
|
18128
|
+
return this.fetchImpl ?? ((url, init) => (0, import_upstreamFetch14.fetchUpstream)(url, init, { providerId, accountId, redactBodies: true }));
|
|
17537
18129
|
}
|
|
17538
18130
|
/**
|
|
17539
18131
|
* In-flight refresh coalescing. OAuth refresh tokens are
|
|
@@ -17574,7 +18166,7 @@ var JsonSubscriptionCredentialStore = class {
|
|
|
17574
18166
|
* other hot reads. Never returns token material.
|
|
17575
18167
|
*/
|
|
17576
18168
|
getAccountProxy(providerId, accountId) {
|
|
17577
|
-
if (providerId !== "claude" && providerId !== "codex" && providerId !== "gemini" && providerId !== "opencodego" && providerId !== "kimi" && providerId !== "grok" && providerId !== "copilot") {
|
|
18169
|
+
if (providerId !== "claude" && providerId !== "codex" && providerId !== "gemini" && providerId !== "opencodego" && providerId !== "kimi" && providerId !== "grok" && providerId !== "copilot" && providerId !== "antigravity") {
|
|
17578
18170
|
return void 0;
|
|
17579
18171
|
}
|
|
17580
18172
|
return getAccountProxy(this.readConfig(), providerId, accountId);
|
|
@@ -17593,7 +18185,7 @@ var JsonSubscriptionCredentialStore = class {
|
|
|
17593
18185
|
const fingerprintOn = identityStore.isEnabled();
|
|
17594
18186
|
const now = Date.now();
|
|
17595
18187
|
const out = {};
|
|
17596
|
-
for (const provider of ["claude", "codex", "gemini", "opencodego", "kimi", "grok", "copilot"]) {
|
|
18188
|
+
for (const provider of ["claude", "codex", "gemini", "opencodego", "kimi", "grok", "copilot", "antigravity"]) {
|
|
17597
18189
|
const sanitized = sanitizeAccounts(config, provider);
|
|
17598
18190
|
if (sanitized.length === 0) continue;
|
|
17599
18191
|
for (const account of sanitized) {
|
|
@@ -17659,7 +18251,7 @@ var JsonSubscriptionCredentialStore = class {
|
|
|
17659
18251
|
this.materializeMigration(config);
|
|
17660
18252
|
const refreshFetch = this.buildRefreshFetch("claude", capturedId);
|
|
17661
18253
|
try {
|
|
17662
|
-
const result = await
|
|
18254
|
+
const result = await import_subscriptions12.claudeOAuth.refreshAccessToken(claude.refreshToken, refreshFetch);
|
|
17663
18255
|
const expiresAt = new Date(Date.now() + result.expiresIn * 1e3).toISOString();
|
|
17664
18256
|
const next = {
|
|
17665
18257
|
...claude,
|
|
@@ -17694,7 +18286,7 @@ var JsonSubscriptionCredentialStore = class {
|
|
|
17694
18286
|
this.materializeMigration(config);
|
|
17695
18287
|
const refreshFetch = this.buildRefreshFetch("codex", capturedId);
|
|
17696
18288
|
try {
|
|
17697
|
-
const result = await
|
|
18289
|
+
const result = await import_subscriptions12.codexOAuth.refreshAccessToken(codex.refreshToken, refreshFetch);
|
|
17698
18290
|
const expiresAt = new Date(Date.now() + result.expiresIn * 1e3).toISOString();
|
|
17699
18291
|
const next = {
|
|
17700
18292
|
...codex,
|
|
@@ -17732,7 +18324,7 @@ var JsonSubscriptionCredentialStore = class {
|
|
|
17732
18324
|
this.materializeMigration(config);
|
|
17733
18325
|
const refreshFetch = this.buildRefreshFetch("gemini", capturedId);
|
|
17734
18326
|
try {
|
|
17735
|
-
const result = await
|
|
18327
|
+
const result = await import_subscriptions12.geminiOAuth.refreshAccessToken(gemini.refreshToken, refreshFetch);
|
|
17736
18328
|
const expiresAt = new Date(Date.now() + result.expiresIn * 1e3).toISOString();
|
|
17737
18329
|
const next = {
|
|
17738
18330
|
...gemini,
|
|
@@ -17768,10 +18360,10 @@ var JsonSubscriptionCredentialStore = class {
|
|
|
17768
18360
|
this.materializeMigration(config);
|
|
17769
18361
|
const refreshFetch = this.buildRefreshFetch("kimi", capturedId);
|
|
17770
18362
|
try {
|
|
17771
|
-
const result = await
|
|
18363
|
+
const result = await import_subscriptions12.kimiOAuth.refreshAccessToken(
|
|
17772
18364
|
kimi.refreshToken,
|
|
17773
18365
|
refreshFetch,
|
|
17774
|
-
|
|
18366
|
+
import_subscriptions12.kimiOAuth.kimiFingerprintHeaders(kimi.deviceId)
|
|
17775
18367
|
);
|
|
17776
18368
|
const expiresAt = new Date(Date.now() + result.expiresIn * 1e3).toISOString();
|
|
17777
18369
|
const next = {
|
|
@@ -17808,8 +18400,8 @@ var JsonSubscriptionCredentialStore = class {
|
|
|
17808
18400
|
this.materializeMigration(config);
|
|
17809
18401
|
const refreshFetch = this.buildRefreshFetch("grok", capturedId);
|
|
17810
18402
|
try {
|
|
17811
|
-
const tokenEndpoint = await
|
|
17812
|
-
const result = await
|
|
18403
|
+
const tokenEndpoint = await import_subscriptions12.grokOAuth.resolveGrokTokenEndpoint(refreshFetch);
|
|
18404
|
+
const result = await import_subscriptions12.grokOAuth.refreshGrokAccessToken(grok.refreshToken, tokenEndpoint, refreshFetch);
|
|
17813
18405
|
const expiresAt = new Date(Date.now() + result.expiresIn * 1e3).toISOString();
|
|
17814
18406
|
const next = {
|
|
17815
18407
|
...grok,
|
|
@@ -17852,6 +18444,76 @@ var JsonSubscriptionCredentialStore = class {
|
|
|
17852
18444
|
return false;
|
|
17853
18445
|
});
|
|
17854
18446
|
}
|
|
18447
|
+
/**
|
|
18448
|
+
* Refresh the Antigravity (Google) OAuth access token. Like gemini, the
|
|
18449
|
+
* Google token endpoint does NOT return a refresh_token on refresh, so this
|
|
18450
|
+
* writes ONLY access+expiresAt (+status/lastRefreshedAt) and DELIBERATELY
|
|
18451
|
+
* preserves the stored `refreshToken` — plus the account's `projectId`
|
|
18452
|
+
* (a handshake product; the post-refresh re-validation is the refresh
|
|
18453
|
+
* scheduler's hook, not this write) and `email`. HONEST `false` when no
|
|
18454
|
+
* refresh_token.
|
|
18455
|
+
*/
|
|
18456
|
+
async refreshAntigravityToken() {
|
|
18457
|
+
return this.coalesce("antigravity:active", async () => {
|
|
18458
|
+
const config = this.readConfig();
|
|
18459
|
+
const active = getActiveAccount(config, "antigravity");
|
|
18460
|
+
const antigravity = active?.tokens;
|
|
18461
|
+
if (!active || !antigravity?.refreshToken) return false;
|
|
18462
|
+
const capturedId = active.id;
|
|
18463
|
+
this.materializeMigration(config);
|
|
18464
|
+
const refreshFetch = this.buildRefreshFetch("antigravity", capturedId);
|
|
18465
|
+
try {
|
|
18466
|
+
const result = await import_subscriptions12.antigravityOAuth.refreshAccessToken(antigravity.refreshToken, refreshFetch);
|
|
18467
|
+
const expiresAt = new Date(Date.now() + result.expiresIn * 1e3).toISOString();
|
|
18468
|
+
const next = {
|
|
18469
|
+
...antigravity,
|
|
18470
|
+
// KEEP the existing refreshToken/projectId/email.
|
|
18471
|
+
accessToken: result.accessToken,
|
|
18472
|
+
expiresAt,
|
|
18473
|
+
status: "authorized",
|
|
18474
|
+
lastRefreshedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
18475
|
+
errorMessage: void 0
|
|
18476
|
+
};
|
|
18477
|
+
this.writeBackById("antigravity", capturedId, next);
|
|
18478
|
+
await this.revalidateAntigravityProject(capturedId);
|
|
18479
|
+
return true;
|
|
18480
|
+
} catch (error) {
|
|
18481
|
+
this.markExpiredById("antigravity", capturedId, antigravity, error);
|
|
18482
|
+
return false;
|
|
18483
|
+
}
|
|
18484
|
+
});
|
|
18485
|
+
}
|
|
18486
|
+
/**
|
|
18487
|
+
* Post-refresh project re-validation hook (antigravity design D8): after a
|
|
18488
|
+
* successful antigravity token refresh, re-run the Code Assist project
|
|
18489
|
+
* handshake and write the (possibly rotated) `projectId` back to the account.
|
|
18490
|
+
* A handshake FAILURE keeps the stored projectId untouched (logged) so the
|
|
18491
|
+
* account keeps serving with the last-known-good project until a later
|
|
18492
|
+
* refresh succeeds. Returns whether the handshake produced a project.
|
|
18493
|
+
*/
|
|
18494
|
+
async revalidateAntigravityProject(accountId) {
|
|
18495
|
+
const before = getAccountById(this.readConfig(), "antigravity", accountId);
|
|
18496
|
+
const accessToken = before?.tokens?.accessToken;
|
|
18497
|
+
if (!accessToken) return false;
|
|
18498
|
+
try {
|
|
18499
|
+
const projectId = await (0, import_GeminiCodeAssistProjectResolver5.getAntigravityProjectResolver)().resolveProject(accessToken);
|
|
18500
|
+
if (projectId !== void 0) {
|
|
18501
|
+
const config = this.readConfig();
|
|
18502
|
+
const account = getAccountById(config, "antigravity", accountId);
|
|
18503
|
+
const tokens = account?.tokens;
|
|
18504
|
+
if (account && tokens?.accessToken === accessToken && tokens.projectId !== projectId) {
|
|
18505
|
+
this.writeBackById("antigravity", accountId, { ...tokens, projectId });
|
|
18506
|
+
}
|
|
18507
|
+
return true;
|
|
18508
|
+
}
|
|
18509
|
+
return false;
|
|
18510
|
+
} catch (error) {
|
|
18511
|
+
console.warn(
|
|
18512
|
+
`[JsonSubscriptionCredentialStore] antigravity project re-validation failed for account ${accountId}: ` + (error instanceof Error ? error.message : String(error))
|
|
18513
|
+
);
|
|
18514
|
+
return false;
|
|
18515
|
+
}
|
|
18516
|
+
}
|
|
17855
18517
|
/**
|
|
17856
18518
|
* Refresh a SPECIFIC managed account by id (background scheduler sweep and
|
|
17857
18519
|
* account-pool resolution). It uses only that account's stored refresh
|
|
@@ -17880,6 +18542,7 @@ var JsonSubscriptionCredentialStore = class {
|
|
|
17880
18542
|
};
|
|
17881
18543
|
if (refreshed.idToken) next.idToken = refreshed.idToken;
|
|
17882
18544
|
this.writeBackById(provider, id, next);
|
|
18545
|
+
if (provider === "antigravity") await this.revalidateAntigravityProject(id);
|
|
17883
18546
|
return true;
|
|
17884
18547
|
} catch (error) {
|
|
17885
18548
|
this.markExpiredById(provider, id, captured, error);
|
|
@@ -17904,7 +18567,7 @@ var JsonSubscriptionCredentialStore = class {
|
|
|
17904
18567
|
}
|
|
17905
18568
|
const oauth = account.tokens;
|
|
17906
18569
|
if (!oauth.accessToken) return null;
|
|
17907
|
-
if (providerId === "codex" || providerId === "gemini" || providerId === "kimi" || providerId === "grok" || providerId === "copilot") {
|
|
18570
|
+
if (providerId === "codex" || providerId === "gemini" || providerId === "kimi" || providerId === "grok" || providerId === "copilot" || providerId === "antigravity") {
|
|
17908
18571
|
const expiresAtMs = oauth.expiresAt ? Date.parse(oauth.expiresAt) : 0;
|
|
17909
18572
|
const expiringSoon = expiresAtMs > 0 && Date.now() >= expiresAtMs - ACCOUNT_REFRESH_LEAD_MS;
|
|
17910
18573
|
if (expiringSoon && oauth.refreshToken) {
|
|
@@ -17997,10 +18660,10 @@ var JsonSubscriptionCredentialStore = class {
|
|
|
17997
18660
|
if (provider === "kimi") {
|
|
17998
18661
|
const account = accountId ? getAccountById(this.readConfig(), "kimi", accountId) : void 0;
|
|
17999
18662
|
const deviceId = account?.tokens?.deviceId;
|
|
18000
|
-
const r2 = await
|
|
18663
|
+
const r2 = await import_subscriptions12.kimiOAuth.refreshAccessToken(
|
|
18001
18664
|
refreshToken,
|
|
18002
18665
|
refreshFetch,
|
|
18003
|
-
|
|
18666
|
+
import_subscriptions12.kimiOAuth.kimiFingerprintHeaders(deviceId)
|
|
18004
18667
|
);
|
|
18005
18668
|
return {
|
|
18006
18669
|
accessToken: r2.accessToken,
|
|
@@ -18009,8 +18672,8 @@ var JsonSubscriptionCredentialStore = class {
|
|
|
18009
18672
|
};
|
|
18010
18673
|
}
|
|
18011
18674
|
if (provider === "grok") {
|
|
18012
|
-
const tokenEndpoint = await
|
|
18013
|
-
const r2 = await
|
|
18675
|
+
const tokenEndpoint = await import_subscriptions12.grokOAuth.resolveGrokTokenEndpoint(refreshFetch);
|
|
18676
|
+
const r2 = await import_subscriptions12.grokOAuth.refreshGrokAccessToken(refreshToken, tokenEndpoint, refreshFetch);
|
|
18014
18677
|
return {
|
|
18015
18678
|
accessToken: r2.accessToken,
|
|
18016
18679
|
refreshToken: r2.refreshToken,
|
|
@@ -18020,7 +18683,14 @@ var JsonSubscriptionCredentialStore = class {
|
|
|
18020
18683
|
if (provider === "copilot") {
|
|
18021
18684
|
throw new Error("GitHub Copilot tokens cannot be refreshed \u2014 re-authenticate the account");
|
|
18022
18685
|
}
|
|
18023
|
-
|
|
18686
|
+
if (provider === "antigravity") {
|
|
18687
|
+
const r2 = await import_subscriptions12.antigravityOAuth.refreshAccessToken(refreshToken, refreshFetch);
|
|
18688
|
+
return {
|
|
18689
|
+
accessToken: r2.accessToken,
|
|
18690
|
+
expiresAt: new Date(Date.now() + r2.expiresIn * 1e3).toISOString()
|
|
18691
|
+
};
|
|
18692
|
+
}
|
|
18693
|
+
const flow = provider === "claude" ? import_subscriptions12.claudeOAuth : provider === "codex" ? import_subscriptions12.codexOAuth : import_subscriptions12.geminiOAuth;
|
|
18024
18694
|
const r = await flow.refreshAccessToken(refreshToken, refreshFetch);
|
|
18025
18695
|
return {
|
|
18026
18696
|
accessToken: r.accessToken,
|
|
@@ -18263,7 +18933,7 @@ var JsonSubscriptionCredentialStore = class {
|
|
|
18263
18933
|
};
|
|
18264
18934
|
|
|
18265
18935
|
// src/AccountHealthProbeScheduler.ts
|
|
18266
|
-
var
|
|
18936
|
+
var import_upstreamFetch15 = require("@omnicross/core/pipeline/upstreamFetch");
|
|
18267
18937
|
|
|
18268
18938
|
// src/probe/CodexGenerationProbe.ts
|
|
18269
18939
|
var import_codexCliHeaders = require("@omnicross/core/provider-proxy/identity/codexCliHeaders");
|
|
@@ -18415,7 +19085,11 @@ var PROVIDER_PROBE_PLANS = {
|
|
|
18415
19085
|
// The Copilot quota endpoint (copilot_internal/user) is a verified FREE
|
|
18416
19086
|
// authed GET but lives on api.github.com with its own auth dialect and a
|
|
18417
19087
|
// monthly-only window — the allowance collector owns the health surface.
|
|
18418
|
-
copilot: { kind: "local" }
|
|
19088
|
+
copilot: { kind: "local" },
|
|
19089
|
+
// Antigravity's quota endpoints are POST RPCs on daily-cloudcode-pa (not a
|
|
19090
|
+
// cheap GET) and need the antigravity/hub UA — the allowance collector owns
|
|
19091
|
+
// the health surface; the probe stays local.
|
|
19092
|
+
antigravity: { kind: "local" }
|
|
18419
19093
|
};
|
|
18420
19094
|
function probePlanFor(providerId) {
|
|
18421
19095
|
return PROVIDER_PROBE_PLANS[providerId] ?? { kind: "local" };
|
|
@@ -18437,7 +19111,7 @@ var AccountHealthProbeScheduler = class {
|
|
|
18437
19111
|
this.logger = logger;
|
|
18438
19112
|
this.config = config;
|
|
18439
19113
|
this.now = opts.now ?? Date.now;
|
|
18440
|
-
this.fetchImpl = opts.fetchImpl ??
|
|
19114
|
+
this.fetchImpl = opts.fetchImpl ?? import_upstreamFetch15.fetchUpstream;
|
|
18441
19115
|
this.sleep = opts.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
|
|
18442
19116
|
this.planFor = opts.planFor ?? probePlanFor;
|
|
18443
19117
|
}
|
|
@@ -19593,7 +20267,7 @@ var AuditWriter = class {
|
|
|
19593
20267
|
var import_node_fs34 = require("fs");
|
|
19594
20268
|
var import_node_crypto24 = require("crypto");
|
|
19595
20269
|
var import_node_path34 = require("path");
|
|
19596
|
-
var
|
|
20270
|
+
var import_upstreamFetch16 = require("@omnicross/core/pipeline/upstreamFetch");
|
|
19597
20271
|
|
|
19598
20272
|
// src/billing/billingFiles.ts
|
|
19599
20273
|
var BILLING_FILE_RE = /^billing-(\d{4})-(\d{2})-(\d{2})\.jsonl$/;
|
|
@@ -19616,7 +20290,7 @@ var BillingPublisher = class {
|
|
|
19616
20290
|
constructor(billingDir, logger, opts = {}) {
|
|
19617
20291
|
this.billingDir = billingDir;
|
|
19618
20292
|
this.logger = logger;
|
|
19619
|
-
this.fetchImpl = opts.fetchImpl ?? ((url, init) => (0,
|
|
20293
|
+
this.fetchImpl = opts.fetchImpl ?? ((url, init) => (0, import_upstreamFetch16.fetchUpstream)(url, init));
|
|
19620
20294
|
this.defer = opts.defer ?? ((fn) => setTimeout(fn, 0));
|
|
19621
20295
|
this.timeoutMs = opts.timeoutMs ?? BILLING_POST_TIMEOUT_MS;
|
|
19622
20296
|
this.now = opts.now ?? Date.now;
|
|
@@ -19866,7 +20540,7 @@ var BillingRetrySweeper = class {
|
|
|
19866
20540
|
// src/TokenRefreshScheduler.ts
|
|
19867
20541
|
var REFRESH_LEAD_MS2 = 5 * 6e4;
|
|
19868
20542
|
var SWEEP_INTERVAL_MS5 = 6e4;
|
|
19869
|
-
var OAUTH_PROVIDERS2 = ["claude", "codex", "gemini", "kimi", "grok", "copilot"];
|
|
20543
|
+
var OAUTH_PROVIDERS2 = ["claude", "codex", "gemini", "kimi", "grok", "copilot", "antigravity"];
|
|
19870
20544
|
var TokenRefreshScheduler = class {
|
|
19871
20545
|
constructor(store, logger, intervalMs = SWEEP_INTERVAL_MS5, leadMs = REFRESH_LEAD_MS2) {
|
|
19872
20546
|
this.store = store;
|
|
@@ -19957,6 +20631,8 @@ var TokenRefreshScheduler = class {
|
|
|
19957
20631
|
// never reaches this — the branch exists for union totality.
|
|
19958
20632
|
case "copilot":
|
|
19959
20633
|
return this.store.refreshCopilotToken();
|
|
20634
|
+
case "antigravity":
|
|
20635
|
+
return this.store.refreshAntigravityToken();
|
|
19960
20636
|
}
|
|
19961
20637
|
}
|
|
19962
20638
|
};
|
|
@@ -20033,7 +20709,7 @@ function createRouteLeaseSubscriptionPreflight(credentials) {
|
|
|
20033
20709
|
|
|
20034
20710
|
// src/webhook/WebhookDispatcher.ts
|
|
20035
20711
|
var import_node_crypto25 = require("crypto");
|
|
20036
|
-
var
|
|
20712
|
+
var import_upstreamFetch17 = require("@omnicross/core/pipeline/upstreamFetch");
|
|
20037
20713
|
var WEBHOOK_MAX_ATTEMPTS = 3;
|
|
20038
20714
|
var WEBHOOK_QUEUE_MAX = 1e3;
|
|
20039
20715
|
var WEBHOOK_SEND_TIMEOUT_MS = 1e4;
|
|
@@ -20053,7 +20729,7 @@ var WebhookDispatcher = class {
|
|
|
20053
20729
|
sleep;
|
|
20054
20730
|
now;
|
|
20055
20731
|
constructor(opts = {}) {
|
|
20056
|
-
this.fetchImpl = opts.fetchImpl ?? ((url, init) => (0,
|
|
20732
|
+
this.fetchImpl = opts.fetchImpl ?? ((url, init) => (0, import_upstreamFetch17.fetchUpstream)(url, init));
|
|
20057
20733
|
this.logger = opts.logger;
|
|
20058
20734
|
this.maxAttempts = opts.maxAttempts ?? WEBHOOK_MAX_ATTEMPTS;
|
|
20059
20735
|
this.queueMax = opts.queueMax ?? WEBHOOK_QUEUE_MAX;
|
|
@@ -20139,8 +20815,8 @@ var WebhookDispatcher = class {
|
|
|
20139
20815
|
signal: AbortSignal.timeout(this.timeoutMs)
|
|
20140
20816
|
});
|
|
20141
20817
|
return res.ok ? { ok: true, status: res.status } : { ok: false, status: res.status };
|
|
20142
|
-
} catch (
|
|
20143
|
-
return { ok: false, error:
|
|
20818
|
+
} catch (err9) {
|
|
20819
|
+
return { ok: false, error: err9 instanceof Error ? err9.message : String(err9) };
|
|
20144
20820
|
}
|
|
20145
20821
|
}
|
|
20146
20822
|
/**
|
|
@@ -20277,12 +20953,12 @@ function buildDaemon(config, paths) {
|
|
|
20277
20953
|
setSecretBox(secretBox3);
|
|
20278
20954
|
setSecretBox2(secretBox3);
|
|
20279
20955
|
const decryptedConfig = decryptConfigSecrets(config, secretBox3);
|
|
20280
|
-
const accountAllowanceStore = new
|
|
20956
|
+
const accountAllowanceStore = new import_AccountAllowanceStore11.AccountAllowanceStore(
|
|
20281
20957
|
Date.now,
|
|
20282
20958
|
void 0,
|
|
20283
20959
|
new JsonAccountAllowancePersistence(defaultAccountAllowancePath(paths.configPath))
|
|
20284
20960
|
);
|
|
20285
|
-
(0,
|
|
20961
|
+
(0, import_AccountAllowanceStore11.setSharedAccountAllowanceStore)(accountAllowanceStore);
|
|
20286
20962
|
(0, import_AccountAllowanceScheduling5.getSharedAccountAllowanceScheduling)().configure(
|
|
20287
20963
|
(0, import_outbound_api10.normalizeServerConfig)(decryptedConfig.server).allowanceScheduling
|
|
20288
20964
|
);
|
|
@@ -20307,20 +20983,22 @@ function buildDaemon(config, paths) {
|
|
|
20307
20983
|
claudeAllowanceRefreshScheduler.configure(
|
|
20308
20984
|
(0, import_outbound_api10.normalizeServerConfig)(decryptedConfig.server).allowanceScheduling
|
|
20309
20985
|
);
|
|
20310
|
-
const subscriptionAccounts = new
|
|
20311
|
-
(0,
|
|
20312
|
-
const subscriptionRegistry = new
|
|
20986
|
+
const subscriptionAccounts = new import_subscriptions13.SubscriptionAccountService(credentialStore);
|
|
20987
|
+
(0, import_subscriptions13.setSubscriptionAccountService)(subscriptionAccounts);
|
|
20988
|
+
const subscriptionRegistry = new import_subscriptions13.SubscriptionProviderRegistry(
|
|
20313
20989
|
subscriptionAccounts,
|
|
20314
20990
|
credentialStore
|
|
20315
20991
|
);
|
|
20316
|
-
(0,
|
|
20992
|
+
(0, import_subscriptions13.setSubscriptionProviderRegistry)(subscriptionRegistry);
|
|
20317
20993
|
setServerProxyConfig(decryptedConfig.server?.proxy);
|
|
20318
|
-
(0,
|
|
20994
|
+
(0, import_upstreamFetch18.setUpstreamProxyResolver)(
|
|
20319
20995
|
createUpstreamProxyResolver({
|
|
20320
20996
|
getAccountProxy: (providerId, accountId) => credentialStore.getAccountProxy(providerId, accountId)
|
|
20321
20997
|
})
|
|
20322
20998
|
);
|
|
20323
|
-
(0, import_gemini_code_assist_resolver.setGeminiCodeAssistResolver)((0,
|
|
20999
|
+
(0, import_gemini_code_assist_resolver.setGeminiCodeAssistResolver)((0, import_GeminiCodeAssistProjectResolver6.getGeminiCodeAssistProjectResolver)());
|
|
21000
|
+
(0, import_antigravityFailover.setAntigravitySandboxFailover)(decryptedConfig.antigravity?.sandboxFailover === true);
|
|
21001
|
+
(0, import_openCodeGoHeaders2.setOpenCodeGoUserAgent)(decryptedConfig.opencodego?.userAgent ?? null);
|
|
20324
21002
|
const autoDisableStore = new AutoDisableStore();
|
|
20325
21003
|
const providerKeyQuotaService = new ProviderKeyQuotaService(secretBox3);
|
|
20326
21004
|
const apiKeyPool = new import_ApiKeyPoolService.ApiKeyPoolService(
|
|
@@ -20339,7 +21017,7 @@ function buildDaemon(config, paths) {
|
|
|
20339
21017
|
const pricingEngine = new import_usage2.PricingEngine(pricingStore, logger, {
|
|
20340
21018
|
// Catalog egress follows the same global/env proxy policy as every other
|
|
20341
21019
|
// daemon upstream call; no provider/account override applies here.
|
|
20342
|
-
fetchImpl: ((input, init) => (0,
|
|
21020
|
+
fetchImpl: ((input, init) => (0, import_upstreamFetch18.fetchUpstream)(String(input), init ?? {}))
|
|
20343
21021
|
});
|
|
20344
21022
|
const pricingRefreshScheduler = new PricingRefreshScheduler(
|
|
20345
21023
|
pricingEngine,
|
|
@@ -20624,7 +21302,7 @@ function buildDaemon(config, paths) {
|
|
|
20624
21302
|
// — `server.proxy.byProvider[...]` was silently skipped — and the call was
|
|
20625
21303
|
// excluded from the upstream trace, so a failing login left no evidence.
|
|
20626
21304
|
// `redactBodies` keeps the code/verifier + minted token out of that trace.
|
|
20627
|
-
oauthExchangeFetch: paths.oauthExchangeFetch ? () => paths.oauthExchangeFetch : (providerId) => (url, init) => (0,
|
|
21305
|
+
oauthExchangeFetch: paths.oauthExchangeFetch ? () => paths.oauthExchangeFetch : (providerId) => (url, init) => (0, import_upstreamFetch18.fetchUpstream)(url, init, { providerId, redactBodies: true }),
|
|
20628
21306
|
subscriptionAccountAppender: credentialStore,
|
|
20629
21307
|
// Codex interactive OAuth (app-parity-2 child 5) — the async loopback flow store
|
|
20630
21308
|
// + the one-shot 127.0.0.1:1455 listener. Token captured + persisted daemon-side;
|
|
@@ -20639,6 +21317,21 @@ function buildDaemon(config, paths) {
|
|
|
20639
21317
|
// Grok interactive OAuth — the same async DEVICE-CODE shape as kimi.
|
|
20640
21318
|
grokSessions: new CodexOAuthSessionStore(),
|
|
20641
21319
|
copilotSessions: new CodexOAuthSessionStore(),
|
|
21320
|
+
// Antigravity interactive OAuth — the async LOOPBACK flow store + the
|
|
21321
|
+
// one-shot 127.0.0.1:51121 listener (same shape as codex; test seam below).
|
|
21322
|
+
antigravitySessions: new CodexOAuthSessionStore(),
|
|
21323
|
+
antigravityAwaitLoopback: paths.antigravityAwaitLoopback ?? ((state, timeoutMs, signal) => awaitLoopbackCode(state, timeoutMs, signal, {
|
|
21324
|
+
port: 51121,
|
|
21325
|
+
path: "/oauth-callback",
|
|
21326
|
+
label: "antigravity"
|
|
21327
|
+
})),
|
|
21328
|
+
// The dynamic model-catalog probe's token source (the ACTIVE antigravity
|
|
21329
|
+
// account; refreshed by the by-id near-expiry seam inside the lookup).
|
|
21330
|
+
resolveAntigravityAccessToken: async () => {
|
|
21331
|
+
const config2 = await credentialStore.getFullConfig();
|
|
21332
|
+
const activeId = config2.activeAntigravityAccountId ?? config2.antigravityAccounts?.[0]?.id;
|
|
21333
|
+
return activeId ? credentialStore.getAccessTokenForAccount("antigravity", activeId) : null;
|
|
21334
|
+
},
|
|
20642
21335
|
// Migration pack (app-parity child 6, design D2/D3) — the concrete credential
|
|
20643
21336
|
// store provides BOTH the full DECRYPTED read (`getFullConfig`, export) and
|
|
20644
21337
|
// the multi-account append (`appendProviderAccount`, import re-encrypts at-
|
|
@@ -20697,7 +21390,7 @@ function buildDaemon(config, paths) {
|
|
|
20697
21390
|
});
|
|
20698
21391
|
const webhookDispatcher = new WebhookDispatcher({
|
|
20699
21392
|
logger,
|
|
20700
|
-
fetchImpl: (url, init) => (0,
|
|
21393
|
+
fetchImpl: (url, init) => (0, import_upstreamFetch18.fetchUpstream)(url, init)
|
|
20701
21394
|
});
|
|
20702
21395
|
setWebhookRuntime(webhookDispatcher, (0, import_SubscriptionAccountHealth4.getSharedAccountHealth)());
|
|
20703
21396
|
const auditWriter = new AuditWriter(auditDir, logger);
|
|
@@ -20832,15 +21525,59 @@ function buildClaudeDoctorChecks(config) {
|
|
|
20832
21525
|
});
|
|
20833
21526
|
return checks;
|
|
20834
21527
|
}
|
|
21528
|
+
function buildAntigravityDoctorChecks(snapshot) {
|
|
21529
|
+
const checks = [];
|
|
21530
|
+
checks.push({
|
|
21531
|
+
name: "antigravity credential",
|
|
21532
|
+
ok: snapshot.accountCount > 0 && snapshot.hasAccessToken,
|
|
21533
|
+
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"}`
|
|
21534
|
+
});
|
|
21535
|
+
const expiresAtMs = snapshot.expiresAt ? Date.parse(snapshot.expiresAt) : 0;
|
|
21536
|
+
const expired = snapshot.expired || expiresAtMs > 0 && Date.now() >= expiresAtMs;
|
|
21537
|
+
const expiringSoon = expiresAtMs > 0 && Date.now() >= expiresAtMs - 10 * 6e4;
|
|
21538
|
+
checks.push({
|
|
21539
|
+
name: "token freshness",
|
|
21540
|
+
ok: !expired,
|
|
21541
|
+
warn: !expired && expiringSoon,
|
|
21542
|
+
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)"
|
|
21543
|
+
});
|
|
21544
|
+
return checks;
|
|
21545
|
+
}
|
|
21546
|
+
function hasFreshAntigravityQuota(snapshot, now = Date.now()) {
|
|
21547
|
+
if (!snapshot || snapshot.lastErrorCode) return false;
|
|
21548
|
+
if (snapshot.expiresAt && !(Date.parse(snapshot.expiresAt) > now)) return false;
|
|
21549
|
+
return snapshot.windows.some(
|
|
21550
|
+
(window) => window.state === "fresh" && (!window.resetsAt || Date.parse(window.resetsAt) > now) && (window.disabled === true || typeof window.usedPercent === "number" && Number.isFinite(window.usedPercent))
|
|
21551
|
+
);
|
|
21552
|
+
}
|
|
21553
|
+
function buildAntigravityLiveChecks(result) {
|
|
21554
|
+
return [
|
|
21555
|
+
{
|
|
21556
|
+
name: "token refresh (--live)",
|
|
21557
|
+
ok: result.refreshOk,
|
|
21558
|
+
detail: result.refreshOk ? "the active account refreshed successfully" : "refresh failed (see the daemon log)"
|
|
21559
|
+
},
|
|
21560
|
+
{
|
|
21561
|
+
name: "quota collection (--live)",
|
|
21562
|
+
ok: result.quotaOk,
|
|
21563
|
+
detail: result.quotaOk ? "quotaSummary windows collected" : result.detail
|
|
21564
|
+
}
|
|
21565
|
+
];
|
|
21566
|
+
}
|
|
20835
21567
|
function buildImagesDoctorChecks(snapshot) {
|
|
20836
21568
|
const enabled = snapshot.config.enabled;
|
|
20837
|
-
const
|
|
21569
|
+
const routed = snapshot.config.routedProviders ?? ["codex-subscription"];
|
|
21570
|
+
const codexRouted = routed.includes("codex-subscription");
|
|
21571
|
+
const antigravityRouted = routed.includes("antigravity-subscription");
|
|
21572
|
+
const antigravity = snapshot.antigravityAccount ?? { present: false, usable: false, reason: "missing" };
|
|
21573
|
+
const accountOk = !enabled || !codexRouted || snapshot.account.usable;
|
|
21574
|
+
const antigravityOk = !enabled || !antigravityRouted || antigravity.usable;
|
|
20838
21575
|
const evidenceOk = !enabled || snapshot.evidence.valid && snapshot.evidence.freshEntries > 0;
|
|
20839
21576
|
return [
|
|
20840
21577
|
{
|
|
20841
21578
|
name: "normalized Images config",
|
|
20842
21579
|
ok: snapshot.config.valid,
|
|
20843
|
-
detail: snapshot.config.valid ? `enabled=${enabled},
|
|
21580
|
+
detail: snapshot.config.valid ? `enabled=${enabled}, providers=${routed.join("+")}, default=${snapshot.config.model} (${snapshot.config.provider})` : `invalid normalized configuration (${snapshot.config.errorCount} issue(s))`
|
|
20844
21581
|
},
|
|
20845
21582
|
{
|
|
20846
21583
|
name: "private roots",
|
|
@@ -20861,8 +21598,14 @@ function buildImagesDoctorChecks(snapshot) {
|
|
|
20861
21598
|
{
|
|
20862
21599
|
name: "Codex account",
|
|
20863
21600
|
ok: accountOk,
|
|
20864
|
-
warn: !snapshot.account.usable,
|
|
20865
|
-
detail: snapshot.account.usable ? "eligible local credential is present" : `${snapshot.account.reason};
|
|
21601
|
+
warn: enabled && codexRouted && !snapshot.account.usable,
|
|
21602
|
+
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`
|
|
21603
|
+
},
|
|
21604
|
+
{
|
|
21605
|
+
name: "Antigravity account",
|
|
21606
|
+
ok: antigravityOk,
|
|
21607
|
+
warn: enabled && antigravityRouted && !antigravity.usable,
|
|
21608
|
+
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`
|
|
20866
21609
|
},
|
|
20867
21610
|
{
|
|
20868
21611
|
name: "cached capability evidence",
|
|
@@ -20877,6 +21620,12 @@ async function runImagesLiveDoctor(config, doctor, signal = new AbortController(
|
|
|
20877
21620
|
" [\u26A0] live Images verification may consume subscription quota; one minimal low-quality PNG request will be sent"
|
|
20878
21621
|
);
|
|
20879
21622
|
const result = await doctor.verifyLive(config.images ?? import_outbound_api12.DEFAULT_IMAGES_SERVER_CONFIG, signal);
|
|
21623
|
+
const antigravityRouted = Object.values(config.images?.models ?? {}).includes("antigravity-subscription");
|
|
21624
|
+
if (antigravityRouted) {
|
|
21625
|
+
console.info(
|
|
21626
|
+
" [i] live verification covers the Codex wire only; the Antigravity provider has no independent verifier in v1 (its first real request bootstraps)"
|
|
21627
|
+
);
|
|
21628
|
+
}
|
|
20880
21629
|
if (!result.ok) {
|
|
20881
21630
|
console.info(` [\u2717] live Images verification: ${result.code}`);
|
|
20882
21631
|
return false;
|
|
@@ -21011,14 +21760,49 @@ async function runLiveProbe(url, key, fetchImpl = fetch) {
|
|
|
21011
21760
|
status: res.status,
|
|
21012
21761
|
estimateHeader: res.headers.get("x-omnicross-count-estimate")
|
|
21013
21762
|
};
|
|
21014
|
-
} catch (
|
|
21763
|
+
} catch (err9) {
|
|
21015
21764
|
return {
|
|
21016
21765
|
status: null,
|
|
21017
21766
|
estimateHeader: null,
|
|
21018
|
-
error:
|
|
21767
|
+
error: err9 instanceof Error ? err9.message : String(err9)
|
|
21019
21768
|
};
|
|
21020
21769
|
}
|
|
21021
21770
|
}
|
|
21771
|
+
async function runAntigravityDoctor(daemon, live) {
|
|
21772
|
+
const config = await daemon.credentialStore.getFullConfig();
|
|
21773
|
+
const accounts = config.antigravityAccounts ?? [];
|
|
21774
|
+
const activeId = config.activeAntigravityAccountId ?? accounts[0]?.id;
|
|
21775
|
+
const active = accounts.find((account) => account.id === activeId);
|
|
21776
|
+
const snapshot = {
|
|
21777
|
+
accountCount: accounts.length,
|
|
21778
|
+
...active?.tokens.email ? { activeEmail: active.tokens.email } : {},
|
|
21779
|
+
hasAccessToken: Boolean(active?.tokens.accessToken),
|
|
21780
|
+
expired: active?.tokens.status === "expired",
|
|
21781
|
+
...active?.tokens.expiresAt ? { expiresAt: active.tokens.expiresAt } : {}
|
|
21782
|
+
};
|
|
21783
|
+
const checks = buildAntigravityDoctorChecks(snapshot);
|
|
21784
|
+
if (live && active) {
|
|
21785
|
+
const refreshOk = await daemon.credentialStore.refreshAntigravityToken();
|
|
21786
|
+
let quotaOk = false;
|
|
21787
|
+
let detail = "quotaSummary collection produced no usable windows";
|
|
21788
|
+
try {
|
|
21789
|
+
const snapshots = await daemon.accountAllowanceService.refreshAntigravity(active.id);
|
|
21790
|
+
quotaOk = hasFreshAntigravityQuota(snapshots.find((entry) => entry.accountId === active.id));
|
|
21791
|
+
if (!quotaOk) detail = snapshots[0]?.lastErrorCode ?? detail;
|
|
21792
|
+
} catch (error) {
|
|
21793
|
+
detail = error instanceof Error ? error.message : String(error);
|
|
21794
|
+
}
|
|
21795
|
+
checks.push(...buildAntigravityLiveChecks({ refreshOk, quotaOk, detail }));
|
|
21796
|
+
}
|
|
21797
|
+
console.info("omnicross doctor antigravity \u2014 subscription credential health");
|
|
21798
|
+
let hardFailure = false;
|
|
21799
|
+
for (const check of checks) {
|
|
21800
|
+
const mark = check.ok ? check.warn ? "\u26A0" : "\u2713" : "\u2717";
|
|
21801
|
+
if (!check.ok) hardFailure = true;
|
|
21802
|
+
console.info(` [${mark}] ${check.name}: ${check.detail}`);
|
|
21803
|
+
}
|
|
21804
|
+
return hardFailure ? 1 : 0;
|
|
21805
|
+
}
|
|
21022
21806
|
async function runDoctor(argv, fetchImpl = fetch) {
|
|
21023
21807
|
const { values, positionals } = (0, import_node_util2.parseArgs)({
|
|
21024
21808
|
args: argv,
|
|
@@ -21032,8 +21816,8 @@ async function runDoctor(argv, fetchImpl = fetch) {
|
|
|
21032
21816
|
allowPositionals: true
|
|
21033
21817
|
});
|
|
21034
21818
|
const subject = positionals[0] ?? "claude";
|
|
21035
|
-
if (subject !== "claude" && subject !== "images" && subject !== "search") {
|
|
21036
|
-
throw new Error(`doctor: unknown subject '${subject}' (supported: 'claude', 'images', 'search')`);
|
|
21819
|
+
if (subject !== "claude" && subject !== "images" && subject !== "search" && subject !== "antigravity") {
|
|
21820
|
+
throw new Error(`doctor: unknown subject '${subject}' (supported: 'claude', 'images', 'search', 'antigravity')`);
|
|
21037
21821
|
}
|
|
21038
21822
|
const configPath = values.config;
|
|
21039
21823
|
if (!configPath) {
|
|
@@ -21056,6 +21840,9 @@ async function runDoctor(argv, fetchImpl = fetch) {
|
|
|
21056
21840
|
runtime: daemon.searchRuntime
|
|
21057
21841
|
});
|
|
21058
21842
|
}
|
|
21843
|
+
if (subject === "antigravity") {
|
|
21844
|
+
return await runAntigravityDoctor(daemon, values.live === true);
|
|
21845
|
+
}
|
|
21059
21846
|
const checks = subject === "images" ? buildImagesDoctorChecks(await daemon.imageDoctor.inspectLocal(
|
|
21060
21847
|
serverConfig.images ?? import_outbound_api12.DEFAULT_IMAGES_SERVER_CONFIG
|
|
21061
21848
|
)) : buildClaudeDoctorChecks(serverConfig);
|
|
@@ -21422,9 +22209,9 @@ async function runLaunch(argv, deps) {
|
|
|
21422
22209
|
await daemon.llmConfig.ready();
|
|
21423
22210
|
await daemon.migrateUsageStore();
|
|
21424
22211
|
await daemon.providerProxy.start();
|
|
21425
|
-
} catch (
|
|
22212
|
+
} catch (err9) {
|
|
21426
22213
|
await shutdownLaunchDaemon(daemon);
|
|
21427
|
-
throw
|
|
22214
|
+
throw err9;
|
|
21428
22215
|
}
|
|
21429
22216
|
let launch;
|
|
21430
22217
|
try {
|
|
@@ -21432,9 +22219,9 @@ async function runLaunch(argv, deps) {
|
|
|
21432
22219
|
providerId: values.provider,
|
|
21433
22220
|
model: values.model
|
|
21434
22221
|
});
|
|
21435
|
-
} catch (
|
|
22222
|
+
} catch (err9) {
|
|
21436
22223
|
await shutdownLaunchDaemon(daemon);
|
|
21437
|
-
throw
|
|
22224
|
+
throw err9;
|
|
21438
22225
|
}
|
|
21439
22226
|
try {
|
|
21440
22227
|
const plan = buildCliSpawnPlan({
|
|
@@ -21539,9 +22326,9 @@ function spawnCliInherit(plan) {
|
|
|
21539
22326
|
process.removeListener("SIGINT", onSignal);
|
|
21540
22327
|
process.removeListener("SIGTERM", onSignal);
|
|
21541
22328
|
};
|
|
21542
|
-
child.on("error", (
|
|
22329
|
+
child.on("error", (err9) => {
|
|
21543
22330
|
detach();
|
|
21544
|
-
if (
|
|
22331
|
+
if (err9.code === "ENOENT") {
|
|
21545
22332
|
reject(
|
|
21546
22333
|
new Error(
|
|
21547
22334
|
`launch: "${plan.command}" not found on PATH \u2014 install the CLI first.`
|
|
@@ -21549,7 +22336,7 @@ function spawnCliInherit(plan) {
|
|
|
21549
22336
|
);
|
|
21550
22337
|
return;
|
|
21551
22338
|
}
|
|
21552
|
-
reject(
|
|
22339
|
+
reject(err9);
|
|
21553
22340
|
});
|
|
21554
22341
|
child.on("exit", (code, signal) => {
|
|
21555
22342
|
detach();
|
|
@@ -21562,9 +22349,10 @@ function spawnCliInherit(plan) {
|
|
|
21562
22349
|
var import_node_child_process3 = require("child_process");
|
|
21563
22350
|
var import_node_readline2 = require("readline");
|
|
21564
22351
|
var import_node_util7 = require("util");
|
|
21565
|
-
var
|
|
21566
|
-
var
|
|
21567
|
-
var
|
|
22352
|
+
var import_GeminiCodeAssistProjectResolver7 = require("@omnicross/core/auth/GeminiCodeAssistProjectResolver");
|
|
22353
|
+
var import_upstreamFetch19 = require("@omnicross/core/pipeline/upstreamFetch");
|
|
22354
|
+
var import_subscriptions14 = require("@omnicross/subscriptions");
|
|
22355
|
+
var PROVIDERS2 = ["claude", "codex", "gemini", "kimi", "grok", "copilot", "antigravity"];
|
|
21568
22356
|
async function runLogin(argv, deps) {
|
|
21569
22357
|
const { values, positionals } = (0, import_node_util7.parseArgs)({
|
|
21570
22358
|
args: argv,
|
|
@@ -21591,11 +22379,11 @@ async function runLogin(argv, deps) {
|
|
|
21591
22379
|
if (values.enterprise !== void 0 && provider !== "copilot") {
|
|
21592
22380
|
throw new Error("login: --enterprise is only supported for the copilot provider");
|
|
21593
22381
|
}
|
|
21594
|
-
const enterpriseDomain = values.enterprise !== void 0 ?
|
|
22382
|
+
const enterpriseDomain = values.enterprise !== void 0 ? import_subscriptions14.copilotOAuth.normalizeCopilotEnterpriseDomain(values.enterprise) : void 0;
|
|
21595
22383
|
const resolved = {
|
|
21596
22384
|
openBrowser: deps?.openBrowser ?? openBrowser,
|
|
21597
22385
|
promptPaste: deps?.promptPaste ?? promptPaste,
|
|
21598
|
-
awaitLoopback: deps?.awaitLoopback ?? ((state) => awaitLoopbackCode(state)),
|
|
22386
|
+
awaitLoopback: deps?.awaitLoopback ?? ((state, timeoutMs, signal, binding) => awaitLoopbackCode(state, timeoutMs, signal, binding)),
|
|
21599
22387
|
awaitKimiDevice: deps?.awaitKimiDevice ?? ((fetchImpl) => runKimiDeviceFlow(fetchImpl, resolvedOpenBrowser)),
|
|
21600
22388
|
awaitGrokDevice: deps?.awaitGrokDevice ?? ((fetchImpl) => runGrokDeviceFlow(fetchImpl, resolvedOpenBrowser)),
|
|
21601
22389
|
awaitCopilotDevice: deps?.awaitCopilotDevice ?? ((fetchImpl, enterpriseUrl) => runCopilotDeviceFlow(fetchImpl, resolvedOpenBrowser, enterpriseUrl)),
|
|
@@ -21604,10 +22392,10 @@ async function runLogin(argv, deps) {
|
|
|
21604
22392
|
const resolvedOpenBrowser = resolved.openBrowser;
|
|
21605
22393
|
const box = resolveSecretBox(values["master-key-file"]);
|
|
21606
22394
|
setSecretBox(box);
|
|
21607
|
-
(0,
|
|
22395
|
+
(0, import_upstreamFetch19.setUpstreamProxyResolver)(createUpstreamProxyResolver());
|
|
21608
22396
|
try {
|
|
21609
22397
|
const tokensPath = defaultTokensPath(values.config);
|
|
21610
|
-
const exchangeFetch = resolved.tokensFetch ?? ((url, init) => (0,
|
|
22398
|
+
const exchangeFetch = resolved.tokensFetch ?? ((url, init) => (0, import_upstreamFetch19.fetchUpstream)(url, init, { providerId: provider, redactBodies: true }));
|
|
21611
22399
|
const store = new JsonSubscriptionCredentialStore(tokensPath, box, exchangeFetch);
|
|
21612
22400
|
const expiresAt = await runProviderLogin(
|
|
21613
22401
|
provider,
|
|
@@ -21621,7 +22409,7 @@ async function runLogin(argv, deps) {
|
|
|
21621
22409
|
console.info(` token: [stored, encrypted] expiresAt: ${expiresAt ?? "n/a"}`);
|
|
21622
22410
|
} finally {
|
|
21623
22411
|
setSecretBox(null);
|
|
21624
|
-
(0,
|
|
22412
|
+
(0, import_upstreamFetch19.setUpstreamProxyResolver)(null);
|
|
21625
22413
|
}
|
|
21626
22414
|
}
|
|
21627
22415
|
async function runProviderLogin(provider, store, deps, exchangeFetch, label, enterpriseUrl) {
|
|
@@ -21630,13 +22418,14 @@ async function runProviderLogin(provider, store, deps, exchangeFetch, label, ent
|
|
|
21630
22418
|
if (provider === "kimi") return loginKimi(store, deps, exchangeFetch, label);
|
|
21631
22419
|
if (provider === "grok") return loginGrok(store, deps, exchangeFetch, label);
|
|
21632
22420
|
if (provider === "copilot") return loginCopilot(store, deps, exchangeFetch, label, enterpriseUrl);
|
|
22421
|
+
if (provider === "antigravity") return loginAntigravity(store, deps, exchangeFetch, label);
|
|
21633
22422
|
return loginGemini(store, deps, exchangeFetch, label);
|
|
21634
22423
|
}
|
|
21635
22424
|
async function loginCodex(store, deps, exchangeFetch, label) {
|
|
21636
|
-
const { authUrl, codeVerifier, state } =
|
|
22425
|
+
const { authUrl, codeVerifier, state } = import_subscriptions14.codexOAuth.generateAuthParams();
|
|
21637
22426
|
await presentUrl(authUrl, deps);
|
|
21638
22427
|
const code = await deps.awaitLoopback(state);
|
|
21639
|
-
const result = await
|
|
22428
|
+
const result = await import_subscriptions14.codexOAuth.exchangeCodeForTokens(
|
|
21640
22429
|
{ authorizationCode: code, codeVerifier, state },
|
|
21641
22430
|
exchangeFetch
|
|
21642
22431
|
);
|
|
@@ -21655,7 +22444,7 @@ async function loginCodex(store, deps, exchangeFetch, label) {
|
|
|
21655
22444
|
return expiresAt;
|
|
21656
22445
|
}
|
|
21657
22446
|
async function loginClaude(store, deps, exchangeFetch, label) {
|
|
21658
|
-
const { authUrl, codeVerifier, state } =
|
|
22447
|
+
const { authUrl, codeVerifier, state } = import_subscriptions14.claudeOAuth.generateAuthParams();
|
|
21659
22448
|
await presentUrl(authUrl, deps);
|
|
21660
22449
|
const pasted = (await deps.promptPaste("Paste the authorization code (code#state): ")).trim();
|
|
21661
22450
|
const [code, pastedState] = pasted.split("#");
|
|
@@ -21663,7 +22452,7 @@ async function loginClaude(store, deps, exchangeFetch, label) {
|
|
|
21663
22452
|
if (pastedState && pastedState !== state) {
|
|
21664
22453
|
throw new Error("login: pasted state did not match (possible CSRF) \u2014 aborting");
|
|
21665
22454
|
}
|
|
21666
|
-
const result = await
|
|
22455
|
+
const result = await import_subscriptions14.claudeOAuth.exchangeCodeForTokens(
|
|
21667
22456
|
{ authorizationCode: code, codeVerifier, state },
|
|
21668
22457
|
exchangeFetch
|
|
21669
22458
|
);
|
|
@@ -21682,11 +22471,11 @@ async function loginClaude(store, deps, exchangeFetch, label) {
|
|
|
21682
22471
|
return expiresAt;
|
|
21683
22472
|
}
|
|
21684
22473
|
async function loginGemini(store, deps, exchangeFetch, label) {
|
|
21685
|
-
const { authUrl, codeVerifier } =
|
|
22474
|
+
const { authUrl, codeVerifier } = import_subscriptions14.geminiOAuth.generateAuthParams();
|
|
21686
22475
|
await presentUrl(authUrl, deps);
|
|
21687
22476
|
const code = (await deps.promptPaste("Paste the authorization code: ")).trim();
|
|
21688
22477
|
if (!code) throw new Error("login: no authorization code was pasted");
|
|
21689
|
-
const result = await
|
|
22478
|
+
const result = await import_subscriptions14.geminiOAuth.exchangeCodeForTokens(code, codeVerifier, exchangeFetch);
|
|
21690
22479
|
const expiresAt = new Date(Date.now() + result.expiresIn * 1e3).toISOString();
|
|
21691
22480
|
const block = {
|
|
21692
22481
|
authMethod: "oauth",
|
|
@@ -21701,9 +22490,9 @@ async function loginGemini(store, deps, exchangeFetch, label) {
|
|
|
21701
22490
|
return expiresAt;
|
|
21702
22491
|
}
|
|
21703
22492
|
async function runKimiDeviceFlow(exchangeFetch, openBrowserFn) {
|
|
21704
|
-
const deviceId =
|
|
21705
|
-
const fingerprint =
|
|
21706
|
-
const authorization = await
|
|
22493
|
+
const deviceId = import_subscriptions14.kimiOAuth.generateKimiDeviceId();
|
|
22494
|
+
const fingerprint = import_subscriptions14.kimiOAuth.kimiFingerprintHeaders(deviceId);
|
|
22495
|
+
const authorization = await import_subscriptions14.kimiOAuth.requestDeviceAuthorization(exchangeFetch, fingerprint);
|
|
21707
22496
|
const url = authorization.verificationUriComplete ?? authorization.verificationUri;
|
|
21708
22497
|
console.info("Open this URL in your browser and approve the request:");
|
|
21709
22498
|
console.info(` ${url}`);
|
|
@@ -21711,14 +22500,14 @@ async function runKimiDeviceFlow(exchangeFetch, openBrowserFn) {
|
|
|
21711
22500
|
console.info(` Then enter this code: ${authorization.userCode}`);
|
|
21712
22501
|
}
|
|
21713
22502
|
await openBrowserFn(url).catch(() => false);
|
|
21714
|
-
const result = await
|
|
22503
|
+
const result = await import_subscriptions14.kimiOAuth.awaitDeviceToken(authorization, exchangeFetch, {
|
|
21715
22504
|
fingerprint,
|
|
21716
22505
|
onPending: () => process.stdout.write(".")
|
|
21717
22506
|
});
|
|
21718
22507
|
console.info("");
|
|
21719
22508
|
return {
|
|
21720
22509
|
...result,
|
|
21721
|
-
accountId:
|
|
22510
|
+
accountId: import_subscriptions14.kimiOAuth.kimiAccountIdFromAccessToken(result.accessToken),
|
|
21722
22511
|
deviceId
|
|
21723
22512
|
};
|
|
21724
22513
|
}
|
|
@@ -21740,8 +22529,8 @@ async function loginKimi(store, deps, exchangeFetch, label) {
|
|
|
21740
22529
|
return expiresAt;
|
|
21741
22530
|
}
|
|
21742
22531
|
async function runGrokDeviceFlow(exchangeFetch, openBrowserFn) {
|
|
21743
|
-
const tokenEndpoint = await
|
|
21744
|
-
const authorization = await
|
|
22532
|
+
const tokenEndpoint = await import_subscriptions14.grokOAuth.resolveGrokTokenEndpoint(exchangeFetch);
|
|
22533
|
+
const authorization = await import_subscriptions14.grokOAuth.requestGrokDeviceAuthorization(exchangeFetch);
|
|
21745
22534
|
const url = authorization.verificationUriComplete ?? authorization.verificationUri;
|
|
21746
22535
|
console.info("Open this URL in your browser and approve the request:");
|
|
21747
22536
|
console.info(` ${url}`);
|
|
@@ -21749,13 +22538,13 @@ async function runGrokDeviceFlow(exchangeFetch, openBrowserFn) {
|
|
|
21749
22538
|
console.info(` Then enter this code: ${authorization.userCode}`);
|
|
21750
22539
|
}
|
|
21751
22540
|
await openBrowserFn(url).catch(() => false);
|
|
21752
|
-
const result = await
|
|
22541
|
+
const result = await import_subscriptions14.grokOAuth.awaitGrokDeviceToken(authorization, tokenEndpoint, exchangeFetch, {
|
|
21753
22542
|
onPending: () => process.stdout.write(".")
|
|
21754
22543
|
});
|
|
21755
22544
|
console.info("");
|
|
21756
22545
|
return {
|
|
21757
22546
|
...result,
|
|
21758
|
-
accountId:
|
|
22547
|
+
accountId: import_subscriptions14.grokOAuth.grokAccountIdFromAccessToken(result.accessToken)
|
|
21759
22548
|
};
|
|
21760
22549
|
}
|
|
21761
22550
|
async function loginGrok(store, deps, exchangeFetch, label) {
|
|
@@ -21776,28 +22565,28 @@ async function loginGrok(store, deps, exchangeFetch, label) {
|
|
|
21776
22565
|
}
|
|
21777
22566
|
async function runCopilotDeviceFlow(exchangeFetch, openBrowserFn, enterpriseUrl) {
|
|
21778
22567
|
if (enterpriseUrl) console.info(`Using GitHub Enterprise host: ${enterpriseUrl}`);
|
|
21779
|
-
const authorization = await
|
|
22568
|
+
const authorization = await import_subscriptions14.copilotOAuth.requestCopilotDeviceAuthorization(exchangeFetch, enterpriseUrl);
|
|
21780
22569
|
const url = authorization.verificationUri;
|
|
21781
22570
|
console.info("Open this URL in your browser and approve the request:");
|
|
21782
22571
|
console.info(` ${url}`);
|
|
21783
22572
|
console.info(` Then enter this code: ${authorization.userCode}`);
|
|
21784
22573
|
await openBrowserFn(url).catch(() => false);
|
|
21785
|
-
const result = await
|
|
22574
|
+
const result = await import_subscriptions14.copilotOAuth.awaitCopilotDeviceToken(authorization, exchangeFetch, {
|
|
21786
22575
|
onPending: () => process.stdout.write("."),
|
|
21787
22576
|
...enterpriseUrl ? { enterpriseUrl } : {}
|
|
21788
22577
|
});
|
|
21789
22578
|
console.info("");
|
|
21790
|
-
const identity = await
|
|
21791
|
-
const apiEndpoint = await
|
|
22579
|
+
const identity = await import_subscriptions14.copilotOAuth.fetchCopilotIdentity(result.accessToken, exchangeFetch, enterpriseUrl);
|
|
22580
|
+
const apiEndpoint = await import_subscriptions14.copilotOAuth.discoverCopilotApiEndpoint(result.accessToken, exchangeFetch, enterpriseUrl);
|
|
21792
22581
|
console.info("Enabling Copilot models (policy)...");
|
|
21793
|
-
await
|
|
22582
|
+
await import_subscriptions14.copilotOAuth.enableAllCopilotModels(
|
|
21794
22583
|
result.accessToken,
|
|
21795
22584
|
{ apiEndpoint, ...enterpriseUrl ? { enterpriseUrl } : {} },
|
|
21796
22585
|
exchangeFetch
|
|
21797
22586
|
);
|
|
21798
22587
|
return {
|
|
21799
22588
|
accessToken: result.accessToken,
|
|
21800
|
-
expiresIn: Math.floor(
|
|
22589
|
+
expiresIn: Math.floor(import_subscriptions14.copilotOAuth.COPILOT_FAR_FUTURE_MS / 1e3),
|
|
21801
22590
|
...identity,
|
|
21802
22591
|
...apiEndpoint ? { apiEndpoint } : {}
|
|
21803
22592
|
};
|
|
@@ -21823,6 +22612,70 @@ async function loginCopilot(store, deps, exchangeFetch, label, enterpriseUrl) {
|
|
|
21823
22612
|
logMasked("copilot", result.accessToken);
|
|
21824
22613
|
return expiresAt;
|
|
21825
22614
|
}
|
|
22615
|
+
async function loginAntigravity(store, deps, exchangeFetch, label) {
|
|
22616
|
+
const { authUrl, state } = import_subscriptions14.antigravityOAuth.generateAuthParams();
|
|
22617
|
+
await presentUrl(authUrl, deps);
|
|
22618
|
+
const code = await captureAntigravityCode(deps, state);
|
|
22619
|
+
const result = await import_subscriptions14.antigravityOAuth.exchangeCodeForTokens(code, exchangeFetch);
|
|
22620
|
+
const expiresAt = new Date(Date.now() + result.expiresIn * 1e3).toISOString();
|
|
22621
|
+
const email = await import_subscriptions14.antigravityOAuth.fetchUserEmail(result.accessToken, exchangeFetch);
|
|
22622
|
+
console.info("Resolving the Antigravity Cloud Code Assist project...");
|
|
22623
|
+
const projectId = await (0, import_GeminiCodeAssistProjectResolver7.getAntigravityProjectResolver)().resolveProject(result.accessToken);
|
|
22624
|
+
const block = {
|
|
22625
|
+
authMethod: "oauth",
|
|
22626
|
+
status: "authorized",
|
|
22627
|
+
accessToken: result.accessToken,
|
|
22628
|
+
refreshToken: result.refreshToken,
|
|
22629
|
+
expiresAt,
|
|
22630
|
+
...email ? { email } : {},
|
|
22631
|
+
...projectId ? { projectId } : {},
|
|
22632
|
+
lastRefreshedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
22633
|
+
};
|
|
22634
|
+
await store.appendProviderAccount("antigravity", block, label);
|
|
22635
|
+
logMasked("antigravity", result.accessToken);
|
|
22636
|
+
return expiresAt;
|
|
22637
|
+
}
|
|
22638
|
+
async function captureAntigravityCode(deps, state) {
|
|
22639
|
+
try {
|
|
22640
|
+
return await deps.awaitLoopback(state, void 0, void 0, {
|
|
22641
|
+
port: 51121,
|
|
22642
|
+
path: "/oauth-callback",
|
|
22643
|
+
label: "antigravity"
|
|
22644
|
+
});
|
|
22645
|
+
} catch (loopbackError) {
|
|
22646
|
+
const reason = loopbackError instanceof Error ? loopbackError.message : String(loopbackError);
|
|
22647
|
+
console.warn(`(loopback capture unavailable: ${reason})`);
|
|
22648
|
+
console.info(
|
|
22649
|
+
"Paste fallback: after authorizing, copy the failing redirect URL (or just its code parameter) here."
|
|
22650
|
+
);
|
|
22651
|
+
const pasted = (await deps.promptPaste("Paste the authorization code (or redirect URL): ")).trim();
|
|
22652
|
+
if (!pasted) throw new Error("login: no authorization code was pasted");
|
|
22653
|
+
const { code, state: pastedState } = parseAntigravityPaste(pasted);
|
|
22654
|
+
if (!code) throw new Error("login: the pasted value carried no authorization code");
|
|
22655
|
+
if (pastedState && pastedState !== state) {
|
|
22656
|
+
throw new Error("login: pasted state did not match (possible CSRF) \u2014 aborting");
|
|
22657
|
+
}
|
|
22658
|
+
return code;
|
|
22659
|
+
}
|
|
22660
|
+
}
|
|
22661
|
+
function parseAntigravityPaste(pasted) {
|
|
22662
|
+
if (pasted.includes("://")) {
|
|
22663
|
+
try {
|
|
22664
|
+
const url = new URL(pasted);
|
|
22665
|
+
const code = url.searchParams.get("code") ?? "";
|
|
22666
|
+
const state = url.searchParams.get("state") ?? void 0;
|
|
22667
|
+
return { code, ...state ? { state } : {} };
|
|
22668
|
+
} catch {
|
|
22669
|
+
}
|
|
22670
|
+
}
|
|
22671
|
+
if (/^[?]?code=/.test(pasted)) {
|
|
22672
|
+
const params = new URLSearchParams(pasted.replace(/^\?/, ""));
|
|
22673
|
+
const code = params.get("code") ?? "";
|
|
22674
|
+
const state = params.get("state") ?? void 0;
|
|
22675
|
+
return { code, ...state ? { state } : {} };
|
|
22676
|
+
}
|
|
22677
|
+
return { code: pasted };
|
|
22678
|
+
}
|
|
21826
22679
|
function isLoginProvider(value) {
|
|
21827
22680
|
return PROVIDERS2.includes(value);
|
|
21828
22681
|
}
|
|
@@ -22244,7 +23097,11 @@ var TOKEN_FIELDS2 = {
|
|
|
22244
23097
|
claude: ["accessToken", "refreshToken"],
|
|
22245
23098
|
codex: ["accessToken", "refreshToken", "idToken"],
|
|
22246
23099
|
gemini: ["accessToken", "refreshToken"],
|
|
22247
|
-
opencodego: ["apiKey"]
|
|
23100
|
+
opencodego: ["apiKey"],
|
|
23101
|
+
kimi: ["accessToken", "refreshToken"],
|
|
23102
|
+
grok: ["accessToken", "refreshToken"],
|
|
23103
|
+
copilot: ["accessToken", "refreshToken"],
|
|
23104
|
+
antigravity: ["accessToken", "refreshToken"]
|
|
22248
23105
|
};
|
|
22249
23106
|
function walkTokens(raw, fn) {
|
|
22250
23107
|
const next = { ...raw };
|
|
@@ -22528,7 +23385,7 @@ async function main() {
|
|
|
22528
23385
|
process.exitCode = 1;
|
|
22529
23386
|
}
|
|
22530
23387
|
}
|
|
22531
|
-
main().catch((
|
|
22532
|
-
console.error(
|
|
23388
|
+
main().catch((err9) => {
|
|
23389
|
+
console.error(err9 instanceof Error ? err9.message : String(err9));
|
|
22533
23390
|
process.exitCode = 1;
|
|
22534
23391
|
});
|