omnigateway 0.1.2 → 0.1.4
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 +140 -51
- package/gateway.js +289 -87
- package/package.json +1 -1
- package/public/assets/{Chip-D0YiqYkz.js → Chip-Ccqsb_Mq.js} +2 -2
- package/public/assets/{CopyValue-bzKz2tiJ.js → CopyValue-BhGx7Gy0.js} +5 -5
- package/public/assets/{Field-DdscQ9OO.js → Field-Devm4K46.js} +8 -8
- package/public/assets/Lamp-BXSUIAtG.js +25 -0
- package/public/assets/{Meter-Bm1oQE2U.js → Meter-Fn8X7t60.js} +2 -2
- package/public/assets/{Modal-Crr8uyWt.js → Modal-DOQGdhoM.js} +8 -8
- package/public/assets/{Rack-uDxrjvaz.js → Rack-DnbGnBvz.js} +18 -18
- package/public/assets/{Readout-CYg6UOop.js → Readout-BKpOZIGX.js} +5 -5
- package/public/assets/{States-DPTTYUHL.js → States-DBzsiHjQ.js} +10 -10
- package/public/assets/{Table-LkPaHBsj.js → Table-DPDJeeVc.js} +1 -1
- package/public/assets/{Toggle-D0e4C94X.js → Toggle-CP3RvAAB.js} +3 -3
- package/public/assets/_app-D83powx4.js +1 -0
- package/public/assets/_app.accounts-DR-2t9-7.js +51 -0
- package/public/assets/_app.index-DimCB0Bo.js +61 -0
- package/public/assets/{_app.keys-BNEOjtbu.js → _app.keys-B7kl3CSe.js} +8 -8
- package/public/assets/_app.logs-BjtdzcDY.js +18 -0
- package/public/assets/_app.models-BEECjcLM.js +144 -0
- package/public/assets/{_app.settings-C1gB4w7c.js → _app.settings-DtDIhAAr.js} +6 -6
- package/public/assets/{_app.usage-B0iHKzmI.js → _app.usage-BChnSBbS.js} +28 -28
- package/public/assets/index-C53PiRfb.js +170 -0
- package/public/assets/{login-D-FsWNX8.js → login-BuvJY1Qd.js} +8 -8
- package/public/assets/{queries-vY5lJqBe.js → queries-BMwc6EvM.js} +1 -1
- package/public/assets/{trash-2-Cep_aVLx.js → trash-2-Cq7ldH9D.js} +1 -1
- package/public/index.html +2 -2
- package/public/assets/Lamp-WOotyOTd.js +0 -15
- package/public/assets/_app-OSvB-Dv9.js +0 -1
- package/public/assets/_app.accounts-BOE49WyS.js +0 -51
- package/public/assets/_app.index-CTRlqxOq.js +0 -61
- package/public/assets/_app.logs-BxxqeEhM.js +0 -18
- package/public/assets/_app.models-BJi-RGUO.js +0 -144
- package/public/assets/index--dA3FFSN.js +0 -170
package/bin/omni.js
CHANGED
|
@@ -608,6 +608,7 @@ async function* decodeAnthropic(messages) {
|
|
|
608
608
|
let cacheWriteTokens = 0;
|
|
609
609
|
let outputTokens = 0;
|
|
610
610
|
let stopReason = "endTurn";
|
|
611
|
+
let terminal = false;
|
|
611
612
|
for await (const msg of messages) {
|
|
612
613
|
const d = json(msg.data);
|
|
613
614
|
if (d === null)
|
|
@@ -673,6 +674,7 @@ async function* decodeAnthropic(messages) {
|
|
|
673
674
|
break;
|
|
674
675
|
}
|
|
675
676
|
case "message_stop":
|
|
677
|
+
terminal = true;
|
|
676
678
|
yield {
|
|
677
679
|
type: "end",
|
|
678
680
|
stopReason,
|
|
@@ -680,6 +682,7 @@ async function* decodeAnthropic(messages) {
|
|
|
680
682
|
};
|
|
681
683
|
break;
|
|
682
684
|
case "error": {
|
|
685
|
+
terminal = true;
|
|
683
686
|
const code = ERROR_TYPE[String(d.error?.type)] ?? "UPSTREAM";
|
|
684
687
|
yield {
|
|
685
688
|
type: "error",
|
|
@@ -693,6 +696,14 @@ async function* decodeAnthropic(messages) {
|
|
|
693
696
|
break;
|
|
694
697
|
}
|
|
695
698
|
}
|
|
699
|
+
if (!terminal) {
|
|
700
|
+
yield {
|
|
701
|
+
type: "error",
|
|
702
|
+
code: "UPSTREAM",
|
|
703
|
+
message: "upstream stream ended before message_stop",
|
|
704
|
+
retryable: RETRYABLE.UPSTREAM
|
|
705
|
+
};
|
|
706
|
+
}
|
|
696
707
|
}
|
|
697
708
|
|
|
698
709
|
// packages/providers/src/anthropic/wire.ts
|
|
@@ -805,9 +816,10 @@ var anthropicAdapter = {
|
|
|
805
816
|
["anthropic-version", API_VERSION],
|
|
806
817
|
["Accept", req.request.stream ? "text/event-stream" : "application/json"]
|
|
807
818
|
];
|
|
819
|
+
const betas = new Set(req.request.betas ?? []);
|
|
808
820
|
if (oauth) {
|
|
809
821
|
protocol.push(["Authorization", `Bearer ${req.credentials.accessToken}`]);
|
|
810
|
-
|
|
822
|
+
betas.add(OAUTH_BETA);
|
|
811
823
|
} else if (req.credentials.apiKey !== null) {
|
|
812
824
|
protocol.push(["x-api-key", req.credentials.apiKey]);
|
|
813
825
|
} else {
|
|
@@ -815,6 +827,8 @@ var anthropicAdapter = {
|
|
|
815
827
|
provider: "anthropic"
|
|
816
828
|
});
|
|
817
829
|
}
|
|
830
|
+
if (betas.size > 0)
|
|
831
|
+
protocol.push(["anthropic-beta", [...betas].join(",")]);
|
|
818
832
|
const profile = PROFILES.anthropic;
|
|
819
833
|
const headers = orderHeaders(mergeHeaders(profile.headers, protocol), profile.order);
|
|
820
834
|
const bodyString = signAnthropicBody(JSON.stringify(orderFields(withSystem, BODY_ORDER.anthropic)));
|
|
@@ -1032,18 +1046,16 @@ async function* decodeChat(messages) {
|
|
|
1032
1046
|
let started = false;
|
|
1033
1047
|
let textOpen = false;
|
|
1034
1048
|
let textIndex;
|
|
1035
|
-
let
|
|
1049
|
+
let done = false;
|
|
1036
1050
|
let stopReason = "endTurn";
|
|
1037
1051
|
let usage = { inputTokens: 0, outputTokens: 0, cacheReadTokens: 0, cacheWriteTokens: 0 };
|
|
1038
1052
|
const toolIndex = new Map;
|
|
1039
1053
|
let nextIndex = 0;
|
|
1040
|
-
const emitEnd = () => {
|
|
1041
|
-
ended = true;
|
|
1042
|
-
return { type: "end", stopReason, usage };
|
|
1043
|
-
};
|
|
1044
1054
|
for await (const msg of messages) {
|
|
1045
|
-
if (msg.data === "[DONE]")
|
|
1055
|
+
if (msg.data === "[DONE]") {
|
|
1056
|
+
done = true;
|
|
1046
1057
|
break;
|
|
1058
|
+
}
|
|
1047
1059
|
const d = json2(msg.data);
|
|
1048
1060
|
if (d === null)
|
|
1049
1061
|
continue;
|
|
@@ -1098,19 +1110,21 @@ async function* decodeChat(messages) {
|
|
|
1098
1110
|
}
|
|
1099
1111
|
if (typeof choice.finish_reason === "string") {
|
|
1100
1112
|
stopReason = FINISH[choice.finish_reason] ?? "endTurn";
|
|
1101
|
-
if (textOpen)
|
|
1102
|
-
yield { type: "blockEnd", index: textIndex ?? 0 };
|
|
1103
|
-
for (const index of toolIndex.values())
|
|
1104
|
-
yield { type: "blockEnd", index };
|
|
1105
|
-
yield emitEnd();
|
|
1106
1113
|
}
|
|
1107
1114
|
}
|
|
1108
|
-
if (
|
|
1115
|
+
if (done) {
|
|
1109
1116
|
if (textOpen)
|
|
1110
1117
|
yield { type: "blockEnd", index: textIndex ?? 0 };
|
|
1111
1118
|
for (const index of toolIndex.values())
|
|
1112
1119
|
yield { type: "blockEnd", index };
|
|
1113
|
-
yield
|
|
1120
|
+
yield { type: "end", stopReason, usage };
|
|
1121
|
+
} else {
|
|
1122
|
+
yield {
|
|
1123
|
+
type: "error",
|
|
1124
|
+
code: "UPSTREAM",
|
|
1125
|
+
message: "upstream stream ended before [DONE]",
|
|
1126
|
+
retryable: RETRYABLE.UPSTREAM
|
|
1127
|
+
};
|
|
1114
1128
|
}
|
|
1115
1129
|
}
|
|
1116
1130
|
|
|
@@ -1265,6 +1279,7 @@ async function* decodeResponses(messages) {
|
|
|
1265
1279
|
return assigned;
|
|
1266
1280
|
};
|
|
1267
1281
|
let sawToolCall = false;
|
|
1282
|
+
let terminal = false;
|
|
1268
1283
|
const ownsBlock = new Set;
|
|
1269
1284
|
for await (const msg of messages) {
|
|
1270
1285
|
const d = json3(msg.data);
|
|
@@ -1340,6 +1355,7 @@ async function* decodeResponses(messages) {
|
|
|
1340
1355
|
}
|
|
1341
1356
|
case "response.completed":
|
|
1342
1357
|
case "response.incomplete": {
|
|
1358
|
+
terminal = true;
|
|
1343
1359
|
const r = d.response ?? {};
|
|
1344
1360
|
const reason = r.incomplete_details?.reason;
|
|
1345
1361
|
let stopReason = sawToolCall ? "toolUse" : "endTurn";
|
|
@@ -1361,6 +1377,7 @@ async function* decodeResponses(messages) {
|
|
|
1361
1377
|
}
|
|
1362
1378
|
case "response.failed":
|
|
1363
1379
|
case "error": {
|
|
1380
|
+
terminal = true;
|
|
1364
1381
|
const err = d.response?.error ?? d.error ?? {};
|
|
1365
1382
|
const code = ERROR_CODE[String(err.code ?? err.type)] ?? "UPSTREAM";
|
|
1366
1383
|
yield {
|
|
@@ -1375,6 +1392,14 @@ async function* decodeResponses(messages) {
|
|
|
1375
1392
|
break;
|
|
1376
1393
|
}
|
|
1377
1394
|
}
|
|
1395
|
+
if (!terminal) {
|
|
1396
|
+
yield {
|
|
1397
|
+
type: "error",
|
|
1398
|
+
code: "UPSTREAM",
|
|
1399
|
+
message: "upstream stream ended before response completion",
|
|
1400
|
+
retryable: RETRYABLE.UPSTREAM
|
|
1401
|
+
};
|
|
1402
|
+
}
|
|
1378
1403
|
}
|
|
1379
1404
|
|
|
1380
1405
|
// packages/providers/src/openai/wire.ts
|
|
@@ -17310,6 +17335,27 @@ ALTER TABLE credentials ADD COLUMN disabled_reason TEXT;
|
|
|
17310
17335
|
ALTER TABLE credentials ADD COLUMN disabled_at INTEGER;
|
|
17311
17336
|
`;
|
|
17312
17337
|
|
|
17338
|
+
// packages/store/src/sqlite/migrations/004_request_state.sql
|
|
17339
|
+
var _004_request_state_default = `-- Whether a request is still running.
|
|
17340
|
+
--
|
|
17341
|
+
-- A row used to be written once, after the response stream drained, so a long
|
|
17342
|
+
-- stream was invisible for its whole life and the console showed an idle
|
|
17343
|
+
-- gateway. A row is now written twice: \`pending\` when dispatch starts, \`done\`
|
|
17344
|
+
-- when it finishes.
|
|
17345
|
+
--
|
|
17346
|
+
-- Existing rows default to 'done'. Every row that predates this migration
|
|
17347
|
+
-- describes a request that has already ended, by definition.
|
|
17348
|
+
ALTER TABLE request_logs ADD COLUMN state TEXT NOT NULL DEFAULT 'done';
|
|
17349
|
+
|
|
17350
|
+
-- \`status\` and \`duration_ms\` stay NOT NULL: making them nullable means a table
|
|
17351
|
+
-- rebuild in SQLite, and a pending row's zeros are never read. Readers key off
|
|
17352
|
+
-- \`state\` alone.
|
|
17353
|
+
--
|
|
17354
|
+
-- Partial, because pending rows are a handful at any moment while the table
|
|
17355
|
+
-- holds a month of finished ones.
|
|
17356
|
+
CREATE INDEX idx_request_logs_pending ON request_logs(state) WHERE state = 'pending';
|
|
17357
|
+
`;
|
|
17358
|
+
|
|
17313
17359
|
// packages/store/src/sqlite/rollup.ts
|
|
17314
17360
|
function startOfLocalDay(at) {
|
|
17315
17361
|
const day = new Date(at);
|
|
@@ -17416,7 +17462,8 @@ function backfillDaily(db) {
|
|
|
17416
17462
|
var MIGRATIONS = [
|
|
17417
17463
|
{ id: 1, sql: _001_init_default },
|
|
17418
17464
|
{ id: 2, sql: _002_usage_daily_default, after: backfillDaily },
|
|
17419
|
-
{ id: 3, sql: _003_quota_snapshot_default }
|
|
17465
|
+
{ id: 3, sql: _003_quota_snapshot_default },
|
|
17466
|
+
{ id: 4, sql: _004_request_state_default }
|
|
17420
17467
|
];
|
|
17421
17468
|
function openDb(path) {
|
|
17422
17469
|
const db = new Database(path, { create: true });
|
|
@@ -17488,6 +17535,7 @@ function createKeyRepo(db) {
|
|
|
17488
17535
|
// packages/store/src/sqlite/usage.ts
|
|
17489
17536
|
var toLog = (r) => ({
|
|
17490
17537
|
id: r.id,
|
|
17538
|
+
state: r.state === "pending" ? "pending" : "done",
|
|
17491
17539
|
at: r.at,
|
|
17492
17540
|
apiKeyId: r.api_key_id,
|
|
17493
17541
|
requestedModel: r.requested_model,
|
|
@@ -17546,37 +17594,78 @@ function label(value) {
|
|
|
17546
17594
|
const text = String(value);
|
|
17547
17595
|
return text.length === 0 ? "unknown" : text;
|
|
17548
17596
|
}
|
|
17597
|
+
var COLUMNS = `(id, state, at, api_key_id, requested_model, resolved_provider, resolved_model,
|
|
17598
|
+
credential_id, attempts, status, error_code, input_tokens, output_tokens,
|
|
17599
|
+
cache_read_tokens, cache_write_tokens, ttft_ms, duration_ms, cost_usd,
|
|
17600
|
+
degradations)`;
|
|
17601
|
+
var PLACEHOLDERS = "(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
|
|
17602
|
+
function values(log, state) {
|
|
17603
|
+
return [
|
|
17604
|
+
log.id,
|
|
17605
|
+
state,
|
|
17606
|
+
log.at,
|
|
17607
|
+
log.apiKeyId,
|
|
17608
|
+
log.requestedModel,
|
|
17609
|
+
log.resolvedProvider,
|
|
17610
|
+
log.resolvedModel,
|
|
17611
|
+
log.credentialId,
|
|
17612
|
+
log.attempts,
|
|
17613
|
+
log.status,
|
|
17614
|
+
log.errorCode,
|
|
17615
|
+
log.inputTokens,
|
|
17616
|
+
log.outputTokens,
|
|
17617
|
+
log.cacheReadTokens,
|
|
17618
|
+
log.cacheWriteTokens,
|
|
17619
|
+
log.ttftMs,
|
|
17620
|
+
log.durationMs,
|
|
17621
|
+
log.costUsd,
|
|
17622
|
+
JSON.stringify(log.degradations)
|
|
17623
|
+
];
|
|
17624
|
+
}
|
|
17625
|
+
var COMPLETE = `INSERT INTO request_logs ${COLUMNS} VALUES ${PLACEHOLDERS}
|
|
17626
|
+
ON CONFLICT(id) DO UPDATE SET
|
|
17627
|
+
state = 'done',
|
|
17628
|
+
requested_model = COALESCE(NULLIF(excluded.requested_model, ''), request_logs.requested_model),
|
|
17629
|
+
api_key_id = COALESCE(excluded.api_key_id, request_logs.api_key_id),
|
|
17630
|
+
resolved_provider = excluded.resolved_provider,
|
|
17631
|
+
resolved_model = excluded.resolved_model,
|
|
17632
|
+
credential_id = excluded.credential_id,
|
|
17633
|
+
attempts = excluded.attempts,
|
|
17634
|
+
status = excluded.status,
|
|
17635
|
+
error_code = excluded.error_code,
|
|
17636
|
+
input_tokens = excluded.input_tokens,
|
|
17637
|
+
output_tokens = excluded.output_tokens,
|
|
17638
|
+
cache_read_tokens = excluded.cache_read_tokens,
|
|
17639
|
+
cache_write_tokens = excluded.cache_write_tokens,
|
|
17640
|
+
ttft_ms = excluded.ttft_ms,
|
|
17641
|
+
duration_ms = excluded.duration_ms,
|
|
17642
|
+
cost_usd = excluded.cost_usd,
|
|
17643
|
+
degradations = excluded.degradations`;
|
|
17549
17644
|
function createUsageRepo(db) {
|
|
17550
|
-
const
|
|
17551
|
-
db.run(
|
|
17552
|
-
|
|
17553
|
-
|
|
17554
|
-
|
|
17555
|
-
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`, [
|
|
17556
|
-
log.id,
|
|
17557
|
-
log.at,
|
|
17558
|
-
log.apiKeyId,
|
|
17559
|
-
log.requestedModel,
|
|
17560
|
-
log.resolvedProvider,
|
|
17561
|
-
log.resolvedModel,
|
|
17562
|
-
log.credentialId,
|
|
17563
|
-
log.attempts,
|
|
17564
|
-
log.status,
|
|
17565
|
-
log.errorCode,
|
|
17566
|
-
log.inputTokens,
|
|
17567
|
-
log.outputTokens,
|
|
17568
|
-
log.cacheReadTokens,
|
|
17569
|
-
log.cacheWriteTokens,
|
|
17570
|
-
log.ttftMs,
|
|
17571
|
-
log.durationMs,
|
|
17572
|
-
log.costUsd,
|
|
17573
|
-
JSON.stringify(log.degradations)
|
|
17574
|
-
]);
|
|
17575
|
-
rollupLog(db, log);
|
|
17645
|
+
const complete = db.transaction((log) => {
|
|
17646
|
+
db.run(COMPLETE, values(log, "done"));
|
|
17647
|
+
const stored = db.query("SELECT * FROM request_logs WHERE id = ?").get(log.id);
|
|
17648
|
+
if (stored !== null)
|
|
17649
|
+
rollupLog(db, toLog(stored));
|
|
17576
17650
|
});
|
|
17577
17651
|
return {
|
|
17652
|
+
async begin(log) {
|
|
17653
|
+
db.run(`INSERT INTO request_logs ${COLUMNS} VALUES ${PLACEHOLDERS}`, values(log, "pending"));
|
|
17654
|
+
},
|
|
17655
|
+
async route(id, target) {
|
|
17656
|
+
db.run(`UPDATE request_logs
|
|
17657
|
+
SET resolved_provider = ?, resolved_model = ?, credential_id = ?
|
|
17658
|
+
WHERE id = ? AND state = 'pending'`, [target.provider, target.model, target.credentialId, id]);
|
|
17659
|
+
},
|
|
17578
17660
|
async append(log) {
|
|
17579
|
-
|
|
17661
|
+
complete(log);
|
|
17662
|
+
},
|
|
17663
|
+
async sweepPending() {
|
|
17664
|
+
const stale = db.query("SELECT * FROM request_logs WHERE state = 'pending'").all().map(toLog);
|
|
17665
|
+
for (const log of stale) {
|
|
17666
|
+
complete({ ...log, status: 499, errorCode: "interrupted", durationMs: 0 });
|
|
17667
|
+
}
|
|
17668
|
+
return stale.length;
|
|
17580
17669
|
},
|
|
17581
17670
|
async recent(limit) {
|
|
17582
17671
|
return db.query("SELECT * FROM request_logs ORDER BY at DESC LIMIT ?").all(limit).map(toLog);
|
|
@@ -17598,7 +17687,7 @@ function createUsageRepo(db) {
|
|
|
17598
17687
|
COALESCE(SUM(cache_write_tokens), 0) AS cache_write_tokens,
|
|
17599
17688
|
COALESCE(SUM(cost_usd), 0) AS cost_usd
|
|
17600
17689
|
FROM ${daily ? "usage_daily" : "request_logs"}
|
|
17601
|
-
WHERE ${timeColumn} >= ? AND ${timeColumn} <= ?
|
|
17690
|
+
WHERE ${daily ? "" : "state = 'done' AND "}${timeColumn} >= ? AND ${timeColumn} <= ?
|
|
17602
17691
|
GROUP BY key${split === null ? "" : ", split"}
|
|
17603
17692
|
ORDER BY requests DESC`).all(since, until);
|
|
17604
17693
|
return rows.map((r) => {
|
|
@@ -18077,21 +18166,21 @@ function parse5(argv, options = {}) {
|
|
|
18077
18166
|
throw new UsageError(error51 instanceof Error ? error51.message : "could not parse arguments");
|
|
18078
18167
|
}
|
|
18079
18168
|
}
|
|
18080
|
-
function stringFlag(
|
|
18081
|
-
const value =
|
|
18169
|
+
function stringFlag(values2, name) {
|
|
18170
|
+
const value = values2[name];
|
|
18082
18171
|
return typeof value === "string" ? value : undefined;
|
|
18083
18172
|
}
|
|
18084
|
-
function boolFlag(
|
|
18085
|
-
return
|
|
18173
|
+
function boolFlag(values2, name) {
|
|
18174
|
+
return values2[name] === true;
|
|
18086
18175
|
}
|
|
18087
|
-
function listFlag(
|
|
18088
|
-
const value =
|
|
18176
|
+
function listFlag(values2, name) {
|
|
18177
|
+
const value = values2[name];
|
|
18089
18178
|
if (Array.isArray(value))
|
|
18090
18179
|
return value.filter((entry) => typeof entry === "string");
|
|
18091
18180
|
return typeof value === "string" ? [value] : undefined;
|
|
18092
18181
|
}
|
|
18093
|
-
function numberFlag(
|
|
18094
|
-
const raw = stringFlag(
|
|
18182
|
+
function numberFlag(values2, name) {
|
|
18183
|
+
const raw = stringFlag(values2, name);
|
|
18095
18184
|
if (raw === undefined)
|
|
18096
18185
|
return;
|
|
18097
18186
|
const value = Number(raw);
|