@jeffusion/bungee-core 5.22.0 → 5.23.0

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/dist/main.js +3382 -3104
  2. package/dist/plugins/anthropic-request-sanitizer/index.js.map +2 -2
  3. package/dist/plugins/anthropic-tool-name-transformer/index.js.map +2 -2
  4. package/dist/plugins/chatgpt-oauth/control.js.map +2 -2
  5. package/dist/plugins/chatgpt-oauth/index.js +20 -7
  6. package/dist/plugins/chatgpt-oauth/index.js.map +6 -6
  7. package/dist/plugins/codex-router/index.js +174 -80
  8. package/dist/plugins/codex-router/index.js.map +8 -8
  9. package/dist/plugins/codex-router/manifest.json +63 -12
  10. package/dist/plugins/deepseek-reasoning-fix/index.js.map +2 -2
  11. package/dist/plugins/key-access/control.js.map +3 -3
  12. package/dist/plugins/key-access/index.js +19 -5
  13. package/dist/plugins/key-access/index.js.map +6 -6
  14. package/dist/plugins/key-access/ingress.js +19 -5
  15. package/dist/plugins/key-access/ingress.js.map +6 -6
  16. package/dist/plugins/key-rate-limit/index.js.map +2 -2
  17. package/dist/plugins/llm-protocol-adapter/control.js +785 -209
  18. package/dist/plugins/llm-protocol-adapter/control.js.map +21 -17
  19. package/dist/plugins/llm-protocol-adapter/index.js +861 -208
  20. package/dist/plugins/llm-protocol-adapter/index.js.map +21 -17
  21. package/dist/plugins/llm-protocol-adapter/manifest.json +7 -0
  22. package/dist/plugins/local-accounts/control.js.map +2 -2
  23. package/dist/plugins/local-accounts/index.js.map +2 -2
  24. package/dist/plugins/model-mapping/index.js.map +2 -2
  25. package/dist/plugins/models-dev/index.js.map +2 -2
  26. package/dist/plugins/signature-repair/index.js.map +2 -2
  27. package/dist/plugins/token-budget/control.js.map +2 -2
  28. package/dist/plugins/token-budget/index.js.map +3 -3
  29. package/dist/plugins/token-metering/index.js +9 -9
  30. package/dist/plugins/token-metering/index.js.map +7 -7
  31. package/dist/plugins/token-stats/control.js.map +2 -2
  32. package/dist/plugins/token-stats/index.js.map +3 -3
  33. package/dist/plugins/token-stats/ui/PriceModelPicker.svelte +3 -3
  34. package/package.json +2 -2
@@ -896,6 +896,29 @@ var manifest_default = {
896
896
  }
897
897
  ]
898
898
  }
899
+ },
900
+ {
901
+ name: "collaborationRelay",
902
+ type: "object",
903
+ label: "relay.label",
904
+ properties: [
905
+ {
906
+ name: "target",
907
+ type: "gateway_target",
908
+ label: "relay.target",
909
+ required: true
910
+ },
911
+ {
912
+ name: "model",
913
+ type: "string",
914
+ label: "relay.model",
915
+ required: true,
916
+ validation: {
917
+ trimmed: true,
918
+ max: 512
919
+ }
920
+ }
921
+ ]
899
922
  }
900
923
  ],
901
924
  contributes: {
@@ -919,26 +942,27 @@ var manifest_default = {
919
942
  "metadata.name": "Codex \u6A21\u578B\u8DEF\u7531",
920
943
  "plugin.description": "\u4ECE\u5171\u4EAB\u76EE\u5F55\u9009\u62E9\u6A21\u578B\u5E76\u7ED1\u5B9A\u5DF2\u6709\u8DEF\u7531\u6216\u670D\u52A1",
921
944
  "models.label": "\u6A21\u578B\u7ED1\u5B9A",
922
- "editor.description": "\u6309\u539F\u59CB\u6A21\u578B\u5339\u914D\u8BF7\u6C42\uFF0C\u5C06\u76EE\u6807\u6A21\u578B\u8F6C\u53D1\u5230\u6307\u5B9A\u8DEF\u7531\u6216\u670D\u52A1\u3002",
923
945
  "editor.binding": "\u7ED1\u5B9A",
924
946
  "editor.match": "\u5339\u914D\u8BF7\u6C42",
925
947
  "editor.sourceProvider": "\u539F\u59CB\u63D0\u4F9B\u5546",
926
948
  "editor.manual": "\u624B\u52A8\u8F93\u5165",
927
949
  "editor.fromCatalog": "\u4ECE\u76EE\u5F55\u9009\u62E9",
928
950
  "editor.source": "\u539F\u59CB\u6A21\u578B",
929
- "editor.sourceHint": "\u7CBE\u786E\u5339\u914D\u5BA2\u6237\u7AEF\u8BF7\u6C42\u4E2D\u7684\u6A21\u578B\u6807\u8BC6\uFF1B\u4F9B\u5E94\u5546\u4EC5\u7528\u4E8E\u76EE\u5F55\u7B5B\u9009\u3002",
930
951
  "editor.sourcePlaceholder": "\u4F8B\u5982 gpt-5.4",
931
952
  "editor.provider": "\u76EE\u6807\u63D0\u4F9B\u5546",
932
953
  "editor.model": "\u76EE\u6807\u6A21\u578B",
933
- "editor.target": "\u8F6C\u53D1\u8DEF\u7531 / \u670D\u52A1",
934
- "editor.targetPlaceholder": "\u9009\u62E9\u5DF2\u6709\u8DEF\u7531\u6216\u670D\u52A1",
954
+ "editor.target": "\u8F6C\u53D1\u76EE\u6807",
955
+ "editor.targetType": "\u76EE\u6807\u7C7B\u578B",
956
+ "editor.targetTypePlaceholder": "\u9009\u62E9\u76EE\u6807\u7C7B\u578B",
957
+ "editor.routePlaceholder": "\u9009\u62E9\u8DEF\u7531",
958
+ "editor.servicePlaceholder": "\u9009\u62E9\u670D\u52A1",
959
+ "editor.forward": "\u8F6C\u53D1\u8BF7\u6C42",
935
960
  "editor.search": "\u641C\u7D22\u6A21\u578B",
936
961
  "editor.empty": "\u6CA1\u6709\u5339\u914D\u7684\u6A21\u578B",
937
962
  "editor.loading": "\u6B63\u5728\u52A0\u8F7D\u6A21\u578B\u76EE\u5F55",
938
963
  "editor.error": "\u76EE\u5F55\u4E0D\u53EF\u7528\uFF0C\u8BF7\u68C0\u67E5 models.dev \u6216\u91CD\u8BD5\u3002",
939
964
  "editor.targetsError": "\u65E0\u6CD5\u8BFB\u53D6\u8F6C\u53D1\u76EE\u6807\uFF0C\u8BF7\u91CD\u8BD5\u3002",
940
965
  "editor.retry": "\u91CD\u8BD5",
941
- "editor.add": "\u6DFB\u52A0\u6A21\u578B\u7ED1\u5B9A",
942
966
  "editor.remove": "\u79FB\u9664",
943
967
  "editor.noBindings": "\u5C1A\u672A\u914D\u7F6E\u6A21\u578B\u7ED1\u5B9A\u3002",
944
968
  "editor.noCatalog": "\u76EE\u5F55\u4E3A\u7A7A\uFF0C\u8BF7\u5148\u542F\u7528 models.dev \u5E76\u5237\u65B0\u76EE\u5F55\u3002",
@@ -957,7 +981,20 @@ var manifest_default = {
957
981
  "editor.route": "\u8DEF\u7531",
958
982
  "editor.service": "\u670D\u52A1",
959
983
  "editor.targetUnavailable": "\u76EE\u6807\u4E0D\u53EF\u7528",
960
- "editor.noOptions": "\u6CA1\u6709\u5339\u914D\u7684\u9009\u9879"
984
+ "editor.noOptions": "\u6CA1\u6709\u5339\u914D\u7684\u9009\u9879",
985
+ "relay.label": "\u534F\u4F5C\u4E2D\u7EE7",
986
+ "relay.target": "\u4E2D\u7EE7\u76EE\u6807",
987
+ "relay.model": "\u4E2D\u7EE7\u6A21\u578B",
988
+ "relay.modelPlaceholder": "\u9009\u62E9 OpenAI \u6A21\u578B",
989
+ "relay.modelInvalid": "\u8BF7\u9009\u62E9\u6709\u6548\u7684\u4E2D\u7EE7\u6A21\u578B\u3002",
990
+ "relay.targetRequired": "\u8BF7\u9009\u62E9\u53EF\u7528\u7684\u4E2D\u7EE7\u8DEF\u7531\u6216\u670D\u52A1\u3002",
991
+ "relay.protocolInvalid": "\u4E2D\u7EE7\u76EE\u6807\u63A5\u6536\u534F\u8BAE\u5FC5\u987B\u4E3A Responses\u3002",
992
+ "editor.mode": "\u7ED1\u5B9A\u65B9\u5F0F",
993
+ "editor.addModel": "\u65B0\u589E\u6A21\u578B",
994
+ "editor.replaceModel": "\u66FF\u6362\u6A21\u578B",
995
+ "editor.addReplacement": "\u6DFB\u52A0\u6A21\u578B\u66FF\u6362",
996
+ "editor.bindingInvalid": "\u8BF7\u586B\u5199\u6709\u6548\u7684\u6A21\u578B\u3001\u8F6C\u53D1\u76EE\u6807\u548C\u534F\u8BAE\u3002",
997
+ "editor.modelConflict": "\u6A21\u578B\u7ED1\u5B9A\u91CD\u590D\uFF0C\u8BF7\u4FEE\u6539\u6A21\u578B\u6216\u79FB\u9664\u91CD\u590D\u7ED1\u5B9A\u3002"
961
998
  },
962
999
  en: {
963
1000
  "editor.loaded": "Loaded",
@@ -966,26 +1003,27 @@ var manifest_default = {
966
1003
  "metadata.name": "Codex Router",
967
1004
  "plugin.description": "Bind catalog models to existing routes or services",
968
1005
  "models.label": "Model bindings",
969
- "editor.description": "Match the original model and forward the target model through an existing route or service.",
970
1006
  "editor.binding": "Binding",
971
1007
  "editor.match": "Match request",
972
1008
  "editor.sourceProvider": "Original provider",
973
1009
  "editor.manual": "Enter manually",
974
1010
  "editor.fromCatalog": "Choose from catalog",
975
1011
  "editor.source": "Original model",
976
- "editor.sourceHint": "Match the exact model ID in client requests; the provider only filters the catalog.",
977
1012
  "editor.sourcePlaceholder": "For example, gpt-5.4",
978
1013
  "editor.provider": "Target provider",
979
1014
  "editor.model": "Target model",
980
- "editor.target": "Forwarding route / service",
981
- "editor.targetPlaceholder": "Select an existing route or service",
1015
+ "editor.target": "Forwarding target",
1016
+ "editor.targetType": "Target type",
1017
+ "editor.targetTypePlaceholder": "Select a target type",
1018
+ "editor.routePlaceholder": "Select a route",
1019
+ "editor.servicePlaceholder": "Select a service",
1020
+ "editor.forward": "Forward request",
982
1021
  "editor.search": "Search models",
983
1022
  "editor.empty": "No matching models",
984
1023
  "editor.loading": "Loading model catalog",
985
1024
  "editor.error": "Catalog unavailable. Check models.dev or retry.",
986
1025
  "editor.targetsError": "Unable to load forwarding targets. Please retry.",
987
1026
  "editor.retry": "Retry",
988
- "editor.add": "Add model binding",
989
1027
  "editor.remove": "Remove",
990
1028
  "editor.noBindings": "No model bindings configured.",
991
1029
  "editor.noCatalog": "The catalog is empty. Enable models.dev and refresh it first.",
@@ -1004,13 +1042,36 @@ var manifest_default = {
1004
1042
  "editor.route": "Route",
1005
1043
  "editor.service": "Service",
1006
1044
  "editor.targetUnavailable": "Target unavailable",
1007
- "editor.noOptions": "No matching options"
1045
+ "editor.noOptions": "No matching options",
1046
+ "relay.label": "Collaboration relay",
1047
+ "relay.target": "Relay target",
1048
+ "relay.model": "Relay model",
1049
+ "relay.modelPlaceholder": "Select an OpenAI model",
1050
+ "relay.modelInvalid": "Select a valid relay model.",
1051
+ "relay.targetRequired": "Select an available relay route or service.",
1052
+ "relay.protocolInvalid": "The relay target must receive Responses.",
1053
+ "editor.mode": "Binding mode",
1054
+ "editor.addModel": "Add model",
1055
+ "editor.replaceModel": "Replace model",
1056
+ "editor.addReplacement": "Add model replacement",
1057
+ "editor.bindingInvalid": "Select valid models, a forwarding target and a protocol.",
1058
+ "editor.modelConflict": "Duplicate model binding. Change the model or remove the duplicate."
1008
1059
  }
1009
1060
  },
1010
1061
  uiExtensionMode: "none"
1011
1062
  };
1012
1063
 
1013
1064
  // plugins/codex-router/server/config.ts
1065
+ function parseCollaborationRelay(value) {
1066
+ if (value === undefined)
1067
+ return;
1068
+ if (!value || typeof value !== "object" || Array.isArray(value))
1069
+ throw new Error("codex_router_invalid_collaboration_relay");
1070
+ const relay = value, target = relay.target;
1071
+ if (Object.keys(relay).some((key) => !["target", "model"].includes(key)) || typeof relay.model !== "string" || !relay.model || relay.model !== relay.model.trim() || relay.model.length > 512 || /[\x00-\x1f\x7f]/.test(relay.model) || !target || typeof target !== "object" || Array.isArray(target) || !["route", "service"].includes(target.type) || typeof target.id !== "string" || !target.id || target.id !== target.id.trim() || target.id.length > 512 || /[\x00-\x1f\x7f]/.test(target.id) || target.protocol !== "responses" || Object.keys(target).some((key) => !["type", "id", "protocol"].includes(key)))
1072
+ throw new Error("codex_router_invalid_collaboration_relay");
1073
+ return Object.freeze(structuredClone(relay));
1074
+ }
1014
1075
  function bindingSource(binding) {
1015
1076
  return binding.source ?? binding.alias ?? binding.model;
1016
1077
  }
@@ -1167,11 +1228,13 @@ var CodexRouterPlugin = definePlugin(class {
1167
1228
  static version = "1.0.0";
1168
1229
  static configSchema = manifest_default.configSchema;
1169
1230
  bindings;
1231
+ relay;
1170
1232
  history;
1171
1233
  catalog;
1172
1234
  conversion;
1173
1235
  constructor(options) {
1174
1236
  this.bindings = parseBindings(options?.models);
1237
+ this.relay = parseCollaborationRelay(options?.collaborationRelay);
1175
1238
  }
1176
1239
  async init(context) {
1177
1240
  if (context.scope?.type !== "route")
@@ -1185,7 +1248,7 @@ var CodexRouterPlugin = definePlugin(class {
1185
1248
  }
1186
1249
  register(hooks) {
1187
1250
  hooks.onWebSocketSessionMode.tap("codex-router.session", (url) => /\/responses$/.test(url.pathname) ? "responses" : undefined);
1188
- hooks.onDispatchRequest.tapPromise("codex-router.binding", async ({ context, targets, principal, servingRevision, signal }) => {
1251
+ hooks.onDispatchRequest.tapPromise("codex-router.binding", async ({ context, targets }) => {
1189
1252
  if (context.method !== "POST" || !/\/responses$/.test(context.originalUrl.pathname))
1190
1253
  return;
1191
1254
  const binding = this.bindings.find((binding) => bindingSource(binding) === context.body?.model);
@@ -1197,75 +1260,106 @@ var CodexRouterPlugin = definePlugin(class {
1197
1260
  const capabilities = this.conversion.resolveCapabilities({ provider: binding.provider, model: binding.model, targetProtocol: protocol, restrictions: binding.capabilityOverrides });
1198
1261
  if (!capabilities || capabilities.contextWindow === null || !capabilities.inputModalities.includes("text"))
1199
1262
  throw new DataAdmissionError(503, "codex_router_model_unavailable");
1200
- const scope = principal?.domain !== "anonymous" && principal?.keyId ? createHash2("sha256").update(JSON.stringify([principal, context.routeId, servingRevision ?? null, this.bindings])).digest("hex") : null;
1201
- const input = structuredClone(context.body);
1202
- let requiredUpstreamId;
1203
- let opaqueRestored = false;
1204
- if (input.previous_response_id) {
1205
- if (!scope)
1206
- throw new DataAdmissionError(422, "codex_router_history_identity_required");
1207
- const prior = await this.history.get({ scope, id: input.previous_response_id }, { signal });
1208
- if (!prior)
1209
- throw new DataAdmissionError(422, "codex_router_history_missing_start_new_conversation");
1210
- const delta = typeof input.input === "string" ? [{ role: "user", content: input.input }] : input.input;
1211
- if (!Array.isArray(delta))
1263
+ context.body = { ...context.body, model: binding.model };
1264
+ return { target: binding.target, protocol, prepareRequest: async ({ context, principal, servingRevision, signal, executeAuxiliary, webSocketConnection }) => {
1265
+ const entryScope = createHash2("sha256").update(JSON.stringify([context.routeId, servingRevision ?? null, this.bindings, this.relay])).digest("hex");
1266
+ const scope = principal?.domain !== "anonymous" && principal?.keyId ? createHash2("sha256").update(JSON.stringify([principal, entryScope])).digest("hex") : null;
1267
+ let input = structuredClone(context.body);
1268
+ let requiredUpstreamId;
1269
+ let opaqueRestored = false;
1270
+ if (input.previous_response_id) {
1271
+ if (!scope)
1272
+ throw new DataAdmissionError(422, "codex_router_history_identity_required");
1273
+ const prior = await this.history.get({ scope, id: input.previous_response_id }, { signal });
1274
+ if (!prior)
1275
+ throw new DataAdmissionError(422, "codex_router_history_missing_start_new_conversation");
1276
+ const delta = typeof input.input === "string" ? [{ role: "user", content: input.input }] : input.input;
1277
+ if (!Array.isArray(delta))
1278
+ throw new DataAdmissionError(422, "codex_router_invalid_history");
1279
+ if (prior.items.some((item) => item.encrypted_content || item.type === "compaction")) {
1280
+ if (protocol !== "responses" || JSON.stringify(prior.target) !== JSON.stringify(binding.target) || prior.origin?.provider !== binding.provider || prior.origin?.model !== binding.model || !prior.origin?.upstreamId)
1281
+ throw new DataAdmissionError(422, "codex_router_unrestorable_history_start_new_conversation");
1282
+ requiredUpstreamId = prior.origin.upstreamId;
1283
+ opaqueRestored = true;
1284
+ }
1285
+ input.input = [...prior.items, ...delta];
1286
+ delete input.previous_response_id;
1287
+ }
1288
+ if (input.conversation || input.response_id)
1289
+ throw new DataAdmissionError(422, "codex_router_unsupported_history_reference");
1290
+ input.model = binding.model;
1291
+ let logicalInput = typeof input.input === "string" ? [{ role: "user", content: input.input }] : input.input;
1292
+ if (!Array.isArray(logicalInput))
1212
1293
  throw new DataAdmissionError(422, "codex_router_invalid_history");
1213
- if (prior.items.some((item) => item.encrypted_content || item.type === "compaction")) {
1214
- if (protocol !== "responses" || JSON.stringify(prior.target) !== JSON.stringify(binding.target) || prior.origin?.provider !== binding.provider || prior.origin?.model !== binding.model || !prior.origin?.upstreamId)
1215
- throw new DataAdmissionError(422, "codex_router_unrestorable_history_start_new_conversation");
1216
- requiredUpstreamId = prior.origin.upstreamId;
1217
- opaqueRestored = true;
1294
+ if (protocol !== "responses" && !opaqueRestored && logicalInput.some((item) => item?.encrypted_content || item?.type === "compaction"))
1295
+ throw new DataAdmissionError(422, "codex_router_unrestorable_history_start_new_conversation");
1296
+ const hasTools = input.tools?.length || logicalInput.some((item) => item?.type === "additional_tools" && item.tools?.length);
1297
+ if (hasTools && (!capabilities.toolCall || binding.capabilityOverrides?.tools === false))
1298
+ throw new DataAdmissionError(422, "codex_router_tools_unsupported");
1299
+ let relayDiagnostics = [];
1300
+ if (protocol !== "responses") {
1301
+ try {
1302
+ const inspected = this.conversion.inspectAgentMessages(input);
1303
+ for (const message of inspected.messages)
1304
+ if (message.encryptedContents.length > 1)
1305
+ throw new DataAdmissionError(422, "llm_adapter_agent_message_multiple_encrypted_blocks", undefined, { param: message.encryptedContents[1].param, message: "Multiple encrypted agent blocks cannot be restored losslessly" });
1306
+ const replacements = [];
1307
+ for (const message of inspected.messages)
1308
+ for (const encrypted of message.encryptedContents) {
1309
+ if (!this.relay)
1310
+ throw new DataAdmissionError(422, "llm_adapter_agent_message_relay_required", undefined, { param: encrypted.param, message: "Encrypted agent content requires a configured relay" });
1311
+ const text = await this.conversion.relayAgentMessage({ message: input.input[message.inputIndex], contentIndex: encrypted.contentIndex, param: encrypted.param, relay: this.relay, entryScope, scope, requestId: context.requestId, signal, executeAuxiliary, webSocketConnection });
1312
+ replacements.push({ param: encrypted.param, text });
1313
+ }
1314
+ if (replacements.length) {
1315
+ const replaced = this.conversion.replaceAgentMessageEncryptedContent(input, replacements);
1316
+ input = replaced.body;
1317
+ relayDiagnostics = replaced.diagnostics;
1318
+ }
1319
+ } catch (error) {
1320
+ const e = error;
1321
+ if (typeof e.code === "string" && e.name !== "DataAdmissionError")
1322
+ throw new DataAdmissionError(422, `llm_adapter_${e.code}`, undefined, { message: "Agent message cannot be converted", param: e.param });
1323
+ throw error;
1324
+ }
1218
1325
  }
1219
- input.input = [...prior.items, ...delta];
1220
- delete input.previous_response_id;
1221
- }
1222
- if (input.conversation || input.response_id)
1223
- throw new DataAdmissionError(422, "codex_router_unsupported_history_reference");
1224
- input.model = binding.model;
1225
- let logicalInput = typeof input.input === "string" ? [{ role: "user", content: input.input }] : input.input;
1226
- if (!Array.isArray(logicalInput))
1227
- throw new DataAdmissionError(422, "codex_router_invalid_history");
1228
- if (!opaqueRestored && logicalInput.some((item) => item?.encrypted_content || item?.type === "compaction"))
1229
- throw new DataAdmissionError(422, "codex_router_unrestorable_history_start_new_conversation");
1230
- const hasTools = input.tools?.length || logicalInput.some((item) => item?.type === "additional_tools" && item.tools?.length);
1231
- if (hasTools && (!capabilities.toolCall || binding.capabilityOverrides?.tools === false))
1232
- throw new DataAdmissionError(422, "codex_router_tools_unsupported");
1233
- let diagnostics;
1234
- let session;
1235
- try {
1236
- session = this.conversion.createSession({ sourceProtocol: "responses", targetProtocol: protocol, model: binding.model, responseModel: bindingSource(binding), provider: binding.provider, profile: capabilities, selectedEffort: input.reasoning?.effort });
1237
- } catch (error) {
1238
- const e = error;
1239
- if (typeof e.code === "string")
1240
- throw new DataAdmissionError(422, `llm_adapter_${e.code}`, undefined, { message: e.message, param: e.param });
1241
- throw error;
1242
- }
1243
- try {
1244
- const decoded = session.convertRequest(input);
1245
- context.body = structuredClone(decoded.body);
1246
- if (protocol !== "responses")
1247
- logicalInput = structuredClone(decoded.canonicalHistory);
1248
- diagnostics = structuredClone(decoded.diagnostics);
1249
- } catch (error) {
1250
- session.dispose();
1251
- const e = error;
1252
- if (typeof e.code === "string")
1253
- throw new DataAdmissionError(422, `llm_adapter_${e.code}`, undefined, { message: e.message, param: e.param });
1254
- throw error;
1255
- }
1256
- if (protocol !== "responses")
1257
- context.url.pathname = context.url.pathname.replace(/\/responses$/, protocol === "chat_completions" ? "/chat/completions" : "/messages");
1258
- const adapter = protocolAdapter({
1259
- session,
1260
- protocol,
1261
- model: bindingSource(binding),
1262
- signal,
1263
- save: async (response, responseContext) => {
1264
- if (scope && typeof response.id === "string")
1265
- 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() });
1326
+ let diagnostics;
1327
+ let session;
1328
+ try {
1329
+ session = this.conversion.createSession({ sourceProtocol: "responses", targetProtocol: protocol, model: binding.model, responseModel: bindingSource(binding), provider: binding.provider, profile: capabilities, selectedEffort: input.reasoning?.effort, ...protocol !== "responses" ? { agentMessageDelivery: "plaintext" } : {} });
1330
+ } catch (error) {
1331
+ const e = error;
1332
+ if (typeof e.code === "string")
1333
+ throw new DataAdmissionError(422, `llm_adapter_${e.code}`, undefined, { message: e.message, param: e.param });
1334
+ throw error;
1335
+ }
1336
+ try {
1337
+ const decoded = session.convertRequest(input);
1338
+ context.body = structuredClone(decoded.body);
1339
+ if (protocol !== "responses")
1340
+ logicalInput = structuredClone(decoded.canonicalHistory);
1341
+ diagnostics = structuredClone([...relayDiagnostics, ...decoded.diagnostics]);
1342
+ } catch (error) {
1343
+ session.dispose();
1344
+ const e = error;
1345
+ if (typeof e.code === "string")
1346
+ throw new DataAdmissionError(422, `llm_adapter_${e.code}`, undefined, { message: e.message, param: e.param });
1347
+ throw error;
1266
1348
  }
1267
- });
1268
- return { target: binding.target, protocol, requiredUpstreamId, adapter, ...protocol !== "responses" ? { canonicalInput: logicalInput, diagnostics } : {} };
1349
+ if (protocol !== "responses")
1350
+ context.url.pathname = context.url.pathname.replace(/\/responses$/, protocol === "chat_completions" ? "/chat/completions" : "/messages");
1351
+ const adapter = protocolAdapter({
1352
+ session,
1353
+ protocol,
1354
+ model: bindingSource(binding),
1355
+ signal,
1356
+ save: async (response, responseContext) => {
1357
+ if (scope && typeof response.id === "string")
1358
+ 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
+ }
1360
+ });
1361
+ return { requiredUpstreamId, adapter, ...protocol !== "responses" ? { canonicalInput: logicalInput, diagnostics } : {} };
1362
+ } };
1269
1363
  });
1270
1364
  hooks.onBeforeRequest.tap("codex-router.catalog-validator", (context) => {
1271
1365
  if (context.method === "GET" && /\/models$/.test(context.originalUrl.pathname)) {
@@ -1296,4 +1390,4 @@ export {
1296
1390
  server_default as default
1297
1391
  };
1298
1392
 
1299
- //# debugId=B0DF8A3FDB79AE4D64756E2164756E21
1393
+ //# debugId=15F3624284EDF84064756E2164756E21