@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,77 +1,57 @@
1
+ import {
2
+ createProviderHttpClient
3
+ } from "./chunk-WW2IMPQK.js";
4
+ import {
5
+ asJsonObject,
6
+ trimmedText
7
+ } from "./chunk-JXHMDBAY.js";
1
8
  import {
2
9
  createProviderPlugin,
3
10
  requireApiKey,
4
11
  upstreamError
5
- } from "./chunk-VK3V2WTY.js";
6
- import {
7
- guardedFetch
8
- } from "./chunk-2O27H4Y2.js";
9
- import "./chunk-GKX72JMJ.js";
12
+ } from "./chunk-YASUMV2K.js";
13
+ import "./chunk-U5UHT7CX.js";
10
14
  import {
11
15
  TBError,
12
16
  external_exports
13
- } from "./chunk-YB2FLNWI.js";
14
- import "./chunk-MLKGABMK.js";
17
+ } from "./chunk-RVWZN3CI.js";
18
+ import "./chunk-U67V476Y.js";
15
19
 
16
20
  // ../plugins/src/telnyx/api.ts
17
21
  var SERVICE = "telnyx";
18
22
  var API_BASE = "https://api.telnyx.com/v2";
19
- function toRecord(value) {
20
- return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
21
- }
22
- function text(value) {
23
- if (typeof value !== "string") return void 0;
24
- const trimmed = value.trim();
25
- return trimmed === "" ? void 0 : trimmed;
26
- }
27
- function errorMessage(payload, response) {
23
+ var http = createProviderHttpClient({ baseUrl: `${API_BASE}/`, service: SERVICE });
24
+ function errorMessage(payload, status, statusText) {
28
25
  if (typeof payload === "string" && payload.trim() !== "") return payload;
29
- const record = toRecord(payload);
26
+ const record = asJsonObject(payload);
30
27
  const errors = Array.isArray(record?.errors) ? record.errors : [];
31
- const first = errors.map(toRecord).find(Boolean);
32
- const message = first === void 0 ? text(record?.detail) ?? text(record?.message) ?? text(record?.error) ?? text(record?.title) : text(first.detail) ?? text(first.title) ?? text(first.code);
33
- return message ?? (response.statusText || `Telnyx \u8FD4\u56DE HTTP ${response.status}`);
34
- }
35
- async function readPayload(response) {
36
- const body = await response.text().catch(() => "");
37
- if (body.trim() === "") return null;
38
- try {
39
- return JSON.parse(body);
40
- } catch {
41
- throw upstreamError(response.status === 429 ? 429 : 502, "Telnyx \u8FD4\u56DE\u4E86\u975E JSON \u54CD\u5E94");
42
- }
43
- }
44
- async function send(url, init) {
45
- try {
46
- return await guardedFetch(url.toString(), init);
47
- } catch (error) {
48
- if (error instanceof TypeError) {
49
- throw upstreamError(502, `telnyx request failed: ${error.message}`);
50
- }
51
- throw error;
52
- }
28
+ const first = errors.map(asJsonObject).find(Boolean);
29
+ const message = first === void 0 ? trimmedText(record?.detail) ?? trimmedText(record?.message) ?? trimmedText(record?.error) ?? trimmedText(record?.title) : trimmedText(first.detail) ?? trimmedText(first.title) ?? trimmedText(first.code);
30
+ return message ?? (statusText || `Telnyx \u8FD4\u56DE HTTP ${status}`);
53
31
  }
54
32
  async function request(ctx, path, input = {}) {
55
- const url = new URL(`${API_BASE}${path}`);
56
- for (const [name, value] of input.query ?? []) {
57
- if (value === void 0 || value === null || value === "") continue;
58
- url.searchParams.set(name, String(value));
59
- }
60
33
  const headers = {
61
34
  accept: "application/json",
62
35
  authorization: `Bearer ${requireApiKey(ctx, SERVICE)}`
63
36
  };
64
- if (input.body !== void 0) headers["content-type"] = "application/json";
65
- const response = await send(url, {
37
+ const response = await http.request({
66
38
  method: input.method ?? "GET",
39
+ path,
40
+ // 空串不进 query:Telnyx 会把 `filter[name]=` 读成"匹配空名字",而调用方省略一个
41
+ // 可选筛选时想要的是"不筛选"。
42
+ query: (input.query ?? []).filter(([, value]) => value !== void 0 && value !== null && value !== ""),
67
43
  headers,
68
44
  // JSON.stringify 自己会丢掉值为 undefined 的键,故不必复制上游的 removeUndefined;
69
45
  // 但 null 必须留住 —— schema 允许 sendAt 显式传 null,那是要发给 Telnyx 的值。
70
- ...input.body === void 0 ? {} : { body: JSON.stringify(input.body) }
46
+ ...input.body === void 0 ? {} : { json: input.body },
47
+ invalidJsonMessage: "Telnyx \u8FD4\u56DE\u4E86\u975E JSON \u54CD\u5E94",
48
+ mapError: ({ bodyKind, data, status, statusText }) => bodyKind === "invalid-json" ? upstreamError(status === 429 ? 429 : 502, "Telnyx \u8FD4\u56DE\u4E86\u975E JSON \u54CD\u5E94") : upstreamError(status, errorMessage(bodyKind === "empty" ? null : data, status, statusText)),
49
+ mapTransportError: ({ message }) => upstreamError(
50
+ 502,
51
+ message === void 0 ? "telnyx request failed" : `telnyx request failed: ${message}`
52
+ )
71
53
  });
72
- const payload = await readPayload(response);
73
- if (!response.ok) throw upstreamError(response.status, errorMessage(payload, response));
74
- const record = toRecord(payload);
54
+ const record = asJsonObject(response.bodyKind === "empty" ? null : response.data);
75
55
  if (record === void 0) {
76
56
  throw upstreamError(502, "Telnyx \u7684\u6210\u529F\u54CD\u5E94\u4E0D\u662F\u4E00\u4E2A\u5BF9\u8C61");
77
57
  }
@@ -1,118 +1,106 @@
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/todoist/api.ts
17
22
  var SERVICE = "todoist";
18
23
  var API_BASE = "https://api.todoist.com/api/v1";
19
24
  var USER_PATH = "/user";
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
- function compact(input) {
29
- return Object.fromEntries(Object.entries(input).filter(([, value]) => value !== void 0));
30
- }
25
+ var http = createProviderHttpClient({ baseUrl: `${API_BASE}/`, service: SERVICE });
31
26
  function requireText(value, field) {
32
- const result = text(value);
27
+ const result = trimmedText(value);
33
28
  if (result === void 0) throw new TBError("invalid_argument", `${field} is required.`);
34
29
  return result;
35
30
  }
36
31
  function stringArray(value) {
37
32
  if (!Array.isArray(value)) return void 0;
38
- const items = value.map((item) => text(item)).filter((item) => item !== void 0);
33
+ const items = value.map((item) => trimmedText(item)).filter((item) => item !== void 0);
39
34
  return items.length > 0 ? items : void 0;
40
35
  }
41
36
  function requireRecord(value, label) {
42
- const result = record(value);
37
+ const result = asJsonObject(value);
43
38
  if (result === void 0) throw new TBError("unavailable", `${label}\u4E0D\u662F\u5BF9\u8C61`, { retryable: true });
44
39
  return result;
45
40
  }
46
41
  function errorMessage(status, payload) {
47
- const body = record(payload);
48
- const direct = text(body?.error) ?? text(body?.error_description) ?? text(body?.message) ?? text(body?.detail);
42
+ const body = asJsonObject(payload);
43
+ const direct = trimmedText(body?.error) ?? trimmedText(body?.error_description) ?? trimmedText(body?.message) ?? trimmedText(body?.detail);
49
44
  if (direct !== void 0) return direct;
50
45
  if (Array.isArray(body?.errors)) {
51
- const first = body.errors.find((item) => text(item) !== void 0);
46
+ const first = body.errors.find((item) => trimmedText(item) !== void 0);
52
47
  if (first !== void 0) return first;
53
48
  }
54
49
  return `todoist request failed with ${status}`;
55
50
  }
56
51
  async function request(ctx, input) {
57
- const url = new URL(input.path.replace(/^\/+/, ""), `${API_BASE}/`);
58
- for (const [key, value] of Object.entries(input.query ?? {})) {
59
- if (value === void 0) continue;
60
- url.searchParams.set(key, Array.isArray(value) ? value.join(",") : String(value));
61
- }
62
52
  const hasBody = input.body !== void 0;
63
- const response = await guardedFetch(url.toString(), {
53
+ const query = Object.entries(input.query ?? {}).map(([key, value]) => [
54
+ key,
55
+ // 多值参数(list_tasks 的 ids)是**逗号串**,不是重复的同名参数。
56
+ Array.isArray(value) ? value.join(",") : value
57
+ ]);
58
+ const { data } = await http.request({
59
+ path: input.path,
64
60
  method: input.method ?? "GET",
61
+ query,
65
62
  headers: {
66
63
  accept: "application/json",
67
- authorization: `Bearer ${requireApiKey(ctx, SERVICE)}`,
68
- ...hasBody ? { "content-type": "application/json" } : {}
64
+ authorization: `Bearer ${requireApiKey(ctx, SERVICE)}`
69
65
  },
70
- body: hasBody ? JSON.stringify(input.body) : void 0
66
+ ...hasBody ? { json: input.body } : {},
67
+ invalidJsonMessage: "Todoist \u8FD4\u56DE\u4E86\u975E JSON \u54CD\u5E94",
68
+ mapError: ({ data: data2, status }) => upstreamError(
69
+ status,
70
+ errorMessage(status, typeof data2 === "string" ? { message: data2 } : data2)
71
+ )
71
72
  });
72
- const raw = await response.text();
73
- let payload = {};
74
- if (raw !== "") {
75
- try {
76
- payload = JSON.parse(raw);
77
- } catch {
78
- if (response.ok) {
79
- throw new TBError("unavailable", "Todoist \u8FD4\u56DE\u4E86\u975E JSON \u54CD\u5E94", { retryable: true });
80
- }
81
- payload = { message: raw };
82
- }
83
- }
84
- if (!response.ok) throw upstreamError(response.status, errorMessage(response.status, payload));
85
- return payload;
73
+ return data ?? {};
86
74
  }
87
75
  function results(payload, label) {
88
76
  const body = requireRecord(payload, `${label} \u54CD\u5E94`);
89
77
  if (!Array.isArray(body.results)) {
90
78
  throw new TBError("unavailable", `${label} \u54CD\u5E94\u7F3A\u5C11 results`, { retryable: true });
91
79
  }
92
- return body.results.map((item) => record(item)).filter((item) => item !== void 0);
80
+ return body.results.map((item) => asJsonObject(item)).filter((item) => item !== void 0);
93
81
  }
94
82
  function nextCursor(payload) {
95
- return text(record(payload)?.next_cursor) ?? null;
83
+ return trimmedText(asJsonObject(payload)?.next_cursor) ?? null;
96
84
  }
97
85
  function idValue(value) {
98
86
  if (typeof value === "number" && Number.isInteger(value)) return value;
99
- return text(value);
87
+ return trimmedText(value);
100
88
  }
101
89
  function normalizeComment(payload) {
102
90
  const comment = requireRecord(payload, "todoist comment");
103
- return compact({
91
+ return compactDefined({
104
92
  ...comment,
105
- attachment: record(comment.attachment) ?? record(comment.file_attachment)
93
+ attachment: asJsonObject(comment.attachment) ?? asJsonObject(comment.file_attachment)
106
94
  });
107
95
  }
108
96
  function commentAttachment(value) {
109
- const attachment = record(value);
97
+ const attachment = asJsonObject(value);
110
98
  if (attachment === void 0) return void 0;
111
- return compact({
112
- file_url: text(attachment.fileUrl),
113
- file_name: text(attachment.fileName),
114
- file_type: text(attachment.fileType),
115
- resource_type: text(attachment.resourceType)
99
+ return compactDefined({
100
+ file_url: trimmedText(attachment.fileUrl),
101
+ file_name: trimmedText(attachment.fileName),
102
+ file_type: trimmedText(attachment.fileType),
103
+ resource_type: trimmedText(attachment.resourceType)
116
104
  });
117
105
  }
118
106
  function notifyUserIds(value) {
@@ -121,20 +109,20 @@ function notifyUserIds(value) {
121
109
  return ids.length > 0 ? ids : void 0;
122
110
  }
123
111
  function taskBody(input, isCreate) {
124
- return compact({
125
- content: isCreate ? requireText(input.content, "content") : text(input.content),
112
+ return compactDefined({
113
+ content: isCreate ? requireText(input.content, "content") : trimmedText(input.content),
126
114
  description: input.description,
127
- project_id: text(input.projectId),
128
- section_id: text(input.sectionId),
129
- parent_id: text(input.parentId),
115
+ project_id: trimmedText(input.projectId),
116
+ section_id: trimmedText(input.sectionId),
117
+ parent_id: trimmedText(input.parentId),
130
118
  order: input.order,
131
119
  labels: stringArray(input.labels),
132
120
  priority: input.priority,
133
121
  assignee_id: input.assigneeId,
134
- due_string: text(input.dueString),
135
- due_date: text(input.dueDate),
136
- due_datetime: text(input.dueDatetime),
137
- due_lang: text(input.dueLang),
122
+ due_string: trimmedText(input.dueString),
123
+ due_date: trimmedText(input.dueDate),
124
+ due_datetime: trimmedText(input.dueDatetime),
125
+ due_lang: trimmedText(input.dueLang),
138
126
  duration: input.duration,
139
127
  duration_unit: input.durationUnit,
140
128
  deadline_date: input.deadlineDate,
@@ -152,7 +140,7 @@ async function listProjects(input, ctx) {
152
140
  query: {
153
141
  folder_id: idValue(input.folderId),
154
142
  workspace_id: idValue(input.workspaceId),
155
- cursor: text(input.cursor),
143
+ cursor: trimmedText(input.cursor),
156
144
  limit: input.limit
157
145
  }
158
146
  });
@@ -166,14 +154,14 @@ async function createProject(input, ctx) {
166
154
  const payload = await request(ctx, {
167
155
  path: "/projects",
168
156
  method: "POST",
169
- body: compact({
157
+ body: compactDefined({
170
158
  name: requireText(input.name, "name"),
171
- description: text(input.description),
159
+ description: trimmedText(input.description),
172
160
  // 上游显式区分 null(建成顶层项目)与"未给"(不带这个键)。
173
- parent_id: input.parentId === null ? null : text(input.parentId),
161
+ parent_id: input.parentId === null ? null : trimmedText(input.parentId),
174
162
  color: input.color,
175
163
  is_favorite: input.isFavorite,
176
- view_style: text(input.viewStyle),
164
+ view_style: trimmedText(input.viewStyle),
177
165
  workspace_id: idValue(input.workspaceId)
178
166
  })
179
167
  });
@@ -184,7 +172,7 @@ async function updateProject(input, ctx) {
184
172
  path: `/projects/${encodeURIComponent(requireText(input.projectId, "projectId"))}`,
185
173
  method: "POST",
186
174
  // 更新是三态字段:未给不改、null 清空、有值改成它 —— 故原样透传。
187
- body: compact({
175
+ body: compactDefined({
188
176
  name: input.name,
189
177
  description: input.description,
190
178
  color: input.color,
@@ -200,7 +188,7 @@ async function updateProject(input, ctx) {
200
188
  async function listSections(input, ctx) {
201
189
  const payload = await request(ctx, {
202
190
  path: "/sections",
203
- query: { project_id: text(input.projectId), cursor: text(input.cursor), limit: input.limit }
191
+ query: { project_id: trimmedText(input.projectId), cursor: trimmedText(input.cursor), limit: input.limit }
204
192
  });
205
193
  return { sections: results(payload, "todoist sections"), nextCursor: nextCursor(payload) };
206
194
  }
@@ -212,7 +200,7 @@ async function createSection(input, ctx) {
212
200
  const payload = await request(ctx, {
213
201
  path: "/sections",
214
202
  method: "POST",
215
- body: compact({
203
+ body: compactDefined({
216
204
  name: requireText(input.name, "name"),
217
205
  project_id: requireText(input.projectId, "projectId"),
218
206
  order: input.order
@@ -224,7 +212,7 @@ async function updateSection(input, ctx) {
224
212
  const payload = await request(ctx, {
225
213
  path: `/sections/${encodeURIComponent(requireText(input.sectionId, "sectionId"))}`,
226
214
  method: "POST",
227
- body: compact({
215
+ body: compactDefined({
228
216
  name: input.name,
229
217
  section_order: input.sectionOrder,
230
218
  is_collapsed: input.isCollapsed
@@ -236,13 +224,13 @@ async function listTasks(input, ctx) {
236
224
  const payload = await request(ctx, {
237
225
  path: "/tasks",
238
226
  query: {
239
- project_id: text(input.projectId),
240
- section_id: text(input.sectionId),
241
- parent_id: text(input.parentId),
242
- label: text(input.label),
227
+ project_id: trimmedText(input.projectId),
228
+ section_id: trimmedText(input.sectionId),
229
+ parent_id: trimmedText(input.parentId),
230
+ label: trimmedText(input.label),
243
231
  ids: stringArray(input.ids),
244
- goal_id: text(input.goalId),
245
- cursor: text(input.cursor),
232
+ goal_id: trimmedText(input.goalId),
233
+ cursor: trimmedText(input.cursor),
246
234
  limit: input.limit
247
235
  }
248
236
  });
@@ -275,9 +263,9 @@ async function listComments(input, ctx) {
275
263
  const payload = await request(ctx, {
276
264
  path: "/comments",
277
265
  query: {
278
- task_id: text(input.taskId),
279
- project_id: text(input.projectId),
280
- cursor: text(input.cursor),
266
+ task_id: trimmedText(input.taskId),
267
+ project_id: trimmedText(input.projectId),
268
+ cursor: trimmedText(input.cursor),
281
269
  limit: input.limit
282
270
  }
283
271
  });
@@ -294,10 +282,10 @@ async function createComment(input, ctx) {
294
282
  const payload = await request(ctx, {
295
283
  path: "/comments",
296
284
  method: "POST",
297
- body: compact({
285
+ body: compactDefined({
298
286
  content: requireText(input.content, "content"),
299
- task_id: text(input.taskId),
300
- project_id: text(input.projectId),
287
+ task_id: trimmedText(input.taskId),
288
+ project_id: trimmedText(input.projectId),
301
289
  attachment: commentAttachment(input.attachment),
302
290
  uids_to_notify: notifyUserIds(input.uidsToNotify)
303
291
  })
@@ -316,7 +304,7 @@ async function updateComment(input, ctx) {
316
304
  async function listLabels(input, ctx) {
317
305
  const payload = await request(ctx, {
318
306
  path: "/labels",
319
- query: { cursor: text(input.cursor), limit: input.limit }
307
+ query: { cursor: trimmedText(input.cursor), limit: input.limit }
320
308
  });
321
309
  return { labels: results(payload, "todoist labels"), nextCursor: nextCursor(payload) };
322
310
  }