omnigateway 0.4.10 → 0.4.12

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 (25) hide show
  1. package/bin/omni.js +198 -25
  2. package/gateway.js +225 -29
  3. package/package.json +1 -1
  4. package/public/assets/{CopyValue-CcE2vXiA.js → CopyValue-By5BAgv7.js} +1 -1
  5. package/public/assets/{Rack-Bbk1hAor.js → Rack-fDZClWZL.js} +1 -1
  6. package/public/assets/{Toggle-DGsa7LWV.js → Toggle-ClEeOh0F.js} +1 -1
  7. package/public/assets/{TokenBreakdown-Do_4AmfF.js → TokenBreakdown-D70VeZ2N.js} +1 -1
  8. package/public/assets/{_app-UpbTpRCt.js → _app-CDPKnQ72.js} +1 -1
  9. package/public/assets/{_app.accounts-CPG3iaDT.js → _app.accounts-Dz0ox4Br.js} +1 -1
  10. package/public/assets/{_app.console-BaGTRPEe.js → _app.console-hPUmmYjp.js} +1 -1
  11. package/public/assets/{_app.database-DA2aB-ij.js → _app.database-DGtP4NdG.js} +1 -1
  12. package/public/assets/{_app.index-CDjVA5Ix.js → _app.index-COcCAmbH.js} +1 -1
  13. package/public/assets/{_app.keys-Bf8HiloS.js → _app.keys-yTXTbKTA.js} +1 -1
  14. package/public/assets/{_app.logs-DTF9RDhN.js → _app.logs-BhMvO_Fx.js} +1 -1
  15. package/public/assets/{_app.models-B6_6bC3z.js → _app.models-0S3rurIl.js} +1 -1
  16. package/public/assets/{_app.plugins._pluginId-Dl_jYunC.js → _app.plugins._pluginId-B-ZDQNPU.js} +1 -1
  17. package/public/assets/_app.settings-DTnFwTeA.js +46 -0
  18. package/public/assets/{_app.usage-D4TLCm9J.js → _app.usage-C2-VLiq9.js} +1 -1
  19. package/public/assets/{index-CJZIRJ43.js → index-COwhxKU7.js} +2 -2
  20. package/public/assets/{login-Bu6texfZ.js → login-DjfMomJJ.js} +1 -1
  21. package/public/assets/plus-UDQ_BTEr.js +1 -0
  22. package/public/assets/{trash-2-5CCUKFQ0.js → trash-2-U2ViYZum.js} +1 -1
  23. package/public/index.html +1 -1
  24. package/public/assets/_app.settings-Dh6lrqws.js +0 -46
  25. package/public/assets/plus-Z1kRC6KA.js +0 -1
package/bin/omni.js CHANGED
@@ -233,6 +233,7 @@ var RETRYABLE = {
233
233
  BAD_REQUEST: false,
234
234
  CONFLICT: false,
235
235
  CONTENT_FILTER: false,
236
+ FINGERPRINT_REFUSED: false,
236
237
  NO_CANDIDATES: false,
237
238
  ALL_CANDIDATES_FAILED: false,
238
239
  INTERNAL: false
@@ -249,6 +250,7 @@ class GatewayError extends Error {
249
250
  provider;
250
251
  upstreamStatus;
251
252
  retryAfterMs;
253
+ degradations;
252
254
  constructor(code, message, opts) {
253
255
  super(message, opts?.cause === undefined ? undefined : { cause: opts.cause });
254
256
  this.name = "GatewayError";
@@ -257,6 +259,7 @@ class GatewayError extends Error {
257
259
  this.provider = opts?.provider;
258
260
  this.upstreamStatus = opts?.status;
259
261
  this.retryAfterMs = opts?.retryAfterMs;
262
+ this.degradations = [...opts?.degradations ?? []];
260
263
  }
261
264
  }
262
265
  // packages/ir/src/logger.ts
@@ -1290,6 +1293,82 @@ function parseRecord(record) {
1290
1293
  `) };
1291
1294
  }
1292
1295
 
1296
+ // packages/providers/src/anthropic/cloak.ts
1297
+ var ALREADY_CLOAKED = /^[A-Z][A-Za-z0-9]*$/;
1298
+ var MCP_PREFIX = "mcp__";
1299
+ function isExempt(name) {
1300
+ return ALREADY_CLOAKED.test(name) || name.startsWith(MCP_PREFIX);
1301
+ }
1302
+ var MAX_ALIAS = 128;
1303
+ var SUFFIX_LENGTH = 6;
1304
+ function aliasFor(name) {
1305
+ const joined = name.split(/[^A-Za-z0-9]+/).filter((s) => s.length > 0).map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join("");
1306
+ if (joined === "")
1307
+ return { base: "Tool", forced: true };
1308
+ if (joined.length > MAX_ALIAS) {
1309
+ return { base: joined.slice(0, MAX_ALIAS - SUFFIX_LENGTH), forced: true };
1310
+ }
1311
+ return { base: joined, forced: false };
1312
+ }
1313
+ function clientToolNames(request2) {
1314
+ const renamable = new Set;
1315
+ const reserved = new Set;
1316
+ const add = (name) => {
1317
+ (isExempt(name) ? reserved : renamable).add(name);
1318
+ };
1319
+ for (const tool of request2.tools ?? []) {
1320
+ if (tool.provider === "custom")
1321
+ add(tool.name);
1322
+ }
1323
+ for (const message of request2.messages) {
1324
+ for (const block of message.content) {
1325
+ if (block.type === "toolUse")
1326
+ add(block.name);
1327
+ }
1328
+ }
1329
+ if (request2.toolChoice?.type === "tool")
1330
+ add(request2.toolChoice.name);
1331
+ return { renamable: [...renamable], reserved: [...reserved] };
1332
+ }
1333
+ function suffixFor(name) {
1334
+ const digest = Bun.hash.xxHash64(Buffer.from(name, "utf8")) & 0xffffffn;
1335
+ const hex = digest.toString(16).padStart(SUFFIX_LENGTH, "0");
1336
+ return hex.charAt(0).toUpperCase() + hex.slice(1);
1337
+ }
1338
+ function buildToolCloak(request2) {
1339
+ const { renamable, reserved } = clientToolNames(request2);
1340
+ const claims = new Map;
1341
+ const claim = (name) => {
1342
+ claims.set(name, (claims.get(name) ?? 0) + 1);
1343
+ };
1344
+ for (const tool of request2.tools ?? []) {
1345
+ if (tool.provider === "anthropic" && tool.name !== "")
1346
+ claim(tool.name);
1347
+ }
1348
+ for (const name of reserved)
1349
+ claim(name);
1350
+ const bases = new Map;
1351
+ for (const name of renamable) {
1352
+ const derived = aliasFor(name);
1353
+ bases.set(name, derived);
1354
+ claim(derived.base);
1355
+ }
1356
+ const toWire = new Map;
1357
+ const fromWire = new Map;
1358
+ for (const [name, { base, forced }] of bases) {
1359
+ const alias = forced || (claims.get(base) ?? 0) > 1 ? base + suffixFor(name) : base;
1360
+ toWire.set(name, alias);
1361
+ fromWire.set(alias, name);
1362
+ }
1363
+ return toWire.size === 0 ? null : { toWire, fromWire };
1364
+ }
1365
+ function cloakName(cloak, name) {
1366
+ return cloak?.toWire.get(name) ?? name;
1367
+ }
1368
+ function uncloakName(cloak, name) {
1369
+ return cloak?.fromWire.get(name) ?? name;
1370
+ }
1371
+
1293
1372
  // packages/providers/src/anthropic/tools.ts
1294
1373
  var COMMON = ["cache_control", "strict", "defer_loading", "allowed_callers"];
1295
1374
  var COMMON_WITH_EXAMPLES = [...COMMON, "input_examples"];
@@ -1524,6 +1603,14 @@ var ERROR_TYPE = {
1524
1603
  invalid_request_error: "BAD_REQUEST",
1525
1604
  api_error: "UPSTREAM"
1526
1605
  };
1606
+ var FINGERPRINT_PHRASES = ["out of extra usage", "draw from extra usage"];
1607
+ function isFingerprintMessage(message) {
1608
+ const lowered = message.toLowerCase();
1609
+ return FINGERPRINT_PHRASES.some((phrase) => lowered.includes(phrase));
1610
+ }
1611
+ function isFingerprintRefusal(type, message) {
1612
+ return type === "invalid_request_error" && isFingerprintMessage(message);
1613
+ }
1527
1614
  function json(data) {
1528
1615
  try {
1529
1616
  const v = JSON.parse(data);
@@ -1532,7 +1619,8 @@ function json(data) {
1532
1619
  return null;
1533
1620
  }
1534
1621
  }
1535
- async function* decodeAnthropic(messages) {
1622
+ async function* decodeAnthropic(messages, opts = {}) {
1623
+ const cloak = opts.cloak ?? null;
1536
1624
  let inputTokens = 0;
1537
1625
  let cacheReadTokens = 0;
1538
1626
  let cacheWriteTokens = 0;
@@ -1578,7 +1666,11 @@ async function* decodeAnthropic(messages) {
1578
1666
  yield {
1579
1667
  type: "blockStart",
1580
1668
  index,
1581
- block: { type: "toolUse", id: String(cb.id), name: String(cb.name) }
1669
+ block: {
1670
+ type: "toolUse",
1671
+ id: String(cb.id),
1672
+ name: uncloakName(cloak, String(cb.name))
1673
+ }
1582
1674
  };
1583
1675
  else if (cb.type !== undefined && ANTHROPIC_NATIVE_BLOCK_TYPES.has(cb.type)) {
1584
1676
  nativeBlocks.add(index);
@@ -1681,13 +1773,10 @@ async function* decodeAnthropic(messages) {
1681
1773
  break;
1682
1774
  case "error": {
1683
1775
  terminal = true;
1684
- const code = ERROR_TYPE[String(d.error?.type)] ?? "UPSTREAM";
1685
- yield {
1686
- type: "error",
1687
- code,
1688
- message: String(d.error?.message ?? "upstream error"),
1689
- retryable: RETRYABLE[code]
1690
- };
1776
+ const type = String(d.error?.type);
1777
+ const message = String(d.error?.message ?? "upstream error");
1778
+ const code = isFingerprintRefusal(type, message) ? "FINGERPRINT_REFUSED" : ERROR_TYPE[type] ?? "UPSTREAM";
1779
+ yield { type: "error", code, message, retryable: RETRYABLE[code] };
1691
1780
  break;
1692
1781
  }
1693
1782
  default:
@@ -1714,7 +1803,7 @@ function wireCacheControl(c) {
1714
1803
  function isReplayableThinking(b) {
1715
1804
  return b.type !== "thinking" || b.signature !== undefined && b.signature !== "";
1716
1805
  }
1717
- function encodeBlock(b) {
1806
+ function encodeBlock(b, cloak) {
1718
1807
  const cache = wireCacheControl(cacheControlOf(b));
1719
1808
  switch (b.type) {
1720
1809
  case "text":
@@ -1733,7 +1822,13 @@ function encodeBlock(b) {
1733
1822
  case "thinking":
1734
1823
  return { type: "thinking", thinking: b.text, signature: b.signature };
1735
1824
  case "toolUse":
1736
- return { type: "tool_use", id: b.id, name: b.name, input: b.input, ...cache };
1825
+ return {
1826
+ type: "tool_use",
1827
+ id: b.id,
1828
+ name: cloakName(cloak, b.name),
1829
+ input: b.input,
1830
+ ...cache
1831
+ };
1737
1832
  case "toolResult":
1738
1833
  return {
1739
1834
  type: "tool_result",
@@ -1746,12 +1841,12 @@ function encodeBlock(b) {
1746
1841
  return { ...b.data, type: b.blockType, ...cache };
1747
1842
  }
1748
1843
  }
1749
- function encodeSystemTurn(content) {
1844
+ function encodeSystemTurn(content, cloak) {
1750
1845
  if (content.every((block) => block.type === "text")) {
1751
1846
  return content.map((block) => block.text).join(`
1752
1847
  `);
1753
1848
  }
1754
- return content.map(encodeBlock);
1849
+ return content.map((block) => encodeBlock(block, cloak));
1755
1850
  }
1756
1851
  function systemCacheControl(req) {
1757
1852
  const cacheable = req.messages.flatMap((message) => message.content.flatMap((block) => block.type === "thinking" ? [] : [{ role: message.role, block }]));
@@ -1763,7 +1858,7 @@ function systemCacheControl(req) {
1763
1858
  lost: markedSystemBlocks.length > (promoted === undefined ? 0 : 1)
1764
1859
  };
1765
1860
  }
1766
- function encodeTool(t) {
1861
+ function encodeTool(t, cloak) {
1767
1862
  if (t.provider === "anthropic") {
1768
1863
  return {
1769
1864
  type: t.type,
@@ -1773,14 +1868,14 @@ function encodeTool(t) {
1773
1868
  };
1774
1869
  }
1775
1870
  return {
1776
- name: t.name,
1871
+ name: cloakName(cloak, t.name),
1777
1872
  ...t.description === undefined ? {} : { description: t.description },
1778
1873
  input_schema: t.inputSchema,
1779
1874
  ...t.options ?? {},
1780
1875
  ...wireCacheControl(t.cacheControl)
1781
1876
  };
1782
1877
  }
1783
- function encodeToolChoice(c) {
1878
+ function encodeToolChoice(c, cloak) {
1784
1879
  switch (c.type) {
1785
1880
  case "auto":
1786
1881
  return { type: "auto" };
@@ -1789,7 +1884,7 @@ function encodeToolChoice(c) {
1789
1884
  case "none":
1790
1885
  return { type: "none" };
1791
1886
  case "tool":
1792
- return { type: "tool", name: c.name };
1887
+ return { type: "tool", name: cloakName(cloak, c.name) };
1793
1888
  }
1794
1889
  }
1795
1890
  function isRecord(value) {
@@ -1831,7 +1926,59 @@ function stripUnsupportedEdits(body, note2) {
1831
1926
  }
1832
1927
  body.context_management = { ...config, edits: kept };
1833
1928
  }
1929
+ var AUTO_CACHE_MIN_TOKENS = 1024;
1930
+ function hasVendorCacheControl(req) {
1931
+ const anthropic2 = req.vendor?.anthropic;
1932
+ return typeof anthropic2 === "object" && anthropic2 !== null && "cache_control" in anthropic2;
1933
+ }
1934
+ var CACHEABLE_WIRE_BLOCKS = new Set(["text", "image", "tool_use", "tool_result", "document"]);
1935
+ function lastCacheableHistoryBlock(messages) {
1936
+ for (let m = messages.length - 1;m >= 0; m--) {
1937
+ const message = messages[m];
1938
+ if (!isRecord(message) || !Array.isArray(message.content))
1939
+ continue;
1940
+ for (let b = message.content.length - 1;b >= 0; b--) {
1941
+ const block = message.content[b];
1942
+ if (!isRecord(block))
1943
+ continue;
1944
+ if (typeof block.type === "string" && CACHEABLE_WIRE_BLOCKS.has(block.type))
1945
+ return block;
1946
+ }
1947
+ }
1948
+ return;
1949
+ }
1950
+ function addAutoCacheBreakpoints(body, req, note2) {
1951
+ if (estimateCachedInputTokens(req) !== 0 || hasVendorCacheControl(req))
1952
+ return;
1953
+ let markedPrefix = 0;
1954
+ const worthAMarker = (prefix) => prefix - markedPrefix >= AUTO_CACHE_MIN_TOKENS;
1955
+ let stablePrefixMarked = false;
1956
+ const toolsPrefix = estimateInputTokens({ ...req, messages: [], system: [] });
1957
+ const lastTool = body.tools?.at(-1);
1958
+ if (lastTool !== undefined && worthAMarker(toolsPrefix)) {
1959
+ lastTool.cache_control = { type: "ephemeral" };
1960
+ markedPrefix = toolsPrefix;
1961
+ stablePrefixMarked = true;
1962
+ }
1963
+ const systemPrefix = estimateInputTokens({ ...req, messages: [] });
1964
+ const lastSystem = body.system?.at(-1);
1965
+ if (lastSystem !== undefined && worthAMarker(systemPrefix)) {
1966
+ lastSystem.cache_control = { type: "ephemeral" };
1967
+ markedPrefix = systemPrefix;
1968
+ stablePrefixMarked = true;
1969
+ }
1970
+ if (stablePrefixMarked)
1971
+ note2("anthropic:cache-breakpoint-added");
1972
+ if (!worthAMarker(estimateInputTokens(req)))
1973
+ return;
1974
+ const lastHistory = lastCacheableHistoryBlock(body.messages);
1975
+ if (lastHistory === undefined)
1976
+ return;
1977
+ lastHistory.cache_control = { type: "ephemeral" };
1978
+ note2("anthropic:history-cache-breakpoint-added");
1979
+ }
1834
1980
  function toWire(req, model, opts) {
1981
+ const cloak = opts.cloak ?? null;
1835
1982
  const degradations = [];
1836
1983
  const note2 = (d) => {
1837
1984
  if (!degradations.includes(d))
@@ -1842,6 +1989,8 @@ function toWire(req, model, opts) {
1842
1989
  system = [{ type: "text", text: OAUTH_IDENTITY }, ...system ?? []];
1843
1990
  note2("anthropic:oauth-system-prefix");
1844
1991
  }
1992
+ if (cloak !== null)
1993
+ note2("anthropic:tool-names-cloaked");
1845
1994
  const systemCache = systemCacheControl(req);
1846
1995
  if (systemCache.lost)
1847
1996
  note2("anthropic:system-turn-cache-control-dropped");
@@ -1854,9 +2003,9 @@ function toWire(req, model, opts) {
1854
2003
  note2("anthropic:unsigned-thinking-dropped");
1855
2004
  if (replayable.length === 0)
1856
2005
  return [];
1857
- return [{ role: m.role, content: replayable.map(encodeBlock) }];
2006
+ return [{ role: m.role, content: replayable.map((b) => encodeBlock(b, cloak)) }];
1858
2007
  }
1859
- return [{ role: m.role, content: encodeSystemTurn(m.content) }];
2008
+ return [{ role: m.role, content: encodeSystemTurn(m.content, cloak) }];
1860
2009
  }),
1861
2010
  max_tokens: req.maxTokens ?? 4096,
1862
2011
  stream: req.stream,
@@ -1874,9 +2023,11 @@ function toWire(req, model, opts) {
1874
2023
  if (req.stopSequences !== undefined)
1875
2024
  body.stop_sequences = req.stopSequences;
1876
2025
  if (req.tools !== undefined)
1877
- body.tools = req.tools.map(encodeTool);
2026
+ body.tools = req.tools.map((t) => encodeTool(t, cloak));
1878
2027
  if (req.toolChoice !== undefined)
1879
- body.tool_choice = encodeToolChoice(req.toolChoice);
2028
+ body.tool_choice = encodeToolChoice(req.toolChoice, cloak);
2029
+ if (opts.autoCache === true)
2030
+ addAutoCacheBreakpoints(body, req, note2);
1880
2031
  if (req.reasoning !== undefined) {
1881
2032
  switch (req.reasoning.mode) {
1882
2033
  case "adaptive":
@@ -1919,7 +2070,12 @@ var anthropicAdapter = {
1919
2070
  capabilities: PROVIDER_CAPABILITIES.anthropic,
1920
2071
  async send(req) {
1921
2072
  const oauth = req.credentials.accessToken !== null;
1922
- const { body, degradations } = toWire(req.request, req.model, { oauth });
2073
+ const cloak = oauth ? buildToolCloak(req.request) : null;
2074
+ const { body, degradations } = toWire(req.request, req.model, {
2075
+ oauth,
2076
+ cloak,
2077
+ autoCache: req.autoCache === true
2078
+ });
1923
2079
  const withSystem = {
1924
2080
  ...body,
1925
2081
  system: applyAnthropicSystem(body.system ?? []),
@@ -1963,11 +2119,25 @@ var anthropicAdapter = {
1963
2119
  body: bodyString,
1964
2120
  signal: req.signal
1965
2121
  });
1966
- if (res.status < 200 || res.status >= 300)
1967
- throw await httpError(res, "anthropic");
2122
+ if (res.status < 200 || res.status >= 300) {
2123
+ const error = await httpError(res, "anthropic");
2124
+ if (res.status === 400 && isFingerprintMessage(error.message)) {
2125
+ throw new GatewayError("FINGERPRINT_REFUSED", error.message, {
2126
+ provider: "anthropic",
2127
+ degradations: notes,
2128
+ ...error.upstreamStatus === undefined ? {} : { status: error.upstreamStatus },
2129
+ ...error.retryAfterMs === undefined ? {} : { retryAfterMs: error.retryAfterMs }
2130
+ });
2131
+ }
2132
+ throw error;
2133
+ }
1968
2134
  if (res.body === null)
1969
2135
  throw new GatewayError("UPSTREAM", "empty response body", { provider: "anthropic" });
1970
- return { events: decodeAnthropic(parseSse(res.body)), degradations: notes };
2136
+ return {
2137
+ events: decodeAnthropic(parseSse(res.body), { cloak }),
2138
+ degradations: notes,
2139
+ ...cloak === null ? {} : { cloakedTools: cloak.toWire.size }
2140
+ };
1971
2141
  }
1972
2142
  };
1973
2143
  // packages/providers/src/kimi/decode.ts
@@ -17998,6 +18168,7 @@ var settingsSchema = exports_external.object({
17998
18168
  logRetentionDays: exports_external.number().int().min(1),
17999
18169
  quotaPollIntervalMs: exports_external.number().int().min(0),
18000
18170
  rtkEnabled: exports_external.boolean(),
18171
+ autoCacheEnabled: exports_external.boolean(),
18001
18172
  bodyLoggingEnabled: exports_external.boolean(),
18002
18173
  bodyLoggingCaptureStreamChunks: exports_external.boolean(),
18003
18174
  snapshotKeepLatest: retentionSchema.shape.keepLatest.optional(),
@@ -18225,6 +18396,7 @@ var DEFAULT_SETTINGS = {
18225
18396
  logRetentionDays: 30,
18226
18397
  quotaPollIntervalMs: 300000,
18227
18398
  rtkEnabled: false,
18399
+ autoCacheEnabled: true,
18228
18400
  bodyLoggingEnabled: false,
18229
18401
  bodyLoggingCaptureStreamChunks: false,
18230
18402
  snapshotKeepLatest: 5,
@@ -18821,6 +18993,7 @@ function createConfigRepo(db, emit2 = () => {}) {
18821
18993
  ...DEFAULT_SETTINGS,
18822
18994
  ...stored,
18823
18995
  rtkEnabled: stored.rtkEnabled === true,
18996
+ autoCacheEnabled: stored.autoCacheEnabled === undefined ? true : stored.autoCacheEnabled === true,
18824
18997
  bodyLoggingEnabled: stored.bodyLoggingEnabled === true,
18825
18998
  bodyLoggingCaptureStreamChunks: stored.bodyLoggingCaptureStreamChunks === true,
18826
18999
  weights: knownWeights(stored.weights)