@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/index.cjs
CHANGED
|
@@ -60,13 +60,14 @@ var import_GeminiCodeAssistProjectResolver = require("@omnicross/core/auth/Gemin
|
|
|
60
60
|
var import_ApiKeyPoolService = require("@omnicross/core/completion/ApiKeyPoolService");
|
|
61
61
|
var import_outbound_api4 = require("@omnicross/core/outbound-api");
|
|
62
62
|
var import_subscriptionRegistryPort = require("@omnicross/core/outbound-api/subscriptionRegistryPort");
|
|
63
|
-
var
|
|
63
|
+
var import_SubscriptionAccountHealth4 = require("@omnicross/core/pipeline/SubscriptionAccountHealth");
|
|
64
64
|
var import_AccountAllowanceStore4 = require("@omnicross/core/pipeline/AccountAllowanceStore");
|
|
65
|
-
var
|
|
65
|
+
var import_AccountAllowanceScheduling5 = require("@omnicross/core/pipeline/AccountAllowanceScheduling");
|
|
66
66
|
var import_upstreamFetch8 = require("@omnicross/core/pipeline/upstreamFetch");
|
|
67
67
|
var import_SubscriptionIdentityStore3 = require("@omnicross/core/provider-proxy/identity/SubscriptionIdentityStore");
|
|
68
68
|
var import_gemini_code_assist_resolver = require("@omnicross/core/ports/gemini-code-assist-resolver");
|
|
69
|
-
var
|
|
69
|
+
var import_provider_proxy4 = require("@omnicross/core/provider-proxy");
|
|
70
|
+
var import_cli_launcher2 = require("@omnicross/cli-launcher");
|
|
70
71
|
var import_outbound_api5 = require("@omnicross/core/outbound-api");
|
|
71
72
|
var import_usage = require("@omnicross/core/usage");
|
|
72
73
|
var import_subscriptions4 = require("@omnicross/subscriptions");
|
|
@@ -756,6 +757,88 @@ async function handleWebhookTest(req, res) {
|
|
|
756
757
|
res.end(JSON.stringify({ result }));
|
|
757
758
|
}
|
|
758
759
|
|
|
760
|
+
// src/admin/routeLeaseApi.ts
|
|
761
|
+
var import_provider_proxy = require("@omnicross/core/provider-proxy");
|
|
762
|
+
var MAX_BODY_BYTES = 64 * 1024;
|
|
763
|
+
var SAFE_LEASE_ID = /^[A-Za-z0-9-]{1,128}$/u;
|
|
764
|
+
async function readJson(req) {
|
|
765
|
+
const chunks = [];
|
|
766
|
+
let bytes = 0;
|
|
767
|
+
for await (const chunk of req) {
|
|
768
|
+
const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
|
|
769
|
+
bytes += buffer.length;
|
|
770
|
+
if (bytes > MAX_BODY_BYTES) throw new import_provider_proxy.RouteLeaseError("invalid_request", "request body is too large");
|
|
771
|
+
chunks.push(buffer);
|
|
772
|
+
}
|
|
773
|
+
if (chunks.length === 0) return {};
|
|
774
|
+
try {
|
|
775
|
+
return JSON.parse(Buffer.concat(chunks).toString("utf8"));
|
|
776
|
+
} catch {
|
|
777
|
+
throw new import_provider_proxy.RouteLeaseError("invalid_request", "request body is not valid JSON");
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
function json(res, status, body, noStore = false) {
|
|
781
|
+
res.statusCode = status;
|
|
782
|
+
res.setHeader("Content-Type", "application/json");
|
|
783
|
+
if (noStore) res.setHeader("Cache-Control", "no-store");
|
|
784
|
+
res.end(JSON.stringify(body));
|
|
785
|
+
}
|
|
786
|
+
function leaseId(value) {
|
|
787
|
+
if (!value || !SAFE_LEASE_ID.test(value)) throw new import_provider_proxy.RouteLeaseError("invalid_request", "lease id is invalid");
|
|
788
|
+
return value;
|
|
789
|
+
}
|
|
790
|
+
function header(req, name) {
|
|
791
|
+
const value = req.headers[name.toLowerCase()];
|
|
792
|
+
return Array.isArray(value) ? value[0] : value;
|
|
793
|
+
}
|
|
794
|
+
function writeError(res, error, noStore) {
|
|
795
|
+
const safe = error instanceof import_provider_proxy.RouteLeaseError ? error : new import_provider_proxy.RouteLeaseError("upstream_unavailable", "route lease operation failed safely");
|
|
796
|
+
if (safe.retryAfterSeconds !== void 0) res.setHeader("Retry-After", String(safe.retryAfterSeconds));
|
|
797
|
+
json(res, safe.status, safe.toResponse(), noStore);
|
|
798
|
+
}
|
|
799
|
+
async function handleRouteLeaseApi(req, res, path2, deps) {
|
|
800
|
+
const method = (req.method ?? "GET").toUpperCase();
|
|
801
|
+
const noStore = method === "POST" && (path2 === "/admin/api/route-leases" || path2.endsWith("/renew"));
|
|
802
|
+
try {
|
|
803
|
+
if (!(0, import_provider_proxy.isLoopbackAddress)(req.socket.remoteAddress)) {
|
|
804
|
+
throw new import_provider_proxy.RouteLeaseError("control_unauthorized", "route lease control plane is loopback only");
|
|
805
|
+
}
|
|
806
|
+
const manager = deps.routeLeaseManager;
|
|
807
|
+
if (!manager) throw new import_provider_proxy.RouteLeaseError("daemon_not_ready", "route lease manager is unavailable");
|
|
808
|
+
const base = "/admin/api/route-leases";
|
|
809
|
+
const suffix = path2.slice(base.length).replace(/^\/+|\/+$/gu, "");
|
|
810
|
+
const segments = suffix ? suffix.split("/") : [];
|
|
811
|
+
if (segments.length === 1 && segments[0] === "capabilities") {
|
|
812
|
+
if (method !== "GET" && method !== "HEAD") throw new import_provider_proxy.RouteLeaseError("invalid_request", "method is not allowed");
|
|
813
|
+
return json(res, 200, import_provider_proxy.ROUTE_LEASE_CAPABILITIES);
|
|
814
|
+
}
|
|
815
|
+
if (segments.length === 0) {
|
|
816
|
+
if (method === "GET") return json(res, 200, { leases: manager.list() });
|
|
817
|
+
if (method === "POST") {
|
|
818
|
+
const outcome = await manager.createFromRequest(await readJson(req), header(req, "idempotency-key"));
|
|
819
|
+
return json(res, outcome.created ? 201 : 200, outcome.result, true);
|
|
820
|
+
}
|
|
821
|
+
throw new import_provider_proxy.RouteLeaseError("invalid_request", "method is not allowed");
|
|
822
|
+
}
|
|
823
|
+
const id = leaseId(segments[0]);
|
|
824
|
+
if (segments.length === 1) {
|
|
825
|
+
if (method === "GET") return json(res, 200, manager.get(id));
|
|
826
|
+
if (method === "DELETE") return json(res, 200, manager.release(id));
|
|
827
|
+
throw new import_provider_proxy.RouteLeaseError("invalid_request", "method is not allowed");
|
|
828
|
+
}
|
|
829
|
+
if (segments.length === 2 && segments[1] === "renew" && method === "POST") {
|
|
830
|
+
const body = await readJson(req);
|
|
831
|
+
const ttl = (0, import_provider_proxy.normalizeRouteLeaseTtl)(
|
|
832
|
+
body && typeof body === "object" && !Array.isArray(body) ? body.ttlSeconds : void 0
|
|
833
|
+
);
|
|
834
|
+
return json(res, 200, manager.renew(id, ttl), true);
|
|
835
|
+
}
|
|
836
|
+
throw new import_provider_proxy.RouteLeaseError("lease_not_found", "route lease endpoint was not found");
|
|
837
|
+
} catch (error) {
|
|
838
|
+
writeError(res, error, noStore);
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
|
|
759
842
|
// src/admin/adminApi.ts
|
|
760
843
|
var import_node_http = __toESM(require("http"), 1);
|
|
761
844
|
var import_outbound_api2 = require("@omnicross/core/outbound-api");
|
|
@@ -1181,6 +1264,35 @@ function validateApiKeys(raw) {
|
|
|
1181
1264
|
}
|
|
1182
1265
|
return out.length > 0 ? out : void 0;
|
|
1183
1266
|
}
|
|
1267
|
+
var THINK_LEVELS = /* @__PURE__ */ new Set([
|
|
1268
|
+
"none",
|
|
1269
|
+
"minimal",
|
|
1270
|
+
"low",
|
|
1271
|
+
"medium",
|
|
1272
|
+
"high",
|
|
1273
|
+
"xhigh",
|
|
1274
|
+
"max"
|
|
1275
|
+
]);
|
|
1276
|
+
function validateThinkingLevels(raw) {
|
|
1277
|
+
if (!Array.isArray(raw)) return void 0;
|
|
1278
|
+
if (!raw.every((level) => typeof level === "string" && THINK_LEVELS.has(level))) {
|
|
1279
|
+
return void 0;
|
|
1280
|
+
}
|
|
1281
|
+
return [...raw];
|
|
1282
|
+
}
|
|
1283
|
+
function validateThinkingTokenLimit(raw) {
|
|
1284
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return void 0;
|
|
1285
|
+
const bounds = raw;
|
|
1286
|
+
const min = bounds["min"];
|
|
1287
|
+
const max = bounds["max"];
|
|
1288
|
+
if (typeof min !== "number" || !Number.isFinite(min) || !Number.isInteger(min) || min < 0) {
|
|
1289
|
+
return void 0;
|
|
1290
|
+
}
|
|
1291
|
+
if (typeof max !== "number" || !Number.isFinite(max) || !Number.isInteger(max) || max < min) {
|
|
1292
|
+
return void 0;
|
|
1293
|
+
}
|
|
1294
|
+
return { min, max };
|
|
1295
|
+
}
|
|
1184
1296
|
function validateModelConfigs(raw) {
|
|
1185
1297
|
if (!Array.isArray(raw)) return void 0;
|
|
1186
1298
|
const out = [];
|
|
@@ -1195,6 +1307,10 @@ function validateModelConfigs(raw) {
|
|
|
1195
1307
|
if (typeof m["enabled"] === "boolean") entry.enabled = m["enabled"];
|
|
1196
1308
|
if (typeof m["vision"] === "boolean") entry.vision = m["vision"];
|
|
1197
1309
|
if (typeof m["reasoning"] === "boolean") entry.reasoning = m["reasoning"];
|
|
1310
|
+
const thinkingLevels = validateThinkingLevels(m["thinkingLevels"]);
|
|
1311
|
+
if (thinkingLevels) entry.thinkingLevels = thinkingLevels;
|
|
1312
|
+
const thinkingTokenLimit = validateThinkingTokenLimit(m["thinkingTokenLimit"]);
|
|
1313
|
+
if (thinkingTokenLimit) entry.thinkingTokenLimit = thinkingTokenLimit;
|
|
1198
1314
|
out.push(entry);
|
|
1199
1315
|
}
|
|
1200
1316
|
return out.length > 0 ? out : void 0;
|
|
@@ -2611,8 +2727,34 @@ async function exchangeGemini(code, codeVerifier, exchangeFetch) {
|
|
|
2611
2727
|
var import_node_child_process = require("child_process");
|
|
2612
2728
|
var import_node_crypto6 = require("crypto");
|
|
2613
2729
|
var import_node_fs6 = require("fs");
|
|
2730
|
+
var import_node_net = require("net");
|
|
2731
|
+
var import_node_os3 = require("os");
|
|
2614
2732
|
var import_node_path5 = require("path");
|
|
2615
2733
|
var import_cli_launcher = require("@omnicross/cli-launcher");
|
|
2734
|
+
var import_provider_proxy2 = require("@omnicross/core/provider-proxy");
|
|
2735
|
+
|
|
2736
|
+
// src/routeLeaseRenewal.ts
|
|
2737
|
+
var TERMINAL_LEASE_TTL_SECONDS = 600;
|
|
2738
|
+
var TERMINAL_LEASE_RENEW_INTERVAL_MS = 5 * 60 * 1e3;
|
|
2739
|
+
var TERMINAL_LEASE_MAX_LIFETIME_MS = 24 * 60 * 60 * 1e3;
|
|
2740
|
+
function startTerminalLeaseRenewal(manager, leaseId2) {
|
|
2741
|
+
const stopAt = Date.now() + TERMINAL_LEASE_MAX_LIFETIME_MS;
|
|
2742
|
+
const timer = setInterval(() => {
|
|
2743
|
+
if (Date.now() >= stopAt) {
|
|
2744
|
+
clearInterval(timer);
|
|
2745
|
+
return;
|
|
2746
|
+
}
|
|
2747
|
+
try {
|
|
2748
|
+
manager.renew(leaseId2, TERMINAL_LEASE_TTL_SECONDS);
|
|
2749
|
+
} catch {
|
|
2750
|
+
clearInterval(timer);
|
|
2751
|
+
}
|
|
2752
|
+
}, TERMINAL_LEASE_RENEW_INTERVAL_MS);
|
|
2753
|
+
timer.unref?.();
|
|
2754
|
+
return () => clearInterval(timer);
|
|
2755
|
+
}
|
|
2756
|
+
|
|
2757
|
+
// src/admin/cliLaunch.ts
|
|
2616
2758
|
var LAUNCHABLE_CLIS = [
|
|
2617
2759
|
{ id: "claude", displayName: "Claude Code", command: "claude" },
|
|
2618
2760
|
{ id: "codex", displayName: "Codex CLI", command: "codex" },
|
|
@@ -2693,34 +2835,183 @@ async function buildLaunchEnv(cli, llmConfig, target) {
|
|
|
2693
2835
|
function shq(s) {
|
|
2694
2836
|
return `'${s.replace(/'/g, `'\\''`)}'`;
|
|
2695
2837
|
}
|
|
2696
|
-
var
|
|
2838
|
+
var MAC_TERMINAL_BOOTSTRAP_SOURCE = `
|
|
2839
|
+
'use strict';
|
|
2840
|
+
const fs = require('node:fs');
|
|
2841
|
+
const net = require('node:net');
|
|
2842
|
+
const { spawn } = require('node:child_process');
|
|
2843
|
+
const [socketPath, launchDir, cwd, command, ...args] = process.argv.slice(2);
|
|
2844
|
+
let payload = '';
|
|
2845
|
+
const socket = net.createConnection(socketPath);
|
|
2846
|
+
socket.setEncoding('utf8');
|
|
2847
|
+
socket.on('data', (chunk) => { payload += chunk; });
|
|
2848
|
+
socket.on('end', () => {
|
|
2849
|
+
const descriptor = JSON.parse(payload);
|
|
2850
|
+
if (!descriptor || Array.isArray(descriptor) || Object.values(descriptor).some((value) => typeof value !== 'string')) {
|
|
2851
|
+
throw new Error('invalid terminal launch descriptor');
|
|
2852
|
+
}
|
|
2853
|
+
try { fs.rmSync(launchDir, { recursive: true, force: true }); } catch {}
|
|
2854
|
+
const child = spawn(command, args, {
|
|
2855
|
+
cwd: cwd || undefined,
|
|
2856
|
+
env: { ...process.env, ...descriptor },
|
|
2857
|
+
stdio: 'inherit',
|
|
2858
|
+
});
|
|
2859
|
+
child.on('error', (error) => { console.error(error.message); process.exitCode = 1; });
|
|
2860
|
+
child.on('exit', (code, signal) => {
|
|
2861
|
+
if (signal) process.kill(process.pid, signal);
|
|
2862
|
+
else process.exitCode = code == null ? 1 : code;
|
|
2863
|
+
});
|
|
2864
|
+
});
|
|
2865
|
+
socket.on('error', (error) => { console.error(error.message); process.exitCode = 1; });
|
|
2866
|
+
`;
|
|
2867
|
+
var MAC_TERMINAL_IPC_TIMEOUT_MS = 12e4;
|
|
2868
|
+
function openTerminal({ cli, command, extraArgs, env, cwd, platform, onFailure }, spawnProcess = import_node_child_process.spawn, macIpc = {}) {
|
|
2697
2869
|
const childEnv = { ...process.env, ...env };
|
|
2698
2870
|
if (platform === "win32") {
|
|
2699
2871
|
const args = ["/c", "start", `"omnicross ${cli}"`];
|
|
2700
2872
|
if (cwd) args.push("/D", `"${cwd}"`);
|
|
2701
2873
|
args.push("cmd", "/k", command, ...extraArgs);
|
|
2702
|
-
(
|
|
2874
|
+
spawnProcess(process.env["ComSpec"] || "cmd.exe", args, {
|
|
2703
2875
|
env: childEnv,
|
|
2704
2876
|
windowsVerbatimArguments: true,
|
|
2705
2877
|
detached: true,
|
|
2706
2878
|
stdio: "ignore"
|
|
2707
2879
|
}).unref();
|
|
2708
|
-
return
|
|
2880
|
+
return () => {
|
|
2881
|
+
};
|
|
2709
2882
|
}
|
|
2710
|
-
const exportLine = Object.entries(env).map(([k, v]) => `export ${k}=${shq(v)}`).join("; ");
|
|
2711
2883
|
const runLine = [command, ...extraArgs].map(shq).join(" ");
|
|
2712
|
-
const script = `${
|
|
2884
|
+
const script = `${cwd ? `cd ${shq(cwd)}; ` : ""}${runLine}`;
|
|
2713
2885
|
if (platform === "darwin") {
|
|
2714
|
-
const
|
|
2715
|
-
(0,
|
|
2716
|
-
|
|
2886
|
+
const launchDir = (0, import_node_fs6.mkdtempSync)((0, import_node_path5.join)((0, import_node_os3.tmpdir)(), "omnicross-terminal-"));
|
|
2887
|
+
const commandFile = (0, import_node_path5.join)(launchDir, "launch.command");
|
|
2888
|
+
const bootstrapFile = (0, import_node_path5.join)(launchDir, "bootstrap.cjs");
|
|
2889
|
+
const socketPath = macIpc.socketPath ?? (0, import_node_path5.join)(launchDir, "descriptor.sock");
|
|
2890
|
+
const openerEnv = { ...process.env };
|
|
2891
|
+
for (const key of Object.keys(env)) delete openerEnv[key];
|
|
2892
|
+
let claimed = false;
|
|
2893
|
+
let cleaned = false;
|
|
2894
|
+
let failureNotified = false;
|
|
2895
|
+
let timer;
|
|
2896
|
+
const notifyFailure = () => {
|
|
2897
|
+
cleanup();
|
|
2898
|
+
if (failureNotified) return;
|
|
2899
|
+
failureNotified = true;
|
|
2900
|
+
try {
|
|
2901
|
+
onFailure?.();
|
|
2902
|
+
} catch {
|
|
2903
|
+
}
|
|
2904
|
+
};
|
|
2905
|
+
const handleLaunchFailure = () => {
|
|
2906
|
+
if (claimed) cleanup();
|
|
2907
|
+
else notifyFailure();
|
|
2908
|
+
};
|
|
2909
|
+
const sockets = /* @__PURE__ */ new Set();
|
|
2910
|
+
const server = (0, import_node_net.createServer)((socket) => {
|
|
2911
|
+
socket.unref();
|
|
2912
|
+
sockets.add(socket);
|
|
2913
|
+
socket.once("close", () => sockets.delete(socket));
|
|
2914
|
+
try {
|
|
2915
|
+
macIpc.onAccepted?.(socket);
|
|
2916
|
+
} catch {
|
|
2917
|
+
cleanup();
|
|
2918
|
+
return;
|
|
2919
|
+
}
|
|
2920
|
+
if (claimed || cleaned) {
|
|
2921
|
+
socket.destroy();
|
|
2922
|
+
return;
|
|
2923
|
+
}
|
|
2924
|
+
claimed = true;
|
|
2925
|
+
try {
|
|
2926
|
+
macIpc.onClaimed?.();
|
|
2927
|
+
if (cleaned) return;
|
|
2928
|
+
socket.end(JSON.stringify(env), cleanup);
|
|
2929
|
+
} catch {
|
|
2930
|
+
cleanup();
|
|
2931
|
+
}
|
|
2932
|
+
});
|
|
2933
|
+
const cleanup = () => {
|
|
2934
|
+
if (!cleaned) {
|
|
2935
|
+
cleaned = true;
|
|
2936
|
+
if (timer) clearTimeout(timer);
|
|
2937
|
+
for (const socket of sockets) socket.destroy();
|
|
2938
|
+
sockets.clear();
|
|
2939
|
+
try {
|
|
2940
|
+
server.close();
|
|
2941
|
+
} catch {
|
|
2942
|
+
}
|
|
2943
|
+
}
|
|
2944
|
+
try {
|
|
2945
|
+
if (macIpc.removeArtifacts) {
|
|
2946
|
+
macIpc.removeArtifacts(launchDir);
|
|
2947
|
+
} else {
|
|
2948
|
+
(0, import_node_fs6.rmSync)(launchDir, {
|
|
2949
|
+
recursive: true,
|
|
2950
|
+
force: true,
|
|
2951
|
+
maxRetries: 3,
|
|
2952
|
+
retryDelay: 20
|
|
2953
|
+
});
|
|
2954
|
+
}
|
|
2955
|
+
} catch {
|
|
2956
|
+
}
|
|
2957
|
+
};
|
|
2958
|
+
try {
|
|
2959
|
+
(0, import_node_fs6.writeFileSync)(bootstrapFile, MAC_TERMINAL_BOOTSTRAP_SOURCE, { encoding: "utf8", mode: 448 });
|
|
2960
|
+
(0, import_node_fs6.writeFileSync)(commandFile, `#!/bin/bash
|
|
2961
|
+
rm -f -- "$0"
|
|
2962
|
+
exec ${shq(process.execPath)} ${shq(bootstrapFile)} ${shq(socketPath)} ${shq(launchDir)} ${shq(cwd ?? "")} ${runLine}
|
|
2963
|
+
`, {
|
|
2964
|
+
encoding: "utf8",
|
|
2965
|
+
mode: 448
|
|
2966
|
+
});
|
|
2967
|
+
(0, import_node_fs6.chmodSync)(commandFile, 448);
|
|
2968
|
+
(0, import_node_fs6.chmodSync)(bootstrapFile, 448);
|
|
2969
|
+
server.once("error", handleLaunchFailure);
|
|
2970
|
+
server.listen(socketPath, () => {
|
|
2971
|
+
if (cleaned) return;
|
|
2972
|
+
try {
|
|
2973
|
+
macIpc.onListening?.();
|
|
2974
|
+
if (cleaned) return;
|
|
2975
|
+
if (process.platform !== "win32") (0, import_node_fs6.chmodSync)(socketPath, 384);
|
|
2976
|
+
const opener = spawnProcess("open", ["-n", "-a", "Terminal", commandFile], {
|
|
2977
|
+
env: openerEnv,
|
|
2978
|
+
detached: true,
|
|
2979
|
+
stdio: "ignore"
|
|
2980
|
+
});
|
|
2981
|
+
opener.once("error", handleLaunchFailure);
|
|
2982
|
+
opener.unref();
|
|
2983
|
+
server.unref();
|
|
2984
|
+
} catch {
|
|
2985
|
+
handleLaunchFailure();
|
|
2986
|
+
}
|
|
2987
|
+
});
|
|
2988
|
+
timer = setTimeout(handleLaunchFailure, macIpc.timeoutMs ?? MAC_TERMINAL_IPC_TIMEOUT_MS);
|
|
2989
|
+
timer.unref?.();
|
|
2990
|
+
return cleanup;
|
|
2991
|
+
} catch (error) {
|
|
2992
|
+
cleanup();
|
|
2993
|
+
throw error;
|
|
2994
|
+
}
|
|
2717
2995
|
}
|
|
2718
|
-
(
|
|
2996
|
+
spawnProcess("x-terminal-emulator", ["-e", "bash", "-lc", `${script}; exec bash`], {
|
|
2997
|
+
env: childEnv,
|
|
2719
2998
|
detached: true,
|
|
2720
2999
|
stdio: "ignore"
|
|
2721
3000
|
}).unref();
|
|
2722
|
-
|
|
3001
|
+
return () => {
|
|
3002
|
+
};
|
|
3003
|
+
}
|
|
3004
|
+
var defaultTerminalOpener = (input) => openTerminal(input);
|
|
2723
3005
|
var sessions = /* @__PURE__ */ new Map();
|
|
3006
|
+
function resetCliSessions() {
|
|
3007
|
+
for (const s of sessions.values()) {
|
|
3008
|
+
try {
|
|
3009
|
+
s.onSessionEnd();
|
|
3010
|
+
} catch {
|
|
3011
|
+
}
|
|
3012
|
+
}
|
|
3013
|
+
sessions.clear();
|
|
3014
|
+
}
|
|
2724
3015
|
function errBody(message) {
|
|
2725
3016
|
return { error: { type: "admin_api_error", message } };
|
|
2726
3017
|
}
|
|
@@ -2775,29 +3066,81 @@ async function handleCliLaunch(cli, body, ctx) {
|
|
|
2775
3066
|
} catch (err5) {
|
|
2776
3067
|
return { status: 400, body: errBody(err5 instanceof Error ? err5.message : "no launch target") };
|
|
2777
3068
|
}
|
|
3069
|
+
const id = (0, import_node_crypto6.randomUUID)();
|
|
3070
|
+
let leaseId2;
|
|
2778
3071
|
let launch;
|
|
2779
3072
|
try {
|
|
2780
|
-
|
|
3073
|
+
if ((cli === "claude" || cli === "codex") && ctx.routeLeaseManager) {
|
|
3074
|
+
const outcome = await ctx.routeLeaseManager.createFromRequest({
|
|
3075
|
+
schemaVersion: import_provider_proxy2.ROUTE_LEASE_REQUEST_SCHEMA,
|
|
3076
|
+
consumer: "omnicross-terminal",
|
|
3077
|
+
runtime: cli,
|
|
3078
|
+
upstream: { kind: "provider", providerId: target.providerId },
|
|
3079
|
+
model: target.model,
|
|
3080
|
+
execution: { sessionId: id }
|
|
3081
|
+
}, `omnicross-terminal:${id}`);
|
|
3082
|
+
leaseId2 = outcome.result.leaseId;
|
|
3083
|
+
const stopRenewal = startTerminalLeaseRenewal(ctx.routeLeaseManager, leaseId2);
|
|
3084
|
+
launch = {
|
|
3085
|
+
env: outcome.result.launch.env,
|
|
3086
|
+
extraArgs: outcome.result.launch.extraArgs,
|
|
3087
|
+
onSessionEnd: () => {
|
|
3088
|
+
stopRenewal();
|
|
3089
|
+
ctx.routeLeaseManager?.release(outcome.result.leaseId);
|
|
3090
|
+
}
|
|
3091
|
+
};
|
|
3092
|
+
} else {
|
|
3093
|
+
launch = await buildLaunchEnv(cli, ctx.llmConfig, target);
|
|
3094
|
+
}
|
|
2781
3095
|
} catch (err5) {
|
|
2782
|
-
|
|
3096
|
+
const status = err5 instanceof import_provider_proxy2.RouteLeaseError ? err5.status : 400;
|
|
3097
|
+
return { status, body: errBody(err5 instanceof Error ? err5.message : "failed to build launch env") };
|
|
2783
3098
|
}
|
|
2784
3099
|
const cwd = typeof body["cwd"] === "string" && body["cwd"].trim() ? body["cwd"].trim() : void 0;
|
|
2785
3100
|
const opener = ctx.opener ?? defaultTerminalOpener;
|
|
3101
|
+
let openerCleanup;
|
|
3102
|
+
let ended = false;
|
|
3103
|
+
let published = false;
|
|
3104
|
+
const onSessionEnd = () => {
|
|
3105
|
+
if (ended) return;
|
|
3106
|
+
ended = true;
|
|
3107
|
+
if (published) sessions.delete(id);
|
|
3108
|
+
try {
|
|
3109
|
+
openerCleanup?.();
|
|
3110
|
+
} finally {
|
|
3111
|
+
launch.onSessionEnd();
|
|
3112
|
+
}
|
|
3113
|
+
};
|
|
2786
3114
|
try {
|
|
2787
|
-
opener({
|
|
3115
|
+
const cleanup = opener({
|
|
3116
|
+
cli,
|
|
3117
|
+
command: meta.command,
|
|
3118
|
+
extraArgs: launch.extraArgs ?? [],
|
|
3119
|
+
env: launch.env,
|
|
3120
|
+
cwd,
|
|
3121
|
+
platform,
|
|
3122
|
+
onFailure: onSessionEnd
|
|
3123
|
+
});
|
|
3124
|
+
if (cleanup) openerCleanup = cleanup;
|
|
2788
3125
|
} catch (err5) {
|
|
2789
|
-
|
|
3126
|
+
onSessionEnd();
|
|
2790
3127
|
return { status: 500, body: errBody(err5 instanceof Error ? err5.message : "failed to open terminal") };
|
|
2791
3128
|
}
|
|
2792
|
-
|
|
3129
|
+
if (ended) {
|
|
3130
|
+
openerCleanup?.();
|
|
3131
|
+
return { status: 500, body: errBody("failed to open terminal") };
|
|
3132
|
+
}
|
|
2793
3133
|
sessions.set(id, {
|
|
2794
3134
|
id,
|
|
2795
3135
|
cli,
|
|
2796
3136
|
providerId: target.providerId,
|
|
2797
3137
|
model: target.model,
|
|
3138
|
+
...leaseId2 ? { leaseId: leaseId2 } : {},
|
|
2798
3139
|
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2799
|
-
onSessionEnd
|
|
3140
|
+
onSessionEnd
|
|
2800
3141
|
});
|
|
3142
|
+
published = true;
|
|
3143
|
+
if (ended) sessions.delete(id);
|
|
2801
3144
|
return { status: 200, body: { sessionId: id, providerId: target.providerId, model: target.model } };
|
|
2802
3145
|
}
|
|
2803
3146
|
|
|
@@ -3689,7 +4032,7 @@ function sealPack(bundleJson, passphrase) {
|
|
|
3689
4032
|
cipher.setAAD(aadFor(PACK_MAGIC, PACK_VERSION, KDF_ALGORITHM));
|
|
3690
4033
|
const ciphertext = Buffer.concat([cipher.update(bundleJson, "utf8"), cipher.final()]);
|
|
3691
4034
|
const tag = cipher.getAuthTag();
|
|
3692
|
-
const
|
|
4035
|
+
const header2 = {
|
|
3693
4036
|
magic: PACK_MAGIC,
|
|
3694
4037
|
v: PACK_VERSION,
|
|
3695
4038
|
kdf: KDF_ALGORITHM,
|
|
@@ -3700,7 +4043,7 @@ function sealPack(bundleJson, passphrase) {
|
|
|
3700
4043
|
iv: iv.toString("base64"),
|
|
3701
4044
|
tag: tag.toString("base64")
|
|
3702
4045
|
};
|
|
3703
|
-
return `${PACK_PREFIX}${toB64Url(JSON.stringify(
|
|
4046
|
+
return `${PACK_PREFIX}${toB64Url(JSON.stringify(header2))}.${ciphertext.toString("base64")}`;
|
|
3704
4047
|
}
|
|
3705
4048
|
function parsePack(packString) {
|
|
3706
4049
|
if (typeof packString !== "string" || !packString.startsWith(PACK_PREFIX)) {
|
|
@@ -3711,28 +4054,28 @@ function parsePack(packString) {
|
|
|
3711
4054
|
if (dot < 0) throw new PackAuthError("migration pack is malformed (missing body)");
|
|
3712
4055
|
const headerB64Url = rest.slice(0, dot);
|
|
3713
4056
|
const ctB64 = rest.slice(dot + 1);
|
|
3714
|
-
let
|
|
4057
|
+
let header2;
|
|
3715
4058
|
try {
|
|
3716
|
-
|
|
4059
|
+
header2 = JSON.parse(fromB64Url(headerB64Url));
|
|
3717
4060
|
} catch {
|
|
3718
4061
|
throw new PackAuthError("migration pack is malformed (unreadable header)");
|
|
3719
4062
|
}
|
|
3720
|
-
if (!
|
|
4063
|
+
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") {
|
|
3721
4064
|
throw new PackAuthError("migration pack is malformed (unsupported header)");
|
|
3722
4065
|
}
|
|
3723
4066
|
const ciphertext = Buffer.from(ctB64, "base64");
|
|
3724
|
-
return { header, ciphertext };
|
|
4067
|
+
return { header: header2, ciphertext };
|
|
3725
4068
|
}
|
|
3726
4069
|
function openPack(packString, passphrase) {
|
|
3727
4070
|
assertPassphraseStrength(passphrase);
|
|
3728
|
-
const { header, ciphertext } = parsePack(packString);
|
|
3729
|
-
const salt = Buffer.from(
|
|
3730
|
-
const iv = Buffer.from(
|
|
3731
|
-
const tag = Buffer.from(
|
|
4071
|
+
const { header: header2, ciphertext } = parsePack(packString);
|
|
4072
|
+
const salt = Buffer.from(header2.salt, "base64");
|
|
4073
|
+
const iv = Buffer.from(header2.iv, "base64");
|
|
4074
|
+
const tag = Buffer.from(header2.tag, "base64");
|
|
3732
4075
|
if (iv.length !== IV_BYTES2 || tag.length !== TAG_BYTES2) {
|
|
3733
4076
|
throw new PackAuthError("migration pack is malformed (invalid iv/tag length)");
|
|
3734
4077
|
}
|
|
3735
|
-
const key = deriveKey(passphrase, salt,
|
|
4078
|
+
const key = deriveKey(passphrase, salt, header2.N, header2.r, header2.p);
|
|
3736
4079
|
const decipher = (0, import_node_crypto8.createDecipheriv)("aes-256-gcm", key, iv);
|
|
3737
4080
|
decipher.setAAD(aadFor(PACK_MAGIC, PACK_VERSION, KDF_ALGORITHM));
|
|
3738
4081
|
decipher.setAuthTag(tag);
|
|
@@ -4068,10 +4411,10 @@ function writeJson2(res, status, body) {
|
|
|
4068
4411
|
res.writeHead(status, { "Content-Type": "application/json" });
|
|
4069
4412
|
res.end(JSON.stringify(body));
|
|
4070
4413
|
}
|
|
4071
|
-
function
|
|
4414
|
+
function writeError2(res, status, message) {
|
|
4072
4415
|
writeJson2(res, status, { error: { type: "account_allowance_error", message } });
|
|
4073
4416
|
}
|
|
4074
|
-
function
|
|
4417
|
+
function readJson2(req) {
|
|
4075
4418
|
return new Promise((resolve2, reject) => {
|
|
4076
4419
|
const chunks = [];
|
|
4077
4420
|
req.on("data", (chunk) => chunks.push(Buffer.from(chunk)));
|
|
@@ -4097,10 +4440,10 @@ function allowanceProvider(value) {
|
|
|
4097
4440
|
return value === "claude" || value === "codex" ? value : null;
|
|
4098
4441
|
}
|
|
4099
4442
|
async function handleAccountAllowanceApi(req, res, method, rest, service) {
|
|
4100
|
-
if (!service) return
|
|
4443
|
+
if (!service) return writeError2(res, 501, "account allowance service is not available");
|
|
4101
4444
|
if (method === "GET" && rest.length === 1 && rest[0] === "scheduling") {
|
|
4102
4445
|
if (!service.getSchedulingStatus) {
|
|
4103
|
-
return
|
|
4446
|
+
return writeError2(res, 501, "allowance scheduling diagnostics are not available");
|
|
4104
4447
|
}
|
|
4105
4448
|
return writeJson2(res, 200, { scheduling: service.getSchedulingStatus() });
|
|
4106
4449
|
}
|
|
@@ -4108,27 +4451,27 @@ async function handleAccountAllowanceApi(req, res, method, rest, service) {
|
|
|
4108
4451
|
const params = query(req);
|
|
4109
4452
|
const pathProvider = rest.length >= 2 ? rest[0] : null;
|
|
4110
4453
|
const providerId = allowanceProvider(pathProvider ?? params.get("providerId") ?? params.get("provider"));
|
|
4111
|
-
if (providerId === null) return
|
|
4454
|
+
if (providerId === null) return writeError2(res, 400, "providerId must be claude or codex");
|
|
4112
4455
|
const accountId = rest.length >= 2 ? rest[1] : params.get("accountId") ?? void 0;
|
|
4113
4456
|
const allowances = await service.list({ providerId, accountId });
|
|
4114
4457
|
return writeJson2(res, 200, { allowances });
|
|
4115
4458
|
}
|
|
4116
4459
|
if (method === "POST" && rest[0] === "refresh") {
|
|
4117
|
-
const body = await
|
|
4460
|
+
const body = await readJson2(req);
|
|
4118
4461
|
const requestedProvider = allowanceProvider(
|
|
4119
4462
|
typeof body["providerId"] === "string" ? body["providerId"] : "claude"
|
|
4120
4463
|
);
|
|
4121
4464
|
if (requestedProvider !== "claude") {
|
|
4122
|
-
return
|
|
4465
|
+
return writeError2(res, 400, "only Claude allowances support explicit refresh");
|
|
4123
4466
|
}
|
|
4124
4467
|
const accountId = typeof body["accountId"] === "string" && body["accountId"].trim() ? body["accountId"].trim() : void 0;
|
|
4125
4468
|
const allowances = await service.refreshClaude(accountId);
|
|
4126
4469
|
if (accountId && allowances.length === 0) {
|
|
4127
|
-
return
|
|
4470
|
+
return writeError2(res, 404, `Claude account '${accountId}' not found`);
|
|
4128
4471
|
}
|
|
4129
4472
|
return writeJson2(res, 200, { allowances });
|
|
4130
4473
|
}
|
|
4131
|
-
return
|
|
4474
|
+
return writeError2(res, 405, `method ${method} not allowed on account allowances`);
|
|
4132
4475
|
}
|
|
4133
4476
|
|
|
4134
4477
|
// src/admin/adminApi.ts
|
|
@@ -4703,6 +5046,12 @@ function parseModelConfigsInput(raw, existing) {
|
|
|
4703
5046
|
else if (typeof prior?.vision === "boolean") entry.vision = prior.vision;
|
|
4704
5047
|
if (typeof m["reasoning"] === "boolean") entry.reasoning = m["reasoning"];
|
|
4705
5048
|
else if (typeof prior?.reasoning === "boolean") entry.reasoning = prior.reasoning;
|
|
5049
|
+
const thinkingLevels = validateThinkingLevels(m["thinkingLevels"]);
|
|
5050
|
+
if (thinkingLevels) entry.thinkingLevels = thinkingLevels;
|
|
5051
|
+
else if (prior?.thinkingLevels) entry.thinkingLevels = prior.thinkingLevels;
|
|
5052
|
+
const thinkingTokenLimit = validateThinkingTokenLimit(m["thinkingTokenLimit"]);
|
|
5053
|
+
if (thinkingTokenLimit) entry.thinkingTokenLimit = thinkingTokenLimit;
|
|
5054
|
+
else if (prior?.thinkingTokenLimit) entry.thinkingTokenLimit = prior.thinkingTokenLimit;
|
|
4706
5055
|
out.push(entry);
|
|
4707
5056
|
}
|
|
4708
5057
|
return out.length > 0 ? out : void 0;
|
|
@@ -5360,6 +5709,7 @@ async function handleCli(req, res, method, rest, deps) {
|
|
|
5360
5709
|
const result = await handleCliLaunch(cli, body, {
|
|
5361
5710
|
llmConfig: deps.llmConfig,
|
|
5362
5711
|
providers,
|
|
5712
|
+
routeLeaseManager: deps.routeLeaseManager,
|
|
5363
5713
|
opener: deps.cliTerminalOpener,
|
|
5364
5714
|
probe: deps.cliPathProbe
|
|
5365
5715
|
});
|
|
@@ -5623,7 +5973,7 @@ async function handleUiStatic(req, res, urlPath, uiDist) {
|
|
|
5623
5973
|
}
|
|
5624
5974
|
|
|
5625
5975
|
// src/admin/version.ts
|
|
5626
|
-
var DAEMON_VERSION = true ? "0.1.
|
|
5976
|
+
var DAEMON_VERSION = true ? "0.1.9" : "0.0.0-dev";
|
|
5627
5977
|
|
|
5628
5978
|
// src/admin/AdminServer.ts
|
|
5629
5979
|
var LOOPBACK_ADDR = "127.0.0.1";
|
|
@@ -5743,6 +6093,10 @@ var AdminServer = class {
|
|
|
5743
6093
|
await handleWebhookTest(req, res);
|
|
5744
6094
|
return;
|
|
5745
6095
|
}
|
|
6096
|
+
if (path2 === "/admin/api/route-leases" || path2.startsWith("/admin/api/route-leases/")) {
|
|
6097
|
+
await handleRouteLeaseApi(req, res, path2, this.deps);
|
|
6098
|
+
return;
|
|
6099
|
+
}
|
|
5746
6100
|
if (path2.startsWith("/admin/api/")) {
|
|
5747
6101
|
await handleAdminApi(req, res, path2, this.deps);
|
|
5748
6102
|
return;
|
|
@@ -5754,8 +6108,8 @@ var AdminServer = class {
|
|
|
5754
6108
|
}
|
|
5755
6109
|
/** Constant-time bearer/header check against the configured token. */
|
|
5756
6110
|
isAuthorized(req, token) {
|
|
5757
|
-
const
|
|
5758
|
-
const bearer = typeof
|
|
6111
|
+
const header2 = req.headers["authorization"];
|
|
6112
|
+
const bearer = typeof header2 === "string" && header2.startsWith("Bearer ") ? header2.slice("Bearer ".length).trim() : void 0;
|
|
5759
6113
|
const xToken = req.headers["x-admin-token"];
|
|
5760
6114
|
const presented = bearer ?? (typeof xToken === "string" ? xToken.trim() : void 0);
|
|
5761
6115
|
return constantTimeEquals(presented, token);
|
|
@@ -6187,6 +6541,15 @@ function toLLMProvider(row) {
|
|
|
6187
6541
|
api_base_url: row.baseUrl,
|
|
6188
6542
|
api_key: resolvePreferredApiKey(row),
|
|
6189
6543
|
models,
|
|
6544
|
+
modelConfigs: row.modelConfigs?.map((config) => ({
|
|
6545
|
+
id: config.id,
|
|
6546
|
+
name: config.name ?? config.id,
|
|
6547
|
+
enabled: config.enabled ?? true,
|
|
6548
|
+
vision: config.vision,
|
|
6549
|
+
reasoning: config.reasoning,
|
|
6550
|
+
thinkingLevels: config.thinkingLevels,
|
|
6551
|
+
thinkingTokenLimit: config.thinkingTokenLimit
|
|
6552
|
+
})),
|
|
6190
6553
|
enabled: true,
|
|
6191
6554
|
transformer,
|
|
6192
6555
|
// app-parity-2 child 3: POPULATE the coding-plan endpoint onto the core
|
|
@@ -7299,9 +7662,9 @@ function findDuplicateCredentialIds(accounts) {
|
|
|
7299
7662
|
|
|
7300
7663
|
// src/ports/external-cli-credentials.ts
|
|
7301
7664
|
var import_node_fs15 = require("fs");
|
|
7302
|
-
var
|
|
7665
|
+
var import_node_os4 = require("os");
|
|
7303
7666
|
var import_node_path8 = require("path");
|
|
7304
|
-
function externalStorePath(provider, home = (0,
|
|
7667
|
+
function externalStorePath(provider, home = (0, import_node_os4.homedir)()) {
|
|
7305
7668
|
return provider === "claude" ? (0, import_node_path8.join)(home, ".claude", ".credentials.json") : (0, import_node_path8.join)(home, ".codex", "auth.json");
|
|
7306
7669
|
}
|
|
7307
7670
|
function decodeJwtExpiryMs(token) {
|
|
@@ -7349,7 +7712,7 @@ function parseCodexTokensEnvelope(raw) {
|
|
|
7349
7712
|
}
|
|
7350
7713
|
return parsed;
|
|
7351
7714
|
}
|
|
7352
|
-
function readExternalCliCredentials(provider, home = (0,
|
|
7715
|
+
function readExternalCliCredentials(provider, home = (0, import_node_os4.homedir)()) {
|
|
7353
7716
|
const path2 = externalStorePath(provider, home);
|
|
7354
7717
|
if (!(0, import_node_fs15.existsSync)(path2)) return null;
|
|
7355
7718
|
let raw;
|
|
@@ -9234,6 +9597,76 @@ var TokenRefreshScheduler = class {
|
|
|
9234
9597
|
}
|
|
9235
9598
|
};
|
|
9236
9599
|
|
|
9600
|
+
// src/routeLeaseSubscriptionPreflight.ts
|
|
9601
|
+
var import_provider_proxy3 = require("@omnicross/core/provider-proxy");
|
|
9602
|
+
var import_AccountAllowanceScheduling4 = require("@omnicross/core/pipeline/AccountAllowanceScheduling");
|
|
9603
|
+
var import_SubscriptionAccountHealth3 = require("@omnicross/core/pipeline/SubscriptionAccountHealth");
|
|
9604
|
+
var import_accountModelMap = require("@omnicross/subscriptions/scheduler/accountModelMap");
|
|
9605
|
+
var PROVIDERS = /* @__PURE__ */ new Set(["claude", "codex", "gemini", "opencodego"]);
|
|
9606
|
+
function accountArray(config, providerId) {
|
|
9607
|
+
const record = config;
|
|
9608
|
+
const key = `${providerId}Accounts`;
|
|
9609
|
+
const accounts = record[key];
|
|
9610
|
+
if (Array.isArray(accounts)) return accounts;
|
|
9611
|
+
const legacy = record[providerId];
|
|
9612
|
+
if (!legacy || typeof legacy !== "object") return [];
|
|
9613
|
+
const activeKey = `active${providerId[0].toUpperCase()}${providerId.slice(1)}AccountId`;
|
|
9614
|
+
return [{ id: String(record[activeKey] ?? "active"), enabled: true, tokens: legacy }];
|
|
9615
|
+
}
|
|
9616
|
+
function hasCredential(providerId, account) {
|
|
9617
|
+
const tokens = account.tokens;
|
|
9618
|
+
if (providerId === "opencodego") return typeof tokens.apiKey === "string" && tokens.apiKey.length > 0;
|
|
9619
|
+
return typeof tokens.accessToken === "string" && tokens.accessToken.length > 0;
|
|
9620
|
+
}
|
|
9621
|
+
function safeProviderId(value) {
|
|
9622
|
+
if (!PROVIDERS.has(value)) {
|
|
9623
|
+
throw new import_provider_proxy3.RouteLeaseError("upstream_not_found", "subscription provider was not found");
|
|
9624
|
+
}
|
|
9625
|
+
return value;
|
|
9626
|
+
}
|
|
9627
|
+
function createRouteLeaseSubscriptionPreflight(credentials) {
|
|
9628
|
+
return {
|
|
9629
|
+
async assertAvailable(upstream, model) {
|
|
9630
|
+
const providerId = safeProviderId(upstream.providerId);
|
|
9631
|
+
const config = await credentials.getFullConfig();
|
|
9632
|
+
const all = accountArray(config, providerId);
|
|
9633
|
+
if (all.length === 0) {
|
|
9634
|
+
throw new import_provider_proxy3.RouteLeaseError("upstream_unavailable", "subscription provider has no configured account");
|
|
9635
|
+
}
|
|
9636
|
+
let bounded = all;
|
|
9637
|
+
if (upstream.kind === "account") {
|
|
9638
|
+
bounded = all.filter((account) => account.id === upstream.accountId);
|
|
9639
|
+
} else if (upstream.kind === "account-group") {
|
|
9640
|
+
bounded = all.filter((account) => account.group?.trim() === upstream.group);
|
|
9641
|
+
}
|
|
9642
|
+
if (bounded.length === 0) {
|
|
9643
|
+
throw new import_provider_proxy3.RouteLeaseError("upstream_not_found", "the selected subscription resource was not found");
|
|
9644
|
+
}
|
|
9645
|
+
const modelEligible = bounded.filter(
|
|
9646
|
+
(account) => (0, import_accountModelMap.accountSupportsModel)(account.supportedModels, model)
|
|
9647
|
+
);
|
|
9648
|
+
if (modelEligible.length === 0) {
|
|
9649
|
+
throw new import_provider_proxy3.RouteLeaseError("model_not_configured", "model is not supported by the selected subscription resource");
|
|
9650
|
+
}
|
|
9651
|
+
const credentialEligible = modelEligible.filter(
|
|
9652
|
+
(account) => account.enabled !== false && hasCredential(providerId, account)
|
|
9653
|
+
);
|
|
9654
|
+
const health2 = (0, import_SubscriptionAccountHealth3.getSharedAccountHealth)();
|
|
9655
|
+
const allowance = (0, import_AccountAllowanceScheduling4.getSharedAccountAllowanceScheduling)();
|
|
9656
|
+
const candidates = credentialEligible.filter(
|
|
9657
|
+
(account) => health2.isSchedulable(providerId, account.id) && allowance.preview(providerId, account.id, account.priority ?? 50).schedulable
|
|
9658
|
+
);
|
|
9659
|
+
if (candidates.length > 0) return;
|
|
9660
|
+
if (upstream.kind === "account") {
|
|
9661
|
+
throw new import_provider_proxy3.RouteLeaseError("upstream_unavailable", "the selected subscription account is unavailable");
|
|
9662
|
+
}
|
|
9663
|
+
throw new import_provider_proxy3.RouteLeaseError("upstream_exhausted", "the selected subscription pool has no eligible account", {
|
|
9664
|
+
retryAfterSeconds: 30
|
|
9665
|
+
});
|
|
9666
|
+
}
|
|
9667
|
+
};
|
|
9668
|
+
}
|
|
9669
|
+
|
|
9237
9670
|
// src/webhook/WebhookDispatcher.ts
|
|
9238
9671
|
var import_node_crypto14 = require("crypto");
|
|
9239
9672
|
var import_upstreamFetch7 = require("@omnicross/core/pipeline/upstreamFetch");
|
|
@@ -9416,7 +9849,7 @@ function buildDaemon(config, paths) {
|
|
|
9416
9849
|
new JsonAccountAllowancePersistence(defaultAccountAllowancePath(paths.configPath))
|
|
9417
9850
|
);
|
|
9418
9851
|
(0, import_AccountAllowanceStore4.setSharedAccountAllowanceStore)(accountAllowanceStore);
|
|
9419
|
-
(0,
|
|
9852
|
+
(0, import_AccountAllowanceScheduling5.getSharedAccountAllowanceScheduling)().configure(
|
|
9420
9853
|
(0, import_outbound_api4.normalizeServerConfig)(decryptedConfig.server).allowanceScheduling
|
|
9421
9854
|
);
|
|
9422
9855
|
const llmConfig = new ConfigFileProviderConfigSource(decryptedConfig);
|
|
@@ -9483,11 +9916,22 @@ function buildDaemon(config, paths) {
|
|
|
9483
9916
|
const usageRecorder = new import_usage.UsageRecorder(usageEventStore, pricingEngine, logger, {
|
|
9484
9917
|
onRecord: (apiKeyId, costUsd, at) => keySpendTracker.add(apiKeyId, costUsd, at)
|
|
9485
9918
|
});
|
|
9486
|
-
const providerProxy = (0,
|
|
9919
|
+
const providerProxy = (0, import_provider_proxy4.getProviderProxy)({ llmConfig, apiKeyPool, usageRecorder });
|
|
9920
|
+
const routeLeaseManager = new import_provider_proxy4.RouteLeaseManager(
|
|
9921
|
+
providerProxy,
|
|
9922
|
+
new import_provider_proxy4.RouteLeaseTargetResolver(llmConfig, {
|
|
9923
|
+
providerKeys: apiKeyPool,
|
|
9924
|
+
subscriptions: createRouteLeaseSubscriptionPreflight(credentialStore)
|
|
9925
|
+
}),
|
|
9926
|
+
import_cli_launcher2.routeLeaseDescriptorPort,
|
|
9927
|
+
{ logger }
|
|
9928
|
+
);
|
|
9929
|
+
providerProxy.registerBeforeStop(() => routeLeaseManager.shutdown());
|
|
9930
|
+
providerProxy.registerBeforeStop(() => resetCliSessions());
|
|
9487
9931
|
llmConfig.setReloadHook(() => apiKeyPool.invalidateCache());
|
|
9488
9932
|
const accountHealthProbeScheduler = new AccountHealthProbeScheduler(
|
|
9489
9933
|
credentialStore,
|
|
9490
|
-
(0,
|
|
9934
|
+
(0, import_SubscriptionAccountHealth4.getSharedAccountHealth)(),
|
|
9491
9935
|
logger,
|
|
9492
9936
|
import_outbound_api4.DEFAULT_ACCOUNT_PROBE
|
|
9493
9937
|
);
|
|
@@ -9534,6 +9978,7 @@ function buildDaemon(config, paths) {
|
|
|
9534
9978
|
keySpendReader: keySpendTracker,
|
|
9535
9979
|
settingsStore,
|
|
9536
9980
|
outboundApiServer,
|
|
9981
|
+
routeLeaseManager,
|
|
9537
9982
|
subscriptionAccounts,
|
|
9538
9983
|
accountAllowanceService,
|
|
9539
9984
|
allowanceRefreshScheduler: claudeAllowanceRefreshScheduler,
|
|
@@ -9626,7 +10071,7 @@ function buildDaemon(config, paths) {
|
|
|
9626
10071
|
logger,
|
|
9627
10072
|
fetchImpl: (url, init) => (0, import_upstreamFetch8.fetchUpstream)(url, init)
|
|
9628
10073
|
});
|
|
9629
|
-
setWebhookRuntime(webhookDispatcher, (0,
|
|
10074
|
+
setWebhookRuntime(webhookDispatcher, (0, import_SubscriptionAccountHealth4.getSharedAccountHealth)());
|
|
9630
10075
|
const auditWriter = new AuditWriter(auditDir, logger);
|
|
9631
10076
|
const auditPruneSweeper = new AuditPruneSweeper(auditDir, logger, import_audit_types.DEFAULT_AUDIT_CONFIG);
|
|
9632
10077
|
setAuditRuntime(auditWriter, auditPruneSweeper);
|
|
@@ -9641,7 +10086,7 @@ function buildDaemon(config, paths) {
|
|
|
9641
10086
|
const tokenRefreshScheduler = new TokenRefreshScheduler(credentialStore, logger);
|
|
9642
10087
|
const accountHealthSweeper = new AccountHealthSweeper(
|
|
9643
10088
|
credentialStore,
|
|
9644
|
-
(0,
|
|
10089
|
+
(0, import_SubscriptionAccountHealth4.getSharedAccountHealth)(),
|
|
9645
10090
|
logger
|
|
9646
10091
|
);
|
|
9647
10092
|
return {
|
|
@@ -9650,6 +10095,7 @@ function buildDaemon(config, paths) {
|
|
|
9650
10095
|
keyDb,
|
|
9651
10096
|
settingsStore,
|
|
9652
10097
|
providerProxy,
|
|
10098
|
+
routeLeaseManager,
|
|
9653
10099
|
outboundApiServer,
|
|
9654
10100
|
apiKeyPool,
|
|
9655
10101
|
autoDisableStore,
|
|
@@ -9674,7 +10120,7 @@ function buildDaemon(config, paths) {
|
|
|
9674
10120
|
};
|
|
9675
10121
|
}
|
|
9676
10122
|
function resetDaemonSingletonsForTests() {
|
|
9677
|
-
(0,
|
|
10123
|
+
(0, import_provider_proxy4.__resetProviderProxyForTests)();
|
|
9678
10124
|
(0, import_outbound_api4.__resetOutboundApiServerForTests)();
|
|
9679
10125
|
(0, import_subscriptionRegistryPort.setSubscriptionRegistryForOutbound)(null);
|
|
9680
10126
|
(0, import_subscriptions4.setSubscriptionProviderRegistry)(null);
|
|
@@ -9689,7 +10135,7 @@ function resetDaemonSingletonsForTests() {
|
|
|
9689
10135
|
resetBillingRuntimeForTests();
|
|
9690
10136
|
(0, import_SubscriptionIdentityStore3.__resetSharedIdentityStoreForTests)();
|
|
9691
10137
|
(0, import_AccountAllowanceStore4.__resetSharedAccountAllowanceStoreForTests)();
|
|
9692
|
-
(0,
|
|
10138
|
+
(0, import_AccountAllowanceScheduling5.__resetSharedAccountAllowanceSchedulingForTests)();
|
|
9693
10139
|
}
|
|
9694
10140
|
function isTokensStoreReadable(tokensPath) {
|
|
9695
10141
|
try {
|