@omnicross/daemon 0.1.7 → 0.1.9
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 +559 -99
- package/dist/cli.js +584 -114
- package/dist/index.cjs +498 -52
- package/dist/index.d.cts +20 -7
- package/dist/index.d.ts +20 -7
- package/dist/index.js +523 -65
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -497,6 +497,35 @@ function validateApiKeys(raw) {
|
|
|
497
497
|
}
|
|
498
498
|
return out.length > 0 ? out : void 0;
|
|
499
499
|
}
|
|
500
|
+
var THINK_LEVELS = /* @__PURE__ */ new Set([
|
|
501
|
+
"none",
|
|
502
|
+
"minimal",
|
|
503
|
+
"low",
|
|
504
|
+
"medium",
|
|
505
|
+
"high",
|
|
506
|
+
"xhigh",
|
|
507
|
+
"max"
|
|
508
|
+
]);
|
|
509
|
+
function validateThinkingLevels(raw) {
|
|
510
|
+
if (!Array.isArray(raw)) return void 0;
|
|
511
|
+
if (!raw.every((level) => typeof level === "string" && THINK_LEVELS.has(level))) {
|
|
512
|
+
return void 0;
|
|
513
|
+
}
|
|
514
|
+
return [...raw];
|
|
515
|
+
}
|
|
516
|
+
function validateThinkingTokenLimit(raw) {
|
|
517
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return void 0;
|
|
518
|
+
const bounds = raw;
|
|
519
|
+
const min = bounds["min"];
|
|
520
|
+
const max = bounds["max"];
|
|
521
|
+
if (typeof min !== "number" || !Number.isFinite(min) || !Number.isInteger(min) || min < 0) {
|
|
522
|
+
return void 0;
|
|
523
|
+
}
|
|
524
|
+
if (typeof max !== "number" || !Number.isFinite(max) || !Number.isInteger(max) || max < min) {
|
|
525
|
+
return void 0;
|
|
526
|
+
}
|
|
527
|
+
return { min, max };
|
|
528
|
+
}
|
|
500
529
|
function validateModelConfigs(raw) {
|
|
501
530
|
if (!Array.isArray(raw)) return void 0;
|
|
502
531
|
const out = [];
|
|
@@ -511,6 +540,10 @@ function validateModelConfigs(raw) {
|
|
|
511
540
|
if (typeof m["enabled"] === "boolean") entry.enabled = m["enabled"];
|
|
512
541
|
if (typeof m["vision"] === "boolean") entry.vision = m["vision"];
|
|
513
542
|
if (typeof m["reasoning"] === "boolean") entry.reasoning = m["reasoning"];
|
|
543
|
+
const thinkingLevels = validateThinkingLevels(m["thinkingLevels"]);
|
|
544
|
+
if (thinkingLevels) entry.thinkingLevels = thinkingLevels;
|
|
545
|
+
const thinkingTokenLimit = validateThinkingTokenLimit(m["thinkingTokenLimit"]);
|
|
546
|
+
if (thinkingTokenLimit) entry.thinkingTokenLimit = thinkingTokenLimit;
|
|
514
547
|
out.push(entry);
|
|
515
548
|
}
|
|
516
549
|
return out.length > 0 ? out : void 0;
|
|
@@ -1750,15 +1783,15 @@ async function keysRevoke(db, id) {
|
|
|
1750
1783
|
|
|
1751
1784
|
// src/commands/launch.ts
|
|
1752
1785
|
import { spawn as spawn2 } from "child_process";
|
|
1786
|
+
import { randomUUID as randomUUID6 } from "crypto";
|
|
1753
1787
|
import { existsSync as existsSync20 } from "fs";
|
|
1754
1788
|
import { delimiter as delimiter2, join as join12 } from "path";
|
|
1755
1789
|
import { parseArgs as parseArgs4 } from "util";
|
|
1756
1790
|
import {
|
|
1757
1791
|
buildChatCliLaunchConfig as buildChatCliLaunchConfig2,
|
|
1758
|
-
buildClaudeCliLaunchConfig as buildClaudeCliLaunchConfig2,
|
|
1759
|
-
buildCodexLaunchConfig as buildCodexLaunchConfig2,
|
|
1760
1792
|
buildGeminiCliLaunchConfig as buildGeminiCliLaunchConfig2
|
|
1761
1793
|
} from "@omnicross/cli-launcher";
|
|
1794
|
+
import { ROUTE_LEASE_REQUEST_SCHEMA as ROUTE_LEASE_REQUEST_SCHEMA2 } from "@omnicross/core/provider-proxy";
|
|
1762
1795
|
|
|
1763
1796
|
// src/bootstrap.ts
|
|
1764
1797
|
import { accessSync, constants as fsConstants, existsSync as existsSync19 } from "fs";
|
|
@@ -1774,7 +1807,7 @@ import {
|
|
|
1774
1807
|
normalizeServerConfig
|
|
1775
1808
|
} from "@omnicross/core/outbound-api";
|
|
1776
1809
|
import { setSubscriptionRegistryForOutbound } from "@omnicross/core/outbound-api/subscriptionRegistryPort";
|
|
1777
|
-
import { getSharedAccountHealth as
|
|
1810
|
+
import { getSharedAccountHealth as getSharedAccountHealth4 } from "@omnicross/core/pipeline/SubscriptionAccountHealth";
|
|
1778
1811
|
import {
|
|
1779
1812
|
__resetSharedAccountAllowanceStoreForTests,
|
|
1780
1813
|
AccountAllowanceStore as AccountAllowanceStore3,
|
|
@@ -1782,15 +1815,18 @@ import {
|
|
|
1782
1815
|
} from "@omnicross/core/pipeline/AccountAllowanceStore";
|
|
1783
1816
|
import {
|
|
1784
1817
|
__resetSharedAccountAllowanceSchedulingForTests,
|
|
1785
|
-
getSharedAccountAllowanceScheduling as
|
|
1818
|
+
getSharedAccountAllowanceScheduling as getSharedAccountAllowanceScheduling5
|
|
1786
1819
|
} from "@omnicross/core/pipeline/AccountAllowanceScheduling";
|
|
1787
1820
|
import { fetchUpstream as fetchUpstream7, setUpstreamProxyResolver } from "@omnicross/core/pipeline/upstreamFetch";
|
|
1788
1821
|
import { __resetSharedIdentityStoreForTests } from "@omnicross/core/provider-proxy/identity/SubscriptionIdentityStore";
|
|
1789
1822
|
import { setGeminiCodeAssistResolver } from "@omnicross/core/ports/gemini-code-assist-resolver";
|
|
1790
1823
|
import {
|
|
1791
1824
|
__resetProviderProxyForTests,
|
|
1792
|
-
getProviderProxy
|
|
1825
|
+
getProviderProxy,
|
|
1826
|
+
RouteLeaseManager,
|
|
1827
|
+
RouteLeaseTargetResolver
|
|
1793
1828
|
} from "@omnicross/core/provider-proxy";
|
|
1829
|
+
import { routeLeaseDescriptorPort } from "@omnicross/cli-launcher";
|
|
1794
1830
|
import { KeySpendTracker } from "@omnicross/core/outbound-api";
|
|
1795
1831
|
import { PricingEngine, UsageRecorder } from "@omnicross/core/usage";
|
|
1796
1832
|
import {
|
|
@@ -2496,6 +2532,93 @@ async function handleWebhookTest(req, res) {
|
|
|
2496
2532
|
res.end(JSON.stringify({ result }));
|
|
2497
2533
|
}
|
|
2498
2534
|
|
|
2535
|
+
// src/admin/routeLeaseApi.ts
|
|
2536
|
+
import {
|
|
2537
|
+
isLoopbackAddress,
|
|
2538
|
+
normalizeRouteLeaseTtl,
|
|
2539
|
+
ROUTE_LEASE_CAPABILITIES,
|
|
2540
|
+
RouteLeaseError
|
|
2541
|
+
} from "@omnicross/core/provider-proxy";
|
|
2542
|
+
var MAX_BODY_BYTES = 64 * 1024;
|
|
2543
|
+
var SAFE_LEASE_ID = /^[A-Za-z0-9-]{1,128}$/u;
|
|
2544
|
+
async function readJson(req) {
|
|
2545
|
+
const chunks = [];
|
|
2546
|
+
let bytes = 0;
|
|
2547
|
+
for await (const chunk of req) {
|
|
2548
|
+
const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
|
|
2549
|
+
bytes += buffer.length;
|
|
2550
|
+
if (bytes > MAX_BODY_BYTES) throw new RouteLeaseError("invalid_request", "request body is too large");
|
|
2551
|
+
chunks.push(buffer);
|
|
2552
|
+
}
|
|
2553
|
+
if (chunks.length === 0) return {};
|
|
2554
|
+
try {
|
|
2555
|
+
return JSON.parse(Buffer.concat(chunks).toString("utf8"));
|
|
2556
|
+
} catch {
|
|
2557
|
+
throw new RouteLeaseError("invalid_request", "request body is not valid JSON");
|
|
2558
|
+
}
|
|
2559
|
+
}
|
|
2560
|
+
function json(res, status, body, noStore = false) {
|
|
2561
|
+
res.statusCode = status;
|
|
2562
|
+
res.setHeader("Content-Type", "application/json");
|
|
2563
|
+
if (noStore) res.setHeader("Cache-Control", "no-store");
|
|
2564
|
+
res.end(JSON.stringify(body));
|
|
2565
|
+
}
|
|
2566
|
+
function leaseId(value) {
|
|
2567
|
+
if (!value || !SAFE_LEASE_ID.test(value)) throw new RouteLeaseError("invalid_request", "lease id is invalid");
|
|
2568
|
+
return value;
|
|
2569
|
+
}
|
|
2570
|
+
function header(req, name) {
|
|
2571
|
+
const value = req.headers[name.toLowerCase()];
|
|
2572
|
+
return Array.isArray(value) ? value[0] : value;
|
|
2573
|
+
}
|
|
2574
|
+
function writeError(res, error, noStore) {
|
|
2575
|
+
const safe = error instanceof RouteLeaseError ? error : new RouteLeaseError("upstream_unavailable", "route lease operation failed safely");
|
|
2576
|
+
if (safe.retryAfterSeconds !== void 0) res.setHeader("Retry-After", String(safe.retryAfterSeconds));
|
|
2577
|
+
json(res, safe.status, safe.toResponse(), noStore);
|
|
2578
|
+
}
|
|
2579
|
+
async function handleRouteLeaseApi(req, res, path2, deps) {
|
|
2580
|
+
const method = (req.method ?? "GET").toUpperCase();
|
|
2581
|
+
const noStore = method === "POST" && (path2 === "/admin/api/route-leases" || path2.endsWith("/renew"));
|
|
2582
|
+
try {
|
|
2583
|
+
if (!isLoopbackAddress(req.socket.remoteAddress)) {
|
|
2584
|
+
throw new RouteLeaseError("control_unauthorized", "route lease control plane is loopback only");
|
|
2585
|
+
}
|
|
2586
|
+
const manager = deps.routeLeaseManager;
|
|
2587
|
+
if (!manager) throw new RouteLeaseError("daemon_not_ready", "route lease manager is unavailable");
|
|
2588
|
+
const base = "/admin/api/route-leases";
|
|
2589
|
+
const suffix = path2.slice(base.length).replace(/^\/+|\/+$/gu, "");
|
|
2590
|
+
const segments = suffix ? suffix.split("/") : [];
|
|
2591
|
+
if (segments.length === 1 && segments[0] === "capabilities") {
|
|
2592
|
+
if (method !== "GET" && method !== "HEAD") throw new RouteLeaseError("invalid_request", "method is not allowed");
|
|
2593
|
+
return json(res, 200, ROUTE_LEASE_CAPABILITIES);
|
|
2594
|
+
}
|
|
2595
|
+
if (segments.length === 0) {
|
|
2596
|
+
if (method === "GET") return json(res, 200, { leases: manager.list() });
|
|
2597
|
+
if (method === "POST") {
|
|
2598
|
+
const outcome = await manager.createFromRequest(await readJson(req), header(req, "idempotency-key"));
|
|
2599
|
+
return json(res, outcome.created ? 201 : 200, outcome.result, true);
|
|
2600
|
+
}
|
|
2601
|
+
throw new RouteLeaseError("invalid_request", "method is not allowed");
|
|
2602
|
+
}
|
|
2603
|
+
const id = leaseId(segments[0]);
|
|
2604
|
+
if (segments.length === 1) {
|
|
2605
|
+
if (method === "GET") return json(res, 200, manager.get(id));
|
|
2606
|
+
if (method === "DELETE") return json(res, 200, manager.release(id));
|
|
2607
|
+
throw new RouteLeaseError("invalid_request", "method is not allowed");
|
|
2608
|
+
}
|
|
2609
|
+
if (segments.length === 2 && segments[1] === "renew" && method === "POST") {
|
|
2610
|
+
const body = await readJson(req);
|
|
2611
|
+
const ttl = normalizeRouteLeaseTtl(
|
|
2612
|
+
body && typeof body === "object" && !Array.isArray(body) ? body.ttlSeconds : void 0
|
|
2613
|
+
);
|
|
2614
|
+
return json(res, 200, manager.renew(id, ttl), true);
|
|
2615
|
+
}
|
|
2616
|
+
throw new RouteLeaseError("lease_not_found", "route lease endpoint was not found");
|
|
2617
|
+
} catch (error) {
|
|
2618
|
+
writeError(res, error, noStore);
|
|
2619
|
+
}
|
|
2620
|
+
}
|
|
2621
|
+
|
|
2499
2622
|
// src/admin/adminApi.ts
|
|
2500
2623
|
import http from "http";
|
|
2501
2624
|
import {
|
|
@@ -3054,7 +3177,9 @@ async function exchangeGemini(code, codeVerifier, exchangeFetch) {
|
|
|
3054
3177
|
// src/admin/cliLaunch.ts
|
|
3055
3178
|
import { exec, spawn } from "child_process";
|
|
3056
3179
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
3057
|
-
import { existsSync as existsSync6 } from "fs";
|
|
3180
|
+
import { chmodSync as chmodSync3, existsSync as existsSync6, mkdtempSync, rmSync as rmSync2, writeFileSync as writeFileSync6 } from "fs";
|
|
3181
|
+
import { createServer } from "net";
|
|
3182
|
+
import { tmpdir } from "os";
|
|
3058
3183
|
import { delimiter, join as join4 } from "path";
|
|
3059
3184
|
import {
|
|
3060
3185
|
buildChatCliLaunchConfig,
|
|
@@ -3062,6 +3187,33 @@ import {
|
|
|
3062
3187
|
buildCodexLaunchConfig,
|
|
3063
3188
|
buildGeminiCliLaunchConfig
|
|
3064
3189
|
} from "@omnicross/cli-launcher";
|
|
3190
|
+
import {
|
|
3191
|
+
ROUTE_LEASE_REQUEST_SCHEMA,
|
|
3192
|
+
RouteLeaseError as RouteLeaseError2
|
|
3193
|
+
} from "@omnicross/core/provider-proxy";
|
|
3194
|
+
|
|
3195
|
+
// src/routeLeaseRenewal.ts
|
|
3196
|
+
var TERMINAL_LEASE_TTL_SECONDS = 600;
|
|
3197
|
+
var TERMINAL_LEASE_RENEW_INTERVAL_MS = 5 * 60 * 1e3;
|
|
3198
|
+
var TERMINAL_LEASE_MAX_LIFETIME_MS = 24 * 60 * 60 * 1e3;
|
|
3199
|
+
function startTerminalLeaseRenewal(manager, leaseId2) {
|
|
3200
|
+
const stopAt = Date.now() + TERMINAL_LEASE_MAX_LIFETIME_MS;
|
|
3201
|
+
const timer = setInterval(() => {
|
|
3202
|
+
if (Date.now() >= stopAt) {
|
|
3203
|
+
clearInterval(timer);
|
|
3204
|
+
return;
|
|
3205
|
+
}
|
|
3206
|
+
try {
|
|
3207
|
+
manager.renew(leaseId2, TERMINAL_LEASE_TTL_SECONDS);
|
|
3208
|
+
} catch {
|
|
3209
|
+
clearInterval(timer);
|
|
3210
|
+
}
|
|
3211
|
+
}, TERMINAL_LEASE_RENEW_INTERVAL_MS);
|
|
3212
|
+
timer.unref?.();
|
|
3213
|
+
return () => clearInterval(timer);
|
|
3214
|
+
}
|
|
3215
|
+
|
|
3216
|
+
// src/admin/cliLaunch.ts
|
|
3065
3217
|
var LAUNCHABLE_CLIS = [
|
|
3066
3218
|
{ id: "claude", displayName: "Claude Code", command: "claude" },
|
|
3067
3219
|
{ id: "codex", displayName: "Codex CLI", command: "codex" },
|
|
@@ -3142,34 +3294,183 @@ async function buildLaunchEnv(cli, llmConfig, target) {
|
|
|
3142
3294
|
function shq(s) {
|
|
3143
3295
|
return `'${s.replace(/'/g, `'\\''`)}'`;
|
|
3144
3296
|
}
|
|
3145
|
-
var
|
|
3297
|
+
var MAC_TERMINAL_BOOTSTRAP_SOURCE = `
|
|
3298
|
+
'use strict';
|
|
3299
|
+
const fs = require('node:fs');
|
|
3300
|
+
const net = require('node:net');
|
|
3301
|
+
const { spawn } = require('node:child_process');
|
|
3302
|
+
const [socketPath, launchDir, cwd, command, ...args] = process.argv.slice(2);
|
|
3303
|
+
let payload = '';
|
|
3304
|
+
const socket = net.createConnection(socketPath);
|
|
3305
|
+
socket.setEncoding('utf8');
|
|
3306
|
+
socket.on('data', (chunk) => { payload += chunk; });
|
|
3307
|
+
socket.on('end', () => {
|
|
3308
|
+
const descriptor = JSON.parse(payload);
|
|
3309
|
+
if (!descriptor || Array.isArray(descriptor) || Object.values(descriptor).some((value) => typeof value !== 'string')) {
|
|
3310
|
+
throw new Error('invalid terminal launch descriptor');
|
|
3311
|
+
}
|
|
3312
|
+
try { fs.rmSync(launchDir, { recursive: true, force: true }); } catch {}
|
|
3313
|
+
const child = spawn(command, args, {
|
|
3314
|
+
cwd: cwd || undefined,
|
|
3315
|
+
env: { ...process.env, ...descriptor },
|
|
3316
|
+
stdio: 'inherit',
|
|
3317
|
+
});
|
|
3318
|
+
child.on('error', (error) => { console.error(error.message); process.exitCode = 1; });
|
|
3319
|
+
child.on('exit', (code, signal) => {
|
|
3320
|
+
if (signal) process.kill(process.pid, signal);
|
|
3321
|
+
else process.exitCode = code == null ? 1 : code;
|
|
3322
|
+
});
|
|
3323
|
+
});
|
|
3324
|
+
socket.on('error', (error) => { console.error(error.message); process.exitCode = 1; });
|
|
3325
|
+
`;
|
|
3326
|
+
var MAC_TERMINAL_IPC_TIMEOUT_MS = 12e4;
|
|
3327
|
+
function openTerminal({ cli, command, extraArgs, env, cwd, platform, onFailure }, spawnProcess = spawn, macIpc = {}) {
|
|
3146
3328
|
const childEnv = { ...process.env, ...env };
|
|
3147
3329
|
if (platform === "win32") {
|
|
3148
3330
|
const args = ["/c", "start", `"omnicross ${cli}"`];
|
|
3149
3331
|
if (cwd) args.push("/D", `"${cwd}"`);
|
|
3150
3332
|
args.push("cmd", "/k", command, ...extraArgs);
|
|
3151
|
-
|
|
3333
|
+
spawnProcess(process.env["ComSpec"] || "cmd.exe", args, {
|
|
3152
3334
|
env: childEnv,
|
|
3153
3335
|
windowsVerbatimArguments: true,
|
|
3154
3336
|
detached: true,
|
|
3155
3337
|
stdio: "ignore"
|
|
3156
3338
|
}).unref();
|
|
3157
|
-
return
|
|
3339
|
+
return () => {
|
|
3340
|
+
};
|
|
3158
3341
|
}
|
|
3159
|
-
const exportLine = Object.entries(env).map(([k, v]) => `export ${k}=${shq(v)}`).join("; ");
|
|
3160
3342
|
const runLine = [command, ...extraArgs].map(shq).join(" ");
|
|
3161
|
-
const script = `${
|
|
3343
|
+
const script = `${cwd ? `cd ${shq(cwd)}; ` : ""}${runLine}`;
|
|
3162
3344
|
if (platform === "darwin") {
|
|
3163
|
-
const
|
|
3164
|
-
|
|
3165
|
-
|
|
3345
|
+
const launchDir = mkdtempSync(join4(tmpdir(), "omnicross-terminal-"));
|
|
3346
|
+
const commandFile = join4(launchDir, "launch.command");
|
|
3347
|
+
const bootstrapFile = join4(launchDir, "bootstrap.cjs");
|
|
3348
|
+
const socketPath = macIpc.socketPath ?? join4(launchDir, "descriptor.sock");
|
|
3349
|
+
const openerEnv = { ...process.env };
|
|
3350
|
+
for (const key of Object.keys(env)) delete openerEnv[key];
|
|
3351
|
+
let claimed = false;
|
|
3352
|
+
let cleaned = false;
|
|
3353
|
+
let failureNotified = false;
|
|
3354
|
+
let timer;
|
|
3355
|
+
const notifyFailure = () => {
|
|
3356
|
+
cleanup();
|
|
3357
|
+
if (failureNotified) return;
|
|
3358
|
+
failureNotified = true;
|
|
3359
|
+
try {
|
|
3360
|
+
onFailure?.();
|
|
3361
|
+
} catch {
|
|
3362
|
+
}
|
|
3363
|
+
};
|
|
3364
|
+
const handleLaunchFailure = () => {
|
|
3365
|
+
if (claimed) cleanup();
|
|
3366
|
+
else notifyFailure();
|
|
3367
|
+
};
|
|
3368
|
+
const sockets = /* @__PURE__ */ new Set();
|
|
3369
|
+
const server = createServer((socket) => {
|
|
3370
|
+
socket.unref();
|
|
3371
|
+
sockets.add(socket);
|
|
3372
|
+
socket.once("close", () => sockets.delete(socket));
|
|
3373
|
+
try {
|
|
3374
|
+
macIpc.onAccepted?.(socket);
|
|
3375
|
+
} catch {
|
|
3376
|
+
cleanup();
|
|
3377
|
+
return;
|
|
3378
|
+
}
|
|
3379
|
+
if (claimed || cleaned) {
|
|
3380
|
+
socket.destroy();
|
|
3381
|
+
return;
|
|
3382
|
+
}
|
|
3383
|
+
claimed = true;
|
|
3384
|
+
try {
|
|
3385
|
+
macIpc.onClaimed?.();
|
|
3386
|
+
if (cleaned) return;
|
|
3387
|
+
socket.end(JSON.stringify(env), cleanup);
|
|
3388
|
+
} catch {
|
|
3389
|
+
cleanup();
|
|
3390
|
+
}
|
|
3391
|
+
});
|
|
3392
|
+
const cleanup = () => {
|
|
3393
|
+
if (!cleaned) {
|
|
3394
|
+
cleaned = true;
|
|
3395
|
+
if (timer) clearTimeout(timer);
|
|
3396
|
+
for (const socket of sockets) socket.destroy();
|
|
3397
|
+
sockets.clear();
|
|
3398
|
+
try {
|
|
3399
|
+
server.close();
|
|
3400
|
+
} catch {
|
|
3401
|
+
}
|
|
3402
|
+
}
|
|
3403
|
+
try {
|
|
3404
|
+
if (macIpc.removeArtifacts) {
|
|
3405
|
+
macIpc.removeArtifacts(launchDir);
|
|
3406
|
+
} else {
|
|
3407
|
+
rmSync2(launchDir, {
|
|
3408
|
+
recursive: true,
|
|
3409
|
+
force: true,
|
|
3410
|
+
maxRetries: 3,
|
|
3411
|
+
retryDelay: 20
|
|
3412
|
+
});
|
|
3413
|
+
}
|
|
3414
|
+
} catch {
|
|
3415
|
+
}
|
|
3416
|
+
};
|
|
3417
|
+
try {
|
|
3418
|
+
writeFileSync6(bootstrapFile, MAC_TERMINAL_BOOTSTRAP_SOURCE, { encoding: "utf8", mode: 448 });
|
|
3419
|
+
writeFileSync6(commandFile, `#!/bin/bash
|
|
3420
|
+
rm -f -- "$0"
|
|
3421
|
+
exec ${shq(process.execPath)} ${shq(bootstrapFile)} ${shq(socketPath)} ${shq(launchDir)} ${shq(cwd ?? "")} ${runLine}
|
|
3422
|
+
`, {
|
|
3423
|
+
encoding: "utf8",
|
|
3424
|
+
mode: 448
|
|
3425
|
+
});
|
|
3426
|
+
chmodSync3(commandFile, 448);
|
|
3427
|
+
chmodSync3(bootstrapFile, 448);
|
|
3428
|
+
server.once("error", handleLaunchFailure);
|
|
3429
|
+
server.listen(socketPath, () => {
|
|
3430
|
+
if (cleaned) return;
|
|
3431
|
+
try {
|
|
3432
|
+
macIpc.onListening?.();
|
|
3433
|
+
if (cleaned) return;
|
|
3434
|
+
if (process.platform !== "win32") chmodSync3(socketPath, 384);
|
|
3435
|
+
const opener = spawnProcess("open", ["-n", "-a", "Terminal", commandFile], {
|
|
3436
|
+
env: openerEnv,
|
|
3437
|
+
detached: true,
|
|
3438
|
+
stdio: "ignore"
|
|
3439
|
+
});
|
|
3440
|
+
opener.once("error", handleLaunchFailure);
|
|
3441
|
+
opener.unref();
|
|
3442
|
+
server.unref();
|
|
3443
|
+
} catch {
|
|
3444
|
+
handleLaunchFailure();
|
|
3445
|
+
}
|
|
3446
|
+
});
|
|
3447
|
+
timer = setTimeout(handleLaunchFailure, macIpc.timeoutMs ?? MAC_TERMINAL_IPC_TIMEOUT_MS);
|
|
3448
|
+
timer.unref?.();
|
|
3449
|
+
return cleanup;
|
|
3450
|
+
} catch (error) {
|
|
3451
|
+
cleanup();
|
|
3452
|
+
throw error;
|
|
3453
|
+
}
|
|
3166
3454
|
}
|
|
3167
|
-
|
|
3455
|
+
spawnProcess("x-terminal-emulator", ["-e", "bash", "-lc", `${script}; exec bash`], {
|
|
3456
|
+
env: childEnv,
|
|
3168
3457
|
detached: true,
|
|
3169
3458
|
stdio: "ignore"
|
|
3170
3459
|
}).unref();
|
|
3171
|
-
|
|
3460
|
+
return () => {
|
|
3461
|
+
};
|
|
3462
|
+
}
|
|
3463
|
+
var defaultTerminalOpener = (input) => openTerminal(input);
|
|
3172
3464
|
var sessions = /* @__PURE__ */ new Map();
|
|
3465
|
+
function resetCliSessions() {
|
|
3466
|
+
for (const s of sessions.values()) {
|
|
3467
|
+
try {
|
|
3468
|
+
s.onSessionEnd();
|
|
3469
|
+
} catch {
|
|
3470
|
+
}
|
|
3471
|
+
}
|
|
3472
|
+
sessions.clear();
|
|
3473
|
+
}
|
|
3173
3474
|
function errBody(message) {
|
|
3174
3475
|
return { error: { type: "admin_api_error", message } };
|
|
3175
3476
|
}
|
|
@@ -3224,29 +3525,81 @@ async function handleCliLaunch(cli, body, ctx) {
|
|
|
3224
3525
|
} catch (err5) {
|
|
3225
3526
|
return { status: 400, body: errBody(err5 instanceof Error ? err5.message : "no launch target") };
|
|
3226
3527
|
}
|
|
3528
|
+
const id = randomUUID2();
|
|
3529
|
+
let leaseId2;
|
|
3227
3530
|
let launch;
|
|
3228
3531
|
try {
|
|
3229
|
-
|
|
3532
|
+
if ((cli === "claude" || cli === "codex") && ctx.routeLeaseManager) {
|
|
3533
|
+
const outcome = await ctx.routeLeaseManager.createFromRequest({
|
|
3534
|
+
schemaVersion: ROUTE_LEASE_REQUEST_SCHEMA,
|
|
3535
|
+
consumer: "omnicross-terminal",
|
|
3536
|
+
runtime: cli,
|
|
3537
|
+
upstream: { kind: "provider", providerId: target.providerId },
|
|
3538
|
+
model: target.model,
|
|
3539
|
+
execution: { sessionId: id }
|
|
3540
|
+
}, `omnicross-terminal:${id}`);
|
|
3541
|
+
leaseId2 = outcome.result.leaseId;
|
|
3542
|
+
const stopRenewal = startTerminalLeaseRenewal(ctx.routeLeaseManager, leaseId2);
|
|
3543
|
+
launch = {
|
|
3544
|
+
env: outcome.result.launch.env,
|
|
3545
|
+
extraArgs: outcome.result.launch.extraArgs,
|
|
3546
|
+
onSessionEnd: () => {
|
|
3547
|
+
stopRenewal();
|
|
3548
|
+
ctx.routeLeaseManager?.release(outcome.result.leaseId);
|
|
3549
|
+
}
|
|
3550
|
+
};
|
|
3551
|
+
} else {
|
|
3552
|
+
launch = await buildLaunchEnv(cli, ctx.llmConfig, target);
|
|
3553
|
+
}
|
|
3230
3554
|
} catch (err5) {
|
|
3231
|
-
|
|
3555
|
+
const status = err5 instanceof RouteLeaseError2 ? err5.status : 400;
|
|
3556
|
+
return { status, body: errBody(err5 instanceof Error ? err5.message : "failed to build launch env") };
|
|
3232
3557
|
}
|
|
3233
3558
|
const cwd = typeof body["cwd"] === "string" && body["cwd"].trim() ? body["cwd"].trim() : void 0;
|
|
3234
3559
|
const opener = ctx.opener ?? defaultTerminalOpener;
|
|
3560
|
+
let openerCleanup;
|
|
3561
|
+
let ended = false;
|
|
3562
|
+
let published = false;
|
|
3563
|
+
const onSessionEnd = () => {
|
|
3564
|
+
if (ended) return;
|
|
3565
|
+
ended = true;
|
|
3566
|
+
if (published) sessions.delete(id);
|
|
3567
|
+
try {
|
|
3568
|
+
openerCleanup?.();
|
|
3569
|
+
} finally {
|
|
3570
|
+
launch.onSessionEnd();
|
|
3571
|
+
}
|
|
3572
|
+
};
|
|
3235
3573
|
try {
|
|
3236
|
-
opener({
|
|
3574
|
+
const cleanup = opener({
|
|
3575
|
+
cli,
|
|
3576
|
+
command: meta.command,
|
|
3577
|
+
extraArgs: launch.extraArgs ?? [],
|
|
3578
|
+
env: launch.env,
|
|
3579
|
+
cwd,
|
|
3580
|
+
platform,
|
|
3581
|
+
onFailure: onSessionEnd
|
|
3582
|
+
});
|
|
3583
|
+
if (cleanup) openerCleanup = cleanup;
|
|
3237
3584
|
} catch (err5) {
|
|
3238
|
-
|
|
3585
|
+
onSessionEnd();
|
|
3239
3586
|
return { status: 500, body: errBody(err5 instanceof Error ? err5.message : "failed to open terminal") };
|
|
3240
3587
|
}
|
|
3241
|
-
|
|
3588
|
+
if (ended) {
|
|
3589
|
+
openerCleanup?.();
|
|
3590
|
+
return { status: 500, body: errBody("failed to open terminal") };
|
|
3591
|
+
}
|
|
3242
3592
|
sessions.set(id, {
|
|
3243
3593
|
id,
|
|
3244
3594
|
cli,
|
|
3245
3595
|
providerId: target.providerId,
|
|
3246
3596
|
model: target.model,
|
|
3597
|
+
...leaseId2 ? { leaseId: leaseId2 } : {},
|
|
3247
3598
|
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3248
|
-
onSessionEnd
|
|
3599
|
+
onSessionEnd
|
|
3249
3600
|
});
|
|
3601
|
+
published = true;
|
|
3602
|
+
if (ended) sessions.delete(id);
|
|
3250
3603
|
return { status: 200, body: { sessionId: id, providerId: target.providerId, model: target.model } };
|
|
3251
3604
|
}
|
|
3252
3605
|
|
|
@@ -4133,7 +4486,7 @@ function sealPack(bundleJson, passphrase) {
|
|
|
4133
4486
|
cipher.setAAD(aadFor(PACK_MAGIC, PACK_VERSION, KDF_ALGORITHM));
|
|
4134
4487
|
const ciphertext = Buffer.concat([cipher.update(bundleJson, "utf8"), cipher.final()]);
|
|
4135
4488
|
const tag = cipher.getAuthTag();
|
|
4136
|
-
const
|
|
4489
|
+
const header2 = {
|
|
4137
4490
|
magic: PACK_MAGIC,
|
|
4138
4491
|
v: PACK_VERSION,
|
|
4139
4492
|
kdf: KDF_ALGORITHM,
|
|
@@ -4144,7 +4497,7 @@ function sealPack(bundleJson, passphrase) {
|
|
|
4144
4497
|
iv: iv.toString("base64"),
|
|
4145
4498
|
tag: tag.toString("base64")
|
|
4146
4499
|
};
|
|
4147
|
-
return `${PACK_PREFIX}${toB64Url(JSON.stringify(
|
|
4500
|
+
return `${PACK_PREFIX}${toB64Url(JSON.stringify(header2))}.${ciphertext.toString("base64")}`;
|
|
4148
4501
|
}
|
|
4149
4502
|
function parsePack(packString) {
|
|
4150
4503
|
if (typeof packString !== "string" || !packString.startsWith(PACK_PREFIX)) {
|
|
@@ -4155,28 +4508,28 @@ function parsePack(packString) {
|
|
|
4155
4508
|
if (dot < 0) throw new PackAuthError("migration pack is malformed (missing body)");
|
|
4156
4509
|
const headerB64Url = rest.slice(0, dot);
|
|
4157
4510
|
const ctB64 = rest.slice(dot + 1);
|
|
4158
|
-
let
|
|
4511
|
+
let header2;
|
|
4159
4512
|
try {
|
|
4160
|
-
|
|
4513
|
+
header2 = JSON.parse(fromB64Url(headerB64Url));
|
|
4161
4514
|
} catch {
|
|
4162
4515
|
throw new PackAuthError("migration pack is malformed (unreadable header)");
|
|
4163
4516
|
}
|
|
4164
|
-
if (!
|
|
4517
|
+
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
4518
|
throw new PackAuthError("migration pack is malformed (unsupported header)");
|
|
4166
4519
|
}
|
|
4167
4520
|
const ciphertext = Buffer.from(ctB64, "base64");
|
|
4168
|
-
return { header, ciphertext };
|
|
4521
|
+
return { header: header2, ciphertext };
|
|
4169
4522
|
}
|
|
4170
4523
|
function openPack(packString, passphrase) {
|
|
4171
4524
|
assertPassphraseStrength(passphrase);
|
|
4172
|
-
const { header, ciphertext } = parsePack(packString);
|
|
4173
|
-
const salt = Buffer.from(
|
|
4174
|
-
const iv = Buffer.from(
|
|
4175
|
-
const tag = Buffer.from(
|
|
4525
|
+
const { header: header2, ciphertext } = parsePack(packString);
|
|
4526
|
+
const salt = Buffer.from(header2.salt, "base64");
|
|
4527
|
+
const iv = Buffer.from(header2.iv, "base64");
|
|
4528
|
+
const tag = Buffer.from(header2.tag, "base64");
|
|
4176
4529
|
if (iv.length !== IV_BYTES2 || tag.length !== TAG_BYTES2) {
|
|
4177
4530
|
throw new PackAuthError("migration pack is malformed (invalid iv/tag length)");
|
|
4178
4531
|
}
|
|
4179
|
-
const key = deriveKey(passphrase, salt,
|
|
4532
|
+
const key = deriveKey(passphrase, salt, header2.N, header2.r, header2.p);
|
|
4180
4533
|
const decipher = createDecipheriv2("aes-256-gcm", key, iv);
|
|
4181
4534
|
decipher.setAAD(aadFor(PACK_MAGIC, PACK_VERSION, KDF_ALGORITHM));
|
|
4182
4535
|
decipher.setAuthTag(tag);
|
|
@@ -4512,10 +4865,10 @@ function writeJson2(res, status, body) {
|
|
|
4512
4865
|
res.writeHead(status, { "Content-Type": "application/json" });
|
|
4513
4866
|
res.end(JSON.stringify(body));
|
|
4514
4867
|
}
|
|
4515
|
-
function
|
|
4868
|
+
function writeError2(res, status, message) {
|
|
4516
4869
|
writeJson2(res, status, { error: { type: "account_allowance_error", message } });
|
|
4517
4870
|
}
|
|
4518
|
-
function
|
|
4871
|
+
function readJson2(req) {
|
|
4519
4872
|
return new Promise((resolve3, reject) => {
|
|
4520
4873
|
const chunks = [];
|
|
4521
4874
|
req.on("data", (chunk) => chunks.push(Buffer.from(chunk)));
|
|
@@ -4541,10 +4894,10 @@ function allowanceProvider(value) {
|
|
|
4541
4894
|
return value === "claude" || value === "codex" ? value : null;
|
|
4542
4895
|
}
|
|
4543
4896
|
async function handleAccountAllowanceApi(req, res, method, rest, service) {
|
|
4544
|
-
if (!service) return
|
|
4897
|
+
if (!service) return writeError2(res, 501, "account allowance service is not available");
|
|
4545
4898
|
if (method === "GET" && rest.length === 1 && rest[0] === "scheduling") {
|
|
4546
4899
|
if (!service.getSchedulingStatus) {
|
|
4547
|
-
return
|
|
4900
|
+
return writeError2(res, 501, "allowance scheduling diagnostics are not available");
|
|
4548
4901
|
}
|
|
4549
4902
|
return writeJson2(res, 200, { scheduling: service.getSchedulingStatus() });
|
|
4550
4903
|
}
|
|
@@ -4552,27 +4905,27 @@ async function handleAccountAllowanceApi(req, res, method, rest, service) {
|
|
|
4552
4905
|
const params = query(req);
|
|
4553
4906
|
const pathProvider = rest.length >= 2 ? rest[0] : null;
|
|
4554
4907
|
const providerId = allowanceProvider(pathProvider ?? params.get("providerId") ?? params.get("provider"));
|
|
4555
|
-
if (providerId === null) return
|
|
4908
|
+
if (providerId === null) return writeError2(res, 400, "providerId must be claude or codex");
|
|
4556
4909
|
const accountId = rest.length >= 2 ? rest[1] : params.get("accountId") ?? void 0;
|
|
4557
4910
|
const allowances = await service.list({ providerId, accountId });
|
|
4558
4911
|
return writeJson2(res, 200, { allowances });
|
|
4559
4912
|
}
|
|
4560
4913
|
if (method === "POST" && rest[0] === "refresh") {
|
|
4561
|
-
const body = await
|
|
4914
|
+
const body = await readJson2(req);
|
|
4562
4915
|
const requestedProvider = allowanceProvider(
|
|
4563
4916
|
typeof body["providerId"] === "string" ? body["providerId"] : "claude"
|
|
4564
4917
|
);
|
|
4565
4918
|
if (requestedProvider !== "claude") {
|
|
4566
|
-
return
|
|
4919
|
+
return writeError2(res, 400, "only Claude allowances support explicit refresh");
|
|
4567
4920
|
}
|
|
4568
4921
|
const accountId = typeof body["accountId"] === "string" && body["accountId"].trim() ? body["accountId"].trim() : void 0;
|
|
4569
4922
|
const allowances = await service.refreshClaude(accountId);
|
|
4570
4923
|
if (accountId && allowances.length === 0) {
|
|
4571
|
-
return
|
|
4924
|
+
return writeError2(res, 404, `Claude account '${accountId}' not found`);
|
|
4572
4925
|
}
|
|
4573
4926
|
return writeJson2(res, 200, { allowances });
|
|
4574
4927
|
}
|
|
4575
|
-
return
|
|
4928
|
+
return writeError2(res, 405, `method ${method} not allowed on account allowances`);
|
|
4576
4929
|
}
|
|
4577
4930
|
|
|
4578
4931
|
// src/admin/adminApi.ts
|
|
@@ -5150,6 +5503,12 @@ function parseModelConfigsInput(raw, existing) {
|
|
|
5150
5503
|
else if (typeof prior?.vision === "boolean") entry.vision = prior.vision;
|
|
5151
5504
|
if (typeof m["reasoning"] === "boolean") entry.reasoning = m["reasoning"];
|
|
5152
5505
|
else if (typeof prior?.reasoning === "boolean") entry.reasoning = prior.reasoning;
|
|
5506
|
+
const thinkingLevels = validateThinkingLevels(m["thinkingLevels"]);
|
|
5507
|
+
if (thinkingLevels) entry.thinkingLevels = thinkingLevels;
|
|
5508
|
+
else if (prior?.thinkingLevels) entry.thinkingLevels = prior.thinkingLevels;
|
|
5509
|
+
const thinkingTokenLimit = validateThinkingTokenLimit(m["thinkingTokenLimit"]);
|
|
5510
|
+
if (thinkingTokenLimit) entry.thinkingTokenLimit = thinkingTokenLimit;
|
|
5511
|
+
else if (prior?.thinkingTokenLimit) entry.thinkingTokenLimit = prior.thinkingTokenLimit;
|
|
5153
5512
|
out.push(entry);
|
|
5154
5513
|
}
|
|
5155
5514
|
return out.length > 0 ? out : void 0;
|
|
@@ -5807,6 +6166,7 @@ async function handleCli(req, res, method, rest, deps) {
|
|
|
5807
6166
|
const result = await handleCliLaunch(cli, body, {
|
|
5808
6167
|
llmConfig: deps.llmConfig,
|
|
5809
6168
|
providers,
|
|
6169
|
+
routeLeaseManager: deps.routeLeaseManager,
|
|
5810
6170
|
opener: deps.cliTerminalOpener,
|
|
5811
6171
|
probe: deps.cliPathProbe
|
|
5812
6172
|
});
|
|
@@ -6069,7 +6429,7 @@ async function handleUiStatic(req, res, urlPath, uiDist) {
|
|
|
6069
6429
|
}
|
|
6070
6430
|
|
|
6071
6431
|
// src/admin/version.ts
|
|
6072
|
-
var DAEMON_VERSION = true ? "0.1.
|
|
6432
|
+
var DAEMON_VERSION = true ? "0.1.9" : "0.0.0-dev";
|
|
6073
6433
|
|
|
6074
6434
|
// src/admin/AdminServer.ts
|
|
6075
6435
|
var LOOPBACK_ADDR = "127.0.0.1";
|
|
@@ -6189,6 +6549,10 @@ var AdminServer = class {
|
|
|
6189
6549
|
await handleWebhookTest(req, res);
|
|
6190
6550
|
return;
|
|
6191
6551
|
}
|
|
6552
|
+
if (path2 === "/admin/api/route-leases" || path2.startsWith("/admin/api/route-leases/")) {
|
|
6553
|
+
await handleRouteLeaseApi(req, res, path2, this.deps);
|
|
6554
|
+
return;
|
|
6555
|
+
}
|
|
6192
6556
|
if (path2.startsWith("/admin/api/")) {
|
|
6193
6557
|
await handleAdminApi(req, res, path2, this.deps);
|
|
6194
6558
|
return;
|
|
@@ -6200,8 +6564,8 @@ var AdminServer = class {
|
|
|
6200
6564
|
}
|
|
6201
6565
|
/** Constant-time bearer/header check against the configured token. */
|
|
6202
6566
|
isAuthorized(req, token) {
|
|
6203
|
-
const
|
|
6204
|
-
const bearer = typeof
|
|
6567
|
+
const header2 = req.headers["authorization"];
|
|
6568
|
+
const bearer = typeof header2 === "string" && header2.startsWith("Bearer ") ? header2.slice("Bearer ".length).trim() : void 0;
|
|
6205
6569
|
const xToken = req.headers["x-admin-token"];
|
|
6206
6570
|
const presented = bearer ?? (typeof xToken === "string" ? xToken.trim() : void 0);
|
|
6207
6571
|
return constantTimeEquals(presented, token);
|
|
@@ -6336,7 +6700,7 @@ var OAuthSessionStore = class {
|
|
|
6336
6700
|
};
|
|
6337
6701
|
|
|
6338
6702
|
// src/commands/loopbackCallback.ts
|
|
6339
|
-
import { createServer } from "http";
|
|
6703
|
+
import { createServer as createServer2 } from "http";
|
|
6340
6704
|
var LOOPBACK_HOST = "127.0.0.1";
|
|
6341
6705
|
var LOOPBACK_PORT = 1455;
|
|
6342
6706
|
var CALLBACK_PATH = "/auth/callback";
|
|
@@ -6358,7 +6722,7 @@ function awaitLoopbackCode(expectedState, timeoutMs = DEFAULT_TIMEOUT_MS, signal
|
|
|
6358
6722
|
fn();
|
|
6359
6723
|
server2.close();
|
|
6360
6724
|
};
|
|
6361
|
-
const server =
|
|
6725
|
+
const server = createServer2((req, res) => {
|
|
6362
6726
|
const url = new URL(req.url ?? "", `http://${LOOPBACK_HOST}:${LOOPBACK_PORT}`);
|
|
6363
6727
|
if (url.pathname !== CALLBACK_PATH) {
|
|
6364
6728
|
res.writeHead(404, HTML_HEADERS);
|
|
@@ -6609,6 +6973,15 @@ function toLLMProvider(row) {
|
|
|
6609
6973
|
api_base_url: row.baseUrl,
|
|
6610
6974
|
api_key: resolvePreferredApiKey(row),
|
|
6611
6975
|
models,
|
|
6976
|
+
modelConfigs: row.modelConfigs?.map((config) => ({
|
|
6977
|
+
id: config.id,
|
|
6978
|
+
name: config.name ?? config.id,
|
|
6979
|
+
enabled: config.enabled ?? true,
|
|
6980
|
+
vision: config.vision,
|
|
6981
|
+
reasoning: config.reasoning,
|
|
6982
|
+
thinkingLevels: config.thinkingLevels,
|
|
6983
|
+
thinkingTokenLimit: config.thinkingTokenLimit
|
|
6984
|
+
})),
|
|
6612
6985
|
enabled: true,
|
|
6613
6986
|
transformer,
|
|
6614
6987
|
// app-parity-2 child 3: POPULATE the coding-plan endpoint onto the core
|
|
@@ -6780,7 +7153,7 @@ function safeStringify(value) {
|
|
|
6780
7153
|
}
|
|
6781
7154
|
|
|
6782
7155
|
// src/ports/JsonApiServerSettingsStore.ts
|
|
6783
|
-
import { readFileSync as readFileSync8, writeFileSync as
|
|
7156
|
+
import { readFileSync as readFileSync8, writeFileSync as writeFileSync7 } from "fs";
|
|
6784
7157
|
import { OUTBOUND_API_SERVER_CONFIG_KEY } from "@omnicross/core/outbound-api";
|
|
6785
7158
|
var JsonApiServerSettingsStore = class {
|
|
6786
7159
|
/**
|
|
@@ -6807,7 +7180,7 @@ var JsonApiServerSettingsStore = class {
|
|
|
6807
7180
|
if (key !== OUTBOUND_API_SERVER_CONFIG_KEY) return;
|
|
6808
7181
|
const file = this.readFile();
|
|
6809
7182
|
file.server = this.encryptSecrets(value);
|
|
6810
|
-
|
|
7183
|
+
writeFileSync7(this.configPath, JSON.stringify(file, null, 2) + "\n", "utf8");
|
|
6811
7184
|
}
|
|
6812
7185
|
/** Encrypt the proxy passwords + webhook + billing secrets before persisting (no-op without a box). */
|
|
6813
7186
|
encryptSecrets(config) {
|
|
@@ -7161,7 +7534,7 @@ function median(values) {
|
|
|
7161
7534
|
}
|
|
7162
7535
|
|
|
7163
7536
|
// src/ports/JsonPricingStore.ts
|
|
7164
|
-
import { existsSync as existsSync9, readFileSync as readFileSync10, renameSync as renameSync3, rmSync as
|
|
7537
|
+
import { existsSync as existsSync9, readFileSync as readFileSync10, renameSync as renameSync3, rmSync as rmSync3, writeFileSync as writeFileSync8 } from "fs";
|
|
7165
7538
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
7166
7539
|
var JsonPricingStore = class {
|
|
7167
7540
|
constructor(pricingPath) {
|
|
@@ -7302,13 +7675,13 @@ var JsonPricingStore = class {
|
|
|
7302
7675
|
writeRows(rows) {
|
|
7303
7676
|
const temporaryPath = `${this.pricingPath}.${process.pid}.${randomUUID5()}.tmp`;
|
|
7304
7677
|
try {
|
|
7305
|
-
|
|
7678
|
+
writeFileSync8(temporaryPath, JSON.stringify(rows, null, 2) + "\n", {
|
|
7306
7679
|
encoding: "utf8",
|
|
7307
7680
|
flag: "wx"
|
|
7308
7681
|
});
|
|
7309
7682
|
this.replaceFile(temporaryPath);
|
|
7310
7683
|
} finally {
|
|
7311
|
-
|
|
7684
|
+
rmSync3(temporaryPath, { force: true });
|
|
7312
7685
|
}
|
|
7313
7686
|
}
|
|
7314
7687
|
/** Isolated for deterministic failure testing; never removes the target. */
|
|
@@ -7323,7 +7696,7 @@ function isUsablePricingRow(value) {
|
|
|
7323
7696
|
}
|
|
7324
7697
|
|
|
7325
7698
|
// src/pricing/PricingRefreshScheduler.ts
|
|
7326
|
-
import { existsSync as existsSync10, readFileSync as readFileSync11, renameSync as renameSync4, writeFileSync as
|
|
7699
|
+
import { existsSync as existsSync10, readFileSync as readFileSync11, renameSync as renameSync4, writeFileSync as writeFileSync9 } from "fs";
|
|
7327
7700
|
var EMPTY_STATE2 = {
|
|
7328
7701
|
lastAttemptAt: null,
|
|
7329
7702
|
lastSuccessAt: null,
|
|
@@ -7416,7 +7789,7 @@ var PricingRefreshScheduler = class {
|
|
|
7416
7789
|
}
|
|
7417
7790
|
writeState(state) {
|
|
7418
7791
|
const temporaryPath = `${this.statePath}.tmp`;
|
|
7419
|
-
|
|
7792
|
+
writeFileSync9(temporaryPath, `${JSON.stringify(state, null, 2)}
|
|
7420
7793
|
`, "utf8");
|
|
7421
7794
|
renameSync4(temporaryPath, this.statePath);
|
|
7422
7795
|
}
|
|
@@ -7426,7 +7799,7 @@ function finiteOrNull(value) {
|
|
|
7426
7799
|
}
|
|
7427
7800
|
|
|
7428
7801
|
// src/ports/JsonVoucherDb.ts
|
|
7429
|
-
import { existsSync as existsSync11, readFileSync as readFileSync12, writeFileSync as
|
|
7802
|
+
import { existsSync as existsSync11, readFileSync as readFileSync12, writeFileSync as writeFileSync10 } from "fs";
|
|
7430
7803
|
var JsonVoucherDb = class {
|
|
7431
7804
|
constructor(vouchersPath) {
|
|
7432
7805
|
this.vouchersPath = vouchersPath;
|
|
@@ -7513,12 +7886,12 @@ var JsonVoucherDb = class {
|
|
|
7513
7886
|
}
|
|
7514
7887
|
}
|
|
7515
7888
|
writeRows(rows) {
|
|
7516
|
-
|
|
7889
|
+
writeFileSync10(this.vouchersPath, JSON.stringify(rows, null, 2) + "\n", "utf8");
|
|
7517
7890
|
}
|
|
7518
7891
|
};
|
|
7519
7892
|
|
|
7520
7893
|
// src/ports/JsonSubscriptionCredentialStore.ts
|
|
7521
|
-
import { existsSync as existsSync13, mkdirSync as mkdirSync4, readFileSync as readFileSync14, writeFileSync as
|
|
7894
|
+
import { existsSync as existsSync13, mkdirSync as mkdirSync4, readFileSync as readFileSync14, writeFileSync as writeFileSync11 } from "fs";
|
|
7522
7895
|
import { dirname as dirname6 } from "path";
|
|
7523
7896
|
import { getSharedAccountHealth as getSharedAccountHealth2 } from "@omnicross/core/pipeline/SubscriptionAccountHealth";
|
|
7524
7897
|
import { getSharedAccountAllowanceScheduling as getSharedAccountAllowanceScheduling3 } from "@omnicross/core/pipeline/AccountAllowanceScheduling";
|
|
@@ -8201,7 +8574,7 @@ var JsonSubscriptionCredentialStore = class {
|
|
|
8201
8574
|
persist(config) {
|
|
8202
8575
|
mkdirSync4(dirname6(this.tokensPath), { recursive: true });
|
|
8203
8576
|
const encrypted = encryptTokens(config, this.box);
|
|
8204
|
-
|
|
8577
|
+
writeFileSync11(this.tokensPath, JSON.stringify(encrypted, null, 2) + "\n", "utf8");
|
|
8205
8578
|
}
|
|
8206
8579
|
/**
|
|
8207
8580
|
* Read + parse `tokens.json`, tolerating a missing/corrupt file, then DECRYPT
|
|
@@ -8770,7 +9143,7 @@ import {
|
|
|
8770
9143
|
readFileSync as readFileSync15,
|
|
8771
9144
|
readdirSync,
|
|
8772
9145
|
statSync as statSync3,
|
|
8773
|
-
writeFileSync as
|
|
9146
|
+
writeFileSync as writeFileSync12
|
|
8774
9147
|
} from "fs";
|
|
8775
9148
|
import { basename, dirname as dirname7, join as join6 } from "path";
|
|
8776
9149
|
var SIDECAR_VERSION = 1;
|
|
@@ -8812,7 +9185,7 @@ function updateAuditStatsAfterAppend(auditPath, auditBytesBefore, auditBytesAfte
|
|
|
8812
9185
|
minTs: previous.minTs === null ? record.ts : Math.min(previous.minTs, record.ts),
|
|
8813
9186
|
maxTs: previous.maxTs === null ? record.ts : Math.max(previous.maxTs, record.ts)
|
|
8814
9187
|
};
|
|
8815
|
-
|
|
9188
|
+
writeFileSync12(statsPath, JSON.stringify(next), "utf8");
|
|
8816
9189
|
}
|
|
8817
9190
|
function queryCovers(stats, from, to) {
|
|
8818
9191
|
return stats.requestCount === 0 || stats.minTs !== null && stats.maxTs !== null && from <= stats.minTs && to >= stats.maxTs;
|
|
@@ -8956,7 +9329,7 @@ async function readAuditStats(auditDir, query2 = {}) {
|
|
|
8956
9329
|
total.errorCount += scanned.filtered.errorCount + (resumable?.errorCount ?? 0);
|
|
8957
9330
|
total.complete = total.complete && scanned.filtered.complete;
|
|
8958
9331
|
const current = resumable ? mergePersistedStats(resumable, scanned.all) : scanned.all;
|
|
8959
|
-
if (current.complete)
|
|
9332
|
+
if (current.complete) writeFileSync12(statsPath, JSON.stringify(current), "utf8");
|
|
8960
9333
|
} catch {
|
|
8961
9334
|
total.complete = false;
|
|
8962
9335
|
}
|
|
@@ -9518,6 +9891,78 @@ var TokenRefreshScheduler = class {
|
|
|
9518
9891
|
}
|
|
9519
9892
|
};
|
|
9520
9893
|
|
|
9894
|
+
// src/routeLeaseSubscriptionPreflight.ts
|
|
9895
|
+
import {
|
|
9896
|
+
RouteLeaseError as RouteLeaseError3
|
|
9897
|
+
} from "@omnicross/core/provider-proxy";
|
|
9898
|
+
import { getSharedAccountAllowanceScheduling as getSharedAccountAllowanceScheduling4 } from "@omnicross/core/pipeline/AccountAllowanceScheduling";
|
|
9899
|
+
import { getSharedAccountHealth as getSharedAccountHealth3 } from "@omnicross/core/pipeline/SubscriptionAccountHealth";
|
|
9900
|
+
import { accountSupportsModel } from "@omnicross/subscriptions/scheduler/accountModelMap";
|
|
9901
|
+
var PROVIDERS = /* @__PURE__ */ new Set(["claude", "codex", "gemini", "opencodego"]);
|
|
9902
|
+
function accountArray(config, providerId) {
|
|
9903
|
+
const record = config;
|
|
9904
|
+
const key = `${providerId}Accounts`;
|
|
9905
|
+
const accounts = record[key];
|
|
9906
|
+
if (Array.isArray(accounts)) return accounts;
|
|
9907
|
+
const legacy = record[providerId];
|
|
9908
|
+
if (!legacy || typeof legacy !== "object") return [];
|
|
9909
|
+
const activeKey = `active${providerId[0].toUpperCase()}${providerId.slice(1)}AccountId`;
|
|
9910
|
+
return [{ id: String(record[activeKey] ?? "active"), enabled: true, tokens: legacy }];
|
|
9911
|
+
}
|
|
9912
|
+
function hasCredential(providerId, account) {
|
|
9913
|
+
const tokens = account.tokens;
|
|
9914
|
+
if (providerId === "opencodego") return typeof tokens.apiKey === "string" && tokens.apiKey.length > 0;
|
|
9915
|
+
return typeof tokens.accessToken === "string" && tokens.accessToken.length > 0;
|
|
9916
|
+
}
|
|
9917
|
+
function safeProviderId(value) {
|
|
9918
|
+
if (!PROVIDERS.has(value)) {
|
|
9919
|
+
throw new RouteLeaseError3("upstream_not_found", "subscription provider was not found");
|
|
9920
|
+
}
|
|
9921
|
+
return value;
|
|
9922
|
+
}
|
|
9923
|
+
function createRouteLeaseSubscriptionPreflight(credentials) {
|
|
9924
|
+
return {
|
|
9925
|
+
async assertAvailable(upstream, model) {
|
|
9926
|
+
const providerId = safeProviderId(upstream.providerId);
|
|
9927
|
+
const config = await credentials.getFullConfig();
|
|
9928
|
+
const all = accountArray(config, providerId);
|
|
9929
|
+
if (all.length === 0) {
|
|
9930
|
+
throw new RouteLeaseError3("upstream_unavailable", "subscription provider has no configured account");
|
|
9931
|
+
}
|
|
9932
|
+
let bounded = all;
|
|
9933
|
+
if (upstream.kind === "account") {
|
|
9934
|
+
bounded = all.filter((account) => account.id === upstream.accountId);
|
|
9935
|
+
} else if (upstream.kind === "account-group") {
|
|
9936
|
+
bounded = all.filter((account) => account.group?.trim() === upstream.group);
|
|
9937
|
+
}
|
|
9938
|
+
if (bounded.length === 0) {
|
|
9939
|
+
throw new RouteLeaseError3("upstream_not_found", "the selected subscription resource was not found");
|
|
9940
|
+
}
|
|
9941
|
+
const modelEligible = bounded.filter(
|
|
9942
|
+
(account) => accountSupportsModel(account.supportedModels, model)
|
|
9943
|
+
);
|
|
9944
|
+
if (modelEligible.length === 0) {
|
|
9945
|
+
throw new RouteLeaseError3("model_not_configured", "model is not supported by the selected subscription resource");
|
|
9946
|
+
}
|
|
9947
|
+
const credentialEligible = modelEligible.filter(
|
|
9948
|
+
(account) => account.enabled !== false && hasCredential(providerId, account)
|
|
9949
|
+
);
|
|
9950
|
+
const health2 = getSharedAccountHealth3();
|
|
9951
|
+
const allowance = getSharedAccountAllowanceScheduling4();
|
|
9952
|
+
const candidates = credentialEligible.filter(
|
|
9953
|
+
(account) => health2.isSchedulable(providerId, account.id) && allowance.preview(providerId, account.id, account.priority ?? 50).schedulable
|
|
9954
|
+
);
|
|
9955
|
+
if (candidates.length > 0) return;
|
|
9956
|
+
if (upstream.kind === "account") {
|
|
9957
|
+
throw new RouteLeaseError3("upstream_unavailable", "the selected subscription account is unavailable");
|
|
9958
|
+
}
|
|
9959
|
+
throw new RouteLeaseError3("upstream_exhausted", "the selected subscription pool has no eligible account", {
|
|
9960
|
+
retryAfterSeconds: 30
|
|
9961
|
+
});
|
|
9962
|
+
}
|
|
9963
|
+
};
|
|
9964
|
+
}
|
|
9965
|
+
|
|
9521
9966
|
// src/webhook/WebhookDispatcher.ts
|
|
9522
9967
|
import { createHmac as createHmac2 } from "crypto";
|
|
9523
9968
|
import { fetchUpstream as fetchUpstream6 } from "@omnicross/core/pipeline/upstreamFetch";
|
|
@@ -9700,7 +10145,7 @@ function buildDaemon(config, paths) {
|
|
|
9700
10145
|
new JsonAccountAllowancePersistence(defaultAccountAllowancePath(paths.configPath))
|
|
9701
10146
|
);
|
|
9702
10147
|
setSharedAccountAllowanceStore(accountAllowanceStore);
|
|
9703
|
-
|
|
10148
|
+
getSharedAccountAllowanceScheduling5().configure(
|
|
9704
10149
|
normalizeServerConfig(decryptedConfig.server).allowanceScheduling
|
|
9705
10150
|
);
|
|
9706
10151
|
const llmConfig = new ConfigFileProviderConfigSource(decryptedConfig);
|
|
@@ -9768,10 +10213,21 @@ function buildDaemon(config, paths) {
|
|
|
9768
10213
|
onRecord: (apiKeyId, costUsd, at) => keySpendTracker.add(apiKeyId, costUsd, at)
|
|
9769
10214
|
});
|
|
9770
10215
|
const providerProxy = getProviderProxy({ llmConfig, apiKeyPool, usageRecorder });
|
|
10216
|
+
const routeLeaseManager = new RouteLeaseManager(
|
|
10217
|
+
providerProxy,
|
|
10218
|
+
new RouteLeaseTargetResolver(llmConfig, {
|
|
10219
|
+
providerKeys: apiKeyPool,
|
|
10220
|
+
subscriptions: createRouteLeaseSubscriptionPreflight(credentialStore)
|
|
10221
|
+
}),
|
|
10222
|
+
routeLeaseDescriptorPort,
|
|
10223
|
+
{ logger }
|
|
10224
|
+
);
|
|
10225
|
+
providerProxy.registerBeforeStop(() => routeLeaseManager.shutdown());
|
|
10226
|
+
providerProxy.registerBeforeStop(() => resetCliSessions());
|
|
9771
10227
|
llmConfig.setReloadHook(() => apiKeyPool.invalidateCache());
|
|
9772
10228
|
const accountHealthProbeScheduler = new AccountHealthProbeScheduler(
|
|
9773
10229
|
credentialStore,
|
|
9774
|
-
|
|
10230
|
+
getSharedAccountHealth4(),
|
|
9775
10231
|
logger,
|
|
9776
10232
|
DEFAULT_ACCOUNT_PROBE
|
|
9777
10233
|
);
|
|
@@ -9818,6 +10274,7 @@ function buildDaemon(config, paths) {
|
|
|
9818
10274
|
keySpendReader: keySpendTracker,
|
|
9819
10275
|
settingsStore,
|
|
9820
10276
|
outboundApiServer,
|
|
10277
|
+
routeLeaseManager,
|
|
9821
10278
|
subscriptionAccounts,
|
|
9822
10279
|
accountAllowanceService,
|
|
9823
10280
|
allowanceRefreshScheduler: claudeAllowanceRefreshScheduler,
|
|
@@ -9910,7 +10367,7 @@ function buildDaemon(config, paths) {
|
|
|
9910
10367
|
logger,
|
|
9911
10368
|
fetchImpl: (url, init) => fetchUpstream7(url, init)
|
|
9912
10369
|
});
|
|
9913
|
-
setWebhookRuntime(webhookDispatcher,
|
|
10370
|
+
setWebhookRuntime(webhookDispatcher, getSharedAccountHealth4());
|
|
9914
10371
|
const auditWriter = new AuditWriter(auditDir, logger);
|
|
9915
10372
|
const auditPruneSweeper = new AuditPruneSweeper(auditDir, logger, DEFAULT_AUDIT_CONFIG);
|
|
9916
10373
|
setAuditRuntime(auditWriter, auditPruneSweeper);
|
|
@@ -9925,7 +10382,7 @@ function buildDaemon(config, paths) {
|
|
|
9925
10382
|
const tokenRefreshScheduler = new TokenRefreshScheduler(credentialStore, logger);
|
|
9926
10383
|
const accountHealthSweeper = new AccountHealthSweeper(
|
|
9927
10384
|
credentialStore,
|
|
9928
|
-
|
|
10385
|
+
getSharedAccountHealth4(),
|
|
9929
10386
|
logger
|
|
9930
10387
|
);
|
|
9931
10388
|
return {
|
|
@@ -9934,6 +10391,7 @@ function buildDaemon(config, paths) {
|
|
|
9934
10391
|
keyDb,
|
|
9935
10392
|
settingsStore,
|
|
9936
10393
|
providerProxy,
|
|
10394
|
+
routeLeaseManager,
|
|
9937
10395
|
outboundApiServer,
|
|
9938
10396
|
apiKeyPool,
|
|
9939
10397
|
autoDisableStore,
|
|
@@ -10049,32 +10507,17 @@ async function runLaunch(argv, deps) {
|
|
|
10049
10507
|
await daemon.llmConfig.ready();
|
|
10050
10508
|
await daemon.providerProxy.start();
|
|
10051
10509
|
} 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();
|
|
10510
|
+
await shutdownLaunchDaemon(daemon);
|
|
10060
10511
|
throw err5;
|
|
10061
10512
|
}
|
|
10062
10513
|
let launch;
|
|
10063
10514
|
try {
|
|
10064
|
-
launch = await buildLaunchConfig(cli, daemon
|
|
10515
|
+
launch = await buildLaunchConfig(cli, daemon, {
|
|
10065
10516
|
providerId: values.provider,
|
|
10066
10517
|
model: values.model
|
|
10067
10518
|
});
|
|
10068
10519
|
} 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();
|
|
10520
|
+
await shutdownLaunchDaemon(daemon);
|
|
10078
10521
|
throw err5;
|
|
10079
10522
|
}
|
|
10080
10523
|
try {
|
|
@@ -10093,21 +10536,40 @@ async function runLaunch(argv, deps) {
|
|
|
10093
10536
|
cwd: values.cwd
|
|
10094
10537
|
});
|
|
10095
10538
|
} finally {
|
|
10096
|
-
|
|
10097
|
-
|
|
10098
|
-
|
|
10099
|
-
|
|
10100
|
-
|
|
10101
|
-
|
|
10102
|
-
|
|
10103
|
-
|
|
10104
|
-
|
|
10105
|
-
|
|
10106
|
-
|
|
10107
|
-
|
|
10108
|
-
|
|
10539
|
+
try {
|
|
10540
|
+
launch.onSessionEnd();
|
|
10541
|
+
} finally {
|
|
10542
|
+
await shutdownLaunchDaemon(daemon);
|
|
10543
|
+
}
|
|
10544
|
+
}
|
|
10545
|
+
}
|
|
10546
|
+
async function buildLaunchConfig(cli, daemon, opts) {
|
|
10547
|
+
if (cli === "claude" || cli === "codex") {
|
|
10548
|
+
const internalId = randomUUID6();
|
|
10549
|
+
const outcome = await daemon.routeLeaseManager.createFromRequest({
|
|
10550
|
+
schemaVersion: ROUTE_LEASE_REQUEST_SCHEMA2,
|
|
10551
|
+
consumer: "omnicross-terminal",
|
|
10552
|
+
runtime: cli,
|
|
10553
|
+
upstream: { kind: "provider", providerId: opts.providerId },
|
|
10554
|
+
model: opts.model,
|
|
10555
|
+
execution: { sessionId: `launch:${cli}:${internalId}` }
|
|
10556
|
+
}, `omnicross-launch:${internalId}`);
|
|
10557
|
+
const stopRenewal = startTerminalLeaseRenewal(
|
|
10558
|
+
daemon.routeLeaseManager,
|
|
10559
|
+
outcome.result.leaseId
|
|
10560
|
+
);
|
|
10561
|
+
return {
|
|
10562
|
+
baseUrl: daemon.providerProxy.getBaseUrl(),
|
|
10563
|
+
env: outcome.result.launch.env,
|
|
10564
|
+
extraArgs: outcome.result.launch.extraArgs,
|
|
10565
|
+
onSessionEnd: () => {
|
|
10566
|
+
stopRenewal();
|
|
10567
|
+
daemon.routeLeaseManager.release(outcome.result.leaseId);
|
|
10568
|
+
}
|
|
10569
|
+
};
|
|
10570
|
+
}
|
|
10109
10571
|
const common = {
|
|
10110
|
-
llmConfig,
|
|
10572
|
+
llmConfig: daemon.llmConfig,
|
|
10111
10573
|
providerId: opts.providerId,
|
|
10112
10574
|
model: opts.model,
|
|
10113
10575
|
// Stable, bounded session id — pool failover (poolseam) fires on launch
|
|
@@ -10115,10 +10577,6 @@ async function buildLaunchConfig(cli, llmConfig, opts) {
|
|
|
10115
10577
|
sessionId: `launch:${cli}`
|
|
10116
10578
|
};
|
|
10117
10579
|
switch (cli) {
|
|
10118
|
-
case "claude":
|
|
10119
|
-
return buildClaudeCliLaunchConfig2(common);
|
|
10120
|
-
case "codex":
|
|
10121
|
-
return buildCodexLaunchConfig2(common);
|
|
10122
10580
|
case "gemini":
|
|
10123
10581
|
return buildGeminiCliLaunchConfig2(common);
|
|
10124
10582
|
case "qwen":
|
|
@@ -10131,6 +10589,18 @@ async function buildLaunchConfig(cli, llmConfig, opts) {
|
|
|
10131
10589
|
}
|
|
10132
10590
|
}
|
|
10133
10591
|
}
|
|
10592
|
+
async function shutdownLaunchDaemon(daemon) {
|
|
10593
|
+
daemon.routeLeaseManager.shutdown();
|
|
10594
|
+
await daemon.providerProxy.stop();
|
|
10595
|
+
daemon.apiKeyPool.dispose();
|
|
10596
|
+
daemon.tokenRefreshScheduler.dispose();
|
|
10597
|
+
daemon.claudeAllowanceRefreshScheduler.dispose();
|
|
10598
|
+
daemon.accountHealthSweeper.dispose();
|
|
10599
|
+
daemon.accountHealthProbeScheduler.dispose();
|
|
10600
|
+
daemon.auditPruneSweeper.dispose();
|
|
10601
|
+
daemon.billingRetrySweeper.dispose();
|
|
10602
|
+
daemon.pricingRefreshScheduler.dispose();
|
|
10603
|
+
}
|
|
10134
10604
|
function spawnCliInherit(plan) {
|
|
10135
10605
|
return new Promise((resolve3, reject) => {
|
|
10136
10606
|
const child = spawn2(plan.command, plan.args, {
|
|
@@ -10177,7 +10647,7 @@ import { createInterface } from "readline";
|
|
|
10177
10647
|
import { parseArgs as parseArgs5 } from "util";
|
|
10178
10648
|
import { fetchUpstream as fetchUpstream8, setUpstreamProxyResolver as setUpstreamProxyResolver2 } from "@omnicross/core/pipeline/upstreamFetch";
|
|
10179
10649
|
import { claudeOAuth as claudeOAuth3, codexOAuth as codexOAuth3, geminiOAuth as geminiOAuth3 } from "@omnicross/subscriptions";
|
|
10180
|
-
var
|
|
10650
|
+
var PROVIDERS2 = ["claude", "codex", "gemini"];
|
|
10181
10651
|
async function runLogin(argv, deps) {
|
|
10182
10652
|
const { values, positionals } = parseArgs5({
|
|
10183
10653
|
args: argv,
|
|
@@ -10191,10 +10661,10 @@ async function runLogin(argv, deps) {
|
|
|
10191
10661
|
});
|
|
10192
10662
|
const provider = positionals[0];
|
|
10193
10663
|
if (!provider) {
|
|
10194
|
-
throw new Error(`login: a <provider> is required (one of ${
|
|
10664
|
+
throw new Error(`login: a <provider> is required (one of ${PROVIDERS2.join("|")})`);
|
|
10195
10665
|
}
|
|
10196
10666
|
if (!isLoginProvider(provider)) {
|
|
10197
|
-
throw new Error(`login: unknown provider '${provider}' (expected ${
|
|
10667
|
+
throw new Error(`login: unknown provider '${provider}' (expected ${PROVIDERS2.join("|")})`);
|
|
10198
10668
|
}
|
|
10199
10669
|
if (!values.config) {
|
|
10200
10670
|
throw new Error("login: --config <path> is required");
|
|
@@ -10300,7 +10770,7 @@ async function loginGemini(store, deps, exchangeFetch, label) {
|
|
|
10300
10770
|
return expiresAt;
|
|
10301
10771
|
}
|
|
10302
10772
|
function isLoginProvider(value) {
|
|
10303
|
-
return
|
|
10773
|
+
return PROVIDERS2.includes(value);
|
|
10304
10774
|
}
|
|
10305
10775
|
async function presentUrl(authUrl, deps) {
|
|
10306
10776
|
console.info("Open this URL in your browser to authorize:");
|
|
@@ -10346,7 +10816,7 @@ function promptPaste(prompt) {
|
|
|
10346
10816
|
}
|
|
10347
10817
|
|
|
10348
10818
|
// src/commands/providers.ts
|
|
10349
|
-
import { randomUUID as
|
|
10819
|
+
import { randomUUID as randomUUID7 } from "crypto";
|
|
10350
10820
|
import { parseArgs as parseArgs6 } from "util";
|
|
10351
10821
|
async function runProviders(argv) {
|
|
10352
10822
|
const { values, positionals } = parseArgs6({
|
|
@@ -10468,7 +10938,7 @@ function providersAddKey(configPath, providerId, opts) {
|
|
|
10468
10938
|
const cfg = loadConfig(configPath);
|
|
10469
10939
|
const row = cfg.providers.find((p) => p.id === providerId);
|
|
10470
10940
|
if (!row) throw new Error(`providers add-key: unknown provider '${providerId}'`);
|
|
10471
|
-
const entry = { id:
|
|
10941
|
+
const entry = { id: randomUUID7(), apiKey: opts.key };
|
|
10472
10942
|
if (opts.label) entry.label = opts.label;
|
|
10473
10943
|
if (opts.weight !== void 0) {
|
|
10474
10944
|
const w = Number(opts.weight);
|
|
@@ -10496,7 +10966,7 @@ function providersRmKey(configPath, providerId, keyId) {
|
|
|
10496
10966
|
}
|
|
10497
10967
|
|
|
10498
10968
|
// src/commands/secrets.ts
|
|
10499
|
-
import { existsSync as existsSync21, readFileSync as readFileSync18, writeFileSync as
|
|
10969
|
+
import { existsSync as existsSync21, readFileSync as readFileSync18, writeFileSync as writeFileSync13 } from "fs";
|
|
10500
10970
|
import { parseArgs as parseArgs7 } from "util";
|
|
10501
10971
|
async function runSecrets(argv) {
|
|
10502
10972
|
const { values, positionals } = parseArgs7({
|
|
@@ -10670,7 +11140,7 @@ function secretsDecrypt(args) {
|
|
|
10670
11140
|
}
|
|
10671
11141
|
saveConfig(args.config, cfg);
|
|
10672
11142
|
if (tokensPlain) {
|
|
10673
|
-
|
|
11143
|
+
writeFileSync13(tokensPath, JSON.stringify(tokensPlain, null, 2) + "\n", "utf8");
|
|
10674
11144
|
}
|
|
10675
11145
|
console.info(`Decrypted secrets to plaintext in ${args.config}` + tokensSuffix(args.config));
|
|
10676
11146
|
}
|
|
@@ -10714,7 +11184,7 @@ function writeTokensEncrypted(tokensPath, plain, box) {
|
|
|
10714
11184
|
{ updatedAt: "", ...plain },
|
|
10715
11185
|
box
|
|
10716
11186
|
);
|
|
10717
|
-
|
|
11187
|
+
writeFileSync13(tokensPath, JSON.stringify(encrypted, null, 2) + "\n", "utf8");
|
|
10718
11188
|
}
|
|
10719
11189
|
var TOKEN_FIELDS2 = {
|
|
10720
11190
|
claude: ["accessToken", "refreshToken"],
|
|
@@ -10743,8 +11213,8 @@ function tokensSuffix(configPath) {
|
|
|
10743
11213
|
// src/commands/start.ts
|
|
10744
11214
|
import { parseArgs as parseArgs8 } from "util";
|
|
10745
11215
|
import { loadServerConfig as loadServerConfig3 } from "@omnicross/core/outbound-api";
|
|
10746
|
-
import { getSharedAccountHealth as
|
|
10747
|
-
import { getSharedAccountAllowanceScheduling as
|
|
11216
|
+
import { getSharedAccountHealth as getSharedAccountHealth5 } from "@omnicross/core/pipeline/SubscriptionAccountHealth";
|
|
11217
|
+
import { getSharedAccountAllowanceScheduling as getSharedAccountAllowanceScheduling6 } from "@omnicross/core/pipeline/AccountAllowanceScheduling";
|
|
10748
11218
|
|
|
10749
11219
|
// src/identity/identityRuntime.ts
|
|
10750
11220
|
import { getSharedIdentityStore as getSharedIdentityStore3 } from "@omnicross/core/provider-proxy/identity/SubscriptionIdentityStore";
|
|
@@ -10804,11 +11274,11 @@ async function runStart(argv) {
|
|
|
10804
11274
|
await daemon.llmConfig.ready();
|
|
10805
11275
|
await daemon.providerProxy.start();
|
|
10806
11276
|
const serverConfig = await loadServerConfig3(daemon.settingsStore);
|
|
10807
|
-
|
|
11277
|
+
getSharedAccountHealth5().configure({
|
|
10808
11278
|
overloadEnabled: serverConfig.accountHealth?.overloadCooldownEnabled,
|
|
10809
11279
|
overloadTtlMs: serverConfig.accountHealth?.overloadCooldownMs
|
|
10810
11280
|
});
|
|
10811
|
-
|
|
11281
|
+
getSharedAccountAllowanceScheduling6().configure(serverConfig.allowanceScheduling);
|
|
10812
11282
|
daemon.claudeAllowanceRefreshScheduler.configure(serverConfig.allowanceScheduling);
|
|
10813
11283
|
await daemon.outboundApiServer.applyConfig({
|
|
10814
11284
|
enabled: true,
|