@omnicross/daemon 0.1.6 → 0.1.8

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
@@ -1493,10 +1493,20 @@ function assertLoopbackGatewayUrl(value) {
1493
1493
  // src/ports/JsonOutboundKeyDb.ts
1494
1494
  import { existsSync as existsSync4, readFileSync as readFileSync6, writeFileSync as writeFileSync4 } from "fs";
1495
1495
  var JsonOutboundKeyDb = class {
1496
- constructor(keysPath) {
1496
+ /**
1497
+ * @param secretBox OPTIONAL reversible-secret codec. When present, a created
1498
+ * key's plaintext is persisted as a `keySecret` `enc:` envelope (enabling the
1499
+ * operator "view key" affordance via `outboundApiKeysReveal`). When absent the
1500
+ * store stays hash-only (byte-identical to the legacy behavior) and reveal
1501
+ * always returns `null`. Existing 1-arg call sites (tests, lightweight
1502
+ * embedders) keep working.
1503
+ */
1504
+ constructor(keysPath, secretBox3) {
1497
1505
  this.keysPath = keysPath;
1506
+ this.secretBox = secretBox3;
1498
1507
  }
1499
1508
  keysPath;
1509
+ secretBox;
1500
1510
  async outboundApiKeysList() {
1501
1511
  return this.readRows();
1502
1512
  }
@@ -1522,10 +1532,27 @@ var JsonOutboundKeyDb = class {
1522
1532
  allowedEndpoints: input.allowedEndpoints,
1523
1533
  loopbackOnly: input.loopbackOnly
1524
1534
  };
1535
+ if (input.plaintext && this.secretBox) {
1536
+ row.keySecret = this.secretBox.encrypt(input.plaintext);
1537
+ }
1525
1538
  rows.push(row);
1526
1539
  this.writeRows(rows);
1527
1540
  return row;
1528
1541
  }
1542
+ async outboundApiKeysReveal(id) {
1543
+ const rows = this.readRows();
1544
+ const row = rows.find((r) => r.id === id);
1545
+ if (!row || !row.keySecret || !this.secretBox) return null;
1546
+ return this.secretBox.decrypt(row.keySecret);
1547
+ }
1548
+ async outboundApiKeysDelete(id) {
1549
+ const rows = this.readRows();
1550
+ const idx = rows.findIndex((r) => r.id === id);
1551
+ if (idx < 0) return false;
1552
+ rows.splice(idx, 1);
1553
+ this.writeRows(rows);
1554
+ return true;
1555
+ }
1529
1556
  async outboundApiKeysRevoke(id) {
1530
1557
  return this.mutateRow(id, (row) => {
1531
1558
  if (row.revokedAt !== null) return false;
@@ -1723,18 +1750,18 @@ async function keysRevoke(db, id) {
1723
1750
 
1724
1751
  // src/commands/launch.ts
1725
1752
  import { spawn as spawn2 } from "child_process";
1726
- import { existsSync as existsSync18 } from "fs";
1753
+ import { randomUUID as randomUUID6 } from "crypto";
1754
+ import { existsSync as existsSync20 } from "fs";
1727
1755
  import { delimiter as delimiter2, join as join12 } from "path";
1728
1756
  import { parseArgs as parseArgs4 } from "util";
1729
1757
  import {
1730
1758
  buildChatCliLaunchConfig as buildChatCliLaunchConfig2,
1731
- buildClaudeCliLaunchConfig as buildClaudeCliLaunchConfig2,
1732
- buildCodexLaunchConfig as buildCodexLaunchConfig2,
1733
1759
  buildGeminiCliLaunchConfig as buildGeminiCliLaunchConfig2
1734
1760
  } from "@omnicross/cli-launcher";
1761
+ import { ROUTE_LEASE_REQUEST_SCHEMA as ROUTE_LEASE_REQUEST_SCHEMA2 } from "@omnicross/core/provider-proxy";
1735
1762
 
1736
1763
  // src/bootstrap.ts
1737
- import { accessSync, constants as fsConstants, existsSync as existsSync17 } from "fs";
1764
+ import { accessSync, constants as fsConstants, existsSync as existsSync19 } from "fs";
1738
1765
  import { DEFAULT_AUDIT_CONFIG } from "@omnicross/contracts/audit-types";
1739
1766
  import { DEFAULT_BILLING_CONFIG } from "@omnicross/contracts/billing-types";
1740
1767
  import { getGeminiCodeAssistProjectResolver } from "@omnicross/core/auth/GeminiCodeAssistProjectResolver";
@@ -1747,7 +1774,7 @@ import {
1747
1774
  normalizeServerConfig
1748
1775
  } from "@omnicross/core/outbound-api";
1749
1776
  import { setSubscriptionRegistryForOutbound } from "@omnicross/core/outbound-api/subscriptionRegistryPort";
1750
- import { getSharedAccountHealth as getSharedAccountHealth3 } from "@omnicross/core/pipeline/SubscriptionAccountHealth";
1777
+ import { getSharedAccountHealth as getSharedAccountHealth4 } from "@omnicross/core/pipeline/SubscriptionAccountHealth";
1751
1778
  import {
1752
1779
  __resetSharedAccountAllowanceStoreForTests,
1753
1780
  AccountAllowanceStore as AccountAllowanceStore3,
@@ -1755,15 +1782,18 @@ import {
1755
1782
  } from "@omnicross/core/pipeline/AccountAllowanceStore";
1756
1783
  import {
1757
1784
  __resetSharedAccountAllowanceSchedulingForTests,
1758
- getSharedAccountAllowanceScheduling as getSharedAccountAllowanceScheduling4
1785
+ getSharedAccountAllowanceScheduling as getSharedAccountAllowanceScheduling5
1759
1786
  } from "@omnicross/core/pipeline/AccountAllowanceScheduling";
1760
1787
  import { fetchUpstream as fetchUpstream7, setUpstreamProxyResolver } from "@omnicross/core/pipeline/upstreamFetch";
1761
1788
  import { __resetSharedIdentityStoreForTests } from "@omnicross/core/provider-proxy/identity/SubscriptionIdentityStore";
1762
1789
  import { setGeminiCodeAssistResolver } from "@omnicross/core/ports/gemini-code-assist-resolver";
1763
1790
  import {
1764
1791
  __resetProviderProxyForTests,
1765
- getProviderProxy
1792
+ getProviderProxy,
1793
+ RouteLeaseManager,
1794
+ RouteLeaseTargetResolver
1766
1795
  } from "@omnicross/core/provider-proxy";
1796
+ import { routeLeaseDescriptorPort } from "@omnicross/cli-launcher";
1767
1797
  import { KeySpendTracker } from "@omnicross/core/outbound-api";
1768
1798
  import { PricingEngine, UsageRecorder } from "@omnicross/core/usage";
1769
1799
  import {
@@ -1849,7 +1879,7 @@ async function runCodexLoopback(sessionId, codeVerifier, state, signal, deps) {
1849
1879
  const code = await deps.codexAwaitLoopback(state, void 0, signal);
1850
1880
  const result = await codexOAuth.exchangeCodeForTokens(
1851
1881
  { authorizationCode: code, codeVerifier, state },
1852
- deps.oauthExchangeFetch
1882
+ deps.oauthExchangeFetch("codex")
1853
1883
  );
1854
1884
  const expiresAt = new Date(Date.now() + result.expiresIn * 1e3).toISOString();
1855
1885
  const block = {
@@ -2369,6 +2399,17 @@ function handleAuditQuery(req, res, reader) {
2369
2399
  res.writeHead(200, { "Content-Type": "application/json" });
2370
2400
  res.end(JSON.stringify({ records }));
2371
2401
  }
2402
+ async function handleAuditStatsQuery(req, res, reader) {
2403
+ const url = new URL(req.url ?? "/", "http://localhost");
2404
+ const query2 = {};
2405
+ const from = intParam(url.searchParams.get("from"));
2406
+ if (from !== void 0) query2.from = from;
2407
+ const to = intParam(url.searchParams.get("to"));
2408
+ if (to !== void 0) query2.to = to;
2409
+ const stats = reader ? await reader(query2) : { requestCount: 0, errorCount: 0, complete: true };
2410
+ res.writeHead(200, { "Content-Type": "application/json" });
2411
+ res.end(JSON.stringify(stats));
2412
+ }
2372
2413
 
2373
2414
  // src/admin/billingStatusApi.ts
2374
2415
  function handleBillingStatus(res, reader) {
@@ -2458,6 +2499,93 @@ async function handleWebhookTest(req, res) {
2458
2499
  res.end(JSON.stringify({ result }));
2459
2500
  }
2460
2501
 
2502
+ // src/admin/routeLeaseApi.ts
2503
+ import {
2504
+ isLoopbackAddress,
2505
+ normalizeRouteLeaseTtl,
2506
+ ROUTE_LEASE_CAPABILITIES,
2507
+ RouteLeaseError
2508
+ } from "@omnicross/core/provider-proxy";
2509
+ var MAX_BODY_BYTES = 64 * 1024;
2510
+ var SAFE_LEASE_ID = /^[A-Za-z0-9-]{1,128}$/u;
2511
+ async function readJson(req) {
2512
+ const chunks = [];
2513
+ let bytes = 0;
2514
+ for await (const chunk of req) {
2515
+ const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
2516
+ bytes += buffer.length;
2517
+ if (bytes > MAX_BODY_BYTES) throw new RouteLeaseError("invalid_request", "request body is too large");
2518
+ chunks.push(buffer);
2519
+ }
2520
+ if (chunks.length === 0) return {};
2521
+ try {
2522
+ return JSON.parse(Buffer.concat(chunks).toString("utf8"));
2523
+ } catch {
2524
+ throw new RouteLeaseError("invalid_request", "request body is not valid JSON");
2525
+ }
2526
+ }
2527
+ function json(res, status, body, noStore = false) {
2528
+ res.statusCode = status;
2529
+ res.setHeader("Content-Type", "application/json");
2530
+ if (noStore) res.setHeader("Cache-Control", "no-store");
2531
+ res.end(JSON.stringify(body));
2532
+ }
2533
+ function leaseId(value) {
2534
+ if (!value || !SAFE_LEASE_ID.test(value)) throw new RouteLeaseError("invalid_request", "lease id is invalid");
2535
+ return value;
2536
+ }
2537
+ function header(req, name) {
2538
+ const value = req.headers[name.toLowerCase()];
2539
+ return Array.isArray(value) ? value[0] : value;
2540
+ }
2541
+ function writeError(res, error, noStore) {
2542
+ const safe = error instanceof RouteLeaseError ? error : new RouteLeaseError("upstream_unavailable", "route lease operation failed safely");
2543
+ if (safe.retryAfterSeconds !== void 0) res.setHeader("Retry-After", String(safe.retryAfterSeconds));
2544
+ json(res, safe.status, safe.toResponse(), noStore);
2545
+ }
2546
+ async function handleRouteLeaseApi(req, res, path2, deps) {
2547
+ const method = (req.method ?? "GET").toUpperCase();
2548
+ const noStore = method === "POST" && (path2 === "/admin/api/route-leases" || path2.endsWith("/renew"));
2549
+ try {
2550
+ if (!isLoopbackAddress(req.socket.remoteAddress)) {
2551
+ throw new RouteLeaseError("control_unauthorized", "route lease control plane is loopback only");
2552
+ }
2553
+ const manager = deps.routeLeaseManager;
2554
+ if (!manager) throw new RouteLeaseError("daemon_not_ready", "route lease manager is unavailable");
2555
+ const base = "/admin/api/route-leases";
2556
+ const suffix = path2.slice(base.length).replace(/^\/+|\/+$/gu, "");
2557
+ const segments = suffix ? suffix.split("/") : [];
2558
+ if (segments.length === 1 && segments[0] === "capabilities") {
2559
+ if (method !== "GET" && method !== "HEAD") throw new RouteLeaseError("invalid_request", "method is not allowed");
2560
+ return json(res, 200, ROUTE_LEASE_CAPABILITIES);
2561
+ }
2562
+ if (segments.length === 0) {
2563
+ if (method === "GET") return json(res, 200, { leases: manager.list() });
2564
+ if (method === "POST") {
2565
+ const outcome = await manager.createFromRequest(await readJson(req), header(req, "idempotency-key"));
2566
+ return json(res, outcome.created ? 201 : 200, outcome.result, true);
2567
+ }
2568
+ throw new RouteLeaseError("invalid_request", "method is not allowed");
2569
+ }
2570
+ const id = leaseId(segments[0]);
2571
+ if (segments.length === 1) {
2572
+ if (method === "GET") return json(res, 200, manager.get(id));
2573
+ if (method === "DELETE") return json(res, 200, manager.release(id));
2574
+ throw new RouteLeaseError("invalid_request", "method is not allowed");
2575
+ }
2576
+ if (segments.length === 2 && segments[1] === "renew" && method === "POST") {
2577
+ const body = await readJson(req);
2578
+ const ttl = normalizeRouteLeaseTtl(
2579
+ body && typeof body === "object" && !Array.isArray(body) ? body.ttlSeconds : void 0
2580
+ );
2581
+ return json(res, 200, manager.renew(id, ttl), true);
2582
+ }
2583
+ throw new RouteLeaseError("lease_not_found", "route lease endpoint was not found");
2584
+ } catch (error) {
2585
+ writeError(res, error, noStore);
2586
+ }
2587
+ }
2588
+
2461
2589
  // src/admin/adminApi.ts
2462
2590
  import http from "http";
2463
2591
  import {
@@ -2559,7 +2687,13 @@ function listMappablePresets() {
2559
2687
  name: preset.name,
2560
2688
  apiFormat: resolved.format,
2561
2689
  baseUrl: preset.api_base_url,
2562
- models: Array.isArray(preset.models) ? preset.models : []
2690
+ models: Array.isArray(preset.models) ? preset.models : [],
2691
+ nameKey: preset.nameKey,
2692
+ icon: preset.icon,
2693
+ description: preset.description,
2694
+ features: preset.features,
2695
+ website: preset.website,
2696
+ modelsEndpoint: preset.modelsEndpoint
2563
2697
  });
2564
2698
  }
2565
2699
  return { mappable, excluded };
@@ -2950,7 +3084,7 @@ async function handleOAuthComplete(providerId, body, deps) {
2950
3084
  const rawCode = typeof body["code"] === "string" ? body["code"] : "";
2951
3085
  if (!sessionId) return err2(400, "oauth complete requires { sessionId }");
2952
3086
  if (!rawCode) return err2(400, "oauth complete requires { code }");
2953
- const session = deps.oauthSessions.take(sessionId);
3087
+ const session = deps.oauthSessions.peek(sessionId);
2954
3088
  if (!session) return err2(410, "oauth session is unknown, expired, or already used");
2955
3089
  if (session.providerId !== providerId) {
2956
3090
  return err2(400, `oauth session does not match provider '${providerId}'`);
@@ -2964,13 +3098,15 @@ async function handleOAuthComplete(providerId, body, deps) {
2964
3098
  }
2965
3099
  code = splitCode;
2966
3100
  }
3101
+ const exchangeFetch = deps.oauthExchangeFetch(providerId);
2967
3102
  let block;
2968
3103
  try {
2969
- block = providerId === "claude" ? await exchangeClaude(code, session.codeVerifier, session.state, deps.oauthExchangeFetch) : await exchangeGemini(code, session.codeVerifier, deps.oauthExchangeFetch);
3104
+ block = providerId === "claude" ? await exchangeClaude(code, session.codeVerifier, session.state, exchangeFetch) : await exchangeGemini(code, session.codeVerifier, exchangeFetch);
2970
3105
  } catch (exchangeError) {
2971
3106
  const reason = exchangeError instanceof Error ? exchangeError.message : "token exchange failed";
2972
3107
  return err2(502, `oauth token exchange failed for '${providerId}': ${reason}`);
2973
3108
  }
3109
+ deps.oauthSessions.consume(sessionId);
2974
3110
  const label = typeof body["label"] === "string" && body["label"].trim() ? body["label"].trim() : void 0;
2975
3111
  await deps.subscriptionAccountAppender.appendProviderAccount(providerId, block, label);
2976
3112
  const status = await statusEntryFor(deps.subscriptionAccounts, providerId);
@@ -3008,7 +3144,9 @@ async function exchangeGemini(code, codeVerifier, exchangeFetch) {
3008
3144
  // src/admin/cliLaunch.ts
3009
3145
  import { exec, spawn } from "child_process";
3010
3146
  import { randomUUID as randomUUID2 } from "crypto";
3011
- import { existsSync as existsSync6 } from "fs";
3147
+ import { chmodSync as chmodSync3, existsSync as existsSync6, mkdtempSync, rmSync as rmSync2, writeFileSync as writeFileSync6 } from "fs";
3148
+ import { createServer } from "net";
3149
+ import { tmpdir } from "os";
3012
3150
  import { delimiter, join as join4 } from "path";
3013
3151
  import {
3014
3152
  buildChatCliLaunchConfig,
@@ -3016,6 +3154,33 @@ import {
3016
3154
  buildCodexLaunchConfig,
3017
3155
  buildGeminiCliLaunchConfig
3018
3156
  } from "@omnicross/cli-launcher";
3157
+ import {
3158
+ ROUTE_LEASE_REQUEST_SCHEMA,
3159
+ RouteLeaseError as RouteLeaseError2
3160
+ } from "@omnicross/core/provider-proxy";
3161
+
3162
+ // src/routeLeaseRenewal.ts
3163
+ var TERMINAL_LEASE_TTL_SECONDS = 600;
3164
+ var TERMINAL_LEASE_RENEW_INTERVAL_MS = 5 * 60 * 1e3;
3165
+ var TERMINAL_LEASE_MAX_LIFETIME_MS = 24 * 60 * 60 * 1e3;
3166
+ function startTerminalLeaseRenewal(manager, leaseId2) {
3167
+ const stopAt = Date.now() + TERMINAL_LEASE_MAX_LIFETIME_MS;
3168
+ const timer = setInterval(() => {
3169
+ if (Date.now() >= stopAt) {
3170
+ clearInterval(timer);
3171
+ return;
3172
+ }
3173
+ try {
3174
+ manager.renew(leaseId2, TERMINAL_LEASE_TTL_SECONDS);
3175
+ } catch {
3176
+ clearInterval(timer);
3177
+ }
3178
+ }, TERMINAL_LEASE_RENEW_INTERVAL_MS);
3179
+ timer.unref?.();
3180
+ return () => clearInterval(timer);
3181
+ }
3182
+
3183
+ // src/admin/cliLaunch.ts
3019
3184
  var LAUNCHABLE_CLIS = [
3020
3185
  { id: "claude", displayName: "Claude Code", command: "claude" },
3021
3186
  { id: "codex", displayName: "Codex CLI", command: "codex" },
@@ -3096,34 +3261,183 @@ async function buildLaunchEnv(cli, llmConfig, target) {
3096
3261
  function shq(s) {
3097
3262
  return `'${s.replace(/'/g, `'\\''`)}'`;
3098
3263
  }
3099
- var defaultTerminalOpener = ({ cli, command, extraArgs, env, cwd, platform }) => {
3264
+ var MAC_TERMINAL_BOOTSTRAP_SOURCE = `
3265
+ 'use strict';
3266
+ const fs = require('node:fs');
3267
+ const net = require('node:net');
3268
+ const { spawn } = require('node:child_process');
3269
+ const [socketPath, launchDir, cwd, command, ...args] = process.argv.slice(2);
3270
+ let payload = '';
3271
+ const socket = net.createConnection(socketPath);
3272
+ socket.setEncoding('utf8');
3273
+ socket.on('data', (chunk) => { payload += chunk; });
3274
+ socket.on('end', () => {
3275
+ const descriptor = JSON.parse(payload);
3276
+ if (!descriptor || Array.isArray(descriptor) || Object.values(descriptor).some((value) => typeof value !== 'string')) {
3277
+ throw new Error('invalid terminal launch descriptor');
3278
+ }
3279
+ try { fs.rmSync(launchDir, { recursive: true, force: true }); } catch {}
3280
+ const child = spawn(command, args, {
3281
+ cwd: cwd || undefined,
3282
+ env: { ...process.env, ...descriptor },
3283
+ stdio: 'inherit',
3284
+ });
3285
+ child.on('error', (error) => { console.error(error.message); process.exitCode = 1; });
3286
+ child.on('exit', (code, signal) => {
3287
+ if (signal) process.kill(process.pid, signal);
3288
+ else process.exitCode = code == null ? 1 : code;
3289
+ });
3290
+ });
3291
+ socket.on('error', (error) => { console.error(error.message); process.exitCode = 1; });
3292
+ `;
3293
+ var MAC_TERMINAL_IPC_TIMEOUT_MS = 12e4;
3294
+ function openTerminal({ cli, command, extraArgs, env, cwd, platform, onFailure }, spawnProcess = spawn, macIpc = {}) {
3100
3295
  const childEnv = { ...process.env, ...env };
3101
3296
  if (platform === "win32") {
3102
3297
  const args = ["/c", "start", `"omnicross ${cli}"`];
3103
3298
  if (cwd) args.push("/D", `"${cwd}"`);
3104
3299
  args.push("cmd", "/k", command, ...extraArgs);
3105
- spawn(process.env["ComSpec"] || "cmd.exe", args, {
3300
+ spawnProcess(process.env["ComSpec"] || "cmd.exe", args, {
3106
3301
  env: childEnv,
3107
3302
  windowsVerbatimArguments: true,
3108
3303
  detached: true,
3109
3304
  stdio: "ignore"
3110
3305
  }).unref();
3111
- return;
3306
+ return () => {
3307
+ };
3112
3308
  }
3113
- const exportLine = Object.entries(env).map(([k, v]) => `export ${k}=${shq(v)}`).join("; ");
3114
3309
  const runLine = [command, ...extraArgs].map(shq).join(" ");
3115
- const script = `${exportLine}; ${cwd ? `cd ${shq(cwd)}; ` : ""}${runLine}`;
3310
+ const script = `${cwd ? `cd ${shq(cwd)}; ` : ""}${runLine}`;
3116
3311
  if (platform === "darwin") {
3117
- const osa = `tell application "Terminal" to do script ${JSON.stringify(script)}`;
3118
- spawn("osascript", ["-e", osa], { detached: true, stdio: "ignore" }).unref();
3119
- return;
3312
+ const launchDir = mkdtempSync(join4(tmpdir(), "omnicross-terminal-"));
3313
+ const commandFile = join4(launchDir, "launch.command");
3314
+ const bootstrapFile = join4(launchDir, "bootstrap.cjs");
3315
+ const socketPath = macIpc.socketPath ?? join4(launchDir, "descriptor.sock");
3316
+ const openerEnv = { ...process.env };
3317
+ for (const key of Object.keys(env)) delete openerEnv[key];
3318
+ let claimed = false;
3319
+ let cleaned = false;
3320
+ let failureNotified = false;
3321
+ let timer;
3322
+ const notifyFailure = () => {
3323
+ cleanup();
3324
+ if (failureNotified) return;
3325
+ failureNotified = true;
3326
+ try {
3327
+ onFailure?.();
3328
+ } catch {
3329
+ }
3330
+ };
3331
+ const handleLaunchFailure = () => {
3332
+ if (claimed) cleanup();
3333
+ else notifyFailure();
3334
+ };
3335
+ const sockets = /* @__PURE__ */ new Set();
3336
+ const server = createServer((socket) => {
3337
+ socket.unref();
3338
+ sockets.add(socket);
3339
+ socket.once("close", () => sockets.delete(socket));
3340
+ try {
3341
+ macIpc.onAccepted?.(socket);
3342
+ } catch {
3343
+ cleanup();
3344
+ return;
3345
+ }
3346
+ if (claimed || cleaned) {
3347
+ socket.destroy();
3348
+ return;
3349
+ }
3350
+ claimed = true;
3351
+ try {
3352
+ macIpc.onClaimed?.();
3353
+ if (cleaned) return;
3354
+ socket.end(JSON.stringify(env), cleanup);
3355
+ } catch {
3356
+ cleanup();
3357
+ }
3358
+ });
3359
+ const cleanup = () => {
3360
+ if (!cleaned) {
3361
+ cleaned = true;
3362
+ if (timer) clearTimeout(timer);
3363
+ for (const socket of sockets) socket.destroy();
3364
+ sockets.clear();
3365
+ try {
3366
+ server.close();
3367
+ } catch {
3368
+ }
3369
+ }
3370
+ try {
3371
+ if (macIpc.removeArtifacts) {
3372
+ macIpc.removeArtifacts(launchDir);
3373
+ } else {
3374
+ rmSync2(launchDir, {
3375
+ recursive: true,
3376
+ force: true,
3377
+ maxRetries: 3,
3378
+ retryDelay: 20
3379
+ });
3380
+ }
3381
+ } catch {
3382
+ }
3383
+ };
3384
+ try {
3385
+ writeFileSync6(bootstrapFile, MAC_TERMINAL_BOOTSTRAP_SOURCE, { encoding: "utf8", mode: 448 });
3386
+ writeFileSync6(commandFile, `#!/bin/bash
3387
+ rm -f -- "$0"
3388
+ exec ${shq(process.execPath)} ${shq(bootstrapFile)} ${shq(socketPath)} ${shq(launchDir)} ${shq(cwd ?? "")} ${runLine}
3389
+ `, {
3390
+ encoding: "utf8",
3391
+ mode: 448
3392
+ });
3393
+ chmodSync3(commandFile, 448);
3394
+ chmodSync3(bootstrapFile, 448);
3395
+ server.once("error", handleLaunchFailure);
3396
+ server.listen(socketPath, () => {
3397
+ if (cleaned) return;
3398
+ try {
3399
+ macIpc.onListening?.();
3400
+ if (cleaned) return;
3401
+ if (process.platform !== "win32") chmodSync3(socketPath, 384);
3402
+ const opener = spawnProcess("open", ["-n", "-a", "Terminal", commandFile], {
3403
+ env: openerEnv,
3404
+ detached: true,
3405
+ stdio: "ignore"
3406
+ });
3407
+ opener.once("error", handleLaunchFailure);
3408
+ opener.unref();
3409
+ server.unref();
3410
+ } catch {
3411
+ handleLaunchFailure();
3412
+ }
3413
+ });
3414
+ timer = setTimeout(handleLaunchFailure, macIpc.timeoutMs ?? MAC_TERMINAL_IPC_TIMEOUT_MS);
3415
+ timer.unref?.();
3416
+ return cleanup;
3417
+ } catch (error) {
3418
+ cleanup();
3419
+ throw error;
3420
+ }
3120
3421
  }
3121
- spawn("x-terminal-emulator", ["-e", "bash", "-lc", `${script}; exec bash`], {
3422
+ spawnProcess("x-terminal-emulator", ["-e", "bash", "-lc", `${script}; exec bash`], {
3423
+ env: childEnv,
3122
3424
  detached: true,
3123
3425
  stdio: "ignore"
3124
3426
  }).unref();
3125
- };
3427
+ return () => {
3428
+ };
3429
+ }
3430
+ var defaultTerminalOpener = (input) => openTerminal(input);
3126
3431
  var sessions = /* @__PURE__ */ new Map();
3432
+ function resetCliSessions() {
3433
+ for (const s of sessions.values()) {
3434
+ try {
3435
+ s.onSessionEnd();
3436
+ } catch {
3437
+ }
3438
+ }
3439
+ sessions.clear();
3440
+ }
3127
3441
  function errBody(message) {
3128
3442
  return { error: { type: "admin_api_error", message } };
3129
3443
  }
@@ -3178,29 +3492,81 @@ async function handleCliLaunch(cli, body, ctx) {
3178
3492
  } catch (err5) {
3179
3493
  return { status: 400, body: errBody(err5 instanceof Error ? err5.message : "no launch target") };
3180
3494
  }
3495
+ const id = randomUUID2();
3496
+ let leaseId2;
3181
3497
  let launch;
3182
3498
  try {
3183
- launch = await buildLaunchEnv(cli, ctx.llmConfig, target);
3499
+ if ((cli === "claude" || cli === "codex") && ctx.routeLeaseManager) {
3500
+ const outcome = await ctx.routeLeaseManager.createFromRequest({
3501
+ schemaVersion: ROUTE_LEASE_REQUEST_SCHEMA,
3502
+ consumer: "omnicross-terminal",
3503
+ runtime: cli,
3504
+ upstream: { kind: "provider", providerId: target.providerId },
3505
+ model: target.model,
3506
+ execution: { sessionId: id }
3507
+ }, `omnicross-terminal:${id}`);
3508
+ leaseId2 = outcome.result.leaseId;
3509
+ const stopRenewal = startTerminalLeaseRenewal(ctx.routeLeaseManager, leaseId2);
3510
+ launch = {
3511
+ env: outcome.result.launch.env,
3512
+ extraArgs: outcome.result.launch.extraArgs,
3513
+ onSessionEnd: () => {
3514
+ stopRenewal();
3515
+ ctx.routeLeaseManager?.release(outcome.result.leaseId);
3516
+ }
3517
+ };
3518
+ } else {
3519
+ launch = await buildLaunchEnv(cli, ctx.llmConfig, target);
3520
+ }
3184
3521
  } catch (err5) {
3185
- return { status: 400, body: errBody(err5 instanceof Error ? err5.message : "failed to build launch env") };
3522
+ const status = err5 instanceof RouteLeaseError2 ? err5.status : 400;
3523
+ return { status, body: errBody(err5 instanceof Error ? err5.message : "failed to build launch env") };
3186
3524
  }
3187
3525
  const cwd = typeof body["cwd"] === "string" && body["cwd"].trim() ? body["cwd"].trim() : void 0;
3188
3526
  const opener = ctx.opener ?? defaultTerminalOpener;
3527
+ let openerCleanup;
3528
+ let ended = false;
3529
+ let published = false;
3530
+ const onSessionEnd = () => {
3531
+ if (ended) return;
3532
+ ended = true;
3533
+ if (published) sessions.delete(id);
3534
+ try {
3535
+ openerCleanup?.();
3536
+ } finally {
3537
+ launch.onSessionEnd();
3538
+ }
3539
+ };
3189
3540
  try {
3190
- opener({ cli, command: meta.command, extraArgs: launch.extraArgs ?? [], env: launch.env, cwd, platform });
3541
+ const cleanup = opener({
3542
+ cli,
3543
+ command: meta.command,
3544
+ extraArgs: launch.extraArgs ?? [],
3545
+ env: launch.env,
3546
+ cwd,
3547
+ platform,
3548
+ onFailure: onSessionEnd
3549
+ });
3550
+ if (cleanup) openerCleanup = cleanup;
3191
3551
  } catch (err5) {
3192
- launch.onSessionEnd();
3552
+ onSessionEnd();
3193
3553
  return { status: 500, body: errBody(err5 instanceof Error ? err5.message : "failed to open terminal") };
3194
3554
  }
3195
- const id = randomUUID2();
3555
+ if (ended) {
3556
+ openerCleanup?.();
3557
+ return { status: 500, body: errBody("failed to open terminal") };
3558
+ }
3196
3559
  sessions.set(id, {
3197
3560
  id,
3198
3561
  cli,
3199
3562
  providerId: target.providerId,
3200
3563
  model: target.model,
3564
+ ...leaseId2 ? { leaseId: leaseId2 } : {},
3201
3565
  startedAt: (/* @__PURE__ */ new Date()).toISOString(),
3202
- onSessionEnd: launch.onSessionEnd
3566
+ onSessionEnd
3203
3567
  });
3568
+ published = true;
3569
+ if (ended) sessions.delete(id);
3204
3570
  return { status: 200, body: { sessionId: id, providerId: target.providerId, model: target.model } };
3205
3571
  }
3206
3572
 
@@ -3220,8 +3586,8 @@ function validateAuditSegment(patch) {
3220
3586
  }
3221
3587
  }
3222
3588
  const maxBodyBytes = audit["maxBodyBytes"];
3223
- if (maxBodyBytes !== void 0 && (typeof maxBodyBytes !== "number" || !Number.isFinite(maxBodyBytes) || maxBodyBytes < 0)) {
3224
- errors.push("audit.maxBodyBytes must be a non-negative number");
3589
+ if (maxBodyBytes !== void 0 && (typeof maxBodyBytes !== "number" || !Number.isFinite(maxBodyBytes) || maxBodyBytes < -1)) {
3590
+ errors.push("audit.maxBodyBytes must be -1 or a non-negative number");
3225
3591
  }
3226
3592
  const retentionDays = audit["retentionDays"];
3227
3593
  if (retentionDays !== void 0 && (typeof retentionDays !== "number" || !Number.isFinite(retentionDays) || retentionDays < 0)) {
@@ -3666,18 +4032,16 @@ function preserveWebhookSecrets(incoming, current) {
3666
4032
  }
3667
4033
 
3668
4034
  // src/audit/auditRuntime.ts
3669
- import { join as join5 } from "path";
3670
4035
  import { setAuditCaptureConfig, setAuditSink } from "@omnicross/core/pipeline/auditSink";
3671
4036
  import { setUpstreamTracePath } from "@omnicross/core/pipeline/upstreamTrace";
3672
4037
  var writer = null;
3673
4038
  var sweeper = null;
3674
- var auditDir = "";
3675
- function setAuditRuntime(w, s, dir) {
4039
+ function setAuditRuntime(w, s) {
3676
4040
  writer = w;
3677
4041
  sweeper = s;
3678
- auditDir = dir;
3679
4042
  }
3680
4043
  function applyAuditConfig(config) {
4044
+ setUpstreamTracePath(null);
3681
4045
  const enabled = config?.enabled === true && writer !== null;
3682
4046
  if (enabled && config) {
3683
4047
  setAuditCaptureConfig(config);
@@ -3687,11 +4051,9 @@ function applyAuditConfig(config) {
3687
4051
  sweeper.configure(config);
3688
4052
  sweeper.start();
3689
4053
  }
3690
- setUpstreamTracePath(config.captureBodies ? join5(auditDir, "upstream-trace.jsonl") : null);
3691
4054
  } else {
3692
4055
  setAuditCaptureConfig(null);
3693
4056
  setAuditSink(null);
3694
- setUpstreamTracePath(null);
3695
4057
  if (sweeper) {
3696
4058
  if (config) sweeper.configure(config);
3697
4059
  sweeper.dispose();
@@ -4091,7 +4453,7 @@ function sealPack(bundleJson, passphrase) {
4091
4453
  cipher.setAAD(aadFor(PACK_MAGIC, PACK_VERSION, KDF_ALGORITHM));
4092
4454
  const ciphertext = Buffer.concat([cipher.update(bundleJson, "utf8"), cipher.final()]);
4093
4455
  const tag = cipher.getAuthTag();
4094
- const header = {
4456
+ const header2 = {
4095
4457
  magic: PACK_MAGIC,
4096
4458
  v: PACK_VERSION,
4097
4459
  kdf: KDF_ALGORITHM,
@@ -4102,7 +4464,7 @@ function sealPack(bundleJson, passphrase) {
4102
4464
  iv: iv.toString("base64"),
4103
4465
  tag: tag.toString("base64")
4104
4466
  };
4105
- return `${PACK_PREFIX}${toB64Url(JSON.stringify(header))}.${ciphertext.toString("base64")}`;
4467
+ return `${PACK_PREFIX}${toB64Url(JSON.stringify(header2))}.${ciphertext.toString("base64")}`;
4106
4468
  }
4107
4469
  function parsePack(packString) {
4108
4470
  if (typeof packString !== "string" || !packString.startsWith(PACK_PREFIX)) {
@@ -4113,28 +4475,28 @@ function parsePack(packString) {
4113
4475
  if (dot < 0) throw new PackAuthError("migration pack is malformed (missing body)");
4114
4476
  const headerB64Url = rest.slice(0, dot);
4115
4477
  const ctB64 = rest.slice(dot + 1);
4116
- let header;
4478
+ let header2;
4117
4479
  try {
4118
- header = JSON.parse(fromB64Url(headerB64Url));
4480
+ header2 = JSON.parse(fromB64Url(headerB64Url));
4119
4481
  } catch {
4120
4482
  throw new PackAuthError("migration pack is malformed (unreadable header)");
4121
4483
  }
4122
- if (!header || header.magic !== PACK_MAGIC || header.v !== PACK_VERSION || header.kdf !== KDF_ALGORITHM || typeof header.salt !== "string" || typeof header.iv !== "string" || typeof header.tag !== "string" || typeof header.N !== "number" || typeof header.r !== "number" || typeof header.p !== "number") {
4484
+ if (!header2 || header2.magic !== PACK_MAGIC || header2.v !== PACK_VERSION || header2.kdf !== KDF_ALGORITHM || typeof header2.salt !== "string" || typeof header2.iv !== "string" || typeof header2.tag !== "string" || typeof header2.N !== "number" || typeof header2.r !== "number" || typeof header2.p !== "number") {
4123
4485
  throw new PackAuthError("migration pack is malformed (unsupported header)");
4124
4486
  }
4125
4487
  const ciphertext = Buffer.from(ctB64, "base64");
4126
- return { header, ciphertext };
4488
+ return { header: header2, ciphertext };
4127
4489
  }
4128
4490
  function openPack(packString, passphrase) {
4129
4491
  assertPassphraseStrength(passphrase);
4130
- const { header, ciphertext } = parsePack(packString);
4131
- const salt = Buffer.from(header.salt, "base64");
4132
- const iv = Buffer.from(header.iv, "base64");
4133
- const tag = Buffer.from(header.tag, "base64");
4492
+ const { header: header2, ciphertext } = parsePack(packString);
4493
+ const salt = Buffer.from(header2.salt, "base64");
4494
+ const iv = Buffer.from(header2.iv, "base64");
4495
+ const tag = Buffer.from(header2.tag, "base64");
4134
4496
  if (iv.length !== IV_BYTES2 || tag.length !== TAG_BYTES2) {
4135
4497
  throw new PackAuthError("migration pack is malformed (invalid iv/tag length)");
4136
4498
  }
4137
- const key = deriveKey(passphrase, salt, header.N, header.r, header.p);
4499
+ const key = deriveKey(passphrase, salt, header2.N, header2.r, header2.p);
4138
4500
  const decipher = createDecipheriv2("aes-256-gcm", key, iv);
4139
4501
  decipher.setAAD(aadFor(PACK_MAGIC, PACK_VERSION, KDF_ALGORITHM));
4140
4502
  decipher.setAuthTag(tag);
@@ -4470,10 +4832,10 @@ function writeJson2(res, status, body) {
4470
4832
  res.writeHead(status, { "Content-Type": "application/json" });
4471
4833
  res.end(JSON.stringify(body));
4472
4834
  }
4473
- function writeError(res, status, message) {
4835
+ function writeError2(res, status, message) {
4474
4836
  writeJson2(res, status, { error: { type: "account_allowance_error", message } });
4475
4837
  }
4476
- function readJson(req) {
4838
+ function readJson2(req) {
4477
4839
  return new Promise((resolve3, reject) => {
4478
4840
  const chunks = [];
4479
4841
  req.on("data", (chunk) => chunks.push(Buffer.from(chunk)));
@@ -4499,10 +4861,10 @@ function allowanceProvider(value) {
4499
4861
  return value === "claude" || value === "codex" ? value : null;
4500
4862
  }
4501
4863
  async function handleAccountAllowanceApi(req, res, method, rest, service) {
4502
- if (!service) return writeError(res, 501, "account allowance service is not available");
4864
+ if (!service) return writeError2(res, 501, "account allowance service is not available");
4503
4865
  if (method === "GET" && rest.length === 1 && rest[0] === "scheduling") {
4504
4866
  if (!service.getSchedulingStatus) {
4505
- return writeError(res, 501, "allowance scheduling diagnostics are not available");
4867
+ return writeError2(res, 501, "allowance scheduling diagnostics are not available");
4506
4868
  }
4507
4869
  return writeJson2(res, 200, { scheduling: service.getSchedulingStatus() });
4508
4870
  }
@@ -4510,30 +4872,35 @@ async function handleAccountAllowanceApi(req, res, method, rest, service) {
4510
4872
  const params = query(req);
4511
4873
  const pathProvider = rest.length >= 2 ? rest[0] : null;
4512
4874
  const providerId = allowanceProvider(pathProvider ?? params.get("providerId") ?? params.get("provider"));
4513
- if (providerId === null) return writeError(res, 400, "providerId must be claude or codex");
4875
+ if (providerId === null) return writeError2(res, 400, "providerId must be claude or codex");
4514
4876
  const accountId = rest.length >= 2 ? rest[1] : params.get("accountId") ?? void 0;
4515
4877
  const allowances = await service.list({ providerId, accountId });
4516
4878
  return writeJson2(res, 200, { allowances });
4517
4879
  }
4518
4880
  if (method === "POST" && rest[0] === "refresh") {
4519
- const body = await readJson(req);
4881
+ const body = await readJson2(req);
4520
4882
  const requestedProvider = allowanceProvider(
4521
4883
  typeof body["providerId"] === "string" ? body["providerId"] : "claude"
4522
4884
  );
4523
4885
  if (requestedProvider !== "claude") {
4524
- return writeError(res, 400, "only Claude allowances support explicit refresh");
4886
+ return writeError2(res, 400, "only Claude allowances support explicit refresh");
4525
4887
  }
4526
4888
  const accountId = typeof body["accountId"] === "string" && body["accountId"].trim() ? body["accountId"].trim() : void 0;
4527
4889
  const allowances = await service.refreshClaude(accountId);
4528
4890
  if (accountId && allowances.length === 0) {
4529
- return writeError(res, 404, `Claude account '${accountId}' not found`);
4891
+ return writeError2(res, 404, `Claude account '${accountId}' not found`);
4530
4892
  }
4531
4893
  return writeJson2(res, 200, { allowances });
4532
4894
  }
4533
- return writeError(res, 405, `method ${method} not allowed on account allowances`);
4895
+ return writeError2(res, 405, `method ${method} not allowed on account allowances`);
4534
4896
  }
4535
4897
 
4536
4898
  // src/admin/adminApi.ts
4899
+ import {
4900
+ ACCOUNT_ROUTE_ACTIVITY_LIMIT,
4901
+ getSharedAccountRouteActivity
4902
+ } from "@omnicross/core/pipeline/AccountRouteActivity";
4903
+ import { getSharedOverloadCounter } from "@omnicross/core/pipeline/ServerOverloadCounter";
4537
4904
  function readBody(req) {
4538
4905
  return new Promise((resolve3, reject) => {
4539
4906
  const chunks = [];
@@ -4570,6 +4937,9 @@ function toKeyInfo(row) {
4570
4937
  id: row.id,
4571
4938
  name: row.name,
4572
4939
  keyPrefix: row.keyPrefix,
4940
+ // True only when a reversible `keySecret` envelope was persisted at creation
4941
+ // — gates the UI "view key" eye. Legacy hash-only rows read as absent.
4942
+ revealable: Boolean(row.keySecret),
4573
4943
  enabled: row.enabled,
4574
4944
  createdAt: row.createdAt,
4575
4945
  lastUsedAt: row.lastUsedAt,
@@ -5225,7 +5595,13 @@ function handlePresets(res, method) {
5225
5595
  name: p.name,
5226
5596
  apiFormat: p.apiFormat,
5227
5597
  baseUrl: p.baseUrl,
5228
- models: p.models
5598
+ models: p.models,
5599
+ nameKey: p.nameKey,
5600
+ icon: p.icon,
5601
+ description: p.description,
5602
+ features: p.features,
5603
+ website: p.website,
5604
+ modelsEndpoint: p.modelsEndpoint
5229
5605
  }));
5230
5606
  return writeJson3(res, 200, { presets, excluded });
5231
5607
  }
@@ -5259,12 +5635,27 @@ async function handleKeys(req, res, method, rest, deps) {
5259
5635
  plaintextOnce: created.plaintextOnce
5260
5636
  });
5261
5637
  }
5638
+ if (method === "GET" && rest.length === 2 && rest[1] === "reveal") {
5639
+ const revealed = await deps.keyDb.outboundApiKeysReveal(rest[0]);
5640
+ if (revealed !== null) return writeJson3(res, 200, { key: revealed });
5641
+ const exists = (await deps.keyDb.outboundApiKeysList()).some((r) => r.id === rest[0]);
5642
+ if (!exists) return writeJsonError(res, 404, `key '${rest[0]}' not found`);
5643
+ return writeJsonError(
5644
+ res,
5645
+ 409,
5646
+ `key '${rest[0]}' is not revealable (created before revealable key storage)`
5647
+ );
5648
+ }
5262
5649
  const id = rest[0];
5263
5650
  const action = rest[1];
5264
5651
  if (method === "POST" && id && action === "revoke") {
5265
5652
  const ok = await deps.keyDb.outboundApiKeysRevoke(id);
5266
5653
  return writeJson3(res, ok ? 200 : 404, { ok });
5267
5654
  }
5655
+ if (method === "DELETE" && id && !action) {
5656
+ const ok = await deps.keyDb.outboundApiKeysDelete(id);
5657
+ return writeJson3(res, ok ? 200 : 404, { ok });
5658
+ }
5268
5659
  if (method === "POST" && id && action === "enabled") {
5269
5660
  const body = await readJsonBody3(req);
5270
5661
  const enabled = body["enabled"] === true;
@@ -5441,6 +5832,40 @@ async function handleServer(req, res, method, deps) {
5441
5832
  return writeJsonError(res, 405, `method ${method} not allowed on server`);
5442
5833
  }
5443
5834
  async function handleAccounts(req, res, method, rest, deps) {
5835
+ if (rest[0] === "route-activity" && rest.length === 1) {
5836
+ if (method !== "GET") {
5837
+ return writeJsonError(res, 405, `method ${method} not allowed on account route activity`);
5838
+ }
5839
+ const query2 = requestQuery(req);
5840
+ const parsedLimit = Number(query2.get("limit") ?? "100");
5841
+ const records = getSharedAccountRouteActivity().list({
5842
+ providerId: query2.get("providerId") ?? void 0,
5843
+ accountId: query2.get("accountId") ?? void 0,
5844
+ sessionKey: query2.get("sessionKey") ?? void 0,
5845
+ limit: Number.isFinite(parsedLimit) ? parsedLimit : 100
5846
+ });
5847
+ return writeJson3(res, 200, {
5848
+ available: true,
5849
+ records,
5850
+ capacity: ACCOUNT_ROUTE_ACTIVITY_LIMIT,
5851
+ collectedAt: Date.now()
5852
+ });
5853
+ }
5854
+ if (rest[0] === "overload-counters" && rest.length === 1) {
5855
+ if (method !== "GET") {
5856
+ return writeJsonError(res, 405, `method ${method} not allowed on overload counters`);
5857
+ }
5858
+ const query2 = requestQuery(req);
5859
+ const entries = getSharedOverloadCounter().list({
5860
+ providerId: query2.get("providerId") ?? void 0,
5861
+ accountId: query2.get("accountId") ?? void 0
5862
+ });
5863
+ return writeJson3(res, 200, {
5864
+ available: true,
5865
+ entries,
5866
+ collectedAt: Date.now()
5867
+ });
5868
+ }
5444
5869
  if (rest[0] === "allowances") {
5445
5870
  return handleAccountAllowanceApi(
5446
5871
  req,
@@ -5587,8 +6012,13 @@ async function handleAccounts(req, res, method, rest, deps) {
5587
6012
  if (!(listed[providerId] ?? []).some((account) => account.id === accountId)) {
5588
6013
  return writeJsonError(res, 404, `account '${accountId}' not found`);
5589
6014
  }
5590
- const result = await deps.accountProbeService.probeAccount(providerId, accountId);
5591
- return writeJson3(res, 200, { ok: result.ok, marked: result.marked });
6015
+ const result = await deps.accountProbeService.testAccountConnection(providerId, accountId);
6016
+ return writeJson3(res, 200, {
6017
+ ok: result.ok,
6018
+ marked: result.marked,
6019
+ tier: result.tier,
6020
+ model: result.model
6021
+ });
5592
6022
  }
5593
6023
  if (method === "POST" && rest[2] === "label") {
5594
6024
  const accountId = rest[1];
@@ -5697,6 +6127,7 @@ async function handleCli(req, res, method, rest, deps) {
5697
6127
  const result = await handleCliLaunch(cli, body, {
5698
6128
  llmConfig: deps.llmConfig,
5699
6129
  providers,
6130
+ routeLeaseManager: deps.routeLeaseManager,
5700
6131
  opener: deps.cliTerminalOpener,
5701
6132
  probe: deps.cliPathProbe
5702
6133
  });
@@ -5959,7 +6390,7 @@ async function handleUiStatic(req, res, urlPath, uiDist) {
5959
6390
  }
5960
6391
 
5961
6392
  // src/admin/version.ts
5962
- var DAEMON_VERSION = true ? "0.1.6" : "0.0.0-dev";
6393
+ var DAEMON_VERSION = true ? "0.1.8" : "0.0.0-dev";
5963
6394
 
5964
6395
  // src/admin/AdminServer.ts
5965
6396
  var LOOPBACK_ADDR = "127.0.0.1";
@@ -6067,6 +6498,10 @@ var AdminServer = class {
6067
6498
  handleAuditQuery(req, res, this.deps.auditReader);
6068
6499
  return;
6069
6500
  }
6501
+ if (path2 === "/admin/api/audit/stats" && (req.method === "GET" || req.method === "HEAD")) {
6502
+ await handleAuditStatsQuery(req, res, this.deps.auditStatsReader);
6503
+ return;
6504
+ }
6070
6505
  if (path2 === "/admin/api/billing-status" && (req.method === "GET" || req.method === "HEAD")) {
6071
6506
  handleBillingStatus(res, this.deps.billingStatusReader);
6072
6507
  return;
@@ -6075,6 +6510,10 @@ var AdminServer = class {
6075
6510
  await handleWebhookTest(req, res);
6076
6511
  return;
6077
6512
  }
6513
+ if (path2 === "/admin/api/route-leases" || path2.startsWith("/admin/api/route-leases/")) {
6514
+ await handleRouteLeaseApi(req, res, path2, this.deps);
6515
+ return;
6516
+ }
6078
6517
  if (path2.startsWith("/admin/api/")) {
6079
6518
  await handleAdminApi(req, res, path2, this.deps);
6080
6519
  return;
@@ -6086,8 +6525,8 @@ var AdminServer = class {
6086
6525
  }
6087
6526
  /** Constant-time bearer/header check against the configured token. */
6088
6527
  isAuthorized(req, token) {
6089
- const header = req.headers["authorization"];
6090
- const bearer = typeof header === "string" && header.startsWith("Bearer ") ? header.slice("Bearer ".length).trim() : void 0;
6528
+ const header2 = req.headers["authorization"];
6529
+ const bearer = typeof header2 === "string" && header2.startsWith("Bearer ") ? header2.slice("Bearer ".length).trim() : void 0;
6091
6530
  const xToken = req.headers["x-admin-token"];
6092
6531
  const presented = bearer ?? (typeof xToken === "string" ? xToken.trim() : void 0);
6093
6532
  return constantTimeEquals(presented, token);
@@ -6183,20 +6622,36 @@ var OAuthSessionStore = class {
6183
6622
  return sessionId;
6184
6623
  }
6185
6624
  /**
6186
- * SINGLE-USE consume: return + delete the session for `sessionId`, or `null`
6187
- * when it is unknown, already used, or past its TTL (in which case it is
6188
- * dropped). A `null` return means the completer must reject (no exchange, no
6189
- * write).
6625
+ * NON-DESTRUCTIVE lookup: return the session for `sessionId`, or `null` when
6626
+ * it is unknown, already consumed, or past its TTL (an expired entry is
6627
+ * dropped here). A `null` return means the completer must reject (no
6628
+ * exchange, no write).
6629
+ *
6630
+ * Deliberately NOT a consume: the completer peeks, runs the token exchange,
6631
+ * and only {@link consume}s once a token has actually been minted. Consuming
6632
+ * up-front burned the session on EVERY failed exchange (a mistyped/expired
6633
+ * pasted code, a proxy hiccup), so the user's natural retry hit
6634
+ * "session is unknown, expired, or already used" and the login became
6635
+ * unrecoverable without restarting the whole flow.
6190
6636
  */
6191
- take(sessionId) {
6637
+ peek(sessionId) {
6192
6638
  this.sweep();
6193
6639
  const session = this.sessions.get(sessionId);
6194
6640
  if (!session) return null;
6195
- this.sessions.delete(sessionId);
6196
- if (Date.now() - session.createdAt > this.ttlMs) return null;
6641
+ if (Date.now() - session.createdAt > this.ttlMs) {
6642
+ this.sessions.delete(sessionId);
6643
+ return null;
6644
+ }
6197
6645
  return session;
6198
6646
  }
6199
- /** Drop every session past its TTL. Called on each put/take. */
6647
+ /**
6648
+ * SINGLE-USE burn: drop the session so the same `sessionId` can never be
6649
+ * completed twice. Called ONLY after a successful token exchange.
6650
+ */
6651
+ consume(sessionId) {
6652
+ this.sessions.delete(sessionId);
6653
+ }
6654
+ /** Drop every session past its TTL. Called on each put/peek. */
6200
6655
  sweep() {
6201
6656
  const now = Date.now();
6202
6657
  for (const [id, session] of this.sessions) {
@@ -6206,11 +6661,15 @@ var OAuthSessionStore = class {
6206
6661
  };
6207
6662
 
6208
6663
  // src/commands/loopbackCallback.ts
6209
- import { createServer } from "http";
6664
+ import { createServer as createServer2 } from "http";
6210
6665
  var LOOPBACK_HOST = "127.0.0.1";
6211
6666
  var LOOPBACK_PORT = 1455;
6212
6667
  var CALLBACK_PATH = "/auth/callback";
6213
6668
  var DEFAULT_TIMEOUT_MS = 5 * 6e4;
6669
+ var HTML_HEADERS = {
6670
+ "Content-Type": "text/html",
6671
+ Connection: "close"
6672
+ };
6214
6673
  function pageHtml(message) {
6215
6674
  return `<!doctype html><meta charset="utf-8"><title>omnicross login</title><body style="font-family:sans-serif;padding:2rem"><h2>${message}</h2><p>You can close this window and return to the terminal.</p></body>`;
6216
6675
  }
@@ -6221,30 +6680,31 @@ function awaitLoopbackCode(expectedState, timeoutMs = DEFAULT_TIMEOUT_MS, signal
6221
6680
  if (settled) return;
6222
6681
  settled = true;
6223
6682
  clearTimeout(timer);
6224
- server2.close(() => fn());
6683
+ fn();
6684
+ server2.close();
6225
6685
  };
6226
- const server = createServer((req, res) => {
6686
+ const server = createServer2((req, res) => {
6227
6687
  const url = new URL(req.url ?? "", `http://${LOOPBACK_HOST}:${LOOPBACK_PORT}`);
6228
6688
  if (url.pathname !== CALLBACK_PATH) {
6229
- res.writeHead(404, { "Content-Type": "text/html" });
6689
+ res.writeHead(404, HTML_HEADERS);
6230
6690
  res.end(pageHtml("Not found"));
6231
6691
  return;
6232
6692
  }
6233
6693
  const code = url.searchParams.get("code");
6234
6694
  const state = url.searchParams.get("state");
6235
6695
  if (!code) {
6236
- res.writeHead(400, { "Content-Type": "text/html" });
6696
+ res.writeHead(400, HTML_HEADERS);
6237
6697
  res.end(pageHtml("Login failed: missing authorization code."));
6238
6698
  finish(server, () => reject(new Error("login: callback did not include an authorization code")));
6239
6699
  return;
6240
6700
  }
6241
6701
  if (state !== expectedState) {
6242
- res.writeHead(400, { "Content-Type": "text/html" });
6702
+ res.writeHead(400, HTML_HEADERS);
6243
6703
  res.end(pageHtml("Login failed: state mismatch."));
6244
6704
  finish(server, () => reject(new Error("login: callback state did not match (possible CSRF) \u2014 aborting")));
6245
6705
  return;
6246
6706
  }
6247
- res.writeHead(200, { "Content-Type": "text/html" });
6707
+ res.writeHead(200, HTML_HEADERS);
6248
6708
  res.end(pageHtml("Login complete."));
6249
6709
  finish(server, () => resolve3(code));
6250
6710
  });
@@ -6645,7 +7105,7 @@ function safeStringify(value) {
6645
7105
  }
6646
7106
 
6647
7107
  // src/ports/JsonApiServerSettingsStore.ts
6648
- import { readFileSync as readFileSync8, writeFileSync as writeFileSync6 } from "fs";
7108
+ import { readFileSync as readFileSync8, writeFileSync as writeFileSync7 } from "fs";
6649
7109
  import { OUTBOUND_API_SERVER_CONFIG_KEY } from "@omnicross/core/outbound-api";
6650
7110
  var JsonApiServerSettingsStore = class {
6651
7111
  /**
@@ -6672,7 +7132,7 @@ var JsonApiServerSettingsStore = class {
6672
7132
  if (key !== OUTBOUND_API_SERVER_CONFIG_KEY) return;
6673
7133
  const file = this.readFile();
6674
7134
  file.server = this.encryptSecrets(value);
6675
- writeFileSync6(this.configPath, JSON.stringify(file, null, 2) + "\n", "utf8");
7135
+ writeFileSync7(this.configPath, JSON.stringify(file, null, 2) + "\n", "utf8");
6676
7136
  }
6677
7137
  /** Encrypt the proxy passwords + webhook + billing secrets before persisting (no-op without a box). */
6678
7138
  encryptSecrets(config) {
@@ -6733,8 +7193,12 @@ var JsonlUsageEventStore = class {
6733
7193
  reasoningTokens: 0,
6734
7194
  costUsd: 0,
6735
7195
  costSavedByCacheUsd: 0,
6736
- eventCount: 0
7196
+ eventCount: 0,
7197
+ cacheEligibleEventCount: 0,
7198
+ coldCacheEventCount: 0,
7199
+ medianCacheHitRate: null
6737
7200
  };
7201
+ const perEventHitRates = [];
6738
7202
  for (const row of this.readRows(range)) {
6739
7203
  totals.inputTokens += row.inputTokens;
6740
7204
  totals.outputTokens += row.outputTokens;
@@ -6744,7 +7208,14 @@ var JsonlUsageEventStore = class {
6744
7208
  totals.costUsd += row.costUsd;
6745
7209
  totals.costSavedByCacheUsd += row.costSavedByCacheUsd;
6746
7210
  totals.eventCount += 1;
7211
+ const promptSideTokens = row.inputTokens + row.cacheReadTokens + row.cacheCreationTokens;
7212
+ if (promptSideTokens > 0) {
7213
+ totals.cacheEligibleEventCount += 1;
7214
+ if (row.cacheReadTokens === 0) totals.coldCacheEventCount += 1;
7215
+ perEventHitRates.push(row.cacheReadTokens / promptSideTokens);
7216
+ }
6747
7217
  }
7218
+ totals.medianCacheHitRate = median(perEventHitRates);
6748
7219
  return totals;
6749
7220
  }
6750
7221
  async getByModel(range) {
@@ -6978,6 +7449,15 @@ var NUMERIC_FIELDS = [
6978
7449
  ];
6979
7450
  var NULLABLE_STRING_FIELDS = ["messageId", "parentMessageId", "sessionId", "apiKeyId"];
6980
7451
  var isStringOrNull = (v) => v === null || typeof v === "string";
7452
+ var CACHE_KEY_SOURCES = /* @__PURE__ */ new Set([
7453
+ "client",
7454
+ "session-header",
7455
+ "thread-header",
7456
+ "body-session-id",
7457
+ "body-thread-id",
7458
+ "content-fingerprint",
7459
+ "none"
7460
+ ]);
6981
7461
  function isUsageEventRecord(parsed) {
6982
7462
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return false;
6983
7463
  const r = parsed;
@@ -6985,6 +7465,10 @@ function isUsageEventRecord(parsed) {
6985
7465
  if (typeof r["providerId"] !== "string") return false;
6986
7466
  if (typeof r["model"] !== "string") return false;
6987
7467
  if (typeof r["engineOrigin"] !== "string") return false;
7468
+ if (r["cacheKeySource"] !== void 0 && (typeof r["cacheKeySource"] !== "string" || !CACHE_KEY_SOURCES.has(r["cacheKeySource"]))) return false;
7469
+ if (r["cacheKeyInjected"] !== void 0 && typeof r["cacheKeyInjected"] !== "boolean") {
7470
+ return false;
7471
+ }
6988
7472
  for (const f of NULLABLE_STRING_FIELDS) {
6989
7473
  if (!isStringOrNull(r[f])) return false;
6990
7474
  }
@@ -6994,9 +7478,15 @@ function isUsageEventRecord(parsed) {
6994
7478
  }
6995
7479
  return true;
6996
7480
  }
7481
+ function median(values) {
7482
+ if (values.length === 0) return null;
7483
+ values.sort((a, b) => a - b);
7484
+ const middle = Math.floor(values.length / 2);
7485
+ return values.length % 2 === 1 ? values[middle] : (values[middle - 1] + values[middle]) / 2;
7486
+ }
6997
7487
 
6998
7488
  // src/ports/JsonPricingStore.ts
6999
- import { existsSync as existsSync9, readFileSync as readFileSync10, renameSync as renameSync3, rmSync as rmSync2, writeFileSync as writeFileSync7 } from "fs";
7489
+ import { existsSync as existsSync9, readFileSync as readFileSync10, renameSync as renameSync3, rmSync as rmSync3, writeFileSync as writeFileSync8 } from "fs";
7000
7490
  import { randomUUID as randomUUID5 } from "crypto";
7001
7491
  var JsonPricingStore = class {
7002
7492
  constructor(pricingPath) {
@@ -7137,13 +7627,13 @@ var JsonPricingStore = class {
7137
7627
  writeRows(rows) {
7138
7628
  const temporaryPath = `${this.pricingPath}.${process.pid}.${randomUUID5()}.tmp`;
7139
7629
  try {
7140
- writeFileSync7(temporaryPath, JSON.stringify(rows, null, 2) + "\n", {
7630
+ writeFileSync8(temporaryPath, JSON.stringify(rows, null, 2) + "\n", {
7141
7631
  encoding: "utf8",
7142
7632
  flag: "wx"
7143
7633
  });
7144
7634
  this.replaceFile(temporaryPath);
7145
7635
  } finally {
7146
- rmSync2(temporaryPath, { force: true });
7636
+ rmSync3(temporaryPath, { force: true });
7147
7637
  }
7148
7638
  }
7149
7639
  /** Isolated for deterministic failure testing; never removes the target. */
@@ -7158,7 +7648,7 @@ function isUsablePricingRow(value) {
7158
7648
  }
7159
7649
 
7160
7650
  // src/pricing/PricingRefreshScheduler.ts
7161
- import { existsSync as existsSync10, readFileSync as readFileSync11, renameSync as renameSync4, writeFileSync as writeFileSync8 } from "fs";
7651
+ import { existsSync as existsSync10, readFileSync as readFileSync11, renameSync as renameSync4, writeFileSync as writeFileSync9 } from "fs";
7162
7652
  var EMPTY_STATE2 = {
7163
7653
  lastAttemptAt: null,
7164
7654
  lastSuccessAt: null,
@@ -7251,7 +7741,7 @@ var PricingRefreshScheduler = class {
7251
7741
  }
7252
7742
  writeState(state) {
7253
7743
  const temporaryPath = `${this.statePath}.tmp`;
7254
- writeFileSync8(temporaryPath, `${JSON.stringify(state, null, 2)}
7744
+ writeFileSync9(temporaryPath, `${JSON.stringify(state, null, 2)}
7255
7745
  `, "utf8");
7256
7746
  renameSync4(temporaryPath, this.statePath);
7257
7747
  }
@@ -7261,7 +7751,7 @@ function finiteOrNull(value) {
7261
7751
  }
7262
7752
 
7263
7753
  // src/ports/JsonVoucherDb.ts
7264
- import { existsSync as existsSync11, readFileSync as readFileSync12, writeFileSync as writeFileSync9 } from "fs";
7754
+ import { existsSync as existsSync11, readFileSync as readFileSync12, writeFileSync as writeFileSync10 } from "fs";
7265
7755
  var JsonVoucherDb = class {
7266
7756
  constructor(vouchersPath) {
7267
7757
  this.vouchersPath = vouchersPath;
@@ -7348,12 +7838,12 @@ var JsonVoucherDb = class {
7348
7838
  }
7349
7839
  }
7350
7840
  writeRows(rows) {
7351
- writeFileSync9(this.vouchersPath, JSON.stringify(rows, null, 2) + "\n", "utf8");
7841
+ writeFileSync10(this.vouchersPath, JSON.stringify(rows, null, 2) + "\n", "utf8");
7352
7842
  }
7353
7843
  };
7354
7844
 
7355
7845
  // src/ports/JsonSubscriptionCredentialStore.ts
7356
- import { existsSync as existsSync13, mkdirSync as mkdirSync4, readFileSync as readFileSync14, writeFileSync as writeFileSync10 } from "fs";
7846
+ import { existsSync as existsSync13, mkdirSync as mkdirSync4, readFileSync as readFileSync14, writeFileSync as writeFileSync11 } from "fs";
7357
7847
  import { dirname as dirname6 } from "path";
7358
7848
  import { getSharedAccountHealth as getSharedAccountHealth2 } from "@omnicross/core/pipeline/SubscriptionAccountHealth";
7359
7849
  import { getSharedAccountAllowanceScheduling as getSharedAccountAllowanceScheduling3 } from "@omnicross/core/pipeline/AccountAllowanceScheduling";
@@ -7409,9 +7899,9 @@ function findDuplicateCredentialIds(accounts) {
7409
7899
  // src/ports/external-cli-credentials.ts
7410
7900
  import { existsSync as existsSync12, readFileSync as readFileSync13 } from "fs";
7411
7901
  import { homedir as homedir3 } from "os";
7412
- import { join as join6 } from "path";
7902
+ import { join as join5 } from "path";
7413
7903
  function externalStorePath(provider, home = homedir3()) {
7414
- return provider === "claude" ? join6(home, ".claude", ".credentials.json") : join6(home, ".codex", "auth.json");
7904
+ return provider === "claude" ? join5(home, ".claude", ".credentials.json") : join5(home, ".codex", "auth.json");
7415
7905
  }
7416
7906
  function decodeJwtExpiryMs(token) {
7417
7907
  try {
@@ -7501,9 +7991,15 @@ var JsonSubscriptionCredentialStore = class {
7501
7991
  * TEST-injected `fetchImpl` is returned verbatim; otherwise the refresh routes
7502
7992
  * through {@link fetchUpstream} with the account's `{ providerId, accountId }`
7503
7993
  * ctx so the per-account/provider proxy applies. `@internal` also a test seam.
7994
+ *
7995
+ * `redactBodies` is REQUIRED here: this round-trip sends the refresh_token and
7996
+ * receives a fresh access/refresh token pair. Carrying a `providerId` opts the
7997
+ * call into the upstream trace (so a failing refresh is diagnosable), and the
7998
+ * trace captures bodies verbatim — without this flag every refresh would write
7999
+ * a plaintext token pair into `upstream-trace.jsonl`.
7504
8000
  */
7505
8001
  buildRefreshFetch(providerId, accountId) {
7506
- return this.fetchImpl ?? ((url, init) => fetchUpstream3(url, init, { providerId, accountId }));
8002
+ return this.fetchImpl ?? ((url, init) => fetchUpstream3(url, init, { providerId, accountId, redactBodies: true }));
7507
8003
  }
7508
8004
  /**
7509
8005
  * In-flight refresh coalescing. OAuth refresh tokens are
@@ -8030,7 +8526,7 @@ var JsonSubscriptionCredentialStore = class {
8030
8526
  persist(config) {
8031
8527
  mkdirSync4(dirname6(this.tokensPath), { recursive: true });
8032
8528
  const encrypted = encryptTokens(config, this.box);
8033
- writeFileSync10(this.tokensPath, JSON.stringify(encrypted, null, 2) + "\n", "utf8");
8529
+ writeFileSync11(this.tokensPath, JSON.stringify(encrypted, null, 2) + "\n", "utf8");
8034
8530
  }
8035
8531
  /**
8036
8532
  * Read + parse `tokens.json`, tolerating a missing/corrupt file, then DECRYPT
@@ -8063,6 +8559,127 @@ var JsonSubscriptionCredentialStore = class {
8063
8559
  // src/AccountHealthProbeScheduler.ts
8064
8560
  import { fetchUpstream as fetchUpstream4 } from "@omnicross/core/pipeline/upstreamFetch";
8065
8561
 
8562
+ // src/probe/CodexGenerationProbe.ts
8563
+ import {
8564
+ DEFAULT_CODEX_CLI_HEADERS,
8565
+ codexAcceptHeader
8566
+ } from "@omnicross/core/provider-proxy/identity/codexCliHeaders";
8567
+ var CODEX_GENERATION_PROBE_MODEL = "gpt-5.6-luna";
8568
+ var CODEX_GENERATION_PROBE_URL = "https://chatgpt.com/backend-api/codex/responses";
8569
+ var MAX_STREAM_BYTES = 256 * 1024;
8570
+ var PROBE_INSTRUCTION = "Return exactly PONG and no other text.";
8571
+ function buildCodexGenerationProbeInit(token, signal) {
8572
+ return {
8573
+ method: "POST",
8574
+ signal,
8575
+ headers: {
8576
+ ...DEFAULT_CODEX_CLI_HEADERS,
8577
+ Authorization: `Bearer ${token}`,
8578
+ Accept: codexAcceptHeader(true),
8579
+ "Content-Type": "application/json"
8580
+ },
8581
+ body: JSON.stringify({
8582
+ model: CODEX_GENERATION_PROBE_MODEL,
8583
+ input: [
8584
+ {
8585
+ role: "developer",
8586
+ content: [{ type: "input_text", text: PROBE_INSTRUCTION }]
8587
+ },
8588
+ {
8589
+ role: "user",
8590
+ content: [{ type: "input_text", text: "Connection probe." }]
8591
+ }
8592
+ ],
8593
+ // GPT-5.6 otherwise defaults to medium reasoning. A connectivity probe
8594
+ // needs the lowest-cost path and no tool reasoning.
8595
+ reasoning: { effort: "none" },
8596
+ stream: true,
8597
+ store: false
8598
+ })
8599
+ };
8600
+ }
8601
+ async function readCodexGenerationProbeStream(response) {
8602
+ if (!response.body) return { completed: false, outputChars: 0 };
8603
+ const reader = response.body.getReader();
8604
+ const decoder = new TextDecoder();
8605
+ let buffer = "";
8606
+ let bytes = 0;
8607
+ let outputChars = 0;
8608
+ try {
8609
+ while (true) {
8610
+ const { done, value } = await reader.read();
8611
+ if (done) break;
8612
+ bytes += value.byteLength;
8613
+ if (bytes > MAX_STREAM_BYTES) {
8614
+ await reader.cancel();
8615
+ return { completed: false, outputChars };
8616
+ }
8617
+ buffer += decoder.decode(value, { stream: true });
8618
+ buffer = buffer.replace(/\r\n/g, "\n");
8619
+ let boundary = buffer.indexOf("\n\n");
8620
+ while (boundary >= 0) {
8621
+ const block = buffer.slice(0, boundary);
8622
+ buffer = buffer.slice(boundary + 2);
8623
+ const event = parseSseBlock(block);
8624
+ if (event) {
8625
+ const type = event["type"];
8626
+ if (type === "response.output_text.delta" && typeof event["delta"] === "string") {
8627
+ outputChars += event["delta"].length;
8628
+ } else if (type === "response.output_text.done" && typeof event["text"] === "string") {
8629
+ outputChars = Math.max(outputChars, event["text"].length);
8630
+ } else if (type === "response.failed" || type === "error") {
8631
+ await reader.cancel();
8632
+ return { completed: false, outputChars };
8633
+ } else if (type === "response.completed") {
8634
+ const completedResponse = asRecord(event["response"]);
8635
+ const status = completedResponse?.["status"];
8636
+ outputChars = Math.max(outputChars, countCompletedOutputChars(completedResponse));
8637
+ await reader.cancel();
8638
+ return {
8639
+ completed: (status === void 0 || status === "completed") && outputChars > 0,
8640
+ outputChars
8641
+ };
8642
+ }
8643
+ }
8644
+ boundary = buffer.indexOf("\n\n");
8645
+ }
8646
+ }
8647
+ } catch {
8648
+ return { completed: false, outputChars };
8649
+ } finally {
8650
+ reader.releaseLock();
8651
+ }
8652
+ return { completed: false, outputChars };
8653
+ }
8654
+ function parseSseBlock(block) {
8655
+ const data = block.split("\n").filter((line) => line.startsWith("data:")).map((line) => line.slice(5).trimStart()).join("\n");
8656
+ if (!data || data === "[DONE]") return null;
8657
+ try {
8658
+ return JSON.parse(data);
8659
+ } catch {
8660
+ return null;
8661
+ }
8662
+ }
8663
+ function asRecord(value) {
8664
+ return value !== null && typeof value === "object" ? value : void 0;
8665
+ }
8666
+ function countCompletedOutputChars(response) {
8667
+ const output = response?.["output"];
8668
+ if (!Array.isArray(output)) return 0;
8669
+ let chars = 0;
8670
+ for (const item of output) {
8671
+ const content = asRecord(item)?.["content"];
8672
+ if (!Array.isArray(content)) continue;
8673
+ for (const part of content) {
8674
+ const record = asRecord(part);
8675
+ if (record?.["type"] === "output_text" && typeof record["text"] === "string") {
8676
+ chars += record["text"].length;
8677
+ }
8678
+ }
8679
+ }
8680
+ return chars;
8681
+ }
8682
+
8066
8683
  // src/probe/ProbeStrategy.ts
8067
8684
  var PROVIDER_PROBE_PLANS = {
8068
8685
  claude: {
@@ -8190,17 +8807,17 @@ var AccountHealthProbeScheduler = class {
8190
8807
  }
8191
8808
  if (readThrew) {
8192
8809
  this.record(providerId, accountId, { ts: now, ok: false, status: null, tier: "local" });
8193
- return { ok: false, marked: false };
8810
+ return { ok: false, marked: false, tier: "local" };
8194
8811
  }
8195
8812
  if (!token) {
8196
8813
  this.health.recordUpstreamOutcome(providerId, accountId, { status: 401, now });
8197
8814
  this.record(providerId, accountId, { ts: now, ok: false, status: 401, tier: "local" });
8198
- return { ok: false, marked: true };
8815
+ return { ok: false, marked: true, tier: "local" };
8199
8816
  }
8200
8817
  const plan = this.planFor(providerId);
8201
8818
  if (plan.kind === "local") {
8202
8819
  this.record(providerId, accountId, { ts: now, ok: true, tier: "local" });
8203
- return { ok: true, marked: false };
8820
+ return { ok: true, marked: false, tier: "local" };
8204
8821
  }
8205
8822
  const start = this.now();
8206
8823
  let status = null;
@@ -8225,7 +8842,60 @@ var AccountHealthProbeScheduler = class {
8225
8842
  latencyMs,
8226
8843
  tier: "upstream"
8227
8844
  });
8228
- return { ok: status !== null && status < 400, marked };
8845
+ return { ok: status !== null && status < 400, marked, tier: "upstream" };
8846
+ }
8847
+ /**
8848
+ * Manual connection test. Codex performs a real, quota-consuming generation;
8849
+ * every other provider keeps its existing cheap probe. Scheduled sweeps never
8850
+ * call this method, so they remain non-billable.
8851
+ */
8852
+ async testAccountConnection(providerId, accountId) {
8853
+ if (providerId !== "codex") return this.probeAccount(providerId, accountId);
8854
+ const now = this.now();
8855
+ let token;
8856
+ try {
8857
+ token = await this.store.getAccessTokenForAccount(providerId, accountId);
8858
+ } catch {
8859
+ this.record(providerId, accountId, { ts: now, ok: false, status: null, tier: "local" });
8860
+ return { ok: false, marked: false, tier: "local", model: CODEX_GENERATION_PROBE_MODEL };
8861
+ }
8862
+ if (!token) {
8863
+ this.health.recordUpstreamOutcome(providerId, accountId, { status: 401, now });
8864
+ this.record(providerId, accountId, { ts: now, ok: false, status: 401, tier: "local" });
8865
+ return { ok: false, marked: true, tier: "local", model: CODEX_GENERATION_PROBE_MODEL };
8866
+ }
8867
+ const startedAt = this.now();
8868
+ let attempt = await this.runCodexGenerationAttempt(accountId, token);
8869
+ if (attempt.status === 401 && this.store.refreshAccountToken) {
8870
+ try {
8871
+ if (await this.store.refreshAccountToken(providerId, accountId)) {
8872
+ const refreshed = await this.store.getAccessTokenForAccount(providerId, accountId);
8873
+ if (refreshed) attempt = await this.runCodexGenerationAttempt(accountId, refreshed);
8874
+ }
8875
+ } catch {
8876
+ }
8877
+ }
8878
+ const latencyMs = this.now() - startedAt;
8879
+ const ok = attempt.status !== null && attempt.status >= 200 && attempt.status < 300 && attempt.completed;
8880
+ let marked = false;
8881
+ if (ok) {
8882
+ this.health.clearTransientMark(providerId, accountId);
8883
+ } else if (attempt.status === 401 || attempt.status === 403) {
8884
+ marked = this.applyOutcome(providerId, accountId, attempt.status, attempt.bodyText, now);
8885
+ }
8886
+ this.record(providerId, accountId, {
8887
+ ts: now,
8888
+ ok,
8889
+ status: attempt.status,
8890
+ latencyMs,
8891
+ tier: "generation"
8892
+ });
8893
+ return {
8894
+ ok,
8895
+ marked,
8896
+ tier: "generation",
8897
+ model: CODEX_GENERATION_PROBE_MODEL
8898
+ };
8229
8899
  }
8230
8900
  /** Per-account rolling history for the authed admin surface (design D5). */
8231
8901
  getAllHistory() {
@@ -8282,6 +8952,24 @@ var AccountHealthProbeScheduler = class {
8282
8952
  return "";
8283
8953
  }
8284
8954
  }
8955
+ async runCodexGenerationAttempt(accountId, token) {
8956
+ try {
8957
+ const timeoutMs = Math.max(this.config.timeoutMs, 15e3);
8958
+ const response = await this.fetchImpl(
8959
+ CODEX_GENERATION_PROBE_URL,
8960
+ buildCodexGenerationProbeInit(token, AbortSignal.timeout(timeoutMs)),
8961
+ { providerId: "codex", accountId, redactBodies: true }
8962
+ );
8963
+ if (response.status < 200 || response.status >= 300) {
8964
+ const bodyText = response.status === 403 ? await this.readBounded(response) : void 0;
8965
+ return { status: response.status, completed: false, bodyText };
8966
+ }
8967
+ const stream = await readCodexGenerationProbeStream(response);
8968
+ return { status: response.status, completed: stream.completed };
8969
+ } catch {
8970
+ return { status: null, completed: false };
8971
+ }
8972
+ }
8285
8973
  key(providerId, accountId) {
8286
8974
  return `${providerId}${KEY_SEP}${accountId}`;
8287
8975
  }
@@ -8377,7 +9065,7 @@ var AccountHealthSweeper = class {
8377
9065
  };
8378
9066
 
8379
9067
  // src/audit/AuditPruneSweeper.ts
8380
- import { existsSync as existsSync14, readdirSync, unlinkSync as unlinkSync3 } from "fs";
9068
+ import { existsSync as existsSync15, readdirSync as readdirSync2, unlinkSync as unlinkSync3 } from "fs";
8381
9069
  import { join as join7 } from "path";
8382
9070
 
8383
9071
  // src/audit/auditFiles.ts
@@ -8400,12 +9088,213 @@ function auditFileDateMs(fileName) {
8400
9088
  return d.getTime();
8401
9089
  }
8402
9090
 
9091
+ // src/audit/auditStats.ts
9092
+ import {
9093
+ createReadStream,
9094
+ existsSync as existsSync14,
9095
+ readFileSync as readFileSync15,
9096
+ readdirSync,
9097
+ statSync as statSync3,
9098
+ writeFileSync as writeFileSync12
9099
+ } from "fs";
9100
+ import { basename, dirname as dirname7, join as join6 } from "path";
9101
+ var SIDECAR_VERSION = 1;
9102
+ var META_PREFIX_BYTES = 64 * 1024;
9103
+ var READ_CHUNK_BYTES = 4 * 1024 * 1024;
9104
+ function auditStatsFileName(auditFile) {
9105
+ return auditFile.replace(/\.jsonl$/, ".stats.json");
9106
+ }
9107
+ function readPersisted(path2) {
9108
+ if (!existsSync14(path2)) return null;
9109
+ try {
9110
+ const value = JSON.parse(readFileSync15(path2, "utf8"));
9111
+ if (value.version !== SIDECAR_VERSION || !Number.isSafeInteger(value.auditBytes) || (value.auditBytes ?? -1) < 0 || !Number.isSafeInteger(value.requestCount) || (value.requestCount ?? -1) < 0 || !Number.isSafeInteger(value.errorCount) || (value.errorCount ?? -1) < 0 || (value.errorCount ?? 0) > (value.requestCount ?? -1) || typeof value.complete !== "boolean" || value.minTs !== null && !Number.isFinite(value.minTs) || value.maxTs !== null && !Number.isFinite(value.maxTs)) {
9112
+ return null;
9113
+ }
9114
+ return value;
9115
+ } catch {
9116
+ return null;
9117
+ }
9118
+ }
9119
+ function updateAuditStatsAfterAppend(auditPath, auditBytesBefore, auditBytesAfter, record) {
9120
+ const statsPath = join6(dirname7(auditPath), auditStatsFileName(basename(auditPath)));
9121
+ const previous = auditBytesBefore === 0 ? {
9122
+ version: SIDECAR_VERSION,
9123
+ auditBytes: 0,
9124
+ requestCount: 0,
9125
+ errorCount: 0,
9126
+ complete: true,
9127
+ minTs: null,
9128
+ maxTs: null
9129
+ } : readPersisted(statsPath);
9130
+ if (!previous || !previous.complete || previous.auditBytes !== auditBytesBefore) return;
9131
+ const next = {
9132
+ version: SIDECAR_VERSION,
9133
+ auditBytes: auditBytesAfter,
9134
+ requestCount: previous.requestCount + 1,
9135
+ errorCount: previous.errorCount + (record.status >= 400 || Boolean(record.error) ? 1 : 0),
9136
+ complete: true,
9137
+ minTs: previous.minTs === null ? record.ts : Math.min(previous.minTs, record.ts),
9138
+ maxTs: previous.maxTs === null ? record.ts : Math.max(previous.maxTs, record.ts)
9139
+ };
9140
+ writeFileSync12(statsPath, JSON.stringify(next), "utf8");
9141
+ }
9142
+ function queryCovers(stats, from, to) {
9143
+ return stats.requestCount === 0 || stats.minTs !== null && stats.maxTs !== null && from <= stats.minTs && to >= stats.maxTs;
9144
+ }
9145
+ function fileOverlaps(file, from, to) {
9146
+ const start = auditFileDateMs(file);
9147
+ if (start === null) return false;
9148
+ const date = new Date(start);
9149
+ const end = new Date(date.getFullYear(), date.getMonth(), date.getDate() + 1).getTime();
9150
+ return end > from && start <= to;
9151
+ }
9152
+ function parseMetadataPrefix(prefix, prefixTruncated) {
9153
+ const text = prefix.toString("utf8");
9154
+ const tsMatch = /(?:^|,)"ts":(-?\d+)/.exec(text);
9155
+ const statusMatch = /(?:^|,)"status":(-?\d+)/.exec(text);
9156
+ const errorMatch = /(?:^|,)"error":"((?:\\.|[^"\\])*)"/.exec(text);
9157
+ const bodyStarted = /,(?:"requestBody"|"responseBody"):/.test(text);
9158
+ return {
9159
+ ts: tsMatch ? Number(tsMatch[1]) : void 0,
9160
+ status: statusMatch ? Number(statusMatch[1]) : void 0,
9161
+ hasError: Boolean(errorMatch?.[1]),
9162
+ complete: Boolean(tsMatch && statusMatch && (!prefixTruncated || bodyStarted))
9163
+ };
9164
+ }
9165
+ async function scanAuditFile(auditPath, startByte, auditBytes, from, to) {
9166
+ let requestCount = 0;
9167
+ let errorCount = 0;
9168
+ let filteredRequestCount = 0;
9169
+ let filteredErrorCount = 0;
9170
+ let minTs = null;
9171
+ let maxTs = null;
9172
+ let complete = true;
9173
+ let prefixParts = [];
9174
+ let prefixBytes = 0;
9175
+ let prefixTruncated = false;
9176
+ const consumeLine = () => {
9177
+ if (prefixBytes === 0 && !prefixTruncated) return;
9178
+ const prefix = Buffer.concat(prefixParts, prefixBytes);
9179
+ const metadata = parseMetadataPrefix(prefix, prefixTruncated);
9180
+ if (!metadata.complete || metadata.ts === void 0 || metadata.status === void 0) {
9181
+ complete = false;
9182
+ } else {
9183
+ requestCount += 1;
9184
+ const isError = metadata.status >= 400 || metadata.hasError;
9185
+ if (isError) errorCount += 1;
9186
+ minTs = minTs === null ? metadata.ts : Math.min(minTs, metadata.ts);
9187
+ maxTs = maxTs === null ? metadata.ts : Math.max(maxTs, metadata.ts);
9188
+ if (metadata.ts >= from && metadata.ts <= to) {
9189
+ filteredRequestCount += 1;
9190
+ if (isError) filteredErrorCount += 1;
9191
+ }
9192
+ }
9193
+ prefixParts = [];
9194
+ prefixBytes = 0;
9195
+ prefixTruncated = false;
9196
+ };
9197
+ if (auditBytes > startByte) {
9198
+ const stream = createReadStream(auditPath, {
9199
+ start: startByte,
9200
+ end: auditBytes - 1,
9201
+ highWaterMark: READ_CHUNK_BYTES
9202
+ });
9203
+ for await (const value of stream) {
9204
+ const chunk = Buffer.isBuffer(value) ? value : Buffer.from(value);
9205
+ let offset = 0;
9206
+ while (offset < chunk.length) {
9207
+ const newline = chunk.indexOf(10, offset);
9208
+ const end = newline === -1 ? chunk.length : newline;
9209
+ if (prefixBytes < META_PREFIX_BYTES) {
9210
+ const retained = Math.min(META_PREFIX_BYTES - prefixBytes, end - offset);
9211
+ if (retained > 0) {
9212
+ prefixParts.push(Buffer.from(chunk.subarray(offset, offset + retained)));
9213
+ prefixBytes += retained;
9214
+ }
9215
+ if (retained < end - offset) prefixTruncated = true;
9216
+ } else if (end > offset) {
9217
+ prefixTruncated = true;
9218
+ }
9219
+ if (newline === -1) break;
9220
+ consumeLine();
9221
+ offset = newline + 1;
9222
+ }
9223
+ }
9224
+ }
9225
+ if (prefixBytes > 0 || prefixTruncated) complete = false;
9226
+ return {
9227
+ all: {
9228
+ version: SIDECAR_VERSION,
9229
+ auditBytes,
9230
+ requestCount,
9231
+ errorCount,
9232
+ complete,
9233
+ minTs,
9234
+ maxTs
9235
+ },
9236
+ filtered: { requestCount: filteredRequestCount, errorCount: filteredErrorCount, complete }
9237
+ };
9238
+ }
9239
+ function mergePersistedStats(previous, appended) {
9240
+ return {
9241
+ version: SIDECAR_VERSION,
9242
+ auditBytes: appended.auditBytes,
9243
+ requestCount: previous.requestCount + appended.requestCount,
9244
+ errorCount: previous.errorCount + appended.errorCount,
9245
+ complete: previous.complete && appended.complete,
9246
+ minTs: previous.minTs === null ? appended.minTs : appended.minTs === null ? previous.minTs : Math.min(previous.minTs, appended.minTs),
9247
+ maxTs: previous.maxTs === null ? appended.maxTs : appended.maxTs === null ? previous.maxTs : Math.max(previous.maxTs, appended.maxTs)
9248
+ };
9249
+ }
9250
+ async function readAuditStats(auditDir, query2 = {}) {
9251
+ if (!existsSync14(auditDir)) return { requestCount: 0, errorCount: 0, complete: true };
9252
+ const from = typeof query2.from === "number" ? query2.from : -Infinity;
9253
+ const to = typeof query2.to === "number" ? query2.to : Infinity;
9254
+ let files;
9255
+ try {
9256
+ files = readdirSync(auditDir).filter((file) => AUDIT_FILE_RE.test(file) && fileOverlaps(file, from, to)).sort();
9257
+ } catch {
9258
+ return { requestCount: 0, errorCount: 0, complete: false };
9259
+ }
9260
+ const total = { requestCount: 0, errorCount: 0, complete: true };
9261
+ for (const file of files) {
9262
+ const auditPath = join6(auditDir, file);
9263
+ try {
9264
+ const auditBytes = statSync3(auditPath).size;
9265
+ const statsPath = join6(auditDir, auditStatsFileName(file));
9266
+ const persisted = readPersisted(statsPath);
9267
+ if (persisted && persisted.complete && persisted.auditBytes === auditBytes && queryCovers(persisted, from, to)) {
9268
+ total.requestCount += persisted.requestCount;
9269
+ total.errorCount += persisted.errorCount;
9270
+ continue;
9271
+ }
9272
+ const resumable = persisted && persisted.complete && persisted.auditBytes < auditBytes && queryCovers(persisted, from, to) ? persisted : null;
9273
+ const scanned = await scanAuditFile(
9274
+ auditPath,
9275
+ resumable?.auditBytes ?? 0,
9276
+ auditBytes,
9277
+ from,
9278
+ to
9279
+ );
9280
+ total.requestCount += scanned.filtered.requestCount + (resumable?.requestCount ?? 0);
9281
+ total.errorCount += scanned.filtered.errorCount + (resumable?.errorCount ?? 0);
9282
+ total.complete = total.complete && scanned.filtered.complete;
9283
+ const current = resumable ? mergePersistedStats(resumable, scanned.all) : scanned.all;
9284
+ if (current.complete) writeFileSync12(statsPath, JSON.stringify(current), "utf8");
9285
+ } catch {
9286
+ total.complete = false;
9287
+ }
9288
+ }
9289
+ return total;
9290
+ }
9291
+
8403
9292
  // src/audit/AuditPruneSweeper.ts
8404
9293
  var DAY_MS = 24 * 60 * 6e4;
8405
9294
  var SWEEP_INTERVAL_MS2 = 60 * 6e4;
8406
9295
  var AuditPruneSweeper = class {
8407
- constructor(auditDir2, logger, config, intervalMs = SWEEP_INTERVAL_MS2, now = Date.now) {
8408
- this.auditDir = auditDir2;
9296
+ constructor(auditDir, logger, config, intervalMs = SWEEP_INTERVAL_MS2, now = Date.now) {
9297
+ this.auditDir = auditDir;
8409
9298
  this.logger = logger;
8410
9299
  this.config = config;
8411
9300
  this.intervalMs = intervalMs;
@@ -8452,17 +9341,19 @@ var AuditPruneSweeper = class {
8452
9341
  if (!this.config.enabled || this.sweeping) return 0;
8453
9342
  this.sweeping = true;
8454
9343
  try {
8455
- if (!existsSync14(this.auditDir)) return 0;
9344
+ if (!existsSync15(this.auditDir)) return 0;
8456
9345
  const today = new Date(this.now());
8457
9346
  const todayMidnight = new Date(today.getFullYear(), today.getMonth(), today.getDate()).getTime();
8458
9347
  const cutoff = todayMidnight - (this.config.retentionDays - 1) * DAY_MS;
8459
9348
  let removed = 0;
8460
- for (const file of readdirSync(this.auditDir)) {
9349
+ for (const file of readdirSync2(this.auditDir)) {
8461
9350
  const dateMs = auditFileDateMs(file);
8462
9351
  if (dateMs === null || dateMs >= cutoff) continue;
8463
9352
  try {
8464
9353
  unlinkSync3(join7(this.auditDir, file));
8465
9354
  removed += 1;
9355
+ const statsPath = join7(this.auditDir, auditStatsFileName(file));
9356
+ if (existsSync15(statsPath)) unlinkSync3(statsPath);
8466
9357
  } catch (error) {
8467
9358
  this.logger.warn("[AuditPruneSweeper] failed to unlink expired audit file", {
8468
9359
  file,
@@ -8484,15 +9375,15 @@ var AuditPruneSweeper = class {
8484
9375
  };
8485
9376
 
8486
9377
  // src/audit/auditReader.ts
8487
- import { existsSync as existsSync15, readdirSync as readdirSync2, readFileSync as readFileSync15 } from "fs";
9378
+ import { existsSync as existsSync16, readdirSync as readdirSync3, readFileSync as readFileSync16 } from "fs";
8488
9379
  import { join as join8 } from "path";
8489
9380
  var DEFAULT_LIMIT = 200;
8490
9381
  var MAX_LIMIT = 2e3;
8491
- function readAuditRecords(auditDir2, query2 = {}) {
8492
- if (!existsSync15(auditDir2)) return [];
9382
+ function readAuditRecords(auditDir, query2 = {}) {
9383
+ if (!existsSync16(auditDir)) return [];
8493
9384
  let files;
8494
9385
  try {
8495
- files = readdirSync2(auditDir2).filter((f) => AUDIT_FILE_RE.test(f));
9386
+ files = readdirSync3(auditDir).filter((f) => AUDIT_FILE_RE.test(f));
8496
9387
  } catch {
8497
9388
  return [];
8498
9389
  }
@@ -8503,7 +9394,7 @@ function readAuditRecords(auditDir2, query2 = {}) {
8503
9394
  for (const file of files.sort().reverse()) {
8504
9395
  let raw;
8505
9396
  try {
8506
- raw = readFileSync15(join8(auditDir2, file), "utf8");
9397
+ raw = readFileSync16(join8(auditDir, file), "utf8");
8507
9398
  } catch {
8508
9399
  continue;
8509
9400
  }
@@ -8532,11 +9423,11 @@ function isAuditRecord(value) {
8532
9423
  }
8533
9424
 
8534
9425
  // src/audit/AuditWriter.ts
8535
- import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync5 } from "fs";
9426
+ import { appendFileSync as appendFileSync2, existsSync as existsSync17, mkdirSync as mkdirSync5, statSync as statSync4 } from "fs";
8536
9427
  import { join as join9 } from "path";
8537
9428
  var AuditWriter = class {
8538
- constructor(auditDir2, logger, defer = (fn) => setTimeout(fn, 0)) {
8539
- this.auditDir = auditDir2;
9429
+ constructor(auditDir, logger, defer = (fn) => setTimeout(fn, 0)) {
9430
+ this.auditDir = auditDir;
8540
9431
  this.logger = logger;
8541
9432
  this.defer = defer;
8542
9433
  }
@@ -8570,7 +9461,21 @@ var AuditWriter = class {
8570
9461
  this.dirEnsured = true;
8571
9462
  }
8572
9463
  const file = join9(this.auditDir, auditFileName(record.ts));
8573
- appendFileSync2(file, JSON.stringify(record) + "\n", "utf8");
9464
+ const line = JSON.stringify(record) + "\n";
9465
+ const auditBytesBefore = existsSync17(file) ? statSync4(file).size : 0;
9466
+ appendFileSync2(file, line, "utf8");
9467
+ try {
9468
+ updateAuditStatsAfterAppend(
9469
+ file,
9470
+ auditBytesBefore,
9471
+ auditBytesBefore + Buffer.byteLength(line, "utf8"),
9472
+ record
9473
+ );
9474
+ } catch (error) {
9475
+ this.logger.warn("[AuditWriter] failed to update audit stats", {
9476
+ error: error instanceof Error ? error.message : String(error)
9477
+ });
9478
+ }
8574
9479
  }
8575
9480
  };
8576
9481
 
@@ -8714,14 +9619,14 @@ var BillingPublisher = class {
8714
9619
  };
8715
9620
 
8716
9621
  // src/billing/billingReader.ts
8717
- import { existsSync as existsSync16, readdirSync as readdirSync3, readFileSync as readFileSync16 } from "fs";
9622
+ import { existsSync as existsSync18, readdirSync as readdirSync4, readFileSync as readFileSync17 } from "fs";
8718
9623
  import { join as join11 } from "path";
8719
9624
  function readBillingLedger(billingDir) {
8720
9625
  const view = { events: [], deliveredIds: /* @__PURE__ */ new Set() };
8721
- if (!existsSync16(billingDir)) return view;
9626
+ if (!existsSync18(billingDir)) return view;
8722
9627
  let files;
8723
9628
  try {
8724
- files = readdirSync3(billingDir);
9629
+ files = readdirSync4(billingDir);
8725
9630
  } catch {
8726
9631
  return view;
8727
9632
  }
@@ -8752,7 +9657,7 @@ function readBillingStatus(billingDir) {
8752
9657
  function parseLines(dir, file) {
8753
9658
  let raw;
8754
9659
  try {
8755
- raw = readFileSync16(join11(dir, file), "utf8");
9660
+ raw = readFileSync17(join11(dir, file), "utf8");
8756
9661
  } catch {
8757
9662
  return [];
8758
9663
  }
@@ -8938,6 +9843,78 @@ var TokenRefreshScheduler = class {
8938
9843
  }
8939
9844
  };
8940
9845
 
9846
+ // src/routeLeaseSubscriptionPreflight.ts
9847
+ import {
9848
+ RouteLeaseError as RouteLeaseError3
9849
+ } from "@omnicross/core/provider-proxy";
9850
+ import { getSharedAccountAllowanceScheduling as getSharedAccountAllowanceScheduling4 } from "@omnicross/core/pipeline/AccountAllowanceScheduling";
9851
+ import { getSharedAccountHealth as getSharedAccountHealth3 } from "@omnicross/core/pipeline/SubscriptionAccountHealth";
9852
+ import { accountSupportsModel } from "@omnicross/subscriptions/scheduler/accountModelMap";
9853
+ var PROVIDERS = /* @__PURE__ */ new Set(["claude", "codex", "gemini", "opencodego"]);
9854
+ function accountArray(config, providerId) {
9855
+ const record = config;
9856
+ const key = `${providerId}Accounts`;
9857
+ const accounts = record[key];
9858
+ if (Array.isArray(accounts)) return accounts;
9859
+ const legacy = record[providerId];
9860
+ if (!legacy || typeof legacy !== "object") return [];
9861
+ const activeKey = `active${providerId[0].toUpperCase()}${providerId.slice(1)}AccountId`;
9862
+ return [{ id: String(record[activeKey] ?? "active"), enabled: true, tokens: legacy }];
9863
+ }
9864
+ function hasCredential(providerId, account) {
9865
+ const tokens = account.tokens;
9866
+ if (providerId === "opencodego") return typeof tokens.apiKey === "string" && tokens.apiKey.length > 0;
9867
+ return typeof tokens.accessToken === "string" && tokens.accessToken.length > 0;
9868
+ }
9869
+ function safeProviderId(value) {
9870
+ if (!PROVIDERS.has(value)) {
9871
+ throw new RouteLeaseError3("upstream_not_found", "subscription provider was not found");
9872
+ }
9873
+ return value;
9874
+ }
9875
+ function createRouteLeaseSubscriptionPreflight(credentials) {
9876
+ return {
9877
+ async assertAvailable(upstream, model) {
9878
+ const providerId = safeProviderId(upstream.providerId);
9879
+ const config = await credentials.getFullConfig();
9880
+ const all = accountArray(config, providerId);
9881
+ if (all.length === 0) {
9882
+ throw new RouteLeaseError3("upstream_unavailable", "subscription provider has no configured account");
9883
+ }
9884
+ let bounded = all;
9885
+ if (upstream.kind === "account") {
9886
+ bounded = all.filter((account) => account.id === upstream.accountId);
9887
+ } else if (upstream.kind === "account-group") {
9888
+ bounded = all.filter((account) => account.group?.trim() === upstream.group);
9889
+ }
9890
+ if (bounded.length === 0) {
9891
+ throw new RouteLeaseError3("upstream_not_found", "the selected subscription resource was not found");
9892
+ }
9893
+ const modelEligible = bounded.filter(
9894
+ (account) => accountSupportsModel(account.supportedModels, model)
9895
+ );
9896
+ if (modelEligible.length === 0) {
9897
+ throw new RouteLeaseError3("model_not_configured", "model is not supported by the selected subscription resource");
9898
+ }
9899
+ const credentialEligible = modelEligible.filter(
9900
+ (account) => account.enabled !== false && hasCredential(providerId, account)
9901
+ );
9902
+ const health2 = getSharedAccountHealth3();
9903
+ const allowance = getSharedAccountAllowanceScheduling4();
9904
+ const candidates = credentialEligible.filter(
9905
+ (account) => health2.isSchedulable(providerId, account.id) && allowance.preview(providerId, account.id, account.priority ?? 50).schedulable
9906
+ );
9907
+ if (candidates.length > 0) return;
9908
+ if (upstream.kind === "account") {
9909
+ throw new RouteLeaseError3("upstream_unavailable", "the selected subscription account is unavailable");
9910
+ }
9911
+ throw new RouteLeaseError3("upstream_exhausted", "the selected subscription pool has no eligible account", {
9912
+ retryAfterSeconds: 30
9913
+ });
9914
+ }
9915
+ };
9916
+ }
9917
+
8941
9918
  // src/webhook/WebhookDispatcher.ts
8942
9919
  import { createHmac as createHmac2 } from "crypto";
8943
9920
  import { fetchUpstream as fetchUpstream6 } from "@omnicross/core/pipeline/upstreamFetch";
@@ -9120,11 +10097,11 @@ function buildDaemon(config, paths) {
9120
10097
  new JsonAccountAllowancePersistence(defaultAccountAllowancePath(paths.configPath))
9121
10098
  );
9122
10099
  setSharedAccountAllowanceStore(accountAllowanceStore);
9123
- getSharedAccountAllowanceScheduling4().configure(
10100
+ getSharedAccountAllowanceScheduling5().configure(
9124
10101
  normalizeServerConfig(decryptedConfig.server).allowanceScheduling
9125
10102
  );
9126
10103
  const llmConfig = new ConfigFileProviderConfigSource(decryptedConfig);
9127
- const keyDb = new JsonOutboundKeyDb(paths.keysPath);
10104
+ const keyDb = new JsonOutboundKeyDb(paths.keysPath, secretBox3);
9128
10105
  const voucherDb = new JsonVoucherDb(defaultVouchersPath(paths.configPath));
9129
10106
  const settingsStore = new JsonApiServerSettingsStore(paths.configPath, secretBox3);
9130
10107
  const integrationStateStore = new IntegrationStateStore(
@@ -9188,10 +10165,21 @@ function buildDaemon(config, paths) {
9188
10165
  onRecord: (apiKeyId, costUsd, at) => keySpendTracker.add(apiKeyId, costUsd, at)
9189
10166
  });
9190
10167
  const providerProxy = getProviderProxy({ llmConfig, apiKeyPool, usageRecorder });
10168
+ const routeLeaseManager = new RouteLeaseManager(
10169
+ providerProxy,
10170
+ new RouteLeaseTargetResolver(llmConfig, {
10171
+ providerKeys: apiKeyPool,
10172
+ subscriptions: createRouteLeaseSubscriptionPreflight(credentialStore)
10173
+ }),
10174
+ routeLeaseDescriptorPort,
10175
+ { logger }
10176
+ );
10177
+ providerProxy.registerBeforeStop(() => routeLeaseManager.shutdown());
10178
+ providerProxy.registerBeforeStop(() => resetCliSessions());
9191
10179
  llmConfig.setReloadHook(() => apiKeyPool.invalidateCache());
9192
10180
  const accountHealthProbeScheduler = new AccountHealthProbeScheduler(
9193
10181
  credentialStore,
9194
- getSharedAccountHealth3(),
10182
+ getSharedAccountHealth4(),
9195
10183
  logger,
9196
10184
  DEFAULT_ACCOUNT_PROBE
9197
10185
  );
@@ -9225,7 +10213,7 @@ function buildDaemon(config, paths) {
9225
10213
  // lines through the injected logger (honors level/format/file sink).
9226
10214
  logger
9227
10215
  });
9228
- const auditDir2 = defaultAuditDir(paths.configPath);
10216
+ const auditDir = defaultAuditDir(paths.configPath);
9229
10217
  const billingDir = defaultBillingDir(paths.configPath);
9230
10218
  const adminServer = new AdminServer({
9231
10219
  configPath: paths.configPath,
@@ -9238,6 +10226,7 @@ function buildDaemon(config, paths) {
9238
10226
  keySpendReader: keySpendTracker,
9239
10227
  settingsStore,
9240
10228
  outboundApiServer,
10229
+ routeLeaseManager,
9241
10230
  subscriptionAccounts,
9242
10231
  accountAllowanceService,
9243
10232
  allowanceRefreshScheduler: claudeAllowanceRefreshScheduler,
@@ -9259,10 +10248,16 @@ function buildDaemon(config, paths) {
9259
10248
  // (NOT widening the least-authority writer — no token-returning read reachable).
9260
10249
  oauthSessions: new OAuthSessionStore(),
9261
10250
  // Real global fetch by default; a test seam (`paths.oauthExchangeFetch`) can
9262
- // inject a mock so no real token endpoint is hit.
9263
- // upstream-proxy: default the OAuth token-exchange fetch to the proxy-aware
9264
- // helper so interactive login honors a configured proxy (global/env layers).
9265
- oauthExchangeFetch: paths.oauthExchangeFetch ?? ((url, init) => fetchUpstream7(url, init)),
10251
+ // inject a mock so no real token endpoint is hit (one FetchLike for every
10252
+ // provider the ctx below only matters on the real egress path).
10253
+ //
10254
+ // upstream-proxy: a PER-PROVIDER factory, so the exchange carries the same
10255
+ // `{ providerId }` ctx the CLI login and the token refresh already pass.
10256
+ // Without it the interactive login resolved only the global/env proxy layers
10257
+ // — `server.proxy.byProvider[...]` was silently skipped — and the call was
10258
+ // excluded from the upstream trace, so a failing login left no evidence.
10259
+ // `redactBodies` keeps the code/verifier + minted token out of that trace.
10260
+ oauthExchangeFetch: paths.oauthExchangeFetch ? () => paths.oauthExchangeFetch : (providerId) => (url, init) => fetchUpstream7(url, init, { providerId, redactBodies: true }),
9266
10261
  subscriptionAccountAppender: credentialStore,
9267
10262
  // Codex interactive OAuth (app-parity-2 child 5) — the async loopback flow store
9268
10263
  // + the one-shot 127.0.0.1:1455 listener. Token captured + persisted daemon-side;
@@ -9314,7 +10309,8 @@ function buildDaemon(config, paths) {
9314
10309
  // date-rotated audit store. Bound to the store dir here so the AdminServer
9315
10310
  // carries no path/store coupling. Records hold IP/UA/bodies → admin-only,
9316
10311
  // NEVER unauth, NEVER on `/health`. Routed in `AdminServer` (not `adminApi.ts`).
9317
- auditReader: (query2) => readAuditRecords(auditDir2, query2),
10312
+ auditReader: (query2) => readAuditRecords(auditDir, query2),
10313
+ auditStatsReader: (query2) => readAuditStats(auditDir, query2),
9318
10314
  // billing-event-stream: the AUTHED `GET /admin/api/billing-status` returns the
9319
10315
  // secret-free total/delivered/pending counts of the durable ledger.
9320
10316
  billingStatusReader: () => readBillingStatus(billingDir)
@@ -9323,10 +10319,10 @@ function buildDaemon(config, paths) {
9323
10319
  logger,
9324
10320
  fetchImpl: (url, init) => fetchUpstream7(url, init)
9325
10321
  });
9326
- setWebhookRuntime(webhookDispatcher, getSharedAccountHealth3());
9327
- const auditWriter = new AuditWriter(auditDir2, logger);
9328
- const auditPruneSweeper = new AuditPruneSweeper(auditDir2, logger, DEFAULT_AUDIT_CONFIG);
9329
- setAuditRuntime(auditWriter, auditPruneSweeper, auditDir2);
10322
+ setWebhookRuntime(webhookDispatcher, getSharedAccountHealth4());
10323
+ const auditWriter = new AuditWriter(auditDir, logger);
10324
+ const auditPruneSweeper = new AuditPruneSweeper(auditDir, logger, DEFAULT_AUDIT_CONFIG);
10325
+ setAuditRuntime(auditWriter, auditPruneSweeper);
9330
10326
  const billingPublisher = new BillingPublisher(billingDir, logger);
9331
10327
  const billingRetrySweeper = new BillingRetrySweeper(
9332
10328
  billingDir,
@@ -9338,7 +10334,7 @@ function buildDaemon(config, paths) {
9338
10334
  const tokenRefreshScheduler = new TokenRefreshScheduler(credentialStore, logger);
9339
10335
  const accountHealthSweeper = new AccountHealthSweeper(
9340
10336
  credentialStore,
9341
- getSharedAccountHealth3(),
10337
+ getSharedAccountHealth4(),
9342
10338
  logger
9343
10339
  );
9344
10340
  return {
@@ -9347,6 +10343,7 @@ function buildDaemon(config, paths) {
9347
10343
  keyDb,
9348
10344
  settingsStore,
9349
10345
  providerProxy,
10346
+ routeLeaseManager,
9350
10347
  outboundApiServer,
9351
10348
  apiKeyPool,
9352
10349
  autoDisableStore,
@@ -9372,7 +10369,7 @@ function buildDaemon(config, paths) {
9372
10369
  }
9373
10370
  function isTokensStoreReadable(tokensPath) {
9374
10371
  try {
9375
- if (!existsSync17(tokensPath)) return true;
10372
+ if (!existsSync19(tokensPath)) return true;
9376
10373
  accessSync(tokensPath, fsConstants.R_OK);
9377
10374
  return true;
9378
10375
  } catch {
@@ -9421,7 +10418,7 @@ function resolveInPathDefault(candidate) {
9421
10418
  const segments = (process.env["PATH"] ?? "").split(delimiter2).filter(Boolean);
9422
10419
  for (const seg of segments) {
9423
10420
  const full = join12(seg, candidate);
9424
- if (existsSync18(full)) return full;
10421
+ if (existsSync20(full)) return full;
9425
10422
  }
9426
10423
  return null;
9427
10424
  }
@@ -9462,32 +10459,17 @@ async function runLaunch(argv, deps) {
9462
10459
  await daemon.llmConfig.ready();
9463
10460
  await daemon.providerProxy.start();
9464
10461
  } catch (err5) {
9465
- daemon.apiKeyPool.dispose();
9466
- daemon.tokenRefreshScheduler.dispose();
9467
- daemon.claudeAllowanceRefreshScheduler.dispose();
9468
- daemon.accountHealthSweeper.dispose();
9469
- daemon.accountHealthProbeScheduler.dispose();
9470
- daemon.auditPruneSweeper.dispose();
9471
- daemon.billingRetrySweeper.dispose();
9472
- daemon.pricingRefreshScheduler.dispose();
10462
+ await shutdownLaunchDaemon(daemon);
9473
10463
  throw err5;
9474
10464
  }
9475
10465
  let launch;
9476
10466
  try {
9477
- launch = await buildLaunchConfig(cli, daemon.llmConfig, {
10467
+ launch = await buildLaunchConfig(cli, daemon, {
9478
10468
  providerId: values.provider,
9479
10469
  model: values.model
9480
10470
  });
9481
10471
  } catch (err5) {
9482
- await daemon.providerProxy.stop();
9483
- daemon.apiKeyPool.dispose();
9484
- daemon.tokenRefreshScheduler.dispose();
9485
- daemon.claudeAllowanceRefreshScheduler.dispose();
9486
- daemon.accountHealthSweeper.dispose();
9487
- daemon.accountHealthProbeScheduler.dispose();
9488
- daemon.auditPruneSweeper.dispose();
9489
- daemon.billingRetrySweeper.dispose();
9490
- daemon.pricingRefreshScheduler.dispose();
10472
+ await shutdownLaunchDaemon(daemon);
9491
10473
  throw err5;
9492
10474
  }
9493
10475
  try {
@@ -9506,21 +10488,40 @@ async function runLaunch(argv, deps) {
9506
10488
  cwd: values.cwd
9507
10489
  });
9508
10490
  } finally {
9509
- launch.onSessionEnd();
9510
- await daemon.providerProxy.stop();
9511
- daemon.apiKeyPool.dispose();
9512
- daemon.tokenRefreshScheduler.dispose();
9513
- daemon.claudeAllowanceRefreshScheduler.dispose();
9514
- daemon.accountHealthSweeper.dispose();
9515
- daemon.accountHealthProbeScheduler.dispose();
9516
- daemon.auditPruneSweeper.dispose();
9517
- daemon.billingRetrySweeper.dispose();
9518
- daemon.pricingRefreshScheduler.dispose();
9519
- }
9520
- }
9521
- async function buildLaunchConfig(cli, llmConfig, opts) {
10491
+ try {
10492
+ launch.onSessionEnd();
10493
+ } finally {
10494
+ await shutdownLaunchDaemon(daemon);
10495
+ }
10496
+ }
10497
+ }
10498
+ async function buildLaunchConfig(cli, daemon, opts) {
10499
+ if (cli === "claude" || cli === "codex") {
10500
+ const internalId = randomUUID6();
10501
+ const outcome = await daemon.routeLeaseManager.createFromRequest({
10502
+ schemaVersion: ROUTE_LEASE_REQUEST_SCHEMA2,
10503
+ consumer: "omnicross-terminal",
10504
+ runtime: cli,
10505
+ upstream: { kind: "provider", providerId: opts.providerId },
10506
+ model: opts.model,
10507
+ execution: { sessionId: `launch:${cli}:${internalId}` }
10508
+ }, `omnicross-launch:${internalId}`);
10509
+ const stopRenewal = startTerminalLeaseRenewal(
10510
+ daemon.routeLeaseManager,
10511
+ outcome.result.leaseId
10512
+ );
10513
+ return {
10514
+ baseUrl: daemon.providerProxy.getBaseUrl(),
10515
+ env: outcome.result.launch.env,
10516
+ extraArgs: outcome.result.launch.extraArgs,
10517
+ onSessionEnd: () => {
10518
+ stopRenewal();
10519
+ daemon.routeLeaseManager.release(outcome.result.leaseId);
10520
+ }
10521
+ };
10522
+ }
9522
10523
  const common = {
9523
- llmConfig,
10524
+ llmConfig: daemon.llmConfig,
9524
10525
  providerId: opts.providerId,
9525
10526
  model: opts.model,
9526
10527
  // Stable, bounded session id — pool failover (poolseam) fires on launch
@@ -9528,10 +10529,6 @@ async function buildLaunchConfig(cli, llmConfig, opts) {
9528
10529
  sessionId: `launch:${cli}`
9529
10530
  };
9530
10531
  switch (cli) {
9531
- case "claude":
9532
- return buildClaudeCliLaunchConfig2(common);
9533
- case "codex":
9534
- return buildCodexLaunchConfig2(common);
9535
10532
  case "gemini":
9536
10533
  return buildGeminiCliLaunchConfig2(common);
9537
10534
  case "qwen":
@@ -9544,6 +10541,18 @@ async function buildLaunchConfig(cli, llmConfig, opts) {
9544
10541
  }
9545
10542
  }
9546
10543
  }
10544
+ async function shutdownLaunchDaemon(daemon) {
10545
+ daemon.routeLeaseManager.shutdown();
10546
+ await daemon.providerProxy.stop();
10547
+ daemon.apiKeyPool.dispose();
10548
+ daemon.tokenRefreshScheduler.dispose();
10549
+ daemon.claudeAllowanceRefreshScheduler.dispose();
10550
+ daemon.accountHealthSweeper.dispose();
10551
+ daemon.accountHealthProbeScheduler.dispose();
10552
+ daemon.auditPruneSweeper.dispose();
10553
+ daemon.billingRetrySweeper.dispose();
10554
+ daemon.pricingRefreshScheduler.dispose();
10555
+ }
9547
10556
  function spawnCliInherit(plan) {
9548
10557
  return new Promise((resolve3, reject) => {
9549
10558
  const child = spawn2(plan.command, plan.args, {
@@ -9590,7 +10599,7 @@ import { createInterface } from "readline";
9590
10599
  import { parseArgs as parseArgs5 } from "util";
9591
10600
  import { fetchUpstream as fetchUpstream8, setUpstreamProxyResolver as setUpstreamProxyResolver2 } from "@omnicross/core/pipeline/upstreamFetch";
9592
10601
  import { claudeOAuth as claudeOAuth3, codexOAuth as codexOAuth3, geminiOAuth as geminiOAuth3 } from "@omnicross/subscriptions";
9593
- var PROVIDERS = ["claude", "codex", "gemini"];
10602
+ var PROVIDERS2 = ["claude", "codex", "gemini"];
9594
10603
  async function runLogin(argv, deps) {
9595
10604
  const { values, positionals } = parseArgs5({
9596
10605
  args: argv,
@@ -9604,10 +10613,10 @@ async function runLogin(argv, deps) {
9604
10613
  });
9605
10614
  const provider = positionals[0];
9606
10615
  if (!provider) {
9607
- throw new Error(`login: a <provider> is required (one of ${PROVIDERS.join("|")})`);
10616
+ throw new Error(`login: a <provider> is required (one of ${PROVIDERS2.join("|")})`);
9608
10617
  }
9609
10618
  if (!isLoginProvider(provider)) {
9610
- throw new Error(`login: unknown provider '${provider}' (expected ${PROVIDERS.join("|")})`);
10619
+ throw new Error(`login: unknown provider '${provider}' (expected ${PROVIDERS2.join("|")})`);
9611
10620
  }
9612
10621
  if (!values.config) {
9613
10622
  throw new Error("login: --config <path> is required");
@@ -9623,7 +10632,7 @@ async function runLogin(argv, deps) {
9623
10632
  setUpstreamProxyResolver2(createUpstreamProxyResolver());
9624
10633
  try {
9625
10634
  const tokensPath = defaultTokensPath(values.config);
9626
- const exchangeFetch = resolved.tokensFetch ?? ((url, init) => fetchUpstream8(url, init, { providerId: provider }));
10635
+ const exchangeFetch = resolved.tokensFetch ?? ((url, init) => fetchUpstream8(url, init, { providerId: provider, redactBodies: true }));
9627
10636
  const store = new JsonSubscriptionCredentialStore(tokensPath, box, exchangeFetch);
9628
10637
  const expiresAt = await runProviderLogin(
9629
10638
  provider,
@@ -9713,7 +10722,7 @@ async function loginGemini(store, deps, exchangeFetch, label) {
9713
10722
  return expiresAt;
9714
10723
  }
9715
10724
  function isLoginProvider(value) {
9716
- return PROVIDERS.includes(value);
10725
+ return PROVIDERS2.includes(value);
9717
10726
  }
9718
10727
  async function presentUrl(authUrl, deps) {
9719
10728
  console.info("Open this URL in your browser to authorize:");
@@ -9759,7 +10768,7 @@ function promptPaste(prompt) {
9759
10768
  }
9760
10769
 
9761
10770
  // src/commands/providers.ts
9762
- import { randomUUID as randomUUID6 } from "crypto";
10771
+ import { randomUUID as randomUUID7 } from "crypto";
9763
10772
  import { parseArgs as parseArgs6 } from "util";
9764
10773
  async function runProviders(argv) {
9765
10774
  const { values, positionals } = parseArgs6({
@@ -9881,7 +10890,7 @@ function providersAddKey(configPath, providerId, opts) {
9881
10890
  const cfg = loadConfig(configPath);
9882
10891
  const row = cfg.providers.find((p) => p.id === providerId);
9883
10892
  if (!row) throw new Error(`providers add-key: unknown provider '${providerId}'`);
9884
- const entry = { id: randomUUID6(), apiKey: opts.key };
10893
+ const entry = { id: randomUUID7(), apiKey: opts.key };
9885
10894
  if (opts.label) entry.label = opts.label;
9886
10895
  if (opts.weight !== void 0) {
9887
10896
  const w = Number(opts.weight);
@@ -9909,7 +10918,7 @@ function providersRmKey(configPath, providerId, keyId) {
9909
10918
  }
9910
10919
 
9911
10920
  // src/commands/secrets.ts
9912
- import { existsSync as existsSync19, readFileSync as readFileSync17, writeFileSync as writeFileSync11 } from "fs";
10921
+ import { existsSync as existsSync21, readFileSync as readFileSync18, writeFileSync as writeFileSync13 } from "fs";
9913
10922
  import { parseArgs as parseArgs7 } from "util";
9914
10923
  async function runSecrets(argv) {
9915
10924
  const { values, positionals } = parseArgs7({
@@ -9982,12 +10991,12 @@ function secretsStatus(args) {
9982
10991
  reportField("admin.token", cfg.admin.token);
9983
10992
  }
9984
10993
  const tokensPath = defaultTokensPath(args.config);
9985
- if (existsSync19(tokensPath)) {
10994
+ if (existsSync21(tokensPath)) {
9986
10995
  console.info(`Secret status for ${tokensPath}:`);
9987
10996
  reportTokenFields(tokensPath);
9988
10997
  }
9989
10998
  const integrationsPath = defaultIntegrationsPath(args.config);
9990
- if (existsSync19(integrationsPath)) {
10999
+ if (existsSync21(integrationsPath)) {
9991
11000
  const state = readRawJson(integrationsPath);
9992
11001
  const key = state.gatewayKey;
9993
11002
  if (key && typeof key === "object" && !Array.isArray(key)) {
@@ -10041,8 +11050,8 @@ async function secretsRotate(args) {
10041
11050
  const integrationsPath = defaultIntegrationsPath(args.config);
10042
11051
  try {
10043
11052
  cfg = loadConfig(args.config);
10044
- if (existsSync19(tokensPath)) tokensPlain = decryptTokensFile(tokensPath, oldBox);
10045
- if (existsSync19(integrationsPath)) {
11053
+ if (existsSync21(tokensPath)) tokensPlain = decryptTokensFile(tokensPath, oldBox);
11054
+ if (existsSync21(integrationsPath)) {
10046
11055
  integrationsPlain = new IntegrationStateStore(integrationsPath, oldBox).load();
10047
11056
  }
10048
11057
  } finally {
@@ -10077,20 +11086,20 @@ function secretsDecrypt(args) {
10077
11086
  let tokensPlain = null;
10078
11087
  try {
10079
11088
  cfg = loadConfig(args.config);
10080
- if (existsSync19(tokensPath)) tokensPlain = decryptTokensFile(tokensPath, box);
11089
+ if (existsSync21(tokensPath)) tokensPlain = decryptTokensFile(tokensPath, box);
10081
11090
  } finally {
10082
11091
  setSecretBox(null);
10083
11092
  }
10084
11093
  saveConfig(args.config, cfg);
10085
11094
  if (tokensPlain) {
10086
- writeFileSync11(tokensPath, JSON.stringify(tokensPlain, null, 2) + "\n", "utf8");
11095
+ writeFileSync13(tokensPath, JSON.stringify(tokensPlain, null, 2) + "\n", "utf8");
10087
11096
  }
10088
11097
  console.info(`Decrypted secrets to plaintext in ${args.config}` + tokensSuffix(args.config));
10089
11098
  }
10090
11099
  function readRawConfig(path2) {
10091
11100
  let parsed;
10092
11101
  try {
10093
- parsed = JSON.parse(readFileSync17(path2, "utf8"));
11102
+ parsed = JSON.parse(readFileSync18(path2, "utf8"));
10094
11103
  } catch {
10095
11104
  throw new Error(`secrets: cannot read or parse '${path2}'`);
10096
11105
  }
@@ -10098,7 +11107,7 @@ function readRawConfig(path2) {
10098
11107
  }
10099
11108
  function readRawJson(path2) {
10100
11109
  try {
10101
- const parsed = JSON.parse(readFileSync17(path2, "utf8"));
11110
+ const parsed = JSON.parse(readFileSync18(path2, "utf8"));
10102
11111
  if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
10103
11112
  return parsed;
10104
11113
  }
@@ -10108,13 +11117,13 @@ function readRawJson(path2) {
10108
11117
  }
10109
11118
  function encryptTokensFileInPlace(configPath, box) {
10110
11119
  const tokensPath = defaultTokensPath(configPath);
10111
- if (!existsSync19(tokensPath)) return;
11120
+ if (!existsSync21(tokensPath)) return;
10112
11121
  const plain = decryptTokensFile(tokensPath, box);
10113
11122
  writeTokensEncrypted(tokensPath, plain, box);
10114
11123
  }
10115
11124
  function rewriteIntegrationState(configPath, readBox, writeBox) {
10116
11125
  const path2 = defaultIntegrationsPath(configPath);
10117
- if (!existsSync19(path2)) return;
11126
+ if (!existsSync21(path2)) return;
10118
11127
  const state = new IntegrationStateStore(path2, readBox).load();
10119
11128
  new IntegrationStateStore(path2, writeBox).save(state);
10120
11129
  }
@@ -10127,7 +11136,7 @@ function writeTokensEncrypted(tokensPath, plain, box) {
10127
11136
  { updatedAt: "", ...plain },
10128
11137
  box
10129
11138
  );
10130
- writeFileSync11(tokensPath, JSON.stringify(encrypted, null, 2) + "\n", "utf8");
11139
+ writeFileSync13(tokensPath, JSON.stringify(encrypted, null, 2) + "\n", "utf8");
10131
11140
  }
10132
11141
  var TOKEN_FIELDS2 = {
10133
11142
  claude: ["accessToken", "refreshToken"],
@@ -10150,14 +11159,14 @@ function walkTokens(raw, fn) {
10150
11159
  return next;
10151
11160
  }
10152
11161
  function tokensSuffix(configPath) {
10153
- return existsSync19(defaultTokensPath(configPath)) ? " (+ tokens.json)" : "";
11162
+ return existsSync21(defaultTokensPath(configPath)) ? " (+ tokens.json)" : "";
10154
11163
  }
10155
11164
 
10156
11165
  // src/commands/start.ts
10157
11166
  import { parseArgs as parseArgs8 } from "util";
10158
11167
  import { loadServerConfig as loadServerConfig3 } from "@omnicross/core/outbound-api";
10159
- import { getSharedAccountHealth as getSharedAccountHealth4 } from "@omnicross/core/pipeline/SubscriptionAccountHealth";
10160
- import { getSharedAccountAllowanceScheduling as getSharedAccountAllowanceScheduling5 } from "@omnicross/core/pipeline/AccountAllowanceScheduling";
11168
+ import { getSharedAccountHealth as getSharedAccountHealth5 } from "@omnicross/core/pipeline/SubscriptionAccountHealth";
11169
+ import { getSharedAccountAllowanceScheduling as getSharedAccountAllowanceScheduling6 } from "@omnicross/core/pipeline/AccountAllowanceScheduling";
10161
11170
 
10162
11171
  // src/identity/identityRuntime.ts
10163
11172
  import { getSharedIdentityStore as getSharedIdentityStore3 } from "@omnicross/core/provider-proxy/identity/SubscriptionIdentityStore";
@@ -10217,11 +11226,11 @@ async function runStart(argv) {
10217
11226
  await daemon.llmConfig.ready();
10218
11227
  await daemon.providerProxy.start();
10219
11228
  const serverConfig = await loadServerConfig3(daemon.settingsStore);
10220
- getSharedAccountHealth4().configure({
11229
+ getSharedAccountHealth5().configure({
10221
11230
  overloadEnabled: serverConfig.accountHealth?.overloadCooldownEnabled,
10222
11231
  overloadTtlMs: serverConfig.accountHealth?.overloadCooldownMs
10223
11232
  });
10224
- getSharedAccountAllowanceScheduling5().configure(serverConfig.allowanceScheduling);
11233
+ getSharedAccountAllowanceScheduling6().configure(serverConfig.allowanceScheduling);
10225
11234
  daemon.claudeAllowanceRefreshScheduler.configure(serverConfig.allowanceScheduling);
10226
11235
  await daemon.outboundApiServer.applyConfig({
10227
11236
  enabled: true,