omnigateway 0.12.11 → 0.12.13

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 (56) hide show
  1. package/README.md +1 -0
  2. package/bin/omni.js +488 -119
  3. package/gateway.js +488 -111
  4. package/package.json +1 -1
  5. package/public/assets/{Chip-D4qvhu1D.js → Chip-D0XSbQUr.js} +1 -1
  6. package/public/assets/{CopyValue-SnsT2LML.js → CopyValue-DAlmkISB.js} +3 -3
  7. package/public/assets/{Field-BYBri2NV.js → Field-DG1317zr.js} +1 -1
  8. package/public/assets/Lamp-Dk9XrTCg.js +26 -0
  9. package/public/assets/{Panel-CWmOTDAP.js → Panel-CsovmtxF.js} +23 -4
  10. package/public/assets/Rack-CDUOJkS2.js +483 -0
  11. package/public/assets/{Readout-BTh732hP.js → Readout-DlT5oxGO.js} +1 -1
  12. package/public/assets/RequestTable-i3TtCB9m.js +93 -0
  13. package/public/assets/{SummaryDeck-7ivuca39.js → SummaryDeck-DrzTQQo5.js} +2 -2
  14. package/public/assets/{Toggle-t82IhqEt.js → Toggle-CdMD58sy.js} +1 -1
  15. package/public/assets/{TokenBreakdown-D1Wtza1y.js → TokenBreakdown-BC6nqo1v.js} +1 -1
  16. package/public/assets/{WindowChart-BeGPsccS.js → WindowChart-Bqbl-KFO.js} +2 -2
  17. package/public/assets/_app-CSru2YTE.js +1 -0
  18. package/public/assets/_app.accounts-B2lQkMb0.js +70 -0
  19. package/public/assets/_app.console-a2TJDoBC.js +24 -0
  20. package/public/assets/_app.database-CqSoTi2l.js +24 -0
  21. package/public/assets/_app.index-BV1kJJjA.js +67 -0
  22. package/public/assets/_app.keys-Dq5O0AG9.js +92 -0
  23. package/public/assets/_app.logs-PjRK5wqy.js +46 -0
  24. package/public/assets/_app.models-BfmeeB5e.js +148 -0
  25. package/public/assets/_app.plugins._pluginId-Owb05aFv.js +20 -0
  26. package/public/assets/{_app.settings-C3GzeJ4q.js → _app.settings-5i-vvT-H.js} +7 -7
  27. package/public/assets/_app.usage--5qFtU1W.js +76 -0
  28. package/public/assets/chevron-down-Bb5ZGvwk.js +1 -0
  29. package/public/assets/chevron-right-hwF5mD6-.js +1 -0
  30. package/public/assets/{client-k1tkFSNH.js → client-BcXc3lek.js} +4 -4
  31. package/public/assets/{dist-D03q-60i.js → dist-BBGxva0Y.js} +1 -1
  32. package/public/assets/index-D1RDaq3l.js +14 -0
  33. package/public/assets/{login-DW2Ipp21.js → login-GB0ZGUvA.js} +4 -4
  34. package/public/assets/plus-BgcHxxIr.js +1 -0
  35. package/public/assets/{preload-helper-BPaHpbO_.js → preload-helper-B7KDmXJ9.js} +1 -1
  36. package/public/assets/rotate-ccw-Do43Argv.js +1 -0
  37. package/public/assets/{shared-Dtkw6SE0.js → shared-DDpLUhCp.js} +2 -2
  38. package/public/assets/{trash-D4QWzEK_.js → trash-00950_yY.js} +1 -1
  39. package/public/index.html +5 -5
  40. package/public/assets/Lamp-DkvXKB-B.js +0 -26
  41. package/public/assets/Rack-CEuCdVXc.js +0 -483
  42. package/public/assets/RequestTable-D8L6iVJV.js +0 -93
  43. package/public/assets/_app-Drf03PWk.js +0 -1
  44. package/public/assets/_app.accounts-W1USUo2Q.js +0 -70
  45. package/public/assets/_app.console-Co9d2ZiD.js +0 -44
  46. package/public/assets/_app.database-CtFJLcfE.js +0 -24
  47. package/public/assets/_app.index-DigYfob3.js +0 -67
  48. package/public/assets/_app.keys-B1fRMyU-.js +0 -92
  49. package/public/assets/_app.logs-CFixPsUw.js +0 -60
  50. package/public/assets/_app.models-Dpl1O2RE.js +0 -148
  51. package/public/assets/_app.plugins._pluginId-BK0ADugW.js +0 -20
  52. package/public/assets/_app.usage-D2qlcEp4.js +0 -76
  53. package/public/assets/chevron-down-Bs0tSOyA.js +0 -1
  54. package/public/assets/chevron-right-DSaI1kFo.js +0 -1
  55. package/public/assets/index-Bk9sabex.js +0 -14
  56. package/public/assets/plus-BCfjC6nk.js +0 -1
package/gateway.js CHANGED
@@ -30177,12 +30177,18 @@ var ANTHROPIC_MODELS = {
30177
30177
  };
30178
30178
  var ONE_M_SUFFIX = "[1m]";
30179
30179
  var DATED_SUFFIX = /-\d{8}$/;
30180
- function anthropicReasoningForm(model) {
30180
+ function anthropicChoice(model) {
30181
30181
  let id = model.trim();
30182
30182
  if (id.toLowerCase().endsWith(ONE_M_SUFFIX))
30183
30183
  id = id.slice(0, -ONE_M_SUFFIX.length).trim();
30184
30184
  id = id.replace(DATED_SUFFIX, "");
30185
- return ANTHROPIC_MODELS.models.find((m) => m.id === id)?.reasoningForm ?? "adaptive";
30185
+ return ANTHROPIC_MODELS.models.find((m) => m.id === id);
30186
+ }
30187
+ function anthropicReasoningForm(model) {
30188
+ return anthropicChoice(model)?.reasoningForm ?? "adaptive";
30189
+ }
30190
+ function anthropicMaxOutputTokens(model) {
30191
+ return anthropicChoice(model)?.limits.maxOutputTokens;
30186
30192
  }
30187
30193
 
30188
30194
  // packages/providers/src/anthropic/descriptor.ts
@@ -31181,7 +31187,8 @@ function codecAdapter(id, capabilities2, codec2, origins) {
31181
31187
  credentials: req.credentials,
31182
31188
  fail,
31183
31189
  ...req.requestId === undefined ? {} : { requestId: req.requestId },
31184
- ...req.autoCache === undefined ? {} : { autoCacheEnabled: req.autoCache }
31190
+ ...req.autoCache === undefined ? {} : { autoCacheEnabled: req.autoCache },
31191
+ ...req.maxOutputTokens === undefined ? {} : { maxOutputTokens: req.maxOutputTokens }
31185
31192
  }));
31186
31193
  const described = built?.request ?? {};
31187
31194
  const request2 = {
@@ -32635,6 +32642,69 @@ function systemText(system, provider, note) {
32635
32642
  `);
32636
32643
  }
32637
32644
 
32645
+ // packages/providers/src/toolResultFiles.ts
32646
+ function isTextual(mediaType) {
32647
+ const type = mediaType.split(";")[0]?.trim().toLowerCase() ?? "";
32648
+ return type.startsWith("text/") || type.endsWith("+json") || type.endsWith("+xml") || TEXTUAL.has(type);
32649
+ }
32650
+ var TEXTUAL = new Set([
32651
+ "application/json",
32652
+ "application/x-ndjson",
32653
+ "application/xml",
32654
+ "application/yaml",
32655
+ "application/x-yaml",
32656
+ "application/toml",
32657
+ "application/javascript",
32658
+ "application/typescript",
32659
+ "application/sql",
32660
+ "application/x-sh",
32661
+ "message/rfc822"
32662
+ ]);
32663
+ function fileText(file2) {
32664
+ return Buffer.from(file2.data, "base64").toString("utf8");
32665
+ }
32666
+ function splitFiles(files, carries) {
32667
+ const text = [];
32668
+ const carried = [];
32669
+ let dropped = false;
32670
+ for (const file2 of files) {
32671
+ if (isTextual(file2.mediaType))
32672
+ text.push(fileText(file2));
32673
+ else if (carries(file2.mediaType))
32674
+ carried.push(file2);
32675
+ else
32676
+ dropped = true;
32677
+ }
32678
+ return { text, carried, dropped };
32679
+ }
32680
+ function withFileText(content, text) {
32681
+ return [content, ...text].filter((t) => t.length > 0).join(`
32682
+
32683
+ `);
32684
+ }
32685
+ var RESPONSES_FILE_TYPES = Object.assign(Object.create(null), {
32686
+ "application/pdf": "pdf",
32687
+ "application/rtf": "rtf",
32688
+ "application/msword": "doc",
32689
+ "application/vnd.ms-excel": "xls",
32690
+ "application/vnd.ms-powerpoint": "ppt",
32691
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document": "docx",
32692
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": "xlsx",
32693
+ "application/vnd.openxmlformats-officedocument.presentationml.presentation": "pptx"
32694
+ });
32695
+ function fileName(file2) {
32696
+ return file2.filename ?? `file.${RESPONSES_FILE_TYPES[file2.mediaType] ?? "bin"}`;
32697
+ }
32698
+ function responsesFiles(files) {
32699
+ const { text, carried, dropped } = splitFiles(files, (t) => (t in RESPONSES_FILE_TYPES));
32700
+ const parts = carried.map((file2) => ({
32701
+ type: "input_file",
32702
+ filename: fileName(file2),
32703
+ file_data: `data:${file2.mediaType};base64,${file2.data}`
32704
+ }));
32705
+ return { parts, text, dropped };
32706
+ }
32707
+
32638
32708
  // packages/providers/src/anthropic/wire.ts
32639
32709
  var OAUTH_IDENTITY = "You are Claude Code, Anthropic's official CLI for Claude.";
32640
32710
  function wireCacheControl(c) {
@@ -32672,22 +32742,13 @@ function encodeBlock(b, cloak) {
32672
32742
  ...cache
32673
32743
  };
32674
32744
  case "toolResult": {
32675
- const documents = (b.files ?? []).flatMap((file2) => {
32676
- const source = file2.mediaType === "application/pdf" ? { type: "base64", media_type: file2.mediaType, data: file2.data } : file2.mediaType === "text/plain" ? {
32677
- type: "text",
32678
- media_type: file2.mediaType,
32679
- data: Buffer.from(file2.data, "base64").toString("utf8")
32680
- } : undefined;
32681
- if (source === undefined)
32682
- return [];
32683
- return [
32684
- {
32685
- type: "document",
32686
- source,
32687
- ...file2.filename !== undefined && { title: file2.filename }
32688
- }
32689
- ];
32690
- });
32745
+ const files = splitFiles(b.files ?? [], (t) => t === "application/pdf");
32746
+ const text = withFileText(b.content, files.text);
32747
+ const documents = files.carried.map((file2) => ({
32748
+ type: "document",
32749
+ source: { type: "base64", media_type: file2.mediaType, data: file2.data },
32750
+ ...file2.filename !== undefined && { title: file2.filename }
32751
+ }));
32691
32752
  const parts = [
32692
32753
  ...(b.images ?? []).map((image) => encodeBlock(image, cloak)),
32693
32754
  ...documents,
@@ -32696,7 +32757,7 @@ function encodeBlock(b, cloak) {
32696
32757
  return {
32697
32758
  type: "tool_result",
32698
32759
  tool_use_id: b.toolUseId,
32699
- content: parts.length === 0 ? b.content : [...b.content.length > 0 ? [{ type: "text", text: b.content }] : [], ...parts],
32760
+ content: parts.length === 0 ? text : [...text.length > 0 ? [{ type: "text", text }] : [], ...parts],
32700
32761
  is_error: b.isError,
32701
32762
  ...cache
32702
32763
  };
@@ -32848,6 +32909,12 @@ function addAutoCacheBreakpoints(body, req, note) {
32848
32909
  lastHistory.cache_control = { type: "ephemeral" };
32849
32910
  note("anthropic:history-cache-breakpoint-added");
32850
32911
  }
32912
+ function defaultMaxTokens(model, saved) {
32913
+ const ceiling = anthropicMaxOutputTokens(model);
32914
+ if (saved === undefined)
32915
+ return ceiling ?? 4096;
32916
+ return ceiling === undefined ? saved : Math.min(saved, ceiling);
32917
+ }
32851
32918
  function toWire(req, model, opts) {
32852
32919
  const cloak = opts.cloak ?? null;
32853
32920
  const degradations = [];
@@ -32872,8 +32939,12 @@ function toWire(req, model, opts) {
32872
32939
  note("anthropic:system-turn-cache-control-dropped");
32873
32940
  for (const m of req.messages) {
32874
32941
  for (const b of m.content) {
32875
- if (b.type === "toolResult" && b.files?.some((f) => f.mediaType !== "application/pdf" && f.mediaType !== "text/plain")) {
32876
- note("anthropic:files-dropped");
32942
+ if (b.type === "toolResult" && b.files !== undefined) {
32943
+ const files = splitFiles(b.files, (t) => t === "application/pdf");
32944
+ if (files.text.length > 0)
32945
+ note("anthropic:tool-result-files-inlined");
32946
+ if (files.dropped)
32947
+ note("anthropic:files-dropped");
32877
32948
  }
32878
32949
  }
32879
32950
  }
@@ -32890,7 +32961,7 @@ function toWire(req, model, opts) {
32890
32961
  }
32891
32962
  return [{ role: m.role, content: encodeSystemTurn(m.content, cloak) }];
32892
32963
  }),
32893
- max_tokens: req.maxTokens ?? 4096,
32964
+ max_tokens: req.maxTokens ?? defaultMaxTokens(model, opts.maxOutputTokens),
32894
32965
  stream: req.stream
32895
32966
  };
32896
32967
  if (systemCache.retarget !== undefined) {
@@ -33029,7 +33100,8 @@ var anthropicCodec = {
33029
33100
  const { body, degradations } = toWire(input2.request, input2.model, {
33030
33101
  oauth,
33031
33102
  cloak,
33032
- autoCache: input2.autoCacheEnabled === true
33103
+ autoCache: input2.autoCacheEnabled === true,
33104
+ ...input2.maxOutputTokens === undefined ? {} : { maxOutputTokens: input2.maxOutputTokens }
33033
33105
  });
33034
33106
  const firstUser = input2.request.messages.find((m) => m.role === "user");
33035
33107
  const firstText = firstUser?.content.find((b) => b.type === "text");
@@ -33362,8 +33434,125 @@ var anthropicOAuthFlow = {
33362
33434
  if (!usageReadable(res.status, "anthropic"))
33363
33435
  return null;
33364
33436
  return parseAnthropicUsage(parsed(res.body), now());
33437
+ },
33438
+ async* resetCredits({ secrets }) {
33439
+ if (secrets.accessToken === null)
33440
+ return null;
33441
+ const res = yield getJsonRequest(RESET_STATUS_URL, anthropicProfile, {
33442
+ accessToken: secrets.accessToken,
33443
+ extraHeaders: SIDE_HEADERS
33444
+ });
33445
+ if (!usageReadable(res.status, "anthropic"))
33446
+ return null;
33447
+ const root = recordOf(parsed(res.body));
33448
+ return root === null ? null : parseResetGrants(root.cedar_ember ?? null);
33449
+ },
33450
+ async* redeemReset({ secrets, creditId, requestId, fail }) {
33451
+ if (secrets.accessToken === null)
33452
+ throw fail("AUTH", "credential holds no access token");
33453
+ const grantId = grantOf(creditId);
33454
+ if (grantId === null)
33455
+ throw fail("CONFLICT", "that reset credit is not available");
33456
+ const profile = yield getJsonRequest(PROFILE_URL, anthropicProfile, {
33457
+ accessToken: secrets.accessToken,
33458
+ extraHeaders: SIDE_HEADERS
33459
+ });
33460
+ if (profile.status < 200 || profile.status >= 300) {
33461
+ throw fail(redeemErrorCode(profile.status), `profile read refused: http_${profile.status}`, {
33462
+ status: profile.status
33463
+ });
33464
+ }
33465
+ const orgId = orgIdOf(parsed(profile.body));
33466
+ if (orgId === null)
33467
+ throw fail("UPSTREAM", "profile names no organization");
33468
+ const res = yield postJsonRequest(`https://api.anthropic.com/api/organizations/${orgId}/reset_rate_limits`, anthropicProfile, {
33469
+ contentType: "application/json",
33470
+ body: JSON.stringify({ program: RESET_PROGRAM, grant_id: grantId, request_id: requestId }),
33471
+ extraHeaders: [["Authorization", `Bearer ${secrets.accessToken}`], ...SIDE_HEADERS]
33472
+ });
33473
+ if (res.status < 200 || res.status >= 300) {
33474
+ throw fail(redeemErrorCode(res.status), `reset claim refused: http_${res.status}`, {
33475
+ status: res.status
33476
+ });
33477
+ }
33478
+ return claimOutcome(parsed(res.body), fail);
33365
33479
  }
33366
33480
  };
33481
+ var RESET_PROGRAM = "cedar_ember";
33482
+ var RESET_STATUS_URL = `${USAGE_URL}?cedar_ember=1&skip_spend=1`;
33483
+ var PROFILE_URL = "https://api.anthropic.com/api/oauth/profile";
33484
+ var ORG_ID = /^[A-Za-z0-9-]{1,64}$/;
33485
+ var SIDE_HEADERS = [["anthropic-beta", "oauth-2025-04-20"]];
33486
+ var USE_SUFFIX = /-u(\d+)$/;
33487
+ function creditIdOf(grantId, left) {
33488
+ return `${grantId}-u${left}`;
33489
+ }
33490
+ function grantOf(creditId) {
33491
+ const grant = creditId.replace(USE_SUFFIX, "");
33492
+ return grant === creditId || grant === "" ? null : grant;
33493
+ }
33494
+ function orgIdOf(value) {
33495
+ const org = recordOf(recordOf(value)?.organization);
33496
+ const uuid3 = org?.uuid;
33497
+ return typeof uuid3 === "string" && ORG_ID.test(uuid3) ? uuid3 : null;
33498
+ }
33499
+ function parseResetGrants(value) {
33500
+ if (value === null)
33501
+ return { available: 0, credits: [] };
33502
+ const block = recordOf(value);
33503
+ if (block === null || !Array.isArray(block.grants))
33504
+ return null;
33505
+ const next = typeof block.next_grant_id === "string" ? block.next_grant_id : null;
33506
+ const atLimit = block.at_limit === true;
33507
+ let available = 0;
33508
+ const credits = block.grants.flatMap((raw) => {
33509
+ const g = recordOf(raw);
33510
+ if (g === null || typeof g.id !== "string")
33511
+ return [];
33512
+ const left = typeof g.resets_left === "number" ? g.resets_left : 0;
33513
+ const claimable = left > 0 && g.usable_now === true && g.paused !== true && (g.use_requires_limit !== true || atLimit) && (next === null || next === g.id);
33514
+ if (claimable)
33515
+ available += left;
33516
+ return [
33517
+ {
33518
+ id: creditIdOf(g.id, left),
33519
+ status: claimable ? "available" : left > 0 ? "unavailable" : "used",
33520
+ title: typeof g.label === "string" && g.label !== "" ? g.label : null,
33521
+ grantedAt: isoOrNull(g.starts_at),
33522
+ expiresAt: isoOrNull(g.ends_at)
33523
+ }
33524
+ ];
33525
+ });
33526
+ return { available, credits };
33527
+ }
33528
+ function claimOutcome(value, fail) {
33529
+ const body = recordOf(value);
33530
+ const result = typeof body?.result === "string" ? body.result : null;
33531
+ if (result === "reset") {
33532
+ return { windowsReset: Array.isArray(body?.cleared) ? body.cleared.length : null };
33533
+ }
33534
+ if (result === "cooldown")
33535
+ throw fail("RATE_LIMIT", "reset claim refused: cooldown");
33536
+ if (result === "already_used" || result === "not_limited" || result === "ineligible") {
33537
+ throw fail("CONFLICT", `reset claim refused: ${result}`);
33538
+ }
33539
+ throw fail("UPSTREAM", "reset claim answered without a reset");
33540
+ }
33541
+ function redeemErrorCode(status) {
33542
+ if (status === 429)
33543
+ return "RATE_LIMIT";
33544
+ if (status === 401 || status === 403)
33545
+ return "AUTH";
33546
+ if (status >= 400 && status < 500)
33547
+ return "CONFLICT";
33548
+ return "UPSTREAM";
33549
+ }
33550
+ function isoOrNull(value) {
33551
+ if (typeof value !== "string")
33552
+ return null;
33553
+ const at = Date.parse(value);
33554
+ return Number.isNaN(at) ? null : at;
33555
+ }
33367
33556
  // packages/providers/src/antigravity/codec.ts
33368
33557
  import { createHash as createHash2 } from "crypto";
33369
33558
 
@@ -33968,16 +34157,19 @@ function toAntigravityWire(req, model, identity) {
33968
34157
  note("antigravity:tool-result-unmatched");
33969
34158
  if (block.isError === true)
33970
34159
  note("antigravity:tool-result-error-flag-dropped");
34160
+ const files = splitFiles(block.files ?? [], () => true);
34161
+ if (files.text.length > 0)
34162
+ note("antigravity:tool-result-files-inlined");
33971
34163
  parts.push({
33972
34164
  functionResponse: {
33973
34165
  name: cloakName2(cloak, name ?? block.toolUseId),
33974
- response: { output: block.content }
34166
+ response: { output: withFileText(block.content, files.text) }
33975
34167
  }
33976
34168
  });
33977
34169
  for (const image of block.images ?? []) {
33978
34170
  parts.push({ inlineData: { mimeType: image.mediaType, data: image.data } });
33979
34171
  }
33980
- for (const file2 of block.files ?? []) {
34172
+ for (const file2 of files.carried) {
33981
34173
  parts.push({ inlineData: { mimeType: file2.mediaType, data: file2.data } });
33982
34174
  }
33983
34175
  role = "user";
@@ -34682,7 +34874,7 @@ var grokOAuthFlow = {
34682
34874
 
34683
34875
  // packages/providers/src/kilo/oauth.ts
34684
34876
  var CODES_URL = "https://api.kilo.ai/api/device-auth/codes";
34685
- var PROFILE_URL = "https://api.kilo.ai/api/profile";
34877
+ var PROFILE_URL2 = "https://api.kilo.ai/api/profile";
34686
34878
  var FALLBACK_VERIFICATION_URL = "https://kilo.ai";
34687
34879
  var DEFAULT_EXPIRES_SECONDS = 300;
34688
34880
  var POLL_INTERVAL_SECONDS = 3;
@@ -34714,7 +34906,7 @@ function deviceCodeFrom(value, fail) {
34714
34906
  }
34715
34907
  async function* orgIdFor(accessToken) {
34716
34908
  try {
34717
- const res = yield getJsonRequest(PROFILE_URL, kiloProfile, { accessToken });
34909
+ const res = yield getJsonRequest(PROFILE_URL2, kiloProfile, { accessToken });
34718
34910
  if (res.status < 200 || res.status >= 300)
34719
34911
  return null;
34720
34912
  const record2 = recordFrom(parsed(res.body));
@@ -35222,6 +35414,7 @@ var AUTHORIZE_URL3 = "https://auth.openai.com/oauth/authorize";
35222
35414
  var TOKEN_URL5 = "https://auth.openai.com/oauth/token";
35223
35415
  var SCOPES4 = "openid profile email offline_access";
35224
35416
  var USAGE_URL3 = "https://chatgpt.com/backend-api/wham/usage";
35417
+ var RESET_CREDITS_URL = "https://chatgpt.com/backend-api/wham/rate-limit-reset-credits";
35225
35418
  function isRecord7(value) {
35226
35419
  return typeof value === "object" && value !== null;
35227
35420
  }
@@ -35375,8 +35568,78 @@ var openaiOAuthFlow = {
35375
35568
  if (!usageReadable(res.status, "openai"))
35376
35569
  return null;
35377
35570
  return parseOpenAIUsage(parsed(res.body), now());
35571
+ },
35572
+ async* resetCredits({ secrets, providerData }) {
35573
+ if (secrets.accessToken === null)
35574
+ return null;
35575
+ const res = yield getJsonRequest(RESET_CREDITS_URL, openaiProfile, {
35576
+ accessToken: secrets.accessToken,
35577
+ extraHeaders: accountHeader(providerData)
35578
+ });
35579
+ if (!usageReadable(res.status, "openai"))
35580
+ return null;
35581
+ return parseResetCredits(parsed(res.body));
35582
+ },
35583
+ async* redeemReset({ secrets, providerData, creditId, requestId, fail }) {
35584
+ if (secrets.accessToken === null)
35585
+ throw fail("AUTH", "credential holds no access token");
35586
+ const res = yield postJsonRequest(`${RESET_CREDITS_URL}/consume`, openaiProfile, {
35587
+ contentType: "application/json",
35588
+ body: JSON.stringify({ credit_id: creditId, redeem_request_id: requestId }),
35589
+ extraHeaders: [
35590
+ ["Authorization", `Bearer ${secrets.accessToken}`],
35591
+ ...accountHeader(providerData)
35592
+ ]
35593
+ });
35594
+ if (res.status < 200 || res.status >= 300) {
35595
+ throw fail(redeemErrorCode2(res.status), `reset credit redeem refused: http_${res.status}`, {
35596
+ status: res.status
35597
+ });
35598
+ }
35599
+ const body = recordOf(parsed(res.body));
35600
+ const windowsReset = body === null ? null : numberOf(body, ["windows_reset"]);
35601
+ return { windowsReset };
35378
35602
  }
35379
35603
  };
35604
+ function accountHeader(providerData) {
35605
+ const accountId = accountIdFromProviderData(providerData);
35606
+ return accountId === null ? [] : [["chatgpt-account-id", accountId]];
35607
+ }
35608
+ function redeemErrorCode2(status) {
35609
+ if (status === 429)
35610
+ return "RATE_LIMIT";
35611
+ if (status === 401 || status === 403)
35612
+ return "AUTH";
35613
+ if (status >= 400 && status < 500)
35614
+ return "CONFLICT";
35615
+ return "UPSTREAM";
35616
+ }
35617
+ function isoOrNull2(value) {
35618
+ if (typeof value !== "string")
35619
+ return null;
35620
+ const at = Date.parse(value);
35621
+ return Number.isFinite(at) ? at : null;
35622
+ }
35623
+ function parseResetCredits(value) {
35624
+ const root = recordOf(value);
35625
+ if (root === null || !Array.isArray(root.credits))
35626
+ return null;
35627
+ const credits = root.credits.flatMap((raw) => {
35628
+ const c = recordOf(raw);
35629
+ if (c === null || typeof c.id !== "string" || typeof c.status !== "string")
35630
+ return [];
35631
+ return [
35632
+ {
35633
+ id: c.id,
35634
+ status: c.status,
35635
+ title: typeof c.title === "string" ? c.title : null,
35636
+ grantedAt: isoOrNull2(c.granted_at),
35637
+ expiresAt: isoOrNull2(c.expires_at)
35638
+ }
35639
+ ];
35640
+ });
35641
+ return { available: credits.filter((c) => c.status === "available").length, credits };
35642
+ }
35380
35643
 
35381
35644
  // packages/providers/src/builtinOAuth.ts
35382
35645
  function builtinOAuthFlows() {
@@ -35720,61 +35983,6 @@ async function* decodeCustomResponses(messages) {
35720
35983
  }
35721
35984
  }
35722
35985
 
35723
- // packages/providers/src/responsesFile.ts
35724
- var ACCEPTED = new Set([
35725
- "application/pdf",
35726
- "text/plain",
35727
- "text/csv",
35728
- "text/markdown",
35729
- "text/html",
35730
- "text/css",
35731
- "text/xml",
35732
- "text/calendar",
35733
- "text/tab-separated-values",
35734
- "text/javascript",
35735
- "text/x-python",
35736
- "text/x-c",
35737
- "text/x-java",
35738
- "text/x-sh",
35739
- "text/x-sql",
35740
- "text/x-typescript",
35741
- "text/x-yaml",
35742
- "application/json",
35743
- "application/javascript",
35744
- "application/typescript",
35745
- "application/toml",
35746
- "application/yaml",
35747
- "application/x-yaml",
35748
- "message/rfc822",
35749
- "application/rtf",
35750
- "application/msword",
35751
- "application/vnd.ms-excel",
35752
- "application/vnd.ms-powerpoint",
35753
- "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
35754
- "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
35755
- "application/vnd.openxmlformats-officedocument.presentationml.presentation"
35756
- ]);
35757
- var TEXTUAL = new Set(["application/xml", "application/sql", "application/x-sh"]);
35758
- function responsesFiles(files) {
35759
- const parts = [];
35760
- const text = [];
35761
- let dropped = false;
35762
- for (const file2 of files) {
35763
- if (ACCEPTED.has(file2.mediaType)) {
35764
- parts.push({
35765
- type: "input_file",
35766
- ...file2.filename !== undefined && { filename: file2.filename },
35767
- file_data: `data:${file2.mediaType};base64,${file2.data}`
35768
- });
35769
- } else if (file2.mediaType.startsWith("text/") || TEXTUAL.has(file2.mediaType)) {
35770
- text.push(Buffer.from(file2.data, "base64").toString("utf8"));
35771
- } else {
35772
- dropped = true;
35773
- }
35774
- }
35775
- return { parts, text, dropped };
35776
- }
35777
-
35778
35986
  // packages/providers/src/custom/wire.ts
35779
35987
  function encodeChatToolChoice(c) {
35780
35988
  switch (c.type) {
@@ -35838,19 +36046,23 @@ function toCustomChatWire(req, model) {
35838
36046
  function: { name: block.name, arguments: JSON.stringify(block.input) }
35839
36047
  });
35840
36048
  break;
35841
- case "toolResult":
36049
+ case "toolResult": {
35842
36050
  if (block.native !== undefined)
35843
36051
  note("custom:anthropic-native-block-dropped");
36052
+ const files = splitFiles(block.files ?? [], () => false);
35844
36053
  messages.push({
35845
36054
  role: "tool",
35846
36055
  tool_call_id: block.toolUseId,
35847
- content: block.content
36056
+ content: withFileText(block.content, files.text)
35848
36057
  });
35849
36058
  if (block.images !== undefined)
35850
36059
  note("custom:images-dropped");
35851
- if (block.files !== undefined)
36060
+ if (files.text.length > 0)
36061
+ note("custom:tool-result-files-inlined");
36062
+ if (files.dropped)
35852
36063
  note("custom:files-dropped");
35853
36064
  break;
36065
+ }
35854
36066
  case "providerNative":
35855
36067
  note("custom:anthropic-native-block-dropped");
35856
36068
  break;
@@ -35972,9 +36184,7 @@ function toCustomResponsesWire(req, model) {
35972
36184
  input2.push({
35973
36185
  type: "function_call_output",
35974
36186
  call_id: block.toolUseId,
35975
- output: [block.content, ...files.text].filter((t) => t.length > 0).join(`
35976
-
35977
- `)
36187
+ output: withFileText(block.content, files.text)
35978
36188
  });
35979
36189
  if (block.images !== undefined) {
35980
36190
  note("custom:tool-result-images-moved");
@@ -36360,9 +36570,7 @@ function toGrokWire(req, model) {
36360
36570
  input2.push({
36361
36571
  type: "function_call_output",
36362
36572
  call_id: block.toolUseId,
36363
- output: [block.content, ...files.text].filter((t) => t.length > 0).join(`
36364
-
36365
- `)
36573
+ output: withFileText(block.content, files.text)
36366
36574
  });
36367
36575
  if (block.images !== undefined) {
36368
36576
  note("grok:tool-result-images-moved");
@@ -36820,15 +37028,20 @@ function toKiloWire(req, model) {
36820
37028
  function: { name: block.name, arguments: JSON.stringify(block.input) }
36821
37029
  });
36822
37030
  break;
36823
- case "toolResult":
37031
+ case "toolResult": {
36824
37032
  if (block.native !== undefined)
36825
37033
  note("kilo:anthropic-native-block-dropped");
36826
37034
  flush();
37035
+ const files = splitFiles(block.files ?? [], (t) => t === "application/pdf");
36827
37036
  messages.push({
36828
37037
  role: "tool",
36829
37038
  tool_call_id: block.toolUseId,
36830
- content: block.content
37039
+ content: withFileText(block.content, files.text)
36831
37040
  });
37041
+ if (files.text.length > 0)
37042
+ note("kilo:tool-result-files-inlined");
37043
+ if (files.dropped)
37044
+ note("kilo:files-dropped");
36832
37045
  for (const image of block.images ?? []) {
36833
37046
  note("kilo:tool-result-images-moved");
36834
37047
  toolImages.push({
@@ -36836,17 +37049,18 @@ function toKiloWire(req, model) {
36836
37049
  image_url: { url: `data:${image.mediaType};base64,${image.data}` }
36837
37050
  });
36838
37051
  }
36839
- for (const file2 of block.files ?? []) {
37052
+ for (const file2 of files.carried) {
36840
37053
  note("kilo:tool-result-files-moved");
36841
37054
  toolImages.push({
36842
37055
  type: "file",
36843
37056
  file: {
36844
- ...file2.filename !== undefined && { filename: file2.filename },
37057
+ filename: fileName(file2),
36845
37058
  file_data: `data:${file2.mediaType};base64,${file2.data}`
36846
37059
  }
36847
37060
  });
36848
37061
  }
36849
37062
  break;
37063
+ }
36850
37064
  case "providerNative":
36851
37065
  note("kilo:anthropic-native-block-dropped");
36852
37066
  break;
@@ -37100,19 +37314,23 @@ function toChatWire(req, model, vendor = "kimi") {
37100
37314
  function: { name: block.name, arguments: JSON.stringify(block.input) }
37101
37315
  });
37102
37316
  break;
37103
- case "toolResult":
37317
+ case "toolResult": {
37104
37318
  if (block.native !== undefined)
37105
37319
  note("kimi:anthropic-native-block-dropped");
37320
+ const files = splitFiles(block.files ?? [], () => false);
37106
37321
  messages.push({
37107
37322
  role: "tool",
37108
37323
  tool_call_id: block.toolUseId,
37109
- content: block.content
37324
+ content: withFileText(block.content, files.text)
37110
37325
  });
37111
37326
  if (block.images !== undefined)
37112
37327
  note("kimi:images-dropped");
37113
- if (block.files !== undefined)
37328
+ if (files.text.length > 0)
37329
+ note("kimi:tool-result-files-inlined");
37330
+ if (files.dropped)
37114
37331
  note("kimi:files-dropped");
37115
37332
  break;
37333
+ }
37116
37334
  case "providerNative":
37117
37335
  note("kimi:anthropic-native-block-dropped");
37118
37336
  break;
@@ -37519,9 +37737,7 @@ function toMuseWire(req, model) {
37519
37737
  input2.push({
37520
37738
  type: "function_call_output",
37521
37739
  call_id: block.toolUseId,
37522
- output: [block.content, ...files.text].filter((t) => t.length > 0).join(`
37523
-
37524
- `)
37740
+ output: withFileText(block.content, files.text)
37525
37741
  });
37526
37742
  if (block.images !== undefined) {
37527
37743
  note("muse:tool-result-images-moved");
@@ -37947,9 +38163,7 @@ function toResponsesWire(req, model, opts = { oauth: false }) {
37947
38163
  input2.push({
37948
38164
  type: "function_call_output",
37949
38165
  call_id: block.toolUseId,
37950
- output: [block.content, ...files.text].filter((t) => t.length > 0).join(`
37951
-
37952
- `)
38166
+ output: withFileText(block.content, files.text)
37953
38167
  });
37954
38168
  if (block.images !== undefined) {
37955
38169
  note("openai:tool-result-images-moved");
@@ -38363,6 +38577,11 @@ var quotaRefreshSchema = exports_external.discriminatedUnion("kind", [
38363
38577
  }).strict(),
38364
38578
  exports_external.object({ kind: exports_external.literal("all") }).strict()
38365
38579
  ]);
38580
+ var accountIdSchema = exports_external.string().trim().min(1).max(64).regex(/^[A-Za-z0-9_-]+$/, "credentialId must be an account id");
38581
+ var redeemResetSchema = exports_external.object({
38582
+ credentialId: accountIdSchema,
38583
+ creditId: exports_external.string().min(1).max(128).regex(/^[A-Za-z0-9_-]+$/).optional()
38584
+ }).strict();
38366
38585
  var dimensionSchema = exports_external.enum([
38367
38586
  "credential",
38368
38587
  "model",
@@ -40255,6 +40474,29 @@ function oauthAdapter(id, flow, opts = {}) {
40255
40474
  return Promise.resolve(null);
40256
40475
  return runStep(id, "usage", step, deps, origins);
40257
40476
  }
40477
+ },
40478
+ ...flow.resetCredits === undefined ? {} : {
40479
+ resetCredits: (secrets, deps, providerData) => {
40480
+ const step = flow.resetCredits?.({ secrets, providerData, ...helpers(deps) });
40481
+ if (step === undefined)
40482
+ return Promise.resolve(null);
40483
+ return runStep(id, "resetCredits", step, deps, origins);
40484
+ }
40485
+ },
40486
+ ...flow.redeemReset === undefined ? {} : {
40487
+ redeemReset: (secrets, deps, providerData, creditId, requestId) => {
40488
+ const step = flow.redeemReset?.({
40489
+ secrets,
40490
+ providerData,
40491
+ creditId,
40492
+ requestId,
40493
+ ...helpers(deps)
40494
+ });
40495
+ if (step === undefined) {
40496
+ return Promise.reject(flowFailure(id, "redeemReset", "has no redeem step"));
40497
+ }
40498
+ return runStep(id, "redeemReset", step, deps, origins);
40499
+ }
40258
40500
  }
40259
40501
  };
40260
40502
  if (flow.kind === "pkce")
@@ -40290,11 +40532,32 @@ function isAuthorizeStart(value) {
40290
40532
  const candidate = value;
40291
40533
  return typeof candidate.authorizeUrl === "string" && typeof candidate.pending === "object" && candidate.pending !== null;
40292
40534
  }
40535
+ function isResetCreditsOrNull(value) {
40536
+ if (value === null)
40537
+ return true;
40538
+ if (typeof value !== "object")
40539
+ return false;
40540
+ const candidate = value;
40541
+ return typeof candidate.available === "number" && Array.isArray(candidate.credits) && candidate.credits.every((c) => {
40542
+ if (typeof c !== "object" || c === null)
40543
+ return false;
40544
+ const row = c;
40545
+ return typeof row.id === "string" && typeof row.status === "string" && (row.title === null || typeof row.title === "string") && (row.grantedAt === null || typeof row.grantedAt === "number") && (row.expiresAt === null || typeof row.expiresAt === "number");
40546
+ });
40547
+ }
40548
+ function isResetRedeemed(value) {
40549
+ if (typeof value !== "object" || value === null)
40550
+ return false;
40551
+ const held = value.windowsReset;
40552
+ return held === null || typeof held === "number";
40553
+ }
40293
40554
  var RETURN_SHAPE = {
40294
40555
  start: isAuthorizeStart,
40295
40556
  begin: isAuthorizeStart,
40296
40557
  exchange: isFlowResult,
40297
- refresh: isFlowResult
40558
+ refresh: isFlowResult,
40559
+ resetCredits: isResetCreditsOrNull,
40560
+ redeemReset: isResetRedeemed
40298
40561
  };
40299
40562
 
40300
40563
  // packages/control/src/oauth/index.ts
@@ -40511,6 +40774,11 @@ function validateOAuthFlow(id, value) {
40511
40774
  if (value.usage !== undefined) {
40512
40775
  checkAt(typeof value.usage === "function", id, "oauth.usage", "a function");
40513
40776
  }
40777
+ for (const fn of ["resetCredits", "redeemReset"]) {
40778
+ if (value[fn] !== undefined) {
40779
+ checkAt(typeof value[fn] === "function", id, `oauth.${fn}`, "a function");
40780
+ }
40781
+ }
40514
40782
  if (kind === "device") {
40515
40783
  checkAt(typeof value.begin === "function", id, "oauth.begin", "a function");
40516
40784
  checkAt(typeof value.needsDeviceId === "boolean", id, "oauth.needsDeviceId", "a boolean");
@@ -40709,6 +40977,52 @@ async function accountQuotaHistory(deps, input2) {
40709
40977
  truncated
40710
40978
  };
40711
40979
  }
40980
+ // packages/control/src/quota/resets.ts
40981
+ async function resettable(deps, credentialId) {
40982
+ const credential = await deps.store.credentials.get(credentialId.trim());
40983
+ if (credential === null)
40984
+ throw new GatewayError("BAD_REQUEST", "no such credential");
40985
+ const provider = deps.providers[credential.provider];
40986
+ const list = provider?.resetCredits;
40987
+ const redeem = provider?.redeemReset;
40988
+ if (credential.authType !== "oauth" || list === undefined || redeem === undefined) {
40989
+ throw new GatewayError("BAD_REQUEST", "this account's provider has no quota resets");
40990
+ }
40991
+ return { credential, list, redeem };
40992
+ }
40993
+ async function listFor(deps, r) {
40994
+ const secrets = await usageSecretsFor(deps, r.credential);
40995
+ const read = await r.list(secrets, { http: deps.http, now: deps.now }, r.credential.providerData);
40996
+ if (read === null) {
40997
+ throw new GatewayError("UPSTREAM", "provider answered the reset list with nothing usable", {
40998
+ gatewayAuthored: true
40999
+ });
41000
+ }
41001
+ return read;
41002
+ }
41003
+ async function listResetCredits(deps, credentialId) {
41004
+ const r = await resettable(deps, credentialId);
41005
+ return { credentialId: r.credential.id, ...await listFor(deps, r) };
41006
+ }
41007
+ async function redeemResetCredit(deps, request2) {
41008
+ const r = await resettable(deps, request2.credentialId);
41009
+ return deps.coord.mutex.withLock(PROBE_LOCK_PREFIX + r.credential.id, PROBE_LOCK_TTL_MS, PROBE_LOCK_WAIT_MS, () => redeemLocked(deps, r, request2));
41010
+ }
41011
+ async function redeemLocked(deps, r, request2) {
41012
+ const available = (await listFor(deps, r)).credits.filter((c) => c.status === "available").sort((a, b) => (a.expiresAt ?? Number.POSITIVE_INFINITY) - (b.expiresAt ?? Number.POSITIVE_INFINITY));
41013
+ const credit = request2.creditId === undefined ? available[0] : available.find((c) => c.id === request2.creditId);
41014
+ if (credit === undefined) {
41015
+ throw new GatewayError("CONFLICT", request2.creditId === undefined ? "no reset credit is available for this account" : "that reset credit is not available");
41016
+ }
41017
+ const secrets = await usageSecretsFor(deps, r.credential);
41018
+ const { windowsReset } = await r.redeem(secrets, { http: deps.http, now: deps.now }, r.credential.providerData, credit.id, crypto.randomUUID());
41019
+ let quotaRefreshed = false;
41020
+ try {
41021
+ quotaRefreshed = await probe(deps, r.credential) !== null;
41022
+ } catch {}
41023
+ return { credentialId: r.credential.id, creditId: credit.id, windowsReset, quotaRefreshed };
41024
+ }
41025
+
40712
41026
  // packages/control/src/quota/poll.ts
40713
41027
  var CONCURRENCY = 4;
40714
41028
  var RATE_LIMIT_COOLDOWN_MS = 180000;
@@ -40716,14 +41030,17 @@ var COOLDOWN_PREFIX = "quota:cooldown:";
40716
41030
  var PROBE_LOCK_PREFIX = "quota:probe:";
40717
41031
  var PROBE_LOCK_TTL_MS = 60000;
40718
41032
  var PROBE_LOCK_WAIT_MS = 30000;
41033
+ async function usageSecretsFor(deps, credential) {
41034
+ const refreshed = credential.hasRefreshToken && credential.expiresAt !== null && credential.expiresAt - SCHEDULER_REFRESH_LEAD_MS <= deps.now() ? await deps.refresh(credential) : null;
41035
+ return refreshed === null ? await credential.openForUsage() : { accessToken: refreshed.accessToken };
41036
+ }
40719
41037
  async function probe(deps, credential) {
40720
41038
  if (credential.authType !== "oauth")
40721
41039
  return null;
40722
41040
  const provider = deps.providers[credential.provider];
40723
41041
  if (provider?.usage === undefined)
40724
41042
  return null;
40725
- const refreshed = credential.hasRefreshToken && credential.expiresAt !== null && credential.expiresAt - SCHEDULER_REFRESH_LEAD_MS <= deps.now() ? await deps.refresh(credential) : null;
40726
- const secrets = refreshed === null ? await credential.openForUsage() : { accessToken: refreshed.accessToken };
41043
+ const secrets = await usageSecretsFor(deps, credential);
40727
41044
  const report = await provider.usage(secrets, { http: deps.http, now: deps.now }, credential.providerData);
40728
41045
  if (report === null || report.windows.length === 0)
40729
41046
  return null;
@@ -40886,6 +41203,12 @@ function quotaOps(deps) {
40886
41203
  outcomes.push(result?.outcome ?? { kind: "failed", credentialId: credential.id, code: "INTERNAL" });
40887
41204
  }
40888
41205
  return { outcomes };
41206
+ },
41207
+ resetCredits: (credentialId) => listResetCredits(deps, credentialId),
41208
+ redeemReset: (request2) => redeemResetCredit(deps, request2),
41209
+ hasResets: (provider) => {
41210
+ const flow = deps.providers[provider];
41211
+ return flow?.resetCredits !== undefined && flow.redeemReset !== undefined;
40889
41212
  }
40890
41213
  };
40891
41214
  }
@@ -57082,6 +57405,12 @@ function adminRoutes(deps) {
57082
57405
  });
57083
57406
  };
57084
57407
  const changed = (topic) => deps.broadcaster?.invalidate(topic);
57408
+ const quotaOrRefuse = () => {
57409
+ if (deps.quota === undefined) {
57410
+ throw new GatewayError("INTERNAL", "quota operations are not available on this process");
57411
+ }
57412
+ return deps.quota;
57413
+ };
57085
57414
  return new Elysia().onError(apiErrorHandler).get("/api/status", async ({ request: request2 }) => {
57086
57415
  const token = readCookie(request2, ADMIN_COOKIE);
57087
57416
  const principal = token === null ? null : await deps.admin.verify(token);
@@ -57170,6 +57499,18 @@ function adminRoutes(deps) {
57170
57499
  changed("res:quota");
57171
57500
  }
57172
57501
  return result;
57502
+ }).get("/api/credentials/:id/resets", async ({ request: request2, params }) => {
57503
+ await requireAdmin(request2, deps.admin);
57504
+ return quotaOrRefuse().resetCredits(params.id);
57505
+ }).post("/api/credentials/:id/resets/redeem", async ({ request: request2, params }) => {
57506
+ await requireAdmin(request2, deps.admin);
57507
+ const raw = await readJsonRecord(request2);
57508
+ if (raw === null)
57509
+ throw new GatewayError("BAD_REQUEST", "body must be a JSON object");
57510
+ const body2 = parseOrThrow(redeemResetSchema, { ...raw, credentialId: params.id });
57511
+ const result = await quotaOrRefuse().redeemReset(body2);
57512
+ changed("res:quota");
57513
+ return result;
57173
57514
  }).patch("/api/credentials/:id", async ({ request: request2, params }) => {
57174
57515
  await requireAdmin(request2, deps.admin);
57175
57516
  await patchCredential(deps, params.id, await readJson(request2));
@@ -57185,7 +57526,10 @@ function adminRoutes(deps) {
57185
57526
  return { models: await listModels(deps.store) };
57186
57527
  }).get("/api/catalog", async ({ request: request2 }) => {
57187
57528
  await requireReader(request2, deps.admin);
57188
- return { providers: providerCatalog(reportCatalogProblem) };
57529
+ const quota = deps.quota;
57530
+ return {
57531
+ providers: providerCatalog(reportCatalogProblem).map((provider) => quota?.hasResets(provider.id) === true ? { ...provider, quotaResets: true } : provider)
57532
+ };
57189
57533
  }).put("/api/models/:id", async ({ request: request2, params }) => {
57190
57534
  await requireAdmin(request2, deps.admin);
57191
57535
  await putModel(deps.store, params.id, await readJson(request2));
@@ -60072,7 +60416,8 @@ async function attempt(opts) {
60072
60416
  http,
60073
60417
  signal,
60074
60418
  ...opts.requestId === undefined ? {} : { requestId: opts.requestId },
60075
- ...opts.autoCache === undefined ? {} : { autoCache: opts.autoCache }
60419
+ ...opts.autoCache === undefined ? {} : { autoCache: opts.autoCache },
60420
+ ...candidate.target.maxOutputTokens === undefined ? {} : { maxOutputTokens: candidate.target.maxOutputTokens }
60076
60421
  });
60077
60422
  }
60078
60423
 
@@ -61054,6 +61399,7 @@ function readToolResult(content) {
61054
61399
  return { content: "" };
61055
61400
  const text = [];
61056
61401
  const images = [];
61402
+ const files = [];
61057
61403
  const native = [];
61058
61404
  for (const part of content) {
61059
61405
  if (typeof part === "string") {
@@ -61073,6 +61419,16 @@ function readToolResult(content) {
61073
61419
  const p = part !== null && typeof part === "object" ? part : undefined;
61074
61420
  const nativeSchema = p?.type !== undefined && TOOL_RESULT_NATIVE.has(p.type) ? nativeSchemas[p.type] : undefined;
61075
61421
  const parsed2 = nativeSchema?.safeParse(part);
61422
+ if (p?.type === "document" && parsed2?.success === true) {
61423
+ const portable = portableDocument(parsed2.data);
61424
+ if (portable !== undefined) {
61425
+ if (typeof portable === "string")
61426
+ text.push(portable);
61427
+ else
61428
+ files.push(portable);
61429
+ continue;
61430
+ }
61431
+ }
61076
61432
  if (p?.type !== undefined && parsed2?.success === true) {
61077
61433
  const { type: _type, cache_control, ...data } = parsed2.data;
61078
61434
  native.push({
@@ -61090,9 +61446,30 @@ function readToolResult(content) {
61090
61446
  content: text.join(`
61091
61447
  `),
61092
61448
  ...images.length > 0 && { images },
61449
+ ...files.length > 0 && { files },
61093
61450
  ...native.length > 0 && { native }
61094
61451
  };
61095
61452
  }
61453
+ function portableDocument(doc2) {
61454
+ if (doc2.citations !== undefined && doc2.citations !== null || doc2.context !== undefined && doc2.context !== null || doc2.cache_control !== undefined && doc2.cache_control !== null) {
61455
+ return;
61456
+ }
61457
+ const source = doc2.source;
61458
+ const title = typeof doc2.title === "string" ? doc2.title : undefined;
61459
+ if (source.type === "base64" && typeof source.data === "string") {
61460
+ return {
61461
+ type: "file",
61462
+ mediaType: "application/pdf",
61463
+ data: source.data,
61464
+ ...title !== undefined && { filename: title }
61465
+ };
61466
+ }
61467
+ if (source.type === "text" && typeof source.data === "string") {
61468
+ return title === undefined ? source.data : `${title}
61469
+ ${source.data}`;
61470
+ }
61471
+ return;
61472
+ }
61096
61473
  function toIrBlock(b) {
61097
61474
  switch (b.type) {
61098
61475
  case "text":
@@ -63080,7 +63457,7 @@ function createRing(limits = DEFAULT_RING_LIMITS) {
63080
63457
  }
63081
63458
 
63082
63459
  // apps/gateway/src/version.ts
63083
- var VERSION = "0.12.11";
63460
+ var VERSION = "0.12.13";
63084
63461
 
63085
63462
  // apps/gateway/src/app.ts
63086
63463
  var ADMIN_SESSION_TTL_MS = 12 * 60 * 60 * 1000;