omnigateway 0.4.4 → 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.
- package/bin/omni.js +20 -15
- package/gateway.js +36 -23
- 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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
46165
|
+
reason: describeError(error51, "unknown")
|
|
46161
46166
|
});
|
|
46162
46167
|
}
|
|
46163
46168
|
async function beginLog(store, log, keyId, logger2 = noopLogger) {
|
|
@@ -46272,6 +46277,14 @@ function classify(error51) {
|
|
|
46272
46277
|
if (error51 instanceof DOMException && error51.name === "AbortError") {
|
|
46273
46278
|
return { code: "TIMEOUT" };
|
|
46274
46279
|
}
|
|
46280
|
+
if (error51 instanceof AggregateError && Array.isArray(error51.errors)) {
|
|
46281
|
+
for (const inner of error51.errors) {
|
|
46282
|
+
const classified = classify(inner);
|
|
46283
|
+
if (classified.code !== "INTERNAL")
|
|
46284
|
+
return classified;
|
|
46285
|
+
}
|
|
46286
|
+
return { code: "INTERNAL" };
|
|
46287
|
+
}
|
|
46275
46288
|
if (error51 instanceof Error) {
|
|
46276
46289
|
const text = `${error51.name} ${error51.message}`.toLowerCase();
|
|
46277
46290
|
if (NETWORK_HINTS.some((hint) => text.includes(hint)))
|
|
@@ -46380,7 +46393,7 @@ async function dispatch(request2, deps, signal, requestId) {
|
|
|
46380
46393
|
if (isClientAbort(error51))
|
|
46381
46394
|
return fail("TIMEOUT", "client disconnected", true);
|
|
46382
46395
|
const { code } = classify(error51);
|
|
46383
|
-
return fail(code, error51
|
|
46396
|
+
return fail(code, describeError(error51, "unresolvable model"));
|
|
46384
46397
|
}
|
|
46385
46398
|
const { candidates, excluded } = rank({
|
|
46386
46399
|
request: dispatchRequest,
|
|
@@ -46545,7 +46558,7 @@ async function dispatch(request2, deps, signal, requestId) {
|
|
|
46545
46558
|
requestId,
|
|
46546
46559
|
provider: candidate.target.provider,
|
|
46547
46560
|
credentialId: candidate.credential.id,
|
|
46548
|
-
reason: healthError
|
|
46561
|
+
reason: describeError(healthError, "unknown")
|
|
46549
46562
|
});
|
|
46550
46563
|
}
|
|
46551
46564
|
return;
|
|
@@ -46580,7 +46593,7 @@ async function dispatch(request2, deps, signal, requestId) {
|
|
|
46580
46593
|
throw signal.reason;
|
|
46581
46594
|
const classifiedError = deadlineAt !== null && dispatchSignal.aborted ? { code: "TIMEOUT" } : classify(error51);
|
|
46582
46595
|
const { code: code2 } = classifiedError;
|
|
46583
|
-
const message2 = error51
|
|
46596
|
+
const message2 = describeError(error51, "attempt failed");
|
|
46584
46597
|
lastError = rewrap(classifiedError, message2);
|
|
46585
46598
|
if (code2 === "AUTH" && !committed && !authRefreshRetried && !preemptiveRefreshRequired && candidate.credential.authType === "oauth" && candidate.credential.hasRefreshToken) {
|
|
46586
46599
|
authRefreshRetried = true;
|
|
@@ -46599,7 +46612,7 @@ async function dispatch(request2, deps, signal, requestId) {
|
|
|
46599
46612
|
if (signal.aborted)
|
|
46600
46613
|
throw signal.reason;
|
|
46601
46614
|
const classified = deadlineAt !== null && dispatchSignal.aborted ? { code: "TIMEOUT" } : classify(refreshError);
|
|
46602
|
-
const refreshMessage = refreshError
|
|
46615
|
+
const refreshMessage = describeError(refreshError, "credential refresh failed");
|
|
46603
46616
|
lastError = rewrap(classified, refreshMessage);
|
|
46604
46617
|
logger2.warn("credential refresh failed", {
|
|
46605
46618
|
requestId,
|
|
@@ -47652,7 +47665,7 @@ function errorResponse(surface, code, message3, headers = {}) {
|
|
|
47652
47665
|
function asGatewayError(error51) {
|
|
47653
47666
|
if (error51 instanceof GatewayError)
|
|
47654
47667
|
return error51;
|
|
47655
|
-
return new GatewayError("INTERNAL", error51
|
|
47668
|
+
return new GatewayError("INTERNAL", describeError(error51, "internal error"));
|
|
47656
47669
|
}
|
|
47657
47670
|
function sseResponse(frames, onDone, keepaliveMs, source, limitHeaders, onFrame) {
|
|
47658
47671
|
const encoder4 = new TextEncoder;
|
|
@@ -48141,7 +48154,7 @@ function createShutdown(deps) {
|
|
|
48141
48154
|
}, (error51) => {
|
|
48142
48155
|
clearTimeout(timer);
|
|
48143
48156
|
deps.logger.error("shutdown failed", {
|
|
48144
|
-
reason: error51
|
|
48157
|
+
reason: describeError(error51, "unknown")
|
|
48145
48158
|
});
|
|
48146
48159
|
exitAfterClosingStore(1);
|
|
48147
48160
|
});
|
|
@@ -48185,7 +48198,7 @@ function startMaintenance(deps) {
|
|
|
48185
48198
|
const timer = setInterval(() => {
|
|
48186
48199
|
pruneFiles(files).then(({ snapshots, staging }) => logger2.debug("snapshots and staging files swept", { count: snapshots + staging })).catch((error51) => {
|
|
48187
48200
|
logger2.error("snapshot sweeping failed", {
|
|
48188
|
-
reason: error51
|
|
48201
|
+
reason: describeError(error51, "unknown")
|
|
48189
48202
|
});
|
|
48190
48203
|
});
|
|
48191
48204
|
pruneLogs(deps.store, deps.now()).then(({ raw, daily, quotaSamples, bodies, bodiesOverCap, bodyOrphans }) => logger2.debug("request logs pruned", {
|
|
@@ -48195,7 +48208,7 @@ function startMaintenance(deps) {
|
|
|
48195
48208
|
count: bodies + bodiesOverCap + bodyOrphans
|
|
48196
48209
|
})).catch((error51) => {
|
|
48197
48210
|
logger2.error("log pruning failed", {
|
|
48198
|
-
reason: error51
|
|
48211
|
+
reason: describeError(error51, "unknown")
|
|
48199
48212
|
});
|
|
48200
48213
|
});
|
|
48201
48214
|
}, SWEEP_INTERVAL_MS);
|
|
@@ -48232,7 +48245,7 @@ async function sweep(deps) {
|
|
|
48232
48245
|
provider: credential.provider,
|
|
48233
48246
|
credentialId: credential.id,
|
|
48234
48247
|
code,
|
|
48235
|
-
reason: error51
|
|
48248
|
+
reason: describeError(error51, "unknown")
|
|
48236
48249
|
});
|
|
48237
48250
|
}
|
|
48238
48251
|
}
|
|
@@ -48247,7 +48260,7 @@ function startRefreshScheduler(deps) {
|
|
|
48247
48260
|
running = true;
|
|
48248
48261
|
sweep(deps).catch((error51) => {
|
|
48249
48262
|
logger2.error("token refresh sweep failed", {
|
|
48250
|
-
reason: error51
|
|
48263
|
+
reason: describeError(error51, "unknown")
|
|
48251
48264
|
});
|
|
48252
48265
|
}).finally(() => {
|
|
48253
48266
|
running = false;
|
|
@@ -48478,7 +48491,7 @@ function buildContext(deps) {
|
|
|
48478
48491
|
};
|
|
48479
48492
|
}
|
|
48480
48493
|
function reason(error51) {
|
|
48481
|
-
return error51
|
|
48494
|
+
return describeError(error51, String(error51));
|
|
48482
48495
|
}
|
|
48483
48496
|
async function loadPlugins(deps) {
|
|
48484
48497
|
const logger2 = deps.logger ?? noopLogger;
|
|
@@ -48598,7 +48611,7 @@ async function startQuotaPoller(deps) {
|
|
|
48598
48611
|
running = true;
|
|
48599
48612
|
poll(deps).catch((error51) => {
|
|
48600
48613
|
logger2.error("quota poll failed", {
|
|
48601
|
-
reason: error51
|
|
48614
|
+
reason: describeError(error51, "unknown")
|
|
48602
48615
|
});
|
|
48603
48616
|
}).finally(() => {
|
|
48604
48617
|
running = false;
|
|
@@ -48760,7 +48773,7 @@ try {
|
|
|
48760
48773
|
await main();
|
|
48761
48774
|
} catch (error51) {
|
|
48762
48775
|
logger2.error("gateway boot failed", {
|
|
48763
|
-
reason: error51
|
|
48776
|
+
reason: describeError(error51, "unknown")
|
|
48764
48777
|
});
|
|
48765
48778
|
process.exit(1);
|
|
48766
48779
|
}
|
package/package.json
CHANGED