omnigateway 0.4.5 → 0.4.6

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 (3) hide show
  1. package/bin/omni.js +20 -15
  2. package/gateway.js +28 -28
  3. package/package.json +1 -1
package/bin/omni.js CHANGED
@@ -237,6 +237,12 @@ var RETRYABLE = {
237
237
  ALL_CANDIDATES_FAILED: false,
238
238
  INTERNAL: false
239
239
  };
240
+ function describeError(error, fallback) {
241
+ if (!(error instanceof Error))
242
+ return fallback;
243
+ return error.message.length > 0 ? error.message : error.name;
244
+ }
245
+
240
246
  class GatewayError extends Error {
241
247
  code;
242
248
  retryable;
@@ -20131,7 +20137,7 @@ function createPluginRepo(db) {
20131
20137
  applied,
20132
20138
  failed: {
20133
20139
  version: migration.version,
20134
- reason: error51 instanceof Error ? error51.message : String(error51)
20140
+ reason: describeError(error51, String(error51))
20135
20141
  }
20136
20142
  };
20137
20143
  }
@@ -20975,14 +20981,14 @@ async function swapIn(deps, candidate) {
20975
20981
  await deps.store.usage.rebuildRollup();
20976
20982
  } catch (error51) {
20977
20983
  (deps.logger ?? noopLogger).warn("usage rollup not rebuilt after the swap; run omni doctor", {
20978
- reason: error51 instanceof Error ? error51.message : "unknown"
20984
+ reason: describeError(error51, "unknown")
20979
20985
  });
20980
20986
  }
20981
20987
  try {
20982
20988
  await deps.reapplyPluginSchema?.();
20983
20989
  } catch (error51) {
20984
20990
  (deps.logger ?? noopLogger).warn("plugin schema not reapplied after the swap; restart", {
20985
- reason: error51 instanceof Error ? error51.message : "unknown"
20991
+ reason: describeError(error51, "unknown")
20986
20992
  });
20987
20993
  }
20988
20994
  return {
@@ -21386,7 +21392,7 @@ function readManifest(fs, home) {
21386
21392
  try {
21387
21393
  document = JSON.parse(raw);
21388
21394
  } catch (error51) {
21389
- const detail = error51 instanceof Error ? error51.message : String(error51);
21395
+ const detail = describeError(error51, String(error51));
21390
21396
  return {
21391
21397
  check: "manifest",
21392
21398
  reason: `${MANIFEST_FILENAME} is not valid JSON: ${detail}`,
@@ -21592,7 +21598,7 @@ function gunzipIfNeeded(bytes) {
21592
21598
  try {
21593
21599
  return Bun.gunzipSync(new Uint8Array(bytes));
21594
21600
  } catch (error51) {
21595
- const detail = error51 instanceof Error ? error51.message : String(error51);
21601
+ const detail = describeError(error51, String(error51));
21596
21602
  throw new GatewayError("BAD_REQUEST", `could not decompress the archive: ${detail}`);
21597
21603
  }
21598
21604
  }
@@ -21774,7 +21780,7 @@ function parseJson(bytes, what) {
21774
21780
  try {
21775
21781
  return JSON.parse(decoder2.decode(bytes));
21776
21782
  } catch (error51) {
21777
- const detail = error51 instanceof Error ? error51.message : String(error51);
21783
+ const detail = describeError(error51, String(error51));
21778
21784
  throw new GatewayError("BAD_REQUEST", `${what} is not valid JSON: ${detail}`);
21779
21785
  }
21780
21786
  }
@@ -21812,7 +21818,7 @@ async function installPlugin(deps, root, spec) {
21812
21818
  try {
21813
21819
  document = JSON.parse(decoder2.decode(raw));
21814
21820
  } catch (error51) {
21815
- const detail = error51 instanceof Error ? error51.message : String(error51);
21821
+ const detail = describeError(error51, String(error51));
21816
21822
  throw new GatewayError("BAD_REQUEST", `${MANIFEST_FILENAME} is not valid JSON: ${detail}`);
21817
21823
  }
21818
21824
  const parsed = safeParseManifest(document);
@@ -23033,7 +23039,7 @@ function settingsObject(existing) {
23033
23039
  }
23034
23040
  return parsed;
23035
23041
  } catch (error51) {
23036
- const reason = error51 instanceof Error ? error51.message : "invalid JSON";
23042
+ const reason = describeError(error51, "invalid JSON");
23037
23043
  throw new Error(`cannot parse existing settings.json: ${reason}`);
23038
23044
  }
23039
23045
  }
@@ -23179,7 +23185,6 @@ async function recentLogs(store, requested) {
23179
23185
  }
23180
23186
  // apps/cli/src/args.ts
23181
23187
  import { parseArgs } from "util";
23182
-
23183
23188
  class UsageError extends Error {
23184
23189
  }
23185
23190
  var GLOBAL_OPTIONS = {
@@ -23201,7 +23206,7 @@ function parse5(argv, options = {}) {
23201
23206
  });
23202
23207
  return { positionals: result.positionals, values: result.values };
23203
23208
  } catch (error51) {
23204
- throw new UsageError(error51 instanceof Error ? error51.message : "could not parse arguments");
23209
+ throw new UsageError(describeError(error51, "could not parse arguments"));
23205
23210
  }
23206
23211
  }
23207
23212
  function stringFlag(values2, name) {
@@ -23303,7 +23308,7 @@ function createContext(parsed, options = {}) {
23303
23308
  try {
23304
23309
  config2 = loadConfig(env2);
23305
23310
  } catch (error51) {
23306
- configError = error51 instanceof Error ? error51.message : "invalid configuration";
23311
+ configError = describeError(error51, "invalid configuration");
23307
23312
  }
23308
23313
  const configuredPath = dbFlag ?? config2?.databasePath ?? "omnigateway.db";
23309
23314
  const databasePath = isAbsolute(configuredPath) ? configuredPath : resolve3(root.root, configuredPath);
@@ -25376,7 +25381,7 @@ var status2 = {
25376
25381
  try {
25377
25382
  store = await ctx.store();
25378
25383
  } catch (error51) {
25379
- storeError = error51 instanceof Error ? error51.message : "could not open the database";
25384
+ storeError = describeError(error51, "could not open the database");
25380
25385
  }
25381
25386
  const persistent = store === null ? { adminConfigured: false, credentials: [] } : await credentialStatus(store, { now: ctx.now });
25382
25387
  const { adminConfigured: configured, credentials } = persistent;
@@ -25432,7 +25437,7 @@ var adminSetPassword = {
25432
25437
  try {
25433
25438
  await admin.setPassword(password);
25434
25439
  } catch (error51) {
25435
- throw new CliError(error51 instanceof Error ? error51.message : "could not set the password");
25440
+ throw new CliError(describeError(error51, "could not set the password"));
25436
25441
  }
25437
25442
  note(ctx, writer, "restart the gateway to end sessions signed in with the old password");
25438
25443
  emit(ctx, writer, { ok: true }, () => "admin password set");
@@ -25799,7 +25804,7 @@ async function run(argv, writer, options = {}) {
25799
25804
  try {
25800
25805
  args = parse5(resolved.rest, resolved.command.options ?? {});
25801
25806
  } catch (error51) {
25802
- writer.err(error51 instanceof Error ? error51.message : "could not parse arguments");
25807
+ writer.err(describeError(error51, "could not parse arguments"));
25803
25808
  writer.err(`usage: omni ${resolved.command.usage}`);
25804
25809
  return 2;
25805
25810
  }
@@ -25849,7 +25854,7 @@ async function run(argv, writer, options = {}) {
25849
25854
  writer.err(`${error51.code}: ${error51.message}`);
25850
25855
  return 1;
25851
25856
  }
25852
- writer.err(error51 instanceof Error ? error51.message : "unknown error");
25857
+ writer.err(describeError(error51, "unknown error"));
25853
25858
  return 1;
25854
25859
  } finally {
25855
25860
  ctx.close();
package/gateway.js CHANGED
@@ -5375,6 +5375,11 @@ var HTTP_STATUS = {
5375
5375
  ALL_CANDIDATES_FAILED: 503,
5376
5376
  INTERNAL: 500
5377
5377
  };
5378
+ function describeError(error, fallback) {
5379
+ if (!(error instanceof Error))
5380
+ return fallback;
5381
+ return error.message.length > 0 ? error.message : error.name;
5382
+ }
5378
5383
 
5379
5384
  class GatewayError extends Error {
5380
5385
  code;
@@ -25605,7 +25610,7 @@ function createPluginRepo(db) {
25605
25610
  applied,
25606
25611
  failed: {
25607
25612
  version: migration.version,
25608
- reason: error51 instanceof Error ? error51.message : String(error51)
25613
+ reason: describeError(error51, String(error51))
25609
25614
  }
25610
25615
  };
25611
25616
  }
@@ -26460,14 +26465,14 @@ async function swapIn(deps, candidate) {
26460
26465
  await deps.store.usage.rebuildRollup();
26461
26466
  } catch (error51) {
26462
26467
  (deps.logger ?? noopLogger).warn("usage rollup not rebuilt after the swap; run omni doctor", {
26463
- reason: error51 instanceof Error ? error51.message : "unknown"
26468
+ reason: describeError(error51, "unknown")
26464
26469
  });
26465
26470
  }
26466
26471
  try {
26467
26472
  await deps.reapplyPluginSchema?.();
26468
26473
  } catch (error51) {
26469
26474
  (deps.logger ?? noopLogger).warn("plugin schema not reapplied after the swap; restart", {
26470
- reason: error51 instanceof Error ? error51.message : "unknown"
26475
+ reason: describeError(error51, "unknown")
26471
26476
  });
26472
26477
  }
26473
26478
  return {
@@ -28009,7 +28014,7 @@ async function poll(deps) {
28009
28014
  credentialId: credential.id,
28010
28015
  code: error51 instanceof GatewayError ? error51.code : "INTERNAL",
28011
28016
  ...rateLimited ? { retryAfterMs: RATE_LIMIT_COOLDOWN_MS } : {},
28012
- reason: error51 instanceof Error ? error51.message : "unknown"
28017
+ reason: describeError(error51, "unknown")
28013
28018
  });
28014
28019
  }
28015
28020
  }
@@ -28062,7 +28067,7 @@ function settingsObject(existing) {
28062
28067
  }
28063
28068
  return parsed;
28064
28069
  } catch (error51) {
28065
- const reason = error51 instanceof Error ? error51.message : "invalid JSON";
28070
+ const reason = describeError(error51, "invalid JSON");
28066
28071
  throw new Error(`cannot parse existing settings.json: ${reason}`);
28067
28072
  }
28068
28073
  }
@@ -42885,7 +42890,7 @@ class ApiKeyRateLimiter {
42885
42890
  this.logger.warn("rate limit reset unavailable", {
42886
42891
  ...requestId === undefined ? {} : { requestId },
42887
42892
  apiKeyId: keyId,
42888
- reason: error51 instanceof Error ? error51.message : "unknown"
42893
+ reason: describeError(error51, "unknown")
42889
42894
  });
42890
42895
  return null;
42891
42896
  }
@@ -42951,7 +42956,7 @@ class ApiKeyRateLimiter {
42951
42956
  this.logger.warn("rate limit counters unavailable", {
42952
42957
  ...requestId === undefined ? {} : { requestId },
42953
42958
  apiKeyId: keyId,
42954
- reason: error51 instanceof Error ? error51.message : "unknown"
42959
+ reason: describeError(error51, "unknown")
42955
42960
  });
42956
42961
  state.debits = trimDebits(state.debits, now);
42957
42962
  return null;
@@ -43796,7 +43801,7 @@ function adminRoutes(deps) {
43796
43801
  try {
43797
43802
  created = await deps.admin.setInitialPassword(body2.password);
43798
43803
  } catch (error51) {
43799
- throw new GatewayError("BAD_REQUEST", error51 instanceof Error ? error51.message : "invalid password");
43804
+ throw new GatewayError("BAD_REQUEST", describeError(error51, "invalid password"));
43800
43805
  }
43801
43806
  if (!created) {
43802
43807
  set2.status = 409;
@@ -43888,7 +43893,7 @@ function adminRoutes(deps) {
43888
43893
  })
43889
43894
  };
43890
43895
  } catch (error51) {
43891
- throw new GatewayError("BAD_REQUEST", error51 instanceof Error ? error51.message : "invalid Claude model mapping");
43896
+ throw new GatewayError("BAD_REQUEST", describeError(error51, "invalid Claude model mapping"));
43892
43897
  }
43893
43898
  }).get("/api/keys", async ({ request: request2 }) => {
43894
43899
  await requireAdmin(request2, deps.admin);
@@ -46157,7 +46162,7 @@ function reportRejection(logger2, requestId, log, error51, surface) {
46157
46162
  function report(logger2, what, requestId, error51) {
46158
46163
  logger2.warn(what, {
46159
46164
  requestId,
46160
- reason: error51 instanceof Error ? error51.message : "unknown"
46165
+ reason: describeError(error51, "unknown")
46161
46166
  });
46162
46167
  }
46163
46168
  async function beginLog(store, log, keyId, logger2 = noopLogger) {
@@ -46261,11 +46266,6 @@ var NETWORK_HINTS = [
46261
46266
  "socket hang up",
46262
46267
  "unable to connect"
46263
46268
  ];
46264
- function describeError(error51) {
46265
- if (!(error51 instanceof Error))
46266
- return "attempt failed";
46267
- return error51.message.length > 0 ? error51.message : error51.name;
46268
- }
46269
46269
  function classify(error51) {
46270
46270
  if (error51 instanceof GatewayError) {
46271
46271
  return {
@@ -46393,7 +46393,7 @@ async function dispatch(request2, deps, signal, requestId) {
46393
46393
  if (isClientAbort(error51))
46394
46394
  return fail("TIMEOUT", "client disconnected", true);
46395
46395
  const { code } = classify(error51);
46396
- return fail(code, error51 instanceof Error ? error51.message : "unresolvable model");
46396
+ return fail(code, describeError(error51, "unresolvable model"));
46397
46397
  }
46398
46398
  const { candidates, excluded } = rank({
46399
46399
  request: dispatchRequest,
@@ -46558,7 +46558,7 @@ async function dispatch(request2, deps, signal, requestId) {
46558
46558
  requestId,
46559
46559
  provider: candidate.target.provider,
46560
46560
  credentialId: candidate.credential.id,
46561
- reason: healthError instanceof Error ? healthError.message : "unknown"
46561
+ reason: describeError(healthError, "unknown")
46562
46562
  });
46563
46563
  }
46564
46564
  return;
@@ -46593,7 +46593,7 @@ async function dispatch(request2, deps, signal, requestId) {
46593
46593
  throw signal.reason;
46594
46594
  const classifiedError = deadlineAt !== null && dispatchSignal.aborted ? { code: "TIMEOUT" } : classify(error51);
46595
46595
  const { code: code2 } = classifiedError;
46596
- const message2 = describeError(error51);
46596
+ const message2 = describeError(error51, "attempt failed");
46597
46597
  lastError = rewrap(classifiedError, message2);
46598
46598
  if (code2 === "AUTH" && !committed && !authRefreshRetried && !preemptiveRefreshRequired && candidate.credential.authType === "oauth" && candidate.credential.hasRefreshToken) {
46599
46599
  authRefreshRetried = true;
@@ -46612,7 +46612,7 @@ async function dispatch(request2, deps, signal, requestId) {
46612
46612
  if (signal.aborted)
46613
46613
  throw signal.reason;
46614
46614
  const classified = deadlineAt !== null && dispatchSignal.aborted ? { code: "TIMEOUT" } : classify(refreshError);
46615
- const refreshMessage = refreshError instanceof Error ? describeError(refreshError) : "credential refresh failed";
46615
+ const refreshMessage = describeError(refreshError, "credential refresh failed");
46616
46616
  lastError = rewrap(classified, refreshMessage);
46617
46617
  logger2.warn("credential refresh failed", {
46618
46618
  requestId,
@@ -47665,7 +47665,7 @@ function errorResponse(surface, code, message3, headers = {}) {
47665
47665
  function asGatewayError(error51) {
47666
47666
  if (error51 instanceof GatewayError)
47667
47667
  return error51;
47668
- return new GatewayError("INTERNAL", error51 instanceof Error ? error51.message : "internal error");
47668
+ return new GatewayError("INTERNAL", describeError(error51, "internal error"));
47669
47669
  }
47670
47670
  function sseResponse(frames, onDone, keepaliveMs, source, limitHeaders, onFrame) {
47671
47671
  const encoder4 = new TextEncoder;
@@ -48154,7 +48154,7 @@ function createShutdown(deps) {
48154
48154
  }, (error51) => {
48155
48155
  clearTimeout(timer);
48156
48156
  deps.logger.error("shutdown failed", {
48157
- reason: error51 instanceof Error ? error51.message : "unknown"
48157
+ reason: describeError(error51, "unknown")
48158
48158
  });
48159
48159
  exitAfterClosingStore(1);
48160
48160
  });
@@ -48198,7 +48198,7 @@ function startMaintenance(deps) {
48198
48198
  const timer = setInterval(() => {
48199
48199
  pruneFiles(files).then(({ snapshots, staging }) => logger2.debug("snapshots and staging files swept", { count: snapshots + staging })).catch((error51) => {
48200
48200
  logger2.error("snapshot sweeping failed", {
48201
- reason: error51 instanceof Error ? error51.message : "unknown"
48201
+ reason: describeError(error51, "unknown")
48202
48202
  });
48203
48203
  });
48204
48204
  pruneLogs(deps.store, deps.now()).then(({ raw, daily, quotaSamples, bodies, bodiesOverCap, bodyOrphans }) => logger2.debug("request logs pruned", {
@@ -48208,7 +48208,7 @@ function startMaintenance(deps) {
48208
48208
  count: bodies + bodiesOverCap + bodyOrphans
48209
48209
  })).catch((error51) => {
48210
48210
  logger2.error("log pruning failed", {
48211
- reason: error51 instanceof Error ? error51.message : "unknown"
48211
+ reason: describeError(error51, "unknown")
48212
48212
  });
48213
48213
  });
48214
48214
  }, SWEEP_INTERVAL_MS);
@@ -48245,7 +48245,7 @@ async function sweep(deps) {
48245
48245
  provider: credential.provider,
48246
48246
  credentialId: credential.id,
48247
48247
  code,
48248
- reason: error51 instanceof Error ? error51.message : "unknown"
48248
+ reason: describeError(error51, "unknown")
48249
48249
  });
48250
48250
  }
48251
48251
  }
@@ -48260,7 +48260,7 @@ function startRefreshScheduler(deps) {
48260
48260
  running = true;
48261
48261
  sweep(deps).catch((error51) => {
48262
48262
  logger2.error("token refresh sweep failed", {
48263
- reason: error51 instanceof Error ? error51.message : "unknown"
48263
+ reason: describeError(error51, "unknown")
48264
48264
  });
48265
48265
  }).finally(() => {
48266
48266
  running = false;
@@ -48491,7 +48491,7 @@ function buildContext(deps) {
48491
48491
  };
48492
48492
  }
48493
48493
  function reason(error51) {
48494
- return error51 instanceof Error ? error51.message : String(error51);
48494
+ return describeError(error51, String(error51));
48495
48495
  }
48496
48496
  async function loadPlugins(deps) {
48497
48497
  const logger2 = deps.logger ?? noopLogger;
@@ -48611,7 +48611,7 @@ async function startQuotaPoller(deps) {
48611
48611
  running = true;
48612
48612
  poll(deps).catch((error51) => {
48613
48613
  logger2.error("quota poll failed", {
48614
- reason: error51 instanceof Error ? error51.message : "unknown"
48614
+ reason: describeError(error51, "unknown")
48615
48615
  });
48616
48616
  }).finally(() => {
48617
48617
  running = false;
@@ -48773,7 +48773,7 @@ try {
48773
48773
  await main();
48774
48774
  } catch (error51) {
48775
48775
  logger2.error("gateway boot failed", {
48776
- reason: error51 instanceof Error ? error51.message : "unknown"
48776
+ reason: describeError(error51, "unknown")
48777
48777
  });
48778
48778
  process.exit(1);
48779
48779
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "omnigateway",
3
- "version": "0.4.5",
3
+ "version": "0.4.6",
4
4
  "description": "Self-hosted AI gateway with Anthropic- and OpenAI-compatible APIs, an admin console, and a CLI",
5
5
  "license": "MIT",
6
6
  "author": "Harismawan <mail@harismawan.com>",