@tool-bridge/server 0.16.0 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/dist/{airtable-S3T4TAN7.js → airtable-NOSOMOVB.js} +106 -114
  2. package/dist/{alt_text_generator_ai-4DIRIDKL.js → alt_text_generator_ai-BHIJ4LW5.js} +25 -16
  3. package/dist/{amap-LGVGNPML.js → amap-QRLP4TWZ.js} +114 -123
  4. package/dist/{anthropic-27RFZO35.js → anthropic-IEOI36EV.js} +34 -56
  5. package/dist/{apify-6WLYAIAS.js → apify-3CCYTQVK.js} +31 -49
  6. package/dist/{brave_search-K2SVJ66F.js → brave_search-PZNYDQG7.js} +52 -77
  7. package/dist/chunk-JXHMDBAY.js +45 -0
  8. package/dist/chunk-LMLX3DJF.js +50 -0
  9. package/dist/{chunk-YB2FLNWI.js → chunk-RVWZN3CI.js} +2103 -1775
  10. package/dist/{chunk-BB6ZLMTU.js → chunk-TLNUIPFZ.js} +492 -300
  11. package/dist/chunk-U5UHT7CX.js +977 -0
  12. package/dist/chunk-U67V476Y.js +35 -0
  13. package/dist/chunk-WW2IMPQK.js +283 -0
  14. package/dist/{chunk-VK3V2WTY.js → chunk-YASUMV2K.js} +4 -6
  15. package/dist/{circleci-WV3ITU7Q.js → circleci-VSJ4O5FC.js} +36 -55
  16. package/dist/{clerk-NFQEFKS4.js → clerk-CC2JZBZI.js} +60 -80
  17. package/dist/{cloudflare_dns-2RK5ASBJ.js → cloudflare_dns-PJEBSEYQ.js} +90 -113
  18. package/dist/{cohere-5KEW7LWT.js → cohere-KBACYSPF.js} +33 -49
  19. package/dist/{confluence-SZE63S46.js → confluence-2PX3O7G5.js} +79 -115
  20. package/dist/{convertapi-QPG2JC5K.js → convertapi-BVOTD2PJ.js} +13 -16
  21. package/dist/{currencyapi-UO2APQRY.js → currencyapi-6ZQ2VNQ7.js} +30 -53
  22. package/dist/{deepseek-LJELIMM3.js → deepseek-MB3WVVTB.js} +30 -38
  23. package/dist/{docker_hub-2MFXSBOF.js → docker_hub-7CLQL2IJ.js} +141 -157
  24. package/dist/{dropbox-GQYNTTVA.js → dropbox-VFYDVUNK.js} +134 -141
  25. package/dist/{dub-KI2LHXST.js → dub-QN3EETJY.js} +61 -93
  26. package/dist/{e2b-WO6ISY3C.js → e2b-NKC3Y776.js} +39 -69
  27. package/dist/{exa-IZ7B3BPT.js → exa-KKZ6F25K.js} +49 -77
  28. package/dist/{fal_ai-LTMF36GJ.js → fal_ai-25LYJD2O.js} +37 -44
  29. package/dist/{feishu-WM7SLSFD.js → feishu-NRT55B3Q.js} +4 -6
  30. package/dist/{feishu_custom_bot-66W3MXH2.js → feishu_custom_bot-3W3XXUG4.js} +4 -5
  31. package/dist/{figma-2Z274VQZ.js → figma-4FLP35TC.js} +56 -81
  32. package/dist/{firehydrant-IFI4R65V.js → firehydrant-BLXPLZ3X.js} +40 -53
  33. package/dist/{fixer-BCCZEB3D.js → fixer-4OR62TGE.js} +31 -43
  34. package/dist/{fly-755FXYB5.js → fly-MYCKOZZK.js} +50 -66
  35. package/dist/{front-4FZKKXXK.js → front-3DFYVMF3.js} +43 -66
  36. package/dist/{geocodio-WYKDJ3DP.js → geocodio-CXMD6VKA.js} +37 -63
  37. package/dist/{ghost-5BNQTCOH.js → ghost-4UUE737W.js} +51 -57
  38. package/dist/{github-ULELF5VX.js → github-WFS2ON2N.js} +48 -41
  39. package/dist/{gmail-G34WT64J.js → gmail-KW7FXA7A.js} +26 -36
  40. package/dist/{googlecalendar-BQU255SC.js → googlecalendar-AMH5JQMC.js} +57 -78
  41. package/dist/{googledocs-HPCNQXYJ.js → googledocs-R5VA6CKD.js} +14 -22
  42. package/dist/{grafana-VOV24FIC.js → grafana-IT6DWIVB.js} +95 -122
  43. package/dist/{graphhopper-D5RXW6AP.js → graphhopper-TYFDJZWC.js} +32 -46
  44. package/dist/index.d.ts +57 -50
  45. package/dist/index.js +4 -3
  46. package/dist/{ip2proxy-DAYO7EKZ.js → ip2proxy-GJ4HXVXO.js} +35 -42
  47. package/dist/{ipgeolocation_io-XD4PSLII.js → ipgeolocation_io-OAGR6PRF.js} +40 -60
  48. package/dist/{ipqualityscore-K27QEAWK.js → ipqualityscore-BCKAMDGL.js} +30 -42
  49. package/dist/{jina_ai-E6UXFV2P.js → jina_ai-N3NXRVIZ.js} +32 -58
  50. package/dist/{jira-ZDSXGQ6W.js → jira-CHLBKWLO.js} +116 -126
  51. package/dist/{langsmith-TIFJRREW.js → langsmith-OIKOTPY3.js} +101 -121
  52. package/dist/{lemlist-DASEMJMA.js → lemlist-VAKYPKS3.js} +57 -68
  53. package/dist/{linear-KE6UP4SP.js → linear-Q6QTPJ5R.js} +109 -118
  54. package/dist/{logsnag-IMNDN4R5.js → logsnag-SQOQBTES.js} +31 -48
  55. package/dist/main.js +103 -102
  56. package/dist/{mattermost-HHHMUXQA.js → mattermost-G2KBEICM.js} +45 -62
  57. package/dist/{mem0-D2FGGOIY.js → mem0-D2FPLYDX.js} +72 -98
  58. package/dist/{memos-4OVIGFPH.js → memos-76PTWV5V.js} +68 -122
  59. package/dist/{metabase-33WCX5YD.js → metabase-TWSIDVBM.js} +47 -60
  60. package/dist/{mistral_ai-QIMZ2JYL.js → mistral_ai-TP7TQUEJ.js} +35 -40
  61. package/dist/{mother_duck-M6VWS2VH.js → mother_duck-UXY5THYU.js} +42 -62
  62. package/dist/{ngrok-Z2PKQBHH.js → ngrok-RZW2ISJK.js} +42 -58
  63. package/dist/{notes-SS4RPC4K.js → notes-B2I6FWK2.js} +3 -5
  64. package/dist/{notion-FJCNQ6I7.js → notion-QOKRUE6M.js} +83 -97
  65. package/dist/{open_exchange_rates-WU57WTT5.js → open_exchange_rates-ODLFWEJ7.js} +35 -39
  66. package/dist/{openai-JODZ4GKT.js → openai-ZPBPPPGT.js} +51 -55
  67. package/dist/{opengraph_io-SQRAUSV5.js → opengraph_io-EOI5UJKT.js} +61 -79
  68. package/dist/{openrouter-Q5XXEJZ7.js → openrouter-BUWLF3BG.js} +41 -55
  69. package/dist/{outline-RT2EHJ2X.js → outline-NXS3QRXO.js} +89 -104
  70. package/dist/{paddle-OF2V7GAC.js → paddle-T4MSKQ76.js} +34 -49
  71. package/dist/{perplexity-LNZEWLHG.js → perplexity-WW5N2LW7.js} +33 -50
  72. package/dist/{pinecone-JSJIXZYN.js → pinecone-RY5AZPQM.js} +65 -91
  73. package/dist/{pipedrive-D4CKVUXR.js → pipedrive-OHYQNZTU.js} +37 -59
  74. package/dist/{polar-M7ZYP6UR.js → polar-XZIAHXS5.js} +43 -53
  75. package/dist/{posthog-YV7CZOH4.js → posthog-DTPTWORY.js} +58 -77
  76. package/dist/{postmark-KYHLECRG.js → postmark-F4UCQKC3.js} +52 -71
  77. package/dist/{prerender-HCMHBKV2.js → prerender-P3Y2MLIC.js} +32 -50
  78. package/dist/{pubmed-WYVLCCN3.js → pubmed-RHU3GXFB.js} +28 -60
  79. package/dist/{railway-TWIRD5KR.js → railway-VB6SRLI6.js} +32 -39
  80. package/dist/{readwise-UZ467IQ7.js → readwise-DIMSKJZR.js} +62 -78
  81. package/dist/{render-MECUC5CC.js → render-XCCDCEEK.js} +48 -64
  82. package/dist/{replicate-A5MEK3SW.js → replicate-IUEOQ4JC.js} +41 -58
  83. package/dist/{resend-BC6EAWJQ.js → resend-N5MJZH5E.js} +27 -37
  84. package/dist/{rootly-ZM3QDUIS.js → rootly-25T4NBTU.js} +64 -76
  85. package/dist/{scrapfly-WAML42QJ.js → scrapfly-PK4XFXUA.js} +45 -51
  86. package/dist/{scrapingbee-DG7PET3V.js → scrapingbee-ITPBMWQU.js} +25 -33
  87. package/dist/{screenshot_fyi-HY6WTHIO.js → screenshot_fyi-5U6ZYPKR.js} +29 -47
  88. package/dist/{semantic_scholar-C5IZA7IP.js → semantic_scholar-BJGCI2MU.js} +37 -56
  89. package/dist/{sentry-OKBPSTDM.js → sentry-63IC263P.js} +66 -85
  90. package/dist/{shodan-PPC6DYU4.js → shodan-2WBIFHFN.js} +42 -53
  91. package/dist/{shopify-EWGUHBXO.js → shopify-XLLJRAGM.js} +32 -49
  92. package/dist/{stripe-6RPDPC5W.js → stripe-WLVCY3UN.js} +4 -5
  93. package/dist/{supabase-SK7DQ42N.js → supabase-BKNZ35ER.js} +69 -88
  94. package/dist/{tavily-YCG5VQMH.js → tavily-YFSDEUTL.js} +37 -62
  95. package/dist/{telegram-2OES5FYB.js → telegram-FC35W74G.js} +168 -177
  96. package/dist/{telnyx-POOSBBR4.js → telnyx-MI32XZUG.js} +30 -50
  97. package/dist/{todoist-M7YD6YSS.js → todoist-4ZFJKZC6.js} +77 -89
  98. package/dist/{trello-IS6V5W3E.js → trello-UOGFNMK4.js} +108 -122
  99. package/dist/{turso-RCFHUFVH.js → turso-YTSTW3ZS.js} +52 -64
  100. package/dist/{twilio-OS2RXFGO.js → twilio-XAJDFUQH.js} +48 -55
  101. package/dist/{umami-PQ2SJ2LN.js → umami-ZVIUBPAI.js} +49 -69
  102. package/dist/{unsplash-C6BPZO4E.js → unsplash-IU3PLDNS.js} +35 -52
  103. package/dist/{upstash_redis-WH6UER7H.js → upstash_redis-3EYJW7SY.js} +28 -40
  104. package/dist/{uptimerobot-M3YZGS6Z.js → uptimerobot-PJG2ASRU.js} +11 -12
  105. package/dist/{v2ex-R4JWTEHN.js → v2ex-KFQWWGFC.js} +36 -61
  106. package/dist/{vercel-FZVYUOQD.js → vercel-I2ZDOQRL.js} +124 -150
  107. package/dist/{webapi-VLM4IKVB.js → webapi-GW5QXWXE.js} +1 -1
  108. package/dist/{wolfram_alpha_api-2KOLO5DC.js → wolfram_alpha_api-BNXOJMB6.js} +26 -34
  109. package/dist/{wordpress-XRWGO6LG.js → wordpress-36D7BSMP.js} +87 -104
  110. package/dist/{workos-WR4NKOYL.js → workos-6X4JJRRC.js} +37 -56
  111. package/dist/{zhihu-BKZIB3WA.js → zhihu-CIXKCHIU.js} +35 -57
  112. package/package.json +5 -5
  113. package/dist/chunk-2O27H4Y2.js +0 -183
  114. package/dist/chunk-GKX72JMJ.js +0 -378
  115. package/dist/chunk-MLKGABMK.js +0 -9
@@ -1,113 +1,95 @@
1
+ import {
2
+ createProviderHttpClient
3
+ } from "./chunk-WW2IMPQK.js";
4
+ import {
5
+ asJsonObject,
6
+ booleanValue,
7
+ compactDefined,
8
+ integerValue,
9
+ trimmedText
10
+ } from "./chunk-JXHMDBAY.js";
1
11
  import {
2
12
  createProviderPlugin,
3
13
  requireApiKey,
4
14
  upstreamError
5
- } from "./chunk-VK3V2WTY.js";
15
+ } from "./chunk-YASUMV2K.js";
6
16
  import {
7
- assertPublicHttpUrl,
8
- guardedFetch
9
- } from "./chunk-2O27H4Y2.js";
10
- import "./chunk-GKX72JMJ.js";
17
+ assertPublicHttpUrl
18
+ } from "./chunk-U5UHT7CX.js";
11
19
  import {
12
20
  TBError,
13
21
  external_exports
14
- } from "./chunk-YB2FLNWI.js";
15
- import "./chunk-MLKGABMK.js";
22
+ } from "./chunk-RVWZN3CI.js";
23
+ import "./chunk-U67V476Y.js";
16
24
 
17
25
  // ../plugins/src/opengraph_io/api.ts
18
26
  var SERVICE = "opengraph_io";
19
27
  var API_BASE = "https://opengraph.io";
20
- function record(value) {
21
- return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
22
- }
23
- function text(value) {
24
- return typeof value === "string" && value.trim() !== "" ? value.trim() : void 0;
25
- }
26
- function count(value) {
27
- return typeof value === "number" && Number.isInteger(value) ? value : void 0;
28
- }
29
- function flag(value) {
30
- return typeof value === "boolean" ? value : void 0;
31
- }
32
- function compact(input) {
33
- return Object.fromEntries(Object.entries(input).filter(([, value]) => value !== void 0));
34
- }
28
+ var http = createProviderHttpClient({ baseUrl: `${API_BASE}/`, service: SERVICE });
35
29
  function errorMessage(payload) {
36
30
  if (typeof payload === "string" && payload.trim() !== "") return payload;
37
- const body = record(payload);
31
+ const body = asJsonObject(payload);
38
32
  if (body === void 0) return "OpenGraph.io request failed";
39
33
  for (const key of ["error_description", "error_message", "error", "message", "detail"]) {
40
- const found = text(body[key]);
34
+ const found = trimmedText(body[key]);
41
35
  if (found !== void 0) return found;
42
36
  }
43
37
  return "OpenGraph.io request failed";
44
38
  }
45
39
  async function request(ctx, path, query) {
46
- const url = new URL(path, API_BASE);
47
- url.searchParams.set("app_id", requireApiKey(ctx, SERVICE));
48
- for (const [key, value] of Object.entries(query)) {
49
- if (value !== void 0) url.searchParams.set(key, String(value));
50
- }
51
- let response;
52
- let payload = null;
53
- try {
54
- response = await guardedFetch(url.toString(), {
55
- method: "GET",
56
- headers: { accept: "application/json" }
57
- });
58
- const raw = await response.text();
59
- if (raw !== "") {
60
- try {
61
- payload = JSON.parse(raw);
62
- } catch {
63
- payload = raw;
64
- }
65
- }
66
- } catch (error) {
67
- const message = error instanceof Error ? `OpenGraph.io request failed: ${error.message}` : "OpenGraph.io request failed";
68
- throw upstreamError(502, message);
69
- }
70
- if (!response.ok) throw upstreamError(response.status, errorMessage(payload));
71
- return payload;
40
+ const apiKey = requireApiKey(ctx, SERVICE);
41
+ const requestQuery = [["app_id", apiKey], ...Object.entries(query)];
42
+ const { data } = await http.request({
43
+ path,
44
+ query: requestQuery,
45
+ headers: { accept: "application/json" },
46
+ invalidJson: "text",
47
+ mapError: ({ data: payload, status }) => upstreamError(status, errorMessage(payload)),
48
+ mapTransportError: ({ message }) => upstreamError(
49
+ 502,
50
+ message === void 0 ? "OpenGraph.io request failed" : `OpenGraph.io request failed: ${message}`
51
+ )
52
+ });
53
+ return data ?? null;
72
54
  }
73
55
  function unwrap(payload) {
74
- const body = record(payload);
56
+ const body = asJsonObject(payload);
75
57
  if (body === void 0) return payload;
76
58
  return typeof body.successful === "boolean" && body.data !== void 0 ? body.data : payload;
77
59
  }
78
60
  function requireObject(payload, context) {
79
- const body = record(unwrap(payload));
61
+ const body = asJsonObject(unwrap(payload));
80
62
  if (body === void 0) throw upstreamError(502, `OpenGraph.io ${context} response was not a JSON object`);
81
63
  return body;
82
64
  }
83
65
  function normalizeRequestInfo(payload) {
84
- const body = record(payload);
66
+ const body = asJsonObject(payload);
85
67
  if (body === void 0) return void 0;
86
- const normalized = compact({
87
- host: text(body.host),
88
- redirects: count(body.redirects),
89
- responseCode: count(body.responseCode ?? body.response_code),
90
- responseContentType: text(body.responseContentType ?? body.response_content_type)
68
+ const normalized = compactDefined({
69
+ host: trimmedText(body.host),
70
+ redirects: integerValue(body.redirects),
71
+ responseCode: integerValue(body.responseCode ?? body.response_code),
72
+ responseContentType: trimmedText(body.responseContentType ?? body.response_content_type)
91
73
  });
92
74
  return Object.keys(normalized).length > 0 ? normalized : void 0;
93
75
  }
94
76
  function normalizeSiteResult(payload) {
95
77
  const body = requireObject(payload, "site");
96
- const tags = Array.isArray(body.tags) ? body.tags.map((item) => record(item)).filter((item) => item !== void 0) : void 0;
97
- return compact({
98
- hybridGraph: record(body.hybridGraph ?? body.hybrid_graph),
99
- openGraph: record(body.openGraph ?? body.open_graph),
100
- twitterCard: record(body.twitterCard ?? body.twitter_card),
101
- htmlInferred: record(body.htmlInferred ?? body.html_inferred),
102
- oEmbed: record(body.oEmbed ?? body.oembed),
103
- requestUrl: text(body.requestUrl ?? body.request_url),
78
+ const tags = Array.isArray(body.tags) ? body.tags.map((item) => asJsonObject(item)).filter((item) => item !== void 0) : void 0;
79
+ return compactDefined({
80
+ hybridGraph: asJsonObject(body.hybridGraph ?? body.hybrid_graph),
81
+ openGraph: asJsonObject(body.openGraph ?? body.open_graph),
82
+ twitterCard: asJsonObject(body.twitterCard ?? body.twitter_card),
83
+ htmlInferred: asJsonObject(body.htmlInferred ?? body.html_inferred),
84
+ oEmbed: asJsonObject(body.oEmbed ?? body.oembed),
85
+ requestUrl: trimmedText(body.requestUrl ?? body.request_url),
104
86
  requestInfo: normalizeRequestInfo(body.requestInfo ?? body.request_info),
105
- cached: flag(body.cached),
87
+ cached: booleanValue(body.cached),
106
88
  // createdAt 的 null 是有信息的("非缓存结果"),不能被 compact 当缺失丢掉。
107
- createdAt: (body.createdAt ?? body.created_at) === null ? null : text(body.createdAt ?? body.created_at),
108
- retryInfo: record(body.retryInfo ?? body.retry_info),
109
- aiSafety: record(body.aiSafety ?? body.ai_safety ?? body.AI_SAFETY),
110
- domain: text(body.domain),
89
+ createdAt: (body.createdAt ?? body.created_at) === null ? null : trimmedText(body.createdAt ?? body.created_at),
90
+ retryInfo: asJsonObject(body.retryInfo ?? body.retry_info),
91
+ aiSafety: asJsonObject(body.aiSafety ?? body.ai_safety ?? body.AI_SAFETY),
92
+ domain: trimmedText(body.domain),
111
93
  tags: tags !== void 0 && tags.length > 0 ? tags : void 0
112
94
  });
113
95
  }
@@ -163,14 +145,14 @@ async function scrapeUrl(input, ctx) {
163
145
  const unwrapped = unwrap(payload);
164
146
  if (typeof unwrapped === "string") return { htmlContent: unwrapped };
165
147
  const body = requireObject(unwrapped, "scrape");
166
- const htmlContent = text(body.htmlContent ?? body.html_content ?? body.html);
148
+ const htmlContent = trimmedText(body.htmlContent ?? body.html_content ?? body.html);
167
149
  if (htmlContent === void 0) {
168
150
  throw upstreamError(502, "OpenGraph.io scrape response did not include html content");
169
151
  }
170
- return compact({
152
+ return compactDefined({
171
153
  htmlContent,
172
154
  requestInfo: normalizeRequestInfo(body.requestInfo ?? body.request_info),
173
- retryInfo: record(body.retryInfo ?? body.retry_info)
155
+ retryInfo: asJsonObject(body.retryInfo ?? body.retry_info)
174
156
  });
175
157
  }
176
158
  async function captureScreenshot(input, ctx) {
@@ -189,17 +171,17 @@ async function captureScreenshot(input, ctx) {
189
171
  block_cookie_banner: input.blockCookieBanner
190
172
  });
191
173
  const body = requireObject(payload, "screenshot");
192
- const screenshotUrl = text(body.screenshotUrl ?? body.screenshot_url);
174
+ const screenshotUrl = trimmedText(body.screenshotUrl ?? body.screenshot_url);
193
175
  if (screenshotUrl === void 0) {
194
176
  throw upstreamError(502, "OpenGraph.io screenshot response did not include screenshotUrl");
195
177
  }
196
- const dimensions = record(body.dimensions);
197
- const width = count(dimensions?.width);
198
- const height = count(dimensions?.height);
178
+ const dimensions = asJsonObject(body.dimensions);
179
+ const width = integerValue(dimensions?.width);
180
+ const height = integerValue(dimensions?.height);
199
181
  if (width === void 0 || height === void 0) {
200
182
  throw upstreamError(502, "OpenGraph.io screenshot response did not include dimensions");
201
183
  }
202
- return compact({
184
+ return compactDefined({
203
185
  screenshotUrl,
204
186
  dimensions: { width, height },
205
187
  requestInfo: normalizeRequestInfo(body.requestInfo ?? body.request_info)
@@ -1,40 +1,35 @@
1
+ import {
2
+ createProviderHttpClient
3
+ } from "./chunk-WW2IMPQK.js";
4
+ import {
5
+ asJsonObject,
6
+ compactDefined,
7
+ trimmedText
8
+ } from "./chunk-JXHMDBAY.js";
1
9
  import {
2
10
  createProviderPlugin,
3
11
  requireApiKey,
4
12
  upstreamError
5
- } from "./chunk-VK3V2WTY.js";
6
- import {
7
- guardedFetch
8
- } from "./chunk-2O27H4Y2.js";
9
- import "./chunk-GKX72JMJ.js";
13
+ } from "./chunk-YASUMV2K.js";
14
+ import "./chunk-U5UHT7CX.js";
10
15
  import {
11
16
  TBError,
12
17
  external_exports
13
- } from "./chunk-YB2FLNWI.js";
14
- import "./chunk-MLKGABMK.js";
18
+ } from "./chunk-RVWZN3CI.js";
19
+ import "./chunk-U67V476Y.js";
15
20
 
16
21
  // ../plugins/src/openrouter/api.ts
17
22
  var SERVICE = "openrouter";
18
23
  var API_BASE = "https://openrouter.ai/api/v1";
24
+ var http = createProviderHttpClient({ baseUrl: `${API_BASE}/`, service: SERVICE });
19
25
  var HEADER_INPUT_KEYS = ["httpReferer", "xTitle"];
20
- function text(value) {
21
- if (typeof value !== "string") return void 0;
22
- const trimmed = value.trim();
23
- return trimmed === "" ? void 0 : trimmed;
24
- }
25
- function record(value) {
26
- return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
27
- }
28
26
  function requireRecord(value, label) {
29
- const result = record(value);
27
+ const result = asJsonObject(value);
30
28
  if (result === void 0) {
31
29
  throw new TBError("unavailable", `OpenRouter \u7684${label}\u4E0D\u662F\u5BF9\u8C61`, { retryable: true });
32
30
  }
33
31
  return result;
34
32
  }
35
- function compact(input) {
36
- return Object.fromEntries(Object.entries(input).filter(([, value]) => value !== void 0));
37
- }
38
33
  function stripHeaderInputs(input) {
39
34
  return Object.fromEntries(
40
35
  Object.entries(input).filter(([key, value]) => !HEADER_INPUT_KEYS.includes(key) && value !== void 0)
@@ -51,53 +46,44 @@ function legacyTools(value) {
51
46
  }
52
47
  function legacyToolChoice(value) {
53
48
  if (value === "none" || value === "auto") return value;
54
- const name = text(record(value)?.name);
49
+ const name = trimmedText(asJsonObject(value)?.name);
55
50
  if (name === void 0) return void 0;
56
51
  return { type: "function", function: { name } };
57
52
  }
58
- function buildUrl(path, query) {
59
- const url = new URL(`${API_BASE}${path}`);
60
- for (const [key, value] of Object.entries(query)) {
61
- if (value !== void 0) url.searchParams.set(key, String(value));
62
- }
63
- return url.toString();
64
- }
65
53
  function errorMessage(payload) {
66
- const body = record(payload);
54
+ const body = asJsonObject(payload);
67
55
  if (body === void 0) return void 0;
68
- return text(record(body.error)?.message) ?? text(body.message);
56
+ return trimmedText(asJsonObject(body.error)?.message) ?? trimmedText(body.message);
69
57
  }
70
58
  async function request(ctx, input) {
71
59
  const hasBody = input.body !== void 0;
72
60
  const headers = new Headers({ authorization: `Bearer ${requireApiKey(ctx, SERVICE)}` });
73
- if (hasBody) headers.set("content-type", "application/json");
74
- const referer = text(input.headerSource?.httpReferer);
75
- const title = text(input.headerSource?.xTitle);
61
+ const referer = trimmedText(input.headerSource?.httpReferer);
62
+ const title = trimmedText(input.headerSource?.xTitle);
76
63
  if (referer !== void 0) headers.set("HTTP-Referer", referer);
77
64
  if (title !== void 0) headers.set("X-Title", title);
78
- const response = await guardedFetch(buildUrl(input.path, input.query ?? {}), {
65
+ const response = await http.request({
79
66
  method: input.method ?? "GET",
67
+ path: input.path,
68
+ query: Object.entries(input.query ?? {}),
80
69
  headers,
81
- ...hasBody ? { body: JSON.stringify(compact(input.body ?? {})) } : {}
70
+ ...hasBody ? { json: compactDefined(input.body ?? {}) } : {},
71
+ responseType: "json",
72
+ invalidJson: "text",
73
+ mapError: ({ bodyKind, data, status }) => upstreamError(
74
+ status,
75
+ bodyKind === "json" ? errorMessage(data) ?? `OpenRouter \u8FD4\u56DE HTTP ${status}` : `OpenRouter \u8FD4\u56DE HTTP ${status}`
76
+ )
82
77
  });
83
- const body = await response.text();
84
- if (response.ok) {
85
- const contentType = response.headers.get("content-type") ?? "";
86
- const isText = contentType.includes("xml") || contentType.includes("rss") || contentType.startsWith("text/");
87
- if (input.allowText === true && isText) return { rss: body };
88
- try {
89
- return requireRecord(JSON.parse(body), "\u54CD\u5E94");
90
- } catch (error) {
91
- if (error instanceof TBError) throw error;
92
- throw new TBError("unavailable", "OpenRouter \u8FD4\u56DE\u4E86\u975E JSON \u54CD\u5E94", { retryable: true });
93
- }
78
+ const contentType = response.headers.get("content-type") ?? "";
79
+ const isText = contentType.includes("xml") || contentType.includes("rss") || contentType.startsWith("text/");
80
+ if (input.allowText === true && response.bodyKind === "invalid-json" && isText) {
81
+ return { rss: String(response.data) };
94
82
  }
95
- let payload = null;
96
- try {
97
- payload = JSON.parse(body);
98
- } catch {
83
+ if (response.bodyKind !== "json") {
84
+ throw new TBError("unavailable", "OpenRouter \u8FD4\u56DE\u4E86\u975E JSON \u54CD\u5E94", { retryable: true });
99
85
  }
100
- throw upstreamError(response.status, errorMessage(payload) ?? `OpenRouter \u8FD4\u56DE HTTP ${response.status}`);
86
+ return requireRecord(response.data, "\u54CD\u5E94");
101
87
  }
102
88
  function createChatCompletion(input, ctx) {
103
89
  assertStreamingDisabled(input);
@@ -106,7 +92,7 @@ function createChatCompletion(input, ctx) {
106
92
  method: "POST",
107
93
  path: "/chat/completions",
108
94
  headerSource: input,
109
- body: compact({
95
+ body: compactDefined({
110
96
  ...body,
111
97
  // 给了新字段就不翻译 legacy 的那两个(新的优先),翻完旧字段一律不发。
112
98
  tools: body.tools ?? legacyTools(input.functions),
@@ -146,7 +132,7 @@ function getModelsCount(input, ctx) {
146
132
  return request(ctx, {
147
133
  path: "/models/count",
148
134
  headerSource: input,
149
- query: { output_modalities: text(input.outputModalities) }
135
+ query: { output_modalities: trimmedText(input.outputModalities) }
150
136
  });
151
137
  }
152
138
  function listAvailableModels(input, ctx) {
@@ -154,9 +140,9 @@ function listAvailableModels(input, ctx) {
154
140
  path: "/models",
155
141
  // 入参名是驼峰,query 名是下划线 —— 这一层改名是上游的,不是笔误。
156
142
  query: {
157
- category: text(input.category),
158
- supported_parameters: text(input.supportedParameters),
159
- output_modalities: text(input.outputModalities),
143
+ category: trimmedText(input.category),
144
+ supported_parameters: trimmedText(input.supportedParameters),
145
+ output_modalities: trimmedText(input.outputModalities),
160
146
  use_rss: input.useRss,
161
147
  use_rss_chat_links: input.useRssChatLinks
162
148
  },