@omnicross/daemon 0.3.1 → 0.4.1

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.js CHANGED
@@ -1156,7 +1156,7 @@ import { dirname as dirname17 } from "path";
1156
1156
  import { DEFAULT_AUDIT_CONFIG } from "@omnicross/contracts/audit-types";
1157
1157
  import { DEFAULT_BILLING_CONFIG } from "@omnicross/contracts/billing-types";
1158
1158
  import { OpenAIOperationRegistry } from "@omnicross/core";
1159
- import { getGeminiCodeAssistProjectResolver } from "@omnicross/core/auth/GeminiCodeAssistProjectResolver";
1159
+ import { getGeminiCodeAssistProjectResolver as getGeminiCodeAssistProjectResolver2 } from "@omnicross/core/auth/GeminiCodeAssistProjectResolver";
1160
1160
  import { ApiKeyPoolService } from "@omnicross/core/completion/ApiKeyPoolService";
1161
1161
  import {
1162
1162
  __resetOutboundApiServerForTests,
@@ -1170,14 +1170,14 @@ import { setSubscriptionRegistryForOutbound } from "@omnicross/core/outbound-api
1170
1170
  import { getSharedAccountHealth as getSharedAccountHealth4 } from "@omnicross/core/pipeline/SubscriptionAccountHealth";
1171
1171
  import {
1172
1172
  __resetSharedAccountAllowanceStoreForTests,
1173
- AccountAllowanceStore as AccountAllowanceStore6,
1173
+ AccountAllowanceStore as AccountAllowanceStore9,
1174
1174
  setSharedAccountAllowanceStore
1175
1175
  } from "@omnicross/core/pipeline/AccountAllowanceStore";
1176
1176
  import {
1177
1177
  __resetSharedAccountAllowanceSchedulingForTests,
1178
1178
  getSharedAccountAllowanceScheduling as getSharedAccountAllowanceScheduling5
1179
1179
  } from "@omnicross/core/pipeline/AccountAllowanceScheduling";
1180
- import { fetchUpstream as fetchUpstream11, setUpstreamProxyResolver } from "@omnicross/core/pipeline/upstreamFetch";
1180
+ import { fetchUpstream as fetchUpstream14, setUpstreamProxyResolver } from "@omnicross/core/pipeline/upstreamFetch";
1181
1181
  import { __resetSharedIdentityStoreForTests } from "@omnicross/core/provider-proxy/identity/SubscriptionIdentityStore";
1182
1182
  import { setGeminiCodeAssistResolver } from "@omnicross/core/ports/gemini-code-assist-resolver";
1183
1183
  import {
@@ -1382,9 +1382,188 @@ function handleKimiOAuthStatus(sessionId, deps) {
1382
1382
  return { status: 200, body: { state: s.status, ...s.error ? { message: s.error } : {} } };
1383
1383
  }
1384
1384
 
1385
+ // src/admin/accountsGrokOAuth.ts
1386
+ import { grokOAuth } from "@omnicross/subscriptions";
1387
+ function err3(status, message) {
1388
+ return { status, body: { error: { type: "admin_api_error", message } } };
1389
+ }
1390
+ var DEFAULT_GROK_OAUTH_TTL_MS = 15 * 6e4;
1391
+ async function handleGrokOAuthStart(deps) {
1392
+ if (deps.grokSessions.isBusy()) {
1393
+ return err3(409, "a grok sign-in is already in progress \u2014 finish it in the browser or cancel it");
1394
+ }
1395
+ const fetchImpl = deps.oauthExchangeFetch("grok");
1396
+ let tokenEndpoint;
1397
+ try {
1398
+ tokenEndpoint = await grokOAuth.resolveGrokTokenEndpoint(fetchImpl);
1399
+ } catch (e) {
1400
+ const reason = e instanceof Error ? e.message : "OIDC discovery failed";
1401
+ return err3(502, `grok token-endpoint discovery failed: ${reason}`);
1402
+ }
1403
+ let authorization;
1404
+ try {
1405
+ authorization = await grokOAuth.requestGrokDeviceAuthorization(fetchImpl);
1406
+ } catch (e) {
1407
+ const reason = e instanceof Error ? e.message : "device authorization failed";
1408
+ return err3(502, `grok device authorization failed: ${reason}`);
1409
+ }
1410
+ const { sessionId, signal } = deps.grokSessions.begin();
1411
+ void runGrokDevicePoll(sessionId, tokenEndpoint, authorization.deviceCode, signal, deps).catch((e) => {
1412
+ const reason = e instanceof Error ? e.message : "grok sign-in failed";
1413
+ deps.grokSessions.settle(sessionId, "error", reason);
1414
+ });
1415
+ return {
1416
+ status: 200,
1417
+ body: {
1418
+ authUrl: authorization.verificationUriComplete ?? authorization.verificationUri,
1419
+ userCode: authorization.userCode,
1420
+ sessionId
1421
+ }
1422
+ };
1423
+ }
1424
+ async function runGrokDevicePoll(sessionId, tokenEndpoint, deviceCode, signal, deps) {
1425
+ const fetchImpl = deps.oauthExchangeFetch("grok");
1426
+ const result = await grokOAuth.awaitGrokDeviceToken(
1427
+ { userCode: "", deviceCode, verificationUri: "" },
1428
+ tokenEndpoint,
1429
+ fetchImpl,
1430
+ {
1431
+ deadlineMs: DEFAULT_GROK_OAUTH_TTL_MS,
1432
+ sleep: (ms) => new Promise((resolve11, reject) => {
1433
+ const onAbort = () => {
1434
+ clearTimeout(timer);
1435
+ reject(new Error("login: cancelled"));
1436
+ };
1437
+ const timer = setTimeout(() => {
1438
+ signal.removeEventListener("abort", onAbort);
1439
+ resolve11();
1440
+ }, ms);
1441
+ signal.addEventListener("abort", onAbort, { once: true });
1442
+ })
1443
+ }
1444
+ );
1445
+ const block = {
1446
+ authMethod: "oauth",
1447
+ status: "authorized",
1448
+ accessToken: result.accessToken,
1449
+ refreshToken: result.refreshToken,
1450
+ expiresAt: new Date(Date.now() + result.expiresIn * 1e3).toISOString(),
1451
+ accountId: grokOAuth.grokAccountIdFromAccessToken(result.accessToken),
1452
+ lastRefreshedAt: (/* @__PURE__ */ new Date()).toISOString()
1453
+ };
1454
+ await deps.subscriptionAccountAppender.appendProviderAccount("grok", block);
1455
+ deps.grokSessions.settle(sessionId, "done");
1456
+ }
1457
+ function handleGrokOAuthCancel(sessionId, deps) {
1458
+ if (!deps.grokSessions.cancel(sessionId)) return err3(404, "unknown or expired grok sign-in session");
1459
+ return { status: 200, body: { ok: true } };
1460
+ }
1461
+ function handleGrokOAuthStatus(sessionId, deps) {
1462
+ const s = deps.grokSessions.get(sessionId);
1463
+ if (!s) return err3(404, "unknown or expired grok sign-in session");
1464
+ return { status: 200, body: { state: s.status, ...s.error ? { message: s.error } : {} } };
1465
+ }
1466
+
1467
+ // src/admin/accountsCopilotOAuth.ts
1468
+ import { copilotOAuth } from "@omnicross/subscriptions";
1469
+ function err4(status, message) {
1470
+ return { status, body: { error: { type: "admin_api_error", message } } };
1471
+ }
1472
+ var DEFAULT_COPILOT_OAUTH_TTL_MS = 15 * 6e4;
1473
+ async function handleCopilotOAuthStart(deps, enterpriseUrlInput) {
1474
+ if (deps.copilotSessions.isBusy()) {
1475
+ return err4(409, "a copilot sign-in is already in progress \u2014 finish it in the browser or cancel it");
1476
+ }
1477
+ let enterpriseUrl;
1478
+ if (typeof enterpriseUrlInput === "string" && enterpriseUrlInput.trim()) {
1479
+ try {
1480
+ enterpriseUrl = copilotOAuth.normalizeCopilotEnterpriseDomain(enterpriseUrlInput);
1481
+ } catch (e) {
1482
+ const reason = e instanceof Error ? e.message : "invalid GitHub Enterprise domain";
1483
+ return err4(400, `copilot ${reason}`);
1484
+ }
1485
+ }
1486
+ const fetchImpl = deps.oauthExchangeFetch("copilot");
1487
+ let authorization;
1488
+ try {
1489
+ authorization = await copilotOAuth.requestCopilotDeviceAuthorization(fetchImpl, enterpriseUrl);
1490
+ } catch (e) {
1491
+ const reason = e instanceof Error ? e.message : "device authorization failed";
1492
+ return err4(502, `copilot device authorization failed: ${reason}`);
1493
+ }
1494
+ const { sessionId, signal } = deps.copilotSessions.begin();
1495
+ void runCopilotDevicePoll(sessionId, authorization.deviceCode, signal, deps, enterpriseUrl).catch((e) => {
1496
+ const reason = e instanceof Error ? e.message : "copilot sign-in failed";
1497
+ deps.copilotSessions.settle(sessionId, "error", reason);
1498
+ });
1499
+ return {
1500
+ status: 200,
1501
+ body: {
1502
+ authUrl: authorization.verificationUri,
1503
+ userCode: authorization.userCode,
1504
+ sessionId,
1505
+ ...enterpriseUrl ? { enterpriseUrl } : {}
1506
+ }
1507
+ };
1508
+ }
1509
+ async function runCopilotDevicePoll(sessionId, deviceCode, signal, deps, enterpriseUrl) {
1510
+ const fetchImpl = deps.oauthExchangeFetch("copilot");
1511
+ const result = await copilotOAuth.awaitCopilotDeviceToken(
1512
+ { userCode: "", deviceCode, verificationUri: "", interval: 5, expiresIn: 900 },
1513
+ fetchImpl,
1514
+ {
1515
+ deadlineMs: DEFAULT_COPILOT_OAUTH_TTL_MS,
1516
+ ...enterpriseUrl ? { enterpriseUrl } : {},
1517
+ sleep: (ms) => new Promise((resolve11, reject) => {
1518
+ const onAbort = () => {
1519
+ clearTimeout(timer);
1520
+ reject(new Error("login: cancelled"));
1521
+ };
1522
+ const timer = setTimeout(() => {
1523
+ signal.removeEventListener("abort", onAbort);
1524
+ resolve11();
1525
+ }, ms);
1526
+ signal.addEventListener("abort", onAbort, { once: true });
1527
+ })
1528
+ }
1529
+ );
1530
+ const identity = await copilotOAuth.fetchCopilotIdentity(result.accessToken, fetchImpl, enterpriseUrl);
1531
+ const apiEndpoint = await copilotOAuth.discoverCopilotApiEndpoint(result.accessToken, fetchImpl, enterpriseUrl);
1532
+ await copilotOAuth.enableAllCopilotModels(
1533
+ result.accessToken,
1534
+ { apiEndpoint, ...enterpriseUrl ? { enterpriseUrl } : {} },
1535
+ fetchImpl
1536
+ );
1537
+ const block = {
1538
+ authMethod: "oauth",
1539
+ status: "authorized",
1540
+ accessToken: result.accessToken,
1541
+ refreshToken: result.accessToken,
1542
+ expiresAt: new Date(Date.now() + copilotOAuth.COPILOT_FAR_FUTURE_MS).toISOString(),
1543
+ ...identity.accountId ? { accountId: identity.accountId } : {},
1544
+ ...identity.email ? { email: identity.email } : {},
1545
+ ...apiEndpoint ? { apiEndpoint } : {},
1546
+ ...enterpriseUrl ? { enterpriseUrl } : {},
1547
+ lastRefreshedAt: (/* @__PURE__ */ new Date()).toISOString()
1548
+ };
1549
+ await deps.subscriptionAccountAppender.appendProviderAccount("copilot", block);
1550
+ deps.copilotSessions.settle(sessionId, "done");
1551
+ }
1552
+ function handleCopilotOAuthCancel(sessionId, deps) {
1553
+ if (!deps.copilotSessions.cancel(sessionId)) {
1554
+ return err4(404, "unknown or expired copilot sign-in session");
1555
+ }
1556
+ return { status: 200, body: { ok: true } };
1557
+ }
1558
+ function handleCopilotOAuthStatus(sessionId, deps) {
1559
+ const s = deps.copilotSessions.get(sessionId);
1560
+ if (!s) return err4(404, "unknown or expired copilot sign-in session");
1561
+ return { status: 200, body: { state: s.status, ...s.error ? { message: s.error } : {} } };
1562
+ }
1563
+
1385
1564
  // src/allowance/AccountAllowanceService.ts
1386
1565
  import {
1387
- getSharedAccountAllowanceStore as getSharedAccountAllowanceStore5
1566
+ getSharedAccountAllowanceStore as getSharedAccountAllowanceStore8
1388
1567
  } from "@omnicross/core/pipeline/AccountAllowanceStore";
1389
1568
  import {
1390
1569
  getSharedAccountAllowanceScheduling
@@ -1987,13 +2166,676 @@ var KimiAllowanceCollector = class {
1987
2166
  now;
1988
2167
  inFlight = /* @__PURE__ */ new Map();
1989
2168
  async collectMany(accounts, options = {}) {
1990
- const settled = await Promise.allSettled(accounts.map((account) => this.collect(account, options)));
2169
+ const settled = await Promise.allSettled(accounts.map((account) => this.collect(account, options)));
2170
+ return settled.flatMap((result) => result.status === "fulfilled" ? [result.value] : []);
2171
+ }
2172
+ collect(account, options = {}) {
2173
+ const now = this.now();
2174
+ if (account.tokens.authMethod !== "oauth") {
2175
+ const existing = this.store.get("kimi", account.id, now);
2176
+ if (existing?.windows.every((window) => window.state === "unsupported")) {
2177
+ return Promise.resolve(existing);
2178
+ }
2179
+ const snapshot = this.unsupportedSnapshot(account.id, now);
2180
+ this.store.set(snapshot);
2181
+ return Promise.resolve(snapshot);
2182
+ }
2183
+ const cached = this.store.get("kimi", account.id, now);
2184
+ if (!options.force && cached && this.isCacheValid(cached, now, options.refreshAheadMs)) {
2185
+ return Promise.resolve(cached);
2186
+ }
2187
+ const running = this.inFlight.get(account.id);
2188
+ if (running) return running;
2189
+ const promise = this.fetchAccount(account.id, account.tokens).catch(() => this.failureSnapshot(account.id, "kimi_usage_request_failed", this.now())).finally(() => this.inFlight.delete(account.id));
2190
+ this.inFlight.set(account.id, promise);
2191
+ return promise;
2192
+ }
2193
+ isCacheValid(snapshot, now, refreshAheadMs) {
2194
+ if (snapshot.windows.every((window) => window.state === "unsupported")) return true;
2195
+ const expiresAt = snapshot.expiresAt ? Date.parse(snapshot.expiresAt) : 0;
2196
+ const ahead = typeof refreshAheadMs === "number" && Number.isFinite(refreshAheadMs) ? Math.max(0, refreshAheadMs) : 0;
2197
+ return Number.isFinite(expiresAt) && expiresAt > now + ahead;
2198
+ }
2199
+ async fetchAccount(accountId, tokens) {
2200
+ let accessToken = await this.credentials.getAccessTokenForAccount("kimi", accountId);
2201
+ if (!accessToken) return this.failureSnapshot(accountId, "kimi_usage_token_unavailable", this.now());
2202
+ let response = await this.request(accountId, accessToken, tokens);
2203
+ if (response.status === 401) {
2204
+ const refreshed = await this.credentials.refreshAccountToken("kimi", accountId);
2205
+ if (!refreshed) return this.failureSnapshot(accountId, "kimi_usage_unauthorized", this.now());
2206
+ accessToken = await this.credentials.getAccessTokenForAccount("kimi", accountId);
2207
+ if (!accessToken) return this.failureSnapshot(accountId, "kimi_usage_token_unavailable", this.now());
2208
+ response = await this.request(accountId, accessToken, tokens);
2209
+ }
2210
+ if (response.status === 403) {
2211
+ const snapshot2 = this.unsupportedSnapshot(accountId, this.now(), "kimi_usage_unsupported");
2212
+ this.store.set(snapshot2);
2213
+ return snapshot2;
2214
+ }
2215
+ if (!response.ok) return this.failureSnapshot(accountId, "kimi_usage_http_error", this.now());
2216
+ let payload;
2217
+ try {
2218
+ payload = await response.json();
2219
+ } catch {
2220
+ return this.failureSnapshot(accountId, "kimi_usage_invalid_response", this.now());
2221
+ }
2222
+ const now = this.now();
2223
+ const windows = parseKimiUsagePayload(payload, now);
2224
+ const snapshot = {
2225
+ providerId: "kimi",
2226
+ accountId,
2227
+ source: "oauth-usage-api",
2228
+ observedAt: new Date(now).toISOString(),
2229
+ expiresAt: new Date(now + KIMI_ALLOWANCE_CACHE_MS).toISOString(),
2230
+ windows: windows.length > 0 ? windows : [
2231
+ { id: "five-hour", label: "5 hours", scope: "all", usedPercent: null, state: "unavailable" },
2232
+ { id: "seven-day", label: "7 days", scope: "all", usedPercent: null, state: "unavailable" }
2233
+ ],
2234
+ ...windows.length > 0 ? {} : { lastErrorCode: "kimi_usage_invalid_response" }
2235
+ };
2236
+ this.store.set(snapshot);
2237
+ return snapshot;
2238
+ }
2239
+ request(accountId, accessToken, tokens) {
2240
+ return this.fetchImpl(KIMI_USAGE_URL, {
2241
+ method: "GET",
2242
+ headers: {
2243
+ Authorization: `Bearer ${accessToken}`,
2244
+ Accept: "application/json",
2245
+ ...kimiFingerprintHeaders(tokens.deviceId)
2246
+ },
2247
+ signal: AbortSignal.timeout(15e3)
2248
+ }, accountId);
2249
+ }
2250
+ failureSnapshot(accountId, code, now) {
2251
+ const existing = this.store.get("kimi", accountId, now);
2252
+ const snapshot = existing ? {
2253
+ ...existing,
2254
+ expiresAt: new Date(now + KIMI_ALLOWANCE_CACHE_MS).toISOString(),
2255
+ windows: existing.windows.map((window) => ({
2256
+ ...window,
2257
+ state: window.state === "unsupported" ? "unsupported" : window.usedPercent !== null || window.resetsAt ? "stale" : "unavailable"
2258
+ })),
2259
+ lastErrorCode: code
2260
+ } : {
2261
+ providerId: "kimi",
2262
+ accountId,
2263
+ source: "oauth-usage-api",
2264
+ observedAt: new Date(now).toISOString(),
2265
+ expiresAt: new Date(now + KIMI_ALLOWANCE_CACHE_MS).toISOString(),
2266
+ windows: [
2267
+ { id: "five-hour", label: "5 hours", scope: "all", usedPercent: null, state: "unavailable" },
2268
+ { id: "seven-day", label: "7 days", scope: "all", usedPercent: null, state: "unavailable" }
2269
+ ],
2270
+ lastErrorCode: code
2271
+ };
2272
+ this.store.set(snapshot);
2273
+ return snapshot;
2274
+ }
2275
+ unsupportedSnapshot(accountId, now, code = "kimi_usage_unsupported_auth") {
2276
+ return {
2277
+ providerId: "kimi",
2278
+ accountId,
2279
+ source: "oauth-usage-api",
2280
+ observedAt: new Date(now).toISOString(),
2281
+ windows: [
2282
+ { id: "five-hour", label: "5 hours", scope: "all", usedPercent: null, state: "unsupported" },
2283
+ { id: "seven-day", label: "7 days", scope: "all", usedPercent: null, state: "unsupported" }
2284
+ ],
2285
+ lastErrorCode: code
2286
+ };
2287
+ }
2288
+ };
2289
+
2290
+ // src/allowance/GrokAllowanceCollector.ts
2291
+ import {
2292
+ getSharedAccountAllowanceStore as getSharedAccountAllowanceStore4
2293
+ } from "@omnicross/core/pipeline/AccountAllowanceStore";
2294
+ import { fetchUpstream as fetchUpstream4 } from "@omnicross/core/pipeline/upstreamFetch";
2295
+ var GROK_ALLOWANCE_CACHE_MS = 5 * 6e4;
2296
+ var GROK_BILLING_BASE = "https://cli-chat-proxy.grok.com";
2297
+ var GROK_BILLING_CREDITS_URL = `${GROK_BILLING_BASE}/v1/billing?format=credits`;
2298
+ var GROK_BILLING_MONTHLY_URL = `${GROK_BILLING_BASE}/v1/billing`;
2299
+ function isRecord2(value) {
2300
+ return !!value && typeof value === "object" && !Array.isArray(value);
2301
+ }
2302
+ function finiteNumber3(value) {
2303
+ if (value === null || value === void 0 || value === "") return void 0;
2304
+ const parsed = typeof value === "number" ? value : Number(value);
2305
+ return Number.isFinite(parsed) && parsed >= 0 ? parsed : void 0;
2306
+ }
2307
+ function percent(value) {
2308
+ const parsed = finiteNumber3(value);
2309
+ return parsed !== void 0 && parsed <= 100 ? parsed : void 0;
2310
+ }
2311
+ function onDemandAmount(value) {
2312
+ return isRecord2(value) ? finiteNumber3(value["val"]) : void 0;
2313
+ }
2314
+ function confirmsNoMonthlyQuota(raw) {
2315
+ const limit = onDemandAmount(raw["monthlyLimit"]);
2316
+ if (limit !== void 0) return limit === 0;
2317
+ return parseWeeklyConfig(raw)?.inferredPercent === true;
2318
+ }
2319
+ function parseWeeklyConfig(raw) {
2320
+ const period = isRecord2(raw["currentPeriod"]) ? raw["currentPeriod"] : void 0;
2321
+ if (!period) return null;
2322
+ const start = typeof period["start"] === "string" ? Date.parse(period["start"]) : Number.NaN;
2323
+ const end = typeof period["end"] === "string" ? Date.parse(period["end"]) : Number.NaN;
2324
+ const type = typeof period["type"] === "string" ? period["type"] : "";
2325
+ if (!Number.isFinite(start) || !Number.isFinite(end) || end <= start) return null;
2326
+ if (!type.toUpperCase().includes("WEEK")) return null;
2327
+ const inferred = raw["creditUsagePercent"] === void 0 || raw["creditUsagePercent"] === null;
2328
+ let creditUsagePercent;
2329
+ if (inferred) {
2330
+ creditUsagePercent = end > Date.now() ? 0 : void 0;
2331
+ } else {
2332
+ creditUsagePercent = percent(raw["creditUsagePercent"]);
2333
+ }
2334
+ if (creditUsagePercent === void 0) return null;
2335
+ return {
2336
+ creditUsagePercent,
2337
+ inferredPercent: inferred,
2338
+ resetsAtMs: end,
2339
+ unified: raw["isUnifiedBillingUser"] === true
2340
+ };
2341
+ }
2342
+ function parseMonthlyConfig(raw) {
2343
+ const start = typeof raw["billingPeriodStart"] === "string" ? Date.parse(raw["billingPeriodStart"]) : Number.NaN;
2344
+ const end = typeof raw["billingPeriodEnd"] === "string" ? Date.parse(raw["billingPeriodEnd"]) : Number.NaN;
2345
+ if (!Number.isFinite(start) || !Number.isFinite(end) || end <= start) return null;
2346
+ const limit = onDemandAmount(raw["monthlyLimit"]);
2347
+ const used = onDemandAmount(raw["used"]);
2348
+ if (limit === void 0 || limit <= 0 || used === void 0) return null;
2349
+ return { used, limit, periodStartMs: start, periodEndMs: end };
2350
+ }
2351
+ function secondsUntil4(instant, now) {
2352
+ if (!instant) return void 0;
2353
+ return Math.max(0, Math.floor((Date.parse(instant) - now) / 1e3));
2354
+ }
2355
+ var MINUTE_MS2 = 6e4;
2356
+ var DAY_MS2 = 864e5;
2357
+ var WEEK_MINUTES = 7 * 24 * 60;
2358
+ function weeklyWindow(config, now) {
2359
+ const resetsAt = new Date(config.resetsAtMs).toISOString();
2360
+ return {
2361
+ id: "seven-day",
2362
+ label: "7 days",
2363
+ scope: "all",
2364
+ usedPercent: config.creditUsagePercent,
2365
+ windowMinutes: WEEK_MINUTES,
2366
+ resetsAt,
2367
+ remainingSeconds: secondsUntil4(resetsAt, now),
2368
+ state: "fresh"
2369
+ };
2370
+ }
2371
+ function monthlyWindow(config, now) {
2372
+ const resetsAt = new Date(config.periodEndMs).toISOString();
2373
+ const days = Math.max(1, Math.round((config.periodEndMs - config.periodStartMs) / DAY_MS2));
2374
+ return {
2375
+ id: "thirty-day",
2376
+ label: days === 30 || days === 31 ? "30 days" : `${days} days`,
2377
+ scope: "all",
2378
+ usedPercent: Math.round(Math.min(100, config.used / config.limit * 100) * 10) / 10,
2379
+ windowMinutes: Math.round((config.periodEndMs - config.periodStartMs) / MINUTE_MS2),
2380
+ resetsAt,
2381
+ remainingSeconds: secondsUntil4(resetsAt, now),
2382
+ state: "fresh"
2383
+ };
2384
+ }
2385
+ function onDemandWindow(raw) {
2386
+ const cap = onDemandAmount(raw["onDemandCap"]);
2387
+ const used = onDemandAmount(raw["onDemandUsed"]);
2388
+ if (cap === void 0 || cap <= 0 || used === void 0) return null;
2389
+ return {
2390
+ id: "on-demand",
2391
+ label: "On-demand",
2392
+ scope: "all",
2393
+ usedPercent: Math.round(Math.min(100, used / cap * 100) * 10) / 10,
2394
+ state: "fresh"
2395
+ };
2396
+ }
2397
+ async function probeBilling(url, accessToken, accountId, fetchImpl) {
2398
+ try {
2399
+ const response = await fetchImpl(url, {
2400
+ method: "GET",
2401
+ headers: {
2402
+ Authorization: `Bearer ${accessToken}`,
2403
+ Accept: "application/json",
2404
+ "X-XAI-Token-Auth": "xai-grok-cli"
2405
+ },
2406
+ redirect: "error",
2407
+ signal: AbortSignal.timeout(15e3)
2408
+ }, accountId);
2409
+ if (!response.ok) return { status: response.status, payload: null };
2410
+ const payload = await response.json();
2411
+ return { status: response.status, payload: isRecord2(payload) ? payload : null };
2412
+ } catch {
2413
+ return { status: 0, payload: null };
2414
+ }
2415
+ }
2416
+ function parseGrokBillingPayloads(creditsPayload, monthlyPayload, now) {
2417
+ const creditsConfig = isRecord2(creditsPayload?.["config"]) ? creditsPayload["config"] : null;
2418
+ const monthlyConfig = isRecord2(monthlyPayload?.["config"]) ? monthlyPayload["config"] : null;
2419
+ let weekly = creditsConfig ? parseWeeklyConfig(creditsConfig) : null;
2420
+ const unifiedFlag = creditsConfig?.["isUnifiedBillingUser"] === true;
2421
+ let monthly = monthlyConfig ? parseMonthlyConfig(monthlyConfig) : null;
2422
+ if (weekly?.inferredPercent && unifiedFlag) {
2423
+ if (monthly) {
2424
+ weekly = null;
2425
+ } else if (!monthlyConfig || !confirmsNoMonthlyQuota(monthlyConfig)) {
2426
+ weekly = null;
2427
+ }
2428
+ }
2429
+ const windows = [];
2430
+ if (weekly) windows.push(weeklyWindow(weekly, now));
2431
+ if (monthly) windows.push(monthlyWindow(monthly, now));
2432
+ const onDemandSource = monthly && monthlyConfig ? monthlyConfig : creditsConfig;
2433
+ const onDemand = onDemandSource ? onDemandWindow(onDemandSource) : null;
2434
+ if (onDemand) windows.push(onDemand);
2435
+ return windows.length > 0 ? windows : null;
2436
+ }
2437
+ var GrokAllowanceCollector = class {
2438
+ constructor(credentials, store = getSharedAccountAllowanceStore4(), fetchImpl = (url, init, accountId) => fetchUpstream4(url, init, { providerId: "grok", accountId, redactBodies: true }), now = Date.now) {
2439
+ this.credentials = credentials;
2440
+ this.store = store;
2441
+ this.fetchImpl = fetchImpl;
2442
+ this.now = now;
2443
+ }
2444
+ credentials;
2445
+ store;
2446
+ fetchImpl;
2447
+ now;
2448
+ inFlight = /* @__PURE__ */ new Map();
2449
+ async collectMany(accounts, options = {}) {
2450
+ const settled = await Promise.allSettled(accounts.map((account) => this.collect(account, options)));
2451
+ return settled.flatMap((result) => result.status === "fulfilled" ? [result.value] : []);
2452
+ }
2453
+ collect(account, options = {}) {
2454
+ const now = this.now();
2455
+ if (account.tokens.authMethod !== "oauth") {
2456
+ const existing = this.store.get("grok", account.id, now);
2457
+ if (existing?.windows.every((window) => window.state === "unsupported")) {
2458
+ return Promise.resolve(existing);
2459
+ }
2460
+ const snapshot = this.unsupportedSnapshot(account.id, now);
2461
+ this.store.set(snapshot);
2462
+ return Promise.resolve(snapshot);
2463
+ }
2464
+ const cached = this.store.get("grok", account.id, now);
2465
+ if (!options.force && cached && this.isCacheValid(cached, now, options.refreshAheadMs)) {
2466
+ return Promise.resolve(cached);
2467
+ }
2468
+ const running = this.inFlight.get(account.id);
2469
+ if (running) return running;
2470
+ const promise = this.fetchAccount(account.id).catch(() => this.failureSnapshot(account.id, "grok_usage_request_failed", this.now())).finally(() => this.inFlight.delete(account.id));
2471
+ this.inFlight.set(account.id, promise);
2472
+ return promise;
2473
+ }
2474
+ isCacheValid(snapshot, now, refreshAheadMs) {
2475
+ if (snapshot.windows.every((window) => window.state === "unsupported")) return true;
2476
+ const expiresAt = snapshot.expiresAt ? Date.parse(snapshot.expiresAt) : 0;
2477
+ const ahead = typeof refreshAheadMs === "number" && Number.isFinite(refreshAheadMs) ? Math.max(0, refreshAheadMs) : 0;
2478
+ return Number.isFinite(expiresAt) && expiresAt > now + ahead;
2479
+ }
2480
+ async fetchAccount(accountId) {
2481
+ const probe = async () => {
2482
+ const accessToken = await this.credentials.getAccessTokenForAccount("grok", accountId);
2483
+ if (!accessToken) return { unauthorized: true, windows: null };
2484
+ const credits = await probeBilling(GROK_BILLING_CREDITS_URL, accessToken, accountId, this.fetchImpl);
2485
+ if (credits.status === 401 || credits.status === 403) return { unauthorized: true, windows: null };
2486
+ const creditsConfig = isRecord2(credits.payload?.["config"]) ? credits.payload["config"] : null;
2487
+ const weekly = creditsConfig ? parseWeeklyConfig(creditsConfig) : null;
2488
+ const monthly = !weekly || creditsConfig?.["isUnifiedBillingUser"] === true ? await probeBilling(GROK_BILLING_MONTHLY_URL, accessToken, accountId, this.fetchImpl) : { status: 200, payload: null };
2489
+ if (monthly.status === 401 || monthly.status === 403) return { unauthorized: true, windows: null };
2490
+ return {
2491
+ unauthorized: false,
2492
+ windows: parseGrokBillingPayloads(credits.payload, monthly.payload, this.now())
2493
+ };
2494
+ };
2495
+ let result = await probe();
2496
+ if (result.unauthorized) {
2497
+ const refreshed = await this.credentials.refreshAccountToken("grok", accountId);
2498
+ if (!refreshed) return this.failureSnapshot(accountId, "grok_usage_unauthorized", this.now());
2499
+ result = await probe();
2500
+ if (result.unauthorized) {
2501
+ return this.failureSnapshot(accountId, "grok_usage_unauthorized", this.now());
2502
+ }
2503
+ }
2504
+ const now = this.now();
2505
+ if (result.windows && result.windows.length > 0) {
2506
+ const snapshot = {
2507
+ providerId: "grok",
2508
+ accountId,
2509
+ source: "oauth-usage-api",
2510
+ observedAt: new Date(now).toISOString(),
2511
+ expiresAt: new Date(now + GROK_ALLOWANCE_CACHE_MS).toISOString(),
2512
+ windows: result.windows
2513
+ };
2514
+ this.store.set(snapshot);
2515
+ return snapshot;
2516
+ }
2517
+ return this.failureSnapshot(accountId, "grok_usage_invalid_response", now);
2518
+ }
2519
+ failureSnapshot(accountId, code, now) {
2520
+ const existing = this.store.get("grok", accountId, now);
2521
+ const snapshot = existing ? {
2522
+ ...existing,
2523
+ expiresAt: new Date(now + GROK_ALLOWANCE_CACHE_MS).toISOString(),
2524
+ windows: existing.windows.map((window) => ({
2525
+ ...window,
2526
+ state: window.state === "unsupported" ? "unsupported" : window.usedPercent !== null || window.resetsAt ? "stale" : "unavailable"
2527
+ })),
2528
+ lastErrorCode: code
2529
+ } : {
2530
+ providerId: "grok",
2531
+ accountId,
2532
+ source: "oauth-usage-api",
2533
+ observedAt: new Date(now).toISOString(),
2534
+ expiresAt: new Date(now + GROK_ALLOWANCE_CACHE_MS).toISOString(),
2535
+ windows: [
2536
+ { id: "seven-day", label: "7 days", scope: "all", usedPercent: null, state: "unavailable" },
2537
+ { id: "thirty-day", label: "30 days", scope: "all", usedPercent: null, state: "unavailable" }
2538
+ ],
2539
+ lastErrorCode: code
2540
+ };
2541
+ this.store.set(snapshot);
2542
+ return snapshot;
2543
+ }
2544
+ unsupportedSnapshot(accountId, now) {
2545
+ return {
2546
+ providerId: "grok",
2547
+ accountId,
2548
+ source: "oauth-usage-api",
2549
+ observedAt: new Date(now).toISOString(),
2550
+ windows: [
2551
+ { id: "seven-day", label: "7 days", scope: "all", usedPercent: null, state: "unsupported" },
2552
+ { id: "thirty-day", label: "30 days", scope: "all", usedPercent: null, state: "unsupported" }
2553
+ ],
2554
+ lastErrorCode: "grok_usage_unsupported_auth"
2555
+ };
2556
+ }
2557
+ };
2558
+
2559
+ // src/allowance/CopilotAllowanceCollector.ts
2560
+ import {
2561
+ getSharedAccountAllowanceStore as getSharedAccountAllowanceStore5
2562
+ } from "@omnicross/core/pipeline/AccountAllowanceStore";
2563
+ import { fetchUpstream as fetchUpstream5 } from "@omnicross/core/pipeline/upstreamFetch";
2564
+ import { COPILOT_GITHUB_HEADERS, copilotGitHubApiBase } from "@omnicross/subscriptions";
2565
+ var COPILOT_ALLOWANCE_CACHE_MS = 5 * 6e4;
2566
+ function isRecord3(value) {
2567
+ return !!value && typeof value === "object" && !Array.isArray(value);
2568
+ }
2569
+ function finiteNumber4(value) {
2570
+ if (value === null || value === void 0 || value === "") return void 0;
2571
+ const parsed = typeof value === "number" ? value : Number(value);
2572
+ return Number.isFinite(parsed) && parsed >= 0 ? parsed : void 0;
2573
+ }
2574
+ function booleanValue(value) {
2575
+ if (typeof value === "boolean") return value;
2576
+ if (value === "true") return true;
2577
+ if (value === "false") return false;
2578
+ return void 0;
2579
+ }
2580
+ function parseQuotaDetail(value) {
2581
+ if (!isRecord3(value)) return null;
2582
+ const entitlement = finiteNumber4(value["entitlement"]);
2583
+ const remaining = finiteNumber4(value["remaining"]);
2584
+ const percentRemaining = finiteNumber4(value["percent_remaining"]);
2585
+ const unlimited = booleanValue(value["unlimited"]);
2586
+ if (entitlement === void 0 || remaining === void 0 || percentRemaining === void 0 || unlimited === void 0) {
2587
+ return null;
2588
+ }
2589
+ return { entitlement, remaining, percentRemaining, unlimited };
2590
+ }
2591
+ function secondsUntil5(instant, now) {
2592
+ if (!instant) return void 0;
2593
+ return Math.max(0, Math.floor((Date.parse(instant) - now) / 1e3));
2594
+ }
2595
+ function parseCopilotUserPayload(payload, now) {
2596
+ if (!isRecord3(payload)) return null;
2597
+ const snapshots = isRecord3(payload["quota_snapshots"]) ? payload["quota_snapshots"] : void 0;
2598
+ if (!snapshots) return null;
2599
+ const resetRaw = payload["quota_reset_date"];
2600
+ const resetsAt = typeof resetRaw === "string" && resetRaw.trim() && Number.isFinite(Date.parse(resetRaw)) ? new Date(Date.parse(resetRaw)).toISOString() : void 0;
2601
+ const windows = [];
2602
+ const premium = parseQuotaDetail(snapshots["premium_interactions"]);
2603
+ if (premium) {
2604
+ const usedPercent = premium.unlimited ? 0 : premium.entitlement > 0 ? Math.round(Math.min(100, (premium.entitlement - premium.remaining) / premium.entitlement * 100) * 10) / 10 : finiteNumber4(premium.percentRemaining) !== void 0 ? Math.round(Math.min(100, Math.max(0, 100 - premium.percentRemaining)) * 10) / 10 : null;
2605
+ if (usedPercent !== null) {
2606
+ windows.push({
2607
+ id: "thirty-day",
2608
+ label: "Monthly",
2609
+ scope: "all",
2610
+ usedPercent,
2611
+ windowMinutes: 30 * 24 * 60,
2612
+ ...resetsAt !== void 0 ? { resetsAt } : {},
2613
+ remainingSeconds: secondsUntil5(resetsAt, now),
2614
+ state: "fresh"
2615
+ });
2616
+ }
2617
+ }
2618
+ const chat = parseQuotaDetail(snapshots["chat"]);
2619
+ if (chat && !chat.unlimited && chat.entitlement > 0) {
2620
+ const usedPercent = Math.round(Math.min(100, (chat.entitlement - chat.remaining) / chat.entitlement * 100) * 10) / 10;
2621
+ windows.push({
2622
+ id: "chat-monthly",
2623
+ label: "Chat (monthly)",
2624
+ scope: "all",
2625
+ usedPercent,
2626
+ windowMinutes: 30 * 24 * 60,
2627
+ ...resetsAt !== void 0 ? { resetsAt } : {},
2628
+ remainingSeconds: secondsUntil5(resetsAt, now),
2629
+ state: "fresh"
2630
+ });
2631
+ }
2632
+ return windows.length > 0 ? windows : null;
2633
+ }
2634
+ function githubApiBase(tokens) {
2635
+ return copilotGitHubApiBase(tokens.enterpriseUrl);
2636
+ }
2637
+ var CopilotAllowanceCollector = class {
2638
+ constructor(credentials, store = getSharedAccountAllowanceStore5(), fetchImpl = (url, init, accountId) => fetchUpstream5(url, init, { providerId: "copilot", accountId, redactBodies: true }), now = Date.now) {
2639
+ this.credentials = credentials;
2640
+ this.store = store;
2641
+ this.fetchImpl = fetchImpl;
2642
+ this.now = now;
2643
+ }
2644
+ credentials;
2645
+ store;
2646
+ fetchImpl;
2647
+ now;
2648
+ inFlight = /* @__PURE__ */ new Map();
2649
+ async collectMany(accounts, options = {}) {
2650
+ const settled = await Promise.allSettled(
2651
+ accounts.map((account) => this.collect(account, options))
2652
+ );
2653
+ return settled.flatMap((result) => result.status === "fulfilled" ? [result.value] : []);
2654
+ }
2655
+ collect(account, options = {}) {
2656
+ const now = this.now();
2657
+ if (account.tokens.authMethod !== "oauth") {
2658
+ const existing = this.store.get("copilot", account.id, now);
2659
+ if (existing?.windows.every((window) => window.state === "unsupported")) {
2660
+ return Promise.resolve(existing);
2661
+ }
2662
+ const snapshot = this.unsupportedSnapshot(account.id, now);
2663
+ this.store.set(snapshot);
2664
+ return Promise.resolve(snapshot);
2665
+ }
2666
+ const cached = this.store.get("copilot", account.id, now);
2667
+ if (!options.force && cached && this.isCacheValid(cached, now, options.refreshAheadMs)) {
2668
+ return Promise.resolve(cached);
2669
+ }
2670
+ const running = this.inFlight.get(account.id);
2671
+ if (running) return running;
2672
+ const promise = this.fetchAccount(account.id, account.tokens).catch(() => this.failureSnapshot(account.id, "copilot_usage_request_failed", this.now())).finally(() => this.inFlight.delete(account.id));
2673
+ this.inFlight.set(account.id, promise);
2674
+ return promise;
2675
+ }
2676
+ isCacheValid(snapshot, now, refreshAheadMs) {
2677
+ if (snapshot.windows.every((window) => window.state === "unsupported")) return true;
2678
+ const expiresAt = snapshot.expiresAt ? Date.parse(snapshot.expiresAt) : 0;
2679
+ const ahead = typeof refreshAheadMs === "number" && Number.isFinite(refreshAheadMs) ? Math.max(0, refreshAheadMs) : 0;
2680
+ return Number.isFinite(expiresAt) && expiresAt > now + ahead;
2681
+ }
2682
+ async fetchAccount(accountId, tokens) {
2683
+ let accessToken = await this.credentials.getAccessTokenForAccount("copilot", accountId);
2684
+ if (!accessToken) return this.failureSnapshot(accountId, "copilot_usage_token_unavailable", this.now());
2685
+ let response = await this.request(accountId, accessToken, tokens);
2686
+ if (response.status === 401 || response.status === 403) {
2687
+ const refreshed = await this.credentials.refreshAccountToken("copilot", accountId);
2688
+ if (!refreshed) return this.failureSnapshot(accountId, "copilot_usage_unauthorized", this.now());
2689
+ accessToken = await this.credentials.getAccessTokenForAccount("copilot", accountId);
2690
+ if (!accessToken) return this.failureSnapshot(accountId, "copilot_usage_token_unavailable", this.now());
2691
+ response = await this.request(accountId, accessToken, tokens);
2692
+ if (response.status === 401 || response.status === 403) {
2693
+ return this.failureSnapshot(accountId, "copilot_usage_unauthorized", this.now());
2694
+ }
2695
+ }
2696
+ if (!response.ok) return this.failureSnapshot(accountId, "copilot_usage_http_error", this.now());
2697
+ let payload;
2698
+ try {
2699
+ payload = await response.json();
2700
+ } catch {
2701
+ return this.failureSnapshot(accountId, "copilot_usage_invalid_response", this.now());
2702
+ }
2703
+ const now = this.now();
2704
+ const windows = parseCopilotUserPayload(payload, now);
2705
+ const snapshot = {
2706
+ providerId: "copilot",
2707
+ accountId,
2708
+ source: "oauth-usage-api",
2709
+ observedAt: new Date(now).toISOString(),
2710
+ expiresAt: new Date(now + COPILOT_ALLOWANCE_CACHE_MS).toISOString(),
2711
+ windows: windows ?? [
2712
+ { id: "thirty-day", label: "Monthly", scope: "all", usedPercent: null, state: "unavailable" }
2713
+ ],
2714
+ ...windows ? {} : { lastErrorCode: "copilot_usage_invalid_response" }
2715
+ };
2716
+ this.store.set(snapshot);
2717
+ return snapshot;
2718
+ }
2719
+ request(accountId, accessToken, tokens) {
2720
+ return this.fetchImpl(`${githubApiBase(tokens)}/copilot_internal/user`, {
2721
+ method: "GET",
2722
+ headers: {
2723
+ Authorization: `Bearer ${accessToken}`,
2724
+ Accept: "application/json",
2725
+ "Content-Type": "application/json",
2726
+ ...COPILOT_GITHUB_HEADERS
2727
+ },
2728
+ signal: AbortSignal.timeout(15e3)
2729
+ }, accountId);
2730
+ }
2731
+ failureSnapshot(accountId, code, now) {
2732
+ const existing = this.store.get("copilot", accountId, now);
2733
+ const snapshot = existing ? {
2734
+ ...existing,
2735
+ expiresAt: new Date(now + COPILOT_ALLOWANCE_CACHE_MS).toISOString(),
2736
+ windows: existing.windows.map((window) => ({
2737
+ ...window,
2738
+ state: window.state === "unsupported" ? "unsupported" : window.usedPercent !== null || window.resetsAt ? "stale" : "unavailable"
2739
+ })),
2740
+ lastErrorCode: code
2741
+ } : {
2742
+ providerId: "copilot",
2743
+ accountId,
2744
+ source: "oauth-usage-api",
2745
+ observedAt: new Date(now).toISOString(),
2746
+ expiresAt: new Date(now + COPILOT_ALLOWANCE_CACHE_MS).toISOString(),
2747
+ windows: [
2748
+ { id: "thirty-day", label: "Monthly", scope: "all", usedPercent: null, state: "unavailable" }
2749
+ ],
2750
+ lastErrorCode: code
2751
+ };
2752
+ this.store.set(snapshot);
2753
+ return snapshot;
2754
+ }
2755
+ unsupportedSnapshot(accountId, now) {
2756
+ return {
2757
+ providerId: "copilot",
2758
+ accountId,
2759
+ source: "oauth-usage-api",
2760
+ observedAt: new Date(now).toISOString(),
2761
+ windows: [
2762
+ { id: "thirty-day", label: "Monthly", scope: "all", usedPercent: null, state: "unsupported" }
2763
+ ],
2764
+ lastErrorCode: "copilot_usage_unsupported_auth"
2765
+ };
2766
+ }
2767
+ };
2768
+
2769
+ // src/allowance/GeminiAllowanceCollector.ts
2770
+ import { getGeminiCodeAssistProjectResolver } from "@omnicross/core/auth/GeminiCodeAssistProjectResolver";
2771
+ import {
2772
+ getSharedAccountAllowanceStore as getSharedAccountAllowanceStore6
2773
+ } from "@omnicross/core/pipeline/AccountAllowanceStore";
2774
+ import { fetchUpstream as fetchUpstream6 } from "@omnicross/core/pipeline/upstreamFetch";
2775
+ import {
2776
+ getGeminiCliIdentityHeaders,
2777
+ resolveCodeAssistEndpoint
2778
+ } from "@omnicross/core/transformer/transformers";
2779
+ var GEMINI_ALLOWANCE_CACHE_MS = 5 * 6e4;
2780
+ function isRecord4(value) {
2781
+ return !!value && typeof value === "object" && !Array.isArray(value);
2782
+ }
2783
+ function secondsUntil6(instant, now) {
2784
+ if (!instant) return void 0;
2785
+ return Math.max(0, Math.floor((Date.parse(instant) - now) / 1e3));
2786
+ }
2787
+ function parseGeminiQuotaPayload(payload, now) {
2788
+ if (!isRecord4(payload)) return null;
2789
+ const buckets = Array.isArray(payload["buckets"]) ? payload["buckets"] : [];
2790
+ const windows = [];
2791
+ const seen = /* @__PURE__ */ new Set();
2792
+ for (const raw of buckets) {
2793
+ if (!isRecord4(raw)) continue;
2794
+ const modelId = typeof raw["modelId"] === "string" && raw["modelId"].trim() ? raw["modelId"].trim() : void 0;
2795
+ const id = `gemini:${modelId ?? "all"}`;
2796
+ if (seen.has(id)) continue;
2797
+ seen.add(id);
2798
+ const fractionRaw = typeof raw["remainingFraction"] === "number" ? raw["remainingFraction"] : Number(raw["remainingFraction"]);
2799
+ const usedPercent = Number.isFinite(fractionRaw) ? Math.round(Math.min(100, Math.max(0, (1 - Math.min(1, Math.max(0, fractionRaw))) * 100)) * 10) / 10 : null;
2800
+ const resetRaw = typeof raw["resetTime"] === "string" && raw["resetTime"].trim() ? raw["resetTime"] : void 0;
2801
+ const resetsAt = resetRaw !== void 0 && Number.isFinite(Date.parse(resetRaw)) ? new Date(Date.parse(resetRaw)).toISOString() : void 0;
2802
+ windows.push({
2803
+ id,
2804
+ label: modelId ? `Gemini ${modelId}` : "Gemini quota",
2805
+ scope: modelId ? "model-family" : "all",
2806
+ ...modelId ? { modelFamily: modelId } : {},
2807
+ usedPercent,
2808
+ ...resetsAt !== void 0 ? { resetsAt } : {},
2809
+ remainingSeconds: secondsUntil6(resetsAt, now),
2810
+ state: "fresh"
2811
+ });
2812
+ }
2813
+ return windows.length > 0 ? windows : null;
2814
+ }
2815
+ var GeminiAllowanceCollector = class {
2816
+ constructor(credentials, store = getSharedAccountAllowanceStore6(), fetchImpl = (url, init, accountId) => fetchUpstream6(url, init, { providerId: "gemini", accountId, redactBodies: true }), now = Date.now, projectResolver = getGeminiCodeAssistProjectResolver()) {
2817
+ this.credentials = credentials;
2818
+ this.store = store;
2819
+ this.fetchImpl = fetchImpl;
2820
+ this.now = now;
2821
+ this.projectResolver = projectResolver;
2822
+ }
2823
+ credentials;
2824
+ store;
2825
+ fetchImpl;
2826
+ now;
2827
+ projectResolver;
2828
+ inFlight = /* @__PURE__ */ new Map();
2829
+ async collectMany(accounts, options = {}) {
2830
+ const settled = await Promise.allSettled(
2831
+ accounts.map((account) => this.collect(account, options))
2832
+ );
1991
2833
  return settled.flatMap((result) => result.status === "fulfilled" ? [result.value] : []);
1992
2834
  }
1993
2835
  collect(account, options = {}) {
1994
2836
  const now = this.now();
1995
2837
  if (account.tokens.authMethod !== "oauth") {
1996
- const existing = this.store.get("kimi", account.id, now);
2838
+ const existing = this.store.get("gemini", account.id, now);
1997
2839
  if (existing?.windows.every((window) => window.state === "unsupported")) {
1998
2840
  return Promise.resolve(existing);
1999
2841
  }
@@ -2001,13 +2843,13 @@ var KimiAllowanceCollector = class {
2001
2843
  this.store.set(snapshot);
2002
2844
  return Promise.resolve(snapshot);
2003
2845
  }
2004
- const cached = this.store.get("kimi", account.id, now);
2846
+ const cached = this.store.get("gemini", account.id, now);
2005
2847
  if (!options.force && cached && this.isCacheValid(cached, now, options.refreshAheadMs)) {
2006
2848
  return Promise.resolve(cached);
2007
2849
  }
2008
2850
  const running = this.inFlight.get(account.id);
2009
2851
  if (running) return running;
2010
- const promise = this.fetchAccount(account.id, account.tokens).catch(() => this.failureSnapshot(account.id, "kimi_usage_request_failed", this.now())).finally(() => this.inFlight.delete(account.id));
2852
+ const promise = this.fetchAccount(account.id).catch(() => this.failureSnapshot(account.id, "gemini_usage_request_failed", this.now())).finally(() => this.inFlight.delete(account.id));
2011
2853
  this.inFlight.set(account.id, promise);
2012
2854
  return promise;
2013
2855
  }
@@ -2017,102 +2859,105 @@ var KimiAllowanceCollector = class {
2017
2859
  const ahead = typeof refreshAheadMs === "number" && Number.isFinite(refreshAheadMs) ? Math.max(0, refreshAheadMs) : 0;
2018
2860
  return Number.isFinite(expiresAt) && expiresAt > now + ahead;
2019
2861
  }
2020
- async fetchAccount(accountId, tokens) {
2021
- let accessToken = await this.credentials.getAccessTokenForAccount("kimi", accountId);
2022
- if (!accessToken) return this.failureSnapshot(accountId, "kimi_usage_token_unavailable", this.now());
2023
- let response = await this.request(accountId, accessToken, tokens);
2024
- if (response.status === 401) {
2025
- const refreshed = await this.credentials.refreshAccountToken("kimi", accountId);
2026
- if (!refreshed) return this.failureSnapshot(accountId, "kimi_usage_unauthorized", this.now());
2027
- accessToken = await this.credentials.getAccessTokenForAccount("kimi", accountId);
2028
- if (!accessToken) return this.failureSnapshot(accountId, "kimi_usage_token_unavailable", this.now());
2029
- response = await this.request(accountId, accessToken, tokens);
2862
+ async fetchAccount(accountId) {
2863
+ let accessToken = await this.credentials.getAccessTokenForAccount("gemini", accountId);
2864
+ if (!accessToken) return this.failureSnapshot(accountId, "gemini_usage_token_unavailable", this.now());
2865
+ let project;
2866
+ try {
2867
+ project = await this.projectResolver.resolveProject(accessToken);
2868
+ } catch {
2869
+ project = void 0;
2030
2870
  }
2031
- if (response.status === 403) {
2032
- const snapshot2 = this.unsupportedSnapshot(accountId, this.now(), "kimi_usage_unsupported");
2033
- this.store.set(snapshot2);
2034
- return snapshot2;
2871
+ let response = await this.request(accountId, accessToken, project);
2872
+ if (response.status === 401 || response.status === 403) {
2873
+ const refreshed = await this.credentials.refreshAccountToken("gemini", accountId);
2874
+ if (!refreshed) return this.failureSnapshot(accountId, "gemini_usage_unauthorized", this.now());
2875
+ accessToken = await this.credentials.getAccessTokenForAccount("gemini", accountId);
2876
+ if (!accessToken) return this.failureSnapshot(accountId, "gemini_usage_token_unavailable", this.now());
2877
+ response = await this.request(accountId, accessToken, project);
2878
+ if (response.status === 401 || response.status === 403) {
2879
+ return this.failureSnapshot(accountId, "gemini_usage_unauthorized", this.now());
2880
+ }
2035
2881
  }
2036
- if (!response.ok) return this.failureSnapshot(accountId, "kimi_usage_http_error", this.now());
2882
+ if (!response.ok) return this.failureSnapshot(accountId, "gemini_usage_http_error", this.now());
2037
2883
  let payload;
2038
2884
  try {
2039
2885
  payload = await response.json();
2040
2886
  } catch {
2041
- return this.failureSnapshot(accountId, "kimi_usage_invalid_response", this.now());
2887
+ return this.failureSnapshot(accountId, "gemini_usage_invalid_response", this.now());
2042
2888
  }
2043
2889
  const now = this.now();
2044
- const windows = parseKimiUsagePayload(payload, now);
2890
+ const windows = parseGeminiQuotaPayload(payload, now);
2045
2891
  const snapshot = {
2046
- providerId: "kimi",
2892
+ providerId: "gemini",
2047
2893
  accountId,
2048
2894
  source: "oauth-usage-api",
2049
2895
  observedAt: new Date(now).toISOString(),
2050
- expiresAt: new Date(now + KIMI_ALLOWANCE_CACHE_MS).toISOString(),
2051
- windows: windows.length > 0 ? windows : [
2052
- { id: "five-hour", label: "5 hours", scope: "all", usedPercent: null, state: "unavailable" },
2053
- { id: "seven-day", label: "7 days", scope: "all", usedPercent: null, state: "unavailable" }
2896
+ expiresAt: new Date(now + GEMINI_ALLOWANCE_CACHE_MS).toISOString(),
2897
+ windows: windows ?? [
2898
+ { id: "gemini-quota", label: "Gemini quota", scope: "all", usedPercent: null, state: "unavailable" }
2054
2899
  ],
2055
- ...windows.length > 0 ? {} : { lastErrorCode: "kimi_usage_invalid_response" }
2900
+ ...windows ? {} : { lastErrorCode: "gemini_usage_invalid_response" }
2056
2901
  };
2057
2902
  this.store.set(snapshot);
2058
2903
  return snapshot;
2059
2904
  }
2060
- request(accountId, accessToken, tokens) {
2061
- return this.fetchImpl(KIMI_USAGE_URL, {
2062
- method: "GET",
2905
+ request(accountId, accessToken, project) {
2906
+ return this.fetchImpl(`${resolveCodeAssistEndpoint()}/v1internal:retrieveUserQuota`, {
2907
+ method: "POST",
2063
2908
  headers: {
2064
2909
  Authorization: `Bearer ${accessToken}`,
2065
2910
  Accept: "application/json",
2066
- ...kimiFingerprintHeaders(tokens.deviceId)
2911
+ "Content-Type": "application/json",
2912
+ ...getGeminiCliIdentityHeaders()
2067
2913
  },
2914
+ body: JSON.stringify(project ? { project } : {}),
2068
2915
  signal: AbortSignal.timeout(15e3)
2069
2916
  }, accountId);
2070
2917
  }
2071
2918
  failureSnapshot(accountId, code, now) {
2072
- const existing = this.store.get("kimi", accountId, now);
2919
+ const existing = this.store.get("gemini", accountId, now);
2073
2920
  const snapshot = existing ? {
2074
2921
  ...existing,
2075
- expiresAt: new Date(now + KIMI_ALLOWANCE_CACHE_MS).toISOString(),
2922
+ expiresAt: new Date(now + GEMINI_ALLOWANCE_CACHE_MS).toISOString(),
2076
2923
  windows: existing.windows.map((window) => ({
2077
2924
  ...window,
2078
2925
  state: window.state === "unsupported" ? "unsupported" : window.usedPercent !== null || window.resetsAt ? "stale" : "unavailable"
2079
2926
  })),
2080
2927
  lastErrorCode: code
2081
2928
  } : {
2082
- providerId: "kimi",
2929
+ providerId: "gemini",
2083
2930
  accountId,
2084
2931
  source: "oauth-usage-api",
2085
2932
  observedAt: new Date(now).toISOString(),
2086
- expiresAt: new Date(now + KIMI_ALLOWANCE_CACHE_MS).toISOString(),
2933
+ expiresAt: new Date(now + GEMINI_ALLOWANCE_CACHE_MS).toISOString(),
2087
2934
  windows: [
2088
- { id: "five-hour", label: "5 hours", scope: "all", usedPercent: null, state: "unavailable" },
2089
- { id: "seven-day", label: "7 days", scope: "all", usedPercent: null, state: "unavailable" }
2935
+ { id: "gemini-quota", label: "Gemini quota", scope: "all", usedPercent: null, state: "unavailable" }
2090
2936
  ],
2091
2937
  lastErrorCode: code
2092
2938
  };
2093
2939
  this.store.set(snapshot);
2094
2940
  return snapshot;
2095
2941
  }
2096
- unsupportedSnapshot(accountId, now, code = "kimi_usage_unsupported_auth") {
2942
+ unsupportedSnapshot(accountId, now) {
2097
2943
  return {
2098
- providerId: "kimi",
2944
+ providerId: "gemini",
2099
2945
  accountId,
2100
2946
  source: "oauth-usage-api",
2101
2947
  observedAt: new Date(now).toISOString(),
2102
2948
  windows: [
2103
- { id: "five-hour", label: "5 hours", scope: "all", usedPercent: null, state: "unsupported" },
2104
- { id: "seven-day", label: "7 days", scope: "all", usedPercent: null, state: "unsupported" }
2949
+ { id: "gemini-quota", label: "Gemini quota", scope: "all", usedPercent: null, state: "unsupported" }
2105
2950
  ],
2106
- lastErrorCode: code
2951
+ lastErrorCode: "gemini_usage_unsupported_auth"
2107
2952
  };
2108
2953
  }
2109
2954
  };
2110
2955
 
2111
2956
  // src/allowance/OpenCodeGoAllowanceCollector.ts
2112
2957
  import {
2113
- getSharedAccountAllowanceStore as getSharedAccountAllowanceStore4
2958
+ getSharedAccountAllowanceStore as getSharedAccountAllowanceStore7
2114
2959
  } from "@omnicross/core/pipeline/AccountAllowanceStore";
2115
- import { fetchUpstream as fetchUpstream4 } from "@omnicross/core/pipeline/upstreamFetch";
2960
+ import { fetchUpstream as fetchUpstream7 } from "@omnicross/core/pipeline/upstreamFetch";
2116
2961
  import { normalizeOpenCodeGoBaseUrl } from "@omnicross/subscriptions";
2117
2962
  var OPENCODEGO_ALLOWANCE_CACHE_MS = 5 * 6e4;
2118
2963
  var OPENCODEGO_DEFAULT_GO_BASE = "https://opencode.ai/zen/go";
@@ -2126,7 +2971,7 @@ function isoInstant2(value) {
2126
2971
  const time = Date.parse(value);
2127
2972
  return Number.isFinite(time) ? new Date(time).toISOString() : void 0;
2128
2973
  }
2129
- function secondsUntil4(instant, now) {
2974
+ function secondsUntil7(instant, now) {
2130
2975
  if (!instant) return void 0;
2131
2976
  return Math.max(0, Math.floor((Date.parse(instant) - now) / 1e3));
2132
2977
  }
@@ -2141,12 +2986,12 @@ function windowFromPayload3(id, label, minutes, payload, now) {
2141
2986
  usedPercent,
2142
2987
  windowMinutes: minutes,
2143
2988
  ...resetsAt !== void 0 ? { resetsAt } : {},
2144
- remainingSeconds: secondsUntil4(resetsAt, now),
2989
+ remainingSeconds: secondsUntil7(resetsAt, now),
2145
2990
  state: usedPercent !== null || resetsAt ? "fresh" : "unavailable"
2146
2991
  };
2147
2992
  }
2148
2993
  var OpenCodeGoAllowanceCollector = class {
2149
- constructor(credentials, store = getSharedAccountAllowanceStore4(), fetchImpl = (url, init, accountId) => fetchUpstream4(url, init, { providerId: "opencodego", accountId, redactBodies: true }), now = Date.now) {
2994
+ constructor(credentials, store = getSharedAccountAllowanceStore7(), fetchImpl = (url, init, accountId) => fetchUpstream7(url, init, { providerId: "opencodego", accountId, redactBodies: true }), now = Date.now) {
2150
2995
  this.credentials = credentials;
2151
2996
  this.store = store;
2152
2997
  this.fetchImpl = fetchImpl;
@@ -2251,7 +3096,7 @@ function codexUnavailable(accountId, now) {
2251
3096
  };
2252
3097
  }
2253
3098
  var AccountAllowanceService = class {
2254
- constructor(credentials, store = getSharedAccountAllowanceStore5(), collector, codexCollector, kimiCollector, opencodegoCollector, now = Date.now) {
3099
+ constructor(credentials, store = getSharedAccountAllowanceStore8(), collector, codexCollector, kimiCollector, opencodegoCollector, grokCollector, copilotCollector, geminiCollector, now = Date.now) {
2255
3100
  this.credentials = credentials;
2256
3101
  this.store = store;
2257
3102
  this.now = now;
@@ -2259,6 +3104,9 @@ var AccountAllowanceService = class {
2259
3104
  this.codexCollector = codexCollector ?? new CodexAllowanceCollector(credentials, store);
2260
3105
  this.kimiCollector = kimiCollector ?? new KimiAllowanceCollector(credentials, store);
2261
3106
  this.opencodegoCollector = opencodegoCollector ?? new OpenCodeGoAllowanceCollector(credentials, store);
3107
+ this.grokCollector = grokCollector ?? new GrokAllowanceCollector(credentials, store);
3108
+ this.copilotCollector = copilotCollector ?? new CopilotAllowanceCollector(credentials, store);
3109
+ this.geminiCollector = geminiCollector ?? new GeminiAllowanceCollector(credentials, store);
2262
3110
  }
2263
3111
  credentials;
2264
3112
  store;
@@ -2266,7 +3114,10 @@ var AccountAllowanceService = class {
2266
3114
  claudeCollector;
2267
3115
  codexCollector;
2268
3116
  kimiCollector;
3117
+ grokCollector;
3118
+ copilotCollector;
2269
3119
  opencodegoCollector;
3120
+ geminiCollector;
2270
3121
  /**
2271
3122
  * Read all/filtered snapshots. Claude's and Codex's five-minute caches are
2272
3123
  * refreshed lazily on read (Codex polls `/backend-api/wham/usage`; the
@@ -2300,11 +3151,29 @@ var AccountAllowanceService = class {
2300
3151
  (account) => !filter.accountId || account.id === filter.accountId
2301
3152
  );
2302
3153
  if (wantsOpenCodeGo) await this.opencodegoCollector.collectMany(opencodegoAccounts);
3154
+ const wantsGrok = !filter.providerId || filter.providerId === "grok";
3155
+ const grokAccounts = (config.grokAccounts ?? []).filter(
3156
+ (account) => !filter.accountId || account.id === filter.accountId
3157
+ );
3158
+ if (wantsGrok) await this.grokCollector.collectMany(grokAccounts);
3159
+ const wantsCopilot = !filter.providerId || filter.providerId === "copilot";
3160
+ const copilotAccounts = (config.copilotAccounts ?? []).filter(
3161
+ (account) => !filter.accountId || account.id === filter.accountId
3162
+ );
3163
+ if (wantsCopilot) await this.copilotCollector.collectMany(copilotAccounts);
3164
+ const wantsGemini = !filter.providerId || filter.providerId === "gemini";
3165
+ const geminiAccounts = (config.geminiAccounts ?? []).filter(
3166
+ (account) => !filter.accountId || account.id === filter.accountId
3167
+ );
3168
+ if (wantsGemini) await this.geminiCollector.collectMany(geminiAccounts);
2303
3169
  const known = /* @__PURE__ */ new Set();
2304
3170
  if (wantsClaude) for (const account of claudeAccounts) known.add(`claude\0${account.id}`);
2305
3171
  if (wantsCodex) for (const account of codexAccounts) known.add(`codex\0${account.id}`);
2306
3172
  if (wantsKimi) for (const account of kimiAccounts) known.add(`kimi\0${account.id}`);
2307
3173
  if (wantsOpenCodeGo) for (const account of opencodegoAccounts) known.add(`opencodego\0${account.id}`);
3174
+ if (wantsGrok) for (const account of grokAccounts) known.add(`grok\0${account.id}`);
3175
+ if (wantsCopilot) for (const account of copilotAccounts) known.add(`copilot\0${account.id}`);
3176
+ if (wantsGemini) for (const account of geminiAccounts) known.add(`gemini\0${account.id}`);
2308
3177
  return this.store.list(filter).filter((snapshot) => known.has(`${snapshot.providerId}\0${snapshot.accountId}`));
2309
3178
  }
2310
3179
  knownAccounts(config) {
@@ -2312,7 +3181,10 @@ var AccountAllowanceService = class {
2312
3181
  ...(config.claudeAccounts ?? []).map((account) => ({ providerId: "claude", accountId: account.id })),
2313
3182
  ...(config.codexAccounts ?? []).map((account) => ({ providerId: "codex", accountId: account.id })),
2314
3183
  ...(config.kimiAccounts ?? []).map((account) => ({ providerId: "kimi", accountId: account.id })),
2315
- ...(config.opencodegoAccounts ?? []).map((account) => ({ providerId: "opencodego", accountId: account.id }))
3184
+ ...(config.opencodegoAccounts ?? []).map((account) => ({ providerId: "opencodego", accountId: account.id })),
3185
+ ...(config.grokAccounts ?? []).map((account) => ({ providerId: "grok", accountId: account.id })),
3186
+ ...(config.copilotAccounts ?? []).map((account) => ({ providerId: "copilot", accountId: account.id })),
3187
+ ...(config.geminiAccounts ?? []).map((account) => ({ providerId: "gemini", accountId: account.id }))
2316
3188
  ];
2317
3189
  }
2318
3190
  /** Force-refresh Claude usage for one account or every stored Claude account. */
@@ -2355,6 +3227,33 @@ var AccountAllowanceService = class {
2355
3227
  );
2356
3228
  return this.kimiCollector.collectMany(accounts, { force: true });
2357
3229
  }
3230
+ /** Force-refresh Copilot usage (copilot_internal/user) for one/all accounts. */
3231
+ async refreshCopilot(accountId) {
3232
+ const config = await this.credentials.getFullConfig();
3233
+ this.store.pruneToKnownAccounts(this.knownAccounts(config));
3234
+ const accounts = (config.copilotAccounts ?? []).filter(
3235
+ (account) => !accountId || account.id === accountId
3236
+ );
3237
+ return this.copilotCollector.collectMany(accounts, { force: true });
3238
+ }
3239
+ /** Force-refresh Grok usage (CLI billing proxy) for one/all accounts. */
3240
+ async refreshGrok(accountId) {
3241
+ const config = await this.credentials.getFullConfig();
3242
+ this.store.pruneToKnownAccounts(this.knownAccounts(config));
3243
+ const accounts = (config.grokAccounts ?? []).filter(
3244
+ (account) => !accountId || account.id === accountId
3245
+ );
3246
+ return this.grokCollector.collectMany(accounts, { force: true });
3247
+ }
3248
+ /** Force-refresh Gemini usage (Code Assist retrieveUserQuota) for one/all accounts. */
3249
+ async refreshGemini(accountId) {
3250
+ const config = await this.credentials.getFullConfig();
3251
+ this.store.pruneToKnownAccounts(this.knownAccounts(config));
3252
+ const accounts = (config.geminiAccounts ?? []).filter(
3253
+ (account) => !accountId || account.id === accountId
3254
+ );
3255
+ return this.geminiCollector.collectMany(accounts, { force: true });
3256
+ }
2358
3257
  /**
2359
3258
  * Keep Claude + Codex + Kimi snapshots warm for allowance-aware routing. All
2360
3259
  * collectors preserve their cache + per-account in-flight coalescing; a tick
@@ -2369,6 +3268,9 @@ var AccountAllowanceService = class {
2369
3268
  await this.codexCollector.collectMany(config.codexAccounts ?? [], { refreshAheadMs });
2370
3269
  await this.kimiCollector.collectMany(config.kimiAccounts ?? [], { refreshAheadMs });
2371
3270
  await this.opencodegoCollector.collectMany(config.opencodegoAccounts ?? [], { refreshAheadMs });
3271
+ await this.grokCollector.collectMany(config.grokAccounts ?? [], { refreshAheadMs });
3272
+ await this.copilotCollector.collectMany(config.copilotAccounts ?? [], { refreshAheadMs });
3273
+ await this.geminiCollector.collectMany(config.geminiAccounts ?? [], { refreshAheadMs });
2372
3274
  }
2373
3275
  /** Remove a cache row as soon as an account is deleted by the admin path. */
2374
3276
  removeAccountSnapshot(providerId, accountId) {
@@ -2798,7 +3700,8 @@ import {
2798
3700
  } from "@omnicross/contracts/image-generation-types";
2799
3701
  import { getSharedAccountAllowanceScheduling as getSharedAccountAllowanceScheduling2 } from "@omnicross/core/pipeline/AccountAllowanceScheduling";
2800
3702
  import { getSharedAccountHealth } from "@omnicross/core/pipeline/SubscriptionAccountHealth";
2801
- import { fetchUpstream as fetchUpstream5 } from "@omnicross/core/pipeline/upstreamFetch";
3703
+ import { fetchUpstream as fetchUpstream8 } from "@omnicross/core/pipeline/upstreamFetch";
3704
+ import { mergeExtraHeaders } from "@omnicross/core";
2802
3705
 
2803
3706
  // src/image-generation/imagesConfigValidation.ts
2804
3707
  import { validateImagesServerConfig } from "@omnicross/core/outbound-api";
@@ -3111,6 +4014,7 @@ async function applyServerConfigTransaction(current, next, deps) {
3111
4014
 
3112
4015
  // src/config.ts
3113
4016
  import { readFileSync as readFileSync5, writeFileSync as writeFileSync4 } from "fs";
4017
+ import { EXTRA_HEADER_RESERVED_NAMES } from "@omnicross/core";
3114
4018
  var DEFAULT_ADMIN_PORT = 8766;
3115
4019
  function validateAdmin(raw) {
3116
4020
  if (!raw || typeof raw !== "object" || Array.isArray(raw)) return void 0;
@@ -3167,6 +4071,18 @@ var FORMAT_AXIS_TRANSFORMERS = [
3167
4071
  "openai-response",
3168
4072
  "gemini-code-assist"
3169
4073
  ];
4074
+ function validateExtraHeaders(raw) {
4075
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return void 0;
4076
+ const reserved = EXTRA_HEADER_RESERVED_NAMES;
4077
+ const out = {};
4078
+ for (const [name, value] of Object.entries(raw)) {
4079
+ if (!name.trim()) continue;
4080
+ if (typeof value !== "string") continue;
4081
+ if (reserved.has(name.toLowerCase())) continue;
4082
+ out[name] = value;
4083
+ }
4084
+ return Object.keys(out).length > 0 ? out : void 0;
4085
+ }
3170
4086
  function validateApiKeys(raw) {
3171
4087
  if (!Array.isArray(raw)) return void 0;
3172
4088
  const out = [];
@@ -3380,6 +4296,9 @@ function validateProvider(raw, index) {
3380
4296
  apiVersion,
3381
4297
  maxConcurrency,
3382
4298
  modelsEndpoint,
4299
+ // Static extra headers: load-guard (reserved names dropped), collapse-to-
4300
+ // undefined; enforced by the outbound header funnel + admin probes.
4301
+ extraHeaders: validateExtraHeaders(p["extraHeaders"]),
3383
4302
  // Provider transformer config (app-parity child 5): load-guard, collapse-to-
3384
4303
  // undefined; non-secret; ENFORCED via resolveTransformerChain (parity-2 child 2).
3385
4304
  // Format-axis entries are stripped by `migrateFormatAxis` — `use[]` is the
@@ -4344,7 +5263,10 @@ function mapPresetToProvider(preset, opts) {
4344
5263
  apiFormat: resolved.format,
4345
5264
  baseUrl: opts.baseUrlOverride ?? preset.api_base_url,
4346
5265
  apiKey: opts.key,
4347
- models: Array.isArray(preset.models) ? preset.models : void 0
5266
+ models: Array.isArray(preset.models) ? preset.models : void 0,
5267
+ // Static identity headers (e.g. the Cline client set) survive the mapping —
5268
+ // the CLI-seeded row needs them as much as an admin-API-created one.
5269
+ extraHeaders: preset.extraHeaders
4348
5270
  };
4349
5271
  return { provider };
4350
5272
  }
@@ -4369,7 +5291,8 @@ function listMappablePresets() {
4369
5291
  description: preset.description,
4370
5292
  features: preset.features,
4371
5293
  website: preset.website,
4372
- modelsEndpoint: preset.modelsEndpoint
5294
+ modelsEndpoint: preset.modelsEndpoint,
5295
+ extraHeaders: preset.extraHeaders
4373
5296
  });
4374
5297
  }
4375
5298
  return { mappable, excluded };
@@ -4541,7 +5464,9 @@ var VALID_PROVIDER_IDS = [
4541
5464
  "codex",
4542
5465
  "gemini",
4543
5466
  "opencodego",
4544
- "kimi"
5467
+ "kimi",
5468
+ "grok",
5469
+ "copilot"
4545
5470
  ];
4546
5471
  function asSubscriptionProviderId(id) {
4547
5472
  return VALID_PROVIDER_IDS.includes(id) ? id : null;
@@ -4689,6 +5614,40 @@ function validateKimi(body) {
4689
5614
  copyOptional(out, body, ["accessToken", "refreshToken", "expiresAt", "accountId", "deviceId", "lastRefreshedAt", "errorMessage"]);
4690
5615
  return out;
4691
5616
  }
5617
+ function validateGrok(body) {
5618
+ const authMethod = str(body["authMethod"]);
5619
+ const status = str(body["status"]);
5620
+ if (!authMethod || !OAUTH_AUTH_METHODS.has(authMethod)) return null;
5621
+ if (!status || !TOKEN_STATUSES.has(status)) return null;
5622
+ const out = {
5623
+ authMethod,
5624
+ status
5625
+ };
5626
+ copyOptional(out, body, ["accessToken", "refreshToken", "expiresAt", "accountId", "lastRefreshedAt", "errorMessage"]);
5627
+ return out;
5628
+ }
5629
+ function validateCopilot(body) {
5630
+ const authMethod = str(body["authMethod"]);
5631
+ const status = str(body["status"]);
5632
+ if (!authMethod || !OAUTH_AUTH_METHODS.has(authMethod)) return null;
5633
+ if (!status || !TOKEN_STATUSES.has(status)) return null;
5634
+ const out = {
5635
+ authMethod,
5636
+ status
5637
+ };
5638
+ copyOptional(out, body, [
5639
+ "accessToken",
5640
+ "refreshToken",
5641
+ "expiresAt",
5642
+ "accountId",
5643
+ "email",
5644
+ "apiEndpoint",
5645
+ "enterpriseUrl",
5646
+ "lastRefreshedAt",
5647
+ "errorMessage"
5648
+ ]);
5649
+ return out;
5650
+ }
4692
5651
  function validateOpenCodeGo(body) {
4693
5652
  const authMethod = str(body["authMethod"]);
4694
5653
  const status = str(body["status"]);
@@ -4726,6 +5685,10 @@ function validateTokenBody(providerId, body) {
4726
5685
  return validateOpenCodeGo(body);
4727
5686
  case "kimi":
4728
5687
  return validateKimi(body);
5688
+ case "grok":
5689
+ return validateGrok(body);
5690
+ case "copilot":
5691
+ return validateCopilot(body);
4729
5692
  default:
4730
5693
  return null;
4731
5694
  }
@@ -4755,12 +5718,12 @@ async function statusEntryFor(reader, providerId) {
4755
5718
 
4756
5719
  // src/admin/accountsOAuth.ts
4757
5720
  var OAUTH_HTTP_PROVIDERS = /* @__PURE__ */ new Set(["claude", "gemini"]);
4758
- function err3(status, message) {
5721
+ function err5(status, message) {
4759
5722
  return { status, body: { error: { type: "admin_api_error", message } } };
4760
5723
  }
4761
5724
  function handleOAuthStart(providerId, deps) {
4762
5725
  if (!OAUTH_HTTP_PROVIDERS.has(providerId)) {
4763
- return err3(400, `oauth not available for provider '${providerId}'`);
5726
+ return err5(400, `oauth not available for provider '${providerId}'`);
4764
5727
  }
4765
5728
  const flow = providerId === "claude" ? claudeOAuth : geminiOAuth;
4766
5729
  const { authUrl, codeVerifier, state } = flow.generateAuthParams();
@@ -4769,23 +5732,23 @@ function handleOAuthStart(providerId, deps) {
4769
5732
  }
4770
5733
  async function handleOAuthComplete(providerId, body, deps) {
4771
5734
  if (!OAUTH_HTTP_PROVIDERS.has(providerId)) {
4772
- return err3(400, `oauth not available for provider '${providerId}'`);
5735
+ return err5(400, `oauth not available for provider '${providerId}'`);
4773
5736
  }
4774
5737
  const sessionId = typeof body["sessionId"] === "string" ? body["sessionId"] : "";
4775
5738
  const rawCode = typeof body["code"] === "string" ? body["code"] : "";
4776
- if (!sessionId) return err3(400, "oauth complete requires { sessionId }");
4777
- if (!rawCode) return err3(400, "oauth complete requires { code }");
5739
+ if (!sessionId) return err5(400, "oauth complete requires { sessionId }");
5740
+ if (!rawCode) return err5(400, "oauth complete requires { code }");
4778
5741
  const session = deps.oauthSessions.peek(sessionId);
4779
- if (!session) return err3(410, "oauth session is unknown, expired, or already used");
5742
+ if (!session) return err5(410, "oauth session is unknown, expired, or already used");
4780
5743
  if (session.providerId !== providerId) {
4781
- return err3(400, `oauth session does not match provider '${providerId}'`);
5744
+ return err5(400, `oauth session does not match provider '${providerId}'`);
4782
5745
  }
4783
5746
  let code = rawCode.trim();
4784
5747
  if (providerId === "claude") {
4785
5748
  const [splitCode, pastedState] = code.split("#");
4786
- if (!splitCode) return err3(400, "no authorization code was provided");
5749
+ if (!splitCode) return err5(400, "no authorization code was provided");
4787
5750
  if (pastedState && pastedState !== session.state) {
4788
- return err3(400, "oauth state did not match (possible CSRF) \u2014 aborting");
5751
+ return err5(400, "oauth state did not match (possible CSRF) \u2014 aborting");
4789
5752
  }
4790
5753
  code = splitCode;
4791
5754
  }
@@ -4795,7 +5758,7 @@ async function handleOAuthComplete(providerId, body, deps) {
4795
5758
  block = providerId === "claude" ? await exchangeClaude(code, session.codeVerifier, session.state, exchangeFetch) : await exchangeGemini(code, session.codeVerifier, exchangeFetch);
4796
5759
  } catch (exchangeError) {
4797
5760
  const reason = exchangeError instanceof Error ? exchangeError.message : "token exchange failed";
4798
- return err3(502, `oauth token exchange failed for '${providerId}': ${reason}`);
5761
+ return err5(502, `oauth token exchange failed for '${providerId}': ${reason}`);
4799
5762
  }
4800
5763
  deps.oauthSessions.consume(sessionId);
4801
5764
  const label = typeof body["label"] === "string" && body["label"].trim() ? body["label"].trim() : void 0;
@@ -5133,8 +6096,8 @@ function errBody(message) {
5133
6096
  return { error: { type: "admin_api_error", message } };
5134
6097
  }
5135
6098
  var defaultCommandRunner = (command) => new Promise((resolve11) => {
5136
- exec(command, { timeout: 18e4 }, (err6, _stdout, stderr) => {
5137
- if (err6) resolve11({ ok: false, error: stderr.trim() || err6.message });
6099
+ exec(command, { timeout: 18e4 }, (err8, _stdout, stderr) => {
6100
+ if (err8) resolve11({ ok: false, error: stderr.trim() || err8.message });
5138
6101
  else resolve11({ ok: true });
5139
6102
  });
5140
6103
  });
@@ -5180,8 +6143,8 @@ async function handleCliLaunch(cli, body, ctx) {
5180
6143
  providerId: typeof body["providerId"] === "string" ? body["providerId"] : void 0,
5181
6144
  model: typeof body["model"] === "string" ? body["model"] : void 0
5182
6145
  });
5183
- } catch (err6) {
5184
- return { status: 400, body: errBody(err6 instanceof Error ? err6.message : "no launch target") };
6146
+ } catch (err8) {
6147
+ return { status: 400, body: errBody(err8 instanceof Error ? err8.message : "no launch target") };
5185
6148
  }
5186
6149
  const id = randomUUID2();
5187
6150
  let leaseId2;
@@ -5209,9 +6172,9 @@ async function handleCliLaunch(cli, body, ctx) {
5209
6172
  } else {
5210
6173
  launch = await buildLaunchEnv(cli, ctx.llmConfig, target);
5211
6174
  }
5212
- } catch (err6) {
5213
- const status = err6 instanceof RouteLeaseError2 ? err6.status : 400;
5214
- return { status, body: errBody(err6 instanceof Error ? err6.message : "failed to build launch env") };
6175
+ } catch (err8) {
6176
+ const status = err8 instanceof RouteLeaseError2 ? err8.status : 400;
6177
+ return { status, body: errBody(err8 instanceof Error ? err8.message : "failed to build launch env") };
5215
6178
  }
5216
6179
  const cwd = typeof body["cwd"] === "string" && body["cwd"].trim() ? body["cwd"].trim() : void 0;
5217
6180
  const opener = ctx.opener ?? defaultTerminalOpener;
@@ -5239,9 +6202,9 @@ async function handleCliLaunch(cli, body, ctx) {
5239
6202
  onFailure: onSessionEnd
5240
6203
  });
5241
6204
  if (cleanup) openerCleanup = cleanup;
5242
- } catch (err6) {
6205
+ } catch (err8) {
5243
6206
  onSessionEnd();
5244
- return { status: 500, body: errBody(err6 instanceof Error ? err6.message : "failed to open terminal") };
6207
+ return { status: 500, body: errBody(err8 instanceof Error ? err8.message : "failed to open terminal") };
5245
6208
  }
5246
6209
  if (ended) {
5247
6210
  openerCleanup?.();
@@ -5804,7 +6767,7 @@ async function handleSearchQuery(req, res, deps) {
5804
6767
  // src/admin/searchAdminView.ts
5805
6768
  var API_KEY_PROVIDERS = /* @__PURE__ */ new Set(["tavily", "jina", "zhipu", "z.ai"]);
5806
6769
  var BASIC_AUTH_PROVIDERS = /* @__PURE__ */ new Set(["searxng"]);
5807
- function isRecord2(value) {
6770
+ function isRecord5(value) {
5808
6771
  return value !== null && typeof value === "object" && !Array.isArray(value);
5809
6772
  }
5810
6773
  function redactSearchServerConfig(search) {
@@ -5854,13 +6817,13 @@ function resolveSecretField(entry, field, stored) {
5854
6817
  else delete entry[field];
5855
6818
  }
5856
6819
  function preserveSearchSecrets(incoming, current) {
5857
- if (!isRecord2(incoming)) return incoming;
6820
+ if (!isRecord5(incoming)) return incoming;
5858
6821
  const section = { ...incoming };
5859
6822
  const providersValue = section["providers"];
5860
- if (!isRecord2(providersValue)) return section;
6823
+ if (!isRecord5(providersValue)) return section;
5861
6824
  const providers = {};
5862
6825
  for (const [id, entryValue] of Object.entries(providersValue)) {
5863
- if (!isRecord2(entryValue)) {
6826
+ if (!isRecord5(entryValue)) {
5864
6827
  providers[id] = entryValue;
5865
6828
  continue;
5866
6829
  }
@@ -5938,7 +6901,7 @@ function parseKeyPolicyBody(body) {
5938
6901
  var ENDPOINTS = /* @__PURE__ */ new Set(["chat", "responses", "messages", "gemini"]);
5939
6902
  var TARGET_KINDS = /* @__PURE__ */ new Set(["account", "account-group", "account-pool", "provider"]);
5940
6903
  var FALLBACKS = /* @__PURE__ */ new Set(["next", "fail", "global"]);
5941
- function isRecord3(value) {
6904
+ function isRecord6(value) {
5942
6905
  return !!value && typeof value === "object" && !Array.isArray(value);
5943
6906
  }
5944
6907
  function nonBlank(value) {
@@ -5958,7 +6921,7 @@ function validateGatewayBindingsSegment(patch) {
5958
6921
  const ids = /* @__PURE__ */ new Set();
5959
6922
  raw.forEach((entry, index) => {
5960
6923
  const path2 = `bindings[${index}]`;
5961
- if (!isRecord3(entry)) {
6924
+ if (!isRecord6(entry)) {
5962
6925
  errors.push(`${path2} must be an object`);
5963
6926
  return;
5964
6927
  }
@@ -5987,12 +6950,12 @@ function validateGatewayBindingsSegment(patch) {
5987
6950
  } else if (entry.modelMappings.length > 100) {
5988
6951
  errors.push(`${path2}.modelMappings cannot contain more than 100 entries`);
5989
6952
  } else if (entry.modelMappings.some(
5990
- (mapping) => !isRecord3(mapping) || !nonBlank(mapping.source) || !nonBlank(mapping.target)
6953
+ (mapping) => !isRecord6(mapping) || !nonBlank(mapping.source) || !nonBlank(mapping.target)
5991
6954
  )) {
5992
6955
  errors.push(`${path2}.modelMappings must contain non-empty source and target strings`);
5993
6956
  }
5994
6957
  }
5995
- if (!isRecord3(entry.target) || !TARGET_KINDS.has(String(entry.target.kind))) {
6958
+ if (!isRecord6(entry.target) || !TARGET_KINDS.has(String(entry.target.kind))) {
5996
6959
  errors.push(`${path2}.target is invalid`);
5997
6960
  } else {
5998
6961
  if (!nonBlank(entry.target.providerId)) errors.push(`${path2}.target.providerId is required`);
@@ -6007,7 +6970,7 @@ function validateGatewayBindingsSegment(patch) {
6007
6970
  }
6008
6971
  }
6009
6972
  if (entry.modelMap !== void 0) {
6010
- if (!isRecord3(entry.modelMap) || Object.values(entry.modelMap).some((value) => typeof value !== "string")) {
6973
+ if (!isRecord6(entry.modelMap) || Object.values(entry.modelMap).some((value) => typeof value !== "string")) {
6011
6974
  errors.push(`${path2}.modelMap must contain string values`);
6012
6975
  }
6013
6976
  }
@@ -6302,7 +7265,9 @@ var PROVIDER_KEYS = {
6302
7265
  accounts: "opencodegoAccounts",
6303
7266
  active: "activeOpencodegoAccountId"
6304
7267
  },
6305
- kimi: { block: "kimi", accounts: "kimiAccounts", active: "activeKimiAccountId" }
7268
+ kimi: { block: "kimi", accounts: "kimiAccounts", active: "activeKimiAccountId" },
7269
+ grok: { block: "grok", accounts: "grokAccounts", active: "activeGrokAccountId" },
7270
+ copilot: { block: "copilot", accounts: "copilotAccounts", active: "activeCopilotAccountId" }
6306
7271
  };
6307
7272
  function clone(value) {
6308
7273
  return JSON.parse(JSON.stringify(value));
@@ -6824,7 +7789,7 @@ async function applyImport(packString, passphrase, mode, deps, parseProviderInpu
6824
7789
  }
6825
7790
 
6826
7791
  // src/admin/adminMigration.ts
6827
- function err4(status, message) {
7792
+ function err6(status, message) {
6828
7793
  return { status, body: { error: { type: "admin_api_error", message } } };
6829
7794
  }
6830
7795
  async function handleExport(body, deps) {
@@ -6834,30 +7799,30 @@ async function handleExport(body, deps) {
6834
7799
  return { status: 200, body: { pack, version: BUNDLE_VERSION } };
6835
7800
  } catch (error) {
6836
7801
  if (error instanceof WeakPassphraseError) {
6837
- return err4(400, error.message);
7802
+ return err6(400, error.message);
6838
7803
  }
6839
- return err4(500, "failed to build the migration pack");
7804
+ return err6(500, "failed to build the migration pack");
6840
7805
  }
6841
7806
  }
6842
7807
  async function handleImport(body, deps) {
6843
7808
  const blob = typeof body["blob"] === "string" ? body["blob"] : "";
6844
7809
  const passphrase = typeof body["passphrase"] === "string" ? body["passphrase"] : "";
6845
7810
  const mode = body["mode"] === "overwrite" ? "overwrite" : "merge";
6846
- if (!blob) return err4(400, "import requires { blob }");
7811
+ if (!blob) return err6(400, "import requires { blob }");
6847
7812
  try {
6848
7813
  const counts = await applyImport(blob, passphrase, mode, deps, deps.parseProviderInput);
6849
7814
  return { status: 200, body: counts };
6850
7815
  } catch (error) {
6851
7816
  if (error instanceof WeakPassphraseError) {
6852
- return err4(400, error.message);
7817
+ return err6(400, error.message);
6853
7818
  }
6854
- return err4(400, error instanceof Error ? error.message : "import failed");
7819
+ return err6(400, error instanceof Error ? error.message : "import failed");
6855
7820
  }
6856
7821
  }
6857
7822
 
6858
7823
  // src/admin/usagePricing.ts
6859
7824
  import { getSharedUsageThroughputTracker } from "@omnicross/core/usage";
6860
- var err5 = (status, message) => ({
7825
+ var err7 = (status, message) => ({
6861
7826
  status,
6862
7827
  body: { error: { type: "admin_api_error", message } }
6863
7828
  });
@@ -6870,7 +7835,7 @@ function parseRange(query2) {
6870
7835
  const startTs = parseFiniteInt(query2.get("startTs"));
6871
7836
  const endTs = parseFiniteInt(query2.get("endTs"));
6872
7837
  if (startTs === null || endTs === null) {
6873
- return err5(400, "startTs and endTs are required finite-integer unix-millis query params");
7838
+ return err7(400, "startTs and endTs are required finite-integer unix-millis query params");
6874
7839
  }
6875
7840
  return { startTs, endTs };
6876
7841
  }
@@ -6895,14 +7860,14 @@ async function handleUsageGet(view, query2, deps) {
6895
7860
  case "timeseries": {
6896
7861
  const bucket = query2.get("bucket");
6897
7862
  if (bucket !== "hour" && bucket !== "day" && bucket !== "month") {
6898
- return err5(400, "bucket must be one of 'hour', 'day', 'month'");
7863
+ return err7(400, "bucket must be one of 'hour', 'day', 'month'");
6899
7864
  }
6900
7865
  const now = Date.now();
6901
7866
  const clamped = { startTs: range.startTs, endTs: Math.min(range.endTs, now) };
6902
7867
  if (clamped.startTs < clamped.endTs) {
6903
7868
  const projected = Math.ceil((clamped.endTs - clamped.startTs) / BUCKET_SPAN_MS[bucket]) + 1;
6904
7869
  if (projected > MAX_TIMESERIES_BUCKETS) {
6905
- return err5(
7870
+ return err7(
6906
7871
  400,
6907
7872
  `requested range projects ~${projected} '${bucket}' buckets (max ${MAX_TIMESERIES_BUCKETS}); narrow the range or use a coarser bucket`
6908
7873
  );
@@ -6925,7 +7890,7 @@ async function handleUsageGet(view, query2, deps) {
6925
7890
  };
6926
7891
  }
6927
7892
  default:
6928
- return err5(404, `unknown usage view '${view ?? ""}'`);
7893
+ return err7(404, `unknown usage view '${view ?? ""}'`);
6929
7894
  }
6930
7895
  }
6931
7896
  function poolKeyLabels(cfg) {
@@ -6974,7 +7939,7 @@ async function handlePricingList(deps) {
6974
7939
  async function handlePricingUpsert(body, deps) {
6975
7940
  const input = parsePricingEntryInput(body);
6976
7941
  if (!input) {
6977
- return err5(400, "invalid pricing entry (providerId, modelId, finite numeric inputPricePer1m/outputPricePer1m required)");
7942
+ return err7(400, "invalid pricing entry (providerId, modelId, finite numeric inputPricePer1m/outputPricePer1m required)");
6978
7943
  }
6979
7944
  const entry = await deps.pricingEngine.upsertManual(input);
6980
7945
  return { status: 200, body: { entry } };
@@ -6983,7 +7948,7 @@ async function handlePricingDelete(query2, deps) {
6983
7948
  const providerId = query2.get("providerId")?.trim() ?? "";
6984
7949
  const modelId = query2.get("modelId")?.trim() ?? "";
6985
7950
  if (!providerId || !modelId) {
6986
- return err5(400, "delete requires providerId and modelId query params");
7951
+ return err7(400, "delete requires providerId and modelId query params");
6987
7952
  }
6988
7953
  const deleted = await deps.pricingStore.delete(providerId, modelId);
6989
7954
  if (deleted) await deps.pricingEngine.invalidateCache();
@@ -7003,13 +7968,13 @@ async function handlePricingFetchLatest(deps) {
7003
7968
  }
7004
7969
  };
7005
7970
  } catch (e) {
7006
- return err5(502, `pricing-source fetch failed: ${e instanceof Error ? e.message : String(e)}`);
7971
+ return err7(502, `pricing-source fetch failed: ${e instanceof Error ? e.message : String(e)}`);
7007
7972
  }
7008
7973
  }
7009
7974
  async function handlePricingResolveConflicts(body, deps) {
7010
7975
  const raw = body["resolutions"];
7011
7976
  if (!Array.isArray(raw)) {
7012
- return err5(400, "resolve-conflicts requires { resolutions: [...] }");
7977
+ return err7(400, "resolve-conflicts requires { resolutions: [...] }");
7013
7978
  }
7014
7979
  const currentRows = await deps.pricingStore.getAll();
7015
7980
  const userEditedKeys = new Set(
@@ -7019,21 +7984,21 @@ async function handlePricingResolveConflicts(body, deps) {
7019
7984
  const pendingIncoming = /* @__PURE__ */ new Map();
7020
7985
  let staleCount = 0;
7021
7986
  for (const item of raw) {
7022
- if (!item || typeof item !== "object") return err5(400, "invalid resolution entry");
7987
+ if (!item || typeof item !== "object") return err7(400, "invalid resolution entry");
7023
7988
  const r = item;
7024
7989
  const action = r["action"];
7025
7990
  if (action !== "overwrite" && action !== "skip") {
7026
- return err5(400, "resolution action must be 'overwrite' or 'skip'");
7991
+ return err7(400, "resolution action must be 'overwrite' or 'skip'");
7027
7992
  }
7028
7993
  const providerId = typeof r["providerId"] === "string" && r["providerId"].trim() ? r["providerId"].trim() : "";
7029
7994
  const modelId = typeof r["modelId"] === "string" && r["modelId"].trim() ? r["modelId"].trim() : "";
7030
7995
  if (!providerId || !modelId) {
7031
- return err5(400, "each resolution requires top-level providerId and modelId");
7996
+ return err7(400, "each resolution requires top-level providerId and modelId");
7032
7997
  }
7033
7998
  const incoming = parsePricingEntryInput(r["incoming"]);
7034
- if (!incoming) return err5(400, "each resolution must echo a valid incoming pricing entry");
7999
+ if (!incoming) return err7(400, "each resolution must echo a valid incoming pricing entry");
7035
8000
  if (incoming.providerId !== providerId || incoming.modelId !== modelId) {
7036
- return err5(400, "resolution providerId/modelId must match the echoed incoming entry");
8001
+ return err7(400, "resolution providerId/modelId must match the echoed incoming entry");
7037
8002
  }
7038
8003
  const key = `${providerId}::${modelId}`;
7039
8004
  if (action === "overwrite" && !userEditedKeys.has(key)) {
@@ -7078,7 +8043,7 @@ function query(req) {
7078
8043
  }
7079
8044
  function allowanceProvider(value) {
7080
8045
  if (!value) return void 0;
7081
- return value === "claude" || value === "codex" || value === "kimi" || value === "opencodego" ? value : null;
8046
+ return value === "claude" || value === "codex" || value === "kimi" || value === "opencodego" || value === "grok" || value === "copilot" || value === "gemini" ? value : null;
7082
8047
  }
7083
8048
  async function handleAccountAllowanceApi(req, res, method, rest, service) {
7084
8049
  if (!service) return writeError2(res, 501, "account allowance service is not available");
@@ -7093,7 +8058,7 @@ async function handleAccountAllowanceApi(req, res, method, rest, service) {
7093
8058
  const pathProvider = rest.length >= 2 ? rest[0] : null;
7094
8059
  const providerId = allowanceProvider(pathProvider ?? params.get("providerId") ?? params.get("provider"));
7095
8060
  if (providerId === null) {
7096
- return writeError2(res, 400, "providerId must be claude, codex, kimi, or opencodego");
8061
+ return writeError2(res, 400, "providerId must be claude, codex, kimi, opencodego, grok, copilot, or gemini");
7097
8062
  }
7098
8063
  const accountId = rest.length >= 2 ? rest[1] : params.get("accountId") ?? void 0;
7099
8064
  const allowances = await service.list({ providerId, accountId });
@@ -7135,6 +8100,36 @@ async function handleAccountAllowanceApi(req, res, method, rest, service) {
7135
8100
  }
7136
8101
  return writeJson3(res, 200, { allowances: allowances2 });
7137
8102
  }
8103
+ if (requestedProvider === "copilot") {
8104
+ if (!service.refreshCopilot) {
8105
+ return writeError2(res, 501, "copilot allowance refresh is not available");
8106
+ }
8107
+ const allowances2 = await service.refreshCopilot(accountId);
8108
+ if (accountId && allowances2.length === 0) {
8109
+ return writeError2(res, 404, `Copilot account '${accountId}' not found`);
8110
+ }
8111
+ return writeJson3(res, 200, { allowances: allowances2 });
8112
+ }
8113
+ if (requestedProvider === "grok") {
8114
+ if (!service.refreshGrok) {
8115
+ return writeError2(res, 501, "grok allowance refresh is not available");
8116
+ }
8117
+ const allowances2 = await service.refreshGrok(accountId);
8118
+ if (accountId && allowances2.length === 0) {
8119
+ return writeError2(res, 404, `Grok account '${accountId}' not found`);
8120
+ }
8121
+ return writeJson3(res, 200, { allowances: allowances2 });
8122
+ }
8123
+ if (requestedProvider === "gemini") {
8124
+ if (!service.refreshGemini) {
8125
+ return writeError2(res, 501, "gemini allowance refresh is not available");
8126
+ }
8127
+ const allowances2 = await service.refreshGemini(accountId);
8128
+ if (accountId && allowances2.length === 0) {
8129
+ return writeError2(res, 404, `Gemini account '${accountId}' not found`);
8130
+ }
8131
+ return writeJson3(res, 200, { allowances: allowances2 });
8132
+ }
7138
8133
  const allowances = await service.refreshClaude(accountId);
7139
8134
  if (accountId && allowances.length === 0) {
7140
8135
  return writeError2(res, 404, `Claude account '${accountId}' not found`);
@@ -7236,6 +8231,9 @@ function toProviderView(row) {
7236
8231
  apiVersion: row.apiVersion,
7237
8232
  maxConcurrency: row.maxConcurrency,
7238
8233
  modelsEndpoint: row.modelsEndpoint,
8234
+ // Static extra headers round-trip VERBATIM (non-secret identity values;
8235
+ // auth/content names were already dropped at the write/load gate).
8236
+ extraHeaders: row.extraHeaders,
7239
8237
  // app-parity child 5: transformer config round-trips VERBATIM (non-secret —
7240
8238
  // transform-rule names + options, no key material; absent stays absent).
7241
8239
  transformer: row.transformer,
@@ -7305,8 +8303,8 @@ async function handleAdminApi(req, res, path2, deps) {
7305
8303
  default:
7306
8304
  return writeJsonError(res, 404, `unknown admin resource '${resource}'`);
7307
8305
  }
7308
- } catch (err6) {
7309
- writeJsonError(res, 500, err6 instanceof Error ? err6.message : String(err6));
8306
+ } catch (err8) {
8307
+ writeJsonError(res, 500, err8 instanceof Error ? err8.message : String(err8));
7310
8308
  }
7311
8309
  }
7312
8310
  function requestQuery(req) {
@@ -7464,6 +8462,9 @@ async function handleProviderReorder(req, res, cfg, deps) {
7464
8462
  persistProviders(cfg, deps);
7465
8463
  return writeJson4(res, 200, { ok: true, providers: cfg.providers.map(toProviderView) });
7466
8464
  }
8465
+ function expandRowExtraHeaders(row) {
8466
+ return mergeExtraHeaders({}, row.extraHeaders);
8467
+ }
7467
8468
  async function handleDiscoverModels(res, id, cfg) {
7468
8469
  if (!id) return writeJsonError(res, 400, "provider id required in path");
7469
8470
  const row = cfg.providers.find((p) => p.id === id);
@@ -7477,7 +8478,8 @@ async function handleDiscoverModels(res, id, cfg) {
7477
8478
  try {
7478
8479
  const headers = { Accept: "application/json" };
7479
8480
  if (resolvedKey) headers["Authorization"] = `Bearer ${resolvedKey}`;
7480
- const response = await fetchUpstream5(url, { method: "GET", headers }, { providerId: "byo" });
8481
+ Object.assign(headers, expandRowExtraHeaders(row));
8482
+ const response = await fetchUpstream8(url, { method: "GET", headers }, { providerId: "byo" });
7481
8483
  if (!response.ok) {
7482
8484
  const text = await response.text().catch(() => "");
7483
8485
  let message = text.slice(0, 300);
@@ -7494,8 +8496,8 @@ async function handleDiscoverModels(res, id, cfg) {
7494
8496
  const data = await response.json();
7495
8497
  const models = Array.isArray(data?.data) ? data.data.map((m) => typeof m?.id === "string" ? m.id : "").filter((m) => m.length > 0) : [];
7496
8498
  return writeJson4(res, 200, { models });
7497
- } catch (err6) {
7498
- const message = err6 instanceof Error ? err6.message : String(err6);
8499
+ } catch (err8) {
8500
+ const message = err8 instanceof Error ? err8.message : String(err8);
7499
8501
  return writeJson4(res, 200, { models: [], error: `discovery failed: ${message}` });
7500
8502
  }
7501
8503
  }
@@ -7534,9 +8536,10 @@ async function handleTestModel(req, res, id, cfg) {
7534
8536
  messages: [{ role: "user", content: prompt }]
7535
8537
  };
7536
8538
  }
8539
+ Object.assign(headers, expandRowExtraHeaders(row));
7537
8540
  const startedAt = Date.now();
7538
8541
  try {
7539
- const response = await fetchUpstream5(
8542
+ const response = await fetchUpstream8(
7540
8543
  url,
7541
8544
  { method: "POST", headers, body: JSON.stringify(payload) },
7542
8545
  { providerId: "byo" }
@@ -7558,8 +8561,8 @@ async function handleTestModel(req, res, id, cfg) {
7558
8561
  latencyMs,
7559
8562
  sample: extractSampleText(text, row.apiFormat)
7560
8563
  });
7561
- } catch (err6) {
7562
- const message = err6 instanceof Error ? err6.message : String(err6);
8564
+ } catch (err8) {
8565
+ const message = err8 instanceof Error ? err8.message : String(err8);
7563
8566
  return writeJson4(res, 200, { ok: false, latencyMs: Date.now() - startedAt, message });
7564
8567
  }
7565
8568
  }
@@ -7841,6 +8844,7 @@ function parseProviderInput(body, existing) {
7841
8844
  const apiVersion = typeof body["apiVersion"] === "string" && body["apiVersion"].length > 0 ? body["apiVersion"] : body["apiVersion"] === null ? void 0 : existing?.apiVersion;
7842
8845
  const modelsEndpoint = typeof body["modelsEndpoint"] === "string" && body["modelsEndpoint"].length > 0 ? body["modelsEndpoint"] : body["modelsEndpoint"] === null ? void 0 : existing?.modelsEndpoint;
7843
8846
  const maxConcurrency = typeof body["maxConcurrency"] === "number" && Number.isFinite(body["maxConcurrency"]) ? body["maxConcurrency"] : body["maxConcurrency"] === null ? void 0 : existing?.maxConcurrency;
8847
+ const extraHeaders = body["extraHeaders"] === null ? void 0 : body["extraHeaders"] === void 0 ? existing?.extraHeaders : validateExtraHeaders(body["extraHeaders"]);
7844
8848
  const transformer = body["transformer"] === null ? void 0 : parseTransformerInput(body["transformer"], existing?.transformer);
7845
8849
  const codingPlan = body["codingPlan"] === null ? void 0 : body["codingPlan"] === void 0 ? existing?.codingPlan : body["codingPlan"] && typeof body["codingPlan"] === "object" && !Array.isArray(body["codingPlan"]) ? parseCodingPlanInput(body["codingPlan"], existing?.codingPlan) : existing?.codingPlan;
7846
8850
  const apiModes = body["apiModes"] === null ? void 0 : parseApiModesInput(body["apiModes"], existing?.apiModes);
@@ -7866,6 +8870,7 @@ function parseProviderInput(body, existing) {
7866
8870
  apiVersion,
7867
8871
  maxConcurrency,
7868
8872
  modelsEndpoint,
8873
+ extraHeaders,
7869
8874
  transformer: migrated.transformer,
7870
8875
  codingPlan,
7871
8876
  apiModes,
@@ -7887,7 +8892,10 @@ function handlePresets(res, method) {
7887
8892
  description: p.description,
7888
8893
  features: p.features,
7889
8894
  website: p.website,
7890
- modelsEndpoint: p.modelsEndpoint
8895
+ modelsEndpoint: p.modelsEndpoint,
8896
+ // Static extra headers ride along so `addFromPreset` can seed them onto the
8897
+ // row (the write gateway re-validates via the shared allowlist).
8898
+ extraHeaders: p.extraHeaders
7891
8899
  }));
7892
8900
  return writeJson4(res, 200, { presets, excluded });
7893
8901
  }
@@ -8369,12 +9377,12 @@ async function handleAccounts(req, res, method, rest, deps) {
8369
9377
  }
8370
9378
  return writeJson4(res, 200, { ok: true, affected: result.affected });
8371
9379
  }
8372
- if (method === "GET" && (rest[0] === "codex" || rest[0] === "kimi") && rest[1] === "oauth" && rest[3] === "status") {
8373
- const result = rest[0] === "codex" ? handleCodexOAuthStatus(rest[2], deps) : handleKimiOAuthStatus(rest[2], deps);
9380
+ if (method === "GET" && (rest[0] === "codex" || rest[0] === "kimi" || rest[0] === "grok" || rest[0] === "copilot") && rest[1] === "oauth" && rest[3] === "status") {
9381
+ const result = rest[0] === "codex" ? handleCodexOAuthStatus(rest[2], deps) : rest[0] === "kimi" ? handleKimiOAuthStatus(rest[2], deps) : rest[0] === "grok" ? handleGrokOAuthStatus(rest[2], deps) : handleCopilotOAuthStatus(rest[2], deps);
8374
9382
  return writeJson4(res, result.status, result.body);
8375
9383
  }
8376
- if (method === "DELETE" && (rest[0] === "codex" || rest[0] === "kimi") && rest[1] === "oauth" && rest[2]) {
8377
- const result = rest[0] === "codex" ? handleCodexOAuthCancel(rest[2], deps) : handleKimiOAuthCancel(rest[2], deps);
9384
+ if (method === "DELETE" && (rest[0] === "codex" || rest[0] === "kimi" || rest[0] === "grok" || rest[0] === "copilot") && rest[1] === "oauth" && rest[2]) {
9385
+ const result = rest[0] === "codex" ? handleCodexOAuthCancel(rest[2], deps) : rest[0] === "kimi" ? handleKimiOAuthCancel(rest[2], deps) : rest[0] === "grok" ? handleGrokOAuthCancel(rest[2], deps) : handleCopilotOAuthCancel(rest[2], deps);
8378
9386
  return writeJson4(res, result.status, result.body);
8379
9387
  }
8380
9388
  if (method === "GET" && rest.length === 3 && rest[2] === "diagnostics") {
@@ -8435,6 +9443,15 @@ async function handleAccounts(req, res, method, rest, deps) {
8435
9443
  const result2 = await handleKimiOAuthStart(deps);
8436
9444
  return writeJson4(res, result2.status, result2.body);
8437
9445
  }
9446
+ if (providerId === "grok") {
9447
+ const result2 = await handleGrokOAuthStart(deps);
9448
+ return writeJson4(res, result2.status, result2.body);
9449
+ }
9450
+ if (providerId === "copilot") {
9451
+ const body2 = await readJsonBody4(req);
9452
+ const result2 = await handleCopilotOAuthStart(deps, body2["enterpriseUrl"]);
9453
+ return writeJson4(res, result2.status, result2.body);
9454
+ }
8438
9455
  const result = handleOAuthStart(providerId, deps);
8439
9456
  return writeJson4(res, result.status, result.body);
8440
9457
  }
@@ -8929,12 +9946,12 @@ async function handlePlayground(req, res, method, deps) {
8929
9946
  const payload = body["body"];
8930
9947
  const status = deps.outboundApiServer.getStatus();
8931
9948
  if (!status.running || !status.port) return writeJsonError(res, 503, "outbound server not running");
8932
- const path2 = resolvePlaygroundPath(endpoint, isRecord4(payload) ? payload : {});
9949
+ const path2 = resolvePlaygroundPath(endpoint, isRecord7(payload) ? payload : {});
8933
9950
  if (!path2) return writeJsonError(res, 400, `unknown endpoint '${endpoint}'`);
8934
9951
  const upstreamBody = typeof payload === "string" ? payload : JSON.stringify(payload ?? {});
8935
9952
  await proxyToOutbound(res, status.port, path2, key, upstreamBody);
8936
9953
  }
8937
- function isRecord4(v) {
9954
+ function isRecord7(v) {
8938
9955
  return !!v && typeof v === "object" && !Array.isArray(v);
8939
9956
  }
8940
9957
  function proxyToOutbound(res, outboundPort, path2, key, body) {
@@ -8963,8 +9980,8 @@ function proxyToOutbound(res, outboundPort, path2, key, body) {
8963
9980
  });
8964
9981
  }
8965
9982
  );
8966
- upstream.on("error", (err6) => {
8967
- if (!res.headersSent) writeJsonError(res, 502, `playground proxy failed: ${err6.message}`);
9983
+ upstream.on("error", (err8) => {
9984
+ if (!res.headersSent) writeJsonError(res, 502, `playground proxy failed: ${err8.message}`);
8968
9985
  else res.end();
8969
9986
  resolve11();
8970
9987
  });
@@ -9069,7 +10086,7 @@ async function handleUiStatic(req, res, urlPath, uiDist) {
9069
10086
  }
9070
10087
 
9071
10088
  // src/admin/version.ts
9072
- var DAEMON_VERSION = true ? "0.3.1" : "0.0.0-dev";
10089
+ var DAEMON_VERSION = true ? "0.4.1" : "0.0.0-dev";
9073
10090
 
9074
10091
  // src/admin/AdminServer.ts
9075
10092
  var LOOPBACK_ADDR = "127.0.0.1";
@@ -9112,13 +10129,13 @@ var AdminServer = class {
9112
10129
  const server = http2.createServer((req, res) => {
9113
10130
  this.onRequest(req, res);
9114
10131
  });
9115
- const onError = (err6) => {
9116
- if (err6.code === "EADDRINUSE" && port !== 0) {
10132
+ const onError = (err8) => {
10133
+ if (err8.code === "EADDRINUSE" && port !== 0) {
9117
10134
  server.removeListener("error", onError);
9118
10135
  this.listen(bindAddr, 0).then(resolve11, reject);
9119
10136
  return;
9120
10137
  }
9121
- reject(err6);
10138
+ reject(err8);
9122
10139
  };
9123
10140
  server.on("error", onError);
9124
10141
  server.listen(port, bindAddr, () => {
@@ -9136,8 +10153,8 @@ var AdminServer = class {
9136
10153
  }
9137
10154
  /** Per-request handler: auth gate (when a token is set) → routing. */
9138
10155
  onRequest(req, res) {
9139
- void this.dispatch(req, res).catch((err6) => {
9140
- const message = err6 instanceof Error ? err6.message : String(err6);
10156
+ void this.dispatch(req, res).catch((err8) => {
10157
+ const message = err8 instanceof Error ? err8.message : String(err8);
9141
10158
  this.deps.logger.error("[AdminServer] unhandled error:", message);
9142
10159
  if (!res.headersSent) {
9143
10160
  res.writeHead(500, { "Content-Type": "application/json" });
@@ -9401,18 +10418,18 @@ function awaitLoopbackCode(expectedState, timeoutMs = DEFAULT_TIMEOUT_MS, signal
9401
10418
  return;
9402
10419
  }
9403
10420
  signal?.addEventListener("abort", abort, { once: true });
9404
- server.on("error", (err6) => {
10421
+ server.on("error", (err8) => {
9405
10422
  if (settled) return;
9406
10423
  settled = true;
9407
10424
  clearTimeout(timer);
9408
- if (err6.code === "EADDRINUSE") {
10425
+ if (err8.code === "EADDRINUSE") {
9409
10426
  reject(
9410
10427
  new Error(
9411
10428
  `login: cannot bind ${LOOPBACK_HOST}:${LOOPBACK_PORT} (address in use) \u2014 another codex login or process is holding the port`
9412
10429
  )
9413
10430
  );
9414
10431
  } else {
9415
- reject(err6);
10432
+ reject(err8);
9416
10433
  }
9417
10434
  });
9418
10435
  const timer = setTimeout(() => {
@@ -9488,21 +10505,22 @@ function createPoolKeysLoader(getProviderRow, autoDisabled) {
9488
10505
  }
9489
10506
 
9490
10507
  // src/allowance/ProviderKeyQuotaService.ts
9491
- import { fetchUpstream as fetchUpstream6 } from "@omnicross/core/pipeline/upstreamFetch";
10508
+ import { mergeExtraHeaders as mergeExtraHeaders2 } from "@omnicross/core";
10509
+ import { fetchUpstream as fetchUpstream9 } from "@omnicross/core/pipeline/upstreamFetch";
9492
10510
 
9493
10511
  // src/allowance/ProviderKeyQuota.ts
9494
- var MINUTE_MS2 = 6e4;
9495
- var HOUR_MS2 = 60 * MINUTE_MS2;
9496
- var DAY_MS2 = 24 * HOUR_MS2;
9497
- var WEEK_MS = 7 * DAY_MS2;
9498
- var MONTH_MS = 30 * DAY_MS2;
9499
- function finiteNumber3(value) {
10512
+ var MINUTE_MS3 = 6e4;
10513
+ var HOUR_MS2 = 60 * MINUTE_MS3;
10514
+ var DAY_MS3 = 24 * HOUR_MS2;
10515
+ var WEEK_MS = 7 * DAY_MS3;
10516
+ var MONTH_MS = 30 * DAY_MS3;
10517
+ function finiteNumber5(value) {
9500
10518
  if (value === null || value === void 0 || value === "") return void 0;
9501
10519
  const parsed = typeof value === "number" ? value : Number(value);
9502
10520
  return Number.isFinite(parsed) && parsed >= 0 ? parsed : void 0;
9503
10521
  }
9504
10522
  function finitePercent4(value) {
9505
- const parsed = finiteNumber3(value);
10523
+ const parsed = finiteNumber5(value);
9506
10524
  return parsed !== void 0 && parsed <= 100 ? parsed : null;
9507
10525
  }
9508
10526
  function isoInstant3(value) {
@@ -9510,18 +10528,18 @@ function isoInstant3(value) {
9510
10528
  const time = Date.parse(value);
9511
10529
  if (Number.isFinite(time)) return new Date(time).toISOString();
9512
10530
  }
9513
- const numeric = finiteNumber3(value);
10531
+ const numeric = finiteNumber5(value);
9514
10532
  if (numeric !== void 0 && numeric > 1e9) {
9515
10533
  const ms = numeric > 1e12 ? numeric : numeric * 1e3;
9516
10534
  return new Date(ms).toISOString();
9517
10535
  }
9518
10536
  return void 0;
9519
10537
  }
9520
- function secondsUntil5(instant, now) {
10538
+ function secondsUntil8(instant, now) {
9521
10539
  if (!instant) return void 0;
9522
10540
  return Math.max(0, Math.floor((Date.parse(instant) - now) / 1e3));
9523
10541
  }
9524
- function isRecord5(value) {
10542
+ function isRecord8(value) {
9525
10543
  return !!value && typeof value === "object" && !Array.isArray(value);
9526
10544
  }
9527
10545
  function detectProviderKeyQuotaAdapter(baseUrl) {
@@ -9534,7 +10552,7 @@ function detectProviderKeyQuotaAdapter(baseUrl) {
9534
10552
  }
9535
10553
  const host = url.hostname.toLowerCase();
9536
10554
  const path2 = url.pathname.toLowerCase();
9537
- if ((host === "api.z.ai" || host === "open.bigmodel.cn") && path2.includes("/coding")) {
10555
+ if ((host === "api.z.ai" || host === "open.bigmodel.cn") && (path2.includes("/coding") || path2.includes("/anthropic"))) {
9538
10556
  return "zai";
9539
10557
  }
9540
10558
  if ((host === "api.minimax.io" || host === "api.minimaxi.com") && // Token Plan rides the plain openai `/v1` (chat completions) surface; the
@@ -9544,6 +10562,7 @@ function detectProviderKeyQuotaAdapter(baseUrl) {
9544
10562
  }
9545
10563
  if (host === "api.code.umans.ai") return "umans";
9546
10564
  if (host === "api.synthetic.new") return "synthetic";
10565
+ if (host === "api.cline.bot") return "cline-pass";
9547
10566
  return null;
9548
10567
  }
9549
10568
  function providerKeyQuotaUrl(adapter, baseUrl) {
@@ -9551,6 +10570,7 @@ function providerKeyQuotaUrl(adapter, baseUrl) {
9551
10570
  if (adapter === "zai") return `${origin}/api/monitor/usage/quota/limit`;
9552
10571
  if (adapter === "minimax-token-plan") return `${origin}/v1/token_plan/remains`;
9553
10572
  if (adapter === "umans") return `${origin}/v1/usage`;
10573
+ if (adapter === "cline-pass") return `${origin}/api/v1/users/me/plan/usage-limits`;
9554
10574
  return `${origin}/v2/quotas`;
9555
10575
  }
9556
10576
  function providerKeyQuotaAuthHeader(adapter, key) {
@@ -9562,7 +10582,7 @@ function zaiWindowDurationMs(item) {
9562
10582
  case 3:
9563
10583
  return count * HOUR_MS2;
9564
10584
  case 4:
9565
- return count * DAY_MS2;
10585
+ return count * DAY_MS3;
9566
10586
  case 5:
9567
10587
  return count * MONTH_MS;
9568
10588
  case 6:
@@ -9575,8 +10595,8 @@ function zaiWindowIdLabel(durationMs) {
9575
10595
  if (durationMs === WEEK_MS) return { id: "seven-day", label: "7 days" };
9576
10596
  if (durationMs === 5 * HOUR_MS2) return { id: "five-hour", label: "5 hours" };
9577
10597
  if (durationMs === MONTH_MS) return { id: "thirty-day", label: "30 days" };
9578
- if (durationMs !== void 0 && durationMs % DAY_MS2 === 0) {
9579
- const days = durationMs / DAY_MS2;
10598
+ if (durationMs !== void 0 && durationMs % DAY_MS3 === 0) {
10599
+ const days = durationMs / DAY_MS3;
9580
10600
  return { id: `${days}d`, label: `${days} day${days === 1 ? "" : "s"}` };
9581
10601
  }
9582
10602
  if (durationMs !== void 0 && durationMs % HOUR_MS2 === 0) {
@@ -9586,23 +10606,23 @@ function zaiWindowIdLabel(durationMs) {
9586
10606
  return { id: "quota", label: "Quota" };
9587
10607
  }
9588
10608
  function parseZaiQuotaPayload(payload, now) {
9589
- if (!isRecord5(payload)) return null;
9590
- const data = isRecord5(payload["data"]) ? payload["data"] : payload;
10609
+ if (!isRecord8(payload)) return null;
10610
+ const data = isRecord8(payload["data"]) ? payload["data"] : payload;
9591
10611
  if (payload["success"] === false) return null;
9592
10612
  const limits = Array.isArray(data["limits"]) ? data["limits"] : [];
9593
10613
  const byWindow = /* @__PURE__ */ new Map();
9594
10614
  for (const raw of limits) {
9595
- if (!isRecord5(raw)) continue;
10615
+ if (!isRecord8(raw)) continue;
9596
10616
  const item = raw;
9597
10617
  if (item.type === void 0) continue;
9598
10618
  const details = raw["usageDetails"];
9599
- if (Array.isArray(details) && details.some((d) => isRecord5(d) && d["modelCode"] === "zread")) {
10619
+ if (Array.isArray(details) && details.some((d) => isRecord8(d) && d["modelCode"] === "zread")) {
9600
10620
  continue;
9601
10621
  }
9602
10622
  const durationMs = zaiWindowDurationMs(item);
9603
10623
  const { id, label } = zaiWindowIdLabel(durationMs);
9604
- const limit = finiteNumber3(item.usage);
9605
- const used = finiteNumber3(item.currentValue);
10624
+ const limit = finiteNumber5(item.usage);
10625
+ const used = finiteNumber5(item.currentValue);
9606
10626
  const fromAbsolute = limit !== void 0 && used !== void 0 && limit > 0 ? Math.min(100, used / limit * 100) : void 0;
9607
10627
  const fromPercentage = finitePercent4(item.percentage) ?? void 0;
9608
10628
  const usedPercent = fromAbsolute !== void 0 ? Math.round(fromAbsolute * 10) / 10 : fromPercentage;
@@ -9613,9 +10633,9 @@ function parseZaiQuotaPayload(payload, now) {
9613
10633
  label,
9614
10634
  scope: "all",
9615
10635
  usedPercent,
9616
- ...durationMs !== void 0 ? { windowMinutes: Math.round(durationMs / MINUTE_MS2) } : {},
10636
+ ...durationMs !== void 0 ? { windowMinutes: Math.round(durationMs / MINUTE_MS3) } : {},
9617
10637
  ...resetsAt !== void 0 ? { resetsAt } : {},
9618
- remainingSeconds: secondsUntil5(resetsAt, now),
10638
+ remainingSeconds: secondsUntil8(resetsAt, now),
9619
10639
  state: "fresh"
9620
10640
  };
9621
10641
  const existing = byWindow.get(id);
@@ -9629,21 +10649,21 @@ function parseZaiQuotaPayload(payload, now) {
9629
10649
  var MINIMAX_STATUS_EXHAUSTED = 2;
9630
10650
  var MINIMAX_SHARED_BUCKET = "general";
9631
10651
  function parseMiniMaxBucket(value) {
9632
- if (!isRecord5(value)) return null;
10652
+ if (!isRecord8(value)) return null;
9633
10653
  const modelName = typeof value["model_name"] === "string" ? value["model_name"].trim() : "";
9634
10654
  if (!modelName) return null;
9635
10655
  const instant = (v) => {
9636
- const n = finiteNumber3(v);
10656
+ const n = finiteNumber5(v);
9637
10657
  return n !== void 0 && n > 1e9 ? n > 1e12 ? n : n * 1e3 : void 0;
9638
10658
  };
9639
10659
  return {
9640
10660
  modelName,
9641
10661
  intervalEnd: instant(value["end_time"]),
9642
- intervalRemainingPercent: finiteNumber3(value["current_interval_remaining_percent"]),
9643
- intervalStatus: finiteNumber3(value["current_interval_status"]),
10662
+ intervalRemainingPercent: finiteNumber5(value["current_interval_remaining_percent"]),
10663
+ intervalStatus: finiteNumber5(value["current_interval_status"]),
9644
10664
  weeklyEnd: instant(value["weekly_end_time"]),
9645
- weeklyRemainingPercent: finiteNumber3(value["current_weekly_remaining_percent"]),
9646
- weeklyStatus: finiteNumber3(value["current_weekly_status"])
10665
+ weeklyRemainingPercent: finiteNumber5(value["current_weekly_remaining_percent"]),
10666
+ weeklyStatus: finiteNumber5(value["current_weekly_status"])
9647
10667
  };
9648
10668
  }
9649
10669
  function minimaxWindow(id, label, windowMinutes, resetsAtMs, remainingPercent, status, now) {
@@ -9656,14 +10676,14 @@ function minimaxWindow(id, label, windowMinutes, resetsAtMs, remainingPercent, s
9656
10676
  usedPercent,
9657
10677
  ...windowMinutes !== void 0 ? { windowMinutes } : {},
9658
10678
  ...resetsAt !== void 0 ? { resetsAt } : {},
9659
- remainingSeconds: secondsUntil5(resetsAt, now),
10679
+ remainingSeconds: secondsUntil8(resetsAt, now),
9660
10680
  state: usedPercent !== null ? "fresh" : "unavailable"
9661
10681
  };
9662
10682
  }
9663
10683
  function parseMiniMaxTokenPlanPayload(payload, now) {
9664
- if (!isRecord5(payload)) return null;
10684
+ if (!isRecord8(payload)) return null;
9665
10685
  const baseResp = payload["base_resp"];
9666
- if (!isRecord5(baseResp) || baseResp["status_code"] !== 0) return null;
10686
+ if (!isRecord8(baseResp) || baseResp["status_code"] !== 0) return null;
9667
10687
  const buckets = Array.isArray(payload["model_remains"]) ? payload["model_remains"] : [];
9668
10688
  let general = null;
9669
10689
  for (const raw of buckets) {
@@ -9687,7 +10707,7 @@ function parseMiniMaxTokenPlanPayload(payload, now) {
9687
10707
  minimaxWindow(
9688
10708
  "seven-day",
9689
10709
  "7 days",
9690
- Math.round(WEEK_MS / MINUTE_MS2),
10710
+ Math.round(WEEK_MS / MINUTE_MS3),
9691
10711
  general.weeklyEnd,
9692
10712
  general.weeklyRemainingPercent,
9693
10713
  general.weeklyStatus,
@@ -9696,15 +10716,15 @@ function parseMiniMaxTokenPlanPayload(payload, now) {
9696
10716
  ];
9697
10717
  }
9698
10718
  function parseUmansUsagePayload(payload, now) {
9699
- if (!isRecord5(payload)) return null;
9700
- const limits = isRecord5(payload["limits"]) ? payload["limits"] : void 0;
9701
- const requests = limits && isRecord5(limits["requests"]) ? limits["requests"] : void 0;
9702
- const usage = isRecord5(payload["usage"]) ? payload["usage"] : void 0;
9703
- const window = isRecord5(payload["window"]) ? payload["window"] : void 0;
9704
- const hardCap = finiteNumber3(requests?.["hard_cap"]);
9705
- const softLimit = finiteNumber3(requests?.["limit"]);
9706
- const requestsInWindow = finiteNumber3(usage?.["requests_in_window"]);
9707
- const weightedInWindow = finiteNumber3(usage?.["weighted_in_window"]);
10719
+ if (!isRecord8(payload)) return null;
10720
+ const limits = isRecord8(payload["limits"]) ? payload["limits"] : void 0;
10721
+ const requests = limits && isRecord8(limits["requests"]) ? limits["requests"] : void 0;
10722
+ const usage = isRecord8(payload["usage"]) ? payload["usage"] : void 0;
10723
+ const window = isRecord8(payload["window"]) ? payload["window"] : void 0;
10724
+ const hardCap = finiteNumber5(requests?.["hard_cap"]);
10725
+ const softLimit = finiteNumber5(requests?.["limit"]);
10726
+ const requestsInWindow = finiteNumber5(usage?.["requests_in_window"]);
10727
+ const weightedInWindow = finiteNumber5(usage?.["weighted_in_window"]);
9708
10728
  const resetsAt = isoInstant3(window?.["resets_at"]);
9709
10729
  let usedPercent = null;
9710
10730
  if (hardCap !== void 0 && hardCap > 0 && requestsInWindow !== void 0) {
@@ -9721,19 +10741,19 @@ function parseUmansUsagePayload(payload, now) {
9721
10741
  usedPercent,
9722
10742
  windowMinutes: 5 * 60,
9723
10743
  ...resetsAt !== void 0 ? { resetsAt } : {},
9724
- remainingSeconds: secondsUntil5(resetsAt, now),
10744
+ remainingSeconds: secondsUntil8(resetsAt, now),
9725
10745
  state: "fresh"
9726
10746
  }
9727
10747
  ];
9728
10748
  }
9729
10749
  function parseSyntheticQuotasPayload(payload, now) {
9730
- if (!isRecord5(payload)) return null;
9731
- const fiveHour = isRecord5(payload["rollingFiveHourLimit"]) ? payload["rollingFiveHourLimit"] : void 0;
9732
- const weekly = isRecord5(payload["weeklyTokenLimit"]) ? payload["weeklyTokenLimit"] : void 0;
10750
+ if (!isRecord8(payload)) return null;
10751
+ const fiveHour = isRecord8(payload["rollingFiveHourLimit"]) ? payload["rollingFiveHourLimit"] : void 0;
10752
+ const weekly = isRecord8(payload["weeklyTokenLimit"]) ? payload["weeklyTokenLimit"] : void 0;
9733
10753
  const windows = [];
9734
10754
  if (fiveHour) {
9735
- const max = finiteNumber3(fiveHour["max"]);
9736
- const remaining = finiteNumber3(fiveHour["remaining"]);
10755
+ const max = finiteNumber5(fiveHour["max"]);
10756
+ const remaining = finiteNumber5(fiveHour["remaining"]);
9737
10757
  const usedPercent = max !== void 0 && max > 0 && remaining !== void 0 ? Math.round(Math.min(100, (max - remaining) / max * 100) * 10) / 10 : null;
9738
10758
  const resetsAt = isoInstant3(fiveHour["nextTickAt"]);
9739
10759
  windows.push({
@@ -9743,12 +10763,12 @@ function parseSyntheticQuotasPayload(payload, now) {
9743
10763
  usedPercent,
9744
10764
  windowMinutes: 5 * 60,
9745
10765
  ...resetsAt !== void 0 ? { resetsAt } : {},
9746
- remainingSeconds: secondsUntil5(resetsAt, now),
10766
+ remainingSeconds: secondsUntil8(resetsAt, now),
9747
10767
  state: usedPercent !== null || resetsAt ? "fresh" : "unavailable"
9748
10768
  });
9749
10769
  }
9750
10770
  if (weekly) {
9751
- const percentRemaining = finiteNumber3(weekly["percentRemaining"]);
10771
+ const percentRemaining = finiteNumber5(weekly["percentRemaining"]);
9752
10772
  const usedPercent = percentRemaining !== void 0 ? Math.round(Math.min(100, Math.max(0, 100 - percentRemaining)) * 10) / 10 : null;
9753
10773
  const resetsAt = isoInstant3(weekly["nextRegenAt"]);
9754
10774
  windows.push({
@@ -9758,12 +10778,42 @@ function parseSyntheticQuotasPayload(payload, now) {
9758
10778
  usedPercent,
9759
10779
  windowMinutes: 7 * 24 * 60,
9760
10780
  ...resetsAt !== void 0 ? { resetsAt } : {},
9761
- remainingSeconds: secondsUntil5(resetsAt, now),
10781
+ remainingSeconds: secondsUntil8(resetsAt, now),
9762
10782
  state: usedPercent !== null || resetsAt ? "fresh" : "unavailable"
9763
10783
  });
9764
10784
  }
9765
10785
  return windows.length > 0 ? windows : null;
9766
10786
  }
10787
+ var CLINE_WINDOW_CONFIG = {
10788
+ five_hour: { id: "five-hour", label: "5 hours", minutes: 5 * 60 },
10789
+ weekly: { id: "seven-day", label: "7 days", minutes: 7 * 24 * 60 },
10790
+ monthly: { id: "thirty-day", label: "30 days", minutes: 30 * 24 * 60 }
10791
+ };
10792
+ function parseClinePassUsageLimitsPayload(payload, now) {
10793
+ if (!isRecord8(payload)) return null;
10794
+ const data = isRecord8(payload["data"]) ? payload["data"] : payload;
10795
+ const limits = Array.isArray(data["limits"]) ? data["limits"] : [];
10796
+ const windows = [];
10797
+ for (const raw of limits) {
10798
+ if (!isRecord8(raw)) continue;
10799
+ const config = CLINE_WINDOW_CONFIG[typeof raw["type"] === "string" ? raw["type"] : ""];
10800
+ if (!config) continue;
10801
+ const usedPercent = finitePercent4(raw["percentUsed"]);
10802
+ if (usedPercent === null) continue;
10803
+ const resetsAt = isoInstant3(raw["resetsAt"]);
10804
+ windows.push({
10805
+ id: config.id,
10806
+ label: config.label,
10807
+ scope: "all",
10808
+ usedPercent,
10809
+ windowMinutes: config.minutes,
10810
+ ...resetsAt !== void 0 ? { resetsAt } : {},
10811
+ remainingSeconds: secondsUntil8(resetsAt, now),
10812
+ state: "fresh"
10813
+ });
10814
+ }
10815
+ return windows.length > 0 ? windows : null;
10816
+ }
9767
10817
 
9768
10818
  // src/allowance/ProviderKeyQuotaService.ts
9769
10819
  function parseQuotaPayload(adapter, payload, now) {
@@ -9776,6 +10826,8 @@ function parseQuotaPayload(adapter, payload, now) {
9776
10826
  return parseUmansUsagePayload(payload, now);
9777
10827
  case "synthetic":
9778
10828
  return parseSyntheticQuotasPayload(payload, now);
10829
+ case "cline-pass":
10830
+ return parseClinePassUsageLimitsPayload(payload, now);
9779
10831
  }
9780
10832
  }
9781
10833
  var PROVIDER_KEY_QUOTA_CACHE_MS = 5 * 6e4;
@@ -9795,7 +10847,7 @@ function rowKeyEntries(row) {
9795
10847
  return [];
9796
10848
  }
9797
10849
  var ProviderKeyQuotaService = class {
9798
- constructor(box, fetchImpl = (url, init) => fetchUpstream6(url, init, { redactBodies: true }), now = Date.now) {
10850
+ constructor(box, fetchImpl = (url, init) => fetchUpstream9(url, init, { redactBodies: true }), now = Date.now) {
9799
10851
  this.box = box;
9800
10852
  this.fetchImpl = fetchImpl;
9801
10853
  this.now = now;
@@ -9857,7 +10909,10 @@ var ProviderKeyQuotaService = class {
9857
10909
  headers: {
9858
10910
  Authorization: providerKeyQuotaAuthHeader(adapter, key),
9859
10911
  Accept: "application/json",
9860
- "Content-Type": "application/json"
10912
+ "Content-Type": "application/json",
10913
+ // The row's static identity headers ride along — the Cline usage
10914
+ // endpoint sits behind the SAME client-identity 403 gate as inference.
10915
+ ...mergeExtraHeaders2({}, row.extraHeaders)
9861
10916
  },
9862
10917
  signal: AbortSignal.timeout(15e3)
9863
10918
  });
@@ -14629,6 +15684,10 @@ function toLLMProvider(row) {
14629
15684
  // `parseProviderInput`), so customizations are preserved (the row value wins).
14630
15685
  apiModes: row.apiModes,
14631
15686
  selectedApiModeId: row.selectedApiModeId,
15687
+ // Static extra request headers ride along verbatim (load-guarded — no
15688
+ // auth/content names); core's `getProviderHeaders` merges them into every
15689
+ // BYO request, and the same-format relay path inherits that funnel.
15690
+ extraHeaders: row.extraHeaders,
14632
15691
  // Official-Anthropic signature handling only matters for the Anthropic
14633
15692
  // ingress (deferred → 502); leave it off for the BYO transform path.
14634
15693
  isOfficial: false
@@ -16578,12 +17637,13 @@ import { existsSync as existsSync24, mkdirSync as mkdirSync6, readFileSync as re
16578
17637
  import { dirname as dirname15 } from "path";
16579
17638
  import { getSharedAccountHealth as getSharedAccountHealth2 } from "@omnicross/core/pipeline/SubscriptionAccountHealth";
16580
17639
  import { getSharedAccountAllowanceScheduling as getSharedAccountAllowanceScheduling3 } from "@omnicross/core/pipeline/AccountAllowanceScheduling";
16581
- import { fetchUpstream as fetchUpstream7 } from "@omnicross/core/pipeline/upstreamFetch";
17640
+ import { fetchUpstream as fetchUpstream10 } from "@omnicross/core/pipeline/upstreamFetch";
16582
17641
  import { getSharedIdentityStore as getSharedIdentityStore2 } from "@omnicross/core/provider-proxy/identity/SubscriptionIdentityStore";
16583
17642
  import {
16584
17643
  claudeOAuth as claudeOAuth2,
16585
17644
  codexOAuth as codexOAuth2,
16586
17645
  geminiOAuth as geminiOAuth2,
17646
+ grokOAuth as grokOAuth2,
16587
17647
  kimiOAuth as kimiOAuth2
16588
17648
  } from "@omnicross/subscriptions";
16589
17649
 
@@ -16733,7 +17793,7 @@ var JsonSubscriptionCredentialStore = class {
16733
17793
  * a plaintext token pair into `upstream-trace.jsonl`.
16734
17794
  */
16735
17795
  buildRefreshFetch(providerId, accountId) {
16736
- return this.fetchImpl ?? ((url, init) => fetchUpstream7(url, init, { providerId, accountId, redactBodies: true }));
17796
+ return this.fetchImpl ?? ((url, init) => fetchUpstream10(url, init, { providerId, accountId, redactBodies: true }));
16737
17797
  }
16738
17798
  /**
16739
17799
  * In-flight refresh coalescing. OAuth refresh tokens are
@@ -16774,7 +17834,7 @@ var JsonSubscriptionCredentialStore = class {
16774
17834
  * other hot reads. Never returns token material.
16775
17835
  */
16776
17836
  getAccountProxy(providerId, accountId) {
16777
- if (providerId !== "claude" && providerId !== "codex" && providerId !== "gemini" && providerId !== "opencodego" && providerId !== "kimi") {
17837
+ if (providerId !== "claude" && providerId !== "codex" && providerId !== "gemini" && providerId !== "opencodego" && providerId !== "kimi" && providerId !== "grok" && providerId !== "copilot") {
16778
17838
  return void 0;
16779
17839
  }
16780
17840
  return getAccountProxy(this.readConfig(), providerId, accountId);
@@ -16793,7 +17853,7 @@ var JsonSubscriptionCredentialStore = class {
16793
17853
  const fingerprintOn = identityStore.isEnabled();
16794
17854
  const now = Date.now();
16795
17855
  const out = {};
16796
- for (const provider of ["claude", "codex", "gemini", "opencodego", "kimi"]) {
17856
+ for (const provider of ["claude", "codex", "gemini", "opencodego", "kimi", "grok", "copilot"]) {
16797
17857
  const sanitized = sanitizeAccounts(config, provider);
16798
17858
  if (sanitized.length === 0) continue;
16799
17859
  for (const account of sanitized) {
@@ -16992,6 +18052,66 @@ var JsonSubscriptionCredentialStore = class {
16992
18052
  }
16993
18053
  });
16994
18054
  }
18055
+ /**
18056
+ * Refresh the Grok (xAI SuperGrok) OAuth access token. The token endpoint is
18057
+ * resolved through OIDC discovery on every refresh (process-cached 1h by the
18058
+ * flow module) so a rotated endpoint document is picked up without a daemon
18059
+ * restart. HONEST `false` when no refresh_token.
18060
+ */
18061
+ async refreshGrokToken() {
18062
+ return this.coalesce("grok:active", async () => {
18063
+ const config = this.readConfig();
18064
+ const active = getActiveAccount(config, "grok");
18065
+ const grok = active?.tokens;
18066
+ if (!active || !grok?.refreshToken) return false;
18067
+ const capturedId = active.id;
18068
+ this.materializeMigration(config);
18069
+ const refreshFetch = this.buildRefreshFetch("grok", capturedId);
18070
+ try {
18071
+ const tokenEndpoint = await grokOAuth2.resolveGrokTokenEndpoint(refreshFetch);
18072
+ const result = await grokOAuth2.refreshGrokAccessToken(grok.refreshToken, tokenEndpoint, refreshFetch);
18073
+ const expiresAt = new Date(Date.now() + result.expiresIn * 1e3).toISOString();
18074
+ const next = {
18075
+ ...grok,
18076
+ accessToken: result.accessToken,
18077
+ refreshToken: result.refreshToken,
18078
+ expiresAt,
18079
+ status: "authorized",
18080
+ lastRefreshedAt: (/* @__PURE__ */ new Date()).toISOString(),
18081
+ errorMessage: void 0,
18082
+ syncWarning: void 0
18083
+ };
18084
+ this.writeBackById("grok", capturedId, next);
18085
+ return true;
18086
+ } catch (error) {
18087
+ this.markExpiredById("grok", capturedId, grok, error);
18088
+ return false;
18089
+ }
18090
+ });
18091
+ }
18092
+ /**
18093
+ * "Refresh" a GitHub Copilot token — there is nothing to refresh (ghu_
18094
+ * tokens are long-lived with no exchange endpoint). A call here means the
18095
+ * strategy saw a 401 (the token was revoked); mark the account `expired`
18096
+ * with a re-authenticate message and return `false` (the proxy then declines
18097
+ * the retry instead of looping on a dead token).
18098
+ */
18099
+ async refreshCopilotToken() {
18100
+ return this.coalesce("copilot:active", async () => {
18101
+ const config = this.readConfig();
18102
+ const active = getActiveAccount(config, "copilot");
18103
+ const copilot = active?.tokens;
18104
+ if (!active || !copilot?.accessToken) return false;
18105
+ this.materializeMigration(config);
18106
+ this.markExpiredById(
18107
+ "copilot",
18108
+ active.id,
18109
+ copilot,
18110
+ new Error("GitHub Copilot tokens cannot be refreshed \u2014 re-authenticate the account")
18111
+ );
18112
+ return false;
18113
+ });
18114
+ }
16995
18115
  /**
16996
18116
  * Refresh a SPECIFIC managed account by id (background scheduler sweep and
16997
18117
  * account-pool resolution). It uses only that account's stored refresh
@@ -17044,7 +18164,7 @@ var JsonSubscriptionCredentialStore = class {
17044
18164
  }
17045
18165
  const oauth = account.tokens;
17046
18166
  if (!oauth.accessToken) return null;
17047
- if (providerId === "codex" || providerId === "gemini" || providerId === "kimi") {
18167
+ if (providerId === "codex" || providerId === "gemini" || providerId === "kimi" || providerId === "grok" || providerId === "copilot") {
17048
18168
  const expiresAtMs = oauth.expiresAt ? Date.parse(oauth.expiresAt) : 0;
17049
18169
  const expiringSoon = expiresAtMs > 0 && Date.now() >= expiresAtMs - ACCOUNT_REFRESH_LEAD_MS;
17050
18170
  if (expiringSoon && oauth.refreshToken) {
@@ -17148,6 +18268,18 @@ var JsonSubscriptionCredentialStore = class {
17148
18268
  expiresAt: new Date(Date.now() + r2.expiresIn * 1e3).toISOString()
17149
18269
  };
17150
18270
  }
18271
+ if (provider === "grok") {
18272
+ const tokenEndpoint = await grokOAuth2.resolveGrokTokenEndpoint(refreshFetch);
18273
+ const r2 = await grokOAuth2.refreshGrokAccessToken(refreshToken, tokenEndpoint, refreshFetch);
18274
+ return {
18275
+ accessToken: r2.accessToken,
18276
+ refreshToken: r2.refreshToken,
18277
+ expiresAt: new Date(Date.now() + r2.expiresIn * 1e3).toISOString()
18278
+ };
18279
+ }
18280
+ if (provider === "copilot") {
18281
+ throw new Error("GitHub Copilot tokens cannot be refreshed \u2014 re-authenticate the account");
18282
+ }
17151
18283
  const flow = provider === "claude" ? claudeOAuth2 : provider === "codex" ? codexOAuth2 : geminiOAuth2;
17152
18284
  const r = await flow.refreshAccessToken(refreshToken, refreshFetch);
17153
18285
  return {
@@ -17391,7 +18523,7 @@ var JsonSubscriptionCredentialStore = class {
17391
18523
  };
17392
18524
 
17393
18525
  // src/AccountHealthProbeScheduler.ts
17394
- import { fetchUpstream as fetchUpstream8 } from "@omnicross/core/pipeline/upstreamFetch";
18526
+ import { fetchUpstream as fetchUpstream11 } from "@omnicross/core/pipeline/upstreamFetch";
17395
18527
 
17396
18528
  // src/probe/CodexGenerationProbe.ts
17397
18529
  import {
@@ -17537,7 +18669,16 @@ var PROVIDER_PROBE_PLANS = {
17537
18669
  // Kimi's `GET /coding/v1/usages` is a verified FREE authed GET (the allowance
17538
18670
  // collector uses it), but the probe path also needs the fingerprint headers —
17539
18671
  // keep the probe local until the collector covers the health surface.
17540
- kimi: { kind: "local" }
18672
+ kimi: { kind: "local" },
18673
+ // Grok's billing proxy is a verified FREE authed GET (the allowance collector
18674
+ // uses it) but it REJECTS non-OAuth credentials and sits on a separate host
18675
+ // with its own product-gate header — keep the probe local, the collector
18676
+ // owns the health surface.
18677
+ grok: { kind: "local" },
18678
+ // The Copilot quota endpoint (copilot_internal/user) is a verified FREE
18679
+ // authed GET but lives on api.github.com with its own auth dialect and a
18680
+ // monthly-only window — the allowance collector owns the health surface.
18681
+ copilot: { kind: "local" }
17541
18682
  };
17542
18683
  function probePlanFor(providerId) {
17543
18684
  return PROVIDER_PROBE_PLANS[providerId] ?? { kind: "local" };
@@ -17559,7 +18700,7 @@ var AccountHealthProbeScheduler = class {
17559
18700
  this.logger = logger;
17560
18701
  this.config = config;
17561
18702
  this.now = opts.now ?? Date.now;
17562
- this.fetchImpl = opts.fetchImpl ?? fetchUpstream8;
18703
+ this.fetchImpl = opts.fetchImpl ?? fetchUpstream11;
17563
18704
  this.sleep = opts.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
17564
18705
  this.planFor = opts.planFor ?? probePlanFor;
17565
18706
  }
@@ -18116,7 +19257,7 @@ async function readAuditStats(auditDir, query2 = {}) {
18116
19257
  }
18117
19258
 
18118
19259
  // src/audit/AuditPruneSweeper.ts
18119
- var DAY_MS3 = 24 * 60 * 6e4;
19260
+ var DAY_MS4 = 24 * 60 * 6e4;
18120
19261
  var SWEEP_INTERVAL_MS2 = 60 * 6e4;
18121
19262
  var ARCHIVE_BATCH = 64;
18122
19263
  var AuditPruneSweeper = class {
@@ -18180,7 +19321,7 @@ var AuditPruneSweeper = class {
18180
19321
  this.sweeping = true;
18181
19322
  try {
18182
19323
  if (!existsSync26(this.auditDir)) return 0;
18183
- const cutoff = this.todayMidnight() - (this.config.retentionDays - 1) * DAY_MS3;
19324
+ const cutoff = this.todayMidnight() - (this.config.retentionDays - 1) * DAY_MS4;
18184
19325
  let removed = 0;
18185
19326
  for (const name of readdirSync8(this.auditDir)) {
18186
19327
  const dateMs = auditFileDateMs(name);
@@ -18437,7 +19578,7 @@ async function closeAll(writers) {
18437
19578
  // src/usage/UsagePruneSweeper.ts
18438
19579
  import { unlink as unlink3 } from "fs/promises";
18439
19580
  import { join as join24 } from "path";
18440
- var DAY_MS4 = 24 * 60 * 6e4;
19581
+ var DAY_MS5 = 24 * 60 * 6e4;
18441
19582
  var SWEEP_INTERVAL_MS3 = 60 * 6e4;
18442
19583
  var DEFAULT_USAGE_RETENTION_DAYS = 90;
18443
19584
  var UsagePruneSweeper = class {
@@ -18494,7 +19635,7 @@ var UsagePruneSweeper = class {
18494
19635
  this.sweeping = true;
18495
19636
  try {
18496
19637
  const retentionDays = this.config.retentionDays ?? DEFAULT_USAGE_RETENTION_DAYS;
18497
- const cutoff = this.todayMidnight() - (retentionDays - 1) * DAY_MS4;
19638
+ const cutoff = this.todayMidnight() - (retentionDays - 1) * DAY_MS5;
18498
19639
  let removed = 0;
18499
19640
  for (const entry of await listUsageDays(this.usageDir)) {
18500
19641
  if (!entry.hasShard) continue;
@@ -18722,7 +19863,7 @@ var AuditWriter = class {
18722
19863
  import { appendFileSync as appendFileSync3, mkdirSync as mkdirSync8 } from "fs";
18723
19864
  import { createHmac as createHmac5 } from "crypto";
18724
19865
  import { join as join27 } from "path";
18725
- import { fetchUpstream as fetchUpstream9 } from "@omnicross/core/pipeline/upstreamFetch";
19866
+ import { fetchUpstream as fetchUpstream12 } from "@omnicross/core/pipeline/upstreamFetch";
18726
19867
 
18727
19868
  // src/billing/billingFiles.ts
18728
19869
  var BILLING_FILE_RE = /^billing-(\d{4})-(\d{2})-(\d{2})\.jsonl$/;
@@ -18745,7 +19886,7 @@ var BillingPublisher = class {
18745
19886
  constructor(billingDir, logger, opts = {}) {
18746
19887
  this.billingDir = billingDir;
18747
19888
  this.logger = logger;
18748
- this.fetchImpl = opts.fetchImpl ?? ((url, init) => fetchUpstream9(url, init));
19889
+ this.fetchImpl = opts.fetchImpl ?? ((url, init) => fetchUpstream12(url, init));
18749
19890
  this.defer = opts.defer ?? ((fn) => setTimeout(fn, 0));
18750
19891
  this.timeoutMs = opts.timeoutMs ?? BILLING_POST_TIMEOUT_MS;
18751
19892
  this.now = opts.now ?? Date.now;
@@ -18995,7 +20136,7 @@ var BillingRetrySweeper = class {
18995
20136
  // src/TokenRefreshScheduler.ts
18996
20137
  var REFRESH_LEAD_MS2 = 5 * 6e4;
18997
20138
  var SWEEP_INTERVAL_MS5 = 6e4;
18998
- var OAUTH_PROVIDERS2 = ["claude", "codex", "gemini", "kimi"];
20139
+ var OAUTH_PROVIDERS2 = ["claude", "codex", "gemini", "kimi", "grok", "copilot"];
18999
20140
  var TokenRefreshScheduler = class {
19000
20141
  constructor(store, logger, intervalMs = SWEEP_INTERVAL_MS5, leadMs = REFRESH_LEAD_MS2) {
19001
20142
  this.store = store;
@@ -19080,6 +20221,12 @@ var TokenRefreshScheduler = class {
19080
20221
  return this.store.refreshGeminiToken();
19081
20222
  case "kimi":
19082
20223
  return this.store.refreshKimiToken();
20224
+ case "grok":
20225
+ return this.store.refreshGrokToken();
20226
+ // ghu_ tokens never near-expire (far-future expiresAt), so the sweep
20227
+ // never reaches this — the branch exists for union totality.
20228
+ case "copilot":
20229
+ return this.store.refreshCopilotToken();
19083
20230
  }
19084
20231
  }
19085
20232
  };
@@ -19158,7 +20305,7 @@ function createRouteLeaseSubscriptionPreflight(credentials) {
19158
20305
 
19159
20306
  // src/webhook/WebhookDispatcher.ts
19160
20307
  import { createHmac as createHmac6 } from "crypto";
19161
- import { fetchUpstream as fetchUpstream10 } from "@omnicross/core/pipeline/upstreamFetch";
20308
+ import { fetchUpstream as fetchUpstream13 } from "@omnicross/core/pipeline/upstreamFetch";
19162
20309
  var WEBHOOK_MAX_ATTEMPTS = 3;
19163
20310
  var WEBHOOK_QUEUE_MAX = 1e3;
19164
20311
  var WEBHOOK_SEND_TIMEOUT_MS = 1e4;
@@ -19178,7 +20325,7 @@ var WebhookDispatcher = class {
19178
20325
  sleep;
19179
20326
  now;
19180
20327
  constructor(opts = {}) {
19181
- this.fetchImpl = opts.fetchImpl ?? ((url, init) => fetchUpstream10(url, init));
20328
+ this.fetchImpl = opts.fetchImpl ?? ((url, init) => fetchUpstream13(url, init));
19182
20329
  this.logger = opts.logger;
19183
20330
  this.maxAttempts = opts.maxAttempts ?? WEBHOOK_MAX_ATTEMPTS;
19184
20331
  this.queueMax = opts.queueMax ?? WEBHOOK_QUEUE_MAX;
@@ -19264,8 +20411,8 @@ var WebhookDispatcher = class {
19264
20411
  signal: AbortSignal.timeout(this.timeoutMs)
19265
20412
  });
19266
20413
  return res.ok ? { ok: true, status: res.status } : { ok: false, status: res.status };
19267
- } catch (err6) {
19268
- return { ok: false, error: err6 instanceof Error ? err6.message : String(err6) };
20414
+ } catch (err8) {
20415
+ return { ok: false, error: err8 instanceof Error ? err8.message : String(err8) };
19269
20416
  }
19270
20417
  }
19271
20418
  /**
@@ -19402,7 +20549,7 @@ function buildDaemon(config, paths) {
19402
20549
  setSecretBox(secretBox3);
19403
20550
  setSecretBox2(secretBox3);
19404
20551
  const decryptedConfig = decryptConfigSecrets(config, secretBox3);
19405
- const accountAllowanceStore = new AccountAllowanceStore6(
20552
+ const accountAllowanceStore = new AccountAllowanceStore9(
19406
20553
  Date.now,
19407
20554
  void 0,
19408
20555
  new JsonAccountAllowancePersistence(defaultAccountAllowancePath(paths.configPath))
@@ -19445,7 +20592,7 @@ function buildDaemon(config, paths) {
19445
20592
  getAccountProxy: (providerId, accountId) => credentialStore.getAccountProxy(providerId, accountId)
19446
20593
  })
19447
20594
  );
19448
- setGeminiCodeAssistResolver(getGeminiCodeAssistProjectResolver());
20595
+ setGeminiCodeAssistResolver(getGeminiCodeAssistProjectResolver2());
19449
20596
  const autoDisableStore = new AutoDisableStore();
19450
20597
  const providerKeyQuotaService = new ProviderKeyQuotaService(secretBox3);
19451
20598
  const apiKeyPool = new ApiKeyPoolService(
@@ -19464,7 +20611,7 @@ function buildDaemon(config, paths) {
19464
20611
  const pricingEngine = new PricingEngine(pricingStore, logger, {
19465
20612
  // Catalog egress follows the same global/env proxy policy as every other
19466
20613
  // daemon upstream call; no provider/account override applies here.
19467
- fetchImpl: ((input, init) => fetchUpstream11(String(input), init ?? {}))
20614
+ fetchImpl: ((input, init) => fetchUpstream14(String(input), init ?? {}))
19468
20615
  });
19469
20616
  const pricingRefreshScheduler = new PricingRefreshScheduler(
19470
20617
  pricingEngine,
@@ -19749,7 +20896,7 @@ function buildDaemon(config, paths) {
19749
20896
  // — `server.proxy.byProvider[...]` was silently skipped — and the call was
19750
20897
  // excluded from the upstream trace, so a failing login left no evidence.
19751
20898
  // `redactBodies` keeps the code/verifier + minted token out of that trace.
19752
- oauthExchangeFetch: paths.oauthExchangeFetch ? () => paths.oauthExchangeFetch : (providerId) => (url, init) => fetchUpstream11(url, init, { providerId, redactBodies: true }),
20899
+ oauthExchangeFetch: paths.oauthExchangeFetch ? () => paths.oauthExchangeFetch : (providerId) => (url, init) => fetchUpstream14(url, init, { providerId, redactBodies: true }),
19753
20900
  subscriptionAccountAppender: credentialStore,
19754
20901
  // Codex interactive OAuth (app-parity-2 child 5) — the async loopback flow store
19755
20902
  // + the one-shot 127.0.0.1:1455 listener. Token captured + persisted daemon-side;
@@ -19761,6 +20908,9 @@ function buildDaemon(config, paths) {
19761
20908
  // paste; the app shows the verification URL + user code and polls the
19762
20909
  // token-free status). Token captured + persisted daemon-side.
19763
20910
  kimiSessions: new CodexOAuthSessionStore(),
20911
+ // Grok interactive OAuth — the same async DEVICE-CODE shape as kimi.
20912
+ grokSessions: new CodexOAuthSessionStore(),
20913
+ copilotSessions: new CodexOAuthSessionStore(),
19764
20914
  // Migration pack (app-parity child 6, design D2/D3) — the concrete credential
19765
20915
  // store provides BOTH the full DECRYPTED read (`getFullConfig`, export) and
19766
20916
  // the multi-account append (`appendProviderAccount`, import re-encrypts at-
@@ -19819,7 +20969,7 @@ function buildDaemon(config, paths) {
19819
20969
  });
19820
20970
  const webhookDispatcher = new WebhookDispatcher({
19821
20971
  logger,
19822
- fetchImpl: (url, init) => fetchUpstream11(url, init)
20972
+ fetchImpl: (url, init) => fetchUpstream14(url, init)
19823
20973
  });
19824
20974
  setWebhookRuntime(webhookDispatcher, getSharedAccountHealth4());
19825
20975
  const auditWriter = new AuditWriter(auditDir, logger);
@@ -20133,11 +21283,11 @@ async function runLiveProbe(url, key, fetchImpl = fetch) {
20133
21283
  status: res.status,
20134
21284
  estimateHeader: res.headers.get("x-omnicross-count-estimate")
20135
21285
  };
20136
- } catch (err6) {
21286
+ } catch (err8) {
20137
21287
  return {
20138
21288
  status: null,
20139
21289
  estimateHeader: null,
20140
- error: err6 instanceof Error ? err6.message : String(err6)
21290
+ error: err8 instanceof Error ? err8.message : String(err8)
20141
21291
  };
20142
21292
  }
20143
21293
  }
@@ -20547,9 +21697,9 @@ async function runLaunch(argv, deps) {
20547
21697
  await daemon.llmConfig.ready();
20548
21698
  await daemon.migrateUsageStore();
20549
21699
  await daemon.providerProxy.start();
20550
- } catch (err6) {
21700
+ } catch (err8) {
20551
21701
  await shutdownLaunchDaemon(daemon);
20552
- throw err6;
21702
+ throw err8;
20553
21703
  }
20554
21704
  let launch;
20555
21705
  try {
@@ -20557,9 +21707,9 @@ async function runLaunch(argv, deps) {
20557
21707
  providerId: values.provider,
20558
21708
  model: values.model
20559
21709
  });
20560
- } catch (err6) {
21710
+ } catch (err8) {
20561
21711
  await shutdownLaunchDaemon(daemon);
20562
- throw err6;
21712
+ throw err8;
20563
21713
  }
20564
21714
  try {
20565
21715
  const plan = buildCliSpawnPlan({
@@ -20664,9 +21814,9 @@ function spawnCliInherit(plan) {
20664
21814
  process.removeListener("SIGINT", onSignal);
20665
21815
  process.removeListener("SIGTERM", onSignal);
20666
21816
  };
20667
- child.on("error", (err6) => {
21817
+ child.on("error", (err8) => {
20668
21818
  detach();
20669
- if (err6.code === "ENOENT") {
21819
+ if (err8.code === "ENOENT") {
20670
21820
  reject(
20671
21821
  new Error(
20672
21822
  `launch: "${plan.command}" not found on PATH \u2014 install the CLI first.`
@@ -20674,7 +21824,7 @@ function spawnCliInherit(plan) {
20674
21824
  );
20675
21825
  return;
20676
21826
  }
20677
- reject(err6);
21827
+ reject(err8);
20678
21828
  });
20679
21829
  child.on("exit", (code, signal) => {
20680
21830
  detach();
@@ -20687,14 +21837,16 @@ function spawnCliInherit(plan) {
20687
21837
  import { spawn as spawn3 } from "child_process";
20688
21838
  import { createInterface as createInterface2 } from "readline";
20689
21839
  import { parseArgs as parseArgs7 } from "util";
20690
- import { fetchUpstream as fetchUpstream12, setUpstreamProxyResolver as setUpstreamProxyResolver2 } from "@omnicross/core/pipeline/upstreamFetch";
21840
+ import { fetchUpstream as fetchUpstream15, setUpstreamProxyResolver as setUpstreamProxyResolver2 } from "@omnicross/core/pipeline/upstreamFetch";
20691
21841
  import {
20692
21842
  claudeOAuth as claudeOAuth3,
20693
21843
  codexOAuth as codexOAuth3,
21844
+ copilotOAuth as copilotOAuth3,
20694
21845
  geminiOAuth as geminiOAuth3,
21846
+ grokOAuth as grokOAuth3,
20695
21847
  kimiOAuth as kimiOAuth3
20696
21848
  } from "@omnicross/subscriptions";
20697
- var PROVIDERS2 = ["claude", "codex", "gemini", "kimi"];
21849
+ var PROVIDERS2 = ["claude", "codex", "gemini", "kimi", "grok", "copilot"];
20698
21850
  async function runLogin(argv, deps) {
20699
21851
  const { values, positionals } = parseArgs7({
20700
21852
  args: argv,
@@ -20702,7 +21854,9 @@ async function runLogin(argv, deps) {
20702
21854
  config: { type: "string", short: "c" },
20703
21855
  "master-key-file": { type: "string" },
20704
21856
  // Optional user label for the appended account (multi-account).
20705
- label: { type: "string" }
21857
+ label: { type: "string" },
21858
+ // Optional GitHub Enterprise domain for `login copilot` (GHE accounts).
21859
+ enterprise: { type: "string" }
20706
21860
  },
20707
21861
  allowPositionals: true
20708
21862
  });
@@ -20716,11 +21870,17 @@ async function runLogin(argv, deps) {
20716
21870
  if (!values.config) {
20717
21871
  throw new Error("login: --config <path> is required");
20718
21872
  }
21873
+ if (values.enterprise !== void 0 && provider !== "copilot") {
21874
+ throw new Error("login: --enterprise is only supported for the copilot provider");
21875
+ }
21876
+ const enterpriseDomain = values.enterprise !== void 0 ? copilotOAuth3.normalizeCopilotEnterpriseDomain(values.enterprise) : void 0;
20719
21877
  const resolved = {
20720
21878
  openBrowser: deps?.openBrowser ?? openBrowser,
20721
21879
  promptPaste: deps?.promptPaste ?? promptPaste,
20722
21880
  awaitLoopback: deps?.awaitLoopback ?? ((state) => awaitLoopbackCode(state)),
20723
21881
  awaitKimiDevice: deps?.awaitKimiDevice ?? ((fetchImpl) => runKimiDeviceFlow(fetchImpl, resolvedOpenBrowser)),
21882
+ awaitGrokDevice: deps?.awaitGrokDevice ?? ((fetchImpl) => runGrokDeviceFlow(fetchImpl, resolvedOpenBrowser)),
21883
+ awaitCopilotDevice: deps?.awaitCopilotDevice ?? ((fetchImpl, enterpriseUrl) => runCopilotDeviceFlow(fetchImpl, resolvedOpenBrowser, enterpriseUrl)),
20724
21884
  tokensFetch: deps?.tokensFetch
20725
21885
  };
20726
21886
  const resolvedOpenBrowser = resolved.openBrowser;
@@ -20729,14 +21889,15 @@ async function runLogin(argv, deps) {
20729
21889
  setUpstreamProxyResolver2(createUpstreamProxyResolver());
20730
21890
  try {
20731
21891
  const tokensPath = defaultTokensPath(values.config);
20732
- const exchangeFetch = resolved.tokensFetch ?? ((url, init) => fetchUpstream12(url, init, { providerId: provider, redactBodies: true }));
21892
+ const exchangeFetch = resolved.tokensFetch ?? ((url, init) => fetchUpstream15(url, init, { providerId: provider, redactBodies: true }));
20733
21893
  const store = new JsonSubscriptionCredentialStore(tokensPath, box, exchangeFetch);
20734
21894
  const expiresAt = await runProviderLogin(
20735
21895
  provider,
20736
21896
  store,
20737
21897
  resolved,
20738
21898
  exchangeFetch,
20739
- values.label
21899
+ values.label,
21900
+ enterpriseDomain
20740
21901
  );
20741
21902
  console.info(`Logged in to '${provider}' \u2192 ${tokensPath}`);
20742
21903
  console.info(` token: [stored, encrypted] expiresAt: ${expiresAt ?? "n/a"}`);
@@ -20745,10 +21906,12 @@ async function runLogin(argv, deps) {
20745
21906
  setUpstreamProxyResolver2(null);
20746
21907
  }
20747
21908
  }
20748
- async function runProviderLogin(provider, store, deps, exchangeFetch, label) {
21909
+ async function runProviderLogin(provider, store, deps, exchangeFetch, label, enterpriseUrl) {
20749
21910
  if (provider === "codex") return loginCodex(store, deps, exchangeFetch, label);
20750
21911
  if (provider === "claude") return loginClaude(store, deps, exchangeFetch, label);
20751
21912
  if (provider === "kimi") return loginKimi(store, deps, exchangeFetch, label);
21913
+ if (provider === "grok") return loginGrok(store, deps, exchangeFetch, label);
21914
+ if (provider === "copilot") return loginCopilot(store, deps, exchangeFetch, label, enterpriseUrl);
20752
21915
  return loginGemini(store, deps, exchangeFetch, label);
20753
21916
  }
20754
21917
  async function loginCodex(store, deps, exchangeFetch, label) {
@@ -20858,6 +22021,90 @@ async function loginKimi(store, deps, exchangeFetch, label) {
20858
22021
  logMasked("kimi", result.accessToken);
20859
22022
  return expiresAt;
20860
22023
  }
22024
+ async function runGrokDeviceFlow(exchangeFetch, openBrowserFn) {
22025
+ const tokenEndpoint = await grokOAuth3.resolveGrokTokenEndpoint(exchangeFetch);
22026
+ const authorization = await grokOAuth3.requestGrokDeviceAuthorization(exchangeFetch);
22027
+ const url = authorization.verificationUriComplete ?? authorization.verificationUri;
22028
+ console.info("Open this URL in your browser and approve the request:");
22029
+ console.info(` ${url}`);
22030
+ if (!authorization.verificationUriComplete) {
22031
+ console.info(` Then enter this code: ${authorization.userCode}`);
22032
+ }
22033
+ await openBrowserFn(url).catch(() => false);
22034
+ const result = await grokOAuth3.awaitGrokDeviceToken(authorization, tokenEndpoint, exchangeFetch, {
22035
+ onPending: () => process.stdout.write(".")
22036
+ });
22037
+ console.info("");
22038
+ return {
22039
+ ...result,
22040
+ accountId: grokOAuth3.grokAccountIdFromAccessToken(result.accessToken)
22041
+ };
22042
+ }
22043
+ async function loginGrok(store, deps, exchangeFetch, label) {
22044
+ const result = await deps.awaitGrokDevice(exchangeFetch);
22045
+ const expiresAt = new Date(Date.now() + result.expiresIn * 1e3).toISOString();
22046
+ const block = {
22047
+ authMethod: "oauth",
22048
+ status: "authorized",
22049
+ accessToken: result.accessToken,
22050
+ refreshToken: result.refreshToken,
22051
+ expiresAt,
22052
+ ...result.accountId ? { accountId: result.accountId } : {},
22053
+ lastRefreshedAt: (/* @__PURE__ */ new Date()).toISOString()
22054
+ };
22055
+ await store.appendProviderAccount("grok", block, label);
22056
+ logMasked("grok", result.accessToken);
22057
+ return expiresAt;
22058
+ }
22059
+ async function runCopilotDeviceFlow(exchangeFetch, openBrowserFn, enterpriseUrl) {
22060
+ if (enterpriseUrl) console.info(`Using GitHub Enterprise host: ${enterpriseUrl}`);
22061
+ const authorization = await copilotOAuth3.requestCopilotDeviceAuthorization(exchangeFetch, enterpriseUrl);
22062
+ const url = authorization.verificationUri;
22063
+ console.info("Open this URL in your browser and approve the request:");
22064
+ console.info(` ${url}`);
22065
+ console.info(` Then enter this code: ${authorization.userCode}`);
22066
+ await openBrowserFn(url).catch(() => false);
22067
+ const result = await copilotOAuth3.awaitCopilotDeviceToken(authorization, exchangeFetch, {
22068
+ onPending: () => process.stdout.write("."),
22069
+ ...enterpriseUrl ? { enterpriseUrl } : {}
22070
+ });
22071
+ console.info("");
22072
+ const identity = await copilotOAuth3.fetchCopilotIdentity(result.accessToken, exchangeFetch, enterpriseUrl);
22073
+ const apiEndpoint = await copilotOAuth3.discoverCopilotApiEndpoint(result.accessToken, exchangeFetch, enterpriseUrl);
22074
+ console.info("Enabling Copilot models (policy)...");
22075
+ await copilotOAuth3.enableAllCopilotModels(
22076
+ result.accessToken,
22077
+ { apiEndpoint, ...enterpriseUrl ? { enterpriseUrl } : {} },
22078
+ exchangeFetch
22079
+ );
22080
+ return {
22081
+ accessToken: result.accessToken,
22082
+ expiresIn: Math.floor(copilotOAuth3.COPILOT_FAR_FUTURE_MS / 1e3),
22083
+ ...identity,
22084
+ ...apiEndpoint ? { apiEndpoint } : {}
22085
+ };
22086
+ }
22087
+ async function loginCopilot(store, deps, exchangeFetch, label, enterpriseUrl) {
22088
+ const result = await deps.awaitCopilotDevice(exchangeFetch, enterpriseUrl);
22089
+ const expiresAt = new Date(Date.now() + result.expiresIn * 1e3).toISOString();
22090
+ const block = {
22091
+ authMethod: "oauth",
22092
+ status: "authorized",
22093
+ accessToken: result.accessToken,
22094
+ // ghu_ tokens have no refresh lifecycle — the same token doubles as the
22095
+ // stored refresh credential so generic refresh paths stay well-formed.
22096
+ refreshToken: result.accessToken,
22097
+ expiresAt,
22098
+ ...result.accountId ? { accountId: result.accountId } : {},
22099
+ ...result.email ? { email: result.email } : {},
22100
+ ...result.apiEndpoint ? { apiEndpoint: result.apiEndpoint } : {},
22101
+ ...enterpriseUrl ? { enterpriseUrl } : {},
22102
+ lastRefreshedAt: (/* @__PURE__ */ new Date()).toISOString()
22103
+ };
22104
+ await store.appendProviderAccount("copilot", block, label);
22105
+ logMasked("copilot", result.accessToken);
22106
+ return expiresAt;
22107
+ }
20861
22108
  function isLoginProvider(value) {
20862
22109
  return PROVIDERS2.includes(value);
20863
22110
  }
@@ -21563,7 +22810,7 @@ async function main() {
21563
22810
  process.exitCode = 1;
21564
22811
  }
21565
22812
  }
21566
- main().catch((err6) => {
21567
- console.error(err6 instanceof Error ? err6.message : String(err6));
22813
+ main().catch((err8) => {
22814
+ console.error(err8 instanceof Error ? err8.message : String(err8));
21568
22815
  process.exitCode = 1;
21569
22816
  });