@omnicross/daemon 0.4.2 → 0.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.cjs +1193 -281
- package/dist/cli.js +1141 -221
- package/dist/index.cjs +986 -238
- package/dist/index.d.cts +1588 -1386
- package/dist/index.d.ts +1588 -1386
- package/dist/index.js +954 -199
- package/package.json +6 -6
package/dist/cli.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");
|
|
@@ -8148,7 +8684,7 @@ async function handleAdminApi(req, res, path2, deps) {
|
|
|
8148
8684
|
case "server":
|
|
8149
8685
|
return await handleServer(req, res, method, deps);
|
|
8150
8686
|
case "images":
|
|
8151
|
-
return await handleImages(res, method, rest, deps);
|
|
8687
|
+
return await handleImages(req, res, method, rest, deps);
|
|
8152
8688
|
case "search":
|
|
8153
8689
|
return await handleSearchAdmin(req, res, method, rest, deps);
|
|
8154
8690
|
case "accounts":
|
|
@@ -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
|
}
|
|
@@ -9685,7 +10231,41 @@ function imageEndpointUrls(base) {
|
|
|
9685
10231
|
edits: `${base}/v1/images/edits`
|
|
9686
10232
|
}) : null;
|
|
9687
10233
|
}
|
|
9688
|
-
|
|
10234
|
+
function imageProviderEvidence(images, capabilities) {
|
|
10235
|
+
const evidenceAt = safeStatusTimestamp(capabilities?.oldestEvidenceAt);
|
|
10236
|
+
const resolvedAt = safeStatusTimestamp(capabilities?.resolvedAt);
|
|
10237
|
+
if (evidenceAt === void 0 || resolvedAt === void 0) return null;
|
|
10238
|
+
const expiresAt = evidenceAt <= Number.MAX_SAFE_INTEGER - images.evidenceTtlMs ? evidenceAt + images.evidenceTtlMs : void 0;
|
|
10239
|
+
return Object.freeze({
|
|
10240
|
+
verifiedAt: evidenceAt,
|
|
10241
|
+
ageMs: Math.max(0, resolvedAt - evidenceAt),
|
|
10242
|
+
...expiresAt !== void 0 ? { expiresAt } : {}
|
|
10243
|
+
});
|
|
10244
|
+
}
|
|
10245
|
+
async function handleImagesVerifyLive(req, res, deps) {
|
|
10246
|
+
const verifier = deps.imageLiveVerifier;
|
|
10247
|
+
if (!verifier) {
|
|
10248
|
+
return writeJsonError(res, 501, "Images live verification is not available");
|
|
10249
|
+
}
|
|
10250
|
+
const serverConfig = await (0, import_outbound_api5.loadServerConfig)(deps.settingsStore);
|
|
10251
|
+
const images = serverConfig.images ?? import_outbound_api5.DEFAULT_IMAGES_SERVER_CONFIG;
|
|
10252
|
+
req.resume();
|
|
10253
|
+
const controller = new AbortController();
|
|
10254
|
+
req.on("close", () => controller.abort());
|
|
10255
|
+
const result = await verifier.verifyLive(images, controller.signal);
|
|
10256
|
+
const antigravityRouted = Object.values(images.models).includes("antigravity-subscription");
|
|
10257
|
+
return writeJson4(res, 200, {
|
|
10258
|
+
...result,
|
|
10259
|
+
...antigravityRouted ? { antigravityDeferred: true } : {}
|
|
10260
|
+
});
|
|
10261
|
+
}
|
|
10262
|
+
async function handleImages(req, res, method, rest, deps) {
|
|
10263
|
+
if (rest.length === 1 && rest[0] === "verify-live") {
|
|
10264
|
+
if (method !== "POST") {
|
|
10265
|
+
return writeJsonError(res, 405, `method ${method} not allowed on Images verify-live`);
|
|
10266
|
+
}
|
|
10267
|
+
return handleImagesVerifyLive(req, res, deps);
|
|
10268
|
+
}
|
|
9689
10269
|
if (rest.length !== 1 || rest[0] !== "capabilities") {
|
|
9690
10270
|
return writeJsonError(res, 404, "unknown Images admin resource");
|
|
9691
10271
|
}
|
|
@@ -9700,14 +10280,14 @@ async function handleImages(res, method, rest, deps) {
|
|
|
9700
10280
|
const capability = await reader.inspectCapability(IMAGE_ADMIN_STATUS_TENANT);
|
|
9701
10281
|
const resources = safeRuntimeResources(reader.resourceStatus());
|
|
9702
10282
|
const outbound = deps.outboundApiServer.getStatus();
|
|
9703
|
-
const
|
|
9704
|
-
const
|
|
9705
|
-
|
|
9706
|
-
|
|
9707
|
-
|
|
9708
|
-
|
|
9709
|
-
|
|
9710
|
-
})
|
|
10283
|
+
const evidence = imageProviderEvidence(images, capability.capabilities);
|
|
10284
|
+
const providers = (capability.providers ?? []).map((provider) => Object.freeze({
|
|
10285
|
+
providerId: provider.providerId,
|
|
10286
|
+
available: provider.available === true,
|
|
10287
|
+
reason: provider.available ? null : safeImageCapabilityReason(provider.reason),
|
|
10288
|
+
models: Object.freeze([...provider.models]),
|
|
10289
|
+
evidence: imageProviderEvidence(images, provider.capabilities)
|
|
10290
|
+
}));
|
|
9711
10291
|
const draining = lifecycle.draining.map((generation) => Object.freeze({
|
|
9712
10292
|
generationId: safeImageGenerationId(generation.generationId),
|
|
9713
10293
|
enabled: generation.enabled,
|
|
@@ -9717,7 +10297,7 @@ async function handleImages(res, method, rest, deps) {
|
|
|
9717
10297
|
return writeJson4(res, 200, {
|
|
9718
10298
|
configured: {
|
|
9719
10299
|
enabled: images.enabled,
|
|
9720
|
-
provider: images.
|
|
10300
|
+
provider: images.models[images.defaultModel] ?? "codex-subscription",
|
|
9721
10301
|
model: images.defaultModel,
|
|
9722
10302
|
remoteUrlsEnabled: images.remote.enabled,
|
|
9723
10303
|
referenceTtlMs: images.references.ttlMs
|
|
@@ -9728,6 +10308,7 @@ async function handleImages(res, method, rest, deps) {
|
|
|
9728
10308
|
evidence,
|
|
9729
10309
|
features: safeCapabilityValues(capability.capabilities, images.defaultModel)
|
|
9730
10310
|
},
|
|
10311
|
+
providers,
|
|
9731
10312
|
runtime: {
|
|
9732
10313
|
disposed: lifecycle.disposed,
|
|
9733
10314
|
generationId: safeImageGenerationId(lifecycle.current.generationId),
|
|
@@ -9817,12 +10398,12 @@ async function handlePlayground(req, res, method, deps) {
|
|
|
9817
10398
|
const payload = body["body"];
|
|
9818
10399
|
const status = deps.outboundApiServer.getStatus();
|
|
9819
10400
|
if (!status.running || !status.port) return writeJsonError(res, 503, "outbound server not running");
|
|
9820
|
-
const path2 = resolvePlaygroundPath(endpoint,
|
|
10401
|
+
const path2 = resolvePlaygroundPath(endpoint, isRecord9(payload) ? payload : {});
|
|
9821
10402
|
if (!path2) return writeJsonError(res, 400, `unknown endpoint '${endpoint}'`);
|
|
9822
10403
|
const upstreamBody = typeof payload === "string" ? payload : JSON.stringify(payload ?? {});
|
|
9823
10404
|
await proxyToOutbound(res, status.port, path2, key, upstreamBody);
|
|
9824
10405
|
}
|
|
9825
|
-
function
|
|
10406
|
+
function isRecord9(v) {
|
|
9826
10407
|
return !!v && typeof v === "object" && !Array.isArray(v);
|
|
9827
10408
|
}
|
|
9828
10409
|
function proxyToOutbound(res, outboundPort, path2, key, body) {
|
|
@@ -9851,8 +10432,8 @@ function proxyToOutbound(res, outboundPort, path2, key, body) {
|
|
|
9851
10432
|
});
|
|
9852
10433
|
}
|
|
9853
10434
|
);
|
|
9854
|
-
upstream.on("error", (
|
|
9855
|
-
if (!res.headersSent) writeJsonError(res, 502, `playground proxy failed: ${
|
|
10435
|
+
upstream.on("error", (err9) => {
|
|
10436
|
+
if (!res.headersSent) writeJsonError(res, 502, `playground proxy failed: ${err9.message}`);
|
|
9856
10437
|
else res.end();
|
|
9857
10438
|
resolve11();
|
|
9858
10439
|
});
|
|
@@ -9958,7 +10539,7 @@ async function handleUiStatic(req, res, urlPath, uiDist) {
|
|
|
9958
10539
|
}
|
|
9959
10540
|
|
|
9960
10541
|
// src/admin/version.ts
|
|
9961
|
-
var DAEMON_VERSION = true ? "0.4.
|
|
10542
|
+
var DAEMON_VERSION = true ? "0.4.4" : "0.0.0-dev";
|
|
9962
10543
|
|
|
9963
10544
|
// src/admin/AdminServer.ts
|
|
9964
10545
|
var LOOPBACK_ADDR = "127.0.0.1";
|
|
@@ -10001,13 +10582,13 @@ var AdminServer = class {
|
|
|
10001
10582
|
const server = import_node_http2.default.createServer((req, res) => {
|
|
10002
10583
|
this.onRequest(req, res);
|
|
10003
10584
|
});
|
|
10004
|
-
const onError = (
|
|
10005
|
-
if (
|
|
10585
|
+
const onError = (err9) => {
|
|
10586
|
+
if (err9.code === "EADDRINUSE" && port !== 0) {
|
|
10006
10587
|
server.removeListener("error", onError);
|
|
10007
10588
|
this.listen(bindAddr, 0).then(resolve11, reject);
|
|
10008
10589
|
return;
|
|
10009
10590
|
}
|
|
10010
|
-
reject(
|
|
10591
|
+
reject(err9);
|
|
10011
10592
|
};
|
|
10012
10593
|
server.on("error", onError);
|
|
10013
10594
|
server.listen(port, bindAddr, () => {
|
|
@@ -10025,8 +10606,8 @@ var AdminServer = class {
|
|
|
10025
10606
|
}
|
|
10026
10607
|
/** Per-request handler: auth gate (when a token is set) → routing. */
|
|
10027
10608
|
onRequest(req, res) {
|
|
10028
|
-
void this.dispatch(req, res).catch((
|
|
10029
|
-
const message =
|
|
10609
|
+
void this.dispatch(req, res).catch((err9) => {
|
|
10610
|
+
const message = err9 instanceof Error ? err9.message : String(err9);
|
|
10030
10611
|
this.deps.logger.error("[AdminServer] unhandled error:", message);
|
|
10031
10612
|
if (!res.headersSent) {
|
|
10032
10613
|
res.writeHead(500, { "Content-Type": "application/json" });
|
|
@@ -10249,7 +10830,10 @@ var HTML_HEADERS = {
|
|
|
10249
10830
|
function pageHtml(message) {
|
|
10250
10831
|
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
10832
|
}
|
|
10252
|
-
function awaitLoopbackCode(expectedState, timeoutMs = DEFAULT_TIMEOUT_MS, signal) {
|
|
10833
|
+
function awaitLoopbackCode(expectedState, timeoutMs = DEFAULT_TIMEOUT_MS, signal, binding = {}) {
|
|
10834
|
+
const port = binding.port ?? LOOPBACK_PORT;
|
|
10835
|
+
const callbackPath = binding.path ?? CALLBACK_PATH;
|
|
10836
|
+
const label = binding.label ?? "codex";
|
|
10253
10837
|
return new Promise((resolve11, reject) => {
|
|
10254
10838
|
let settled = false;
|
|
10255
10839
|
const finish = (server2, fn) => {
|
|
@@ -10260,8 +10844,8 @@ function awaitLoopbackCode(expectedState, timeoutMs = DEFAULT_TIMEOUT_MS, signal
|
|
|
10260
10844
|
server2.close();
|
|
10261
10845
|
};
|
|
10262
10846
|
const server = (0, import_node_http3.createServer)((req, res) => {
|
|
10263
|
-
const url = new URL(req.url ?? "", `http://${LOOPBACK_HOST}:${
|
|
10264
|
-
if (url.pathname !==
|
|
10847
|
+
const url = new URL(req.url ?? "", `http://${LOOPBACK_HOST}:${port}`);
|
|
10848
|
+
if (url.pathname !== callbackPath) {
|
|
10265
10849
|
res.writeHead(404, HTML_HEADERS);
|
|
10266
10850
|
res.end(pageHtml("Not found"));
|
|
10267
10851
|
return;
|
|
@@ -10290,25 +10874,25 @@ function awaitLoopbackCode(expectedState, timeoutMs = DEFAULT_TIMEOUT_MS, signal
|
|
|
10290
10874
|
return;
|
|
10291
10875
|
}
|
|
10292
10876
|
signal?.addEventListener("abort", abort, { once: true });
|
|
10293
|
-
server.on("error", (
|
|
10877
|
+
server.on("error", (err9) => {
|
|
10294
10878
|
if (settled) return;
|
|
10295
10879
|
settled = true;
|
|
10296
10880
|
clearTimeout(timer);
|
|
10297
|
-
if (
|
|
10881
|
+
if (err9.code === "EADDRINUSE") {
|
|
10298
10882
|
reject(
|
|
10299
10883
|
new Error(
|
|
10300
|
-
`login: cannot bind ${LOOPBACK_HOST}:${
|
|
10884
|
+
`login: cannot bind ${LOOPBACK_HOST}:${port} (address in use) \u2014 another ${label} login or process is holding the port`
|
|
10301
10885
|
)
|
|
10302
10886
|
);
|
|
10303
10887
|
} else {
|
|
10304
|
-
reject(
|
|
10888
|
+
reject(err9);
|
|
10305
10889
|
}
|
|
10306
10890
|
});
|
|
10307
10891
|
const timer = setTimeout(() => {
|
|
10308
10892
|
finish(server, () => reject(new Error(`login: timed out after ${Math.round(timeoutMs / 1e3)}s waiting for the callback`)));
|
|
10309
10893
|
}, timeoutMs);
|
|
10310
10894
|
if (typeof timer.unref === "function") timer.unref();
|
|
10311
|
-
server.listen(
|
|
10895
|
+
server.listen(port, LOOPBACK_HOST);
|
|
10312
10896
|
});
|
|
10313
10897
|
}
|
|
10314
10898
|
|
|
@@ -10378,7 +10962,7 @@ function createPoolKeysLoader(getProviderRow, autoDisabled) {
|
|
|
10378
10962
|
|
|
10379
10963
|
// src/allowance/ProviderKeyQuotaService.ts
|
|
10380
10964
|
var import_core4 = require("@omnicross/core");
|
|
10381
|
-
var
|
|
10965
|
+
var import_upstreamFetch13 = require("@omnicross/core/pipeline/upstreamFetch");
|
|
10382
10966
|
|
|
10383
10967
|
// src/allowance/ProviderKeyQuota.ts
|
|
10384
10968
|
var MINUTE_MS3 = 6e4;
|
|
@@ -10407,11 +10991,11 @@ function isoInstant3(value) {
|
|
|
10407
10991
|
}
|
|
10408
10992
|
return void 0;
|
|
10409
10993
|
}
|
|
10410
|
-
function
|
|
10994
|
+
function secondsUntil9(instant, now) {
|
|
10411
10995
|
if (!instant) return void 0;
|
|
10412
10996
|
return Math.max(0, Math.floor((Date.parse(instant) - now) / 1e3));
|
|
10413
10997
|
}
|
|
10414
|
-
function
|
|
10998
|
+
function isRecord10(value) {
|
|
10415
10999
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
10416
11000
|
}
|
|
10417
11001
|
function detectProviderKeyQuotaAdapter(baseUrl) {
|
|
@@ -10478,17 +11062,17 @@ function zaiWindowIdLabel(durationMs) {
|
|
|
10478
11062
|
return { id: "quota", label: "Quota" };
|
|
10479
11063
|
}
|
|
10480
11064
|
function parseZaiQuotaPayload(payload, now) {
|
|
10481
|
-
if (!
|
|
10482
|
-
const data =
|
|
11065
|
+
if (!isRecord10(payload)) return null;
|
|
11066
|
+
const data = isRecord10(payload["data"]) ? payload["data"] : payload;
|
|
10483
11067
|
if (payload["success"] === false) return null;
|
|
10484
11068
|
const limits = Array.isArray(data["limits"]) ? data["limits"] : [];
|
|
10485
11069
|
const byWindow = /* @__PURE__ */ new Map();
|
|
10486
11070
|
for (const raw of limits) {
|
|
10487
|
-
if (!
|
|
11071
|
+
if (!isRecord10(raw)) continue;
|
|
10488
11072
|
const item = raw;
|
|
10489
11073
|
if (item.type === void 0) continue;
|
|
10490
11074
|
const details = raw["usageDetails"];
|
|
10491
|
-
if (Array.isArray(details) && details.some((d) =>
|
|
11075
|
+
if (Array.isArray(details) && details.some((d) => isRecord10(d) && d["modelCode"] === "zread")) {
|
|
10492
11076
|
continue;
|
|
10493
11077
|
}
|
|
10494
11078
|
const durationMs = zaiWindowDurationMs(item);
|
|
@@ -10507,7 +11091,7 @@ function parseZaiQuotaPayload(payload, now) {
|
|
|
10507
11091
|
usedPercent,
|
|
10508
11092
|
...durationMs !== void 0 ? { windowMinutes: Math.round(durationMs / MINUTE_MS3) } : {},
|
|
10509
11093
|
...resetsAt !== void 0 ? { resetsAt } : {},
|
|
10510
|
-
remainingSeconds:
|
|
11094
|
+
remainingSeconds: secondsUntil9(resetsAt, now),
|
|
10511
11095
|
state: "fresh"
|
|
10512
11096
|
};
|
|
10513
11097
|
const existing = byWindow.get(id);
|
|
@@ -10521,7 +11105,7 @@ function parseZaiQuotaPayload(payload, now) {
|
|
|
10521
11105
|
var MINIMAX_STATUS_EXHAUSTED = 2;
|
|
10522
11106
|
var MINIMAX_SHARED_BUCKET = "general";
|
|
10523
11107
|
function parseMiniMaxBucket(value) {
|
|
10524
|
-
if (!
|
|
11108
|
+
if (!isRecord10(value)) return null;
|
|
10525
11109
|
const modelName = typeof value["model_name"] === "string" ? value["model_name"].trim() : "";
|
|
10526
11110
|
if (!modelName) return null;
|
|
10527
11111
|
const instant = (v) => {
|
|
@@ -10548,14 +11132,14 @@ function minimaxWindow(id, label, windowMinutes, resetsAtMs, remainingPercent, s
|
|
|
10548
11132
|
usedPercent,
|
|
10549
11133
|
...windowMinutes !== void 0 ? { windowMinutes } : {},
|
|
10550
11134
|
...resetsAt !== void 0 ? { resetsAt } : {},
|
|
10551
|
-
remainingSeconds:
|
|
11135
|
+
remainingSeconds: secondsUntil9(resetsAt, now),
|
|
10552
11136
|
state: usedPercent !== null ? "fresh" : "unavailable"
|
|
10553
11137
|
};
|
|
10554
11138
|
}
|
|
10555
11139
|
function parseMiniMaxTokenPlanPayload(payload, now) {
|
|
10556
|
-
if (!
|
|
11140
|
+
if (!isRecord10(payload)) return null;
|
|
10557
11141
|
const baseResp = payload["base_resp"];
|
|
10558
|
-
if (!
|
|
11142
|
+
if (!isRecord10(baseResp) || baseResp["status_code"] !== 0) return null;
|
|
10559
11143
|
const buckets = Array.isArray(payload["model_remains"]) ? payload["model_remains"] : [];
|
|
10560
11144
|
let general = null;
|
|
10561
11145
|
for (const raw of buckets) {
|
|
@@ -10588,11 +11172,11 @@ function parseMiniMaxTokenPlanPayload(payload, now) {
|
|
|
10588
11172
|
];
|
|
10589
11173
|
}
|
|
10590
11174
|
function parseUmansUsagePayload(payload, now) {
|
|
10591
|
-
if (!
|
|
10592
|
-
const limits =
|
|
10593
|
-
const requests = limits &&
|
|
10594
|
-
const usage =
|
|
10595
|
-
const window =
|
|
11175
|
+
if (!isRecord10(payload)) return null;
|
|
11176
|
+
const limits = isRecord10(payload["limits"]) ? payload["limits"] : void 0;
|
|
11177
|
+
const requests = limits && isRecord10(limits["requests"]) ? limits["requests"] : void 0;
|
|
11178
|
+
const usage = isRecord10(payload["usage"]) ? payload["usage"] : void 0;
|
|
11179
|
+
const window = isRecord10(payload["window"]) ? payload["window"] : void 0;
|
|
10596
11180
|
const hardCap = finiteNumber5(requests?.["hard_cap"]);
|
|
10597
11181
|
const softLimit = finiteNumber5(requests?.["limit"]);
|
|
10598
11182
|
const requestsInWindow = finiteNumber5(usage?.["requests_in_window"]);
|
|
@@ -10613,15 +11197,15 @@ function parseUmansUsagePayload(payload, now) {
|
|
|
10613
11197
|
usedPercent,
|
|
10614
11198
|
windowMinutes: 5 * 60,
|
|
10615
11199
|
...resetsAt !== void 0 ? { resetsAt } : {},
|
|
10616
|
-
remainingSeconds:
|
|
11200
|
+
remainingSeconds: secondsUntil9(resetsAt, now),
|
|
10617
11201
|
state: "fresh"
|
|
10618
11202
|
}
|
|
10619
11203
|
];
|
|
10620
11204
|
}
|
|
10621
11205
|
function parseSyntheticQuotasPayload(payload, now) {
|
|
10622
|
-
if (!
|
|
10623
|
-
const fiveHour =
|
|
10624
|
-
const weekly =
|
|
11206
|
+
if (!isRecord10(payload)) return null;
|
|
11207
|
+
const fiveHour = isRecord10(payload["rollingFiveHourLimit"]) ? payload["rollingFiveHourLimit"] : void 0;
|
|
11208
|
+
const weekly = isRecord10(payload["weeklyTokenLimit"]) ? payload["weeklyTokenLimit"] : void 0;
|
|
10625
11209
|
const windows = [];
|
|
10626
11210
|
if (fiveHour) {
|
|
10627
11211
|
const max = finiteNumber5(fiveHour["max"]);
|
|
@@ -10635,7 +11219,7 @@ function parseSyntheticQuotasPayload(payload, now) {
|
|
|
10635
11219
|
usedPercent,
|
|
10636
11220
|
windowMinutes: 5 * 60,
|
|
10637
11221
|
...resetsAt !== void 0 ? { resetsAt } : {},
|
|
10638
|
-
remainingSeconds:
|
|
11222
|
+
remainingSeconds: secondsUntil9(resetsAt, now),
|
|
10639
11223
|
state: usedPercent !== null || resetsAt ? "fresh" : "unavailable"
|
|
10640
11224
|
});
|
|
10641
11225
|
}
|
|
@@ -10650,7 +11234,7 @@ function parseSyntheticQuotasPayload(payload, now) {
|
|
|
10650
11234
|
usedPercent,
|
|
10651
11235
|
windowMinutes: 7 * 24 * 60,
|
|
10652
11236
|
...resetsAt !== void 0 ? { resetsAt } : {},
|
|
10653
|
-
remainingSeconds:
|
|
11237
|
+
remainingSeconds: secondsUntil9(resetsAt, now),
|
|
10654
11238
|
state: usedPercent !== null || resetsAt ? "fresh" : "unavailable"
|
|
10655
11239
|
});
|
|
10656
11240
|
}
|
|
@@ -10662,12 +11246,12 @@ var CLINE_WINDOW_CONFIG = {
|
|
|
10662
11246
|
monthly: { id: "thirty-day", label: "30 days", minutes: 30 * 24 * 60 }
|
|
10663
11247
|
};
|
|
10664
11248
|
function parseClinePassUsageLimitsPayload(payload, now) {
|
|
10665
|
-
if (!
|
|
10666
|
-
const data =
|
|
11249
|
+
if (!isRecord10(payload)) return null;
|
|
11250
|
+
const data = isRecord10(payload["data"]) ? payload["data"] : payload;
|
|
10667
11251
|
const limits = Array.isArray(data["limits"]) ? data["limits"] : [];
|
|
10668
11252
|
const windows = [];
|
|
10669
11253
|
for (const raw of limits) {
|
|
10670
|
-
if (!
|
|
11254
|
+
if (!isRecord10(raw)) continue;
|
|
10671
11255
|
const config = CLINE_WINDOW_CONFIG[typeof raw["type"] === "string" ? raw["type"] : ""];
|
|
10672
11256
|
if (!config) continue;
|
|
10673
11257
|
const usedPercent = finitePercent4(raw["percentUsed"]);
|
|
@@ -10680,7 +11264,7 @@ function parseClinePassUsageLimitsPayload(payload, now) {
|
|
|
10680
11264
|
usedPercent,
|
|
10681
11265
|
windowMinutes: config.minutes,
|
|
10682
11266
|
...resetsAt !== void 0 ? { resetsAt } : {},
|
|
10683
|
-
remainingSeconds:
|
|
11267
|
+
remainingSeconds: secondsUntil9(resetsAt, now),
|
|
10684
11268
|
state: "fresh"
|
|
10685
11269
|
});
|
|
10686
11270
|
}
|
|
@@ -10719,7 +11303,7 @@ function rowKeyEntries(row) {
|
|
|
10719
11303
|
return [];
|
|
10720
11304
|
}
|
|
10721
11305
|
var ProviderKeyQuotaService = class {
|
|
10722
|
-
constructor(box, fetchImpl = (url, init) => (0,
|
|
11306
|
+
constructor(box, fetchImpl = (url, init) => (0, import_upstreamFetch13.fetchUpstream)(url, init, { redactBodies: true }), now = Date.now) {
|
|
10723
11307
|
this.box = box;
|
|
10724
11308
|
this.fetchImpl = fetchImpl;
|
|
10725
11309
|
this.now = now;
|
|
@@ -10822,7 +11406,7 @@ var ProviderKeyQuotaService = class {
|
|
|
10822
11406
|
// src/image-generation/ImageDoctorService.ts
|
|
10823
11407
|
var import_image_generation = require("@omnicross/core/image-generation");
|
|
10824
11408
|
var import_outbound_api7 = require("@omnicross/core/outbound-api");
|
|
10825
|
-
var
|
|
11409
|
+
var import_subscriptions10 = require("@omnicross/subscriptions");
|
|
10826
11410
|
|
|
10827
11411
|
// src/image-generation/FileCodexImageCapabilityEvidenceSource.ts
|
|
10828
11412
|
var import_node_crypto13 = require("crypto");
|
|
@@ -11260,16 +11844,16 @@ function createImageDoctorService(options) {
|
|
|
11260
11844
|
paths,
|
|
11261
11845
|
ttlMs: config.evidenceTtlMs
|
|
11262
11846
|
}));
|
|
11263
|
-
const createLiveVerifier = options.createLiveVerifier ?? ((strategy, config) => (0,
|
|
11847
|
+
const createLiveVerifier = options.createLiveVerifier ?? ((strategy, config) => (0, import_subscriptions10.createCodexImageLiveVerifier)({
|
|
11264
11848
|
authStrategy: strategy,
|
|
11265
11849
|
generationTimeoutMs: config.queue.generationTimeoutMs
|
|
11266
11850
|
}));
|
|
11267
|
-
const readAccount = async () => {
|
|
11268
|
-
const
|
|
11851
|
+
const readAccount = async (providerId) => {
|
|
11852
|
+
const entry = (await options.subscriptionAccounts.listAll()).find((candidate) => candidate.providerId === providerId);
|
|
11269
11853
|
return Object.freeze({
|
|
11270
|
-
present:
|
|
11271
|
-
usable:
|
|
11272
|
-
reason:
|
|
11854
|
+
present: entry !== void 0,
|
|
11855
|
+
usable: entry?.credentialStatus.ok === true,
|
|
11856
|
+
reason: entry === void 0 ? "missing" : entry.credentialStatus.ok ? "ready" : "unavailable"
|
|
11273
11857
|
});
|
|
11274
11858
|
};
|
|
11275
11859
|
const activePaths = () => options.storageCatalog.active().resolver;
|
|
@@ -11307,6 +11891,7 @@ function createImageDoctorService(options) {
|
|
|
11307
11891
|
} catch {
|
|
11308
11892
|
storesValid = false;
|
|
11309
11893
|
}
|
|
11894
|
+
const antigravityAccount = await readAccount("antigravity");
|
|
11310
11895
|
const rows = await options.keyDb.outboundApiKeysList();
|
|
11311
11896
|
let legacyRows = 0;
|
|
11312
11897
|
let invalidRows = 0;
|
|
@@ -11323,7 +11908,7 @@ function createImageDoctorService(options) {
|
|
|
11323
11908
|
invalidRows += 1;
|
|
11324
11909
|
}
|
|
11325
11910
|
}
|
|
11326
|
-
const account = await readAccount();
|
|
11911
|
+
const account = await readAccount("codex");
|
|
11327
11912
|
let evidence;
|
|
11328
11913
|
let evidenceStore;
|
|
11329
11914
|
try {
|
|
@@ -11337,10 +11922,11 @@ function createImageDoctorService(options) {
|
|
|
11337
11922
|
return Object.freeze({
|
|
11338
11923
|
config: Object.freeze({
|
|
11339
11924
|
enabled: config.enabled,
|
|
11340
|
-
provider: config.
|
|
11925
|
+
provider: config.models[config.defaultModel] ?? "codex-subscription",
|
|
11341
11926
|
model: config.defaultModel,
|
|
11342
11927
|
valid: configErrors.length === 0,
|
|
11343
|
-
errorCount: configErrors.length
|
|
11928
|
+
errorCount: configErrors.length,
|
|
11929
|
+
routedProviders: Object.freeze([...new Set(Object.values(config.models))])
|
|
11344
11930
|
}),
|
|
11345
11931
|
roots: Object.freeze({
|
|
11346
11932
|
valid: verifiedAreas === ROOT_AREAS.length,
|
|
@@ -11365,12 +11951,13 @@ function createImageDoctorService(options) {
|
|
|
11365
11951
|
imagesAuthorizedRows
|
|
11366
11952
|
}),
|
|
11367
11953
|
account,
|
|
11954
|
+
antigravityAccount,
|
|
11368
11955
|
evidence: Object.freeze(evidence)
|
|
11369
11956
|
});
|
|
11370
11957
|
},
|
|
11371
11958
|
verifyLive: async (config, signal) => {
|
|
11372
11959
|
if (!config.enabled) return Object.freeze({ ok: false, code: "images_disabled" });
|
|
11373
|
-
const account = await readAccount();
|
|
11960
|
+
const account = await readAccount("codex");
|
|
11374
11961
|
if (!account.usable) {
|
|
11375
11962
|
return Object.freeze({ ok: false, code: "codex_account_unavailable" });
|
|
11376
11963
|
}
|
|
@@ -11622,7 +12209,7 @@ var ImageCleanupService = class {
|
|
|
11622
12209
|
var import_node_crypto16 = require("crypto");
|
|
11623
12210
|
var import_image_generation5 = require("@omnicross/core/image-generation");
|
|
11624
12211
|
var import_outbound_api8 = require("@omnicross/core/outbound-api");
|
|
11625
|
-
var
|
|
12212
|
+
var import_subscriptions11 = require("@omnicross/subscriptions");
|
|
11626
12213
|
|
|
11627
12214
|
// src/image-generation/ImageApiRuntimeResolver.ts
|
|
11628
12215
|
var import_node_crypto14 = require("crypto");
|
|
@@ -11650,10 +12237,11 @@ function createTrustedImageApiRuntimeResolver(options) {
|
|
|
11650
12237
|
throw new TypeError("enabled image remote loading requires a proven resolver");
|
|
11651
12238
|
}
|
|
11652
12239
|
const hmacKey = Buffer.from(options.hmacKey);
|
|
11653
|
-
const modelAliases = new Map(Object.entries(options.config.
|
|
12240
|
+
const modelAliases = new Map(Object.entries(options.config.aliases));
|
|
12241
|
+
const modelRoutes = new Map(Object.entries(options.config.models));
|
|
11654
12242
|
const limits = Object.freeze({ ...options.config.limits });
|
|
11655
|
-
const providerId = options.config.provider;
|
|
11656
12243
|
const defaultModel = options.config.defaultModel;
|
|
12244
|
+
const providerId = modelRoutes.get(defaultModel) ?? "codex-subscription";
|
|
11657
12245
|
const referenceStore = options.referenceStore;
|
|
11658
12246
|
const retention = Object.freeze({
|
|
11659
12247
|
enabled: true,
|
|
@@ -11674,6 +12262,7 @@ function createTrustedImageApiRuntimeResolver(options) {
|
|
|
11674
12262
|
providerId,
|
|
11675
12263
|
defaultModel,
|
|
11676
12264
|
modelAliases,
|
|
12265
|
+
modelRoutes,
|
|
11677
12266
|
limits,
|
|
11678
12267
|
...preferredAccountId ? { preferredAccountId } : {},
|
|
11679
12268
|
...preferredAccountGroup ? { preferredAccountGroup } : {},
|
|
@@ -12075,7 +12664,9 @@ var GENERATION_ID = /^[A-Za-z0-9][A-Za-z0-9_.:-]{0,127}$/u;
|
|
|
12075
12664
|
function snapshotConfig(config) {
|
|
12076
12665
|
return {
|
|
12077
12666
|
...config,
|
|
12078
|
-
|
|
12667
|
+
models: { ...config.models },
|
|
12668
|
+
aliases: { ...config.aliases },
|
|
12669
|
+
codex: { ...config.codex },
|
|
12079
12670
|
account: { ...config.account },
|
|
12080
12671
|
queue: { ...config.queue },
|
|
12081
12672
|
temporary: { ...config.temporary },
|
|
@@ -12109,10 +12700,15 @@ function createImageRuntimeGeneration(options) {
|
|
|
12109
12700
|
}
|
|
12110
12701
|
});
|
|
12111
12702
|
}
|
|
12112
|
-
const
|
|
12113
|
-
|
|
12703
|
+
const routedProviders = [...new Set(Object.values(config.models))];
|
|
12704
|
+
const codexStrategy = routedProviders.includes("codex-subscription") ? options.subscriptionAccounts.getStrategy("codex") : void 0;
|
|
12705
|
+
if (routedProviders.includes("codex-subscription") && (!codexStrategy || codexStrategy.providerId !== "codex")) {
|
|
12114
12706
|
throw new TypeError("enabled image runtime requires the Codex subscription strategy");
|
|
12115
12707
|
}
|
|
12708
|
+
const antigravityStrategy = routedProviders.includes("antigravity-subscription") ? options.subscriptionAccounts.getStrategy("antigravity") : void 0;
|
|
12709
|
+
if (routedProviders.includes("antigravity-subscription") && (!antigravityStrategy || antigravityStrategy.providerId !== "antigravity")) {
|
|
12710
|
+
throw new TypeError("enabled image runtime requires the Antigravity subscription strategy");
|
|
12711
|
+
}
|
|
12116
12712
|
const privateHmacKey = options.privateHmacKey ? Buffer.from(options.privateHmacKey) : loadOrCreateImageTenantHmacSalt(options.storage.paths, import_node_crypto16.randomBytes);
|
|
12117
12713
|
if (privateHmacKey.byteLength !== 32) {
|
|
12118
12714
|
privateHmacKey.fill(0);
|
|
@@ -12147,23 +12743,32 @@ function createImageRuntimeGeneration(options) {
|
|
|
12147
12743
|
if (options.testOnlySyntheticVerifiedProvider && options.testOnlySyntheticVerifiedProvider.label !== "synthetic-verified-image-provider-test-only") {
|
|
12148
12744
|
throw new TypeError("synthetic verified image provider test seam label is invalid");
|
|
12149
12745
|
}
|
|
12150
|
-
const
|
|
12746
|
+
const providers = options.testOnlySyntheticVerifiedProvider ? [options.testOnlySyntheticVerifiedProvider.createProvider({
|
|
12151
12747
|
generationId: options.generationId,
|
|
12152
12748
|
scheduler,
|
|
12153
12749
|
now: options.now ?? Date.now,
|
|
12154
12750
|
referenceStore: options.storage.referenceStore,
|
|
12155
12751
|
stateStore: options.storage.stateStore
|
|
12156
|
-
}) : (0,
|
|
12157
|
-
authStrategy,
|
|
12752
|
+
})] : routedProviders.map((providerId) => providerId === "codex-subscription" ? (0, import_subscriptions11.createCodexSubscriptionImageProvider)({
|
|
12753
|
+
authStrategy: codexStrategy,
|
|
12158
12754
|
evidenceSource: generationEvidenceSource,
|
|
12159
12755
|
executionScheduler: scheduler,
|
|
12160
12756
|
generationTimeoutMs: config.queue.generationTimeoutMs,
|
|
12757
|
+
now: options.now,
|
|
12758
|
+
wire: {
|
|
12759
|
+
imageModel: config.codex.imageModel,
|
|
12760
|
+
carrierModel: config.codex.carrierModel
|
|
12761
|
+
}
|
|
12762
|
+
}) : (0, import_subscriptions11.createAntigravitySubscriptionImageProvider)({
|
|
12763
|
+
authStrategy: antigravityStrategy,
|
|
12764
|
+
executionScheduler: scheduler,
|
|
12765
|
+
generationTimeoutMs: config.queue.generationTimeoutMs,
|
|
12161
12766
|
now: options.now
|
|
12162
|
-
});
|
|
12163
|
-
if (
|
|
12767
|
+
}));
|
|
12768
|
+
if (providers.length === 1 && providers[0].id !== "codex-subscription") {
|
|
12164
12769
|
throw new TypeError("synthetic verified image provider id must match configured provider");
|
|
12165
12770
|
}
|
|
12166
|
-
const providerRegistry = new import_image_generation5.ImageProviderRegistry(
|
|
12771
|
+
const providerRegistry = new import_image_generation5.ImageProviderRegistry(providers);
|
|
12167
12772
|
const orchestrator = new import_image_generation5.ImageOrchestrator({
|
|
12168
12773
|
registry: providerRegistry,
|
|
12169
12774
|
referenceStore: options.storage.referenceStore,
|
|
@@ -12185,35 +12790,72 @@ function createImageRuntimeGeneration(options) {
|
|
|
12185
12790
|
...options.createCallId ? { createCallId: options.createCallId } : {},
|
|
12186
12791
|
...options.now ? { now: options.now } : {}
|
|
12187
12792
|
});
|
|
12793
|
+
const defaultProviderId = config.models[config.defaultModel] ?? "codex-subscription";
|
|
12794
|
+
const inspectOneProvider = async (providerId, apiKeyId) => {
|
|
12795
|
+
const capabilities = await orchestrator.getCapabilities(providerId, {
|
|
12796
|
+
requestId: `${options.generationId}:capability-inspection`,
|
|
12797
|
+
tenantId: apiKeyId,
|
|
12798
|
+
signal: new AbortController().signal,
|
|
12799
|
+
sessionKey: `outbound:images:${apiKeyId}`,
|
|
12800
|
+
...config.account.id ? { preferredAccountId: config.account.id } : {},
|
|
12801
|
+
...config.account.group ? { preferredAccountGroup: config.account.group } : {},
|
|
12802
|
+
boundAccountFallbackPolicy: config.account.fallback
|
|
12803
|
+
});
|
|
12804
|
+
return capabilities;
|
|
12805
|
+
};
|
|
12188
12806
|
const inspectCapability = async (apiKeyId) => {
|
|
12189
|
-
|
|
12190
|
-
|
|
12191
|
-
|
|
12192
|
-
|
|
12193
|
-
|
|
12194
|
-
|
|
12195
|
-
|
|
12196
|
-
|
|
12197
|
-
|
|
12198
|
-
|
|
12199
|
-
|
|
12200
|
-
|
|
12201
|
-
|
|
12202
|
-
|
|
12203
|
-
|
|
12204
|
-
|
|
12205
|
-
|
|
12206
|
-
|
|
12207
|
-
|
|
12208
|
-
|
|
12807
|
+
const providerCapabilities = /* @__PURE__ */ new Map();
|
|
12808
|
+
let defaultProviderError;
|
|
12809
|
+
const providerRows = [];
|
|
12810
|
+
for (const providerId of [...new Set(Object.values(config.models))]) {
|
|
12811
|
+
try {
|
|
12812
|
+
const capabilities2 = await inspectOneProvider(providerId, apiKeyId);
|
|
12813
|
+
providerCapabilities.set(providerId, capabilities2);
|
|
12814
|
+
const affirmed = capabilities2.available === true && capabilities2.generate === true;
|
|
12815
|
+
providerRows.push({
|
|
12816
|
+
providerId,
|
|
12817
|
+
available: affirmed,
|
|
12818
|
+
...!affirmed ? { reason: capabilities2.reason ?? "runtime_unavailable" } : {},
|
|
12819
|
+
models: affirmed ? Object.entries(config.models).filter(([model, modelProvider]) => modelProvider === providerId && capabilities2.models.includes(model)).map(([model]) => model) : [],
|
|
12820
|
+
capabilities: capabilities2
|
|
12821
|
+
});
|
|
12822
|
+
} catch (error) {
|
|
12823
|
+
if (providerId === defaultProviderId) defaultProviderError = error;
|
|
12824
|
+
providerRows.push({
|
|
12825
|
+
providerId,
|
|
12826
|
+
available: false,
|
|
12827
|
+
reason: error instanceof import_image_generation5.ImageGenerationError && (error.code === "upstream_auth_required" || error.code === "invalid_api_key") ? "account_unverified" : "runtime_unavailable",
|
|
12828
|
+
models: []
|
|
12829
|
+
});
|
|
12830
|
+
}
|
|
12831
|
+
}
|
|
12832
|
+
const providers2 = Object.freeze(providerRows);
|
|
12833
|
+
const routedModels = Object.freeze(
|
|
12834
|
+
providerRows.flatMap((row) => row.available ? row.models : [])
|
|
12835
|
+
);
|
|
12836
|
+
const capabilities = providerCapabilities.get(defaultProviderId);
|
|
12837
|
+
if (!capabilities) {
|
|
12209
12838
|
return Object.freeze({
|
|
12210
12839
|
enabled: true,
|
|
12211
12840
|
available: false,
|
|
12212
|
-
providerId:
|
|
12841
|
+
providerId: defaultProviderId,
|
|
12213
12842
|
model: config.defaultModel,
|
|
12214
|
-
|
|
12843
|
+
routedModels,
|
|
12844
|
+
providers: providers2,
|
|
12845
|
+
reason: defaultProviderError instanceof import_image_generation5.ImageGenerationError && (defaultProviderError.code === "upstream_auth_required" || defaultProviderError.code === "invalid_api_key") ? "account_unverified" : "runtime_unavailable"
|
|
12215
12846
|
});
|
|
12216
12847
|
}
|
|
12848
|
+
const available = capabilities.available === true && capabilities.generate === true && capabilities.models.includes(config.defaultModel);
|
|
12849
|
+
return Object.freeze({
|
|
12850
|
+
enabled: true,
|
|
12851
|
+
available,
|
|
12852
|
+
providerId: defaultProviderId,
|
|
12853
|
+
model: config.defaultModel,
|
|
12854
|
+
routedModels,
|
|
12855
|
+
providers: providers2,
|
|
12856
|
+
...!available ? { reason: capabilities.reason ?? "runtime_unavailable" } : {},
|
|
12857
|
+
capabilities
|
|
12858
|
+
});
|
|
12217
12859
|
};
|
|
12218
12860
|
const resolverToDispose = runtimeResolver;
|
|
12219
12861
|
const schedulerToDispose = scheduler;
|
|
@@ -12251,7 +12893,7 @@ function createImageRuntimeGeneration(options) {
|
|
|
12251
12893
|
imageApi,
|
|
12252
12894
|
hosted,
|
|
12253
12895
|
hostedRuntime: Object.freeze({
|
|
12254
|
-
providerId:
|
|
12896
|
+
providerId: defaultProviderId,
|
|
12255
12897
|
imageModel: config.defaultModel,
|
|
12256
12898
|
referenceTtlMs: config.references.ttlMs,
|
|
12257
12899
|
maxOutputBytes: config.limits.maxOutputBytes,
|
|
@@ -15194,6 +15836,9 @@ var ImageRuntimeManager = class {
|
|
|
15194
15836
|
}
|
|
15195
15837
|
async listAvailableModels(apiKeyId) {
|
|
15196
15838
|
const inspection = await this.inspectCapability(apiKeyId);
|
|
15839
|
+
if (inspection.routedModels !== void 0) {
|
|
15840
|
+
return Object.freeze([...inspection.routedModels]);
|
|
15841
|
+
}
|
|
15197
15842
|
return inspection.available && inspection.model === "gpt-image-2" ? Object.freeze([inspection.model]) : Object.freeze([]);
|
|
15198
15843
|
}
|
|
15199
15844
|
resourceStatus() {
|
|
@@ -17381,11 +18026,12 @@ var JsonVoucherDb = class {
|
|
|
17381
18026
|
// src/ports/JsonSubscriptionCredentialStore.ts
|
|
17382
18027
|
var import_node_fs28 = require("fs");
|
|
17383
18028
|
var import_node_path27 = require("path");
|
|
18029
|
+
var import_GeminiCodeAssistProjectResolver5 = require("@omnicross/core/auth/GeminiCodeAssistProjectResolver");
|
|
17384
18030
|
var import_SubscriptionAccountHealth2 = require("@omnicross/core/pipeline/SubscriptionAccountHealth");
|
|
17385
18031
|
var import_AccountAllowanceScheduling3 = require("@omnicross/core/pipeline/AccountAllowanceScheduling");
|
|
17386
|
-
var
|
|
18032
|
+
var import_upstreamFetch14 = require("@omnicross/core/pipeline/upstreamFetch");
|
|
17387
18033
|
var import_SubscriptionIdentityStore2 = require("@omnicross/core/provider-proxy/identity/SubscriptionIdentityStore");
|
|
17388
|
-
var
|
|
18034
|
+
var import_subscriptions12 = require("@omnicross/subscriptions");
|
|
17389
18035
|
|
|
17390
18036
|
// src/ports/account-sync.ts
|
|
17391
18037
|
function viewOf(tokens) {
|
|
@@ -17533,7 +18179,7 @@ var JsonSubscriptionCredentialStore = class {
|
|
|
17533
18179
|
* a plaintext token pair into `upstream-trace.jsonl`.
|
|
17534
18180
|
*/
|
|
17535
18181
|
buildRefreshFetch(providerId, accountId) {
|
|
17536
|
-
return this.fetchImpl ?? ((url, init) => (0,
|
|
18182
|
+
return this.fetchImpl ?? ((url, init) => (0, import_upstreamFetch14.fetchUpstream)(url, init, { providerId, accountId, redactBodies: true }));
|
|
17537
18183
|
}
|
|
17538
18184
|
/**
|
|
17539
18185
|
* In-flight refresh coalescing. OAuth refresh tokens are
|
|
@@ -17574,7 +18220,7 @@ var JsonSubscriptionCredentialStore = class {
|
|
|
17574
18220
|
* other hot reads. Never returns token material.
|
|
17575
18221
|
*/
|
|
17576
18222
|
getAccountProxy(providerId, accountId) {
|
|
17577
|
-
if (providerId !== "claude" && providerId !== "codex" && providerId !== "gemini" && providerId !== "opencodego" && providerId !== "kimi" && providerId !== "grok" && providerId !== "copilot") {
|
|
18223
|
+
if (providerId !== "claude" && providerId !== "codex" && providerId !== "gemini" && providerId !== "opencodego" && providerId !== "kimi" && providerId !== "grok" && providerId !== "copilot" && providerId !== "antigravity") {
|
|
17578
18224
|
return void 0;
|
|
17579
18225
|
}
|
|
17580
18226
|
return getAccountProxy(this.readConfig(), providerId, accountId);
|
|
@@ -17593,7 +18239,7 @@ var JsonSubscriptionCredentialStore = class {
|
|
|
17593
18239
|
const fingerprintOn = identityStore.isEnabled();
|
|
17594
18240
|
const now = Date.now();
|
|
17595
18241
|
const out = {};
|
|
17596
|
-
for (const provider of ["claude", "codex", "gemini", "opencodego", "kimi", "grok", "copilot"]) {
|
|
18242
|
+
for (const provider of ["claude", "codex", "gemini", "opencodego", "kimi", "grok", "copilot", "antigravity"]) {
|
|
17597
18243
|
const sanitized = sanitizeAccounts(config, provider);
|
|
17598
18244
|
if (sanitized.length === 0) continue;
|
|
17599
18245
|
for (const account of sanitized) {
|
|
@@ -17659,7 +18305,7 @@ var JsonSubscriptionCredentialStore = class {
|
|
|
17659
18305
|
this.materializeMigration(config);
|
|
17660
18306
|
const refreshFetch = this.buildRefreshFetch("claude", capturedId);
|
|
17661
18307
|
try {
|
|
17662
|
-
const result = await
|
|
18308
|
+
const result = await import_subscriptions12.claudeOAuth.refreshAccessToken(claude.refreshToken, refreshFetch);
|
|
17663
18309
|
const expiresAt = new Date(Date.now() + result.expiresIn * 1e3).toISOString();
|
|
17664
18310
|
const next = {
|
|
17665
18311
|
...claude,
|
|
@@ -17694,7 +18340,7 @@ var JsonSubscriptionCredentialStore = class {
|
|
|
17694
18340
|
this.materializeMigration(config);
|
|
17695
18341
|
const refreshFetch = this.buildRefreshFetch("codex", capturedId);
|
|
17696
18342
|
try {
|
|
17697
|
-
const result = await
|
|
18343
|
+
const result = await import_subscriptions12.codexOAuth.refreshAccessToken(codex.refreshToken, refreshFetch);
|
|
17698
18344
|
const expiresAt = new Date(Date.now() + result.expiresIn * 1e3).toISOString();
|
|
17699
18345
|
const next = {
|
|
17700
18346
|
...codex,
|
|
@@ -17732,7 +18378,7 @@ var JsonSubscriptionCredentialStore = class {
|
|
|
17732
18378
|
this.materializeMigration(config);
|
|
17733
18379
|
const refreshFetch = this.buildRefreshFetch("gemini", capturedId);
|
|
17734
18380
|
try {
|
|
17735
|
-
const result = await
|
|
18381
|
+
const result = await import_subscriptions12.geminiOAuth.refreshAccessToken(gemini.refreshToken, refreshFetch);
|
|
17736
18382
|
const expiresAt = new Date(Date.now() + result.expiresIn * 1e3).toISOString();
|
|
17737
18383
|
const next = {
|
|
17738
18384
|
...gemini,
|
|
@@ -17768,10 +18414,10 @@ var JsonSubscriptionCredentialStore = class {
|
|
|
17768
18414
|
this.materializeMigration(config);
|
|
17769
18415
|
const refreshFetch = this.buildRefreshFetch("kimi", capturedId);
|
|
17770
18416
|
try {
|
|
17771
|
-
const result = await
|
|
18417
|
+
const result = await import_subscriptions12.kimiOAuth.refreshAccessToken(
|
|
17772
18418
|
kimi.refreshToken,
|
|
17773
18419
|
refreshFetch,
|
|
17774
|
-
|
|
18420
|
+
import_subscriptions12.kimiOAuth.kimiFingerprintHeaders(kimi.deviceId)
|
|
17775
18421
|
);
|
|
17776
18422
|
const expiresAt = new Date(Date.now() + result.expiresIn * 1e3).toISOString();
|
|
17777
18423
|
const next = {
|
|
@@ -17808,8 +18454,8 @@ var JsonSubscriptionCredentialStore = class {
|
|
|
17808
18454
|
this.materializeMigration(config);
|
|
17809
18455
|
const refreshFetch = this.buildRefreshFetch("grok", capturedId);
|
|
17810
18456
|
try {
|
|
17811
|
-
const tokenEndpoint = await
|
|
17812
|
-
const result = await
|
|
18457
|
+
const tokenEndpoint = await import_subscriptions12.grokOAuth.resolveGrokTokenEndpoint(refreshFetch);
|
|
18458
|
+
const result = await import_subscriptions12.grokOAuth.refreshGrokAccessToken(grok.refreshToken, tokenEndpoint, refreshFetch);
|
|
17813
18459
|
const expiresAt = new Date(Date.now() + result.expiresIn * 1e3).toISOString();
|
|
17814
18460
|
const next = {
|
|
17815
18461
|
...grok,
|
|
@@ -17852,6 +18498,76 @@ var JsonSubscriptionCredentialStore = class {
|
|
|
17852
18498
|
return false;
|
|
17853
18499
|
});
|
|
17854
18500
|
}
|
|
18501
|
+
/**
|
|
18502
|
+
* Refresh the Antigravity (Google) OAuth access token. Like gemini, the
|
|
18503
|
+
* Google token endpoint does NOT return a refresh_token on refresh, so this
|
|
18504
|
+
* writes ONLY access+expiresAt (+status/lastRefreshedAt) and DELIBERATELY
|
|
18505
|
+
* preserves the stored `refreshToken` — plus the account's `projectId`
|
|
18506
|
+
* (a handshake product; the post-refresh re-validation is the refresh
|
|
18507
|
+
* scheduler's hook, not this write) and `email`. HONEST `false` when no
|
|
18508
|
+
* refresh_token.
|
|
18509
|
+
*/
|
|
18510
|
+
async refreshAntigravityToken() {
|
|
18511
|
+
return this.coalesce("antigravity:active", async () => {
|
|
18512
|
+
const config = this.readConfig();
|
|
18513
|
+
const active = getActiveAccount(config, "antigravity");
|
|
18514
|
+
const antigravity = active?.tokens;
|
|
18515
|
+
if (!active || !antigravity?.refreshToken) return false;
|
|
18516
|
+
const capturedId = active.id;
|
|
18517
|
+
this.materializeMigration(config);
|
|
18518
|
+
const refreshFetch = this.buildRefreshFetch("antigravity", capturedId);
|
|
18519
|
+
try {
|
|
18520
|
+
const result = await import_subscriptions12.antigravityOAuth.refreshAccessToken(antigravity.refreshToken, refreshFetch);
|
|
18521
|
+
const expiresAt = new Date(Date.now() + result.expiresIn * 1e3).toISOString();
|
|
18522
|
+
const next = {
|
|
18523
|
+
...antigravity,
|
|
18524
|
+
// KEEP the existing refreshToken/projectId/email.
|
|
18525
|
+
accessToken: result.accessToken,
|
|
18526
|
+
expiresAt,
|
|
18527
|
+
status: "authorized",
|
|
18528
|
+
lastRefreshedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
18529
|
+
errorMessage: void 0
|
|
18530
|
+
};
|
|
18531
|
+
this.writeBackById("antigravity", capturedId, next);
|
|
18532
|
+
await this.revalidateAntigravityProject(capturedId);
|
|
18533
|
+
return true;
|
|
18534
|
+
} catch (error) {
|
|
18535
|
+
this.markExpiredById("antigravity", capturedId, antigravity, error);
|
|
18536
|
+
return false;
|
|
18537
|
+
}
|
|
18538
|
+
});
|
|
18539
|
+
}
|
|
18540
|
+
/**
|
|
18541
|
+
* Post-refresh project re-validation hook (antigravity design D8): after a
|
|
18542
|
+
* successful antigravity token refresh, re-run the Code Assist project
|
|
18543
|
+
* handshake and write the (possibly rotated) `projectId` back to the account.
|
|
18544
|
+
* A handshake FAILURE keeps the stored projectId untouched (logged) so the
|
|
18545
|
+
* account keeps serving with the last-known-good project until a later
|
|
18546
|
+
* refresh succeeds. Returns whether the handshake produced a project.
|
|
18547
|
+
*/
|
|
18548
|
+
async revalidateAntigravityProject(accountId) {
|
|
18549
|
+
const before = getAccountById(this.readConfig(), "antigravity", accountId);
|
|
18550
|
+
const accessToken = before?.tokens?.accessToken;
|
|
18551
|
+
if (!accessToken) return false;
|
|
18552
|
+
try {
|
|
18553
|
+
const projectId = await (0, import_GeminiCodeAssistProjectResolver5.getAntigravityProjectResolver)().resolveProject(accessToken);
|
|
18554
|
+
if (projectId !== void 0) {
|
|
18555
|
+
const config = this.readConfig();
|
|
18556
|
+
const account = getAccountById(config, "antigravity", accountId);
|
|
18557
|
+
const tokens = account?.tokens;
|
|
18558
|
+
if (account && tokens?.accessToken === accessToken && tokens.projectId !== projectId) {
|
|
18559
|
+
this.writeBackById("antigravity", accountId, { ...tokens, projectId });
|
|
18560
|
+
}
|
|
18561
|
+
return true;
|
|
18562
|
+
}
|
|
18563
|
+
return false;
|
|
18564
|
+
} catch (error) {
|
|
18565
|
+
console.warn(
|
|
18566
|
+
`[JsonSubscriptionCredentialStore] antigravity project re-validation failed for account ${accountId}: ` + (error instanceof Error ? error.message : String(error))
|
|
18567
|
+
);
|
|
18568
|
+
return false;
|
|
18569
|
+
}
|
|
18570
|
+
}
|
|
17855
18571
|
/**
|
|
17856
18572
|
* Refresh a SPECIFIC managed account by id (background scheduler sweep and
|
|
17857
18573
|
* account-pool resolution). It uses only that account's stored refresh
|
|
@@ -17880,6 +18596,7 @@ var JsonSubscriptionCredentialStore = class {
|
|
|
17880
18596
|
};
|
|
17881
18597
|
if (refreshed.idToken) next.idToken = refreshed.idToken;
|
|
17882
18598
|
this.writeBackById(provider, id, next);
|
|
18599
|
+
if (provider === "antigravity") await this.revalidateAntigravityProject(id);
|
|
17883
18600
|
return true;
|
|
17884
18601
|
} catch (error) {
|
|
17885
18602
|
this.markExpiredById(provider, id, captured, error);
|
|
@@ -17904,7 +18621,7 @@ var JsonSubscriptionCredentialStore = class {
|
|
|
17904
18621
|
}
|
|
17905
18622
|
const oauth = account.tokens;
|
|
17906
18623
|
if (!oauth.accessToken) return null;
|
|
17907
|
-
if (providerId === "codex" || providerId === "gemini" || providerId === "kimi" || providerId === "grok" || providerId === "copilot") {
|
|
18624
|
+
if (providerId === "codex" || providerId === "gemini" || providerId === "kimi" || providerId === "grok" || providerId === "copilot" || providerId === "antigravity") {
|
|
17908
18625
|
const expiresAtMs = oauth.expiresAt ? Date.parse(oauth.expiresAt) : 0;
|
|
17909
18626
|
const expiringSoon = expiresAtMs > 0 && Date.now() >= expiresAtMs - ACCOUNT_REFRESH_LEAD_MS;
|
|
17910
18627
|
if (expiringSoon && oauth.refreshToken) {
|
|
@@ -17997,10 +18714,10 @@ var JsonSubscriptionCredentialStore = class {
|
|
|
17997
18714
|
if (provider === "kimi") {
|
|
17998
18715
|
const account = accountId ? getAccountById(this.readConfig(), "kimi", accountId) : void 0;
|
|
17999
18716
|
const deviceId = account?.tokens?.deviceId;
|
|
18000
|
-
const r2 = await
|
|
18717
|
+
const r2 = await import_subscriptions12.kimiOAuth.refreshAccessToken(
|
|
18001
18718
|
refreshToken,
|
|
18002
18719
|
refreshFetch,
|
|
18003
|
-
|
|
18720
|
+
import_subscriptions12.kimiOAuth.kimiFingerprintHeaders(deviceId)
|
|
18004
18721
|
);
|
|
18005
18722
|
return {
|
|
18006
18723
|
accessToken: r2.accessToken,
|
|
@@ -18009,8 +18726,8 @@ var JsonSubscriptionCredentialStore = class {
|
|
|
18009
18726
|
};
|
|
18010
18727
|
}
|
|
18011
18728
|
if (provider === "grok") {
|
|
18012
|
-
const tokenEndpoint = await
|
|
18013
|
-
const r2 = await
|
|
18729
|
+
const tokenEndpoint = await import_subscriptions12.grokOAuth.resolveGrokTokenEndpoint(refreshFetch);
|
|
18730
|
+
const r2 = await import_subscriptions12.grokOAuth.refreshGrokAccessToken(refreshToken, tokenEndpoint, refreshFetch);
|
|
18014
18731
|
return {
|
|
18015
18732
|
accessToken: r2.accessToken,
|
|
18016
18733
|
refreshToken: r2.refreshToken,
|
|
@@ -18020,7 +18737,14 @@ var JsonSubscriptionCredentialStore = class {
|
|
|
18020
18737
|
if (provider === "copilot") {
|
|
18021
18738
|
throw new Error("GitHub Copilot tokens cannot be refreshed \u2014 re-authenticate the account");
|
|
18022
18739
|
}
|
|
18023
|
-
|
|
18740
|
+
if (provider === "antigravity") {
|
|
18741
|
+
const r2 = await import_subscriptions12.antigravityOAuth.refreshAccessToken(refreshToken, refreshFetch);
|
|
18742
|
+
return {
|
|
18743
|
+
accessToken: r2.accessToken,
|
|
18744
|
+
expiresAt: new Date(Date.now() + r2.expiresIn * 1e3).toISOString()
|
|
18745
|
+
};
|
|
18746
|
+
}
|
|
18747
|
+
const flow = provider === "claude" ? import_subscriptions12.claudeOAuth : provider === "codex" ? import_subscriptions12.codexOAuth : import_subscriptions12.geminiOAuth;
|
|
18024
18748
|
const r = await flow.refreshAccessToken(refreshToken, refreshFetch);
|
|
18025
18749
|
return {
|
|
18026
18750
|
accessToken: r.accessToken,
|
|
@@ -18263,7 +18987,7 @@ var JsonSubscriptionCredentialStore = class {
|
|
|
18263
18987
|
};
|
|
18264
18988
|
|
|
18265
18989
|
// src/AccountHealthProbeScheduler.ts
|
|
18266
|
-
var
|
|
18990
|
+
var import_upstreamFetch15 = require("@omnicross/core/pipeline/upstreamFetch");
|
|
18267
18991
|
|
|
18268
18992
|
// src/probe/CodexGenerationProbe.ts
|
|
18269
18993
|
var import_codexCliHeaders = require("@omnicross/core/provider-proxy/identity/codexCliHeaders");
|
|
@@ -18415,7 +19139,11 @@ var PROVIDER_PROBE_PLANS = {
|
|
|
18415
19139
|
// The Copilot quota endpoint (copilot_internal/user) is a verified FREE
|
|
18416
19140
|
// authed GET but lives on api.github.com with its own auth dialect and a
|
|
18417
19141
|
// monthly-only window — the allowance collector owns the health surface.
|
|
18418
|
-
copilot: { kind: "local" }
|
|
19142
|
+
copilot: { kind: "local" },
|
|
19143
|
+
// Antigravity's quota endpoints are POST RPCs on daily-cloudcode-pa (not a
|
|
19144
|
+
// cheap GET) and need the antigravity/hub UA — the allowance collector owns
|
|
19145
|
+
// the health surface; the probe stays local.
|
|
19146
|
+
antigravity: { kind: "local" }
|
|
18419
19147
|
};
|
|
18420
19148
|
function probePlanFor(providerId) {
|
|
18421
19149
|
return PROVIDER_PROBE_PLANS[providerId] ?? { kind: "local" };
|
|
@@ -18437,7 +19165,7 @@ var AccountHealthProbeScheduler = class {
|
|
|
18437
19165
|
this.logger = logger;
|
|
18438
19166
|
this.config = config;
|
|
18439
19167
|
this.now = opts.now ?? Date.now;
|
|
18440
|
-
this.fetchImpl = opts.fetchImpl ??
|
|
19168
|
+
this.fetchImpl = opts.fetchImpl ?? import_upstreamFetch15.fetchUpstream;
|
|
18441
19169
|
this.sleep = opts.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
|
|
18442
19170
|
this.planFor = opts.planFor ?? probePlanFor;
|
|
18443
19171
|
}
|
|
@@ -19593,7 +20321,7 @@ var AuditWriter = class {
|
|
|
19593
20321
|
var import_node_fs34 = require("fs");
|
|
19594
20322
|
var import_node_crypto24 = require("crypto");
|
|
19595
20323
|
var import_node_path34 = require("path");
|
|
19596
|
-
var
|
|
20324
|
+
var import_upstreamFetch16 = require("@omnicross/core/pipeline/upstreamFetch");
|
|
19597
20325
|
|
|
19598
20326
|
// src/billing/billingFiles.ts
|
|
19599
20327
|
var BILLING_FILE_RE = /^billing-(\d{4})-(\d{2})-(\d{2})\.jsonl$/;
|
|
@@ -19616,7 +20344,7 @@ var BillingPublisher = class {
|
|
|
19616
20344
|
constructor(billingDir, logger, opts = {}) {
|
|
19617
20345
|
this.billingDir = billingDir;
|
|
19618
20346
|
this.logger = logger;
|
|
19619
|
-
this.fetchImpl = opts.fetchImpl ?? ((url, init) => (0,
|
|
20347
|
+
this.fetchImpl = opts.fetchImpl ?? ((url, init) => (0, import_upstreamFetch16.fetchUpstream)(url, init));
|
|
19620
20348
|
this.defer = opts.defer ?? ((fn) => setTimeout(fn, 0));
|
|
19621
20349
|
this.timeoutMs = opts.timeoutMs ?? BILLING_POST_TIMEOUT_MS;
|
|
19622
20350
|
this.now = opts.now ?? Date.now;
|
|
@@ -19866,7 +20594,7 @@ var BillingRetrySweeper = class {
|
|
|
19866
20594
|
// src/TokenRefreshScheduler.ts
|
|
19867
20595
|
var REFRESH_LEAD_MS2 = 5 * 6e4;
|
|
19868
20596
|
var SWEEP_INTERVAL_MS5 = 6e4;
|
|
19869
|
-
var OAUTH_PROVIDERS2 = ["claude", "codex", "gemini", "kimi", "grok", "copilot"];
|
|
20597
|
+
var OAUTH_PROVIDERS2 = ["claude", "codex", "gemini", "kimi", "grok", "copilot", "antigravity"];
|
|
19870
20598
|
var TokenRefreshScheduler = class {
|
|
19871
20599
|
constructor(store, logger, intervalMs = SWEEP_INTERVAL_MS5, leadMs = REFRESH_LEAD_MS2) {
|
|
19872
20600
|
this.store = store;
|
|
@@ -19957,6 +20685,8 @@ var TokenRefreshScheduler = class {
|
|
|
19957
20685
|
// never reaches this — the branch exists for union totality.
|
|
19958
20686
|
case "copilot":
|
|
19959
20687
|
return this.store.refreshCopilotToken();
|
|
20688
|
+
case "antigravity":
|
|
20689
|
+
return this.store.refreshAntigravityToken();
|
|
19960
20690
|
}
|
|
19961
20691
|
}
|
|
19962
20692
|
};
|
|
@@ -20033,7 +20763,7 @@ function createRouteLeaseSubscriptionPreflight(credentials) {
|
|
|
20033
20763
|
|
|
20034
20764
|
// src/webhook/WebhookDispatcher.ts
|
|
20035
20765
|
var import_node_crypto25 = require("crypto");
|
|
20036
|
-
var
|
|
20766
|
+
var import_upstreamFetch17 = require("@omnicross/core/pipeline/upstreamFetch");
|
|
20037
20767
|
var WEBHOOK_MAX_ATTEMPTS = 3;
|
|
20038
20768
|
var WEBHOOK_QUEUE_MAX = 1e3;
|
|
20039
20769
|
var WEBHOOK_SEND_TIMEOUT_MS = 1e4;
|
|
@@ -20053,7 +20783,7 @@ var WebhookDispatcher = class {
|
|
|
20053
20783
|
sleep;
|
|
20054
20784
|
now;
|
|
20055
20785
|
constructor(opts = {}) {
|
|
20056
|
-
this.fetchImpl = opts.fetchImpl ?? ((url, init) => (0,
|
|
20786
|
+
this.fetchImpl = opts.fetchImpl ?? ((url, init) => (0, import_upstreamFetch17.fetchUpstream)(url, init));
|
|
20057
20787
|
this.logger = opts.logger;
|
|
20058
20788
|
this.maxAttempts = opts.maxAttempts ?? WEBHOOK_MAX_ATTEMPTS;
|
|
20059
20789
|
this.queueMax = opts.queueMax ?? WEBHOOK_QUEUE_MAX;
|
|
@@ -20139,8 +20869,8 @@ var WebhookDispatcher = class {
|
|
|
20139
20869
|
signal: AbortSignal.timeout(this.timeoutMs)
|
|
20140
20870
|
});
|
|
20141
20871
|
return res.ok ? { ok: true, status: res.status } : { ok: false, status: res.status };
|
|
20142
|
-
} catch (
|
|
20143
|
-
return { ok: false, error:
|
|
20872
|
+
} catch (err9) {
|
|
20873
|
+
return { ok: false, error: err9 instanceof Error ? err9.message : String(err9) };
|
|
20144
20874
|
}
|
|
20145
20875
|
}
|
|
20146
20876
|
/**
|
|
@@ -20277,12 +21007,12 @@ function buildDaemon(config, paths) {
|
|
|
20277
21007
|
setSecretBox(secretBox3);
|
|
20278
21008
|
setSecretBox2(secretBox3);
|
|
20279
21009
|
const decryptedConfig = decryptConfigSecrets(config, secretBox3);
|
|
20280
|
-
const accountAllowanceStore = new
|
|
21010
|
+
const accountAllowanceStore = new import_AccountAllowanceStore11.AccountAllowanceStore(
|
|
20281
21011
|
Date.now,
|
|
20282
21012
|
void 0,
|
|
20283
21013
|
new JsonAccountAllowancePersistence(defaultAccountAllowancePath(paths.configPath))
|
|
20284
21014
|
);
|
|
20285
|
-
(0,
|
|
21015
|
+
(0, import_AccountAllowanceStore11.setSharedAccountAllowanceStore)(accountAllowanceStore);
|
|
20286
21016
|
(0, import_AccountAllowanceScheduling5.getSharedAccountAllowanceScheduling)().configure(
|
|
20287
21017
|
(0, import_outbound_api10.normalizeServerConfig)(decryptedConfig.server).allowanceScheduling
|
|
20288
21018
|
);
|
|
@@ -20307,20 +21037,22 @@ function buildDaemon(config, paths) {
|
|
|
20307
21037
|
claudeAllowanceRefreshScheduler.configure(
|
|
20308
21038
|
(0, import_outbound_api10.normalizeServerConfig)(decryptedConfig.server).allowanceScheduling
|
|
20309
21039
|
);
|
|
20310
|
-
const subscriptionAccounts = new
|
|
20311
|
-
(0,
|
|
20312
|
-
const subscriptionRegistry = new
|
|
21040
|
+
const subscriptionAccounts = new import_subscriptions13.SubscriptionAccountService(credentialStore);
|
|
21041
|
+
(0, import_subscriptions13.setSubscriptionAccountService)(subscriptionAccounts);
|
|
21042
|
+
const subscriptionRegistry = new import_subscriptions13.SubscriptionProviderRegistry(
|
|
20313
21043
|
subscriptionAccounts,
|
|
20314
21044
|
credentialStore
|
|
20315
21045
|
);
|
|
20316
|
-
(0,
|
|
21046
|
+
(0, import_subscriptions13.setSubscriptionProviderRegistry)(subscriptionRegistry);
|
|
20317
21047
|
setServerProxyConfig(decryptedConfig.server?.proxy);
|
|
20318
|
-
(0,
|
|
21048
|
+
(0, import_upstreamFetch18.setUpstreamProxyResolver)(
|
|
20319
21049
|
createUpstreamProxyResolver({
|
|
20320
21050
|
getAccountProxy: (providerId, accountId) => credentialStore.getAccountProxy(providerId, accountId)
|
|
20321
21051
|
})
|
|
20322
21052
|
);
|
|
20323
|
-
(0, import_gemini_code_assist_resolver.setGeminiCodeAssistResolver)((0,
|
|
21053
|
+
(0, import_gemini_code_assist_resolver.setGeminiCodeAssistResolver)((0, import_GeminiCodeAssistProjectResolver6.getGeminiCodeAssistProjectResolver)());
|
|
21054
|
+
(0, import_antigravityFailover.setAntigravitySandboxFailover)(decryptedConfig.antigravity?.sandboxFailover === true);
|
|
21055
|
+
(0, import_openCodeGoHeaders2.setOpenCodeGoUserAgent)(decryptedConfig.opencodego?.userAgent ?? null);
|
|
20324
21056
|
const autoDisableStore = new AutoDisableStore();
|
|
20325
21057
|
const providerKeyQuotaService = new ProviderKeyQuotaService(secretBox3);
|
|
20326
21058
|
const apiKeyPool = new import_ApiKeyPoolService.ApiKeyPoolService(
|
|
@@ -20339,7 +21071,7 @@ function buildDaemon(config, paths) {
|
|
|
20339
21071
|
const pricingEngine = new import_usage2.PricingEngine(pricingStore, logger, {
|
|
20340
21072
|
// Catalog egress follows the same global/env proxy policy as every other
|
|
20341
21073
|
// daemon upstream call; no provider/account override applies here.
|
|
20342
|
-
fetchImpl: ((input, init) => (0,
|
|
21074
|
+
fetchImpl: ((input, init) => (0, import_upstreamFetch18.fetchUpstream)(String(input), init ?? {}))
|
|
20343
21075
|
});
|
|
20344
21076
|
const pricingRefreshScheduler = new PricingRefreshScheduler(
|
|
20345
21077
|
pricingEngine,
|
|
@@ -20581,6 +21313,7 @@ function buildDaemon(config, paths) {
|
|
|
20581
21313
|
outboundApiServer,
|
|
20582
21314
|
imageRuntimeConfig,
|
|
20583
21315
|
imageRuntimeStatus: paths.imageRuntimeStatus ?? imageRuntimeManager,
|
|
21316
|
+
imageLiveVerifier: paths.imageLiveVerifier ?? imageDoctor,
|
|
20584
21317
|
imageConfigAudit: paths.imageConfigAudit ?? ((record) => {
|
|
20585
21318
|
imageObservability.recordConfigurationAudit(record);
|
|
20586
21319
|
}),
|
|
@@ -20624,7 +21357,7 @@ function buildDaemon(config, paths) {
|
|
|
20624
21357
|
// — `server.proxy.byProvider[...]` was silently skipped — and the call was
|
|
20625
21358
|
// excluded from the upstream trace, so a failing login left no evidence.
|
|
20626
21359
|
// `redactBodies` keeps the code/verifier + minted token out of that trace.
|
|
20627
|
-
oauthExchangeFetch: paths.oauthExchangeFetch ? () => paths.oauthExchangeFetch : (providerId) => (url, init) => (0,
|
|
21360
|
+
oauthExchangeFetch: paths.oauthExchangeFetch ? () => paths.oauthExchangeFetch : (providerId) => (url, init) => (0, import_upstreamFetch18.fetchUpstream)(url, init, { providerId, redactBodies: true }),
|
|
20628
21361
|
subscriptionAccountAppender: credentialStore,
|
|
20629
21362
|
// Codex interactive OAuth (app-parity-2 child 5) — the async loopback flow store
|
|
20630
21363
|
// + the one-shot 127.0.0.1:1455 listener. Token captured + persisted daemon-side;
|
|
@@ -20639,6 +21372,21 @@ function buildDaemon(config, paths) {
|
|
|
20639
21372
|
// Grok interactive OAuth — the same async DEVICE-CODE shape as kimi.
|
|
20640
21373
|
grokSessions: new CodexOAuthSessionStore(),
|
|
20641
21374
|
copilotSessions: new CodexOAuthSessionStore(),
|
|
21375
|
+
// Antigravity interactive OAuth — the async LOOPBACK flow store + the
|
|
21376
|
+
// one-shot 127.0.0.1:51121 listener (same shape as codex; test seam below).
|
|
21377
|
+
antigravitySessions: new CodexOAuthSessionStore(),
|
|
21378
|
+
antigravityAwaitLoopback: paths.antigravityAwaitLoopback ?? ((state, timeoutMs, signal) => awaitLoopbackCode(state, timeoutMs, signal, {
|
|
21379
|
+
port: 51121,
|
|
21380
|
+
path: "/oauth-callback",
|
|
21381
|
+
label: "antigravity"
|
|
21382
|
+
})),
|
|
21383
|
+
// The dynamic model-catalog probe's token source (the ACTIVE antigravity
|
|
21384
|
+
// account; refreshed by the by-id near-expiry seam inside the lookup).
|
|
21385
|
+
resolveAntigravityAccessToken: async () => {
|
|
21386
|
+
const config2 = await credentialStore.getFullConfig();
|
|
21387
|
+
const activeId = config2.activeAntigravityAccountId ?? config2.antigravityAccounts?.[0]?.id;
|
|
21388
|
+
return activeId ? credentialStore.getAccessTokenForAccount("antigravity", activeId) : null;
|
|
21389
|
+
},
|
|
20642
21390
|
// Migration pack (app-parity child 6, design D2/D3) — the concrete credential
|
|
20643
21391
|
// store provides BOTH the full DECRYPTED read (`getFullConfig`, export) and
|
|
20644
21392
|
// the multi-account append (`appendProviderAccount`, import re-encrypts at-
|
|
@@ -20697,7 +21445,7 @@ function buildDaemon(config, paths) {
|
|
|
20697
21445
|
});
|
|
20698
21446
|
const webhookDispatcher = new WebhookDispatcher({
|
|
20699
21447
|
logger,
|
|
20700
|
-
fetchImpl: (url, init) => (0,
|
|
21448
|
+
fetchImpl: (url, init) => (0, import_upstreamFetch18.fetchUpstream)(url, init)
|
|
20701
21449
|
});
|
|
20702
21450
|
setWebhookRuntime(webhookDispatcher, (0, import_SubscriptionAccountHealth4.getSharedAccountHealth)());
|
|
20703
21451
|
const auditWriter = new AuditWriter(auditDir, logger);
|
|
@@ -20832,15 +21580,59 @@ function buildClaudeDoctorChecks(config) {
|
|
|
20832
21580
|
});
|
|
20833
21581
|
return checks;
|
|
20834
21582
|
}
|
|
21583
|
+
function buildAntigravityDoctorChecks(snapshot) {
|
|
21584
|
+
const checks = [];
|
|
21585
|
+
checks.push({
|
|
21586
|
+
name: "antigravity credential",
|
|
21587
|
+
ok: snapshot.accountCount > 0 && snapshot.hasAccessToken,
|
|
21588
|
+
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"}`
|
|
21589
|
+
});
|
|
21590
|
+
const expiresAtMs = snapshot.expiresAt ? Date.parse(snapshot.expiresAt) : 0;
|
|
21591
|
+
const expired = snapshot.expired || expiresAtMs > 0 && Date.now() >= expiresAtMs;
|
|
21592
|
+
const expiringSoon = expiresAtMs > 0 && Date.now() >= expiresAtMs - 10 * 6e4;
|
|
21593
|
+
checks.push({
|
|
21594
|
+
name: "token freshness",
|
|
21595
|
+
ok: !expired,
|
|
21596
|
+
warn: !expired && expiringSoon,
|
|
21597
|
+
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)"
|
|
21598
|
+
});
|
|
21599
|
+
return checks;
|
|
21600
|
+
}
|
|
21601
|
+
function hasFreshAntigravityQuota(snapshot, now = Date.now()) {
|
|
21602
|
+
if (!snapshot || snapshot.lastErrorCode) return false;
|
|
21603
|
+
if (snapshot.expiresAt && !(Date.parse(snapshot.expiresAt) > now)) return false;
|
|
21604
|
+
return snapshot.windows.some(
|
|
21605
|
+
(window) => window.state === "fresh" && (!window.resetsAt || Date.parse(window.resetsAt) > now) && (window.disabled === true || typeof window.usedPercent === "number" && Number.isFinite(window.usedPercent))
|
|
21606
|
+
);
|
|
21607
|
+
}
|
|
21608
|
+
function buildAntigravityLiveChecks(result) {
|
|
21609
|
+
return [
|
|
21610
|
+
{
|
|
21611
|
+
name: "token refresh (--live)",
|
|
21612
|
+
ok: result.refreshOk,
|
|
21613
|
+
detail: result.refreshOk ? "the active account refreshed successfully" : "refresh failed (see the daemon log)"
|
|
21614
|
+
},
|
|
21615
|
+
{
|
|
21616
|
+
name: "quota collection (--live)",
|
|
21617
|
+
ok: result.quotaOk,
|
|
21618
|
+
detail: result.quotaOk ? "quotaSummary windows collected" : result.detail
|
|
21619
|
+
}
|
|
21620
|
+
];
|
|
21621
|
+
}
|
|
20835
21622
|
function buildImagesDoctorChecks(snapshot) {
|
|
20836
21623
|
const enabled = snapshot.config.enabled;
|
|
20837
|
-
const
|
|
21624
|
+
const routed = snapshot.config.routedProviders ?? ["codex-subscription"];
|
|
21625
|
+
const codexRouted = routed.includes("codex-subscription");
|
|
21626
|
+
const antigravityRouted = routed.includes("antigravity-subscription");
|
|
21627
|
+
const antigravity = snapshot.antigravityAccount ?? { present: false, usable: false, reason: "missing" };
|
|
21628
|
+
const accountOk = !enabled || !codexRouted || snapshot.account.usable;
|
|
21629
|
+
const antigravityOk = !enabled || !antigravityRouted || antigravity.usable;
|
|
20838
21630
|
const evidenceOk = !enabled || snapshot.evidence.valid && snapshot.evidence.freshEntries > 0;
|
|
20839
21631
|
return [
|
|
20840
21632
|
{
|
|
20841
21633
|
name: "normalized Images config",
|
|
20842
21634
|
ok: snapshot.config.valid,
|
|
20843
|
-
detail: snapshot.config.valid ? `enabled=${enabled},
|
|
21635
|
+
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
21636
|
},
|
|
20845
21637
|
{
|
|
20846
21638
|
name: "private roots",
|
|
@@ -20861,8 +21653,14 @@ function buildImagesDoctorChecks(snapshot) {
|
|
|
20861
21653
|
{
|
|
20862
21654
|
name: "Codex account",
|
|
20863
21655
|
ok: accountOk,
|
|
20864
|
-
warn: !snapshot.account.usable,
|
|
20865
|
-
detail: snapshot.account.usable ? "eligible local credential is present" : `${snapshot.account.reason};
|
|
21656
|
+
warn: enabled && codexRouted && !snapshot.account.usable,
|
|
21657
|
+
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`
|
|
21658
|
+
},
|
|
21659
|
+
{
|
|
21660
|
+
name: "Antigravity account",
|
|
21661
|
+
ok: antigravityOk,
|
|
21662
|
+
warn: enabled && antigravityRouted && !antigravity.usable,
|
|
21663
|
+
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
21664
|
},
|
|
20867
21665
|
{
|
|
20868
21666
|
name: "cached capability evidence",
|
|
@@ -20877,6 +21675,12 @@ async function runImagesLiveDoctor(config, doctor, signal = new AbortController(
|
|
|
20877
21675
|
" [\u26A0] live Images verification may consume subscription quota; one minimal low-quality PNG request will be sent"
|
|
20878
21676
|
);
|
|
20879
21677
|
const result = await doctor.verifyLive(config.images ?? import_outbound_api12.DEFAULT_IMAGES_SERVER_CONFIG, signal);
|
|
21678
|
+
const antigravityRouted = Object.values(config.images?.models ?? {}).includes("antigravity-subscription");
|
|
21679
|
+
if (antigravityRouted) {
|
|
21680
|
+
console.info(
|
|
21681
|
+
" [i] live verification covers the Codex wire only; the Antigravity provider has no independent verifier in v1 (its first real request bootstraps)"
|
|
21682
|
+
);
|
|
21683
|
+
}
|
|
20880
21684
|
if (!result.ok) {
|
|
20881
21685
|
console.info(` [\u2717] live Images verification: ${result.code}`);
|
|
20882
21686
|
return false;
|
|
@@ -21011,14 +21815,49 @@ async function runLiveProbe(url, key, fetchImpl = fetch) {
|
|
|
21011
21815
|
status: res.status,
|
|
21012
21816
|
estimateHeader: res.headers.get("x-omnicross-count-estimate")
|
|
21013
21817
|
};
|
|
21014
|
-
} catch (
|
|
21818
|
+
} catch (err9) {
|
|
21015
21819
|
return {
|
|
21016
21820
|
status: null,
|
|
21017
21821
|
estimateHeader: null,
|
|
21018
|
-
error:
|
|
21822
|
+
error: err9 instanceof Error ? err9.message : String(err9)
|
|
21019
21823
|
};
|
|
21020
21824
|
}
|
|
21021
21825
|
}
|
|
21826
|
+
async function runAntigravityDoctor(daemon, live) {
|
|
21827
|
+
const config = await daemon.credentialStore.getFullConfig();
|
|
21828
|
+
const accounts = config.antigravityAccounts ?? [];
|
|
21829
|
+
const activeId = config.activeAntigravityAccountId ?? accounts[0]?.id;
|
|
21830
|
+
const active = accounts.find((account) => account.id === activeId);
|
|
21831
|
+
const snapshot = {
|
|
21832
|
+
accountCount: accounts.length,
|
|
21833
|
+
...active?.tokens.email ? { activeEmail: active.tokens.email } : {},
|
|
21834
|
+
hasAccessToken: Boolean(active?.tokens.accessToken),
|
|
21835
|
+
expired: active?.tokens.status === "expired",
|
|
21836
|
+
...active?.tokens.expiresAt ? { expiresAt: active.tokens.expiresAt } : {}
|
|
21837
|
+
};
|
|
21838
|
+
const checks = buildAntigravityDoctorChecks(snapshot);
|
|
21839
|
+
if (live && active) {
|
|
21840
|
+
const refreshOk = await daemon.credentialStore.refreshAntigravityToken();
|
|
21841
|
+
let quotaOk = false;
|
|
21842
|
+
let detail = "quotaSummary collection produced no usable windows";
|
|
21843
|
+
try {
|
|
21844
|
+
const snapshots = await daemon.accountAllowanceService.refreshAntigravity(active.id);
|
|
21845
|
+
quotaOk = hasFreshAntigravityQuota(snapshots.find((entry) => entry.accountId === active.id));
|
|
21846
|
+
if (!quotaOk) detail = snapshots[0]?.lastErrorCode ?? detail;
|
|
21847
|
+
} catch (error) {
|
|
21848
|
+
detail = error instanceof Error ? error.message : String(error);
|
|
21849
|
+
}
|
|
21850
|
+
checks.push(...buildAntigravityLiveChecks({ refreshOk, quotaOk, detail }));
|
|
21851
|
+
}
|
|
21852
|
+
console.info("omnicross doctor antigravity \u2014 subscription credential health");
|
|
21853
|
+
let hardFailure = false;
|
|
21854
|
+
for (const check of checks) {
|
|
21855
|
+
const mark = check.ok ? check.warn ? "\u26A0" : "\u2713" : "\u2717";
|
|
21856
|
+
if (!check.ok) hardFailure = true;
|
|
21857
|
+
console.info(` [${mark}] ${check.name}: ${check.detail}`);
|
|
21858
|
+
}
|
|
21859
|
+
return hardFailure ? 1 : 0;
|
|
21860
|
+
}
|
|
21022
21861
|
async function runDoctor(argv, fetchImpl = fetch) {
|
|
21023
21862
|
const { values, positionals } = (0, import_node_util2.parseArgs)({
|
|
21024
21863
|
args: argv,
|
|
@@ -21032,8 +21871,8 @@ async function runDoctor(argv, fetchImpl = fetch) {
|
|
|
21032
21871
|
allowPositionals: true
|
|
21033
21872
|
});
|
|
21034
21873
|
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')`);
|
|
21874
|
+
if (subject !== "claude" && subject !== "images" && subject !== "search" && subject !== "antigravity") {
|
|
21875
|
+
throw new Error(`doctor: unknown subject '${subject}' (supported: 'claude', 'images', 'search', 'antigravity')`);
|
|
21037
21876
|
}
|
|
21038
21877
|
const configPath = values.config;
|
|
21039
21878
|
if (!configPath) {
|
|
@@ -21056,6 +21895,9 @@ async function runDoctor(argv, fetchImpl = fetch) {
|
|
|
21056
21895
|
runtime: daemon.searchRuntime
|
|
21057
21896
|
});
|
|
21058
21897
|
}
|
|
21898
|
+
if (subject === "antigravity") {
|
|
21899
|
+
return await runAntigravityDoctor(daemon, values.live === true);
|
|
21900
|
+
}
|
|
21059
21901
|
const checks = subject === "images" ? buildImagesDoctorChecks(await daemon.imageDoctor.inspectLocal(
|
|
21060
21902
|
serverConfig.images ?? import_outbound_api12.DEFAULT_IMAGES_SERVER_CONFIG
|
|
21061
21903
|
)) : buildClaudeDoctorChecks(serverConfig);
|
|
@@ -21422,9 +22264,9 @@ async function runLaunch(argv, deps) {
|
|
|
21422
22264
|
await daemon.llmConfig.ready();
|
|
21423
22265
|
await daemon.migrateUsageStore();
|
|
21424
22266
|
await daemon.providerProxy.start();
|
|
21425
|
-
} catch (
|
|
22267
|
+
} catch (err9) {
|
|
21426
22268
|
await shutdownLaunchDaemon(daemon);
|
|
21427
|
-
throw
|
|
22269
|
+
throw err9;
|
|
21428
22270
|
}
|
|
21429
22271
|
let launch;
|
|
21430
22272
|
try {
|
|
@@ -21432,9 +22274,9 @@ async function runLaunch(argv, deps) {
|
|
|
21432
22274
|
providerId: values.provider,
|
|
21433
22275
|
model: values.model
|
|
21434
22276
|
});
|
|
21435
|
-
} catch (
|
|
22277
|
+
} catch (err9) {
|
|
21436
22278
|
await shutdownLaunchDaemon(daemon);
|
|
21437
|
-
throw
|
|
22279
|
+
throw err9;
|
|
21438
22280
|
}
|
|
21439
22281
|
try {
|
|
21440
22282
|
const plan = buildCliSpawnPlan({
|
|
@@ -21539,9 +22381,9 @@ function spawnCliInherit(plan) {
|
|
|
21539
22381
|
process.removeListener("SIGINT", onSignal);
|
|
21540
22382
|
process.removeListener("SIGTERM", onSignal);
|
|
21541
22383
|
};
|
|
21542
|
-
child.on("error", (
|
|
22384
|
+
child.on("error", (err9) => {
|
|
21543
22385
|
detach();
|
|
21544
|
-
if (
|
|
22386
|
+
if (err9.code === "ENOENT") {
|
|
21545
22387
|
reject(
|
|
21546
22388
|
new Error(
|
|
21547
22389
|
`launch: "${plan.command}" not found on PATH \u2014 install the CLI first.`
|
|
@@ -21549,7 +22391,7 @@ function spawnCliInherit(plan) {
|
|
|
21549
22391
|
);
|
|
21550
22392
|
return;
|
|
21551
22393
|
}
|
|
21552
|
-
reject(
|
|
22394
|
+
reject(err9);
|
|
21553
22395
|
});
|
|
21554
22396
|
child.on("exit", (code, signal) => {
|
|
21555
22397
|
detach();
|
|
@@ -21562,9 +22404,10 @@ function spawnCliInherit(plan) {
|
|
|
21562
22404
|
var import_node_child_process3 = require("child_process");
|
|
21563
22405
|
var import_node_readline2 = require("readline");
|
|
21564
22406
|
var import_node_util7 = require("util");
|
|
21565
|
-
var
|
|
21566
|
-
var
|
|
21567
|
-
var
|
|
22407
|
+
var import_GeminiCodeAssistProjectResolver7 = require("@omnicross/core/auth/GeminiCodeAssistProjectResolver");
|
|
22408
|
+
var import_upstreamFetch19 = require("@omnicross/core/pipeline/upstreamFetch");
|
|
22409
|
+
var import_subscriptions14 = require("@omnicross/subscriptions");
|
|
22410
|
+
var PROVIDERS2 = ["claude", "codex", "gemini", "kimi", "grok", "copilot", "antigravity"];
|
|
21568
22411
|
async function runLogin(argv, deps) {
|
|
21569
22412
|
const { values, positionals } = (0, import_node_util7.parseArgs)({
|
|
21570
22413
|
args: argv,
|
|
@@ -21591,11 +22434,11 @@ async function runLogin(argv, deps) {
|
|
|
21591
22434
|
if (values.enterprise !== void 0 && provider !== "copilot") {
|
|
21592
22435
|
throw new Error("login: --enterprise is only supported for the copilot provider");
|
|
21593
22436
|
}
|
|
21594
|
-
const enterpriseDomain = values.enterprise !== void 0 ?
|
|
22437
|
+
const enterpriseDomain = values.enterprise !== void 0 ? import_subscriptions14.copilotOAuth.normalizeCopilotEnterpriseDomain(values.enterprise) : void 0;
|
|
21595
22438
|
const resolved = {
|
|
21596
22439
|
openBrowser: deps?.openBrowser ?? openBrowser,
|
|
21597
22440
|
promptPaste: deps?.promptPaste ?? promptPaste,
|
|
21598
|
-
awaitLoopback: deps?.awaitLoopback ?? ((state) => awaitLoopbackCode(state)),
|
|
22441
|
+
awaitLoopback: deps?.awaitLoopback ?? ((state, timeoutMs, signal, binding) => awaitLoopbackCode(state, timeoutMs, signal, binding)),
|
|
21599
22442
|
awaitKimiDevice: deps?.awaitKimiDevice ?? ((fetchImpl) => runKimiDeviceFlow(fetchImpl, resolvedOpenBrowser)),
|
|
21600
22443
|
awaitGrokDevice: deps?.awaitGrokDevice ?? ((fetchImpl) => runGrokDeviceFlow(fetchImpl, resolvedOpenBrowser)),
|
|
21601
22444
|
awaitCopilotDevice: deps?.awaitCopilotDevice ?? ((fetchImpl, enterpriseUrl) => runCopilotDeviceFlow(fetchImpl, resolvedOpenBrowser, enterpriseUrl)),
|
|
@@ -21604,10 +22447,10 @@ async function runLogin(argv, deps) {
|
|
|
21604
22447
|
const resolvedOpenBrowser = resolved.openBrowser;
|
|
21605
22448
|
const box = resolveSecretBox(values["master-key-file"]);
|
|
21606
22449
|
setSecretBox(box);
|
|
21607
|
-
(0,
|
|
22450
|
+
(0, import_upstreamFetch19.setUpstreamProxyResolver)(createUpstreamProxyResolver());
|
|
21608
22451
|
try {
|
|
21609
22452
|
const tokensPath = defaultTokensPath(values.config);
|
|
21610
|
-
const exchangeFetch = resolved.tokensFetch ?? ((url, init) => (0,
|
|
22453
|
+
const exchangeFetch = resolved.tokensFetch ?? ((url, init) => (0, import_upstreamFetch19.fetchUpstream)(url, init, { providerId: provider, redactBodies: true }));
|
|
21611
22454
|
const store = new JsonSubscriptionCredentialStore(tokensPath, box, exchangeFetch);
|
|
21612
22455
|
const expiresAt = await runProviderLogin(
|
|
21613
22456
|
provider,
|
|
@@ -21621,7 +22464,7 @@ async function runLogin(argv, deps) {
|
|
|
21621
22464
|
console.info(` token: [stored, encrypted] expiresAt: ${expiresAt ?? "n/a"}`);
|
|
21622
22465
|
} finally {
|
|
21623
22466
|
setSecretBox(null);
|
|
21624
|
-
(0,
|
|
22467
|
+
(0, import_upstreamFetch19.setUpstreamProxyResolver)(null);
|
|
21625
22468
|
}
|
|
21626
22469
|
}
|
|
21627
22470
|
async function runProviderLogin(provider, store, deps, exchangeFetch, label, enterpriseUrl) {
|
|
@@ -21630,13 +22473,14 @@ async function runProviderLogin(provider, store, deps, exchangeFetch, label, ent
|
|
|
21630
22473
|
if (provider === "kimi") return loginKimi(store, deps, exchangeFetch, label);
|
|
21631
22474
|
if (provider === "grok") return loginGrok(store, deps, exchangeFetch, label);
|
|
21632
22475
|
if (provider === "copilot") return loginCopilot(store, deps, exchangeFetch, label, enterpriseUrl);
|
|
22476
|
+
if (provider === "antigravity") return loginAntigravity(store, deps, exchangeFetch, label);
|
|
21633
22477
|
return loginGemini(store, deps, exchangeFetch, label);
|
|
21634
22478
|
}
|
|
21635
22479
|
async function loginCodex(store, deps, exchangeFetch, label) {
|
|
21636
|
-
const { authUrl, codeVerifier, state } =
|
|
22480
|
+
const { authUrl, codeVerifier, state } = import_subscriptions14.codexOAuth.generateAuthParams();
|
|
21637
22481
|
await presentUrl(authUrl, deps);
|
|
21638
22482
|
const code = await deps.awaitLoopback(state);
|
|
21639
|
-
const result = await
|
|
22483
|
+
const result = await import_subscriptions14.codexOAuth.exchangeCodeForTokens(
|
|
21640
22484
|
{ authorizationCode: code, codeVerifier, state },
|
|
21641
22485
|
exchangeFetch
|
|
21642
22486
|
);
|
|
@@ -21655,7 +22499,7 @@ async function loginCodex(store, deps, exchangeFetch, label) {
|
|
|
21655
22499
|
return expiresAt;
|
|
21656
22500
|
}
|
|
21657
22501
|
async function loginClaude(store, deps, exchangeFetch, label) {
|
|
21658
|
-
const { authUrl, codeVerifier, state } =
|
|
22502
|
+
const { authUrl, codeVerifier, state } = import_subscriptions14.claudeOAuth.generateAuthParams();
|
|
21659
22503
|
await presentUrl(authUrl, deps);
|
|
21660
22504
|
const pasted = (await deps.promptPaste("Paste the authorization code (code#state): ")).trim();
|
|
21661
22505
|
const [code, pastedState] = pasted.split("#");
|
|
@@ -21663,7 +22507,7 @@ async function loginClaude(store, deps, exchangeFetch, label) {
|
|
|
21663
22507
|
if (pastedState && pastedState !== state) {
|
|
21664
22508
|
throw new Error("login: pasted state did not match (possible CSRF) \u2014 aborting");
|
|
21665
22509
|
}
|
|
21666
|
-
const result = await
|
|
22510
|
+
const result = await import_subscriptions14.claudeOAuth.exchangeCodeForTokens(
|
|
21667
22511
|
{ authorizationCode: code, codeVerifier, state },
|
|
21668
22512
|
exchangeFetch
|
|
21669
22513
|
);
|
|
@@ -21682,11 +22526,11 @@ async function loginClaude(store, deps, exchangeFetch, label) {
|
|
|
21682
22526
|
return expiresAt;
|
|
21683
22527
|
}
|
|
21684
22528
|
async function loginGemini(store, deps, exchangeFetch, label) {
|
|
21685
|
-
const { authUrl, codeVerifier } =
|
|
22529
|
+
const { authUrl, codeVerifier } = import_subscriptions14.geminiOAuth.generateAuthParams();
|
|
21686
22530
|
await presentUrl(authUrl, deps);
|
|
21687
22531
|
const code = (await deps.promptPaste("Paste the authorization code: ")).trim();
|
|
21688
22532
|
if (!code) throw new Error("login: no authorization code was pasted");
|
|
21689
|
-
const result = await
|
|
22533
|
+
const result = await import_subscriptions14.geminiOAuth.exchangeCodeForTokens(code, codeVerifier, exchangeFetch);
|
|
21690
22534
|
const expiresAt = new Date(Date.now() + result.expiresIn * 1e3).toISOString();
|
|
21691
22535
|
const block = {
|
|
21692
22536
|
authMethod: "oauth",
|
|
@@ -21701,9 +22545,9 @@ async function loginGemini(store, deps, exchangeFetch, label) {
|
|
|
21701
22545
|
return expiresAt;
|
|
21702
22546
|
}
|
|
21703
22547
|
async function runKimiDeviceFlow(exchangeFetch, openBrowserFn) {
|
|
21704
|
-
const deviceId =
|
|
21705
|
-
const fingerprint =
|
|
21706
|
-
const authorization = await
|
|
22548
|
+
const deviceId = import_subscriptions14.kimiOAuth.generateKimiDeviceId();
|
|
22549
|
+
const fingerprint = import_subscriptions14.kimiOAuth.kimiFingerprintHeaders(deviceId);
|
|
22550
|
+
const authorization = await import_subscriptions14.kimiOAuth.requestDeviceAuthorization(exchangeFetch, fingerprint);
|
|
21707
22551
|
const url = authorization.verificationUriComplete ?? authorization.verificationUri;
|
|
21708
22552
|
console.info("Open this URL in your browser and approve the request:");
|
|
21709
22553
|
console.info(` ${url}`);
|
|
@@ -21711,14 +22555,14 @@ async function runKimiDeviceFlow(exchangeFetch, openBrowserFn) {
|
|
|
21711
22555
|
console.info(` Then enter this code: ${authorization.userCode}`);
|
|
21712
22556
|
}
|
|
21713
22557
|
await openBrowserFn(url).catch(() => false);
|
|
21714
|
-
const result = await
|
|
22558
|
+
const result = await import_subscriptions14.kimiOAuth.awaitDeviceToken(authorization, exchangeFetch, {
|
|
21715
22559
|
fingerprint,
|
|
21716
22560
|
onPending: () => process.stdout.write(".")
|
|
21717
22561
|
});
|
|
21718
22562
|
console.info("");
|
|
21719
22563
|
return {
|
|
21720
22564
|
...result,
|
|
21721
|
-
accountId:
|
|
22565
|
+
accountId: import_subscriptions14.kimiOAuth.kimiAccountIdFromAccessToken(result.accessToken),
|
|
21722
22566
|
deviceId
|
|
21723
22567
|
};
|
|
21724
22568
|
}
|
|
@@ -21740,8 +22584,8 @@ async function loginKimi(store, deps, exchangeFetch, label) {
|
|
|
21740
22584
|
return expiresAt;
|
|
21741
22585
|
}
|
|
21742
22586
|
async function runGrokDeviceFlow(exchangeFetch, openBrowserFn) {
|
|
21743
|
-
const tokenEndpoint = await
|
|
21744
|
-
const authorization = await
|
|
22587
|
+
const tokenEndpoint = await import_subscriptions14.grokOAuth.resolveGrokTokenEndpoint(exchangeFetch);
|
|
22588
|
+
const authorization = await import_subscriptions14.grokOAuth.requestGrokDeviceAuthorization(exchangeFetch);
|
|
21745
22589
|
const url = authorization.verificationUriComplete ?? authorization.verificationUri;
|
|
21746
22590
|
console.info("Open this URL in your browser and approve the request:");
|
|
21747
22591
|
console.info(` ${url}`);
|
|
@@ -21749,13 +22593,13 @@ async function runGrokDeviceFlow(exchangeFetch, openBrowserFn) {
|
|
|
21749
22593
|
console.info(` Then enter this code: ${authorization.userCode}`);
|
|
21750
22594
|
}
|
|
21751
22595
|
await openBrowserFn(url).catch(() => false);
|
|
21752
|
-
const result = await
|
|
22596
|
+
const result = await import_subscriptions14.grokOAuth.awaitGrokDeviceToken(authorization, tokenEndpoint, exchangeFetch, {
|
|
21753
22597
|
onPending: () => process.stdout.write(".")
|
|
21754
22598
|
});
|
|
21755
22599
|
console.info("");
|
|
21756
22600
|
return {
|
|
21757
22601
|
...result,
|
|
21758
|
-
accountId:
|
|
22602
|
+
accountId: import_subscriptions14.grokOAuth.grokAccountIdFromAccessToken(result.accessToken)
|
|
21759
22603
|
};
|
|
21760
22604
|
}
|
|
21761
22605
|
async function loginGrok(store, deps, exchangeFetch, label) {
|
|
@@ -21776,28 +22620,28 @@ async function loginGrok(store, deps, exchangeFetch, label) {
|
|
|
21776
22620
|
}
|
|
21777
22621
|
async function runCopilotDeviceFlow(exchangeFetch, openBrowserFn, enterpriseUrl) {
|
|
21778
22622
|
if (enterpriseUrl) console.info(`Using GitHub Enterprise host: ${enterpriseUrl}`);
|
|
21779
|
-
const authorization = await
|
|
22623
|
+
const authorization = await import_subscriptions14.copilotOAuth.requestCopilotDeviceAuthorization(exchangeFetch, enterpriseUrl);
|
|
21780
22624
|
const url = authorization.verificationUri;
|
|
21781
22625
|
console.info("Open this URL in your browser and approve the request:");
|
|
21782
22626
|
console.info(` ${url}`);
|
|
21783
22627
|
console.info(` Then enter this code: ${authorization.userCode}`);
|
|
21784
22628
|
await openBrowserFn(url).catch(() => false);
|
|
21785
|
-
const result = await
|
|
22629
|
+
const result = await import_subscriptions14.copilotOAuth.awaitCopilotDeviceToken(authorization, exchangeFetch, {
|
|
21786
22630
|
onPending: () => process.stdout.write("."),
|
|
21787
22631
|
...enterpriseUrl ? { enterpriseUrl } : {}
|
|
21788
22632
|
});
|
|
21789
22633
|
console.info("");
|
|
21790
|
-
const identity = await
|
|
21791
|
-
const apiEndpoint = await
|
|
22634
|
+
const identity = await import_subscriptions14.copilotOAuth.fetchCopilotIdentity(result.accessToken, exchangeFetch, enterpriseUrl);
|
|
22635
|
+
const apiEndpoint = await import_subscriptions14.copilotOAuth.discoverCopilotApiEndpoint(result.accessToken, exchangeFetch, enterpriseUrl);
|
|
21792
22636
|
console.info("Enabling Copilot models (policy)...");
|
|
21793
|
-
await
|
|
22637
|
+
await import_subscriptions14.copilotOAuth.enableAllCopilotModels(
|
|
21794
22638
|
result.accessToken,
|
|
21795
22639
|
{ apiEndpoint, ...enterpriseUrl ? { enterpriseUrl } : {} },
|
|
21796
22640
|
exchangeFetch
|
|
21797
22641
|
);
|
|
21798
22642
|
return {
|
|
21799
22643
|
accessToken: result.accessToken,
|
|
21800
|
-
expiresIn: Math.floor(
|
|
22644
|
+
expiresIn: Math.floor(import_subscriptions14.copilotOAuth.COPILOT_FAR_FUTURE_MS / 1e3),
|
|
21801
22645
|
...identity,
|
|
21802
22646
|
...apiEndpoint ? { apiEndpoint } : {}
|
|
21803
22647
|
};
|
|
@@ -21823,6 +22667,70 @@ async function loginCopilot(store, deps, exchangeFetch, label, enterpriseUrl) {
|
|
|
21823
22667
|
logMasked("copilot", result.accessToken);
|
|
21824
22668
|
return expiresAt;
|
|
21825
22669
|
}
|
|
22670
|
+
async function loginAntigravity(store, deps, exchangeFetch, label) {
|
|
22671
|
+
const { authUrl, state } = import_subscriptions14.antigravityOAuth.generateAuthParams();
|
|
22672
|
+
await presentUrl(authUrl, deps);
|
|
22673
|
+
const code = await captureAntigravityCode(deps, state);
|
|
22674
|
+
const result = await import_subscriptions14.antigravityOAuth.exchangeCodeForTokens(code, exchangeFetch);
|
|
22675
|
+
const expiresAt = new Date(Date.now() + result.expiresIn * 1e3).toISOString();
|
|
22676
|
+
const email = await import_subscriptions14.antigravityOAuth.fetchUserEmail(result.accessToken, exchangeFetch);
|
|
22677
|
+
console.info("Resolving the Antigravity Cloud Code Assist project...");
|
|
22678
|
+
const projectId = await (0, import_GeminiCodeAssistProjectResolver7.getAntigravityProjectResolver)().resolveProject(result.accessToken);
|
|
22679
|
+
const block = {
|
|
22680
|
+
authMethod: "oauth",
|
|
22681
|
+
status: "authorized",
|
|
22682
|
+
accessToken: result.accessToken,
|
|
22683
|
+
refreshToken: result.refreshToken,
|
|
22684
|
+
expiresAt,
|
|
22685
|
+
...email ? { email } : {},
|
|
22686
|
+
...projectId ? { projectId } : {},
|
|
22687
|
+
lastRefreshedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
22688
|
+
};
|
|
22689
|
+
await store.appendProviderAccount("antigravity", block, label);
|
|
22690
|
+
logMasked("antigravity", result.accessToken);
|
|
22691
|
+
return expiresAt;
|
|
22692
|
+
}
|
|
22693
|
+
async function captureAntigravityCode(deps, state) {
|
|
22694
|
+
try {
|
|
22695
|
+
return await deps.awaitLoopback(state, void 0, void 0, {
|
|
22696
|
+
port: 51121,
|
|
22697
|
+
path: "/oauth-callback",
|
|
22698
|
+
label: "antigravity"
|
|
22699
|
+
});
|
|
22700
|
+
} catch (loopbackError) {
|
|
22701
|
+
const reason = loopbackError instanceof Error ? loopbackError.message : String(loopbackError);
|
|
22702
|
+
console.warn(`(loopback capture unavailable: ${reason})`);
|
|
22703
|
+
console.info(
|
|
22704
|
+
"Paste fallback: after authorizing, copy the failing redirect URL (or just its code parameter) here."
|
|
22705
|
+
);
|
|
22706
|
+
const pasted = (await deps.promptPaste("Paste the authorization code (or redirect URL): ")).trim();
|
|
22707
|
+
if (!pasted) throw new Error("login: no authorization code was pasted");
|
|
22708
|
+
const { code, state: pastedState } = parseAntigravityPaste(pasted);
|
|
22709
|
+
if (!code) throw new Error("login: the pasted value carried no authorization code");
|
|
22710
|
+
if (pastedState && pastedState !== state) {
|
|
22711
|
+
throw new Error("login: pasted state did not match (possible CSRF) \u2014 aborting");
|
|
22712
|
+
}
|
|
22713
|
+
return code;
|
|
22714
|
+
}
|
|
22715
|
+
}
|
|
22716
|
+
function parseAntigravityPaste(pasted) {
|
|
22717
|
+
if (pasted.includes("://")) {
|
|
22718
|
+
try {
|
|
22719
|
+
const url = new URL(pasted);
|
|
22720
|
+
const code = url.searchParams.get("code") ?? "";
|
|
22721
|
+
const state = url.searchParams.get("state") ?? void 0;
|
|
22722
|
+
return { code, ...state ? { state } : {} };
|
|
22723
|
+
} catch {
|
|
22724
|
+
}
|
|
22725
|
+
}
|
|
22726
|
+
if (/^[?]?code=/.test(pasted)) {
|
|
22727
|
+
const params = new URLSearchParams(pasted.replace(/^\?/, ""));
|
|
22728
|
+
const code = params.get("code") ?? "";
|
|
22729
|
+
const state = params.get("state") ?? void 0;
|
|
22730
|
+
return { code, ...state ? { state } : {} };
|
|
22731
|
+
}
|
|
22732
|
+
return { code: pasted };
|
|
22733
|
+
}
|
|
21826
22734
|
function isLoginProvider(value) {
|
|
21827
22735
|
return PROVIDERS2.includes(value);
|
|
21828
22736
|
}
|
|
@@ -22244,7 +23152,11 @@ var TOKEN_FIELDS2 = {
|
|
|
22244
23152
|
claude: ["accessToken", "refreshToken"],
|
|
22245
23153
|
codex: ["accessToken", "refreshToken", "idToken"],
|
|
22246
23154
|
gemini: ["accessToken", "refreshToken"],
|
|
22247
|
-
opencodego: ["apiKey"]
|
|
23155
|
+
opencodego: ["apiKey"],
|
|
23156
|
+
kimi: ["accessToken", "refreshToken"],
|
|
23157
|
+
grok: ["accessToken", "refreshToken"],
|
|
23158
|
+
copilot: ["accessToken", "refreshToken"],
|
|
23159
|
+
antigravity: ["accessToken", "refreshToken"]
|
|
22248
23160
|
};
|
|
22249
23161
|
function walkTokens(raw, fn) {
|
|
22250
23162
|
const next = { ...raw };
|
|
@@ -22528,7 +23440,7 @@ async function main() {
|
|
|
22528
23440
|
process.exitCode = 1;
|
|
22529
23441
|
}
|
|
22530
23442
|
}
|
|
22531
|
-
main().catch((
|
|
22532
|
-
console.error(
|
|
23443
|
+
main().catch((err9) => {
|
|
23444
|
+
console.error(err9 instanceof Error ? err9.message : String(err9));
|
|
22533
23445
|
process.exitCode = 1;
|
|
22534
23446
|
});
|