omnigateway 0.12.6 → 0.12.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/bin/omni.js +411 -37
  2. package/gateway.js +424 -50
  3. package/package.json +1 -1
package/gateway.js CHANGED
@@ -31532,7 +31532,7 @@ var museBodyOrder = [
31532
31532
  ];
31533
31533
 
31534
31534
  // packages/providers/src/openai/profile.ts
31535
- var OPENAI_CLI_VERSION = env("OMNI_OPENAI_CLI_VERSION", "0.144.1");
31535
+ var OPENAI_CLI_VERSION = env("OMNI_OPENAI_CLI_VERSION", "0.155.1");
31536
31536
  var OPENAI_UA_PLATFORM = env("OMNI_OPENAI_UA_PLATFORM", "Windows 10.0.26200");
31537
31537
  var OPENAI_UA_ARCH = env("OMNI_OPENAI_UA_ARCH", "x64");
31538
31538
  var openaiProfile = {
@@ -32331,6 +32331,265 @@ async function* decodeAnthropic(messages, opts = {}) {
32331
32331
  }
32332
32332
  }
32333
32333
 
32334
+ // packages/providers/src/responseFormat.ts
32335
+ var isRecord = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
32336
+ function readResponseFormatResult(req) {
32337
+ const openai = req.vendor?.openai;
32338
+ const chat = openai?.response_format;
32339
+ if (chat !== undefined) {
32340
+ if (!isRecord(chat) || chat.type !== "json_schema")
32341
+ return { kind: "malformed" };
32342
+ return fromSpec(chat.json_schema);
32343
+ }
32344
+ const responses = openai?.text;
32345
+ if (isRecord(responses) && responses.format !== undefined)
32346
+ return fromSpec(responses.format);
32347
+ if (responses !== undefined)
32348
+ return { kind: "malformed" };
32349
+ const messages = req.vendor?.anthropic?.output_config;
32350
+ if (isRecord(messages) && messages.format !== undefined)
32351
+ return fromSpec(messages.format);
32352
+ if (messages !== undefined)
32353
+ return { kind: "malformed" };
32354
+ return { kind: "absent" };
32355
+ }
32356
+ function readableFormat(spec) {
32357
+ return isRecord(spec) && (spec.type === undefined || spec.type === "json_schema") && isRecord(spec.schema);
32358
+ }
32359
+ function canSerialize(value) {
32360
+ if (typeof value === "bigint")
32361
+ return false;
32362
+ if (typeof value !== "object" || value === null)
32363
+ return true;
32364
+ const seen = new WeakSet;
32365
+ const stack = [value];
32366
+ while (stack.length > 0) {
32367
+ const node2 = stack.pop();
32368
+ if (node2 === undefined)
32369
+ break;
32370
+ if (seen.has(node2))
32371
+ continue;
32372
+ seen.add(node2);
32373
+ if (typeof node2.toJSON === "function") {
32374
+ try {
32375
+ const res = node2.toJSON();
32376
+ if (typeof res === "bigint")
32377
+ return false;
32378
+ } catch {
32379
+ return false;
32380
+ }
32381
+ }
32382
+ const values3 = Array.isArray(node2) ? node2 : Object.values(node2);
32383
+ for (const val of values3) {
32384
+ if (typeof val === "bigint")
32385
+ return false;
32386
+ if (typeof val === "object" && val !== null) {
32387
+ stack.push(val);
32388
+ }
32389
+ }
32390
+ }
32391
+ return true;
32392
+ }
32393
+ function fromSpec(spec) {
32394
+ if (!readableFormat(spec))
32395
+ return { kind: "malformed" };
32396
+ const schema = spec.schema;
32397
+ if (!isRecord(schema))
32398
+ return { kind: "malformed" };
32399
+ if (isCyclic(schema) || tooDeepToSerialize(schema) || !canSerialize(schema)) {
32400
+ return { kind: "tooDeep" };
32401
+ }
32402
+ return {
32403
+ kind: "readable",
32404
+ format: {
32405
+ schema,
32406
+ name: typeof spec.name === "string" && spec.name.length > 0 ? spec.name : "response"
32407
+ }
32408
+ };
32409
+ }
32410
+ function forEachSubschema(nodes, visit2) {
32411
+ for (const node2 of nodes) {
32412
+ for (const [key, value] of Object.entries(node2)) {
32413
+ if (SUBSCHEMA_MAP.includes(key) && isRecord(value)) {
32414
+ for (const member of Object.values(value))
32415
+ if (isRecord(member))
32416
+ visit2(member, node2);
32417
+ } else if (SUBSCHEMA_LIST.includes(key) && Array.isArray(value)) {
32418
+ for (const member of value)
32419
+ if (isRecord(member))
32420
+ visit2(member, node2);
32421
+ } else if (SUBSCHEMA.includes(key) && isRecord(value)) {
32422
+ visit2(value, node2);
32423
+ }
32424
+ }
32425
+ }
32426
+ }
32427
+ function isCyclic(schema) {
32428
+ const onPath = new Set;
32429
+ const done = new WeakSet;
32430
+ const stack = [{ node: schema, entering: true }];
32431
+ while (stack.length > 0) {
32432
+ const frame = stack.pop();
32433
+ if (frame === undefined)
32434
+ break;
32435
+ const node2 = frame.node;
32436
+ if (!frame.entering) {
32437
+ onPath.delete(node2);
32438
+ done.add(node2);
32439
+ continue;
32440
+ }
32441
+ if (onPath.has(node2))
32442
+ return true;
32443
+ if (done.has(node2))
32444
+ continue;
32445
+ onPath.add(node2);
32446
+ stack.push({ node: node2, entering: false });
32447
+ if (Array.isArray(node2)) {
32448
+ for (const item of node2) {
32449
+ if (typeof item === "object" && item !== null) {
32450
+ stack.push({ node: item, entering: true });
32451
+ }
32452
+ }
32453
+ } else {
32454
+ for (const val of Object.values(node2)) {
32455
+ if (typeof val === "object" && val !== null) {
32456
+ stack.push({ node: val, entering: true });
32457
+ }
32458
+ }
32459
+ }
32460
+ }
32461
+ return false;
32462
+ }
32463
+ function tooDeepToSerialize(schema) {
32464
+ let level = [schema];
32465
+ for (let depth = 0;depth < MAX_DEPTH2; depth++) {
32466
+ const next = [];
32467
+ const seenThisLevel = new WeakSet;
32468
+ forEachSubschema(level, (member) => {
32469
+ if (seenThisLevel.has(member))
32470
+ return;
32471
+ seenThisLevel.add(member);
32472
+ next.push(member);
32473
+ });
32474
+ if (next.length === 0)
32475
+ return false;
32476
+ level = next;
32477
+ }
32478
+ return true;
32479
+ }
32480
+ function moveToResponsesText(req, body, provider) {
32481
+ const raw = body.response_format;
32482
+ delete body.response_format;
32483
+ const malformedText = body.text !== undefined && !isRecord(body.text);
32484
+ if (malformedText)
32485
+ delete body.text;
32486
+ const read = readResponseFormatResult(req);
32487
+ const clientText = isRecord(body.text) ? body.text : undefined;
32488
+ const clientFormat = clientText?.format;
32489
+ if (readableFormat(clientFormat) && read.kind === "readable")
32490
+ return;
32491
+ const malformedFormat = clientText !== undefined && clientFormat !== undefined;
32492
+ const text = clientText === undefined ? undefined : { ...clientText };
32493
+ if (text !== undefined)
32494
+ delete text.format;
32495
+ if (malformedFormat)
32496
+ body.text = text;
32497
+ if (read.kind === "readable") {
32498
+ const format = read.format;
32499
+ body.text = {
32500
+ ...text,
32501
+ format: { type: "json_schema", name: format.name, schema: format.schema, strict: true }
32502
+ };
32503
+ return `${provider}:response-format-translated`;
32504
+ }
32505
+ if (isRecord(raw) && raw.type === "json_object") {
32506
+ body.text = { ...text, format: { type: "json_object" } };
32507
+ return `${provider}:response-format-translated`;
32508
+ }
32509
+ if (read.kind === "tooDeep")
32510
+ return `${provider}:response-schema-too-deep`;
32511
+ if (raw !== undefined || malformedText || malformedFormat) {
32512
+ return `${provider}:response-format-dropped`;
32513
+ }
32514
+ return;
32515
+ }
32516
+ function closeObjects(schema, stats) {
32517
+ if (stats !== undefined) {
32518
+ stats.changed = false;
32519
+ stats.truncated = false;
32520
+ }
32521
+ return closeNode(schema, 0, stats ?? { changed: false, truncated: false }, new Map);
32522
+ }
32523
+ var SUBSCHEMA = [
32524
+ "items",
32525
+ "additionalItems",
32526
+ "additionalProperties",
32527
+ "contains",
32528
+ "contentSchema",
32529
+ "if",
32530
+ "then",
32531
+ "else",
32532
+ "not",
32533
+ "propertyNames",
32534
+ "unevaluatedItems",
32535
+ "unevaluatedProperties"
32536
+ ];
32537
+ var SUBSCHEMA_LIST = ["anyOf", "allOf", "oneOf", "prefixItems", "items"];
32538
+ var SUBSCHEMA_MAP = [
32539
+ "properties",
32540
+ "patternProperties",
32541
+ "$defs",
32542
+ "definitions",
32543
+ "dependentSchemas",
32544
+ "dependencies"
32545
+ ];
32546
+ var MAX_DEPTH2 = 64;
32547
+ function closeNode(schema, depth, stats, memo2) {
32548
+ if (depth >= MAX_DEPTH2) {
32549
+ stats.truncated = true;
32550
+ return schema;
32551
+ }
32552
+ let atDepth = memo2.get(depth);
32553
+ if (atDepth === undefined) {
32554
+ atDepth = new WeakMap;
32555
+ memo2.set(depth, atDepth);
32556
+ }
32557
+ const done = atDepth.get(schema);
32558
+ if (done !== undefined)
32559
+ return done;
32560
+ const out = {};
32561
+ atDepth.set(schema, out);
32562
+ for (const [key, value] of Object.entries(schema)) {
32563
+ if (SUBSCHEMA_MAP.includes(key) && isRecord(value)) {
32564
+ const members2 = {};
32565
+ for (const [name, member] of Object.entries(value)) {
32566
+ Object.defineProperty(members2, name, {
32567
+ value: isRecord(member) ? closeNode(member, depth + 1, stats, memo2) : member,
32568
+ writable: true,
32569
+ enumerable: true,
32570
+ configurable: true
32571
+ });
32572
+ }
32573
+ out[key] = members2;
32574
+ continue;
32575
+ }
32576
+ if (SUBSCHEMA.includes(key) && isRecord(value)) {
32577
+ out[key] = closeNode(value, depth + 1, stats, memo2);
32578
+ continue;
32579
+ }
32580
+ if (SUBSCHEMA_LIST.includes(key) && Array.isArray(value)) {
32581
+ out[key] = value.map((arm) => isRecord(arm) ? closeNode(arm, depth + 1, stats, memo2) : arm);
32582
+ continue;
32583
+ }
32584
+ out[key] = value;
32585
+ }
32586
+ if (out.type === "object" && out.additionalProperties !== false) {
32587
+ out.additionalProperties = false;
32588
+ stats.changed = true;
32589
+ }
32590
+ return out;
32591
+ }
32592
+
32334
32593
  // packages/providers/src/system.ts
32335
32594
  function systemTextBlocks(system, provider, note) {
32336
32595
  if (system === undefined)
@@ -32453,12 +32712,12 @@ function encodeToolChoice(c, cloak) {
32453
32712
  return { type: "tool", name: cloakName(cloak, c.name) };
32454
32713
  }
32455
32714
  }
32456
- function isRecord(value) {
32715
+ function isRecord2(value) {
32457
32716
  return typeof value === "object" && value !== null && !Array.isArray(value);
32458
32717
  }
32459
32718
  function withoutEffort(vendor, note) {
32460
32719
  const config2 = vendor.output_config;
32461
- if (!isRecord(config2))
32720
+ if (!isRecord2(config2))
32462
32721
  return vendor;
32463
32722
  const entries = Object.entries(config2);
32464
32723
  const kept = entries.filter(([key]) => key !== "effort");
@@ -32472,7 +32731,7 @@ function withoutEffort(vendor, note) {
32472
32731
  }
32473
32732
  var THINKING_ONLY_EDITS = new Set(["clear_thinking_20251015"]);
32474
32733
  function thinkingIsOff(thinking) {
32475
- if (!isRecord(thinking))
32734
+ if (!isRecord2(thinking))
32476
32735
  return thinking !== undefined;
32477
32736
  return thinking.type !== "adaptive" && thinking.type !== "enabled";
32478
32737
  }
@@ -32480,9 +32739,9 @@ function stripUnsupportedEdits(body, note) {
32480
32739
  if (!thinkingIsOff(body.thinking))
32481
32740
  return;
32482
32741
  const config2 = body.context_management;
32483
- if (!isRecord(config2) || !Array.isArray(config2.edits))
32742
+ if (!isRecord2(config2) || !Array.isArray(config2.edits))
32484
32743
  return;
32485
- const kept = config2.edits.filter((e) => !(isRecord(e) && THINKING_ONLY_EDITS.has(String(e.type))));
32744
+ const kept = config2.edits.filter((e) => !(isRecord2(e) && THINKING_ONLY_EDITS.has(String(e.type))));
32486
32745
  if (kept.length === config2.edits.length)
32487
32746
  return;
32488
32747
  note("anthropic:clear-thinking-unsupported");
@@ -32501,11 +32760,11 @@ var CACHEABLE_WIRE_BLOCKS = new Set(["text", "image", "tool_use", "tool_result",
32501
32760
  function lastCacheableHistoryBlock(messages) {
32502
32761
  for (let m = messages.length - 1;m >= 0; m--) {
32503
32762
  const message = messages[m];
32504
- if (!isRecord(message) || !Array.isArray(message.content))
32763
+ if (!isRecord2(message) || !Array.isArray(message.content))
32505
32764
  continue;
32506
32765
  for (let b = message.content.length - 1;b >= 0; b--) {
32507
32766
  const block = message.content[b];
32508
- if (!isRecord(block))
32767
+ if (!isRecord2(block))
32509
32768
  continue;
32510
32769
  if (typeof block.type === "string" && CACHEABLE_WIRE_BLOCKS.has(block.type))
32511
32770
  return block;
@@ -32584,9 +32843,9 @@ function toWire(req, model, opts) {
32584
32843
  };
32585
32844
  if (systemCache.retarget !== undefined) {
32586
32845
  const trailing = body.messages.at(-1);
32587
- if (isRecord(trailing) && Array.isArray(trailing.content)) {
32846
+ if (isRecord2(trailing) && Array.isArray(trailing.content)) {
32588
32847
  for (const block of trailing.content) {
32589
- if (isRecord(block))
32848
+ if (isRecord2(block))
32590
32849
  delete block.cache_control;
32591
32850
  }
32592
32851
  }
@@ -32626,7 +32885,7 @@ function toWire(req, model, opts) {
32626
32885
  };
32627
32886
  if (req.reasoning.effort !== undefined) {
32628
32887
  body.output_config = {
32629
- ...isRecord(body.output_config) ? body.output_config : {},
32888
+ ...isRecord2(body.output_config) ? body.output_config : {},
32630
32889
  effort: req.reasoning.effort
32631
32890
  };
32632
32891
  }
@@ -32639,11 +32898,64 @@ function toWire(req, model, opts) {
32639
32898
  break;
32640
32899
  }
32641
32900
  }
32642
- const vendor = req.vendor?.anthropic ?? {};
32901
+ const native = req.vendor?.anthropic?.output_config;
32902
+ const nativeFormat = isRecord2(native) && readableFormat(native.format);
32903
+ const read = readResponseFormatResult(req);
32904
+ const format = !nativeFormat && read.kind === "readable" ? read.format : undefined;
32905
+ if (format !== undefined) {
32906
+ body.output_config = {
32907
+ ...isRecord2(body.output_config) ? body.output_config : {},
32908
+ format: { type: "json_schema", schema: format.schema }
32909
+ };
32910
+ note("anthropic:response-format-translated");
32911
+ } else if (!nativeFormat && read.kind === "tooDeep") {
32912
+ note("anthropic:response-schema-too-deep");
32913
+ }
32914
+ const vendorRaw = req.vendor?.anthropic ?? {};
32915
+ const vendorConfig = vendorRaw.output_config;
32916
+ const encoderConfig = isRecord2(body.output_config) ? body.output_config : undefined;
32917
+ let unreadableFormat = false;
32918
+ let vendor = vendorRaw;
32919
+ if (encoderConfig !== undefined && vendorConfig !== undefined) {
32920
+ if (!isRecord2(vendorConfig)) {
32921
+ const { output_config: _unreadable, ...rest } = vendorRaw;
32922
+ vendor = rest;
32923
+ unreadableFormat = true;
32924
+ } else {
32925
+ const readable = readableFormat(vendorConfig.format);
32926
+ const { format: _unreadable, ...withoutFormat } = vendorConfig;
32927
+ const rest = readable ? vendorConfig : withoutFormat;
32928
+ vendor = { ...vendorRaw, output_config: { ...encoderConfig, ...rest } };
32929
+ unreadableFormat = !readable && vendorConfig.format !== undefined;
32930
+ }
32931
+ }
32643
32932
  Object.assign(body, anthropicReasoningForm(model) === "budget" ? withoutEffort(vendor, note) : vendor);
32933
+ if (unreadableFormat)
32934
+ note("anthropic:response-format-dropped");
32935
+ closeOutputConfigSchema(body, note);
32644
32936
  stripUnsupportedEdits(body, note);
32645
32937
  return { body, degradations };
32646
32938
  }
32939
+ function closeOutputConfigSchema(body, note) {
32940
+ const config2 = body.output_config;
32941
+ if (!isRecord2(config2))
32942
+ return;
32943
+ const format = config2.format;
32944
+ if (!isRecord2(format) || !isRecord2(format.schema))
32945
+ return;
32946
+ const stats = { changed: false, truncated: false };
32947
+ const closed = closeObjects(format.schema, stats);
32948
+ if (stats.truncated || !canSerialize(closed)) {
32949
+ const { format: _tooDeep, ...rest } = config2;
32950
+ body.output_config = rest;
32951
+ note("anthropic:response-schema-too-deep");
32952
+ return;
32953
+ }
32954
+ if (!stats.changed)
32955
+ return;
32956
+ body.output_config = { ...config2, format: { ...format, schema: closed } };
32957
+ note("anthropic:response-schema-closed");
32958
+ }
32647
32959
 
32648
32960
  // packages/providers/src/anthropic/codec.ts
32649
32961
  var BASE_URL = "https://api.anthropic.com/v1/messages";
@@ -33671,6 +33983,14 @@ function toAntigravityWire(req, model, identity) {
33671
33983
  break;
33672
33984
  }
33673
33985
  }
33986
+ const read = readResponseFormatResult(req);
33987
+ if (read.kind === "readable") {
33988
+ const format = read.format;
33989
+ generationConfig.responseSchema = pruneSchema(format.schema, note);
33990
+ note("antigravity:response-format-translated");
33991
+ } else if (read.kind === "tooDeep") {
33992
+ note("antigravity:response-schema-too-deep");
33993
+ }
33674
33994
  const max = generationConfig.maxOutputTokens;
33675
33995
  if (max !== undefined && max > MAX_OUTPUT_TOKENS) {
33676
33996
  generationConfig.maxOutputTokens = MAX_OUTPUT_TOKENS;
@@ -34170,7 +34490,7 @@ var SCOPES3 = [
34170
34490
  "workspaces:write"
34171
34491
  ].join(" ");
34172
34492
  var TRUSTED_HOST = "x.ai";
34173
- function isRecord2(value) {
34493
+ function isRecord3(value) {
34174
34494
  return typeof value === "object" && value !== null;
34175
34495
  }
34176
34496
  function trustedEndpoint(value, field, fail) {
@@ -34195,7 +34515,7 @@ async function* discover(fail) {
34195
34515
  throw fail("UPSTREAM", `discovery endpoint returned http_${res.status}`);
34196
34516
  }
34197
34517
  const parsed2 = parsed(res.body);
34198
- if (!isRecord2(parsed2)) {
34518
+ if (!isRecord3(parsed2)) {
34199
34519
  throw fail("UPSTREAM", "discovery endpoint returned an unusable response");
34200
34520
  }
34201
34521
  return {
@@ -34204,7 +34524,7 @@ async function* discover(fail) {
34204
34524
  };
34205
34525
  }
34206
34526
  function parseTokenResponse2(value) {
34207
- if (!isRecord2(value) || typeof value.access_token !== "string")
34527
+ if (!isRecord3(value) || typeof value.access_token !== "string")
34208
34528
  return null;
34209
34529
  return {
34210
34530
  accessToken: value.access_token,
@@ -34220,7 +34540,7 @@ function emailFromIdToken(idToken) {
34220
34540
  return null;
34221
34541
  try {
34222
34542
  const json4 = JSON.parse(Buffer.from(payload, "base64url").toString("utf8"));
34223
- if (!isRecord2(json4))
34543
+ if (!isRecord3(json4))
34224
34544
  return null;
34225
34545
  return typeof json4.email === "string" && json4.email.trim().length > 0 ? json4.email : null;
34226
34546
  } catch {
@@ -34306,11 +34626,11 @@ var PROFILE_URL = "https://api.kilo.ai/api/profile";
34306
34626
  var FALLBACK_VERIFICATION_URL = "https://kilo.ai";
34307
34627
  var DEFAULT_EXPIRES_SECONDS = 300;
34308
34628
  var POLL_INTERVAL_SECONDS = 3;
34309
- function isRecord3(value) {
34629
+ function isRecord4(value) {
34310
34630
  return typeof value === "object" && value !== null;
34311
34631
  }
34312
34632
  function recordFrom(value) {
34313
- return isRecord3(value) ? value : null;
34633
+ return isRecord4(value) ? value : null;
34314
34634
  }
34315
34635
  function stringFrom(value, field) {
34316
34636
  const candidate = value[field];
@@ -34462,11 +34782,11 @@ var TOKEN_URL3 = "https://auth.kimi.com/api/oauth/token";
34462
34782
  var USAGE_URL2 = "https://api.kimi.com/coding/v1/usages";
34463
34783
  var DEFAULT_INTERVAL_SECONDS = 5;
34464
34784
  var PENDING_ERRORS = new Set(["authorization_pending", "slow_down"]);
34465
- function isRecord4(value) {
34785
+ function isRecord5(value) {
34466
34786
  return typeof value === "object" && value !== null;
34467
34787
  }
34468
34788
  function recordFrom2(value) {
34469
- return isRecord4(value) ? value : null;
34789
+ return isRecord5(value) ? value : null;
34470
34790
  }
34471
34791
  function stringFrom2(value, field) {
34472
34792
  const candidate = value[field];
@@ -34657,11 +34977,11 @@ var DEVICE_CODE_GRANT = "urn:ietf:params:oauth:grant-type:device_code";
34657
34977
  var FALLBACK_VERIFICATION_URL2 = "https://auth.meta.com/oauth/device/";
34658
34978
  var DEFAULT_INTERVAL_SECONDS2 = 5;
34659
34979
  var PENDING_ERRORS2 = new Set(["authorization_pending", "slow_down"]);
34660
- function isRecord5(value) {
34980
+ function isRecord6(value) {
34661
34981
  return typeof value === "object" && value !== null;
34662
34982
  }
34663
34983
  function recordFrom3(value) {
34664
- return isRecord5(value) ? value : null;
34984
+ return isRecord6(value) ? value : null;
34665
34985
  }
34666
34986
  function stringFrom3(value, field) {
34667
34987
  const candidate = value[field];
@@ -34842,7 +35162,7 @@ var AUTHORIZE_URL3 = "https://auth.openai.com/oauth/authorize";
34842
35162
  var TOKEN_URL5 = "https://auth.openai.com/oauth/token";
34843
35163
  var SCOPES4 = "openid profile email offline_access";
34844
35164
  var USAGE_URL3 = "https://chatgpt.com/backend-api/wham/usage";
34845
- function isRecord6(value) {
35165
+ function isRecord7(value) {
34846
35166
  return typeof value === "object" && value !== null;
34847
35167
  }
34848
35168
  function nonBlankStringOrNull(value) {
@@ -34859,19 +35179,19 @@ function decodeClaims(idToken) {
34859
35179
  }
34860
35180
  try {
34861
35181
  const json4 = JSON.parse(Buffer.from(payload, "base64url").toString("utf8"));
34862
- if (!isRecord6(json4))
35182
+ if (!isRecord7(json4))
34863
35183
  return { email: null, accountId: null };
34864
35184
  const auth = json4["https://api.openai.com/auth"];
34865
35185
  return {
34866
35186
  email: typeof json4.email === "string" ? json4.email : null,
34867
- accountId: isRecord6(auth) ? nonBlankStringOrNull(auth.chatgpt_account_id) : null
35187
+ accountId: isRecord7(auth) ? nonBlankStringOrNull(auth.chatgpt_account_id) : null
34868
35188
  };
34869
35189
  } catch {
34870
35190
  return { email: null, accountId: null };
34871
35191
  }
34872
35192
  }
34873
35193
  function parseTokenResponse3(value) {
34874
- if (!isRecord6(value) || typeof value.access_token !== "string")
35194
+ if (!isRecord7(value) || typeof value.access_token !== "string")
34875
35195
  return null;
34876
35196
  return {
34877
35197
  accessToken: value.access_token,
@@ -35456,6 +35776,24 @@ function toCustomChatWire(req, model) {
35456
35776
  else if (req.reasoning?.mode === "budget")
35457
35777
  note("custom:reasoning-budget-dropped");
35458
35778
  Object.assign(body, req.vendor?.openai ?? {});
35779
+ const droppedText = body.text;
35780
+ delete body.text;
35781
+ const read = readResponseFormatResult(req);
35782
+ const format = read.kind === "readable" ? read.format : undefined;
35783
+ if (format !== undefined) {
35784
+ if (body.response_format === undefined) {
35785
+ body.response_format = {
35786
+ type: "json_schema",
35787
+ json_schema: { name: format.name, schema: format.schema, strict: true }
35788
+ };
35789
+ note("custom:response-format-translated");
35790
+ }
35791
+ } else if (isRecord(droppedText) && droppedText.format !== undefined) {
35792
+ note("custom:response-format-dropped");
35793
+ } else if (read.kind === "tooDeep") {
35794
+ delete body.response_format;
35795
+ note("custom:response-schema-too-deep");
35796
+ }
35459
35797
  return { body, degradations };
35460
35798
  }
35461
35799
  function toCustomResponsesWire(req, model) {
@@ -35547,6 +35885,9 @@ function toCustomResponsesWire(req, model) {
35547
35885
  else if (req.reasoning?.mode === "budget")
35548
35886
  note("custom:reasoning-budget-dropped");
35549
35887
  Object.assign(body, req.vendor?.openai ?? {});
35888
+ const moved = moveToResponsesText(req, body, "custom");
35889
+ if (moved !== undefined)
35890
+ note(moved);
35550
35891
  return { body, degradations };
35551
35892
  }
35552
35893
 
@@ -35921,6 +36262,9 @@ function toGrokWire(req, model) {
35921
36262
  }
35922
36263
  }
35923
36264
  Object.assign(body, req.vendor?.grok ?? {});
36265
+ const moved = moveToResponsesText(req, body, "grok");
36266
+ if (moved !== undefined)
36267
+ note(moved);
35924
36268
  return { body, degradations };
35925
36269
  }
35926
36270
 
@@ -36354,6 +36698,18 @@ function toKiloWire(req, model) {
36354
36698
  }
36355
36699
  }
36356
36700
  Object.assign(body, req.vendor?.kilo ?? {});
36701
+ const read = readResponseFormatResult(req);
36702
+ const format = read.kind === "readable" ? read.format : undefined;
36703
+ if (format !== undefined && body.response_format === undefined) {
36704
+ body.response_format = {
36705
+ type: "json_schema",
36706
+ json_schema: { name: format.name, schema: format.schema, strict: true }
36707
+ };
36708
+ note("kilo:response-format-translated");
36709
+ } else if (read.kind === "tooDeep") {
36710
+ delete body.response_format;
36711
+ note("kilo:response-schema-too-deep");
36712
+ }
36357
36713
  return { body, degradations };
36358
36714
  }
36359
36715
 
@@ -36605,6 +36961,18 @@ function toChatWire(req, model, vendor = "kimi") {
36605
36961
  if (req.reasoning !== undefined)
36606
36962
  note("kimi:reasoning-dropped");
36607
36963
  Object.assign(body, req.vendor?.[vendor] ?? {});
36964
+ const read = readResponseFormatResult(req);
36965
+ const format = read.kind === "readable" ? read.format : undefined;
36966
+ if (format !== undefined && body.response_format === undefined) {
36967
+ body.response_format = {
36968
+ type: "json_schema",
36969
+ json_schema: { name: format.name, schema: format.schema, strict: true }
36970
+ };
36971
+ note("kimi:response-format-translated");
36972
+ } else if (read.kind === "tooDeep") {
36973
+ delete body.response_format;
36974
+ note("kimi:response-schema-too-deep");
36975
+ }
36608
36976
  return { body, degradations };
36609
36977
  }
36610
36978
 
@@ -37001,6 +37369,9 @@ function toMuseWire(req, model) {
37001
37369
  }
37002
37370
  const key = suppliedKey(req) ?? cacheKey(req, instructions ?? "", input2[0]);
37003
37371
  Object.assign(body, req.vendor?.openai ?? {});
37372
+ const moved = moveToResponsesText(req, body, "muse");
37373
+ if (moved !== undefined)
37374
+ note(moved);
37004
37375
  body.prompt_cache_key = key;
37005
37376
  return { body, degradations, cacheKey: key };
37006
37377
  }
@@ -37411,6 +37782,9 @@ function toResponsesWire(req, model, opts = { oauth: false }) {
37411
37782
  }
37412
37783
  const key = suppliedKey2(req) ?? cacheKey2(req, instructions ?? "", input2[0]);
37413
37784
  Object.assign(body, req.vendor?.openai ?? {});
37785
+ const moved = moveToResponsesText(req, body, "openai");
37786
+ if (moved !== undefined)
37787
+ note(moved);
37414
37788
  body.prompt_cache_key = key;
37415
37789
  return { body, degradations, cacheKey: key };
37416
37790
  }
@@ -39790,7 +40164,7 @@ function createRefresher(deps) {
39790
40164
  };
39791
40165
  }
39792
40166
  // packages/control/src/pluginProviders.ts
39793
- function isRecord7(value) {
40167
+ function isRecord8(value) {
39794
40168
  return typeof value === "object" && value !== null && !Array.isArray(value);
39795
40169
  }
39796
40170
  function isNumber(value) {
@@ -39801,7 +40175,7 @@ function checkAt(ok, id, path, expected) {
39801
40175
  throw new Error(`provider ${id} descriptor: ${path} must be ${expected}`);
39802
40176
  }
39803
40177
  function checkLimits(id, path, value) {
39804
- checkAt(isRecord7(value), id, path, "an object");
40178
+ checkAt(isRecord8(value), id, path, "an object");
39805
40179
  const limits = value;
39806
40180
  checkAt(isNumber(limits.contextWindow), id, `${path}.contextWindow`, "a finite number");
39807
40181
  checkAt(isNumber(limits.maxOutputTokens), id, `${path}.maxOutputTokens`, "a finite number");
@@ -39819,19 +40193,19 @@ function checkDescriptor(id, record2) {
39819
40193
  }
39820
40194
  }
39821
40195
  const capabilities2 = record2.capabilities;
39822
- checkAt(isRecord7(capabilities2), id, "capabilities", "an object");
40196
+ checkAt(isRecord8(capabilities2), id, "capabilities", "an object");
39823
40197
  for (const flag of ["tools", "images", "reasoning"]) {
39824
40198
  const value = capabilities2[flag];
39825
40199
  checkAt(typeof value === "boolean", id, `capabilities.${flag}`, "a boolean");
39826
40200
  }
39827
40201
  const write = record2.writeOverInput;
39828
- checkAt(isRecord7(write), id, "writeOverInput", "an object");
40202
+ checkAt(isRecord8(write), id, "writeOverInput", "an object");
39829
40203
  for (const ttl of ["fiveMinute", "oneHour"]) {
39830
40204
  const value = write[ttl];
39831
40205
  checkAt(isNumber(value), id, `writeOverInput.${ttl}`, "a finite number");
39832
40206
  }
39833
40207
  const catalog2 = record2.catalog;
39834
- checkAt(isRecord7(catalog2), id, "catalog", "an object");
40208
+ checkAt(isRecord8(catalog2), id, "catalog", "an object");
39835
40209
  const entry = catalog2;
39836
40210
  checkAt(typeof entry.defaultModel === "string", id, "catalog.defaultModel", "a string");
39837
40211
  checkAt(Array.isArray(entry.authTypes), id, "catalog.authTypes", "an array");
@@ -39842,11 +40216,11 @@ function checkDescriptor(id, record2) {
39842
40216
  checkAt(Array.isArray(entry.models), id, "catalog.models", "an array");
39843
40217
  for (const [index, model] of entry.models.entries()) {
39844
40218
  const at = `catalog.models[${index}]`;
39845
- checkAt(isRecord7(model), id, at, "an object");
40219
+ checkAt(isRecord8(model), id, at, "an object");
39846
40220
  const choice = model;
39847
40221
  checkAt(typeof choice.id === "string", id, `${at}.id`, "a string");
39848
40222
  checkAt(typeof choice.label === "string", id, `${at}.label`, "a string");
39849
- checkAt(isRecord7(choice.pricing), id, `${at}.pricing`, "an object");
40223
+ checkAt(isRecord8(choice.pricing), id, `${at}.pricing`, "an object");
39850
40224
  const pricing = choice.pricing;
39851
40225
  for (const field of ["input", "output", "cacheRead", "cacheWrite5m", "cacheWrite1h"]) {
39852
40226
  checkAt(isNumber(pricing[field]), id, `${at}.pricing.${field}`, "a finite number");
@@ -39862,13 +40236,13 @@ function checkDescriptor(id, record2) {
39862
40236
  checkAt(typeof prefix === "string", id, `modelPrefixes[${index}]`, "a string");
39863
40237
  }
39864
40238
  const presentation = record2.presentation;
39865
- checkAt(isRecord7(presentation), id, "presentation", "an object");
40239
+ checkAt(isRecord8(presentation), id, "presentation", "an object");
39866
40240
  const shown = presentation;
39867
40241
  for (const field of ["label", "tone"]) {
39868
40242
  checkAt(typeof shown[field] === "string", id, `presentation.${field}`, "a string");
39869
40243
  }
39870
40244
  checkAt(isNumber(shown.order), id, "presentation.order", "a finite number");
39871
- checkAt(isRecord7(shown.colour), id, "presentation.colour", "an object");
40245
+ checkAt(isRecord8(shown.colour), id, "presentation.colour", "an object");
39872
40246
  for (const scheme of ["light", "dark"]) {
39873
40247
  const value = shown.colour[scheme];
39874
40248
  checkAt(typeof value === "string", id, `presentation.colour.${scheme}`, "a string");
@@ -39880,7 +40254,7 @@ function checkDescriptor(id, record2) {
39880
40254
  function validateOAuthFlow(id, value) {
39881
40255
  if (value === undefined)
39882
40256
  return;
39883
- if (!isRecord7(value))
40257
+ if (!isRecord8(value))
39884
40258
  throw new Error(`provider ${id} oauth must be an object`);
39885
40259
  const kind = value.kind;
39886
40260
  if (kind !== "pkce" && kind !== "device") {
@@ -56077,7 +56451,7 @@ function zodDetail(issue2) {
56077
56451
  }
56078
56452
  return issue2.message;
56079
56453
  }
56080
- function isRecord8(value) {
56454
+ function isRecord9(value) {
56081
56455
  return typeof value === "object" && value !== null;
56082
56456
  }
56083
56457
  function extraFields(body2, known) {
@@ -56220,7 +56594,7 @@ async function readJson(request2) {
56220
56594
  }
56221
56595
  async function readJsonRecord(request2) {
56222
56596
  const body2 = await readJson(request2);
56223
- return isRecord8(body2) ? body2 : null;
56597
+ return isRecord9(body2) ? body2 : null;
56224
56598
  }
56225
56599
  function apiErrorResponse(error62) {
56226
56600
  const gatewayError = error62 instanceof GatewayError ? error62 : new GatewayError("INTERNAL", "internal error");
@@ -60551,10 +60925,10 @@ function toIrToolChoice(c) {
60551
60925
  }
60552
60926
  var EFFORTS = REASONING_EFFORTS;
60553
60927
  function readEffort(body2) {
60554
- if (!isRecord8(body2))
60928
+ if (!isRecord9(body2))
60555
60929
  return;
60556
60930
  const outputConfig = body2.output_config;
60557
- if (!isRecord8(outputConfig))
60931
+ if (!isRecord9(outputConfig))
60558
60932
  return;
60559
60933
  const effort = outputConfig.effort;
60560
60934
  return EFFORTS.find((level) => level === effort);
@@ -60925,7 +61299,7 @@ function roleOf(raw) {
60925
61299
  return "user";
60926
61300
  }
60927
61301
  function contentPart(part2) {
60928
- if (!isRecord8(part2))
61302
+ if (!isRecord9(part2))
60929
61303
  throw new GatewayError("BAD_REQUEST", "input: content part must be an object");
60930
61304
  const type = part2.type;
60931
61305
  if (type === "input_text" || type === "output_text") {
@@ -60965,7 +61339,7 @@ function readInputItems(items) {
60965
61339
  messages.push({ role, content });
60966
61340
  };
60967
61341
  for (const raw of items) {
60968
- if (!isRecord8(raw))
61342
+ if (!isRecord9(raw))
60969
61343
  throw new GatewayError("BAD_REQUEST", "input: item must be an object");
60970
61344
  const type = raw.type ?? (raw.role === undefined ? undefined : "message");
60971
61345
  switch (type) {
@@ -61021,7 +61395,7 @@ function jsonArguments(raw, callId) {
61021
61395
  const text = typeof raw === "string" ? raw : "";
61022
61396
  try {
61023
61397
  const parsed2 = text === "" ? {} : JSON.parse(text);
61024
- return isRecord8(parsed2) ? parsed2 : { value: parsed2 };
61398
+ return isRecord9(parsed2) ? parsed2 : { value: parsed2 };
61025
61399
  } catch {
61026
61400
  throw new GatewayError("BAD_REQUEST", `input: arguments for call ${safeToken(callId)} are not valid JSON`);
61027
61401
  }
@@ -61030,7 +61404,7 @@ var TOOL_NAME = /^[A-Za-z0-9_-]{1,128}$/;
61030
61404
  function readTools(raw) {
61031
61405
  const tools2 = [];
61032
61406
  for (const entry of raw) {
61033
- if (!isRecord8(entry))
61407
+ if (!isRecord9(entry))
61034
61408
  throw new GatewayError("BAD_REQUEST", "tools: each tool must be an object");
61035
61409
  const type = typeof entry.type === "string" ? entry.type : "";
61036
61410
  const declared = typeof entry.name === "string" ? entry.name : "";
@@ -61043,7 +61417,7 @@ function readTools(raw) {
61043
61417
  kind: "portable",
61044
61418
  name: declared,
61045
61419
  ...description === undefined ? {} : { description },
61046
- inputSchema: type === "custom" ? { type: "object", properties: { input: { type: "string" } }, required: ["input"] } : isRecord8(entry.parameters) ? entry.parameters : { type: "object" }
61420
+ inputSchema: type === "custom" ? { type: "object", properties: { input: { type: "string" } }, required: ["input"] } : isRecord9(entry.parameters) ? entry.parameters : { type: "object" }
61047
61421
  });
61048
61422
  continue;
61049
61423
  }
@@ -61058,10 +61432,10 @@ function readTools(raw) {
61058
61432
  }
61059
61433
  function customToolNames(body2) {
61060
61434
  const names = new Set;
61061
- if (!isRecord8(body2) || !Array.isArray(body2.tools))
61435
+ if (!isRecord9(body2) || !Array.isArray(body2.tools))
61062
61436
  return names;
61063
61437
  for (const entry of body2.tools) {
61064
- if (isRecord8(entry) && entry.type === "custom" && typeof entry.name === "string") {
61438
+ if (isRecord9(entry) && entry.type === "custom" && typeof entry.name === "string") {
61065
61439
  names.add(entry.name);
61066
61440
  }
61067
61441
  }
@@ -61697,11 +62071,11 @@ function topicClass(topic) {
61697
62071
  return null;
61698
62072
  }
61699
62073
  var MAX_TOPIC = 128;
61700
- function isRecord9(value) {
62074
+ function isRecord10(value) {
61701
62075
  return typeof value === "object" && value !== null && !Array.isArray(value);
61702
62076
  }
61703
62077
  function parseClientFrame(raw) {
61704
- if (!isRecord9(raw))
62078
+ if (!isRecord10(raw))
61705
62079
  return null;
61706
62080
  const { id, type, topic } = raw;
61707
62081
  if (id !== undefined && typeof id !== "string")
@@ -62385,7 +62759,7 @@ function createRing(limits = DEFAULT_RING_LIMITS) {
62385
62759
  }
62386
62760
 
62387
62761
  // apps/gateway/src/version.ts
62388
- var VERSION = "0.12.6";
62762
+ var VERSION = "0.12.8";
62389
62763
 
62390
62764
  // apps/gateway/src/app.ts
62391
62765
  var ADMIN_SESSION_TTL_MS = 12 * 60 * 60 * 1000;