@jeffusion/bungee-core 5.23.0 → 5.23.1
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/dist/main.js +2692 -243
- package/dist/plugins/chatgpt-oauth/index.js +92 -20
- package/dist/plugins/chatgpt-oauth/index.js.map +4 -4
- package/dist/plugins/codex-router/control.js +606 -2
- package/dist/plugins/codex-router/control.js.map +19 -4
- package/dist/plugins/codex-router/index.js +127 -48
- package/dist/plugins/codex-router/index.js.map +7 -6
- package/dist/plugins/codex-router/manifest.json +14 -14
- package/dist/plugins/llm-protocol-adapter/control.js +4 -3
- package/dist/plugins/llm-protocol-adapter/control.js.map +3 -3
- package/dist/plugins/llm-protocol-adapter/index.js +4 -3
- package/dist/plugins/llm-protocol-adapter/index.js.map +4 -4
- package/dist/plugins/token-metering/index.js +1 -1
- package/dist/plugins/token-metering/index.js.map +1 -1
- package/package.json +2 -2
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
// plugins/codex-router/server/index.ts
|
|
3
|
-
import { createHash as
|
|
3
|
+
import { createHash as createHash3 } from "crypto";
|
|
4
4
|
|
|
5
5
|
// packages/core/src/plugin-logger.ts
|
|
6
6
|
var sinkKey = Symbol.for("@jeffusion/bungee/plugin-log-sink");
|
|
@@ -704,25 +704,6 @@ function protocolAdapter(input) {
|
|
|
704
704
|
});
|
|
705
705
|
} };
|
|
706
706
|
}
|
|
707
|
-
|
|
708
|
-
// plugins/models-dev/contract.ts
|
|
709
|
-
var MODELS_DEV_CATALOG_SNAPSHOT_ID = "models-dev.catalog.snapshot.v1";
|
|
710
|
-
var MODELS_DEV_CATALOG_SNAPSHOT_CONTRACT_VERSION = 1;
|
|
711
|
-
var MODELS_DEV_CATALOG_SNAPSHOT_SCHEMA = Object.freeze({
|
|
712
|
-
type: "object",
|
|
713
|
-
properties: {
|
|
714
|
-
version: { type: "number", integer: true, minimum: 1 },
|
|
715
|
-
fetchedAt: { type: "number", minimum: 0 },
|
|
716
|
-
catalog: { type: "json", maxBytes: 32 * 1024 * 1024 }
|
|
717
|
-
}
|
|
718
|
-
});
|
|
719
|
-
var MODELS_DEV_CATALOG_SNAPSHOT_CONTRACT = Object.freeze({
|
|
720
|
-
id: MODELS_DEV_CATALOG_SNAPSHOT_ID,
|
|
721
|
-
version: MODELS_DEV_CATALOG_SNAPSHOT_CONTRACT_VERSION,
|
|
722
|
-
content: MODELS_DEV_CATALOG_SNAPSHOT_SCHEMA
|
|
723
|
-
});
|
|
724
|
-
var MODELS_DEV_CAPABILITIES_SERVICE_ID = "models-dev.capabilities.v1";
|
|
725
|
-
var MODELS_DEV_CAPABILITIES_CONTRACT_VERSION = 1;
|
|
726
707
|
// plugins/codex-router/manifest.json
|
|
727
708
|
var manifest_default = {
|
|
728
709
|
name: "codex-router",
|
|
@@ -763,13 +744,6 @@ var manifest_default = {
|
|
|
763
744
|
process: "control",
|
|
764
745
|
kind: "local"
|
|
765
746
|
},
|
|
766
|
-
{
|
|
767
|
-
plugin: "models-dev",
|
|
768
|
-
id: "models-dev.catalog.v1",
|
|
769
|
-
version: 1,
|
|
770
|
-
process: "worker",
|
|
771
|
-
kind: "local"
|
|
772
|
-
},
|
|
773
747
|
{
|
|
774
748
|
plugin: "models-dev",
|
|
775
749
|
id: "models-dev.capabilities.v1",
|
|
@@ -777,13 +751,6 @@ var manifest_default = {
|
|
|
777
751
|
process: "control",
|
|
778
752
|
kind: "local"
|
|
779
753
|
},
|
|
780
|
-
{
|
|
781
|
-
plugin: "models-dev",
|
|
782
|
-
id: "models-dev.capabilities.v1",
|
|
783
|
-
version: 1,
|
|
784
|
-
process: "worker",
|
|
785
|
-
kind: "local"
|
|
786
|
-
},
|
|
787
754
|
{
|
|
788
755
|
plugin: "llm-protocol-adapter",
|
|
789
756
|
id: "llm-protocol-adapter.conversion.v1",
|
|
@@ -804,9 +771,23 @@ var manifest_default = {
|
|
|
804
771
|
version: 1,
|
|
805
772
|
process: "worker",
|
|
806
773
|
kind: "rpc"
|
|
774
|
+
},
|
|
775
|
+
{
|
|
776
|
+
plugin: "codex-router",
|
|
777
|
+
id: "codex-router.catalog-validators.v1",
|
|
778
|
+
version: 1,
|
|
779
|
+
process: "worker",
|
|
780
|
+
kind: "rpc"
|
|
807
781
|
}
|
|
808
782
|
],
|
|
809
|
-
provides: [
|
|
783
|
+
provides: [
|
|
784
|
+
{
|
|
785
|
+
id: "codex-router.catalog-validators.v1",
|
|
786
|
+
version: 1,
|
|
787
|
+
process: "control",
|
|
788
|
+
kind: "rpc"
|
|
789
|
+
}
|
|
790
|
+
]
|
|
810
791
|
},
|
|
811
792
|
configSchema: [
|
|
812
793
|
{
|
|
@@ -1218,8 +1199,61 @@ function mergeCatalog(native, bindings, catalog) {
|
|
|
1218
1199
|
}
|
|
1219
1200
|
return { ...body, [rich ? "models" : "data"]: [...existing.filter((entry) => !unavailable.has(rich ? entry.slug : entry.id)).map((entry) => replacements.get(rich ? entry.slug : entry.id) ?? entry), ...added] };
|
|
1220
1201
|
}
|
|
1221
|
-
function catalogEtag(body
|
|
1222
|
-
return `"${createHash("sha256").update(
|
|
1202
|
+
function catalogEtag(body) {
|
|
1203
|
+
return `"${createHash("sha256").update(body, "utf8").digest("hex")}"`;
|
|
1204
|
+
}
|
|
1205
|
+
|
|
1206
|
+
// plugins/codex-router/contract.ts
|
|
1207
|
+
var key2 = { type: "string", minLength: 64, maxLength: 64 };
|
|
1208
|
+
var etag = { type: "string", minLength: 66, maxLength: 66 };
|
|
1209
|
+
var catalogValidatorsRpc = defineRpcService({
|
|
1210
|
+
id: "codex-router.catalog-validators.v1",
|
|
1211
|
+
version: 1,
|
|
1212
|
+
methods: {
|
|
1213
|
+
get: {
|
|
1214
|
+
kind: "query",
|
|
1215
|
+
input: { type: "object", properties: { key: key2 } },
|
|
1216
|
+
output: { type: "union", variants: [etag, { type: "null" }] },
|
|
1217
|
+
purposes: ["request", "attempt"]
|
|
1218
|
+
},
|
|
1219
|
+
put: {
|
|
1220
|
+
kind: "command",
|
|
1221
|
+
input: { type: "object", properties: { key: key2, etag } },
|
|
1222
|
+
output: { type: "null" },
|
|
1223
|
+
purposes: ["request", "attempt"],
|
|
1224
|
+
command: { deduplication: "none", resultRetentionMs: 1, quotaBytes: 1024, maxResultBytes: 1024 }
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1227
|
+
});
|
|
1228
|
+
function catalogValidatorsClient(services) {
|
|
1229
|
+
return services.rpc.consume("codex-router", catalogValidatorsRpc);
|
|
1230
|
+
}
|
|
1231
|
+
|
|
1232
|
+
// plugins/codex-router/server/catalog-validators.ts
|
|
1233
|
+
import { createHash as createHash2 } from "crypto";
|
|
1234
|
+
function header(headers, name) {
|
|
1235
|
+
return Object.entries(headers).find(([key]) => key.toLowerCase() === name)?.[1] ?? "";
|
|
1236
|
+
}
|
|
1237
|
+
function catalogValidatorKey({ context, principal, servingRevision }, bindings) {
|
|
1238
|
+
const directory = context.method === "GET" && /\/models$/.test(context.originalUrl.pathname);
|
|
1239
|
+
const generation = context.method === "POST" && /\/responses$/.test(context.originalUrl.pathname);
|
|
1240
|
+
if (!directory && !generation || !context.routeId)
|
|
1241
|
+
return null;
|
|
1242
|
+
const versions = context.originalUrl.searchParams.getAll("client_version");
|
|
1243
|
+
const version = directory ? versions.length === 1 ? versions[0] : "" : header(context.headers, "version");
|
|
1244
|
+
if (!version || version.length > 128 || /[\u0000-\u0020\u007f]/.test(version))
|
|
1245
|
+
return null;
|
|
1246
|
+
return createHash2("sha256").update(JSON.stringify([
|
|
1247
|
+
context.routeId,
|
|
1248
|
+
servingRevision ?? null,
|
|
1249
|
+
bindings,
|
|
1250
|
+
principal ? [principal.domain, principal.keyId, principal.credentialVersion] : ["anonymous", "", 0],
|
|
1251
|
+
header(context.headers, "authorization"),
|
|
1252
|
+
header(context.headers, "x-api-key"),
|
|
1253
|
+
header(context.headers, "api-key"),
|
|
1254
|
+
header(context.headers, "chatgpt-account-id"),
|
|
1255
|
+
version
|
|
1256
|
+
])).digest("hex");
|
|
1223
1257
|
}
|
|
1224
1258
|
|
|
1225
1259
|
// plugins/codex-router/server/index.ts
|
|
@@ -1230,7 +1264,8 @@ var CodexRouterPlugin = definePlugin(class {
|
|
|
1230
1264
|
bindings;
|
|
1231
1265
|
relay;
|
|
1232
1266
|
history;
|
|
1233
|
-
|
|
1267
|
+
validators;
|
|
1268
|
+
catalogRequests = new Map;
|
|
1234
1269
|
conversion;
|
|
1235
1270
|
constructor(options) {
|
|
1236
1271
|
this.bindings = parseBindings(options?.models);
|
|
@@ -1241,19 +1276,29 @@ var CodexRouterPlugin = definePlugin(class {
|
|
|
1241
1276
|
throw new Error("codex_router_requires_route_scope");
|
|
1242
1277
|
this.history = historyClient(context.services.rpc.consume(ADAPTER_PLUGIN, historyRpc));
|
|
1243
1278
|
this.conversion = context.services.consume(ADAPTER_PLUGIN, CONVERSION_SERVICE_ID, CONVERSION_VERSION);
|
|
1244
|
-
|
|
1279
|
+
try {
|
|
1280
|
+
this.validators = catalogValidatorsClient(context.services);
|
|
1281
|
+
} catch {}
|
|
1282
|
+
context.services.onDispose?.(() => this.catalogRequests.clear());
|
|
1245
1283
|
}
|
|
1246
1284
|
bodyRequirements(context) {
|
|
1247
1285
|
return { request: context.method === "POST" && /\/responses$/.test(context.url.pathname) ? "json-write" : "none", response: context.method === "GET" && /\/models$/.test(context.url.pathname) ? ["json"] : [] };
|
|
1248
1286
|
}
|
|
1249
1287
|
register(hooks) {
|
|
1250
1288
|
hooks.onWebSocketSessionMode.tap("codex-router.session", (url) => /\/responses$/.test(url.pathname) ? "responses" : undefined);
|
|
1289
|
+
hooks.onDispatchRequest.tap("codex-router.catalog-identity", (input) => {
|
|
1290
|
+
const key = catalogValidatorKey(input, this.bindings);
|
|
1291
|
+
if (key)
|
|
1292
|
+
this.catalogRequests.set(input.context.requestId, { key, signal: input.signal });
|
|
1293
|
+
});
|
|
1251
1294
|
hooks.onDispatchRequest.tapPromise("codex-router.binding", async ({ context, targets }) => {
|
|
1252
1295
|
if (context.method !== "POST" || !/\/responses$/.test(context.originalUrl.pathname))
|
|
1253
1296
|
return;
|
|
1254
1297
|
const binding = this.bindings.find((binding) => bindingSource(binding) === context.body?.model);
|
|
1255
1298
|
if (!binding)
|
|
1256
1299
|
return;
|
|
1300
|
+
const notification = this.catalogRequests.get(context.requestId);
|
|
1301
|
+
this.catalogRequests.delete(context.requestId);
|
|
1257
1302
|
if (!targets.some((target) => target.type === binding.target.type && target.id === binding.target.id))
|
|
1258
1303
|
throw new DataAdmissionError(422, "codex_router_target_unavailable");
|
|
1259
1304
|
const protocol = binding.target.protocol;
|
|
@@ -1262,8 +1307,8 @@ var CodexRouterPlugin = definePlugin(class {
|
|
|
1262
1307
|
throw new DataAdmissionError(503, "codex_router_model_unavailable");
|
|
1263
1308
|
context.body = { ...context.body, model: binding.model };
|
|
1264
1309
|
return { target: binding.target, protocol, prepareRequest: async ({ context, principal, servingRevision, signal, executeAuxiliary, webSocketConnection }) => {
|
|
1265
|
-
const entryScope =
|
|
1266
|
-
const scope = principal?.domain !== "anonymous" && principal?.keyId ?
|
|
1310
|
+
const entryScope = createHash3("sha256").update(JSON.stringify([context.routeId, servingRevision ?? null, this.bindings, this.relay])).digest("hex");
|
|
1311
|
+
const scope = principal?.domain !== "anonymous" && principal?.keyId ? createHash3("sha256").update(JSON.stringify([principal, entryScope])).digest("hex") : null;
|
|
1267
1312
|
let input = structuredClone(context.body);
|
|
1268
1313
|
let requiredUpstreamId;
|
|
1269
1314
|
let opaqueRestored = false;
|
|
@@ -1346,9 +1391,7 @@ var CodexRouterPlugin = definePlugin(class {
|
|
|
1346
1391
|
throw new DataAdmissionError(422, `llm_adapter_${e.code}`, undefined, { message: e.message, param: e.param });
|
|
1347
1392
|
throw error;
|
|
1348
1393
|
}
|
|
1349
|
-
|
|
1350
|
-
context.url.pathname = context.url.pathname.replace(/\/responses$/, protocol === "chat_completions" ? "/chat/completions" : "/messages");
|
|
1351
|
-
const adapter = protocolAdapter({
|
|
1394
|
+
const converted = protocolAdapter({
|
|
1352
1395
|
session,
|
|
1353
1396
|
protocol,
|
|
1354
1397
|
model: bindingSource(binding),
|
|
@@ -1358,6 +1401,13 @@ var CodexRouterPlugin = definePlugin(class {
|
|
|
1358
1401
|
await this.history.put({ scope, id: response.id, value: { target: binding.target, origin: { provider: binding.provider, model: binding.model, upstreamId: responseContext?.upstreamId }, items: [...logicalInput, ...response.output] } }, { signal, operationId: crypto.randomUUID() });
|
|
1359
1402
|
}
|
|
1360
1403
|
});
|
|
1404
|
+
const adapter = { bodyRequirements: converted.bodyRequirements.bind(converted), register: (hooks) => {
|
|
1405
|
+
converted.register(hooks);
|
|
1406
|
+
hooks.onRawResponse.tapPromise("codex-router.catalog-notification", async (result) => {
|
|
1407
|
+
await this.rewriteCatalogNotification(result.response, notification);
|
|
1408
|
+
return result;
|
|
1409
|
+
});
|
|
1410
|
+
} };
|
|
1361
1411
|
return { requiredUpstreamId, adapter, ...protocol !== "responses" ? { canonicalInput: logicalInput, diagnostics } : {} };
|
|
1362
1412
|
} };
|
|
1363
1413
|
});
|
|
@@ -1369,20 +1419,49 @@ var CodexRouterPlugin = definePlugin(class {
|
|
|
1369
1419
|
}
|
|
1370
1420
|
return context;
|
|
1371
1421
|
});
|
|
1422
|
+
hooks.onRawResponse.tapPromise("codex-router.catalog-notification", async (result, context) => {
|
|
1423
|
+
if (context.method === "POST" && /\/responses$/.test(context.originalUrl.pathname)) {
|
|
1424
|
+
await this.rewriteCatalogNotification(result.response, this.catalogRequests.get(context.requestId));
|
|
1425
|
+
}
|
|
1426
|
+
return result;
|
|
1427
|
+
});
|
|
1372
1428
|
hooks.onResponse.tapPromise("codex-router.catalog", async (response, context) => {
|
|
1429
|
+
const record = this.catalogRequests.get(context.requestId);
|
|
1373
1430
|
if (context.method !== "GET" || !/\/models$/.test(context.originalUrl.pathname) || !response.ok)
|
|
1374
1431
|
return response;
|
|
1375
1432
|
const native = await context.bodyHandle.json({ id: "codex-router.catalog", mandatory: true });
|
|
1376
|
-
const body = mergeCatalog(native, this.bindings, this.conversion);
|
|
1433
|
+
const body = JSON.stringify(mergeCatalog(native, this.bindings, this.conversion));
|
|
1434
|
+
const etag = catalogEtag(body);
|
|
1377
1435
|
const headers = new Headers(response.headers);
|
|
1378
1436
|
for (const key of ["content-length", "content-encoding", "etag", "last-modified"])
|
|
1379
1437
|
headers.delete(key);
|
|
1380
1438
|
headers.set("content-type", "application/json");
|
|
1381
1439
|
headers.set("cache-control", "private, no-store");
|
|
1382
|
-
headers.set("etag",
|
|
1383
|
-
|
|
1440
|
+
headers.set("etag", etag);
|
|
1441
|
+
if (record && this.validators) {
|
|
1442
|
+
try {
|
|
1443
|
+
await this.validators.put({ key: record.key, etag }, { signal: record.signal, timeoutMs: 1000, operationId: crypto.randomUUID() });
|
|
1444
|
+
} catch {}
|
|
1445
|
+
}
|
|
1446
|
+
return new Response(body, { status: response.status, headers });
|
|
1447
|
+
});
|
|
1448
|
+
hooks.onFinally.tap("codex-router.catalog-cleanup", (context) => {
|
|
1449
|
+
this.catalogRequests.delete(context.requestId);
|
|
1384
1450
|
});
|
|
1385
1451
|
}
|
|
1452
|
+
async rewriteCatalogNotification(response, record) {
|
|
1453
|
+
response.headers.delete("x-models-etag");
|
|
1454
|
+
if (record && this.validators) {
|
|
1455
|
+
try {
|
|
1456
|
+
const etag = await this.validators.get({ key: record.key }, { signal: record.signal, timeoutMs: 1000 });
|
|
1457
|
+
if (etag && !record.signal.aborted)
|
|
1458
|
+
response.headers.set("x-models-etag", etag);
|
|
1459
|
+
} catch {}
|
|
1460
|
+
}
|
|
1461
|
+
}
|
|
1462
|
+
reset() {
|
|
1463
|
+
this.catalogRequests.clear();
|
|
1464
|
+
}
|
|
1386
1465
|
});
|
|
1387
1466
|
var server_default = CodexRouterPlugin;
|
|
1388
1467
|
export {
|
|
@@ -1390,4 +1469,4 @@ export {
|
|
|
1390
1469
|
server_default as default
|
|
1391
1470
|
};
|
|
1392
1471
|
|
|
1393
|
-
//# debugId=
|
|
1472
|
+
//# debugId=C5F01ADAD6007FBF64756E2164756E21
|