omnigateway 0.7.1 → 0.7.2

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 (48) hide show
  1. package/README.md +6 -4
  2. package/bin/omni.js +79 -30
  3. package/gateway.js +782 -64
  4. package/package.json +1 -1
  5. package/public/assets/{Chip-BWxO0uV7.js → Chip-BOyBT5TP.js} +1 -1
  6. package/public/assets/{CopyValue-DIR5A6PG.js → CopyValue-DRHHQlN_.js} +3 -3
  7. package/public/assets/{Field-DI5YTYOX.js → Field-DK5zaBVA.js} +1 -1
  8. package/public/assets/Lamp-ZlMzNs5N.js +25 -0
  9. package/public/assets/{Panel-BCpZVY4U.js → Panel-CYQvfI3L.js} +19 -19
  10. package/public/assets/Rack-D798XvPQ.js +466 -0
  11. package/public/assets/{Readout-B0TZE8aA.js → Readout-D6-aurU8.js} +1 -1
  12. package/public/assets/{RequestTable-D4z82uxG.js → RequestTable-CEBhwDs7.js} +2 -2
  13. package/public/assets/{SummaryDeck-CzozuXOu.js → SummaryDeck-DBCSHihY.js} +2 -2
  14. package/public/assets/{Toggle-ByxBCMfb.js → Toggle-CdCCoDEo.js} +1 -1
  15. package/public/assets/{TokenBreakdown-BMEiZhRX.js → TokenBreakdown-DDI9uTPW.js} +1 -1
  16. package/public/assets/{WindowChart-nxC4SCRC.js → WindowChart-C-Y6U3WF.js} +2 -2
  17. package/public/assets/_app-BWNEo1e-.js +1 -0
  18. package/public/assets/_app.accounts-CLLLwN77.js +59 -0
  19. package/public/assets/{_app.console-D6lrTxJt.js → _app.console-Dr9qxU7J.js} +3 -3
  20. package/public/assets/{_app.database-Y3lFDxoP.js → _app.database-D0W0pcxC.js} +4 -4
  21. package/public/assets/{_app.index-DUFa7RRT.js → _app.index-CyxnfhVX.js} +8 -8
  22. package/public/assets/{_app.keys-DRfXCzMJ.js → _app.keys-D9qmw9Tj.js} +11 -11
  23. package/public/assets/{_app.logs-BQT3kFZr.js → _app.logs-DtXUZETW.js} +4 -4
  24. package/public/assets/{_app.models-CDpbIYHW.js → _app.models-CNxwXyFl.js} +11 -11
  25. package/public/assets/{_app.plugins._pluginId-jaswB8Z5.js → _app.plugins._pluginId-87Ox_hkW.js} +1 -1
  26. package/public/assets/_app.plugins._pluginId-CZWipH1n.js +2 -0
  27. package/public/assets/_app.settings-DjiMSl1Y.js +88 -0
  28. package/public/assets/{_app.usage-BaT54Vee.js → _app.usage-CZz9raYR.js} +6 -6
  29. package/public/assets/{chevron-right-0adI8395.js → chevron-right-CPoaXYHw.js} +1 -1
  30. package/public/assets/client-CZnyYbay.js +39 -0
  31. package/public/assets/{index-BRrBGt1i.js → index-DNSPtYpM.js} +3 -3
  32. package/public/assets/{login-BSWCo_Fz.js → login-BtlMmyKj.js} +3 -3
  33. package/public/assets/login-dV42ZQIA.js +2 -0
  34. package/public/assets/plus-_zo43Lvf.js +1 -0
  35. package/public/assets/{preload-helper-CD37DT-E.js → preload-helper-4wSmu2-E.js} +1 -1
  36. package/public/assets/{shared-dShKzjig.js → shared-OJcoRCqT.js} +1 -1
  37. package/public/assets/{stream-BD4FhzLn.js → stream-CEb81tzM.js} +1 -1
  38. package/public/assets/{trash-2-DrDlpCqO.js → trash-2-BjpqTubo.js} +1 -1
  39. package/public/index.html +8 -8
  40. package/public/assets/Lamp-DN2EKL4m.js +0 -25
  41. package/public/assets/Rack-B03tpeW-.js +0 -466
  42. package/public/assets/_app-D9B6OIjd.js +0 -1
  43. package/public/assets/_app.accounts-BiRGhH3s.js +0 -59
  44. package/public/assets/_app.plugins._pluginId-CtEAGvad.js +0 -2
  45. package/public/assets/_app.settings-CG63splg.js +0 -58
  46. package/public/assets/client-_6YMm6vh.js +0 -39
  47. package/public/assets/login-C7v-Fr28.js +0 -2
  48. package/public/assets/plus-B_f8M9yB.js +0 -1
package/gateway.js CHANGED
@@ -6879,6 +6879,10 @@ class GatewayError extends Error {
6879
6879
  }
6880
6880
  // packages/ir/src/logger.ts
6881
6881
  var LEVELS = { debug: 10, info: 20, warn: 30, error: 40 };
6882
+ function safeToken(value) {
6883
+ const text = typeof value === "string" ? value : String(value);
6884
+ return /^[A-Za-z0-9_.:/+-]{1,64}$/.test(text) ? text : "(unprintable)";
6885
+ }
6882
6886
  var FIELD_ORDER = [
6883
6887
  "requestId",
6884
6888
  "surface",
@@ -6916,6 +6920,12 @@ var FIELD_ORDER = [
6916
6920
  "reason"
6917
6921
  ];
6918
6922
  var REASON_MAX = 200;
6923
+ var MODEL_MAX = 120;
6924
+ var CAPS = {
6925
+ reason: REASON_MAX,
6926
+ model: MODEL_MAX,
6927
+ requestedModel: MODEL_MAX
6928
+ };
6919
6929
  var LEVEL_COLOR = {
6920
6930
  debug: "\x1B[2;37m",
6921
6931
  info: "\x1B[36m",
@@ -6941,7 +6951,8 @@ function formatLine(level, at, msg, fields, color) {
6941
6951
  const value = fields[key];
6942
6952
  if (value === undefined)
6943
6953
  continue;
6944
- const capped = key === "reason" && typeof value === "string" && value.length > REASON_MAX ? `${value.slice(0, REASON_MAX)}\u2026` : value;
6954
+ const cap = CAPS[key];
6955
+ const capped = cap !== undefined && typeof value === "string" && value.length > cap ? `${value.slice(0, cap)}\u2026` : value;
6945
6956
  parts.push(`${key}=${renderValue(capped)}`);
6946
6957
  }
6947
6958
  return parts.length === 0 ? head : `${head} ${parts.join(" ")}`;
@@ -26110,10 +26121,10 @@ function toCustomResponsesWire(req, model) {
26110
26121
  note("custom:context-1m-dropped");
26111
26122
  for (const message of req.messages) {
26112
26123
  const parts = [];
26113
- const inlined = message.role === "system";
26114
- if (inlined)
26115
- note("custom:system-turn-inlined");
26116
- const role = inlined ? "user" : message.role;
26124
+ const asDeveloper = message.role === "system";
26125
+ if (asDeveloper)
26126
+ note("custom:system-turn-as-developer");
26127
+ const role = asDeveloper ? "developer" : message.role;
26117
26128
  const flush = () => {
26118
26129
  if (parts.length === 0)
26119
26130
  return;
@@ -26125,9 +26136,7 @@ function toCustomResponsesWire(req, model) {
26125
26136
  case "text":
26126
26137
  parts.push({
26127
26138
  type: role === "assistant" ? "output_text" : "input_text",
26128
- text: inlined ? `<system-reminder>
26129
- ${block.text}
26130
- </system-reminder>` : block.text
26139
+ text: block.text
26131
26140
  });
26132
26141
  break;
26133
26142
  case "image":
@@ -26205,7 +26214,7 @@ function metadata(data, fail) {
26205
26214
  function endpointUrl(origin, basePath, protocol) {
26206
26215
  const suffix = protocol === "chat_completions" ? "chat/completions" : "responses";
26207
26216
  const base = `${origin}${basePath}`.replace(/\/+$/, "");
26208
- return base.endsWith("/v1") ? `${base}/${suffix}` : `${base}/v1/${suffix}`;
26217
+ return /\/v\d+$/i.test(base) ? `${base}/${suffix}` : `${base}/v1/${suffix}`;
26209
26218
  }
26210
26219
  function protocolOf(state, fail) {
26211
26220
  if (state !== null && typeof state === "object") {
@@ -26474,10 +26483,10 @@ function toGrokWire(req, model) {
26474
26483
  note("grok:context-1m-dropped");
26475
26484
  for (const message of req.messages) {
26476
26485
  const parts = [];
26477
- const inlined = message.role === "system";
26478
- if (inlined)
26479
- note("grok:system-turn-inlined");
26480
- const role = inlined ? "user" : message.role;
26486
+ const asDeveloper = message.role === "system";
26487
+ if (asDeveloper)
26488
+ note("grok:system-turn-as-developer");
26489
+ const role = asDeveloper ? "developer" : message.role;
26481
26490
  const flush = () => {
26482
26491
  if (parts.length === 0)
26483
26492
  return;
@@ -26489,9 +26498,7 @@ function toGrokWire(req, model) {
26489
26498
  case "text":
26490
26499
  parts.push({
26491
26500
  type: role === "assistant" ? "output_text" : "input_text",
26492
- text: inlined ? `<system-reminder>
26493
- ${block.text}
26494
- </system-reminder>` : block.text
26501
+ text: block.text
26495
26502
  });
26496
26503
  break;
26497
26504
  case "image":
@@ -27283,6 +27290,7 @@ var ERROR_CODE2 = {
27283
27290
  content_policy_violation: "CONTENT_FILTER"
27284
27291
  };
27285
27292
  var KNOWN_EVENTS3 = new Set([
27293
+ "keepalive",
27286
27294
  "response.created",
27287
27295
  "response.queued",
27288
27296
  "response.in_progress",
@@ -27316,7 +27324,8 @@ function json7(data) {
27316
27324
  return null;
27317
27325
  }
27318
27326
  }
27319
- async function* decodeResponses(messages) {
27327
+ async function* decodeResponses(messages, options = {}) {
27328
+ const nativeReasoning = options.nativeReasoning === true;
27320
27329
  const indices = new Map;
27321
27330
  let next = 0;
27322
27331
  const irIndex = (outputIndex, contentIndex = 0) => {
@@ -27361,7 +27370,7 @@ async function* decodeResponses(messages) {
27361
27370
  yield {
27362
27371
  type: "blockStart",
27363
27372
  index: irIndex(d.output_index ?? 0),
27364
- block: { type: "thinking" }
27373
+ block: nativeReasoning ? { type: "providerNative", provider: "openai", blockType: "reasoning", data: {} } : { type: "thinking" }
27365
27374
  };
27366
27375
  } else if (item.type === "function_call") {
27367
27376
  sawToolCall = true;
@@ -27394,7 +27403,12 @@ async function* decodeResponses(messages) {
27394
27403
  yield {
27395
27404
  type: "blockDelta",
27396
27405
  index: irIndex(d.output_index ?? 0),
27397
- delta: { type: "thinking", text: String(d.delta ?? "") }
27406
+ delta: nativeReasoning ? {
27407
+ type: "providerNative",
27408
+ provider: "openai",
27409
+ deltaType: "reasoning_summary_text.delta",
27410
+ data: { text: String(d.delta ?? "") }
27411
+ } : { type: "thinking", text: String(d.delta ?? "") }
27398
27412
  };
27399
27413
  break;
27400
27414
  case "response.function_call_arguments.delta":
@@ -27410,6 +27424,20 @@ async function* decodeResponses(messages) {
27410
27424
  case "response.output_item.done": {
27411
27425
  const outputIndex = d.output_index ?? 0;
27412
27426
  if (ownsBlock.delete(outputIndex)) {
27427
+ const item = d.item ?? {};
27428
+ if (nativeReasoning && item.type === "reasoning") {
27429
+ yield {
27430
+ type: "blockDelta",
27431
+ index: irIndex(outputIndex),
27432
+ delta: {
27433
+ type: "providerNative",
27434
+ provider: "openai",
27435
+ deltaType: "response.output_item.done",
27436
+ fold: "merge",
27437
+ data: item
27438
+ }
27439
+ };
27440
+ }
27413
27441
  yield { type: "blockEnd", index: irIndex(outputIndex) };
27414
27442
  }
27415
27443
  break;
@@ -27483,6 +27511,23 @@ function cacheKey(req, instructions, firstInput) {
27483
27511
  const stable = req.conversationId !== undefined && req.conversationId.length > 0 ? JSON.stringify({ conversation: req.conversationId }) : JSON.stringify({ instructions, firstInput: firstInput ?? null });
27484
27512
  return createHash3("sha256").update(stable).digest("hex").slice(0, 32);
27485
27513
  }
27514
+ function repairOrphanedCalls(input) {
27515
+ const answered = new Set;
27516
+ for (const item of input) {
27517
+ const record2 = item;
27518
+ if (record2.type === "function_call_output" && typeof record2.call_id === "string") {
27519
+ answered.add(record2.call_id);
27520
+ }
27521
+ }
27522
+ for (let i = input.length - 1;i >= 0; i--) {
27523
+ const record2 = input[i];
27524
+ if (record2.type !== "function_call" || typeof record2.call_id !== "string")
27525
+ continue;
27526
+ if (answered.has(record2.call_id))
27527
+ continue;
27528
+ input.splice(i + 1, 0, { type: "function_call_output", call_id: record2.call_id, output: "" });
27529
+ }
27530
+ }
27486
27531
  function encodeToolChoice5(c) {
27487
27532
  switch (c.type) {
27488
27533
  case "auto":
@@ -27506,10 +27551,10 @@ function toResponsesWire(req, model, opts = { oauth: false }) {
27506
27551
  note("openai:context-1m-dropped");
27507
27552
  for (const message of req.messages) {
27508
27553
  const parts = [];
27509
- const inlined = message.role === "system";
27510
- if (inlined)
27511
- note("openai:system-turn-inlined");
27512
- const role = inlined ? "user" : message.role;
27554
+ const asDeveloper = message.role === "system";
27555
+ if (asDeveloper)
27556
+ note("openai:system-turn-as-developer");
27557
+ const role = asDeveloper ? "developer" : message.role;
27513
27558
  const flush = () => {
27514
27559
  if (parts.length === 0)
27515
27560
  return;
@@ -27521,9 +27566,7 @@ function toResponsesWire(req, model, opts = { oauth: false }) {
27521
27566
  case "text":
27522
27567
  parts.push({
27523
27568
  type: role === "assistant" ? "output_text" : "input_text",
27524
- text: inlined ? `<system-reminder>
27525
- ${block.text}
27526
- </system-reminder>` : block.text
27569
+ text: block.text
27527
27570
  });
27528
27571
  break;
27529
27572
  case "image":
@@ -27555,12 +27598,19 @@ ${block.text}
27555
27598
  });
27556
27599
  break;
27557
27600
  case "providerNative":
27601
+ if (block.provider === "openai") {
27602
+ flush();
27603
+ const { id: _id, ...rest } = block.data;
27604
+ input.push({ type: block.blockType, ...rest });
27605
+ break;
27606
+ }
27558
27607
  note("openai:anthropic-native-block-dropped");
27559
27608
  break;
27560
27609
  }
27561
27610
  }
27562
27611
  flush();
27563
27612
  }
27613
+ repairOrphanedCalls(input);
27564
27614
  const body = { model, input, stream: req.stream, store: false };
27565
27615
  const instructions = systemText(req.system, "openai", note);
27566
27616
  if (instructions !== undefined && instructions.length > 0)
@@ -27624,7 +27674,10 @@ var openaiCodec = {
27624
27674
  throw input.fail("AUTH", "openai credential has no token");
27625
27675
  }
27626
27676
  const headers = orderHeaders(mergeHeaders(openaiProfile.headers, protocol), openaiProfile.order);
27677
+ const include = body.include;
27678
+ const nativeReasoning = Array.isArray(include) && include.includes("reasoning.encrypted_content");
27627
27679
  return {
27680
+ decodeState: { nativeReasoning },
27628
27681
  request: {
27629
27682
  url: oauth ? OAUTH_URL2 : API_URL3,
27630
27683
  method: "POST",
@@ -27634,8 +27687,9 @@ var openaiCodec = {
27634
27687
  degradations
27635
27688
  };
27636
27689
  },
27637
- decode({ body }) {
27638
- return decodeResponses(parseSse(body));
27690
+ decode({ body, decodeState }) {
27691
+ const state = decodeState;
27692
+ return decodeResponses(parseSse(body), { nativeReasoning: state?.nativeReasoning === true });
27639
27693
  }
27640
27694
  };
27641
27695
 
@@ -27819,8 +27873,10 @@ function parseOrThrow(schema, body2) {
27819
27873
  if (result.success)
27820
27874
  return result.data;
27821
27875
  const issue2 = result.error.issues[0];
27822
- const path = issue2?.path.join(".") ?? "(root)";
27823
- throw new GatewayError("BAD_REQUEST", `${path}: ${issue2?.message ?? "invalid request"}`);
27876
+ const segments = issue2?.path ?? [];
27877
+ const path = segments.length === 0 ? "(root)" : segments.map((s) => safeToken(String(s))).join(".");
27878
+ const detail = issue2 === undefined ? "invalid request" : issue2.code === "unrecognized_keys" ? `unrecognized key "${safeToken(issue2.keys[0])}"` : issue2.message;
27879
+ throw new GatewayError("BAD_REQUEST", `${path}: ${detail}`);
27824
27880
  }
27825
27881
  function optionalNumber(value, fallback) {
27826
27882
  if (value === undefined)
@@ -28326,13 +28382,13 @@ function resolveModel(name, snapshot, providers = PROVIDER_DESCRIPTORS) {
28326
28382
  if (descriptor2 !== undefined && prefix !== "custom" && rest.length > 0) {
28327
28383
  return synthesize(prefix, rest, descriptor2);
28328
28384
  }
28329
- throw new GatewayError("NO_CANDIDATES", `unknown provider "${prefix}" in model "${name}"`);
28385
+ throw new GatewayError("NO_CANDIDATES", `unknown provider "${safeToken(prefix)}" in model "${safeToken(name)}"`);
28330
28386
  }
28331
28387
  for (const [prefix, provider, descriptor2] of prefixProviders(providers)) {
28332
28388
  if (name.startsWith(prefix))
28333
28389
  return synthesize(provider, name, descriptor2);
28334
28390
  }
28335
- throw new GatewayError("NO_CANDIDATES", `model "${name}" is not a configured virtual model and its provider could not be inferred`);
28391
+ throw new GatewayError("NO_CANDIDATES", `model "${safeToken(name)}" is not a configured virtual model and its provider could not be inferred`);
28336
28392
  }
28337
28393
 
28338
28394
  // packages/router/src/index.ts
@@ -45483,6 +45539,367 @@ function openaiRateLimitHeaders(headroom, now) {
45483
45539
  return headers;
45484
45540
  }
45485
45541
 
45542
+ // apps/gateway/src/egress/responses.ts
45543
+ var STATUS = {
45544
+ endTurn: { status: "completed" },
45545
+ toolUse: { status: "completed" },
45546
+ stopSequence: { status: "completed" },
45547
+ pauseTurn: { status: "completed" },
45548
+ maxTokens: { status: "incomplete", reason: "max_output_tokens" },
45549
+ contentFilter: { status: "incomplete", reason: "content_filter" }
45550
+ };
45551
+ function usageBody2(usage) {
45552
+ const input = promptTokens(usage);
45553
+ return {
45554
+ input_tokens: input,
45555
+ input_tokens_details: { cached_tokens: usage.cacheReadTokens },
45556
+ output_tokens: usage.outputTokens,
45557
+ output_tokens_details: { reasoning_tokens: 0 },
45558
+ total_tokens: input + usage.outputTokens
45559
+ };
45560
+ }
45561
+ var CONTENT_INDEX = 0;
45562
+ function customToolInput(raw) {
45563
+ try {
45564
+ const parsed2 = JSON.parse(raw);
45565
+ if (typeof parsed2 === "object" && parsed2 !== null && "input" in parsed2) {
45566
+ const inner = parsed2.input;
45567
+ if (typeof inner === "string")
45568
+ return inner;
45569
+ }
45570
+ } catch {}
45571
+ return raw;
45572
+ }
45573
+ function renderItem(item, status2) {
45574
+ const done = status2 === "completed";
45575
+ switch (item.kind) {
45576
+ case "message":
45577
+ return {
45578
+ id: item.id,
45579
+ type: "message",
45580
+ status: status2,
45581
+ role: "assistant",
45582
+ content: done ? [{ type: "output_text", text: item.text, annotations: [] }] : []
45583
+ };
45584
+ case "reasoning":
45585
+ return {
45586
+ id: item.id,
45587
+ type: "reasoning",
45588
+ status: status2,
45589
+ summary: done && item.text !== "" ? [{ type: "summary_text", text: item.text }] : []
45590
+ };
45591
+ case "function_call":
45592
+ return {
45593
+ id: item.id,
45594
+ type: "function_call",
45595
+ status: status2,
45596
+ call_id: item.callId,
45597
+ name: item.toolName,
45598
+ arguments: done ? item.text : ""
45599
+ };
45600
+ case "custom_tool_call":
45601
+ return {
45602
+ id: item.id,
45603
+ type: "custom_tool_call",
45604
+ status: status2,
45605
+ call_id: item.callId,
45606
+ name: item.toolName,
45607
+ input: done ? customToolInput(item.text) : ""
45608
+ };
45609
+ case "native":
45610
+ return item.native;
45611
+ }
45612
+ }
45613
+ async function* responsesStream(events, render) {
45614
+ let model = "";
45615
+ let sequence = 0;
45616
+ let terminated = false;
45617
+ const frame2 = (event, data) => ({
45618
+ event,
45619
+ data: JSON.stringify({ type: event, sequence_number: ++sequence, ...data })
45620
+ });
45621
+ const output = [];
45622
+ const snapshot = (status2, extra) => ({
45623
+ id: `resp_${render.requestId}`,
45624
+ object: "response",
45625
+ created_at: render.created,
45626
+ status: status2,
45627
+ model,
45628
+ output,
45629
+ ...extra
45630
+ });
45631
+ let nextOutputIndex = 0;
45632
+ const state = { open: null };
45633
+ const ID_PREFIX = {
45634
+ message: "msg",
45635
+ reasoning: "rs",
45636
+ function_call: "fc",
45637
+ custom_tool_call: "ctc",
45638
+ native: "item"
45639
+ };
45640
+ const open = (irIndex, kind, seed) => {
45641
+ const outputIndex = nextOutputIndex++;
45642
+ const id = seed?.callId !== undefined && seed.callId !== "" ? `${ID_PREFIX[kind]}_${seed.callId}` : `${ID_PREFIX[kind]}_${render.requestId}_${outputIndex}`;
45643
+ state.open = {
45644
+ irIndex,
45645
+ outputIndex,
45646
+ id,
45647
+ kind,
45648
+ text: "",
45649
+ toolName: "",
45650
+ callId: "",
45651
+ native: {},
45652
+ ...seed
45653
+ };
45654
+ return state.open;
45655
+ };
45656
+ const itemBody = (item, status2) => renderItem(item, status2);
45657
+ function* closeCurrent() {
45658
+ const item = state.open;
45659
+ if (item === null)
45660
+ return;
45661
+ state.open = null;
45662
+ const at = { item_id: item.id, output_index: item.outputIndex, content_index: CONTENT_INDEX };
45663
+ switch (item.kind) {
45664
+ case "message":
45665
+ yield frame2("response.output_text.done", { ...at, text: item.text });
45666
+ yield frame2("response.content_part.done", {
45667
+ ...at,
45668
+ part: { type: "output_text", text: item.text, annotations: [] }
45669
+ });
45670
+ break;
45671
+ case "reasoning":
45672
+ yield frame2("response.reasoning_summary_text.done", {
45673
+ item_id: item.id,
45674
+ output_index: item.outputIndex,
45675
+ summary_index: CONTENT_INDEX,
45676
+ text: item.text
45677
+ });
45678
+ yield frame2("response.reasoning_summary_part.done", {
45679
+ item_id: item.id,
45680
+ output_index: item.outputIndex,
45681
+ summary_index: CONTENT_INDEX,
45682
+ part: { type: "summary_text", text: item.text }
45683
+ });
45684
+ break;
45685
+ case "function_call":
45686
+ yield frame2("response.function_call_arguments.done", {
45687
+ item_id: item.id,
45688
+ output_index: item.outputIndex,
45689
+ arguments: item.text
45690
+ });
45691
+ break;
45692
+ case "custom_tool_call": {
45693
+ const input = customToolInput(item.text);
45694
+ yield frame2("response.custom_tool_call_input.delta", {
45695
+ item_id: item.id,
45696
+ output_index: item.outputIndex,
45697
+ delta: input
45698
+ });
45699
+ yield frame2("response.custom_tool_call_input.done", {
45700
+ item_id: item.id,
45701
+ output_index: item.outputIndex,
45702
+ input
45703
+ });
45704
+ break;
45705
+ }
45706
+ case "native":
45707
+ break;
45708
+ }
45709
+ const body2 = itemBody(item, "completed");
45710
+ output.push(body2);
45711
+ yield frame2("response.output_item.done", { output_index: item.outputIndex, item: body2 });
45712
+ }
45713
+ function* closeChecked(irIndex) {
45714
+ if (state.open === null || state.open.irIndex !== irIndex)
45715
+ return;
45716
+ yield* closeCurrent();
45717
+ }
45718
+ for await (const event of events) {
45719
+ switch (event.type) {
45720
+ case "start":
45721
+ model = event.model;
45722
+ yield frame2("response.created", { response: snapshot("in_progress") });
45723
+ yield frame2("response.in_progress", { response: snapshot("in_progress") });
45724
+ break;
45725
+ case "blockStart": {
45726
+ if (state.open !== null && state.open.irIndex === event.index)
45727
+ break;
45728
+ yield* closeCurrent();
45729
+ const block = event.block;
45730
+ const kind = block.type === "text" ? "message" : block.type === "thinking" ? "reasoning" : block.type === "toolUse" ? render.customToolNames.has(block.name) ? "custom_tool_call" : "function_call" : "native";
45731
+ const item = open(event.index, kind, block.type === "toolUse" ? { callId: block.id, toolName: block.name } : block.type === "providerNative" ? { native: { type: block.blockType, ...block.data } } : {});
45732
+ yield frame2("response.output_item.added", {
45733
+ output_index: item.outputIndex,
45734
+ item: itemBody(item, "in_progress")
45735
+ });
45736
+ if (kind === "message") {
45737
+ yield frame2("response.content_part.added", {
45738
+ item_id: item.id,
45739
+ output_index: item.outputIndex,
45740
+ content_index: CONTENT_INDEX,
45741
+ part: { type: "output_text", text: "", annotations: [] }
45742
+ });
45743
+ }
45744
+ if (kind === "reasoning") {
45745
+ yield frame2("response.reasoning_summary_part.added", {
45746
+ item_id: item.id,
45747
+ output_index: item.outputIndex,
45748
+ summary_index: CONTENT_INDEX,
45749
+ part: { type: "summary_text", text: "" }
45750
+ });
45751
+ }
45752
+ break;
45753
+ }
45754
+ case "blockDelta": {
45755
+ const item = state.open;
45756
+ if (item === null || item.irIndex !== event.index)
45757
+ break;
45758
+ const delta2 = event.delta;
45759
+ if (delta2.type === "text" && item.kind === "message") {
45760
+ item.text += delta2.text;
45761
+ yield frame2("response.output_text.delta", {
45762
+ item_id: item.id,
45763
+ output_index: item.outputIndex,
45764
+ content_index: CONTENT_INDEX,
45765
+ delta: delta2.text
45766
+ });
45767
+ }
45768
+ if (delta2.type === "thinking" && item.kind === "reasoning") {
45769
+ item.text += delta2.text;
45770
+ yield frame2("response.reasoning_summary_text.delta", {
45771
+ item_id: item.id,
45772
+ output_index: item.outputIndex,
45773
+ summary_index: CONTENT_INDEX,
45774
+ delta: delta2.text
45775
+ });
45776
+ }
45777
+ if (delta2.type === "toolJson") {
45778
+ item.text += delta2.partial;
45779
+ if (item.kind === "function_call") {
45780
+ yield frame2("response.function_call_arguments.delta", {
45781
+ item_id: item.id,
45782
+ output_index: item.outputIndex,
45783
+ delta: delta2.partial
45784
+ });
45785
+ }
45786
+ }
45787
+ if (delta2.type === "providerNative" && item.kind === "native") {
45788
+ if (delta2.deltaType === "reasoning_summary_text.delta") {
45789
+ yield frame2("response.reasoning_summary_text.delta", {
45790
+ item_id: item.id,
45791
+ output_index: item.outputIndex,
45792
+ summary_index: CONTENT_INDEX,
45793
+ delta: String(delta2.data.text ?? "")
45794
+ });
45795
+ }
45796
+ if (delta2.fold === "merge") {
45797
+ item.native = { ...item.native, ...delta2.data };
45798
+ }
45799
+ }
45800
+ break;
45801
+ }
45802
+ case "blockEnd":
45803
+ yield* closeChecked(event.index);
45804
+ break;
45805
+ case "end": {
45806
+ yield* closeCurrent();
45807
+ const { status: status2, reason } = STATUS[event.stopReason];
45808
+ terminated = true;
45809
+ yield frame2(status2 === "completed" ? "response.completed" : "response.incomplete", {
45810
+ response: snapshot(status2, {
45811
+ ...reason === undefined ? {} : { incomplete_details: { reason } },
45812
+ usage: usageBody2(event.usage)
45813
+ })
45814
+ });
45815
+ break;
45816
+ }
45817
+ case "error":
45818
+ yield* closeCurrent();
45819
+ terminated = true;
45820
+ yield frame2("response.failed", {
45821
+ response: snapshot("failed", {
45822
+ error: { code: ERROR_TYPE3[event.code].code, message: event.message }
45823
+ })
45824
+ });
45825
+ break;
45826
+ }
45827
+ }
45828
+ if (!terminated) {
45829
+ yield* closeCurrent();
45830
+ yield frame2("response.failed", {
45831
+ response: snapshot("failed", {
45832
+ error: { code: "stream_disconnected", message: "stream closed before response.completed" }
45833
+ })
45834
+ });
45835
+ }
45836
+ yield { event: "message", data: "[DONE]" };
45837
+ }
45838
+ function responsesResponse(collected, render) {
45839
+ const output = [];
45840
+ let index = 0;
45841
+ for (const block of collected.content) {
45842
+ const outputIndex = index++;
45843
+ const at = { irIndex: outputIndex, outputIndex, toolName: "", callId: "", native: {} };
45844
+ if (block.type === "text") {
45845
+ output.push(renderItem({
45846
+ ...at,
45847
+ kind: "message",
45848
+ id: `msg_${render.requestId}_${outputIndex}`,
45849
+ text: block.text
45850
+ }, "completed"));
45851
+ }
45852
+ if (block.type === "thinking") {
45853
+ output.push(renderItem({
45854
+ ...at,
45855
+ kind: "reasoning",
45856
+ id: `rs_${render.requestId}_${outputIndex}`,
45857
+ text: block.text
45858
+ }, "completed"));
45859
+ }
45860
+ if (block.type === "toolUse") {
45861
+ const custom2 = render.customToolNames.has(block.name);
45862
+ const kind = custom2 ? "custom_tool_call" : "function_call";
45863
+ output.push(renderItem({
45864
+ ...at,
45865
+ kind,
45866
+ id: `${custom2 ? "ctc" : "fc"}_${block.id}`,
45867
+ text: JSON.stringify(block.input),
45868
+ toolName: block.name,
45869
+ callId: block.id
45870
+ }, "completed"));
45871
+ }
45872
+ if (block.type === "providerNative" && block.provider === "openai") {
45873
+ output.push(renderItem({
45874
+ ...at,
45875
+ kind: "native",
45876
+ id: `item_${render.requestId}_${outputIndex}`,
45877
+ text: "",
45878
+ native: { type: block.blockType, ...block.data }
45879
+ }, "completed"));
45880
+ }
45881
+ }
45882
+ const { status: status2, reason } = STATUS[collected.stopReason];
45883
+ return {
45884
+ id: `resp_${render.requestId}`,
45885
+ object: "response",
45886
+ created_at: render.created,
45887
+ status: status2,
45888
+ model: collected.model,
45889
+ output,
45890
+ store: false,
45891
+ ...reason === undefined ? {} : { incomplete_details: { reason } },
45892
+ usage: usageBody2(collected.usage)
45893
+ };
45894
+ }
45895
+ function responsesErrorBody(code, message) {
45896
+ const { type, code: errorCode } = ERROR_TYPE3[code];
45897
+ return { error: { type, code: errorCode, message, param: null } };
45898
+ }
45899
+ function responsesRateLimitHeaders(headroom, now) {
45900
+ return openaiRateLimitHeaders(headroom, now);
45901
+ }
45902
+
45486
45903
  // apps/gateway/src/ingress/schemas.ts
45487
45904
  var cacheControlSchema = exports_external.object({
45488
45905
  type: exports_external.literal("ephemeral"),
@@ -45511,8 +45928,19 @@ function parseOrThrow2(schema, body2) {
45511
45928
  if (result.success)
45512
45929
  return result.data;
45513
45930
  const issue2 = result.error.issues[0];
45514
- const path = issue2?.path.join(".") ?? "(root)";
45515
- throw new GatewayError("BAD_REQUEST", `${path}: ${issue2?.message ?? "invalid request"}`);
45931
+ throw new GatewayError("BAD_REQUEST", `${issuePath(issue2)}: ${zodDetail(issue2)}`);
45932
+ }
45933
+ function issuePath(issue2) {
45934
+ const segments = issue2?.path ?? [];
45935
+ return segments.length === 0 ? "(root)" : segments.map((s) => safeToken(String(s))).join(".");
45936
+ }
45937
+ function zodDetail(issue2) {
45938
+ if (issue2 === undefined)
45939
+ return "invalid request";
45940
+ if (issue2.code === "unrecognized_keys") {
45941
+ return `unrecognized key "${safeToken(issue2.keys[0])}"`;
45942
+ }
45943
+ return issue2.message;
45516
45944
  }
45517
45945
  function isRecord7(value) {
45518
45946
  return typeof value === "object" && value !== null;
@@ -45528,7 +45956,8 @@ function extraFields(body2, known) {
45528
45956
  var CONVERSATION_HEADERS = [
45529
45957
  "x-session-id",
45530
45958
  "x-session-affinity",
45531
- "x-deepseek-harness-session-id"
45959
+ "x-deepseek-harness-session-id",
45960
+ "session-id"
45532
45961
  ];
45533
45962
  function readConversationHeader(headers) {
45534
45963
  for (const name of CONVERSATION_HEADERS) {
@@ -45573,7 +46002,7 @@ function readSidecarImage(raw, declaredMediaType) {
45573
46002
  };
45574
46003
  }
45575
46004
  if (!mediaType.startsWith("image/")) {
45576
- return { ok: false, reason: "not-an-image", detail: `${mediaType} is not an image` };
46005
+ return { ok: false, reason: "not-an-image", detail: `${safeToken(mediaType)} is not an image` };
45577
46006
  }
45578
46007
  return { ok: true, mediaType, data: resolved.data };
45579
46008
  }
@@ -48866,7 +49295,7 @@ async function dispatch(request2, deps, signal, requestId) {
48866
49295
  }
48867
49296
  if (candidates.length === 0) {
48868
49297
  clearDeadline();
48869
- return fail("NO_CANDIDATES", `no eligible credential for model "${request2.model}"`);
49298
+ return fail("NO_CANDIDATES", `no eligible credential for model "${safeToken(request2.model)}"`);
48870
49299
  }
48871
49300
  const maxAttempts = Math.min(snapshot.settings.maxAttempts, candidates.length);
48872
49301
  const head = candidates[0];
@@ -48990,7 +49419,9 @@ async function dispatch(request2, deps, signal, requestId) {
48990
49419
  if (event.type === "error") {
48991
49420
  terminal = true;
48992
49421
  if (!committed && RETRYABLE[event.code]) {
48993
- throw new GatewayError(event.code, event.message);
49422
+ throw new GatewayError(event.code, event.message, {
49423
+ provider: candidate.target.provider
49424
+ });
48994
49425
  }
48995
49426
  committed = true;
48996
49427
  log.status = HTTP_STATUS[event.code];
@@ -49266,18 +49697,18 @@ function fail(path, message) {
49266
49697
  }
49267
49698
  function field(path, name, value) {
49268
49699
  const schema = TOOL_FIELDS[name];
49269
- if (schema === undefined)
49270
- fail(`${path}.${name}`, `unsupported field "${name}"`);
49271
- const parsed2 = schema.safeParse(value);
49272
- if (!parsed2.success) {
49273
- fail(`${path}.${name}`, parsed2.error.issues[0]?.message ?? "invalid value");
49700
+ if (schema === undefined) {
49701
+ fail(`${path}.${safeToken(name)}`, `unsupported field "${safeToken(name)}"`);
49274
49702
  }
49703
+ const parsed2 = schema.safeParse(value);
49704
+ if (!parsed2.success)
49705
+ fail(`${path}.${safeToken(name)}`, zodDetail(parsed2.error.issues[0]));
49275
49706
  return parsed2.data;
49276
49707
  }
49277
49708
  function parseAnthropicTool(raw, type, path, mcpServerNames) {
49278
49709
  const spec = anthropicToolSpec(type);
49279
49710
  if (spec === undefined)
49280
- fail(`${path}.type`, `unrecognized tool type "${type}"`);
49711
+ fail(`${path}.type`, `unrecognized tool type "${safeToken(type)}"`);
49281
49712
  if (spec.name !== undefined && raw.name !== spec.name) {
49282
49713
  fail(`${path}.name`, `${type} must be declared with name "${spec.name}"`);
49283
49714
  }
@@ -49294,8 +49725,9 @@ function parseAnthropicTool(raw, type, path, mcpServerNames) {
49294
49725
  for (const [key, value] of Object.entries(raw)) {
49295
49726
  if (key === "type" || key === "name")
49296
49727
  continue;
49297
- if (!allowed.has(key))
49298
- fail(`${path}.${key}`, `${type} does not accept "${key}"`);
49728
+ if (!allowed.has(key)) {
49729
+ fail(`${path}.${safeToken(key)}`, `${type} does not accept "${safeToken(key)}"`);
49730
+ }
49299
49731
  const parsed2 = field(path, key, value);
49300
49732
  if (key === "cache_control") {
49301
49733
  cacheControl = irCacheControl(parsed2 === null ? undefined : parsed2).cacheControl;
@@ -49310,7 +49742,7 @@ function parseAnthropicTool(raw, type, path, mcpServerNames) {
49310
49742
  if (spec.family === "mcpToolset") {
49311
49743
  const server = wire.mcp_server_name;
49312
49744
  if (typeof server === "string" && !mcpServerNames.has(server)) {
49313
- fail(`${path}.mcp_server_name`, `no mcp_servers entry named "${server}"`);
49745
+ fail(`${path}.mcp_server_name`, `no mcp_servers entry named "${safeToken(server)}"`);
49314
49746
  }
49315
49747
  }
49316
49748
  return {
@@ -49334,7 +49766,7 @@ function parseCustomTool(raw, path) {
49334
49766
  if (["type", "name", "description", "input_schema", "cache_control"].includes(key))
49335
49767
  continue;
49336
49768
  if (!ANTHROPIC_CUSTOM_TOOL_OPTIONS.includes(key)) {
49337
- fail(`${path}.${key}`, `unsupported field "${key}"`);
49769
+ fail(`${path}.${safeToken(key)}`, `unsupported field "${safeToken(key)}"`);
49338
49770
  }
49339
49771
  const value_ = field(path, key, value);
49340
49772
  if (value_ !== null)
@@ -49381,6 +49813,7 @@ function mcpServerNames(body2) {
49381
49813
  }
49382
49814
 
49383
49815
  // apps/gateway/src/ingress/model.ts
49816
+ var MODEL_NAME_MAX = 200;
49384
49817
  var ONE_M_SUFFIX2 = "[1m]";
49385
49818
  function normalizeClientModel(raw, betas2 = []) {
49386
49819
  let model = raw.trim();
@@ -49577,7 +50010,7 @@ var message = exports_external.object({
49577
50010
  content: exports_external.union([exports_external.string(), exports_external.array(exports_external.unknown())])
49578
50011
  });
49579
50012
  var schema = exports_external.object({
49580
- model: exports_external.string().min(1),
50013
+ model: exports_external.string().min(1).max(MODEL_NAME_MAX),
49581
50014
  messages: exports_external.array(message).min(1),
49582
50015
  system: exports_external.union([exports_external.string(), exports_external.array(textBlock)]).optional(),
49583
50016
  max_tokens: exports_external.number().int().positive().optional(),
@@ -49701,9 +50134,10 @@ function readBlock(raw, role, path) {
49701
50134
  const parsed3 = nativeSchema.safeParse(raw);
49702
50135
  if (!parsed3.success) {
49703
50136
  const issue2 = parsed3.error.issues[0];
49704
- const issuePath = issue2?.code === "unrecognized_keys" ? [...issue2.path, issue2.keys[0]] : issue2?.path;
49705
- const suffix = issuePath?.length ? `.${issuePath.join(".")}` : "";
49706
- throw new GatewayError("BAD_REQUEST", `${path}${suffix}: ${issue2?.message ?? "invalid native content block"}`);
50137
+ const unknownKey = issue2?.code === "unrecognized_keys" ? safeToken(issue2.keys[0]) : null;
50138
+ const issuePath2 = unknownKey === null ? issue2?.path : [...issue2?.path ?? [], unknownKey];
50139
+ const suffix = issuePath2?.length ? `.${issuePath2.join(".")}` : "";
50140
+ throw new GatewayError("BAD_REQUEST", `${path}${suffix}: ${zodDetail(issue2)}`);
49707
50141
  }
49708
50142
  const { type: _type, cache_control, ...data } = parsed3.data;
49709
50143
  return {
@@ -49721,11 +50155,11 @@ function readBlock(raw, role, path) {
49721
50155
  if (issue2?.code === "invalid_union" || issue2?.path.at(-1) === "type") {
49722
50156
  const type = raw?.type;
49723
50157
  if (typeof type === "string") {
49724
- throw new GatewayError("BAD_REQUEST", `${path}.type: unrecognized block type "${type}"`);
50158
+ throw new GatewayError("BAD_REQUEST", `${path}.type: unrecognized block type "${safeToken(type)}"`);
49725
50159
  }
49726
50160
  }
49727
50161
  const suffix = issue2?.path.length ? `.${issue2.path.join(".")}` : "";
49728
- throw new GatewayError("BAD_REQUEST", `${path}${suffix}: ${issue2?.message ?? "invalid content block"}`);
50162
+ throw new GatewayError("BAD_REQUEST", `${path}${suffix}: ${zodDetail(issue2)}`);
49729
50163
  }
49730
50164
  return toIrBlock(parsed2.data);
49731
50165
  }
@@ -49872,7 +50306,7 @@ function sidecarImages(m) {
49872
50306
  return blocks2;
49873
50307
  }
49874
50308
  var schema2 = exports_external.object({
49875
- model: exports_external.string().min(1),
50309
+ model: exports_external.string().min(1).max(MODEL_NAME_MAX),
49876
50310
  messages: exports_external.array(message2).min(1),
49877
50311
  max_tokens: exports_external.number().int().positive().optional(),
49878
50312
  max_completion_tokens: exports_external.number().int().positive().optional(),
@@ -50031,6 +50465,265 @@ function parseOpenAIRequest(body2, headers) {
50031
50465
  return validateRequest(request2);
50032
50466
  }
50033
50467
 
50468
+ // apps/gateway/src/ingress/responses.ts
50469
+ import { createHash as createHash4 } from "crypto";
50470
+ var reasoning = exports_external.object({
50471
+ effort: exports_external.enum(REASONING_EFFORTS).optional(),
50472
+ summary: exports_external.string().optional()
50473
+ });
50474
+ var schema3 = exports_external.object({
50475
+ model: exports_external.string().min(1).max(MODEL_NAME_MAX),
50476
+ input: exports_external.union([exports_external.string(), exports_external.array(exports_external.unknown())]),
50477
+ tools: exports_external.array(exports_external.unknown()).optional(),
50478
+ instructions: exports_external.string().optional(),
50479
+ max_output_tokens: exports_external.number().int().positive().optional(),
50480
+ temperature: exports_external.number().optional(),
50481
+ stream: exports_external.boolean().optional(),
50482
+ reasoning: reasoning.optional(),
50483
+ tool_choice: exports_external.union([
50484
+ exports_external.enum(["auto", "none", "required"]),
50485
+ exports_external.object({ type: exports_external.enum(["function", "custom"]), name: exports_external.string() })
50486
+ ]).optional(),
50487
+ previous_response_id: exports_external.string().nullish(),
50488
+ store: exports_external.boolean().nullish(),
50489
+ background: exports_external.boolean().nullish(),
50490
+ prompt_cache_key: exports_external.string().nullish()
50491
+ });
50492
+ var KNOWN3 = [
50493
+ "model",
50494
+ "input",
50495
+ "instructions",
50496
+ "tools",
50497
+ "tool_choice",
50498
+ "stream",
50499
+ "store",
50500
+ "reasoning",
50501
+ "background",
50502
+ "previous_response_id",
50503
+ "max_output_tokens",
50504
+ "temperature",
50505
+ "metadata",
50506
+ "user"
50507
+ ];
50508
+ function refuseStatefulFields(parsed2) {
50509
+ if (typeof parsed2.previous_response_id === "string" && parsed2.previous_response_id.length > 0) {
50510
+ throw new GatewayError("BAD_REQUEST", "previous_response_id: this gateway stores no responses, so prior state cannot be resumed");
50511
+ }
50512
+ if (parsed2.store === true) {
50513
+ throw new GatewayError("BAD_REQUEST", "store: this gateway stores no responses; send store: false or omit it");
50514
+ }
50515
+ }
50516
+ function readCacheKey(raw) {
50517
+ if (typeof raw !== "string")
50518
+ return;
50519
+ const trimmed = raw.trim();
50520
+ return trimmed.length > 0 && trimmed.length <= 512 ? trimmed : undefined;
50521
+ }
50522
+ function toIrToolChoice3(c) {
50523
+ if (typeof c === "string")
50524
+ return c === "required" ? { type: "any" } : { type: c };
50525
+ return { type: "tool", name: c.name };
50526
+ }
50527
+ function toIrReasoning2(r) {
50528
+ return {
50529
+ mode: "adaptive",
50530
+ ...r.effort === undefined ? {} : { effort: r.effort },
50531
+ ...r.summary === "none" ? { display: "omitted" } : {}
50532
+ };
50533
+ }
50534
+ function clampCallId(raw) {
50535
+ return raw.length <= 64 ? raw : createHash4("sha256").update(raw).digest("hex");
50536
+ }
50537
+ function roleOf(raw) {
50538
+ if (raw === "assistant")
50539
+ return "assistant";
50540
+ if (raw === "system" || raw === "developer")
50541
+ return "system";
50542
+ return "user";
50543
+ }
50544
+ function contentPart(part2) {
50545
+ if (!isRecord7(part2))
50546
+ throw new GatewayError("BAD_REQUEST", "input: content part must be an object");
50547
+ const type = part2.type;
50548
+ if (type === "input_text" || type === "output_text") {
50549
+ return { type: "text", text: String(part2.text ?? "") };
50550
+ }
50551
+ if (type === "input_image") {
50552
+ const url2 = typeof part2.image_url === "string" ? part2.image_url : "";
50553
+ if (!url2.startsWith("data:"))
50554
+ return null;
50555
+ const { mediaType, data } = parseDataUrl(url2);
50556
+ return { type: "image", mediaType, data };
50557
+ }
50558
+ throw new GatewayError("BAD_REQUEST", `input: unsupported content part type "${safeToken(type)}"`);
50559
+ }
50560
+ function messageBlocks(content) {
50561
+ if (typeof content === "string")
50562
+ return [{ type: "text", text: content }];
50563
+ if (!Array.isArray(content))
50564
+ return [];
50565
+ const blocks2 = [];
50566
+ for (const part2 of content) {
50567
+ const block2 = contentPart(part2);
50568
+ if (block2 !== null)
50569
+ blocks2.push(block2);
50570
+ }
50571
+ return blocks2;
50572
+ }
50573
+ function nativeBlock(item, blockType) {
50574
+ const { type: _type, ...data } = item;
50575
+ return { type: "providerNative", provider: "openai", blockType, data };
50576
+ }
50577
+ function readInputItems(items) {
50578
+ const dropped = new Set;
50579
+ const messages = [];
50580
+ const push = (role, content) => {
50581
+ if (content.length > 0)
50582
+ messages.push({ role, content });
50583
+ };
50584
+ for (const raw of items) {
50585
+ if (!isRecord7(raw))
50586
+ throw new GatewayError("BAD_REQUEST", "input: item must be an object");
50587
+ const type = raw.type ?? (raw.role === undefined ? undefined : "message");
50588
+ switch (type) {
50589
+ case "message":
50590
+ push(roleOf(raw.role), messageBlocks(raw.content));
50591
+ break;
50592
+ case "function_call":
50593
+ case "custom_tool_call": {
50594
+ const name = typeof raw.name === "string" ? raw.name : "";
50595
+ const callId = typeof raw.call_id === "string" ? raw.call_id : "";
50596
+ if (name === "" || callId === "") {
50597
+ if (callId !== "")
50598
+ dropped.add(callId);
50599
+ else
50600
+ dropped.add("");
50601
+ break;
50602
+ }
50603
+ const input = type === "custom_tool_call" ? { input: typeof raw.input === "string" ? raw.input : "" } : jsonArguments(raw.arguments, clampCallId(callId));
50604
+ push("assistant", [{ type: "toolUse", id: clampCallId(callId), name, input }]);
50605
+ break;
50606
+ }
50607
+ case "function_call_output":
50608
+ case "custom_tool_call_output": {
50609
+ const callId = typeof raw.call_id === "string" ? raw.call_id : "";
50610
+ if (dropped.has(callId))
50611
+ break;
50612
+ push("user", [
50613
+ {
50614
+ type: "toolResult",
50615
+ toolUseId: clampCallId(callId),
50616
+ content: typeof raw.output === "string" ? raw.output : JSON.stringify(raw.output ?? ""),
50617
+ isError: false
50618
+ }
50619
+ ]);
50620
+ break;
50621
+ }
50622
+ case "reasoning":
50623
+ case "local_shell_call":
50624
+ push("assistant", [nativeBlock(raw, String(type))]);
50625
+ break;
50626
+ case "local_shell_call_output":
50627
+ push("user", [nativeBlock(raw, "local_shell_call_output")]);
50628
+ break;
50629
+ case "item_reference":
50630
+ throw new GatewayError("BAD_REQUEST", "input: item_reference names a stored item, and this gateway stores no responses");
50631
+ default:
50632
+ throw new GatewayError("BAD_REQUEST", `input: unsupported item type "${safeToken(type)}"`);
50633
+ }
50634
+ }
50635
+ return messages;
50636
+ }
50637
+ function jsonArguments(raw, callId) {
50638
+ const text = typeof raw === "string" ? raw : "";
50639
+ try {
50640
+ const parsed2 = text === "" ? {} : JSON.parse(text);
50641
+ return isRecord7(parsed2) ? parsed2 : { value: parsed2 };
50642
+ } catch {
50643
+ throw new GatewayError("BAD_REQUEST", `input: arguments for call ${safeToken(callId)} are not valid JSON`);
50644
+ }
50645
+ }
50646
+ var TOOL_NAME = /^[A-Za-z0-9_-]{1,128}$/;
50647
+ function readTools(raw) {
50648
+ const tools2 = [];
50649
+ for (const entry of raw) {
50650
+ if (!isRecord7(entry))
50651
+ throw new GatewayError("BAD_REQUEST", "tools: each tool must be an object");
50652
+ const type = typeof entry.type === "string" ? entry.type : "";
50653
+ const declared = typeof entry.name === "string" ? entry.name : "";
50654
+ if (type === "function" || type === "custom") {
50655
+ if (!TOOL_NAME.test(declared)) {
50656
+ throw new GatewayError("BAD_REQUEST", `tools: a tool name must match ${TOOL_NAME.source}`);
50657
+ }
50658
+ const description = typeof entry.description === "string" ? entry.description : undefined;
50659
+ tools2.push({
50660
+ kind: "portable",
50661
+ name: declared,
50662
+ ...description === undefined ? {} : { description },
50663
+ inputSchema: type === "custom" ? { type: "object", properties: { input: { type: "string" } }, required: ["input"] } : isRecord7(entry.parameters) ? entry.parameters : { type: "object" }
50664
+ });
50665
+ continue;
50666
+ }
50667
+ const name = declared === "" ? type : declared;
50668
+ if (!TOOL_NAME.test(name)) {
50669
+ throw new GatewayError("BAD_REQUEST", `tools: a tool name must match ${TOOL_NAME.source}`);
50670
+ }
50671
+ const { type: _type, name: _name, ...wire } = entry;
50672
+ tools2.push({ kind: "provider", provider: "openai", type, name, wire });
50673
+ }
50674
+ return tools2;
50675
+ }
50676
+ function customToolNames(body2) {
50677
+ const names = new Set;
50678
+ if (!isRecord7(body2) || !Array.isArray(body2.tools))
50679
+ return names;
50680
+ for (const entry of body2.tools) {
50681
+ if (isRecord7(entry) && entry.type === "custom" && typeof entry.name === "string") {
50682
+ names.add(entry.name);
50683
+ }
50684
+ }
50685
+ return names;
50686
+ }
50687
+ function parseResponsesRequest(body2, headers) {
50688
+ if (typeof body2 !== "object" || body2 === null) {
50689
+ throw new GatewayError("BAD_REQUEST", "request body must be a JSON object");
50690
+ }
50691
+ const parsed2 = parseOrThrow2(schema3, body2);
50692
+ refuseStatefulFields(parsed2);
50693
+ const messages = typeof parsed2.input === "string" ? [{ role: "user", content: [{ type: "text", text: parsed2.input }] }] : readInputItems(parsed2.input);
50694
+ if (messages.length === 0) {
50695
+ throw new GatewayError("BAD_REQUEST", "input: at least one input item is required");
50696
+ }
50697
+ const named = normalizeClientModel(parsed2.model);
50698
+ const request2 = {
50699
+ model: named.model,
50700
+ messages,
50701
+ stream: parsed2.stream ?? false
50702
+ };
50703
+ if (parsed2.instructions !== undefined && parsed2.instructions.length > 0) {
50704
+ request2.system = [{ type: "text", text: parsed2.instructions }];
50705
+ }
50706
+ if (parsed2.max_output_tokens !== undefined)
50707
+ request2.maxTokens = parsed2.max_output_tokens;
50708
+ if (parsed2.temperature !== undefined)
50709
+ request2.temperature = parsed2.temperature;
50710
+ if (parsed2.tools !== undefined && parsed2.tools.length > 0)
50711
+ request2.tools = readTools(parsed2.tools);
50712
+ if (parsed2.tool_choice !== undefined)
50713
+ request2.toolChoice = toIrToolChoice3(parsed2.tool_choice);
50714
+ if (parsed2.reasoning !== undefined)
50715
+ request2.reasoning = toIrReasoning2(parsed2.reasoning);
50716
+ if (named.betas.length > 0)
50717
+ request2.betas = named.betas;
50718
+ const conversation = readCacheKey(parsed2.prompt_cache_key) ?? readConversationHeader(headers);
50719
+ if (conversation !== undefined)
50720
+ request2.conversationId = conversation;
50721
+ const extras = extraFields(body2, KNOWN3);
50722
+ if (extras !== undefined)
50723
+ request2.vendor = { openai: extras };
50724
+ return validateRequest(request2);
50725
+ }
50726
+
50034
50727
  // apps/gateway/src/routes/models.ts
50035
50728
  var CREATED_AT = new Date(0).toISOString();
50036
50729
  function describeModel(model, credentials) {
@@ -50060,6 +50753,10 @@ function modelListBody(models, credentials) {
50060
50753
 
50061
50754
  // apps/gateway/src/routes/proxy.ts
50062
50755
  var KEEPALIVE_MS = 1e4;
50756
+ var RESPONSES_KEEPALIVE_MS = 4000;
50757
+ function keepaliveFor(surface, configured2) {
50758
+ return surface === "responses" ? Math.min(configured2, RESPONSES_KEEPALIVE_MS) : configured2;
50759
+ }
50063
50760
  var KEEPALIVE = Symbol("keepalive");
50064
50761
  function withKeepalive(pending, ms) {
50065
50762
  let timer;
@@ -50075,10 +50772,18 @@ var SSE_HEADERS = {
50075
50772
  "x-accel-buffering": "no"
50076
50773
  };
50077
50774
  function errorBody(surface, code, message3) {
50078
- return surface === "anthropic" ? anthropicErrorBody(code, message3) : openaiErrorBody(code, message3);
50775
+ if (surface === "anthropic")
50776
+ return anthropicErrorBody(code, message3);
50777
+ if (surface === "responses")
50778
+ return responsesErrorBody(code, message3);
50779
+ return openaiErrorBody(code, message3);
50079
50780
  }
50080
50781
  function rateLimitHeaders(surface, headroom, now) {
50081
- return surface === "anthropic" ? anthropicRateLimitHeaders(headroom) : openaiRateLimitHeaders(headroom, now);
50782
+ if (surface === "anthropic")
50783
+ return anthropicRateLimitHeaders(headroom);
50784
+ if (surface === "responses")
50785
+ return responsesRateLimitHeaders(headroom, now);
50786
+ return openaiRateLimitHeaders(headroom, now);
50082
50787
  }
50083
50788
  function afterThisRequest(headroom) {
50084
50789
  const requests = headroom.requests;
@@ -50237,9 +50942,14 @@ async function handle(deps, rateLimiter, surface, request2) {
50237
50942
  const body2 = await request2.json();
50238
50943
  if (captured !== null)
50239
50944
  captured.client.request = body2;
50240
- const chatRequest = surface === "anthropic" ? parseAnthropicRequest(body2, request2.headers) : parseOpenAIRequest(body2, request2.headers);
50945
+ const chatRequest = surface === "anthropic" ? parseAnthropicRequest(body2, request2.headers) : surface === "responses" ? parseResponsesRequest(body2, request2.headers) : parseOpenAIRequest(body2, request2.headers);
50946
+ const render2 = () => ({
50947
+ requestId,
50948
+ created: Math.floor(deps.now() / 1000),
50949
+ customToolNames: customToolNames(body2)
50950
+ });
50241
50951
  if (key.modelAllowlist !== null && !key.modelAllowlist.includes(chatRequest.model)) {
50242
- throw new GatewayError("AUTH", `model "${chatRequest.model}" is not allowed for this API key`);
50952
+ throw new GatewayError("AUTH", `model "${safeToken(chatRequest.model)}" is not allowed for this API key`);
50243
50953
  }
50244
50954
  requestedModel = chatRequest.model;
50245
50955
  let began = false;
@@ -50286,7 +50996,7 @@ async function handle(deps, rateLimiter, surface, request2) {
50286
50996
  await finishLog(deps.store, completed, keyId, deps.logger, writeBodies, debit, deps.emit, deps.broadcaster);
50287
50997
  };
50288
50998
  if (chatRequest.stream) {
50289
- const frames = surface === "anthropic" ? anthropicStream(dispatched.events, requestId) : openaiStream(dispatched.events, requestId, Math.floor(deps.now() / 1000));
50999
+ const frames = surface === "anthropic" ? anthropicStream(dispatched.events, requestId) : surface === "responses" ? responsesStream(dispatched.events, render2()) : openaiStream(dispatched.events, requestId, Math.floor(deps.now() / 1000));
50290
51000
  let onFrame;
50291
51001
  if (captured !== null) {
50292
51002
  const sink = createFrameSink();
@@ -50298,7 +51008,7 @@ async function handle(deps, rateLimiter, surface, request2) {
50298
51008
  release?.();
50299
51009
  await log(cancelled, failure2);
50300
51010
  };
50301
- const response = sseResponse(frames, finish, deps.keepaliveMs, dispatched.events, limitHeaders(), onFrame);
51011
+ const response = sseResponse(frames, finish, keepaliveFor(surface, deps.keepaliveMs), dispatched.events, limitHeaders(), onFrame);
50302
51012
  streaming = true;
50303
51013
  return response;
50304
51014
  }
@@ -50306,7 +51016,7 @@ async function handle(deps, rateLimiter, surface, request2) {
50306
51016
  for await (const event of dispatched.events)
50307
51017
  events.push(event);
50308
51018
  const failure = events.find((e) => e.type === "error");
50309
- const responseBody = failure !== undefined ? errorBody(surface, failure.code, failure.message) : surface === "anthropic" ? anthropicResponse(collect(events), requestId) : openaiResponse(collect(events), requestId, Math.floor(deps.now() / 1000));
51019
+ const responseBody = failure !== undefined ? errorBody(surface, failure.code, failure.message) : surface === "anthropic" ? anthropicResponse(collect(events), requestId) : surface === "responses" ? responsesResponse(collect(events), render2()) : openaiResponse(collect(events), requestId, Math.floor(deps.now() / 1000));
50310
51020
  if (captured !== null)
50311
51021
  captured.client.response = responseBody;
50312
51022
  await log();
@@ -50349,6 +51059,9 @@ function proxyRoutes(deps) {
50349
51059
  return new Elysia().post("/v1/messages", ({ request: request2, server }) => {
50350
51060
  server?.timeout(request2, 0);
50351
51061
  return handle(dispatchDeps, rateLimiter, "anthropic", request2);
51062
+ }).post("/v1/responses", ({ request: request2, server }) => {
51063
+ server?.timeout(request2, 0);
51064
+ return handle(dispatchDeps, rateLimiter, "responses", request2);
50352
51065
  }).post("/v1/chat/completions", ({ request: request2, server }) => {
50353
51066
  server?.timeout(request2, 0);
50354
51067
  return handle(dispatchDeps, rateLimiter, "openai", request2);
@@ -50375,7 +51088,7 @@ function proxyRoutes(deps) {
50375
51088
  const body2 = await request2.json();
50376
51089
  const chatRequest = parseAnthropicRequest(body2, request2.headers);
50377
51090
  if (key.modelAllowlist !== null && !key.modelAllowlist.includes(chatRequest.model)) {
50378
- throw new GatewayError("AUTH", `model "${chatRequest.model}" is not allowed for this API key`);
51091
+ throw new GatewayError("AUTH", `model "${safeToken(chatRequest.model)}" is not allowed for this API key`);
50379
51092
  }
50380
51093
  const { settings } = await dispatchDeps.snapshots.get(deps.now());
50381
51094
  const counted = injectPonytail(chatRequest, { mode: settings.ponytailMode }).request;
@@ -51109,8 +51822,13 @@ function createRing(limits) {
51109
51822
  // apps/gateway/src/app.ts
51110
51823
  var ADMIN_SESSION_TTL_MS = 12 * 60 * 60 * 1000;
51111
51824
  var QUIESCE_MESSAGE = "the gateway is briefly quiesced for database maintenance";
51825
+ var QUIESCE_BODY = {
51826
+ "/v1/chat/completions": (m) => openaiErrorBody("OVERLOADED", m),
51827
+ "/v1/responses": (m) => responsesErrorBody("OVERLOADED", m)
51828
+ };
51112
51829
  function quiesceResponse(path) {
51113
- const body2 = path === "/v1/chat/completions" ? openaiErrorBody("OVERLOADED", QUIESCE_MESSAGE) : anthropicErrorBody("OVERLOADED", QUIESCE_MESSAGE);
51830
+ const render2 = QUIESCE_BODY[path];
51831
+ const body2 = render2 === undefined ? anthropicErrorBody("OVERLOADED", QUIESCE_MESSAGE) : render2(QUIESCE_MESSAGE);
51114
51832
  return new Response(JSON.stringify(body2), {
51115
51833
  status: HTTP_STATUS.OVERLOADED,
51116
51834
  headers: { "content-type": "application/json", "retry-after": "5" }