@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,79 +1,65 @@
1
+ import {
2
+ createProviderHttpClient
3
+ } from "./chunk-WW2IMPQK.js";
4
+ import {
5
+ asJsonObject,
6
+ booleanValue,
7
+ compactDefined
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/notion/api.ts
17
22
  var SERVICE = "notion";
18
23
  var API_BASE = "https://api.notion.com/v1";
19
24
  var NOTION_VERSION = "2026-03-11";
20
- function record(value) {
21
- return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
22
- }
25
+ var http = createProviderHttpClient({ baseUrl: `${API_BASE}/`, service: SERVICE });
23
26
  function nonEmpty(value) {
24
27
  return typeof value === "string" && value.length > 0 ? value : void 0;
25
28
  }
26
- function bool(value) {
27
- return typeof value === "boolean" ? value : void 0;
28
- }
29
29
  function array(value) {
30
30
  return Array.isArray(value) ? value : void 0;
31
31
  }
32
- function compact(input) {
33
- return Object.fromEntries(Object.entries(input).filter(([, value]) => value !== void 0));
34
- }
35
32
  function inputError(message) {
36
33
  return new TBError("invalid_argument", message);
37
34
  }
38
- function errorMessage(status, raw) {
39
- if (raw === "") return `notion request failed with ${status}`;
40
- try {
41
- const parsed = record(JSON.parse(raw));
42
- return nonEmpty(parsed?.message) ?? nonEmpty(parsed?.error) ?? raw;
43
- } catch {
44
- return raw;
35
+ function errorMessage(status, payload, bodyKind) {
36
+ if (bodyKind === "empty") return `notion request failed with ${status}`;
37
+ if (bodyKind === "invalid-json" || bodyKind === "text") {
38
+ return nonEmpty(payload) ?? `notion request failed with ${status}`;
45
39
  }
40
+ const parsed = asJsonObject(payload);
41
+ return nonEmpty(parsed?.message) ?? nonEmpty(parsed?.error) ?? JSON.stringify(payload) ?? `notion request failed with ${status}`;
46
42
  }
47
43
  async function request(ctx, input) {
48
- const url = new URL(`${API_BASE}${input.path}`);
49
- for (const [key, value] of Object.entries(input.query ?? {})) {
50
- if (value === void 0) continue;
51
- if (Array.isArray(value)) {
52
- for (const item of value) url.searchParams.append(key, item);
53
- continue;
54
- }
55
- url.searchParams.set(key, String(value));
56
- }
57
44
  const hasBody = input.body !== void 0;
58
- const response = await guardedFetch(url.toString(), {
45
+ const { data } = await http.request({
46
+ path: input.path,
59
47
  method: input.method ?? "GET",
48
+ // filter_properties[] 靠**重复同名参数**表达;空数组在调用处就丢掉了。
49
+ query: Object.entries(input.query ?? {}),
60
50
  headers: {
61
51
  "authorization": `Bearer ${requireApiKey(ctx, SERVICE)}`,
62
- "notion-version": NOTION_VERSION,
63
- ...hasBody ? { "content-type": "application/json" } : {}
52
+ "notion-version": NOTION_VERSION
64
53
  },
65
- body: hasBody ? JSON.stringify(input.body) : void 0
54
+ ...hasBody ? { json: input.body } : {},
55
+ invalidJsonMessage: "Notion \u8FD4\u56DE\u4E86\u975E JSON \u54CD\u5E94",
56
+ mapError: ({ bodyKind, data: payload, status }) => upstreamError(
57
+ status,
58
+ errorMessage(status, payload, bodyKind)
59
+ )
66
60
  });
67
- const raw = await response.text();
68
- if (!response.ok) throw upstreamError(response.status, errorMessage(response.status, raw));
69
- if (raw === "") return {};
70
- let payload;
71
- try {
72
- payload = JSON.parse(raw);
73
- } catch {
74
- throw new TBError("unavailable", "Notion \u8FD4\u56DE\u4E86\u975E JSON \u54CD\u5E94", { retryable: true });
75
- }
76
- const result = record(payload);
61
+ if (data === void 0) return {};
62
+ const result = asJsonObject(data);
77
63
  if (result === void 0) {
78
64
  throw new TBError("unavailable", "Notion \u8FD4\u56DE\u7684\u4E0D\u662F JSON \u5BF9\u8C61", { retryable: true });
79
65
  }
@@ -89,15 +75,15 @@ function isSamePageParent(parent, parentId) {
89
75
  return typeof parent.page_id === "string" && parent.page_id === parentId;
90
76
  }
91
77
  function createPageBody(input) {
92
- const parent = record(input.parent);
78
+ const parent = asJsonObject(input.parent);
93
79
  const parentId = nonEmpty(input.parentId);
94
80
  const children = array(input.children);
95
81
  const nonEmptyChildren = children !== void 0 && children.length > 0 ? children : void 0;
96
82
  const markdown = typeof input.markdown === "string" ? input.markdown : void 0;
97
- const icon = record(input.icon);
98
- const cover = record(input.cover);
99
- const template = record(input.template);
100
- const properties = record(input.properties);
83
+ const icon = asJsonObject(input.icon);
84
+ const cover = asJsonObject(input.cover);
85
+ const template = asJsonObject(input.template);
86
+ const properties = asJsonObject(input.properties);
101
87
  if (markdown !== void 0 && nonEmptyChildren !== void 0) {
102
88
  throw inputError("markdown cannot be used with children");
103
89
  }
@@ -108,7 +94,7 @@ function createPageBody(input) {
108
94
  if (parentId !== void 0 && !isSamePageParent(parent, parentId)) {
109
95
  throw inputError("parent and parentId must describe the same page parent");
110
96
  }
111
- return compact({ parent, properties, children: nonEmptyChildren, markdown, template, icon, cover });
97
+ return compactDefined({ parent, properties, children: nonEmptyChildren, markdown, template, icon, cover });
112
98
  }
113
99
  const title = nonEmpty(input.title);
114
100
  if (parentId === void 0 && markdown === void 0) {
@@ -117,7 +103,7 @@ function createPageBody(input) {
117
103
  if (parentId !== void 0 && title === void 0) {
118
104
  throw inputError("title is required with parentId");
119
105
  }
120
- return compact({
106
+ return compactDefined({
121
107
  parent: parentId === void 0 ? void 0 : { page_id: parentId },
122
108
  properties: title === void 0 ? properties : { ...properties, title: titleProperty(title) },
123
109
  children: nonEmptyChildren,
@@ -132,10 +118,10 @@ function search(input, ctx) {
132
118
  method: "POST",
133
119
  path: "/search",
134
120
  // query 恒发(上游 `String(input.query)`),空串在 Notion 侧就是"列出全部可见对象"。
135
- body: compact({
121
+ body: compactDefined({
136
122
  query: String(input.query),
137
- filter: record(input.filter),
138
- sort: record(input.sort),
123
+ filter: asJsonObject(input.filter),
124
+ sort: asJsonObject(input.sort),
139
125
  page_size: input.pageSize,
140
126
  start_cursor: nonEmpty(input.startCursor)
141
127
  })
@@ -170,12 +156,12 @@ function updatePageMarkdown(input, ctx) {
170
156
  return request(ctx, {
171
157
  method: "PATCH",
172
158
  path: `/pages/${encodeURIComponent(input.pageId)}/markdown`,
173
- body: compact({
159
+ body: compactDefined({
174
160
  type: nonEmpty(input.type),
175
- insert_content: record(input.insert_content),
176
- replace_content_range: record(input.replace_content_range),
177
- update_content: record(input.update_content),
178
- replace_content: record(input.replace_content)
161
+ insert_content: asJsonObject(input.insert_content),
162
+ replace_content_range: asJsonObject(input.replace_content_range),
163
+ update_content: asJsonObject(input.update_content),
164
+ replace_content: asJsonObject(input.replace_content)
179
165
  })
180
166
  });
181
167
  }
@@ -189,20 +175,20 @@ function createPage(input, ctx) {
189
175
  return request(ctx, { method: "POST", path: "/pages", body: createPageBody(input) });
190
176
  }
191
177
  function updatePage(input, ctx) {
192
- const properties = record(input.properties);
178
+ const properties = asJsonObject(input.properties);
193
179
  return request(ctx, {
194
180
  method: "PATCH",
195
181
  path: `/pages/${encodeURIComponent(input.pageId)}`,
196
- body: compact({
182
+ body: compactDefined({
197
183
  // 简化写法:给了 title 就把它并进 properties(上游如此,与 create_page 不同 ——
198
184
  // 这里 title 与 parent 不冲突)。
199
185
  properties: typeof input.title === "string" ? { ...properties, title: titleProperty(input.title) } : properties,
200
- icon: record(input.icon),
201
- cover: record(input.cover),
202
- template: record(input.template),
203
- in_trash: bool(input.in_trash),
204
- is_locked: bool(input.is_locked),
205
- erase_content: bool(input.erase_content)
186
+ icon: asJsonObject(input.icon),
187
+ cover: asJsonObject(input.cover),
188
+ template: asJsonObject(input.template),
189
+ in_trash: booleanValue(input.in_trash),
190
+ is_locked: booleanValue(input.is_locked),
191
+ erase_content: booleanValue(input.erase_content)
206
192
  })
207
193
  });
208
194
  }
@@ -210,7 +196,7 @@ function movePage(input, ctx) {
210
196
  return request(ctx, {
211
197
  method: "POST",
212
198
  path: `/pages/${encodeURIComponent(input.pageId)}/move`,
213
- body: { parent: record(input.parent) }
199
+ body: { parent: asJsonObject(input.parent) }
214
200
  });
215
201
  }
216
202
  function appendBlockChildren(input, ctx) {
@@ -218,7 +204,7 @@ function appendBlockChildren(input, ctx) {
218
204
  method: "PATCH",
219
205
  path: `/blocks/${encodeURIComponent(input.blockId)}/children`,
220
206
  // children 缺失时发空数组(上游如此,让 Notion 自己报 validation_error)。
221
- body: compact({ children: array(input.children) ?? [], position: record(input.position) })
207
+ body: compactDefined({ children: array(input.children) ?? [], position: asJsonObject(input.position) })
222
208
  });
223
209
  }
224
210
  function appendBlock(input, ctx) {
@@ -240,7 +226,7 @@ function updateBlock(input, ctx) {
240
226
  method: "PATCH",
241
227
  path: `/blocks/${encodeURIComponent(blockId)}`,
242
228
  // 入参是 looseObject:除 blockId 外的字段原样进 body(块字段随块类型变化,枚举不完)。
243
- body: compact({ ...rest, in_trash: bool(rest.in_trash) })
229
+ body: compactDefined({ ...rest, in_trash: booleanValue(rest.in_trash) })
244
230
  });
245
231
  }
246
232
  function deleteBlock(input, ctx) {
@@ -256,14 +242,14 @@ function createDatabase(input, ctx) {
256
242
  return request(ctx, {
257
243
  method: "POST",
258
244
  path: "/databases",
259
- body: compact({
260
- parent: record(input.parent),
245
+ body: compactDefined({
246
+ parent: asJsonObject(input.parent),
261
247
  title: array(input.title),
262
248
  description: array(input.description),
263
- is_inline: bool(input.is_inline),
264
- initial_data_source: record(input.initial_data_source),
265
- icon: record(input.icon),
266
- cover: record(input.cover)
249
+ is_inline: booleanValue(input.is_inline),
250
+ initial_data_source: asJsonObject(input.initial_data_source),
251
+ icon: asJsonObject(input.icon),
252
+ cover: asJsonObject(input.cover)
267
253
  })
268
254
  });
269
255
  }
@@ -274,15 +260,15 @@ function updateDatabase(input, ctx) {
274
260
  return request(ctx, {
275
261
  method: "PATCH",
276
262
  path: `/databases/${encodeURIComponent(input.databaseId)}`,
277
- body: compact({
278
- parent: record(input.parent),
263
+ body: compactDefined({
264
+ parent: asJsonObject(input.parent),
279
265
  title: array(input.title),
280
266
  description: array(input.description),
281
- is_inline: bool(input.is_inline),
282
- icon: record(input.icon),
283
- cover: record(input.cover),
284
- in_trash: bool(input.in_trash),
285
- is_locked: bool(input.is_locked)
267
+ is_inline: booleanValue(input.is_inline),
268
+ icon: asJsonObject(input.icon),
269
+ cover: asJsonObject(input.cover),
270
+ in_trash: booleanValue(input.in_trash),
271
+ is_locked: booleanValue(input.is_locked)
286
272
  })
287
273
  });
288
274
  }
@@ -290,11 +276,11 @@ function createDataSource(input, ctx) {
290
276
  return request(ctx, {
291
277
  method: "POST",
292
278
  path: "/data_sources",
293
- body: compact({
294
- parent: record(input.parent),
295
- properties: record(input.properties),
279
+ body: compactDefined({
280
+ parent: asJsonObject(input.parent),
281
+ properties: asJsonObject(input.properties),
296
282
  title: array(input.title),
297
- icon: record(input.icon)
283
+ icon: asJsonObject(input.icon)
298
284
  })
299
285
  });
300
286
  }
@@ -305,13 +291,13 @@ function updateDataSource(input, ctx) {
305
291
  return request(ctx, {
306
292
  method: "PATCH",
307
293
  path: `/data_sources/${encodeURIComponent(input.dataSourceId)}`,
308
- body: compact({
294
+ body: compactDefined({
309
295
  title: array(input.title),
310
296
  description: array(input.description),
311
- icon: record(input.icon),
312
- properties: record(input.properties),
313
- in_trash: bool(input.in_trash),
314
- parent: record(input.parent)
297
+ icon: asJsonObject(input.icon),
298
+ properties: asJsonObject(input.properties),
299
+ in_trash: booleanValue(input.in_trash),
300
+ parent: asJsonObject(input.parent)
315
301
  })
316
302
  });
317
303
  }
@@ -322,12 +308,12 @@ function queryDataSource(input, ctx) {
322
308
  path: `/data_sources/${encodeURIComponent(input.dataSourceId)}/query`,
323
309
  // 参数名带方括号,且是重复的同名参数;空数组不发(上游 `compactQuery`)。
324
310
  query: { "filter_properties[]": filterProperties.length > 0 ? filterProperties : void 0 },
325
- body: compact({
326
- filter: record(input.filter),
311
+ body: compactDefined({
312
+ filter: asJsonObject(input.filter),
327
313
  sorts: array(input.sorts),
328
314
  page_size: input.pageSize,
329
315
  start_cursor: nonEmpty(input.startCursor),
330
- in_trash: bool(input.in_trash),
316
+ in_trash: booleanValue(input.in_trash),
331
317
  result_type: nonEmpty(input.result_type)
332
318
  })
333
319
  });
@@ -1,64 +1,60 @@
1
+ import {
2
+ createProviderHttpClient
3
+ } from "./chunk-WW2IMPQK.js";
4
+ import {
5
+ asJsonObject
6
+ } from "./chunk-JXHMDBAY.js";
1
7
  import {
2
8
  createProviderPlugin,
3
9
  requireApiKey,
4
10
  upstreamError
5
- } from "./chunk-VK3V2WTY.js";
6
- import {
7
- guardedFetch
8
- } from "./chunk-2O27H4Y2.js";
9
- import "./chunk-GKX72JMJ.js";
11
+ } from "./chunk-YASUMV2K.js";
12
+ import "./chunk-U5UHT7CX.js";
10
13
  import {
11
14
  TBError,
12
15
  external_exports
13
- } from "./chunk-YB2FLNWI.js";
14
- import "./chunk-MLKGABMK.js";
16
+ } from "./chunk-RVWZN3CI.js";
17
+ import "./chunk-U67V476Y.js";
15
18
 
16
19
  // ../plugins/src/open_exchange_rates/api.ts
17
20
  var SERVICE = "open_exchange_rates";
18
21
  var API_BASE = "https://openexchangerates.org/api";
19
- function record(value) {
20
- return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
21
- }
22
+ var http = createProviderHttpClient({ baseUrl: `${API_BASE}/`, service: SERVICE });
22
23
  function text(value) {
23
24
  return typeof value === "string" && value !== "" ? value : void 0;
24
25
  }
25
26
  function errorMessage(payload) {
26
- const body = record(payload);
27
+ const body = asJsonObject(payload);
27
28
  if (body === void 0) return void 0;
28
29
  return text(body.description) ?? text(body.message) ?? text(body.error);
29
30
  }
30
31
  async function request(ctx, input) {
31
32
  const apiKey = requireApiKey(ctx, SERVICE);
32
- const url = new URL(`${API_BASE}${input.path}`);
33
- if (input.includeAppId !== false) url.searchParams.set("app_id", apiKey);
34
- for (const [key, value] of Object.entries(input.query ?? {})) {
35
- if (value === void 0) continue;
36
- url.searchParams.set(key, String(value));
37
- }
38
- let response;
39
- try {
40
- response = await guardedFetch(url.toString(), {
41
- method: "GET",
42
- headers: { accept: "application/json" }
43
- });
44
- } catch (error) {
45
- throw upstreamError(502, error instanceof Error ? `open_exchange_rates \u8BF7\u6C42\u5931\u8D25: ${error.message}` : "open_exchange_rates \u8BF7\u6C42\u5931\u8D25");
46
- }
47
- const raw = await response.text().catch(() => "");
48
- let payload = null;
49
- if (raw !== "") {
50
- try {
51
- payload = JSON.parse(raw);
52
- } catch {
53
- throw upstreamError(502, "Open Exchange Rates \u8FD4\u56DE\u4E86\u975E\u6CD5 JSON");
54
- }
55
- }
56
- const body = record(payload);
33
+ const query = [
34
+ ...input.includeAppId === false ? [] : [["app_id", apiKey]],
35
+ ...Object.entries(input.query ?? {})
36
+ ];
37
+ const result = await http.request({
38
+ path: input.path.replace(/^\//, ""),
39
+ query,
40
+ headers: { accept: "application/json" },
41
+ invalidJsonMessage: "Open Exchange Rates \u8FD4\u56DE\u4E86\u975E\u6CD5 JSON",
42
+ mapError: ({ bodyKind, data: payload2, status }) => bodyKind === "invalid-json" ? upstreamError(502, "Open Exchange Rates \u8FD4\u56DE\u4E86\u975E\u6CD5 JSON") : upstreamError(
43
+ status,
44
+ errorMessage(payload2) ?? `Open Exchange Rates \u8FD4\u56DE HTTP ${status}`
45
+ ),
46
+ mapTransportError: ({ message }) => upstreamError(
47
+ 502,
48
+ message === void 0 ? "open_exchange_rates \u8BF7\u6C42\u5931\u8D25" : `open_exchange_rates \u8BF7\u6C42\u5931\u8D25: ${message}`
49
+ )
50
+ });
51
+ const payload = result.data ?? null;
52
+ const body = asJsonObject(payload);
57
53
  const flagged = body?.error === true;
58
- if (!response.ok || flagged) {
54
+ if (flagged) {
59
55
  const embedded = body?.status;
60
- const status = response.ok ? typeof embedded === "number" && embedded >= 400 ? embedded : 502 : response.status;
61
- throw upstreamError(status, errorMessage(payload) ?? (response.statusText || `Open Exchange Rates \u8FD4\u56DE HTTP ${response.status}`));
56
+ const status = typeof embedded === "number" && embedded >= 400 ? embedded : 502;
57
+ throw upstreamError(status, errorMessage(payload) ?? `Open Exchange Rates \u8FD4\u56DE HTTP ${result.status}`);
62
58
  }
63
59
  if (body === void 0) throw upstreamError(502, "Open Exchange Rates \u8FD4\u56DE\u4E86\u975E\u5BF9\u8C61\u54CD\u5E94");
64
60
  return body;
@@ -1,41 +1,38 @@
1
+ import {
2
+ bytesToBase64,
3
+ readBoundedResponseBytes
4
+ } from "./chunk-LMLX3DJF.js";
5
+ import {
6
+ createProviderHttpClient
7
+ } from "./chunk-WW2IMPQK.js";
8
+ import {
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
17
  assertPublicHttpUrl,
8
18
  guardedFetch
9
- } from "./chunk-2O27H4Y2.js";
10
- import "./chunk-GKX72JMJ.js";
19
+ } from "./chunk-U5UHT7CX.js";
11
20
  import {
12
21
  TBError,
13
22
  external_exports
14
- } from "./chunk-YB2FLNWI.js";
15
- import "./chunk-MLKGABMK.js";
23
+ } from "./chunk-RVWZN3CI.js";
24
+ import "./chunk-U67V476Y.js";
16
25
 
17
26
  // ../plugins/src/openai/api.ts
18
27
  var SERVICE = "openai";
19
28
  var API_BASE = "https://api.openai.com/v1";
20
29
  var AUDIO_SOURCE_MAX_BYTES = 25 * 1024 * 1024;
21
30
  var AUDIO_SOURCE_FETCH_TIMEOUT_MS = 3e4;
22
- function text(value) {
23
- if (typeof value !== "string") return void 0;
24
- const trimmed = value.trim();
25
- return trimmed === "" ? void 0 : trimmed;
26
- }
31
+ var http = createProviderHttpClient({ baseUrl: `${API_BASE}/`, service: SERVICE });
27
32
  function normalizedContentType(value, fallback) {
28
33
  if (value === null || value === "") return fallback;
29
34
  return value.split(";", 1)[0]?.trim() || fallback;
30
35
  }
31
- function encodeBase64(bytes) {
32
- const CHUNK = 32768;
33
- let binary = "";
34
- for (let i = 0; i < bytes.length; i += CHUNK) {
35
- binary += String.fromCharCode(...bytes.subarray(i, i + CHUNK));
36
- }
37
- return btoa(binary);
38
- }
39
36
  function stripPadding(value) {
40
37
  let end = value.length;
41
38
  while (end > 0 && value[end - 1] === "=") end -= 1;
@@ -47,7 +44,7 @@ function decodeBase64Content(value, fieldName) {
47
44
  if (binary.length === 0) throw new Error("empty");
48
45
  const bytes = new Uint8Array(binary.length);
49
46
  for (let i = 0; i < binary.length; i += 1) bytes[i] = binary.charCodeAt(i);
50
- if (stripPadding(encodeBase64(bytes)) !== stripPadding(value)) throw new Error("mismatch");
47
+ if (stripPadding(bytesToBase64(bytes)) !== stripPadding(value)) throw new Error("mismatch");
51
48
  return bytes;
52
49
  } catch {
53
50
  throw new TBError("invalid_argument", `${fieldName} must be valid base64`);
@@ -99,8 +96,31 @@ async function rawRequest(ctx, input) {
99
96
  if (!response.ok) throw upstreamError(response.status, await errorMessage(response));
100
97
  return response;
101
98
  }
99
+ function errorMessageFromContext(context) {
100
+ const fallback = `openai request failed with ${context.status}`;
101
+ const payload = context.data;
102
+ const message = payload !== null && typeof payload === "object" ? payload.error?.message ?? payload.message : void 0;
103
+ if (typeof message === "string" && message !== "") return message;
104
+ return context.rawText?.trim() || fallback;
105
+ }
102
106
  async function jsonRequest(ctx, input) {
103
- return (await rawRequest(ctx, input)).json();
107
+ if (input.body instanceof FormData) {
108
+ throw new TBError("internal", "openai jsonRequest cannot send multipart data");
109
+ }
110
+ const method = input.method ?? "GET";
111
+ const result = await http.request({
112
+ path: input.path,
113
+ method,
114
+ headers: input.headers ?? baseHeaders(requireApiKey(ctx, SERVICE)),
115
+ ...input.body === void 0 ? {} : { json: input.body },
116
+ invalidJsonMessage: "OpenAI \u8FD4\u56DE\u4E86\u975E JSON \u54CD\u5E94",
117
+ mapError: (context) => upstreamError(context.status, errorMessageFromContext(context)),
118
+ mapTransportError: ({ message }) => upstreamError(
119
+ 502,
120
+ `openai request failed before receiving response: ${message ?? "unknown network error"}`
121
+ )
122
+ });
123
+ return result.data;
104
124
  }
105
125
  function assertStreamingDisabled(input) {
106
126
  if (input.stream === true) {
@@ -125,37 +145,13 @@ function withQuery(path, query) {
125
145
  return `${url.pathname}${url.search}`;
126
146
  }
127
147
  async function readBoundedBytes(response, fieldName) {
128
- const declared = Number(response.headers.get("content-length"));
129
- if (Number.isSafeInteger(declared) && declared > 0) assertAudioSourceSize(declared, fieldName);
130
- if (response.body === null) {
131
- const bytes2 = new Uint8Array(await response.arrayBuffer());
132
- assertAudioSourceSize(bytes2.byteLength, fieldName);
133
- return bytes2;
134
- }
135
- const reader = response.body.getReader();
136
- const chunks = [];
137
- let total = 0;
138
- try {
139
- for (; ; ) {
140
- const { done, value } = await reader.read();
141
- if (done) break;
142
- total += value.byteLength;
143
- if (total > AUDIO_SOURCE_MAX_BYTES) {
144
- await reader.cancel().catch(() => void 0);
145
- assertAudioSourceSize(total, fieldName);
146
- }
147
- chunks.push(value);
148
- }
149
- } finally {
150
- reader.releaseLock();
151
- }
152
- const bytes = new Uint8Array(total);
153
- let offset = 0;
154
- for (const chunk of chunks) {
155
- bytes.set(chunk, offset);
156
- offset += chunk.byteLength;
157
- }
158
- return bytes;
148
+ return readBoundedResponseBytes(response, {
149
+ maxBytes: AUDIO_SOURCE_MAX_BYTES,
150
+ tooLarge: () => new TBError(
151
+ "invalid_argument",
152
+ `${fieldName} exceeds ${AUDIO_SOURCE_MAX_BYTES} bytes`
153
+ )
154
+ });
159
155
  }
160
156
  async function fetchAudioSource(url) {
161
157
  try {
@@ -178,9 +174,9 @@ async function fetchAudioSource(url) {
178
174
  }
179
175
  async function resolveAudioUploadSource(input) {
180
176
  const file = input.file;
181
- const fileUrl = text(file.url);
182
- const contentBase64 = text(file.content_base64);
183
- const mimeType = text(file.mimetype);
177
+ const fileUrl = trimmedText(file.url);
178
+ const contentBase64 = trimmedText(file.content_base64);
179
+ const mimeType = trimmedText(file.mimetype);
184
180
  if (fileUrl === void 0 && contentBase64 === void 0) {
185
181
  throw new TBError("invalid_argument", "file.url or file.content_base64 is required");
186
182
  }
@@ -298,7 +294,7 @@ async function createSpeech(input, ctx) {
298
294
  headers: { ...jsonHeaders(requireApiKey(ctx, SERVICE)), accept: "*/*" }
299
295
  });
300
296
  return {
301
- content_base64: encodeBase64(new Uint8Array(await response.arrayBuffer())),
297
+ content_base64: bytesToBase64(new Uint8Array(await response.arrayBuffer())),
302
298
  content_type: normalizedContentType(
303
299
  response.headers.get("content-type"),
304
300
  inferSpeechContentType(input.response_format)