@omnicross/daemon 0.1.7 → 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.cjs +511 -99
- package/dist/cli.js +536 -114
- package/dist/index.cjs +450 -52
- package/dist/index.d.cts +7 -2
- package/dist/index.d.ts +7 -2
- package/dist/index.js +475 -65
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1750,15 +1750,15 @@ async function keysRevoke(db, id) {
|
|
|
1750
1750
|
|
|
1751
1751
|
// src/commands/launch.ts
|
|
1752
1752
|
import { spawn as spawn2 } from "child_process";
|
|
1753
|
+
import { randomUUID as randomUUID6 } from "crypto";
|
|
1753
1754
|
import { existsSync as existsSync20 } from "fs";
|
|
1754
1755
|
import { delimiter as delimiter2, join as join12 } from "path";
|
|
1755
1756
|
import { parseArgs as parseArgs4 } from "util";
|
|
1756
1757
|
import {
|
|
1757
1758
|
buildChatCliLaunchConfig as buildChatCliLaunchConfig2,
|
|
1758
|
-
buildClaudeCliLaunchConfig as buildClaudeCliLaunchConfig2,
|
|
1759
|
-
buildCodexLaunchConfig as buildCodexLaunchConfig2,
|
|
1760
1759
|
buildGeminiCliLaunchConfig as buildGeminiCliLaunchConfig2
|
|
1761
1760
|
} from "@omnicross/cli-launcher";
|
|
1761
|
+
import { ROUTE_LEASE_REQUEST_SCHEMA as ROUTE_LEASE_REQUEST_SCHEMA2 } from "@omnicross/core/provider-proxy";
|
|
1762
1762
|
|
|
1763
1763
|
// src/bootstrap.ts
|
|
1764
1764
|
import { accessSync, constants as fsConstants, existsSync as existsSync19 } from "fs";
|
|
@@ -1774,7 +1774,7 @@ import {
|
|
|
1774
1774
|
normalizeServerConfig
|
|
1775
1775
|
} from "@omnicross/core/outbound-api";
|
|
1776
1776
|
import { setSubscriptionRegistryForOutbound } from "@omnicross/core/outbound-api/subscriptionRegistryPort";
|
|
1777
|
-
import { getSharedAccountHealth as
|
|
1777
|
+
import { getSharedAccountHealth as getSharedAccountHealth4 } from "@omnicross/core/pipeline/SubscriptionAccountHealth";
|
|
1778
1778
|
import {
|
|
1779
1779
|
__resetSharedAccountAllowanceStoreForTests,
|
|
1780
1780
|
AccountAllowanceStore as AccountAllowanceStore3,
|
|
@@ -1782,15 +1782,18 @@ import {
|
|
|
1782
1782
|
} from "@omnicross/core/pipeline/AccountAllowanceStore";
|
|
1783
1783
|
import {
|
|
1784
1784
|
__resetSharedAccountAllowanceSchedulingForTests,
|
|
1785
|
-
getSharedAccountAllowanceScheduling as
|
|
1785
|
+
getSharedAccountAllowanceScheduling as getSharedAccountAllowanceScheduling5
|
|
1786
1786
|
} from "@omnicross/core/pipeline/AccountAllowanceScheduling";
|
|
1787
1787
|
import { fetchUpstream as fetchUpstream7, setUpstreamProxyResolver } from "@omnicross/core/pipeline/upstreamFetch";
|
|
1788
1788
|
import { __resetSharedIdentityStoreForTests } from "@omnicross/core/provider-proxy/identity/SubscriptionIdentityStore";
|
|
1789
1789
|
import { setGeminiCodeAssistResolver } from "@omnicross/core/ports/gemini-code-assist-resolver";
|
|
1790
1790
|
import {
|
|
1791
1791
|
__resetProviderProxyForTests,
|
|
1792
|
-
getProviderProxy
|
|
1792
|
+
getProviderProxy,
|
|
1793
|
+
RouteLeaseManager,
|
|
1794
|
+
RouteLeaseTargetResolver
|
|
1793
1795
|
} from "@omnicross/core/provider-proxy";
|
|
1796
|
+
import { routeLeaseDescriptorPort } from "@omnicross/cli-launcher";
|
|
1794
1797
|
import { KeySpendTracker } from "@omnicross/core/outbound-api";
|
|
1795
1798
|
import { PricingEngine, UsageRecorder } from "@omnicross/core/usage";
|
|
1796
1799
|
import {
|
|
@@ -2496,6 +2499,93 @@ async function handleWebhookTest(req, res) {
|
|
|
2496
2499
|
res.end(JSON.stringify({ result }));
|
|
2497
2500
|
}
|
|
2498
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
|
+
|
|
2499
2589
|
// src/admin/adminApi.ts
|
|
2500
2590
|
import http from "http";
|
|
2501
2591
|
import {
|
|
@@ -3054,7 +3144,9 @@ async function exchangeGemini(code, codeVerifier, exchangeFetch) {
|
|
|
3054
3144
|
// src/admin/cliLaunch.ts
|
|
3055
3145
|
import { exec, spawn } from "child_process";
|
|
3056
3146
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
3057
|
-
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";
|
|
3058
3150
|
import { delimiter, join as join4 } from "path";
|
|
3059
3151
|
import {
|
|
3060
3152
|
buildChatCliLaunchConfig,
|
|
@@ -3062,6 +3154,33 @@ import {
|
|
|
3062
3154
|
buildCodexLaunchConfig,
|
|
3063
3155
|
buildGeminiCliLaunchConfig
|
|
3064
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
|
|
3065
3184
|
var LAUNCHABLE_CLIS = [
|
|
3066
3185
|
{ id: "claude", displayName: "Claude Code", command: "claude" },
|
|
3067
3186
|
{ id: "codex", displayName: "Codex CLI", command: "codex" },
|
|
@@ -3142,34 +3261,183 @@ async function buildLaunchEnv(cli, llmConfig, target) {
|
|
|
3142
3261
|
function shq(s) {
|
|
3143
3262
|
return `'${s.replace(/'/g, `'\\''`)}'`;
|
|
3144
3263
|
}
|
|
3145
|
-
var
|
|
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 = {}) {
|
|
3146
3295
|
const childEnv = { ...process.env, ...env };
|
|
3147
3296
|
if (platform === "win32") {
|
|
3148
3297
|
const args = ["/c", "start", `"omnicross ${cli}"`];
|
|
3149
3298
|
if (cwd) args.push("/D", `"${cwd}"`);
|
|
3150
3299
|
args.push("cmd", "/k", command, ...extraArgs);
|
|
3151
|
-
|
|
3300
|
+
spawnProcess(process.env["ComSpec"] || "cmd.exe", args, {
|
|
3152
3301
|
env: childEnv,
|
|
3153
3302
|
windowsVerbatimArguments: true,
|
|
3154
3303
|
detached: true,
|
|
3155
3304
|
stdio: "ignore"
|
|
3156
3305
|
}).unref();
|
|
3157
|
-
return
|
|
3306
|
+
return () => {
|
|
3307
|
+
};
|
|
3158
3308
|
}
|
|
3159
|
-
const exportLine = Object.entries(env).map(([k, v]) => `export ${k}=${shq(v)}`).join("; ");
|
|
3160
3309
|
const runLine = [command, ...extraArgs].map(shq).join(" ");
|
|
3161
|
-
const script = `${
|
|
3310
|
+
const script = `${cwd ? `cd ${shq(cwd)}; ` : ""}${runLine}`;
|
|
3162
3311
|
if (platform === "darwin") {
|
|
3163
|
-
const
|
|
3164
|
-
|
|
3165
|
-
|
|
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
|
+
}
|
|
3166
3421
|
}
|
|
3167
|
-
|
|
3422
|
+
spawnProcess("x-terminal-emulator", ["-e", "bash", "-lc", `${script}; exec bash`], {
|
|
3423
|
+
env: childEnv,
|
|
3168
3424
|
detached: true,
|
|
3169
3425
|
stdio: "ignore"
|
|
3170
3426
|
}).unref();
|
|
3171
|
-
|
|
3427
|
+
return () => {
|
|
3428
|
+
};
|
|
3429
|
+
}
|
|
3430
|
+
var defaultTerminalOpener = (input) => openTerminal(input);
|
|
3172
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
|
+
}
|
|
3173
3441
|
function errBody(message) {
|
|
3174
3442
|
return { error: { type: "admin_api_error", message } };
|
|
3175
3443
|
}
|
|
@@ -3224,29 +3492,81 @@ async function handleCliLaunch(cli, body, ctx) {
|
|
|
3224
3492
|
} catch (err5) {
|
|
3225
3493
|
return { status: 400, body: errBody(err5 instanceof Error ? err5.message : "no launch target") };
|
|
3226
3494
|
}
|
|
3495
|
+
const id = randomUUID2();
|
|
3496
|
+
let leaseId2;
|
|
3227
3497
|
let launch;
|
|
3228
3498
|
try {
|
|
3229
|
-
|
|
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
|
+
}
|
|
3230
3521
|
} catch (err5) {
|
|
3231
|
-
|
|
3522
|
+
const status = err5 instanceof RouteLeaseError2 ? err5.status : 400;
|
|
3523
|
+
return { status, body: errBody(err5 instanceof Error ? err5.message : "failed to build launch env") };
|
|
3232
3524
|
}
|
|
3233
3525
|
const cwd = typeof body["cwd"] === "string" && body["cwd"].trim() ? body["cwd"].trim() : void 0;
|
|
3234
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
|
+
};
|
|
3235
3540
|
try {
|
|
3236
|
-
opener({
|
|
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;
|
|
3237
3551
|
} catch (err5) {
|
|
3238
|
-
|
|
3552
|
+
onSessionEnd();
|
|
3239
3553
|
return { status: 500, body: errBody(err5 instanceof Error ? err5.message : "failed to open terminal") };
|
|
3240
3554
|
}
|
|
3241
|
-
|
|
3555
|
+
if (ended) {
|
|
3556
|
+
openerCleanup?.();
|
|
3557
|
+
return { status: 500, body: errBody("failed to open terminal") };
|
|
3558
|
+
}
|
|
3242
3559
|
sessions.set(id, {
|
|
3243
3560
|
id,
|
|
3244
3561
|
cli,
|
|
3245
3562
|
providerId: target.providerId,
|
|
3246
3563
|
model: target.model,
|
|
3564
|
+
...leaseId2 ? { leaseId: leaseId2 } : {},
|
|
3247
3565
|
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3248
|
-
onSessionEnd
|
|
3566
|
+
onSessionEnd
|
|
3249
3567
|
});
|
|
3568
|
+
published = true;
|
|
3569
|
+
if (ended) sessions.delete(id);
|
|
3250
3570
|
return { status: 200, body: { sessionId: id, providerId: target.providerId, model: target.model } };
|
|
3251
3571
|
}
|
|
3252
3572
|
|
|
@@ -4133,7 +4453,7 @@ function sealPack(bundleJson, passphrase) {
|
|
|
4133
4453
|
cipher.setAAD(aadFor(PACK_MAGIC, PACK_VERSION, KDF_ALGORITHM));
|
|
4134
4454
|
const ciphertext = Buffer.concat([cipher.update(bundleJson, "utf8"), cipher.final()]);
|
|
4135
4455
|
const tag = cipher.getAuthTag();
|
|
4136
|
-
const
|
|
4456
|
+
const header2 = {
|
|
4137
4457
|
magic: PACK_MAGIC,
|
|
4138
4458
|
v: PACK_VERSION,
|
|
4139
4459
|
kdf: KDF_ALGORITHM,
|
|
@@ -4144,7 +4464,7 @@ function sealPack(bundleJson, passphrase) {
|
|
|
4144
4464
|
iv: iv.toString("base64"),
|
|
4145
4465
|
tag: tag.toString("base64")
|
|
4146
4466
|
};
|
|
4147
|
-
return `${PACK_PREFIX}${toB64Url(JSON.stringify(
|
|
4467
|
+
return `${PACK_PREFIX}${toB64Url(JSON.stringify(header2))}.${ciphertext.toString("base64")}`;
|
|
4148
4468
|
}
|
|
4149
4469
|
function parsePack(packString) {
|
|
4150
4470
|
if (typeof packString !== "string" || !packString.startsWith(PACK_PREFIX)) {
|
|
@@ -4155,28 +4475,28 @@ function parsePack(packString) {
|
|
|
4155
4475
|
if (dot < 0) throw new PackAuthError("migration pack is malformed (missing body)");
|
|
4156
4476
|
const headerB64Url = rest.slice(0, dot);
|
|
4157
4477
|
const ctB64 = rest.slice(dot + 1);
|
|
4158
|
-
let
|
|
4478
|
+
let header2;
|
|
4159
4479
|
try {
|
|
4160
|
-
|
|
4480
|
+
header2 = JSON.parse(fromB64Url(headerB64Url));
|
|
4161
4481
|
} catch {
|
|
4162
4482
|
throw new PackAuthError("migration pack is malformed (unreadable header)");
|
|
4163
4483
|
}
|
|
4164
|
-
if (!
|
|
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") {
|
|
4165
4485
|
throw new PackAuthError("migration pack is malformed (unsupported header)");
|
|
4166
4486
|
}
|
|
4167
4487
|
const ciphertext = Buffer.from(ctB64, "base64");
|
|
4168
|
-
return { header, ciphertext };
|
|
4488
|
+
return { header: header2, ciphertext };
|
|
4169
4489
|
}
|
|
4170
4490
|
function openPack(packString, passphrase) {
|
|
4171
4491
|
assertPassphraseStrength(passphrase);
|
|
4172
|
-
const { header, ciphertext } = parsePack(packString);
|
|
4173
|
-
const salt = Buffer.from(
|
|
4174
|
-
const iv = Buffer.from(
|
|
4175
|
-
const tag = Buffer.from(
|
|
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");
|
|
4176
4496
|
if (iv.length !== IV_BYTES2 || tag.length !== TAG_BYTES2) {
|
|
4177
4497
|
throw new PackAuthError("migration pack is malformed (invalid iv/tag length)");
|
|
4178
4498
|
}
|
|
4179
|
-
const key = deriveKey(passphrase, salt,
|
|
4499
|
+
const key = deriveKey(passphrase, salt, header2.N, header2.r, header2.p);
|
|
4180
4500
|
const decipher = createDecipheriv2("aes-256-gcm", key, iv);
|
|
4181
4501
|
decipher.setAAD(aadFor(PACK_MAGIC, PACK_VERSION, KDF_ALGORITHM));
|
|
4182
4502
|
decipher.setAuthTag(tag);
|
|
@@ -4512,10 +4832,10 @@ function writeJson2(res, status, body) {
|
|
|
4512
4832
|
res.writeHead(status, { "Content-Type": "application/json" });
|
|
4513
4833
|
res.end(JSON.stringify(body));
|
|
4514
4834
|
}
|
|
4515
|
-
function
|
|
4835
|
+
function writeError2(res, status, message) {
|
|
4516
4836
|
writeJson2(res, status, { error: { type: "account_allowance_error", message } });
|
|
4517
4837
|
}
|
|
4518
|
-
function
|
|
4838
|
+
function readJson2(req) {
|
|
4519
4839
|
return new Promise((resolve3, reject) => {
|
|
4520
4840
|
const chunks = [];
|
|
4521
4841
|
req.on("data", (chunk) => chunks.push(Buffer.from(chunk)));
|
|
@@ -4541,10 +4861,10 @@ function allowanceProvider(value) {
|
|
|
4541
4861
|
return value === "claude" || value === "codex" ? value : null;
|
|
4542
4862
|
}
|
|
4543
4863
|
async function handleAccountAllowanceApi(req, res, method, rest, service) {
|
|
4544
|
-
if (!service) return
|
|
4864
|
+
if (!service) return writeError2(res, 501, "account allowance service is not available");
|
|
4545
4865
|
if (method === "GET" && rest.length === 1 && rest[0] === "scheduling") {
|
|
4546
4866
|
if (!service.getSchedulingStatus) {
|
|
4547
|
-
return
|
|
4867
|
+
return writeError2(res, 501, "allowance scheduling diagnostics are not available");
|
|
4548
4868
|
}
|
|
4549
4869
|
return writeJson2(res, 200, { scheduling: service.getSchedulingStatus() });
|
|
4550
4870
|
}
|
|
@@ -4552,27 +4872,27 @@ async function handleAccountAllowanceApi(req, res, method, rest, service) {
|
|
|
4552
4872
|
const params = query(req);
|
|
4553
4873
|
const pathProvider = rest.length >= 2 ? rest[0] : null;
|
|
4554
4874
|
const providerId = allowanceProvider(pathProvider ?? params.get("providerId") ?? params.get("provider"));
|
|
4555
|
-
if (providerId === null) return
|
|
4875
|
+
if (providerId === null) return writeError2(res, 400, "providerId must be claude or codex");
|
|
4556
4876
|
const accountId = rest.length >= 2 ? rest[1] : params.get("accountId") ?? void 0;
|
|
4557
4877
|
const allowances = await service.list({ providerId, accountId });
|
|
4558
4878
|
return writeJson2(res, 200, { allowances });
|
|
4559
4879
|
}
|
|
4560
4880
|
if (method === "POST" && rest[0] === "refresh") {
|
|
4561
|
-
const body = await
|
|
4881
|
+
const body = await readJson2(req);
|
|
4562
4882
|
const requestedProvider = allowanceProvider(
|
|
4563
4883
|
typeof body["providerId"] === "string" ? body["providerId"] : "claude"
|
|
4564
4884
|
);
|
|
4565
4885
|
if (requestedProvider !== "claude") {
|
|
4566
|
-
return
|
|
4886
|
+
return writeError2(res, 400, "only Claude allowances support explicit refresh");
|
|
4567
4887
|
}
|
|
4568
4888
|
const accountId = typeof body["accountId"] === "string" && body["accountId"].trim() ? body["accountId"].trim() : void 0;
|
|
4569
4889
|
const allowances = await service.refreshClaude(accountId);
|
|
4570
4890
|
if (accountId && allowances.length === 0) {
|
|
4571
|
-
return
|
|
4891
|
+
return writeError2(res, 404, `Claude account '${accountId}' not found`);
|
|
4572
4892
|
}
|
|
4573
4893
|
return writeJson2(res, 200, { allowances });
|
|
4574
4894
|
}
|
|
4575
|
-
return
|
|
4895
|
+
return writeError2(res, 405, `method ${method} not allowed on account allowances`);
|
|
4576
4896
|
}
|
|
4577
4897
|
|
|
4578
4898
|
// src/admin/adminApi.ts
|
|
@@ -5807,6 +6127,7 @@ async function handleCli(req, res, method, rest, deps) {
|
|
|
5807
6127
|
const result = await handleCliLaunch(cli, body, {
|
|
5808
6128
|
llmConfig: deps.llmConfig,
|
|
5809
6129
|
providers,
|
|
6130
|
+
routeLeaseManager: deps.routeLeaseManager,
|
|
5810
6131
|
opener: deps.cliTerminalOpener,
|
|
5811
6132
|
probe: deps.cliPathProbe
|
|
5812
6133
|
});
|
|
@@ -6069,7 +6390,7 @@ async function handleUiStatic(req, res, urlPath, uiDist) {
|
|
|
6069
6390
|
}
|
|
6070
6391
|
|
|
6071
6392
|
// src/admin/version.ts
|
|
6072
|
-
var DAEMON_VERSION = true ? "0.1.
|
|
6393
|
+
var DAEMON_VERSION = true ? "0.1.8" : "0.0.0-dev";
|
|
6073
6394
|
|
|
6074
6395
|
// src/admin/AdminServer.ts
|
|
6075
6396
|
var LOOPBACK_ADDR = "127.0.0.1";
|
|
@@ -6189,6 +6510,10 @@ var AdminServer = class {
|
|
|
6189
6510
|
await handleWebhookTest(req, res);
|
|
6190
6511
|
return;
|
|
6191
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
|
+
}
|
|
6192
6517
|
if (path2.startsWith("/admin/api/")) {
|
|
6193
6518
|
await handleAdminApi(req, res, path2, this.deps);
|
|
6194
6519
|
return;
|
|
@@ -6200,8 +6525,8 @@ var AdminServer = class {
|
|
|
6200
6525
|
}
|
|
6201
6526
|
/** Constant-time bearer/header check against the configured token. */
|
|
6202
6527
|
isAuthorized(req, token) {
|
|
6203
|
-
const
|
|
6204
|
-
const bearer = typeof
|
|
6528
|
+
const header2 = req.headers["authorization"];
|
|
6529
|
+
const bearer = typeof header2 === "string" && header2.startsWith("Bearer ") ? header2.slice("Bearer ".length).trim() : void 0;
|
|
6205
6530
|
const xToken = req.headers["x-admin-token"];
|
|
6206
6531
|
const presented = bearer ?? (typeof xToken === "string" ? xToken.trim() : void 0);
|
|
6207
6532
|
return constantTimeEquals(presented, token);
|
|
@@ -6336,7 +6661,7 @@ var OAuthSessionStore = class {
|
|
|
6336
6661
|
};
|
|
6337
6662
|
|
|
6338
6663
|
// src/commands/loopbackCallback.ts
|
|
6339
|
-
import { createServer } from "http";
|
|
6664
|
+
import { createServer as createServer2 } from "http";
|
|
6340
6665
|
var LOOPBACK_HOST = "127.0.0.1";
|
|
6341
6666
|
var LOOPBACK_PORT = 1455;
|
|
6342
6667
|
var CALLBACK_PATH = "/auth/callback";
|
|
@@ -6358,7 +6683,7 @@ function awaitLoopbackCode(expectedState, timeoutMs = DEFAULT_TIMEOUT_MS, signal
|
|
|
6358
6683
|
fn();
|
|
6359
6684
|
server2.close();
|
|
6360
6685
|
};
|
|
6361
|
-
const server =
|
|
6686
|
+
const server = createServer2((req, res) => {
|
|
6362
6687
|
const url = new URL(req.url ?? "", `http://${LOOPBACK_HOST}:${LOOPBACK_PORT}`);
|
|
6363
6688
|
if (url.pathname !== CALLBACK_PATH) {
|
|
6364
6689
|
res.writeHead(404, HTML_HEADERS);
|
|
@@ -6780,7 +7105,7 @@ function safeStringify(value) {
|
|
|
6780
7105
|
}
|
|
6781
7106
|
|
|
6782
7107
|
// src/ports/JsonApiServerSettingsStore.ts
|
|
6783
|
-
import { readFileSync as readFileSync8, writeFileSync as
|
|
7108
|
+
import { readFileSync as readFileSync8, writeFileSync as writeFileSync7 } from "fs";
|
|
6784
7109
|
import { OUTBOUND_API_SERVER_CONFIG_KEY } from "@omnicross/core/outbound-api";
|
|
6785
7110
|
var JsonApiServerSettingsStore = class {
|
|
6786
7111
|
/**
|
|
@@ -6807,7 +7132,7 @@ var JsonApiServerSettingsStore = class {
|
|
|
6807
7132
|
if (key !== OUTBOUND_API_SERVER_CONFIG_KEY) return;
|
|
6808
7133
|
const file = this.readFile();
|
|
6809
7134
|
file.server = this.encryptSecrets(value);
|
|
6810
|
-
|
|
7135
|
+
writeFileSync7(this.configPath, JSON.stringify(file, null, 2) + "\n", "utf8");
|
|
6811
7136
|
}
|
|
6812
7137
|
/** Encrypt the proxy passwords + webhook + billing secrets before persisting (no-op without a box). */
|
|
6813
7138
|
encryptSecrets(config) {
|
|
@@ -7161,7 +7486,7 @@ function median(values) {
|
|
|
7161
7486
|
}
|
|
7162
7487
|
|
|
7163
7488
|
// src/ports/JsonPricingStore.ts
|
|
7164
|
-
import { existsSync as existsSync9, readFileSync as readFileSync10, renameSync as renameSync3, rmSync as
|
|
7489
|
+
import { existsSync as existsSync9, readFileSync as readFileSync10, renameSync as renameSync3, rmSync as rmSync3, writeFileSync as writeFileSync8 } from "fs";
|
|
7165
7490
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
7166
7491
|
var JsonPricingStore = class {
|
|
7167
7492
|
constructor(pricingPath) {
|
|
@@ -7302,13 +7627,13 @@ var JsonPricingStore = class {
|
|
|
7302
7627
|
writeRows(rows) {
|
|
7303
7628
|
const temporaryPath = `${this.pricingPath}.${process.pid}.${randomUUID5()}.tmp`;
|
|
7304
7629
|
try {
|
|
7305
|
-
|
|
7630
|
+
writeFileSync8(temporaryPath, JSON.stringify(rows, null, 2) + "\n", {
|
|
7306
7631
|
encoding: "utf8",
|
|
7307
7632
|
flag: "wx"
|
|
7308
7633
|
});
|
|
7309
7634
|
this.replaceFile(temporaryPath);
|
|
7310
7635
|
} finally {
|
|
7311
|
-
|
|
7636
|
+
rmSync3(temporaryPath, { force: true });
|
|
7312
7637
|
}
|
|
7313
7638
|
}
|
|
7314
7639
|
/** Isolated for deterministic failure testing; never removes the target. */
|
|
@@ -7323,7 +7648,7 @@ function isUsablePricingRow(value) {
|
|
|
7323
7648
|
}
|
|
7324
7649
|
|
|
7325
7650
|
// src/pricing/PricingRefreshScheduler.ts
|
|
7326
|
-
import { existsSync as existsSync10, readFileSync as readFileSync11, renameSync as renameSync4, writeFileSync as
|
|
7651
|
+
import { existsSync as existsSync10, readFileSync as readFileSync11, renameSync as renameSync4, writeFileSync as writeFileSync9 } from "fs";
|
|
7327
7652
|
var EMPTY_STATE2 = {
|
|
7328
7653
|
lastAttemptAt: null,
|
|
7329
7654
|
lastSuccessAt: null,
|
|
@@ -7416,7 +7741,7 @@ var PricingRefreshScheduler = class {
|
|
|
7416
7741
|
}
|
|
7417
7742
|
writeState(state) {
|
|
7418
7743
|
const temporaryPath = `${this.statePath}.tmp`;
|
|
7419
|
-
|
|
7744
|
+
writeFileSync9(temporaryPath, `${JSON.stringify(state, null, 2)}
|
|
7420
7745
|
`, "utf8");
|
|
7421
7746
|
renameSync4(temporaryPath, this.statePath);
|
|
7422
7747
|
}
|
|
@@ -7426,7 +7751,7 @@ function finiteOrNull(value) {
|
|
|
7426
7751
|
}
|
|
7427
7752
|
|
|
7428
7753
|
// src/ports/JsonVoucherDb.ts
|
|
7429
|
-
import { existsSync as existsSync11, readFileSync as readFileSync12, writeFileSync as
|
|
7754
|
+
import { existsSync as existsSync11, readFileSync as readFileSync12, writeFileSync as writeFileSync10 } from "fs";
|
|
7430
7755
|
var JsonVoucherDb = class {
|
|
7431
7756
|
constructor(vouchersPath) {
|
|
7432
7757
|
this.vouchersPath = vouchersPath;
|
|
@@ -7513,12 +7838,12 @@ var JsonVoucherDb = class {
|
|
|
7513
7838
|
}
|
|
7514
7839
|
}
|
|
7515
7840
|
writeRows(rows) {
|
|
7516
|
-
|
|
7841
|
+
writeFileSync10(this.vouchersPath, JSON.stringify(rows, null, 2) + "\n", "utf8");
|
|
7517
7842
|
}
|
|
7518
7843
|
};
|
|
7519
7844
|
|
|
7520
7845
|
// src/ports/JsonSubscriptionCredentialStore.ts
|
|
7521
|
-
import { existsSync as existsSync13, mkdirSync as mkdirSync4, readFileSync as readFileSync14, writeFileSync as
|
|
7846
|
+
import { existsSync as existsSync13, mkdirSync as mkdirSync4, readFileSync as readFileSync14, writeFileSync as writeFileSync11 } from "fs";
|
|
7522
7847
|
import { dirname as dirname6 } from "path";
|
|
7523
7848
|
import { getSharedAccountHealth as getSharedAccountHealth2 } from "@omnicross/core/pipeline/SubscriptionAccountHealth";
|
|
7524
7849
|
import { getSharedAccountAllowanceScheduling as getSharedAccountAllowanceScheduling3 } from "@omnicross/core/pipeline/AccountAllowanceScheduling";
|
|
@@ -8201,7 +8526,7 @@ var JsonSubscriptionCredentialStore = class {
|
|
|
8201
8526
|
persist(config) {
|
|
8202
8527
|
mkdirSync4(dirname6(this.tokensPath), { recursive: true });
|
|
8203
8528
|
const encrypted = encryptTokens(config, this.box);
|
|
8204
|
-
|
|
8529
|
+
writeFileSync11(this.tokensPath, JSON.stringify(encrypted, null, 2) + "\n", "utf8");
|
|
8205
8530
|
}
|
|
8206
8531
|
/**
|
|
8207
8532
|
* Read + parse `tokens.json`, tolerating a missing/corrupt file, then DECRYPT
|
|
@@ -8770,7 +9095,7 @@ import {
|
|
|
8770
9095
|
readFileSync as readFileSync15,
|
|
8771
9096
|
readdirSync,
|
|
8772
9097
|
statSync as statSync3,
|
|
8773
|
-
writeFileSync as
|
|
9098
|
+
writeFileSync as writeFileSync12
|
|
8774
9099
|
} from "fs";
|
|
8775
9100
|
import { basename, dirname as dirname7, join as join6 } from "path";
|
|
8776
9101
|
var SIDECAR_VERSION = 1;
|
|
@@ -8812,7 +9137,7 @@ function updateAuditStatsAfterAppend(auditPath, auditBytesBefore, auditBytesAfte
|
|
|
8812
9137
|
minTs: previous.minTs === null ? record.ts : Math.min(previous.minTs, record.ts),
|
|
8813
9138
|
maxTs: previous.maxTs === null ? record.ts : Math.max(previous.maxTs, record.ts)
|
|
8814
9139
|
};
|
|
8815
|
-
|
|
9140
|
+
writeFileSync12(statsPath, JSON.stringify(next), "utf8");
|
|
8816
9141
|
}
|
|
8817
9142
|
function queryCovers(stats, from, to) {
|
|
8818
9143
|
return stats.requestCount === 0 || stats.minTs !== null && stats.maxTs !== null && from <= stats.minTs && to >= stats.maxTs;
|
|
@@ -8956,7 +9281,7 @@ async function readAuditStats(auditDir, query2 = {}) {
|
|
|
8956
9281
|
total.errorCount += scanned.filtered.errorCount + (resumable?.errorCount ?? 0);
|
|
8957
9282
|
total.complete = total.complete && scanned.filtered.complete;
|
|
8958
9283
|
const current = resumable ? mergePersistedStats(resumable, scanned.all) : scanned.all;
|
|
8959
|
-
if (current.complete)
|
|
9284
|
+
if (current.complete) writeFileSync12(statsPath, JSON.stringify(current), "utf8");
|
|
8960
9285
|
} catch {
|
|
8961
9286
|
total.complete = false;
|
|
8962
9287
|
}
|
|
@@ -9518,6 +9843,78 @@ var TokenRefreshScheduler = class {
|
|
|
9518
9843
|
}
|
|
9519
9844
|
};
|
|
9520
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
|
+
|
|
9521
9918
|
// src/webhook/WebhookDispatcher.ts
|
|
9522
9919
|
import { createHmac as createHmac2 } from "crypto";
|
|
9523
9920
|
import { fetchUpstream as fetchUpstream6 } from "@omnicross/core/pipeline/upstreamFetch";
|
|
@@ -9700,7 +10097,7 @@ function buildDaemon(config, paths) {
|
|
|
9700
10097
|
new JsonAccountAllowancePersistence(defaultAccountAllowancePath(paths.configPath))
|
|
9701
10098
|
);
|
|
9702
10099
|
setSharedAccountAllowanceStore(accountAllowanceStore);
|
|
9703
|
-
|
|
10100
|
+
getSharedAccountAllowanceScheduling5().configure(
|
|
9704
10101
|
normalizeServerConfig(decryptedConfig.server).allowanceScheduling
|
|
9705
10102
|
);
|
|
9706
10103
|
const llmConfig = new ConfigFileProviderConfigSource(decryptedConfig);
|
|
@@ -9768,10 +10165,21 @@ function buildDaemon(config, paths) {
|
|
|
9768
10165
|
onRecord: (apiKeyId, costUsd, at) => keySpendTracker.add(apiKeyId, costUsd, at)
|
|
9769
10166
|
});
|
|
9770
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());
|
|
9771
10179
|
llmConfig.setReloadHook(() => apiKeyPool.invalidateCache());
|
|
9772
10180
|
const accountHealthProbeScheduler = new AccountHealthProbeScheduler(
|
|
9773
10181
|
credentialStore,
|
|
9774
|
-
|
|
10182
|
+
getSharedAccountHealth4(),
|
|
9775
10183
|
logger,
|
|
9776
10184
|
DEFAULT_ACCOUNT_PROBE
|
|
9777
10185
|
);
|
|
@@ -9818,6 +10226,7 @@ function buildDaemon(config, paths) {
|
|
|
9818
10226
|
keySpendReader: keySpendTracker,
|
|
9819
10227
|
settingsStore,
|
|
9820
10228
|
outboundApiServer,
|
|
10229
|
+
routeLeaseManager,
|
|
9821
10230
|
subscriptionAccounts,
|
|
9822
10231
|
accountAllowanceService,
|
|
9823
10232
|
allowanceRefreshScheduler: claudeAllowanceRefreshScheduler,
|
|
@@ -9910,7 +10319,7 @@ function buildDaemon(config, paths) {
|
|
|
9910
10319
|
logger,
|
|
9911
10320
|
fetchImpl: (url, init) => fetchUpstream7(url, init)
|
|
9912
10321
|
});
|
|
9913
|
-
setWebhookRuntime(webhookDispatcher,
|
|
10322
|
+
setWebhookRuntime(webhookDispatcher, getSharedAccountHealth4());
|
|
9914
10323
|
const auditWriter = new AuditWriter(auditDir, logger);
|
|
9915
10324
|
const auditPruneSweeper = new AuditPruneSweeper(auditDir, logger, DEFAULT_AUDIT_CONFIG);
|
|
9916
10325
|
setAuditRuntime(auditWriter, auditPruneSweeper);
|
|
@@ -9925,7 +10334,7 @@ function buildDaemon(config, paths) {
|
|
|
9925
10334
|
const tokenRefreshScheduler = new TokenRefreshScheduler(credentialStore, logger);
|
|
9926
10335
|
const accountHealthSweeper = new AccountHealthSweeper(
|
|
9927
10336
|
credentialStore,
|
|
9928
|
-
|
|
10337
|
+
getSharedAccountHealth4(),
|
|
9929
10338
|
logger
|
|
9930
10339
|
);
|
|
9931
10340
|
return {
|
|
@@ -9934,6 +10343,7 @@ function buildDaemon(config, paths) {
|
|
|
9934
10343
|
keyDb,
|
|
9935
10344
|
settingsStore,
|
|
9936
10345
|
providerProxy,
|
|
10346
|
+
routeLeaseManager,
|
|
9937
10347
|
outboundApiServer,
|
|
9938
10348
|
apiKeyPool,
|
|
9939
10349
|
autoDisableStore,
|
|
@@ -10049,32 +10459,17 @@ async function runLaunch(argv, deps) {
|
|
|
10049
10459
|
await daemon.llmConfig.ready();
|
|
10050
10460
|
await daemon.providerProxy.start();
|
|
10051
10461
|
} catch (err5) {
|
|
10052
|
-
daemon
|
|
10053
|
-
daemon.tokenRefreshScheduler.dispose();
|
|
10054
|
-
daemon.claudeAllowanceRefreshScheduler.dispose();
|
|
10055
|
-
daemon.accountHealthSweeper.dispose();
|
|
10056
|
-
daemon.accountHealthProbeScheduler.dispose();
|
|
10057
|
-
daemon.auditPruneSweeper.dispose();
|
|
10058
|
-
daemon.billingRetrySweeper.dispose();
|
|
10059
|
-
daemon.pricingRefreshScheduler.dispose();
|
|
10462
|
+
await shutdownLaunchDaemon(daemon);
|
|
10060
10463
|
throw err5;
|
|
10061
10464
|
}
|
|
10062
10465
|
let launch;
|
|
10063
10466
|
try {
|
|
10064
|
-
launch = await buildLaunchConfig(cli, daemon
|
|
10467
|
+
launch = await buildLaunchConfig(cli, daemon, {
|
|
10065
10468
|
providerId: values.provider,
|
|
10066
10469
|
model: values.model
|
|
10067
10470
|
});
|
|
10068
10471
|
} catch (err5) {
|
|
10069
|
-
await daemon
|
|
10070
|
-
daemon.apiKeyPool.dispose();
|
|
10071
|
-
daemon.tokenRefreshScheduler.dispose();
|
|
10072
|
-
daemon.claudeAllowanceRefreshScheduler.dispose();
|
|
10073
|
-
daemon.accountHealthSweeper.dispose();
|
|
10074
|
-
daemon.accountHealthProbeScheduler.dispose();
|
|
10075
|
-
daemon.auditPruneSweeper.dispose();
|
|
10076
|
-
daemon.billingRetrySweeper.dispose();
|
|
10077
|
-
daemon.pricingRefreshScheduler.dispose();
|
|
10472
|
+
await shutdownLaunchDaemon(daemon);
|
|
10078
10473
|
throw err5;
|
|
10079
10474
|
}
|
|
10080
10475
|
try {
|
|
@@ -10093,21 +10488,40 @@ async function runLaunch(argv, deps) {
|
|
|
10093
10488
|
cwd: values.cwd
|
|
10094
10489
|
});
|
|
10095
10490
|
} finally {
|
|
10096
|
-
|
|
10097
|
-
|
|
10098
|
-
|
|
10099
|
-
|
|
10100
|
-
|
|
10101
|
-
|
|
10102
|
-
|
|
10103
|
-
|
|
10104
|
-
|
|
10105
|
-
|
|
10106
|
-
|
|
10107
|
-
|
|
10108
|
-
|
|
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
|
+
}
|
|
10109
10523
|
const common = {
|
|
10110
|
-
llmConfig,
|
|
10524
|
+
llmConfig: daemon.llmConfig,
|
|
10111
10525
|
providerId: opts.providerId,
|
|
10112
10526
|
model: opts.model,
|
|
10113
10527
|
// Stable, bounded session id — pool failover (poolseam) fires on launch
|
|
@@ -10115,10 +10529,6 @@ async function buildLaunchConfig(cli, llmConfig, opts) {
|
|
|
10115
10529
|
sessionId: `launch:${cli}`
|
|
10116
10530
|
};
|
|
10117
10531
|
switch (cli) {
|
|
10118
|
-
case "claude":
|
|
10119
|
-
return buildClaudeCliLaunchConfig2(common);
|
|
10120
|
-
case "codex":
|
|
10121
|
-
return buildCodexLaunchConfig2(common);
|
|
10122
10532
|
case "gemini":
|
|
10123
10533
|
return buildGeminiCliLaunchConfig2(common);
|
|
10124
10534
|
case "qwen":
|
|
@@ -10131,6 +10541,18 @@ async function buildLaunchConfig(cli, llmConfig, opts) {
|
|
|
10131
10541
|
}
|
|
10132
10542
|
}
|
|
10133
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
|
+
}
|
|
10134
10556
|
function spawnCliInherit(plan) {
|
|
10135
10557
|
return new Promise((resolve3, reject) => {
|
|
10136
10558
|
const child = spawn2(plan.command, plan.args, {
|
|
@@ -10177,7 +10599,7 @@ import { createInterface } from "readline";
|
|
|
10177
10599
|
import { parseArgs as parseArgs5 } from "util";
|
|
10178
10600
|
import { fetchUpstream as fetchUpstream8, setUpstreamProxyResolver as setUpstreamProxyResolver2 } from "@omnicross/core/pipeline/upstreamFetch";
|
|
10179
10601
|
import { claudeOAuth as claudeOAuth3, codexOAuth as codexOAuth3, geminiOAuth as geminiOAuth3 } from "@omnicross/subscriptions";
|
|
10180
|
-
var
|
|
10602
|
+
var PROVIDERS2 = ["claude", "codex", "gemini"];
|
|
10181
10603
|
async function runLogin(argv, deps) {
|
|
10182
10604
|
const { values, positionals } = parseArgs5({
|
|
10183
10605
|
args: argv,
|
|
@@ -10191,10 +10613,10 @@ async function runLogin(argv, deps) {
|
|
|
10191
10613
|
});
|
|
10192
10614
|
const provider = positionals[0];
|
|
10193
10615
|
if (!provider) {
|
|
10194
|
-
throw new Error(`login: a <provider> is required (one of ${
|
|
10616
|
+
throw new Error(`login: a <provider> is required (one of ${PROVIDERS2.join("|")})`);
|
|
10195
10617
|
}
|
|
10196
10618
|
if (!isLoginProvider(provider)) {
|
|
10197
|
-
throw new Error(`login: unknown provider '${provider}' (expected ${
|
|
10619
|
+
throw new Error(`login: unknown provider '${provider}' (expected ${PROVIDERS2.join("|")})`);
|
|
10198
10620
|
}
|
|
10199
10621
|
if (!values.config) {
|
|
10200
10622
|
throw new Error("login: --config <path> is required");
|
|
@@ -10300,7 +10722,7 @@ async function loginGemini(store, deps, exchangeFetch, label) {
|
|
|
10300
10722
|
return expiresAt;
|
|
10301
10723
|
}
|
|
10302
10724
|
function isLoginProvider(value) {
|
|
10303
|
-
return
|
|
10725
|
+
return PROVIDERS2.includes(value);
|
|
10304
10726
|
}
|
|
10305
10727
|
async function presentUrl(authUrl, deps) {
|
|
10306
10728
|
console.info("Open this URL in your browser to authorize:");
|
|
@@ -10346,7 +10768,7 @@ function promptPaste(prompt) {
|
|
|
10346
10768
|
}
|
|
10347
10769
|
|
|
10348
10770
|
// src/commands/providers.ts
|
|
10349
|
-
import { randomUUID as
|
|
10771
|
+
import { randomUUID as randomUUID7 } from "crypto";
|
|
10350
10772
|
import { parseArgs as parseArgs6 } from "util";
|
|
10351
10773
|
async function runProviders(argv) {
|
|
10352
10774
|
const { values, positionals } = parseArgs6({
|
|
@@ -10468,7 +10890,7 @@ function providersAddKey(configPath, providerId, opts) {
|
|
|
10468
10890
|
const cfg = loadConfig(configPath);
|
|
10469
10891
|
const row = cfg.providers.find((p) => p.id === providerId);
|
|
10470
10892
|
if (!row) throw new Error(`providers add-key: unknown provider '${providerId}'`);
|
|
10471
|
-
const entry = { id:
|
|
10893
|
+
const entry = { id: randomUUID7(), apiKey: opts.key };
|
|
10472
10894
|
if (opts.label) entry.label = opts.label;
|
|
10473
10895
|
if (opts.weight !== void 0) {
|
|
10474
10896
|
const w = Number(opts.weight);
|
|
@@ -10496,7 +10918,7 @@ function providersRmKey(configPath, providerId, keyId) {
|
|
|
10496
10918
|
}
|
|
10497
10919
|
|
|
10498
10920
|
// src/commands/secrets.ts
|
|
10499
|
-
import { existsSync as existsSync21, readFileSync as readFileSync18, writeFileSync as
|
|
10921
|
+
import { existsSync as existsSync21, readFileSync as readFileSync18, writeFileSync as writeFileSync13 } from "fs";
|
|
10500
10922
|
import { parseArgs as parseArgs7 } from "util";
|
|
10501
10923
|
async function runSecrets(argv) {
|
|
10502
10924
|
const { values, positionals } = parseArgs7({
|
|
@@ -10670,7 +11092,7 @@ function secretsDecrypt(args) {
|
|
|
10670
11092
|
}
|
|
10671
11093
|
saveConfig(args.config, cfg);
|
|
10672
11094
|
if (tokensPlain) {
|
|
10673
|
-
|
|
11095
|
+
writeFileSync13(tokensPath, JSON.stringify(tokensPlain, null, 2) + "\n", "utf8");
|
|
10674
11096
|
}
|
|
10675
11097
|
console.info(`Decrypted secrets to plaintext in ${args.config}` + tokensSuffix(args.config));
|
|
10676
11098
|
}
|
|
@@ -10714,7 +11136,7 @@ function writeTokensEncrypted(tokensPath, plain, box) {
|
|
|
10714
11136
|
{ updatedAt: "", ...plain },
|
|
10715
11137
|
box
|
|
10716
11138
|
);
|
|
10717
|
-
|
|
11139
|
+
writeFileSync13(tokensPath, JSON.stringify(encrypted, null, 2) + "\n", "utf8");
|
|
10718
11140
|
}
|
|
10719
11141
|
var TOKEN_FIELDS2 = {
|
|
10720
11142
|
claude: ["accessToken", "refreshToken"],
|
|
@@ -10743,8 +11165,8 @@ function tokensSuffix(configPath) {
|
|
|
10743
11165
|
// src/commands/start.ts
|
|
10744
11166
|
import { parseArgs as parseArgs8 } from "util";
|
|
10745
11167
|
import { loadServerConfig as loadServerConfig3 } from "@omnicross/core/outbound-api";
|
|
10746
|
-
import { getSharedAccountHealth as
|
|
10747
|
-
import { getSharedAccountAllowanceScheduling as
|
|
11168
|
+
import { getSharedAccountHealth as getSharedAccountHealth5 } from "@omnicross/core/pipeline/SubscriptionAccountHealth";
|
|
11169
|
+
import { getSharedAccountAllowanceScheduling as getSharedAccountAllowanceScheduling6 } from "@omnicross/core/pipeline/AccountAllowanceScheduling";
|
|
10748
11170
|
|
|
10749
11171
|
// src/identity/identityRuntime.ts
|
|
10750
11172
|
import { getSharedIdentityStore as getSharedIdentityStore3 } from "@omnicross/core/provider-proxy/identity/SubscriptionIdentityStore";
|
|
@@ -10804,11 +11226,11 @@ async function runStart(argv) {
|
|
|
10804
11226
|
await daemon.llmConfig.ready();
|
|
10805
11227
|
await daemon.providerProxy.start();
|
|
10806
11228
|
const serverConfig = await loadServerConfig3(daemon.settingsStore);
|
|
10807
|
-
|
|
11229
|
+
getSharedAccountHealth5().configure({
|
|
10808
11230
|
overloadEnabled: serverConfig.accountHealth?.overloadCooldownEnabled,
|
|
10809
11231
|
overloadTtlMs: serverConfig.accountHealth?.overloadCooldownMs
|
|
10810
11232
|
});
|
|
10811
|
-
|
|
11233
|
+
getSharedAccountAllowanceScheduling6().configure(serverConfig.allowanceScheduling);
|
|
10812
11234
|
daemon.claudeAllowanceRefreshScheduler.configure(serverConfig.allowanceScheduling);
|
|
10813
11235
|
await daemon.outboundApiServer.applyConfig({
|
|
10814
11236
|
enabled: true,
|