omnigateway 0.1.3 → 0.1.5

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.
Files changed (34) hide show
  1. package/bin/omni.js +101 -37
  2. package/gateway.js +332 -227
  3. package/package.json +1 -1
  4. package/public/assets/{Chip-D0YiqYkz.js → Chip-Ccqsb_Mq.js} +2 -2
  5. package/public/assets/{CopyValue-bzKz2tiJ.js → CopyValue-CvEMy9Zo.js} +5 -5
  6. package/public/assets/{Field-DdscQ9OO.js → Field-Devm4K46.js} +8 -8
  7. package/public/assets/Lamp-BXSUIAtG.js +25 -0
  8. package/public/assets/{Meter-Bm1oQE2U.js → Meter-Fn8X7t60.js} +2 -2
  9. package/public/assets/{Modal-Crr8uyWt.js → Modal-C4y9zALa.js} +8 -8
  10. package/public/assets/{Rack-uDxrjvaz.js → Rack-CRQSwSeB.js} +18 -18
  11. package/public/assets/{Readout-CYg6UOop.js → Readout-BKpOZIGX.js} +5 -5
  12. package/public/assets/{States-DPTTYUHL.js → States-DBzsiHjQ.js} +10 -10
  13. package/public/assets/{Table-LkPaHBsj.js → Table-DPDJeeVc.js} +1 -1
  14. package/public/assets/{Toggle-D0e4C94X.js → Toggle-CBq5XAMU.js} +3 -3
  15. package/public/assets/_app-VCodWes4.js +1 -0
  16. package/public/assets/_app.accounts-BP3L84us.js +51 -0
  17. package/public/assets/_app.index-C5Vd-zlp.js +61 -0
  18. package/public/assets/{_app.keys-BNEOjtbu.js → _app.keys-0e1BHrIZ.js} +8 -8
  19. package/public/assets/_app.logs-DNSND96R.js +33 -0
  20. package/public/assets/_app.models-DzFIbnem.js +144 -0
  21. package/public/assets/{_app.settings-C1gB4w7c.js → _app.settings-Du5Nsp9f.js} +6 -6
  22. package/public/assets/{_app.usage-B0iHKzmI.js → _app.usage-DKq4Hsia.js} +28 -28
  23. package/public/assets/index-BYyeRTQJ.js +170 -0
  24. package/public/assets/{login-D-FsWNX8.js → login-Gyf-1fSa.js} +8 -8
  25. package/public/assets/{queries-vY5lJqBe.js → queries-BMwc6EvM.js} +1 -1
  26. package/public/assets/{trash-2-Cep_aVLx.js → trash-2-DFVxurNH.js} +1 -1
  27. package/public/index.html +3 -3
  28. package/public/assets/Lamp-WOotyOTd.js +0 -15
  29. package/public/assets/_app-OSvB-Dv9.js +0 -1
  30. package/public/assets/_app.accounts-BOE49WyS.js +0 -51
  31. package/public/assets/_app.index-CTRlqxOq.js +0 -61
  32. package/public/assets/_app.logs-BxxqeEhM.js +0 -18
  33. package/public/assets/_app.models-BJi-RGUO.js +0 -144
  34. package/public/assets/index--dA3FFSN.js +0 -170
package/bin/omni.js CHANGED
@@ -17335,6 +17335,27 @@ ALTER TABLE credentials ADD COLUMN disabled_reason TEXT;
17335
17335
  ALTER TABLE credentials ADD COLUMN disabled_at INTEGER;
17336
17336
  `;
17337
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
+
17338
17359
  // packages/store/src/sqlite/rollup.ts
17339
17360
  function startOfLocalDay(at) {
17340
17361
  const day = new Date(at);
@@ -17441,7 +17462,8 @@ function backfillDaily(db) {
17441
17462
  var MIGRATIONS = [
17442
17463
  { id: 1, sql: _001_init_default },
17443
17464
  { id: 2, sql: _002_usage_daily_default, after: backfillDaily },
17444
- { id: 3, sql: _003_quota_snapshot_default }
17465
+ { id: 3, sql: _003_quota_snapshot_default },
17466
+ { id: 4, sql: _004_request_state_default }
17445
17467
  ];
17446
17468
  function openDb(path) {
17447
17469
  const db = new Database(path, { create: true });
@@ -17513,6 +17535,7 @@ function createKeyRepo(db) {
17513
17535
  // packages/store/src/sqlite/usage.ts
17514
17536
  var toLog = (r) => ({
17515
17537
  id: r.id,
17538
+ state: r.state === "pending" ? "pending" : "done",
17516
17539
  at: r.at,
17517
17540
  apiKeyId: r.api_key_id,
17518
17541
  requestedModel: r.requested_model,
@@ -17571,37 +17594,78 @@ function label(value) {
17571
17594
  const text = String(value);
17572
17595
  return text.length === 0 ? "unknown" : text;
17573
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`;
17574
17644
  function createUsageRepo(db) {
17575
- const insert = db.transaction((log) => {
17576
- db.run(`INSERT INTO request_logs
17577
- (id, at, api_key_id, requested_model, resolved_provider, resolved_model, credential_id,
17578
- attempts, status, error_code, input_tokens, output_tokens, cache_read_tokens,
17579
- cache_write_tokens, ttft_ms, duration_ms, cost_usd, degradations)
17580
- VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`, [
17581
- log.id,
17582
- log.at,
17583
- log.apiKeyId,
17584
- log.requestedModel,
17585
- log.resolvedProvider,
17586
- log.resolvedModel,
17587
- log.credentialId,
17588
- log.attempts,
17589
- log.status,
17590
- log.errorCode,
17591
- log.inputTokens,
17592
- log.outputTokens,
17593
- log.cacheReadTokens,
17594
- log.cacheWriteTokens,
17595
- log.ttftMs,
17596
- log.durationMs,
17597
- log.costUsd,
17598
- JSON.stringify(log.degradations)
17599
- ]);
17600
- 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));
17601
17650
  });
17602
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
+ },
17603
17660
  async append(log) {
17604
- insert(log);
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;
17605
17669
  },
17606
17670
  async recent(limit) {
17607
17671
  return db.query("SELECT * FROM request_logs ORDER BY at DESC LIMIT ?").all(limit).map(toLog);
@@ -17623,7 +17687,7 @@ function createUsageRepo(db) {
17623
17687
  COALESCE(SUM(cache_write_tokens), 0) AS cache_write_tokens,
17624
17688
  COALESCE(SUM(cost_usd), 0) AS cost_usd
17625
17689
  FROM ${daily ? "usage_daily" : "request_logs"}
17626
- WHERE ${timeColumn} >= ? AND ${timeColumn} <= ?
17690
+ WHERE ${daily ? "" : "state = 'done' AND "}${timeColumn} >= ? AND ${timeColumn} <= ?
17627
17691
  GROUP BY key${split === null ? "" : ", split"}
17628
17692
  ORDER BY requests DESC`).all(since, until);
17629
17693
  return rows.map((r) => {
@@ -18102,21 +18166,21 @@ function parse5(argv, options = {}) {
18102
18166
  throw new UsageError(error51 instanceof Error ? error51.message : "could not parse arguments");
18103
18167
  }
18104
18168
  }
18105
- function stringFlag(values, name) {
18106
- const value = values[name];
18169
+ function stringFlag(values2, name) {
18170
+ const value = values2[name];
18107
18171
  return typeof value === "string" ? value : undefined;
18108
18172
  }
18109
- function boolFlag(values, name) {
18110
- return values[name] === true;
18173
+ function boolFlag(values2, name) {
18174
+ return values2[name] === true;
18111
18175
  }
18112
- function listFlag(values, name) {
18113
- const value = values[name];
18176
+ function listFlag(values2, name) {
18177
+ const value = values2[name];
18114
18178
  if (Array.isArray(value))
18115
18179
  return value.filter((entry) => typeof entry === "string");
18116
18180
  return typeof value === "string" ? [value] : undefined;
18117
18181
  }
18118
- function numberFlag(values, name) {
18119
- const raw = stringFlag(values, name);
18182
+ function numberFlag(values2, name) {
18183
+ const raw = stringFlag(values2, name);
18120
18184
  if (raw === undefined)
18121
18185
  return;
18122
18186
  const value = Number(raw);