@tool-bridge/server 0.16.0 → 0.19.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-23JBIM6X.js} +106 -114
  2. package/dist/{alt_text_generator_ai-4DIRIDKL.js → alt_text_generator_ai-ADWBTCIH.js} +25 -16
  3. package/dist/{amap-LGVGNPML.js → amap-CYQCYW2Z.js} +114 -123
  4. package/dist/{anthropic-27RFZO35.js → anthropic-5P62HDNR.js} +34 -56
  5. package/dist/{apify-6WLYAIAS.js → apify-54RZUAGW.js} +31 -49
  6. package/dist/{brave_search-K2SVJ66F.js → brave_search-AHJ6FTD5.js} +52 -77
  7. package/dist/{chunk-VK3V2WTY.js → chunk-B4P6YZFS.js} +4 -6
  8. package/dist/{chunk-BB6ZLMTU.js → chunk-CLEZ6YQ6.js} +2600 -481
  9. package/dist/chunk-JXHMDBAY.js +45 -0
  10. package/dist/chunk-LMLX3DJF.js +50 -0
  11. package/dist/{chunk-YB2FLNWI.js → chunk-OKRZPQ3R.js} +2558 -1926
  12. package/dist/chunk-SWBNHIO4.js +977 -0
  13. package/dist/chunk-U67V476Y.js +35 -0
  14. package/dist/chunk-VLOIDU5U.js +283 -0
  15. package/dist/{circleci-WV3ITU7Q.js → circleci-UM3NSQJ3.js} +36 -55
  16. package/dist/{clerk-NFQEFKS4.js → clerk-FE5LQ2CZ.js} +60 -80
  17. package/dist/{cloudflare_dns-2RK5ASBJ.js → cloudflare_dns-KEZABKUT.js} +90 -113
  18. package/dist/{cohere-5KEW7LWT.js → cohere-4IPJADXP.js} +33 -49
  19. package/dist/{confluence-SZE63S46.js → confluence-56QEKNQI.js} +79 -115
  20. package/dist/{convertapi-QPG2JC5K.js → convertapi-3QRM5K5T.js} +13 -16
  21. package/dist/{currencyapi-UO2APQRY.js → currencyapi-L6G4OND5.js} +30 -53
  22. package/dist/{deepseek-LJELIMM3.js → deepseek-LGC6HBFG.js} +30 -38
  23. package/dist/{docker_hub-2MFXSBOF.js → docker_hub-XDMK3BIU.js} +141 -157
  24. package/dist/{dropbox-GQYNTTVA.js → dropbox-4QARMFZU.js} +134 -141
  25. package/dist/{dub-KI2LHXST.js → dub-C6JSJKOT.js} +61 -93
  26. package/dist/{e2b-WO6ISY3C.js → e2b-6A6TVACJ.js} +39 -69
  27. package/dist/{exa-IZ7B3BPT.js → exa-SIWWW6AA.js} +49 -77
  28. package/dist/{fal_ai-LTMF36GJ.js → fal_ai-3IJXOKSP.js} +37 -44
  29. package/dist/{feishu-WM7SLSFD.js → feishu-L4KDA4DC.js} +4 -6
  30. package/dist/{feishu_custom_bot-66W3MXH2.js → feishu_custom_bot-SDM75H4P.js} +4 -5
  31. package/dist/{figma-2Z274VQZ.js → figma-6DD436DN.js} +56 -81
  32. package/dist/{firehydrant-IFI4R65V.js → firehydrant-SYSGYB3R.js} +40 -53
  33. package/dist/{fixer-BCCZEB3D.js → fixer-FZG7ASTF.js} +31 -43
  34. package/dist/{fly-755FXYB5.js → fly-HMRCZBUC.js} +50 -66
  35. package/dist/{front-4FZKKXXK.js → front-FAFSD7I3.js} +43 -66
  36. package/dist/{geocodio-WYKDJ3DP.js → geocodio-4D3TWENM.js} +37 -63
  37. package/dist/{ghost-5BNQTCOH.js → ghost-OSO2FOZS.js} +51 -57
  38. package/dist/{github-ULELF5VX.js → github-OR4I4RHE.js} +48 -41
  39. package/dist/{gmail-G34WT64J.js → gmail-5AOPJ63E.js} +26 -36
  40. package/dist/{googlecalendar-BQU255SC.js → googlecalendar-SOJIJUWH.js} +57 -78
  41. package/dist/{googledocs-HPCNQXYJ.js → googledocs-QSKN5TLN.js} +14 -22
  42. package/dist/{grafana-VOV24FIC.js → grafana-R3AIZM7M.js} +95 -122
  43. package/dist/{graphhopper-D5RXW6AP.js → graphhopper-4CR3QOAX.js} +32 -46
  44. package/dist/index.d.ts +108 -56
  45. package/dist/index.js +4 -3
  46. package/dist/{ip2proxy-DAYO7EKZ.js → ip2proxy-OBCG6X6J.js} +35 -42
  47. package/dist/{ipgeolocation_io-XD4PSLII.js → ipgeolocation_io-NHH3DTQW.js} +40 -60
  48. package/dist/{ipqualityscore-K27QEAWK.js → ipqualityscore-7POMCBEC.js} +30 -42
  49. package/dist/{jina_ai-E6UXFV2P.js → jina_ai-YXVKROV4.js} +32 -58
  50. package/dist/{jira-ZDSXGQ6W.js → jira-LADO3VJU.js} +116 -126
  51. package/dist/{langsmith-TIFJRREW.js → langsmith-XZ6UAQFU.js} +101 -121
  52. package/dist/{lemlist-DASEMJMA.js → lemlist-P74GLNE7.js} +57 -68
  53. package/dist/{linear-KE6UP4SP.js → linear-CXJ7D37A.js} +109 -118
  54. package/dist/{logsnag-IMNDN4R5.js → logsnag-EVVHWFLK.js} +31 -48
  55. package/dist/main.js +103 -102
  56. package/dist/{mattermost-HHHMUXQA.js → mattermost-WG2MRGBD.js} +45 -62
  57. package/dist/{mem0-D2FGGOIY.js → mem0-HQWUKG6U.js} +72 -98
  58. package/dist/{memos-4OVIGFPH.js → memos-SQMJIFOE.js} +68 -122
  59. package/dist/{metabase-33WCX5YD.js → metabase-E27G2DZI.js} +47 -60
  60. package/dist/{mistral_ai-QIMZ2JYL.js → mistral_ai-MIL63NIT.js} +35 -40
  61. package/dist/{mother_duck-M6VWS2VH.js → mother_duck-AIZVCBNR.js} +42 -62
  62. package/dist/{ngrok-Z2PKQBHH.js → ngrok-XS4DVIQS.js} +42 -58
  63. package/dist/{notes-SS4RPC4K.js → notes-JEOUSL2Y.js} +3 -5
  64. package/dist/{notion-FJCNQ6I7.js → notion-U4EZVDW2.js} +83 -97
  65. package/dist/{open_exchange_rates-WU57WTT5.js → open_exchange_rates-AZSQEYEJ.js} +35 -39
  66. package/dist/{openai-JODZ4GKT.js → openai-HW3SYMTQ.js} +51 -55
  67. package/dist/{opengraph_io-SQRAUSV5.js → opengraph_io-QX74MAEL.js} +61 -79
  68. package/dist/{openrouter-Q5XXEJZ7.js → openrouter-OXSKYL6N.js} +41 -55
  69. package/dist/{outline-RT2EHJ2X.js → outline-CCQAPDSW.js} +89 -104
  70. package/dist/{paddle-OF2V7GAC.js → paddle-6KQPSSCK.js} +34 -49
  71. package/dist/{perplexity-LNZEWLHG.js → perplexity-2TXO7IQE.js} +33 -50
  72. package/dist/{pinecone-JSJIXZYN.js → pinecone-YOO7NULI.js} +65 -91
  73. package/dist/{pipedrive-D4CKVUXR.js → pipedrive-Q6RIFIFP.js} +37 -59
  74. package/dist/{polar-M7ZYP6UR.js → polar-KUMGCES3.js} +43 -53
  75. package/dist/{posthog-YV7CZOH4.js → posthog-VXQHBSMB.js} +58 -77
  76. package/dist/{postmark-KYHLECRG.js → postmark-YLIPF52S.js} +52 -71
  77. package/dist/{prerender-HCMHBKV2.js → prerender-CRY7UJN5.js} +32 -50
  78. package/dist/{pubmed-WYVLCCN3.js → pubmed-3Z4T5AM7.js} +28 -60
  79. package/dist/{railway-TWIRD5KR.js → railway-BP37IGFL.js} +32 -39
  80. package/dist/{readwise-UZ467IQ7.js → readwise-HTKICF4K.js} +62 -78
  81. package/dist/{render-MECUC5CC.js → render-WIVTUXJH.js} +48 -64
  82. package/dist/{replicate-A5MEK3SW.js → replicate-JJYPA43D.js} +41 -58
  83. package/dist/{resend-BC6EAWJQ.js → resend-TKHZVG7A.js} +27 -37
  84. package/dist/{rootly-ZM3QDUIS.js → rootly-FRSZLG5U.js} +64 -76
  85. package/dist/{scrapfly-WAML42QJ.js → scrapfly-M5WXGQWE.js} +45 -51
  86. package/dist/{scrapingbee-DG7PET3V.js → scrapingbee-PMXNLLBK.js} +25 -33
  87. package/dist/{screenshot_fyi-HY6WTHIO.js → screenshot_fyi-HFW4TAOH.js} +29 -47
  88. package/dist/{semantic_scholar-C5IZA7IP.js → semantic_scholar-KXVH2VZQ.js} +37 -56
  89. package/dist/{sentry-OKBPSTDM.js → sentry-WWOT2LRX.js} +66 -85
  90. package/dist/{shodan-PPC6DYU4.js → shodan-FY635H35.js} +42 -53
  91. package/dist/{shopify-EWGUHBXO.js → shopify-HQLBVSA5.js} +32 -49
  92. package/dist/{stripe-6RPDPC5W.js → stripe-GJN2GOHB.js} +4 -5
  93. package/dist/{supabase-SK7DQ42N.js → supabase-BBNZGQU6.js} +69 -88
  94. package/dist/{tavily-YCG5VQMH.js → tavily-DPENIBOG.js} +37 -62
  95. package/dist/{telegram-2OES5FYB.js → telegram-L4NONG6H.js} +168 -177
  96. package/dist/{telnyx-POOSBBR4.js → telnyx-H67MAEZS.js} +30 -50
  97. package/dist/{todoist-M7YD6YSS.js → todoist-G2BSP4DX.js} +77 -89
  98. package/dist/{trello-IS6V5W3E.js → trello-7WMVFDG2.js} +108 -122
  99. package/dist/{turso-RCFHUFVH.js → turso-ZUAESFC2.js} +52 -64
  100. package/dist/{twilio-OS2RXFGO.js → twilio-EYFYIX3B.js} +48 -55
  101. package/dist/{umami-PQ2SJ2LN.js → umami-AXAUDUVF.js} +49 -69
  102. package/dist/{unsplash-C6BPZO4E.js → unsplash-UCQAWPLR.js} +35 -52
  103. package/dist/{upstash_redis-WH6UER7H.js → upstash_redis-ZPZ4ASU6.js} +28 -40
  104. package/dist/{uptimerobot-M3YZGS6Z.js → uptimerobot-4QVKKUD5.js} +11 -12
  105. package/dist/{v2ex-R4JWTEHN.js → v2ex-VGEFJTYC.js} +36 -61
  106. package/dist/{vercel-FZVYUOQD.js → vercel-JME4TSCN.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-TRGU2MDG.js} +26 -34
  109. package/dist/{wordpress-XRWGO6LG.js → wordpress-WRUKLCZR.js} +87 -104
  110. package/dist/{workos-WR4NKOYL.js → workos-ZDW4EHS4.js} +37 -56
  111. package/dist/{zhihu-BKZIB3WA.js → zhihu-4VI67CWU.js} +35 -57
  112. package/package.json +3 -3
  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,74 +1,48 @@
1
+ import {
2
+ createProviderHttpClient
3
+ } from "./chunk-VLOIDU5U.js";
4
+ import {
5
+ messageFrom
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-B4P6YZFS.js";
12
+ import "./chunk-SWBNHIO4.js";
10
13
  import {
11
- TBError,
12
14
  external_exports
13
- } from "./chunk-YB2FLNWI.js";
14
- import "./chunk-MLKGABMK.js";
15
+ } from "./chunk-OKRZPQ3R.js";
16
+ import "./chunk-U67V476Y.js";
15
17
 
16
18
  // ../plugins/src/jina_ai/api.ts
17
19
  var SERVICE = "jina_ai";
18
- var API_BASE = "https://api.jina.ai";
19
20
  var REQUEST_TIMEOUT_MS = 3e4;
20
- function record(value) {
21
- return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
22
- }
23
- function text(value) {
24
- if (typeof value !== "string") return void 0;
25
- const trimmed = value.trim();
26
- return trimmed === "" ? void 0 : trimmed;
27
- }
28
- function errorMessage(status, body, payload) {
29
- const top = record(payload);
30
- return text(top?.detail) ?? text(top?.message) ?? text(body) ?? `Jina AI request failed with ${status}`;
31
- }
21
+ var http = createProviderHttpClient({ baseUrl: "https://api.jina.ai/", service: SERVICE });
32
22
  async function request(ctx, path, body) {
33
- const apiKey = requireApiKey(ctx, SERVICE);
34
- const timeoutSignal = AbortSignal.timeout(REQUEST_TIMEOUT_MS);
35
- let response;
36
- try {
37
- response = await guardedFetch(`${API_BASE}${path}`, {
38
- method: "POST",
39
- headers: {
40
- "accept": "application/json",
41
- "authorization": `Bearer ${apiKey}`,
42
- "content-type": "application/json"
43
- },
44
- body: JSON.stringify(body),
45
- signal: timeoutSignal
46
- });
47
- } catch (error) {
48
- if (error instanceof TBError) throw error;
49
- if (timeoutSignal.aborted) throw upstreamError(504, `Jina AI ${REQUEST_TIMEOUT_MS / 1e3}s \u5185\u6CA1\u6709\u8FD4\u56DE`);
50
- const message = error instanceof Error ? error.message : "unknown network error";
51
- throw upstreamError(502, `Jina AI \u8BF7\u6C42\u5931\u8D25: ${message}`);
52
- }
53
- const raw = await response.text();
54
- let payload = null;
55
- if (raw !== "") {
56
- try {
57
- payload = JSON.parse(raw);
58
- } catch {
59
- if (response.ok) {
60
- throw new TBError("unavailable", "Jina AI \u8FD4\u56DE\u4E86\u975E JSON \u54CD\u5E94", { retryable: true });
61
- }
62
- }
63
- }
64
- if (!response.ok) throw upstreamError(response.status, errorMessage(response.status, raw, payload));
65
- return payload;
23
+ const { data } = await http.request({
24
+ path,
25
+ method: "POST",
26
+ headers: {
27
+ accept: "application/json",
28
+ authorization: `Bearer ${requireApiKey(ctx, SERVICE)}`
29
+ },
30
+ json: body,
31
+ timeoutMs: REQUEST_TIMEOUT_MS,
32
+ invalidJsonMessage: "Jina AI \u8FD4\u56DE\u4E86\u975E JSON \u54CD\u5E94",
33
+ mapError: ({ data: payload, status }) => upstreamError(
34
+ status,
35
+ messageFrom(payload, ["detail", "message"], `Jina AI request failed with ${status}`)
36
+ ),
37
+ mapTransportError: ({ kind, message }) => kind === "timeout" ? upstreamError(504, `Jina AI ${REQUEST_TIMEOUT_MS / 1e3}s \u5185\u6CA1\u6709\u8FD4\u56DE`) : upstreamError(502, `Jina AI \u8BF7\u6C42\u5931\u8D25: ${message ?? "unknown network error"}`)
38
+ });
39
+ return data ?? null;
66
40
  }
67
- async function createEmbeddings(input, ctx) {
68
- return request(ctx, "/v1/embeddings", input);
41
+ function createEmbeddings(input, ctx) {
42
+ return request(ctx, "v1/embeddings", input);
69
43
  }
70
- async function rerankDocuments(input, ctx) {
71
- return request(ctx, "/v1/rerank", input);
44
+ function rerankDocuments(input, ctx) {
45
+ return request(ctx, "v1/rerank", input);
72
46
  }
73
47
 
74
48
  // ../plugins/src/jina_ai/schema.ts
@@ -1,22 +1,31 @@
1
+ import {
2
+ createProviderHttpClient
3
+ } from "./chunk-VLOIDU5U.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
  requireCredential,
4
14
  upstreamError
5
- } from "./chunk-VK3V2WTY.js";
15
+ } from "./chunk-B4P6YZFS.js";
6
16
  import {
7
- assertPublicHttpUrl,
8
- guardedFetch
9
- } from "./chunk-2O27H4Y2.js";
10
- import "./chunk-GKX72JMJ.js";
17
+ assertPublicHttpUrl
18
+ } from "./chunk-SWBNHIO4.js";
11
19
  import {
12
20
  TBError,
13
21
  external_exports
14
- } from "./chunk-YB2FLNWI.js";
15
- import "./chunk-MLKGABMK.js";
22
+ } from "./chunk-OKRZPQ3R.js";
23
+ import "./chunk-U67V476Y.js";
16
24
 
17
25
  // ../plugins/src/jira/api.ts
18
26
  var SERVICE = "jira";
19
27
  var DEFAULT_LIMIT = 50;
28
+ var http = createProviderHttpClient({ service: SERVICE });
20
29
  var DEFAULT_ISSUE_FIELD_IDS = [
21
30
  "summary",
22
31
  "description",
@@ -31,32 +40,13 @@ var DEFAULT_ISSUE_FIELD_IDS = [
31
40
  "updated",
32
41
  "duedate"
33
42
  ];
34
- function text(value) {
35
- if (typeof value !== "string") return void 0;
36
- const trimmed = value.trim();
37
- return trimmed === "" ? void 0 : trimmed;
38
- }
39
- function record(value) {
40
- return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
41
- }
42
- function integer(value) {
43
- return typeof value === "number" && Number.isInteger(value) ? value : void 0;
44
- }
45
- function boolean(value) {
46
- return typeof value === "boolean" ? value : void 0;
47
- }
48
- function compact(input) {
49
- return Object.fromEntries(
50
- Object.entries(input).filter(([, value]) => value !== void 0)
51
- );
52
- }
53
43
  function stringArray(value) {
54
44
  if (!Array.isArray(value)) return [];
55
- return value.map((item) => text(item)).filter((item) => item !== void 0);
45
+ return value.map((item) => trimmedText(item)).filter((item) => item !== void 0);
56
46
  }
57
47
  function recordArray(value) {
58
48
  if (!Array.isArray(value)) return [];
59
- return value.map((item) => record(item)).filter((item) => item !== void 0);
49
+ return value.map((item) => asJsonObject(item)).filter((item) => item !== void 0);
60
50
  }
61
51
  function joinOptionalList(values) {
62
52
  return values.length > 0 ? values.join(",") : void 0;
@@ -98,7 +88,7 @@ function buildUrl(base, pathOrUrl, query) {
98
88
  const target = isAbsoluteUrl(pathOrUrl) ? new URL(pathOrUrl) : new URL(pathOrUrl.replace(/^\/+/, ""), `${base}/`);
99
89
  const baseUrl = new URL(base);
100
90
  if (target.origin !== baseUrl.origin || !target.pathname.startsWith(`${baseUrl.pathname}/`)) {
101
- throw new TBError("invalid_argument", `jira requests must target ${base}`);
91
+ throw new TBError("invalid_argument", "jira requests must target the configured API base");
102
92
  }
103
93
  for (const [key, value] of Object.entries(query ?? {})) {
104
94
  if (value === void 0 || value === "") continue;
@@ -107,53 +97,53 @@ function buildUrl(base, pathOrUrl, query) {
107
97
  return target.toString();
108
98
  }
109
99
  function errorMessage(payload) {
110
- const body = record(payload);
100
+ const body = asJsonObject(payload);
111
101
  if (body === void 0) return "jira request failed";
112
102
  const messages = stringArray(body.errorMessages);
113
103
  if (messages.length > 0) return messages.join("; ");
114
- const fieldErrors = record(body.errors);
104
+ const fieldErrors = asJsonObject(body.errors);
115
105
  if (fieldErrors !== void 0) {
116
106
  const parts = [];
117
107
  for (const [key, value] of Object.entries(fieldErrors)) {
118
- const message = text(value);
108
+ const message = trimmedText(value);
119
109
  if (message !== void 0) parts.push(`${key}: ${message}`);
120
110
  }
121
111
  if (parts.length > 0) return parts.join("; ");
122
112
  }
123
- return text(body.message) ?? "jira request failed";
113
+ return trimmedText(body.message) ?? "jira request failed";
124
114
  }
125
- async function readPayload(response) {
126
- const raw = await response.text().catch(() => "");
127
- if (raw === "") return {};
128
- try {
129
- return JSON.parse(raw);
130
- } catch {
131
- return { message: raw };
132
- }
115
+ function responsePayload(data, bodyKind) {
116
+ if (bodyKind === "empty") return {};
117
+ return bodyKind === "invalid-json" ? { message: data } : data;
133
118
  }
134
119
  async function requestValue(ctx, options) {
135
- const headers = {
136
- accept: "application/json",
137
- authorization: `Bearer ${requireCredential(ctx, SERVICE, "personalAccessToken")}`
138
- };
139
- if (options.body !== void 0) headers["content-type"] = "application/json";
140
- const response = await guardedFetch(buildUrl(apiBaseUrl(ctx), options.path, options.query), {
120
+ const baseUrl = apiBaseUrl(ctx);
121
+ const result = await http.request({
122
+ baseUrl,
123
+ // create_issue 会跟随 Jira 返回的 self;buildUrl 先锁定 origin 与 REST API path 前缀。
124
+ path: buildUrl(baseUrl, options.path, options.query),
141
125
  method: options.method ?? (options.body === void 0 ? "GET" : "POST"),
142
- headers,
143
- ...options.body === void 0 ? {} : { body: JSON.stringify(options.body) }
126
+ headers: {
127
+ accept: "application/json",
128
+ authorization: `Bearer ${requireCredential(ctx, SERVICE, "personalAccessToken")}`
129
+ },
130
+ ...options.body === void 0 ? {} : { json: options.body },
131
+ invalidJson: "text",
132
+ mapError: ({ bodyKind, data, status }) => upstreamError(
133
+ status,
134
+ errorMessage(responsePayload(data, bodyKind))
135
+ )
144
136
  });
145
- const payload = await readPayload(response);
146
- if (!response.ok) throw upstreamError(response.status, errorMessage(payload));
147
- return payload;
137
+ return responsePayload(result.data, result.bodyKind);
148
138
  }
149
139
  async function requestObject(ctx, options) {
150
140
  const payload = await requestValue(ctx, options);
151
- const body = record(payload);
141
+ const body = asJsonObject(payload);
152
142
  if (body === void 0) throw upstreamError(502, "jira response payload must be a JSON object");
153
143
  return body;
154
144
  }
155
145
  function parseCursor(value) {
156
- const cursor = text(value);
146
+ const cursor = trimmedText(value);
157
147
  if (cursor === void 0) return 0;
158
148
  const parsed = Number(cursor);
159
149
  if (!Number.isInteger(parsed) || parsed < 0) {
@@ -168,86 +158,86 @@ function nextNumericCursor(startAt, itemCount, total, isLast) {
168
158
  return String(startAt + itemCount);
169
159
  }
170
160
  function requireText(value, field) {
171
- const result = text(value);
161
+ const result = trimmedText(value);
172
162
  if (result === void 0) throw new TBError("invalid_argument", `${field} is required`);
173
163
  return result;
174
164
  }
175
165
  function normalizeUser(value) {
176
- const user = record(value);
166
+ const user = asJsonObject(value);
177
167
  if (user === void 0) return void 0;
178
- return compact({
179
- accountId: text(user.accountId),
180
- accountType: text(user.accountType),
168
+ return compactDefined({
169
+ accountId: trimmedText(user.accountId),
170
+ accountType: trimmedText(user.accountType),
181
171
  // DC 用 name/key 标识用户,而不是 Cloud 的 accountId。
182
- name: text(user.name),
183
- key: text(user.key),
184
- displayName: text(user.displayName),
185
- emailAddress: text(user.emailAddress),
186
- active: boolean(user.active),
187
- self: text(user.self),
188
- timeZone: text(user.timeZone)
172
+ name: trimmedText(user.name),
173
+ key: trimmedText(user.key),
174
+ displayName: trimmedText(user.displayName),
175
+ emailAddress: trimmedText(user.emailAddress),
176
+ active: booleanValue(user.active),
177
+ self: trimmedText(user.self),
178
+ timeZone: trimmedText(user.timeZone)
189
179
  });
190
180
  }
191
181
  function normalizeNamedReference(value) {
192
- const reference = record(value);
182
+ const reference = asJsonObject(value);
193
183
  if (reference === void 0) return void 0;
194
- return compact({
195
- id: text(reference.id),
196
- name: text(reference.name),
197
- key: text(reference.key),
198
- self: text(reference.self),
199
- description: text(reference.description)
184
+ return compactDefined({
185
+ id: trimmedText(reference.id),
186
+ name: trimmedText(reference.name),
187
+ key: trimmedText(reference.key),
188
+ self: trimmedText(reference.self),
189
+ description: trimmedText(reference.description)
200
190
  });
201
191
  }
202
192
  function normalizeProject(project) {
203
- return compact({
204
- id: text(project.id),
205
- key: text(project.key),
206
- name: text(project.name),
207
- self: text(project.self),
208
- description: text(project.description),
209
- projectTypeKey: text(project.projectTypeKey),
210
- simplified: boolean(project.simplified),
211
- style: text(project.style),
212
- url: text(project.url),
193
+ return compactDefined({
194
+ id: trimmedText(project.id),
195
+ key: trimmedText(project.key),
196
+ name: trimmedText(project.name),
197
+ self: trimmedText(project.self),
198
+ description: trimmedText(project.description),
199
+ projectTypeKey: trimmedText(project.projectTypeKey),
200
+ simplified: booleanValue(project.simplified),
201
+ style: trimmedText(project.style),
202
+ url: trimmedText(project.url),
213
203
  lead: normalizeUser(project.lead),
214
204
  projectCategory: normalizeNamedReference(project.projectCategory),
215
- avatarUrls: record(project.avatarUrls),
205
+ avatarUrls: asJsonObject(project.avatarUrls),
216
206
  raw: project
217
207
  });
218
208
  }
219
209
  function normalizeIssue(issue) {
220
- const fields = record(issue.fields) ?? {};
221
- return compact({
222
- id: text(issue.id),
223
- key: text(issue.key),
224
- self: text(issue.self),
225
- summary: text(fields.summary),
210
+ const fields = asJsonObject(issue.fields) ?? {};
211
+ return compactDefined({
212
+ id: trimmedText(issue.id),
213
+ key: trimmedText(issue.key),
214
+ self: trimmedText(issue.self),
215
+ summary: trimmedText(fields.summary),
226
216
  description: fields.description,
227
217
  status: normalizeNamedReference(fields.status),
228
218
  issueType: normalizeNamedReference(fields.issuetype),
229
- project: record(fields.project) === void 0 ? void 0 : normalizeProject(record(fields.project)),
219
+ project: asJsonObject(fields.project) === void 0 ? void 0 : normalizeProject(asJsonObject(fields.project)),
230
220
  assignee: normalizeUser(fields.assignee),
231
221
  reporter: normalizeUser(fields.reporter),
232
222
  priority: normalizeNamedReference(fields.priority),
233
223
  labels: stringArray(fields.labels),
234
- created: text(fields.created),
235
- updated: text(fields.updated),
236
- dueDate: text(fields.duedate),
224
+ created: trimmedText(fields.created),
225
+ updated: trimmedText(fields.updated),
226
+ dueDate: trimmedText(fields.duedate),
237
227
  fields,
238
228
  raw: issue
239
229
  });
240
230
  }
241
231
  function normalizeComment(comment) {
242
- return compact({
243
- id: text(comment.id),
244
- self: text(comment.self),
232
+ return compactDefined({
233
+ id: trimmedText(comment.id),
234
+ self: trimmedText(comment.self),
245
235
  body: comment.body,
246
236
  author: normalizeUser(comment.author),
247
237
  updateAuthor: normalizeUser(comment.updateAuthor),
248
- created: text(comment.created),
249
- updated: text(comment.updated),
250
- jsdPublic: boolean(comment.jsdPublic),
238
+ created: trimmedText(comment.created),
239
+ updated: trimmedText(comment.updated),
240
+ jsdPublic: booleanValue(comment.jsdPublic),
251
241
  raw: comment
252
242
  });
253
243
  }
@@ -255,19 +245,19 @@ function rawText(value) {
255
245
  return typeof value === "string" && value !== "" ? value : void 0;
256
246
  }
257
247
  function appendAdfText(value, parts) {
258
- const node = record(value);
248
+ const node = asJsonObject(value);
259
249
  if (node === void 0) return;
260
- const type = text(node.type);
250
+ const type = trimmedText(node.type);
261
251
  if (type === "text") {
262
252
  const content = rawText(node.text);
263
253
  if (content !== void 0) parts.push(content);
264
254
  } else if (type === "hardBreak") {
265
255
  parts.push("\n");
266
256
  } else if (type === "mention" || type === "emoji" || type === "date" || type === "status") {
267
- const content = rawText(record(node.attrs)?.text);
257
+ const content = rawText(asJsonObject(node.attrs)?.text);
268
258
  if (content !== void 0) parts.push(content);
269
259
  } else if (type === "inlineCard") {
270
- const url = rawText(record(node.attrs)?.url);
260
+ const url = rawText(asJsonObject(node.attrs)?.url);
271
261
  if (url !== void 0) parts.push(url);
272
262
  }
273
263
  const children = Array.isArray(node.content) ? node.content : [];
@@ -286,7 +276,7 @@ async function listProjects(input, ctx) {
286
276
  const startAt = parseCursor(input.cursor);
287
277
  const payload = await requestValue(ctx, {
288
278
  path: "/project",
289
- query: compact({ expand: joinOptionalList(stringArray(input.expand)) })
279
+ query: compactDefined({ expand: joinOptionalList(stringArray(input.expand)) })
290
280
  });
291
281
  const projects = recordArray(payload).map((project) => normalizeProject(project));
292
282
  const page = projects.slice(startAt, startAt + limit);
@@ -300,7 +290,7 @@ async function listProjects(input, ctx) {
300
290
  async function getProject(input, ctx) {
301
291
  const payload = await requestObject(ctx, {
302
292
  path: `/project/${encodeURIComponent(requireText(input.projectIdOrKey, "projectIdOrKey"))}`,
303
- query: compact({ expand: joinOptionalList(stringArray(input.expand)) })
293
+ query: compactDefined({ expand: joinOptionalList(stringArray(input.expand)) })
304
294
  });
305
295
  return { project: normalizeProject(payload) };
306
296
  }
@@ -309,7 +299,7 @@ async function searchIssues(input, ctx) {
309
299
  const payload = await requestObject(ctx, {
310
300
  path: "/search",
311
301
  method: "POST",
312
- body: compact({
302
+ body: compactDefined({
313
303
  jql: requireText(input.jql, "jql"),
314
304
  maxResults: input.limit ?? DEFAULT_LIMIT,
315
305
  // DC 的 POST /rest/api/2/search 绑的是 SearchRequestBean,fields 与 expand 都收**数组**;
@@ -323,14 +313,14 @@ async function searchIssues(input, ctx) {
323
313
  return {
324
314
  issues: issues.map((issue) => normalizeIssue(issue)),
325
315
  pagination: {
326
- nextCursor: nextNumericCursor(startAt, issues.length, integer(payload.total))
316
+ nextCursor: nextNumericCursor(startAt, issues.length, integerValue(payload.total))
327
317
  }
328
318
  };
329
319
  }
330
320
  async function getIssue(input, ctx) {
331
321
  const payload = await requestObject(ctx, {
332
322
  path: `/issue/${encodeURIComponent(requireText(input.issueIdOrKey, "issueIdOrKey"))}`,
333
- query: compact({
323
+ query: compactDefined({
334
324
  // 这个端点上 fields 是**逗号串**,不是数组。
335
325
  fields: joinOptionalList(mergeUniqueFieldIds(DEFAULT_ISSUE_FIELD_IDS, stringArray(input.includeFields))),
336
326
  expand: joinOptionalList(stringArray(input.expand))
@@ -339,42 +329,42 @@ async function getIssue(input, ctx) {
339
329
  return { issue: normalizeIssue(payload) };
340
330
  }
341
331
  function projectReference(input) {
342
- const projectId = text(input.projectId);
332
+ const projectId = trimmedText(input.projectId);
343
333
  if (projectId !== void 0) return { id: projectId };
344
- const projectKey = text(input.projectKey);
334
+ const projectKey = trimmedText(input.projectKey);
345
335
  if (projectKey !== void 0) return { key: projectKey };
346
336
  throw new TBError("invalid_argument", "projectKey or projectId is required");
347
337
  }
348
338
  function issueTypeReference(input) {
349
- const issueTypeId = text(input.issueTypeId);
339
+ const issueTypeId = trimmedText(input.issueTypeId);
350
340
  if (issueTypeId !== void 0) return { id: issueTypeId };
351
- const issueTypeName = text(input.issueTypeName);
341
+ const issueTypeName = trimmedText(input.issueTypeName);
352
342
  if (issueTypeName !== void 0) return { name: issueTypeName };
353
343
  throw new TBError("invalid_argument", "issueTypeId or issueTypeName is required");
354
344
  }
355
345
  async function createIssue(input, ctx) {
356
- const description = record(input.description);
357
- const explicitFields = compact({
346
+ const description = asJsonObject(input.description);
347
+ const explicitFields = compactDefined({
358
348
  project: projectReference(input),
359
349
  issuetype: issueTypeReference(input),
360
350
  summary: requireText(input.summary, "summary"),
361
351
  // DC 的 description 是纯文本:给了 ADF 就拍平,只给了 descriptionText 就直接用。
362
- description: description !== void 0 ? adfToPlainText(description) : text(input.descriptionText),
352
+ description: description !== void 0 ? adfToPlainText(description) : trimmedText(input.descriptionText),
363
353
  // 上游这里用的是 `readStringArray`,没给 labels 时得到的是 `[]` 而非 undefined,于是
364
354
  // 创建请求总会带上 `labels: []`。保留这个行为(创建时本就没有标签,发空数组无副作用)。
365
355
  labels: stringArray(input.labels),
366
- assignee: text(input.assigneeAccountId) === void 0 ? void 0 : { name: text(input.assigneeAccountId) },
367
- priority: text(input.priorityId) === void 0 ? void 0 : { id: text(input.priorityId) },
368
- duedate: text(input.dueDate),
369
- parent: text(input.parentIssueKey) === void 0 ? void 0 : { key: text(input.parentIssueKey) }
356
+ assignee: trimmedText(input.assigneeAccountId) === void 0 ? void 0 : { name: trimmedText(input.assigneeAccountId) },
357
+ priority: trimmedText(input.priorityId) === void 0 ? void 0 : { id: trimmedText(input.priorityId) },
358
+ duedate: trimmedText(input.dueDate),
359
+ parent: trimmedText(input.parentIssueKey) === void 0 ? void 0 : { key: trimmedText(input.parentIssueKey) }
370
360
  });
371
361
  const created = await requestObject(ctx, {
372
362
  path: "/issue",
373
363
  method: "POST",
374
364
  // extraFields 在前:同名键由显式入参覆盖,免得裸传的 extraFields 悄悄改掉 summary 之类。
375
- body: { fields: { ...record(input.extraFields) ?? {}, ...explicitFields } }
365
+ body: { fields: { ...asJsonObject(input.extraFields) ?? {}, ...explicitFields } }
376
366
  });
377
- const createdRef = text(created.key) ?? text(created.id) ?? text(created.self);
367
+ const createdRef = trimmedText(created.key) ?? trimmedText(created.id) ?? trimmedText(created.self);
378
368
  if (createdRef === void 0) throw upstreamError(502, "missing jira created issue self");
379
369
  const issue = await requestObject(ctx, {
380
370
  // self 是绝对地址,`buildUrl` 会验它仍落在 base URL 之内。
@@ -388,7 +378,7 @@ async function listIssueComments(input, ctx) {
388
378
  const startAt = parseCursor(input.cursor);
389
379
  const payload = await requestObject(ctx, {
390
380
  path: `/issue/${encodeURIComponent(requireText(input.issueIdOrKey, "issueIdOrKey"))}/comment`,
391
- query: compact({
381
+ query: compactDefined({
392
382
  maxResults: String(limit),
393
383
  startAt: String(startAt),
394
384
  expand: joinOptionalList(stringArray(input.expand))
@@ -397,12 +387,12 @@ async function listIssueComments(input, ctx) {
397
387
  const comments = recordArray(payload.comments).map((comment) => normalizeComment(comment));
398
388
  return {
399
389
  comments,
400
- pagination: { nextCursor: nextNumericCursor(startAt, comments.length, integer(payload.total)) }
390
+ pagination: { nextCursor: nextNumericCursor(startAt, comments.length, integerValue(payload.total)) }
401
391
  };
402
392
  }
403
393
  async function addComment(input, ctx) {
404
- const document = record(input.body);
405
- const body = document !== void 0 ? adfToPlainText(document) : text(input.bodyText);
394
+ const document = asJsonObject(input.body);
395
+ const body = document !== void 0 ? adfToPlainText(document) : trimmedText(input.bodyText);
406
396
  if (body === void 0 || body === "") {
407
397
  throw new TBError("invalid_argument", "comment body or bodyText is required");
408
398
  }