omnigateway 0.1.7 → 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/omni.js +351 -124
- package/gateway.js +402 -182
- package/package.json +1 -1
- package/public/assets/{Chip-C69u2U_b.js → Chip-CM9ZMdr9.js} +1 -1
- package/public/assets/{CopyValue-CJy2T0H6.js → CopyValue-WrOTcHwq.js} +4 -4
- package/public/assets/{Field-Sc8mDqJv.js → Field-Br6jKPz8.js} +8 -8
- package/public/assets/{Lamp-7jD_9929.js → Lamp-DO-sRDg2.js} +7 -7
- package/public/assets/{Meter-C0nUftAa.js → Meter-BzMaum0C.js} +1 -1
- package/public/assets/{Modal-CiVHSJmm.js → Modal-lhjr949H.js} +8 -8
- package/public/assets/{Rack-CMqGBP4I.js → Rack-BFWC50ex.js} +18 -18
- package/public/assets/{Readout-Dv2dZWtI.js → Readout-DMJs4gYD.js} +5 -5
- package/public/assets/{States-D55MhqMx.js → States-BNeCLhZn.js} +10 -10
- package/public/assets/{Table-DBB3jdgi.js → Table-nOg_lgEJ.js} +1 -1
- package/public/assets/{Toggle-BoGjb5oi.js → Toggle-DYoCVD37.js} +2 -2
- package/public/assets/_app-lXr06Xli.js +1 -0
- package/public/assets/_app.accounts-BTb5vHI_.js +51 -0
- package/public/assets/{_app.console-Bka7AkiL.js → _app.console-DHUClMsI.js} +7 -7
- package/public/assets/_app.index-DZ--9mKU.js +61 -0
- package/public/assets/{_app.keys-BX8k8COP.js → _app.keys-B-cy-2DS.js} +8 -8
- package/public/assets/_app.logs-BQjAIT2P.js +33 -0
- package/public/assets/_app.models-BAmXHlf2.js +144 -0
- package/public/assets/_app.settings-CG8bv_rm.js +34 -0
- package/public/assets/{_app.usage-BRhEvwVr.js → _app.usage-BLrQ2hB8.js} +28 -28
- package/public/assets/index-UAZ0O5y0.js +170 -0
- package/public/assets/{login-DaC-wVpI.js → login-BpUl6C5b.js} +8 -8
- package/public/assets/{queries-2E6-CboE.js → queries-D_-Jj9vt.js} +1 -1
- package/public/assets/{trash-2--aH2iKg-.js → trash-2-DjWP2u19.js} +1 -1
- package/public/index.html +2 -2
- package/public/assets/_app-p5Mz7sXD.js +0 -1
- package/public/assets/_app.accounts-B5wMO9TH.js +0 -51
- package/public/assets/_app.index-MnQuadXb.js +0 -61
- package/public/assets/_app.logs-DD-sd4fn.js +0 -33
- package/public/assets/_app.models-CezFNL6y.js +0 -144
- package/public/assets/_app.settings-D1taAt8B.js +0 -16
- package/public/assets/index-vCuK1fRQ.js +0 -170
package/bin/omni.js
CHANGED
|
@@ -90,6 +90,11 @@ function formatUsd(value) {
|
|
|
90
90
|
return `$${value.toFixed(value < 1 ? 4 : 2)}`;
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
+
// apps/cli/src/run.ts
|
|
94
|
+
import { mkdirSync as mkdirSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
95
|
+
import { homedir as homedir3 } from "os";
|
|
96
|
+
import { dirname as dirname3 } from "path";
|
|
97
|
+
|
|
93
98
|
// packages/control/src/adminAuth.ts
|
|
94
99
|
import { hash, verify } from "@node-rs/argon2";
|
|
95
100
|
var MIN_PASSWORD_LENGTH = 12;
|
|
@@ -233,6 +238,7 @@ function usageFromPromptTotal(promptTokens, outputTokens, cacheReadTokens, cache
|
|
|
233
238
|
}
|
|
234
239
|
// packages/control/src/config.ts
|
|
235
240
|
var MIN_KEY_LENGTH = 16;
|
|
241
|
+
var TRUTHY = new Set(["1", "true", "yes", "on"]);
|
|
236
242
|
var DECIMAL_INTEGER = /^\d+$/;
|
|
237
243
|
function optionalText(value, fallback) {
|
|
238
244
|
return value?.trim() || fallback;
|
|
@@ -252,6 +258,7 @@ function loadConfig(env) {
|
|
|
252
258
|
const baseUrl = optionalText(env.OMNI_BASE_URL, derivedBaseUrl).replace(/\/+$/, "") || derivedBaseUrl;
|
|
253
259
|
const staticDir = env.OMNI_STATIC_DIR?.trim();
|
|
254
260
|
const logFile = env.OMNI_LOG_FILE?.trim();
|
|
261
|
+
const exposeClaudeCodeAliases = TRUTHY.has((env.OMNI_EXPOSE_CLAUDE_CODE_ALIASES ?? "").trim().toLowerCase());
|
|
255
262
|
const rawLogLevel = env.OMNI_LOG_LEVEL?.trim();
|
|
256
263
|
const logLevel = parseLogLevel(rawLogLevel);
|
|
257
264
|
return {
|
|
@@ -263,9 +270,14 @@ function loadConfig(env) {
|
|
|
263
270
|
encryptionKey,
|
|
264
271
|
baseUrl,
|
|
265
272
|
staticDir: staticDir === undefined || staticDir.length === 0 ? null : staticDir,
|
|
273
|
+
exposeClaudeCodeAliases,
|
|
266
274
|
logFile: logFile === undefined || logFile.length === 0 ? null : logFile
|
|
267
275
|
};
|
|
268
276
|
}
|
|
277
|
+
// packages/providers/src/betas.ts
|
|
278
|
+
var CONTEXT_1M_BETA = "context-1m-2025-08-07";
|
|
279
|
+
var CONTEXT_1M_TOKENS = 1e6;
|
|
280
|
+
|
|
269
281
|
// packages/providers/src/body.ts
|
|
270
282
|
var BODY_ORDER = {
|
|
271
283
|
anthropic: [
|
|
@@ -373,6 +385,119 @@ function signAnthropicBody(json) {
|
|
|
373
385
|
return json.replace(needle, `cch=${computeCch(json)};`);
|
|
374
386
|
}
|
|
375
387
|
|
|
388
|
+
// packages/providers/src/anthropic/models.ts
|
|
389
|
+
var ANTHROPIC_MODELS = {
|
|
390
|
+
defaultModel: "claude-opus-5",
|
|
391
|
+
models: [
|
|
392
|
+
{
|
|
393
|
+
id: "claude-fable-5",
|
|
394
|
+
label: "Claude Fable 5",
|
|
395
|
+
pricing: { input: 10, output: 50, cacheRead: 1, cacheWrite5m: 12.5, cacheWrite1h: 20 },
|
|
396
|
+
limits: { contextWindow: 1e6, maxOutputTokens: 128000 }
|
|
397
|
+
},
|
|
398
|
+
{
|
|
399
|
+
id: "claude-opus-5",
|
|
400
|
+
label: "Claude Opus 5",
|
|
401
|
+
pricing: { input: 5, output: 25, cacheRead: 0.5, cacheWrite5m: 6.25, cacheWrite1h: 10 },
|
|
402
|
+
limits: { contextWindow: 1e6, maxOutputTokens: 128000 }
|
|
403
|
+
},
|
|
404
|
+
{
|
|
405
|
+
id: "claude-sonnet-5",
|
|
406
|
+
label: "Claude Sonnet 5",
|
|
407
|
+
pricing: { input: 3, output: 15, cacheRead: 0.3, cacheWrite5m: 3.75, cacheWrite1h: 6 },
|
|
408
|
+
limits: { contextWindow: 1e6, maxOutputTokens: 128000 }
|
|
409
|
+
},
|
|
410
|
+
{
|
|
411
|
+
id: "claude-haiku-4-5",
|
|
412
|
+
label: "Claude Haiku 4.5",
|
|
413
|
+
pricing: { input: 1, output: 5, cacheRead: 0.1, cacheWrite5m: 1.25, cacheWrite1h: 2 },
|
|
414
|
+
limits: { contextWindow: 200000, maxOutputTokens: 64000 }
|
|
415
|
+
}
|
|
416
|
+
]
|
|
417
|
+
};
|
|
418
|
+
|
|
419
|
+
// packages/providers/src/kimi/models.ts
|
|
420
|
+
var KIMI_MODELS = {
|
|
421
|
+
defaultModel: "k3-256k",
|
|
422
|
+
models: [
|
|
423
|
+
{
|
|
424
|
+
id: "k3-256k",
|
|
425
|
+
label: "Kimi K3 \u2014 256K",
|
|
426
|
+
pricing: { input: 3, output: 15, cacheRead: 0.3, cacheWrite5m: 0, cacheWrite1h: 0 },
|
|
427
|
+
limits: { contextWindow: 262144, maxOutputTokens: 131072 }
|
|
428
|
+
},
|
|
429
|
+
{
|
|
430
|
+
id: "k3",
|
|
431
|
+
label: "Kimi K3 \u2014 up to 1M",
|
|
432
|
+
pricing: { input: 3, output: 15, cacheRead: 0.3, cacheWrite5m: 0, cacheWrite1h: 0 },
|
|
433
|
+
limits: { contextWindow: 1048576, maxOutputTokens: 131072 }
|
|
434
|
+
},
|
|
435
|
+
{
|
|
436
|
+
id: "kimi-for-coding",
|
|
437
|
+
label: "Kimi K2.7 Code",
|
|
438
|
+
pricing: { input: 0.95, output: 4, cacheRead: 0.19, cacheWrite5m: 0, cacheWrite1h: 0 },
|
|
439
|
+
limits: { contextWindow: 262144, maxOutputTokens: 131072 }
|
|
440
|
+
},
|
|
441
|
+
{
|
|
442
|
+
id: "kimi-for-coding-highspeed",
|
|
443
|
+
label: "Kimi K2.7 Code \u2014 High Speed",
|
|
444
|
+
pricing: { input: 0.95, output: 8, cacheRead: 0.19, cacheWrite5m: 0, cacheWrite1h: 0 },
|
|
445
|
+
limits: { contextWindow: 262144, maxOutputTokens: 131072 }
|
|
446
|
+
}
|
|
447
|
+
]
|
|
448
|
+
};
|
|
449
|
+
|
|
450
|
+
// packages/providers/src/openai/models.ts
|
|
451
|
+
var OPENAI_MODELS = {
|
|
452
|
+
defaultModel: "gpt-5.6",
|
|
453
|
+
models: [
|
|
454
|
+
{
|
|
455
|
+
id: "gpt-5.6",
|
|
456
|
+
label: "GPT-5.6 \u2014 routes to Sol",
|
|
457
|
+
pricing: { input: 5, output: 30, cacheRead: 0.5, cacheWrite5m: 0, cacheWrite1h: 0 },
|
|
458
|
+
limits: { contextWindow: 922000, maxOutputTokens: 128000 },
|
|
459
|
+
oauthLimits: { contextWindow: 272000, maxOutputTokens: 128000 }
|
|
460
|
+
},
|
|
461
|
+
{
|
|
462
|
+
id: "gpt-5.6-sol",
|
|
463
|
+
label: "GPT-5.6 Sol \u2014 deepest reasoning",
|
|
464
|
+
pricing: { input: 5, output: 30, cacheRead: 0.5, cacheWrite5m: 0, cacheWrite1h: 0 },
|
|
465
|
+
limits: { contextWindow: 922000, maxOutputTokens: 128000 },
|
|
466
|
+
oauthLimits: { contextWindow: 272000, maxOutputTokens: 128000 }
|
|
467
|
+
},
|
|
468
|
+
{
|
|
469
|
+
id: "gpt-5.6-terra",
|
|
470
|
+
label: "GPT-5.6 Terra \u2014 balanced",
|
|
471
|
+
pricing: { input: 2, output: 12, cacheRead: 0.2, cacheWrite5m: 0, cacheWrite1h: 0 },
|
|
472
|
+
limits: { contextWindow: 922000, maxOutputTokens: 128000 },
|
|
473
|
+
oauthLimits: { contextWindow: 272000, maxOutputTokens: 128000 }
|
|
474
|
+
},
|
|
475
|
+
{
|
|
476
|
+
id: "gpt-5.6-luna",
|
|
477
|
+
label: "GPT-5.6 Luna \u2014 fastest",
|
|
478
|
+
pricing: { input: 0.2, output: 1.2, cacheRead: 0.02, cacheWrite5m: 0, cacheWrite1h: 0 },
|
|
479
|
+
limits: { contextWindow: 922000, maxOutputTokens: 128000 },
|
|
480
|
+
oauthLimits: { contextWindow: 272000, maxOutputTokens: 128000 }
|
|
481
|
+
}
|
|
482
|
+
]
|
|
483
|
+
};
|
|
484
|
+
|
|
485
|
+
// packages/providers/src/catalog.ts
|
|
486
|
+
var PROVIDER_MODEL_CATALOG = {
|
|
487
|
+
anthropic: ANTHROPIC_MODELS,
|
|
488
|
+
openai: OPENAI_MODELS,
|
|
489
|
+
kimi: KIMI_MODELS
|
|
490
|
+
};
|
|
491
|
+
function catalogPricing(provider, model) {
|
|
492
|
+
return PROVIDER_MODEL_CATALOG[provider]?.models.find((entry) => entry.id === model)?.pricing ?? null;
|
|
493
|
+
}
|
|
494
|
+
function catalogLimits(provider, model, auth = "apiKey") {
|
|
495
|
+
const entry = PROVIDER_MODEL_CATALOG[provider]?.models.find((choice) => choice.id === model);
|
|
496
|
+
if (entry === undefined)
|
|
497
|
+
return null;
|
|
498
|
+
return (auth === "oauth" ? entry.oauthLimits : undefined) ?? entry.limits;
|
|
499
|
+
}
|
|
500
|
+
|
|
376
501
|
// packages/providers/src/http.ts
|
|
377
502
|
function codeForStatus(status) {
|
|
378
503
|
if (status === 401 || status === 403)
|
|
@@ -930,6 +1055,15 @@ var anthropicAdapter = {
|
|
|
930
1055
|
["Accept", "text/event-stream"]
|
|
931
1056
|
];
|
|
932
1057
|
const betas = new Set(req.request.betas ?? []);
|
|
1058
|
+
const notes = [...degradations];
|
|
1059
|
+
if (betas.has(CONTEXT_1M_BETA)) {
|
|
1060
|
+
const limits = catalogLimits("anthropic", req.model, oauth ? "oauth" : "apiKey");
|
|
1061
|
+
const window = limits?.contextWindow;
|
|
1062
|
+
if (window !== undefined && window < CONTEXT_1M_TOKENS) {
|
|
1063
|
+
betas.delete(CONTEXT_1M_BETA);
|
|
1064
|
+
notes.push("anthropic:context-1m-dropped");
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
933
1067
|
if (oauth) {
|
|
934
1068
|
protocol.push(["Authorization", `Bearer ${req.credentials.accessToken}`]);
|
|
935
1069
|
betas.add(OAUTH_BETA);
|
|
@@ -957,121 +1091,9 @@ var anthropicAdapter = {
|
|
|
957
1091
|
throw await httpError(res, "anthropic");
|
|
958
1092
|
if (res.body === null)
|
|
959
1093
|
throw new GatewayError("UPSTREAM", "empty response body", { provider: "anthropic" });
|
|
960
|
-
return { events: decodeAnthropic(parseSse(res.body)), degradations };
|
|
1094
|
+
return { events: decodeAnthropic(parseSse(res.body)), degradations: notes };
|
|
961
1095
|
}
|
|
962
1096
|
};
|
|
963
|
-
// packages/providers/src/anthropic/models.ts
|
|
964
|
-
var ANTHROPIC_MODELS = {
|
|
965
|
-
defaultModel: "claude-opus-5",
|
|
966
|
-
models: [
|
|
967
|
-
{
|
|
968
|
-
id: "claude-fable-5",
|
|
969
|
-
label: "Claude Fable 5",
|
|
970
|
-
pricing: { input: 10, output: 50, cacheRead: 1, cacheWrite5m: 12.5, cacheWrite1h: 20 },
|
|
971
|
-
limits: { contextWindow: 1e6, maxOutputTokens: 128000 }
|
|
972
|
-
},
|
|
973
|
-
{
|
|
974
|
-
id: "claude-opus-5",
|
|
975
|
-
label: "Claude Opus 5",
|
|
976
|
-
pricing: { input: 5, output: 25, cacheRead: 0.5, cacheWrite5m: 6.25, cacheWrite1h: 10 },
|
|
977
|
-
limits: { contextWindow: 1e6, maxOutputTokens: 128000 }
|
|
978
|
-
},
|
|
979
|
-
{
|
|
980
|
-
id: "claude-sonnet-5",
|
|
981
|
-
label: "Claude Sonnet 5",
|
|
982
|
-
pricing: { input: 3, output: 15, cacheRead: 0.3, cacheWrite5m: 3.75, cacheWrite1h: 6 },
|
|
983
|
-
limits: { contextWindow: 1e6, maxOutputTokens: 128000 }
|
|
984
|
-
},
|
|
985
|
-
{
|
|
986
|
-
id: "claude-haiku-4-5",
|
|
987
|
-
label: "Claude Haiku 4.5",
|
|
988
|
-
pricing: { input: 1, output: 5, cacheRead: 0.1, cacheWrite5m: 1.25, cacheWrite1h: 2 },
|
|
989
|
-
limits: { contextWindow: 200000, maxOutputTokens: 64000 }
|
|
990
|
-
}
|
|
991
|
-
]
|
|
992
|
-
};
|
|
993
|
-
|
|
994
|
-
// packages/providers/src/kimi/models.ts
|
|
995
|
-
var KIMI_MODELS = {
|
|
996
|
-
defaultModel: "k3-256k",
|
|
997
|
-
models: [
|
|
998
|
-
{
|
|
999
|
-
id: "k3-256k",
|
|
1000
|
-
label: "Kimi K3 \u2014 256K",
|
|
1001
|
-
pricing: { input: 3, output: 15, cacheRead: 0.3, cacheWrite5m: 0, cacheWrite1h: 0 },
|
|
1002
|
-
limits: { contextWindow: 262144, maxOutputTokens: 131072 }
|
|
1003
|
-
},
|
|
1004
|
-
{
|
|
1005
|
-
id: "k3",
|
|
1006
|
-
label: "Kimi K3 \u2014 up to 1M",
|
|
1007
|
-
pricing: { input: 3, output: 15, cacheRead: 0.3, cacheWrite5m: 0, cacheWrite1h: 0 },
|
|
1008
|
-
limits: { contextWindow: 1048576, maxOutputTokens: 131072 }
|
|
1009
|
-
},
|
|
1010
|
-
{
|
|
1011
|
-
id: "kimi-for-coding",
|
|
1012
|
-
label: "Kimi K2.7 Code",
|
|
1013
|
-
pricing: { input: 0.95, output: 4, cacheRead: 0.19, cacheWrite5m: 0, cacheWrite1h: 0 },
|
|
1014
|
-
limits: { contextWindow: 262144, maxOutputTokens: 131072 }
|
|
1015
|
-
},
|
|
1016
|
-
{
|
|
1017
|
-
id: "kimi-for-coding-highspeed",
|
|
1018
|
-
label: "Kimi K2.7 Code \u2014 High Speed",
|
|
1019
|
-
pricing: { input: 0.95, output: 8, cacheRead: 0.19, cacheWrite5m: 0, cacheWrite1h: 0 },
|
|
1020
|
-
limits: { contextWindow: 262144, maxOutputTokens: 131072 }
|
|
1021
|
-
}
|
|
1022
|
-
]
|
|
1023
|
-
};
|
|
1024
|
-
|
|
1025
|
-
// packages/providers/src/openai/models.ts
|
|
1026
|
-
var OPENAI_MODELS = {
|
|
1027
|
-
defaultModel: "gpt-5.6",
|
|
1028
|
-
models: [
|
|
1029
|
-
{
|
|
1030
|
-
id: "gpt-5.6",
|
|
1031
|
-
label: "GPT-5.6 \u2014 routes to Sol",
|
|
1032
|
-
pricing: { input: 5, output: 30, cacheRead: 0.5, cacheWrite5m: 0, cacheWrite1h: 0 },
|
|
1033
|
-
limits: { contextWindow: 922000, maxOutputTokens: 128000 },
|
|
1034
|
-
oauthLimits: { contextWindow: 272000, maxOutputTokens: 128000 }
|
|
1035
|
-
},
|
|
1036
|
-
{
|
|
1037
|
-
id: "gpt-5.6-sol",
|
|
1038
|
-
label: "GPT-5.6 Sol \u2014 deepest reasoning",
|
|
1039
|
-
pricing: { input: 5, output: 30, cacheRead: 0.5, cacheWrite5m: 0, cacheWrite1h: 0 },
|
|
1040
|
-
limits: { contextWindow: 922000, maxOutputTokens: 128000 },
|
|
1041
|
-
oauthLimits: { contextWindow: 272000, maxOutputTokens: 128000 }
|
|
1042
|
-
},
|
|
1043
|
-
{
|
|
1044
|
-
id: "gpt-5.6-terra",
|
|
1045
|
-
label: "GPT-5.6 Terra \u2014 balanced",
|
|
1046
|
-
pricing: { input: 2, output: 12, cacheRead: 0.2, cacheWrite5m: 0, cacheWrite1h: 0 },
|
|
1047
|
-
limits: { contextWindow: 922000, maxOutputTokens: 128000 },
|
|
1048
|
-
oauthLimits: { contextWindow: 272000, maxOutputTokens: 128000 }
|
|
1049
|
-
},
|
|
1050
|
-
{
|
|
1051
|
-
id: "gpt-5.6-luna",
|
|
1052
|
-
label: "GPT-5.6 Luna \u2014 fastest",
|
|
1053
|
-
pricing: { input: 0.2, output: 1.2, cacheRead: 0.02, cacheWrite5m: 0, cacheWrite1h: 0 },
|
|
1054
|
-
limits: { contextWindow: 922000, maxOutputTokens: 128000 },
|
|
1055
|
-
oauthLimits: { contextWindow: 272000, maxOutputTokens: 128000 }
|
|
1056
|
-
}
|
|
1057
|
-
]
|
|
1058
|
-
};
|
|
1059
|
-
|
|
1060
|
-
// packages/providers/src/catalog.ts
|
|
1061
|
-
var PROVIDER_MODEL_CATALOG = {
|
|
1062
|
-
anthropic: ANTHROPIC_MODELS,
|
|
1063
|
-
openai: OPENAI_MODELS,
|
|
1064
|
-
kimi: KIMI_MODELS
|
|
1065
|
-
};
|
|
1066
|
-
function catalogPricing(provider, model) {
|
|
1067
|
-
return PROVIDER_MODEL_CATALOG[provider]?.models.find((entry) => entry.id === model)?.pricing ?? null;
|
|
1068
|
-
}
|
|
1069
|
-
function catalogLimits(provider, model, auth = "apiKey") {
|
|
1070
|
-
const entry = PROVIDER_MODEL_CATALOG[provider]?.models.find((choice) => choice.id === model);
|
|
1071
|
-
if (entry === undefined)
|
|
1072
|
-
return null;
|
|
1073
|
-
return (auth === "oauth" ? entry.oauthLimits : undefined) ?? entry.limits;
|
|
1074
|
-
}
|
|
1075
1097
|
// packages/providers/src/http-client.ts
|
|
1076
1098
|
import { request as httpRequest } from "http";
|
|
1077
1099
|
import { request as httpsRequest } from "https";
|
|
@@ -1297,6 +1319,8 @@ function toChatWire(req, model) {
|
|
|
1297
1319
|
if (!degradations.includes(d))
|
|
1298
1320
|
degradations.push(d);
|
|
1299
1321
|
};
|
|
1322
|
+
if (req.betas?.includes(CONTEXT_1M_BETA))
|
|
1323
|
+
note2("kimi:context-1m-dropped");
|
|
1300
1324
|
const messages = [];
|
|
1301
1325
|
const system = req.system?.flatMap((b) => b.type === "text" ? [b.text] : []).join(`
|
|
1302
1326
|
|
|
@@ -1573,6 +1597,8 @@ function toResponsesWire(req, model, opts = { oauth: false }) {
|
|
|
1573
1597
|
if (!degradations.includes(d))
|
|
1574
1598
|
degradations.push(d);
|
|
1575
1599
|
};
|
|
1600
|
+
if (req.betas?.includes(CONTEXT_1M_BETA))
|
|
1601
|
+
note2("openai:context-1m-dropped");
|
|
1576
1602
|
for (const message of req.messages) {
|
|
1577
1603
|
const parts = [];
|
|
1578
1604
|
const inlined = message.role === "system";
|
|
@@ -2261,12 +2287,10 @@ async function readSource(deps, source, lines) {
|
|
|
2261
2287
|
return "";
|
|
2262
2288
|
if (source.kind === "file")
|
|
2263
2289
|
return deps.readFile(source.path, lines) ?? "";
|
|
2264
|
-
const
|
|
2290
|
+
const unit = source.scope === "system" ? ["-u", source.unit] : [`--user-unit=${source.unit}`];
|
|
2265
2291
|
const result = await deps.run([
|
|
2266
2292
|
"journalctl",
|
|
2267
|
-
...
|
|
2268
|
-
"-u",
|
|
2269
|
-
source.unit,
|
|
2293
|
+
...unit,
|
|
2270
2294
|
"-n",
|
|
2271
2295
|
String(lines),
|
|
2272
2296
|
"--no-pager",
|
|
@@ -16573,7 +16597,9 @@ var dryRunSchema = exports_external.object({
|
|
|
16573
16597
|
reasoning: exports_external.boolean().default(false)
|
|
16574
16598
|
}).strict();
|
|
16575
16599
|
var modelSchema = exports_external.object({
|
|
16576
|
-
id: exports_external.string().min(1),
|
|
16600
|
+
id: exports_external.string().min(1).refine((value) => !value.toLowerCase().startsWith("claude/"), {
|
|
16601
|
+
message: 'model id must not start with "claude/": that prefix is reserved for discovery mirrors'
|
|
16602
|
+
}),
|
|
16577
16603
|
strategy: exports_external.enum(["score", "priority", "roundRobin", "weighted"]),
|
|
16578
16604
|
isAlias: exports_external.boolean(),
|
|
16579
16605
|
targets: exports_external.array(exports_external.object({
|
|
@@ -17985,6 +18011,60 @@ async function createKey(store, input) {
|
|
|
17985
18011
|
async function revokeKey(store, id) {
|
|
17986
18012
|
await store.keys.revoke(id);
|
|
17987
18013
|
}
|
|
18014
|
+
// packages/control/src/modelLimits.ts
|
|
18015
|
+
function narrower(a, b) {
|
|
18016
|
+
const context = [a.contextWindow, b.contextWindow].filter((n) => n !== undefined);
|
|
18017
|
+
const output = [a.maxOutputTokens, b.maxOutputTokens].filter((n) => n !== undefined);
|
|
18018
|
+
return {
|
|
18019
|
+
...context.length === 0 ? {} : { contextWindow: Math.min(...context) },
|
|
18020
|
+
...output.length === 0 ? {} : { maxOutputTokens: Math.min(...output) }
|
|
18021
|
+
};
|
|
18022
|
+
}
|
|
18023
|
+
function targetLimits(target, auths) {
|
|
18024
|
+
const ways = auths.size === 0 ? ["apiKey"] : [...auths];
|
|
18025
|
+
let listed = {};
|
|
18026
|
+
for (const auth of ways) {
|
|
18027
|
+
const entry = catalogLimits(target.provider, target.model, auth);
|
|
18028
|
+
if (entry === null)
|
|
18029
|
+
continue;
|
|
18030
|
+
listed = narrower(listed, {
|
|
18031
|
+
contextWindow: entry.contextWindow,
|
|
18032
|
+
maxOutputTokens: entry.maxOutputTokens
|
|
18033
|
+
});
|
|
18034
|
+
}
|
|
18035
|
+
const contextWindow = target.contextWindow ?? listed.contextWindow;
|
|
18036
|
+
const maxOutputTokens = target.maxOutputTokens ?? listed.maxOutputTokens;
|
|
18037
|
+
return {
|
|
18038
|
+
...contextWindow === undefined ? {} : { contextWindow },
|
|
18039
|
+
...maxOutputTokens === undefined ? {} : { maxOutputTokens }
|
|
18040
|
+
};
|
|
18041
|
+
}
|
|
18042
|
+
function servingAuths(credentials) {
|
|
18043
|
+
const byProvider = new Map;
|
|
18044
|
+
for (const credential of credentials) {
|
|
18045
|
+
if (!credential.enabled)
|
|
18046
|
+
continue;
|
|
18047
|
+
const ways = byProvider.get(credential.provider) ?? new Set;
|
|
18048
|
+
ways.add(credential.authType);
|
|
18049
|
+
byProvider.set(credential.provider, ways);
|
|
18050
|
+
}
|
|
18051
|
+
return byProvider;
|
|
18052
|
+
}
|
|
18053
|
+
function resolveModelLimits(model, credentials) {
|
|
18054
|
+
const auths = servingAuths(credentials);
|
|
18055
|
+
let limits = {};
|
|
18056
|
+
for (const target of model.targets) {
|
|
18057
|
+
limits = narrower(limits, targetLimits(target, auths.get(target.provider) ?? new Set));
|
|
18058
|
+
}
|
|
18059
|
+
return limits;
|
|
18060
|
+
}
|
|
18061
|
+
function modelDisplayName(model) {
|
|
18062
|
+
const only = model.targets.length === 1 ? model.targets[0] : undefined;
|
|
18063
|
+
if (only === undefined)
|
|
18064
|
+
return model.id;
|
|
18065
|
+
const labelled = PROVIDER_MODEL_CATALOG[only.provider]?.models.find((choice) => choice.id === only.model);
|
|
18066
|
+
return labelled?.label ?? model.id;
|
|
18067
|
+
}
|
|
17988
18068
|
// packages/control/src/models.ts
|
|
17989
18069
|
async function listModels(store) {
|
|
17990
18070
|
return store.config.listModels();
|
|
@@ -18341,6 +18421,71 @@ async function putSettings(store, input) {
|
|
|
18341
18421
|
await store.config.putSettings(settings);
|
|
18342
18422
|
return settings;
|
|
18343
18423
|
}
|
|
18424
|
+
// packages/control/src/setup.ts
|
|
18425
|
+
var KEY_PLACEHOLDER = "<your OmniGateway key>";
|
|
18426
|
+
async function describeModelsForSetup(store) {
|
|
18427
|
+
const models = await listModels(store);
|
|
18428
|
+
const credentials = (await listCredentials(store)).map((credential) => ({
|
|
18429
|
+
provider: credential.provider,
|
|
18430
|
+
authType: credential.authType,
|
|
18431
|
+
enabled: credential.enabled
|
|
18432
|
+
}));
|
|
18433
|
+
return models.map((model) => ({
|
|
18434
|
+
model,
|
|
18435
|
+
limits: resolveModelLimits(model, credentials),
|
|
18436
|
+
label: modelDisplayName(model)
|
|
18437
|
+
}));
|
|
18438
|
+
}
|
|
18439
|
+
function slug(id) {
|
|
18440
|
+
return encodeURIComponent(id).replace(/\./g, "%2E");
|
|
18441
|
+
}
|
|
18442
|
+
function claudeProfiles(described, input) {
|
|
18443
|
+
const apiKey = input.apiKey ?? KEY_PLACEHOLDER;
|
|
18444
|
+
return described.map(({ model, limits }) => {
|
|
18445
|
+
const useMirror = input.discoveryMirrors === true && !/^(?:claude|anthropic)/i.test(model.id);
|
|
18446
|
+
const modelId = useMirror ? `claude/${model.id}` : model.id;
|
|
18447
|
+
const env2 = {
|
|
18448
|
+
ANTHROPIC_BASE_URL: input.baseUrl,
|
|
18449
|
+
ANTHROPIC_AUTH_TOKEN: apiKey,
|
|
18450
|
+
ANTHROPIC_MODEL: modelId,
|
|
18451
|
+
CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY: "1"
|
|
18452
|
+
};
|
|
18453
|
+
if (limits.contextWindow !== undefined && !/^claude-/i.test(modelId)) {
|
|
18454
|
+
env2.CLAUDE_CODE_MAX_CONTEXT_TOKENS = String(limits.contextWindow);
|
|
18455
|
+
}
|
|
18456
|
+
return {
|
|
18457
|
+
path: `${slug(model.id)}/settings.json`,
|
|
18458
|
+
contents: `${JSON.stringify({ env: env2 }, null, 2)}
|
|
18459
|
+
`
|
|
18460
|
+
};
|
|
18461
|
+
});
|
|
18462
|
+
}
|
|
18463
|
+
function opencodeConfig(described, input) {
|
|
18464
|
+
const models = {};
|
|
18465
|
+
for (const { model, limits, label: label2 } of described) {
|
|
18466
|
+
const limit = limits.contextWindow === undefined ? undefined : {
|
|
18467
|
+
context: limits.contextWindow,
|
|
18468
|
+
...limits.maxOutputTokens === undefined ? {} : { output: limits.maxOutputTokens }
|
|
18469
|
+
};
|
|
18470
|
+
models[model.id] = { name: label2, ...limit === undefined ? {} : { limit } };
|
|
18471
|
+
}
|
|
18472
|
+
const contents = `${JSON.stringify({
|
|
18473
|
+
$schema: "https://opencode.ai/config.json",
|
|
18474
|
+
provider: {
|
|
18475
|
+
omnigateway: {
|
|
18476
|
+
npm: "@ai-sdk/openai-compatible",
|
|
18477
|
+
name: "OmniGateway",
|
|
18478
|
+
options: {
|
|
18479
|
+
baseURL: `${input.baseUrl.replace(/\/+$/, "").replace(/(?:\/v1)+$/i, "")}/v1`,
|
|
18480
|
+
apiKey: input.apiKey ?? KEY_PLACEHOLDER
|
|
18481
|
+
},
|
|
18482
|
+
models
|
|
18483
|
+
}
|
|
18484
|
+
}
|
|
18485
|
+
}, null, 2)}
|
|
18486
|
+
`;
|
|
18487
|
+
return { path: "opencode.json", contents };
|
|
18488
|
+
}
|
|
18344
18489
|
// packages/control/src/tail.ts
|
|
18345
18490
|
import { closeSync, fstatSync, openSync, readSync, statSync } from "fs";
|
|
18346
18491
|
var CHUNK = 64 * 1024;
|
|
@@ -19256,8 +19401,8 @@ var modelsShow = {
|
|
|
19256
19401
|
price(target.costPerMTok.cacheRead),
|
|
19257
19402
|
price(target.costPerMTok.cacheWrite5m),
|
|
19258
19403
|
price(target.costPerMTok.cacheWrite1h),
|
|
19259
|
-
|
|
19260
|
-
|
|
19404
|
+
tokens2(target.contextWindow),
|
|
19405
|
+
tokens2(target.maxOutputTokens),
|
|
19261
19406
|
capabilityList(target)
|
|
19262
19407
|
]))
|
|
19263
19408
|
].join(`
|
|
@@ -19267,7 +19412,7 @@ var modelsShow = {
|
|
|
19267
19412
|
function price(value) {
|
|
19268
19413
|
return value === undefined ? "\u2014" : value.toFixed(2);
|
|
19269
19414
|
}
|
|
19270
|
-
function
|
|
19415
|
+
function tokens2(value) {
|
|
19271
19416
|
return value === undefined ? "\u2014" : value.toLocaleString("en-US");
|
|
19272
19417
|
}
|
|
19273
19418
|
function capabilityList(target) {
|
|
@@ -19335,9 +19480,9 @@ var modelsCatalog = {
|
|
|
19335
19480
|
price(listed?.cacheRead),
|
|
19336
19481
|
price(listed?.cacheWrite5m),
|
|
19337
19482
|
price(listed?.cacheWrite1h),
|
|
19338
|
-
|
|
19339
|
-
oauth?.contextWindow === limits?.contextWindow ? "\u2014" :
|
|
19340
|
-
|
|
19483
|
+
tokens2(limits?.contextWindow),
|
|
19484
|
+
oauth?.contextWindow === limits?.contextWindow ? "\u2014" : tokens2(oauth?.contextWindow),
|
|
19485
|
+
tokens2(limits?.maxOutputTokens)
|
|
19341
19486
|
];
|
|
19342
19487
|
})));
|
|
19343
19488
|
}
|
|
@@ -19721,6 +19866,78 @@ var settingsSet = {
|
|
|
19721
19866
|
}
|
|
19722
19867
|
};
|
|
19723
19868
|
|
|
19869
|
+
// apps/cli/src/commands/setup.ts
|
|
19870
|
+
import { dirname as dirname2, join as join4 } from "path";
|
|
19871
|
+
var OPTIONS = {
|
|
19872
|
+
dir: { type: "string" },
|
|
19873
|
+
key: { type: "string" },
|
|
19874
|
+
"dry-run": { type: "boolean" }
|
|
19875
|
+
};
|
|
19876
|
+
async function described(ctx) {
|
|
19877
|
+
const models = await describeModelsForSetup(await ctx.store());
|
|
19878
|
+
if (models.length === 0) {
|
|
19879
|
+
throw new CliError("no virtual models configured; add one with `omni models put`");
|
|
19880
|
+
}
|
|
19881
|
+
return models;
|
|
19882
|
+
}
|
|
19883
|
+
function baseUrl(ctx) {
|
|
19884
|
+
if (ctx.configError !== null)
|
|
19885
|
+
throw new CliError(ctx.configError);
|
|
19886
|
+
return ctx.config().baseUrl;
|
|
19887
|
+
}
|
|
19888
|
+
function finish(ctx, writer, files, dryRun2, key, write) {
|
|
19889
|
+
if (!dryRun2) {
|
|
19890
|
+
for (const file2 of files)
|
|
19891
|
+
write(file2.path, file2.contents);
|
|
19892
|
+
}
|
|
19893
|
+
emit(ctx, writer, { files }, () => dryRun2 ? files.map((f) => `--- ${f.path}
|
|
19894
|
+
${f.contents}`).join(`
|
|
19895
|
+
`) : files.map((f) => f.path).join(`
|
|
19896
|
+
`));
|
|
19897
|
+
if (key === undefined) {
|
|
19898
|
+
note(ctx, writer, "no --key given: the files carry a placeholder, so paste your key over it");
|
|
19899
|
+
}
|
|
19900
|
+
}
|
|
19901
|
+
function at(dir, file2) {
|
|
19902
|
+
return { path: join4(dir, file2.path), contents: file2.contents };
|
|
19903
|
+
}
|
|
19904
|
+
var setupClaude = {
|
|
19905
|
+
usage: "setup claude [--dir <path>] [--key <key>] [--dry-run]",
|
|
19906
|
+
summary: "Write a Claude Code profile per virtual model",
|
|
19907
|
+
options: OPTIONS,
|
|
19908
|
+
async run(args, { ctx, writer, setupFs }) {
|
|
19909
|
+
const models = await described(ctx);
|
|
19910
|
+
const dir = stringFlag(args.values, "dir") ?? join4(setupFs.homeDir, ".claude", "profiles");
|
|
19911
|
+
const key = stringFlag(args.values, "key");
|
|
19912
|
+
const dryRun2 = boolFlag(args.values, "dry-run");
|
|
19913
|
+
const files = claudeProfiles(models, {
|
|
19914
|
+
baseUrl: baseUrl(ctx),
|
|
19915
|
+
discoveryMirrors: ctx.config().exposeClaudeCodeAliases,
|
|
19916
|
+
...key === undefined ? {} : { apiKey: key }
|
|
19917
|
+
}).map((file2) => at(dir, file2));
|
|
19918
|
+
finish(ctx, writer, files, dryRun2, key, setupFs.write);
|
|
19919
|
+
if (!dryRun2) {
|
|
19920
|
+
note(ctx, writer, `run one with: CLAUDE_CONFIG_DIR=${dirname2(files[0]?.path ?? dir)} claude`);
|
|
19921
|
+
}
|
|
19922
|
+
}
|
|
19923
|
+
};
|
|
19924
|
+
var setupOpencode = {
|
|
19925
|
+
usage: "setup opencode [--dir <path>] [--key <key>] [--dry-run]",
|
|
19926
|
+
summary: "Write an opencode.json provider entry for this gateway",
|
|
19927
|
+
options: OPTIONS,
|
|
19928
|
+
async run(args, { ctx, writer, setupFs }) {
|
|
19929
|
+
const models = await described(ctx);
|
|
19930
|
+
const dir = stringFlag(args.values, "dir") ?? setupFs.cwd;
|
|
19931
|
+
const key = stringFlag(args.values, "key");
|
|
19932
|
+
const dryRun2 = boolFlag(args.values, "dry-run");
|
|
19933
|
+
const file2 = opencodeConfig(models, {
|
|
19934
|
+
baseUrl: baseUrl(ctx),
|
|
19935
|
+
...key === undefined ? {} : { apiKey: key }
|
|
19936
|
+
});
|
|
19937
|
+
finish(ctx, writer, [at(dir, file2)], dryRun2, key, setupFs.write);
|
|
19938
|
+
}
|
|
19939
|
+
};
|
|
19940
|
+
|
|
19724
19941
|
// apps/cli/src/commands/status.ts
|
|
19725
19942
|
var WINDOW_ORDER = {
|
|
19726
19943
|
fiveHour: 0,
|
|
@@ -19955,6 +20172,8 @@ var COMMANDS = {
|
|
|
19955
20172
|
"keys revoke": keysRevoke,
|
|
19956
20173
|
"settings get": settingsGet,
|
|
19957
20174
|
"settings set": settingsSet,
|
|
20175
|
+
"setup claude": setupClaude,
|
|
20176
|
+
"setup opencode": setupOpencode,
|
|
19958
20177
|
"admin set-password": adminSetPassword,
|
|
19959
20178
|
"db migrate": dbMigrate
|
|
19960
20179
|
};
|
|
@@ -20155,6 +20374,14 @@ async function run(argv, writer, options = {}) {
|
|
|
20155
20374
|
ctx,
|
|
20156
20375
|
writer,
|
|
20157
20376
|
prompt,
|
|
20377
|
+
setupFs: options.setupFs ?? {
|
|
20378
|
+
homeDir: homedir3(),
|
|
20379
|
+
cwd: process.cwd(),
|
|
20380
|
+
write: (path, contents) => {
|
|
20381
|
+
mkdirSync2(dirname3(path), { recursive: true });
|
|
20382
|
+
writeFileSync2(path, contents);
|
|
20383
|
+
}
|
|
20384
|
+
},
|
|
20158
20385
|
service: () => options.service?.({ root: ctx.root.root, env: ctx.env }) ?? createServiceDeps({ root: ctx.root.root, env: ctx.env, scope, now: ctx.now }),
|
|
20159
20386
|
foreground: options.foreground ?? runForeground,
|
|
20160
20387
|
connect: (store) => options.connect?.(store) ?? createConnectFlows({
|