@oomol-lab/open-connector 1.6.2 → 1.6.4

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 (175) hide show
  1. package/README.md +27 -0
  2. package/assets/open-connector/catalog/apps/assured_platform.json +218 -0
  3. package/assets/open-connector/catalog/apps/baixiao.json +1080 -0
  4. package/assets/open-connector/catalog/apps/benchmarkone.json +956 -0
  5. package/assets/open-connector/catalog/apps/bing_webmaster.json +3097 -0
  6. package/assets/open-connector/catalog/apps/buzzsprout.json +1979 -0
  7. package/assets/open-connector/catalog/apps/feishu.json +13 -19
  8. package/assets/open-connector/catalog/apps/feishu_app_bot.json +12 -19
  9. package/assets/open-connector/catalog/apps/jin10.json +1 -1
  10. package/assets/open-connector/catalog/apps/linkfox.json +836 -0
  11. package/assets/open-connector/catalog/apps/metatraderapi.json +1077 -0
  12. package/assets/open-connector/catalog/apps/mktindex.json +2411 -0
  13. package/assets/open-connector/catalog/apps/mojo_helpdesk.json +660 -0
  14. package/assets/open-connector/catalog/apps/mumble.json +446 -0
  15. package/assets/open-connector/catalog/apps/notion.json +112 -3
  16. package/assets/open-connector/catalog/apps/omise.json +438 -0
  17. package/assets/open-connector/catalog/apps/panjiva.json +2858 -0
  18. package/assets/open-connector/catalog/apps/papertrail.json +449 -0
  19. package/assets/open-connector/catalog/apps/peec.json +747 -0
  20. package/assets/open-connector/catalog/apps/polygon_io.json +5156 -584
  21. package/assets/open-connector/catalog/apps/quant_data.json +1928 -0
  22. package/assets/open-connector/catalog/apps/riddle_quiz_maker.json +621 -0
  23. package/assets/open-connector/catalog/apps/slack.json +327 -4
  24. package/assets/open-connector/catalog/apps/slackbot.json +280 -3
  25. package/assets/open-connector/catalog/apps/templatedocs.json +438 -0
  26. package/assets/open-connector/catalog/apps/terminus_app.json +510 -0
  27. package/assets/open-connector/catalog/apps/ticket_tailor.json +584 -0
  28. package/assets/open-connector/catalog/apps/tongdaxin.json +2186 -82
  29. package/assets/open-connector/catalog/apps/veremark.json +514 -0
  30. package/assets/open-connector/catalog/apps/walletap.json +549 -0
  31. package/assets/open-connector/catalog/apps/xiaohongshu_store.json +955 -39
  32. package/assets/open-connector/catalog/apps-index.json +1 -1
  33. package/package.json +5 -1
  34. package/src/connection-service.d.ts +2 -0
  35. package/src/connection-service.js +8 -1
  36. package/src/core/provider-id.d.ts +5 -0
  37. package/src/core/provider-id.js +12 -0
  38. package/src/oauth/oauth-credential-refresh-service.js +2 -0
  39. package/src/oauth/oauth-flow-service.js +2 -0
  40. package/src/providers/action-contracts.generated.d.ts +27 -7
  41. package/src/providers/assured_platform/executors.d.ts +4 -0
  42. package/src/providers/assured_platform/executors.js +18 -0
  43. package/src/providers/assured_platform/runtime.d.ts +7 -0
  44. package/src/providers/assured_platform/runtime.js +108 -0
  45. package/src/providers/baixiao/actions.d.ts +2 -0
  46. package/src/providers/baixiao/actions.js +377 -0
  47. package/src/providers/baixiao/executors.d.ts +4 -0
  48. package/src/providers/baixiao/executors.js +106 -0
  49. package/src/providers/benchmarkone/executors.d.ts +4 -0
  50. package/src/providers/benchmarkone/executors.js +26 -0
  51. package/src/providers/benchmarkone/runtime.d.ts +12 -0
  52. package/src/providers/benchmarkone/runtime.js +113 -0
  53. package/src/providers/bing_webmaster/actions.d.ts +2 -0
  54. package/src/providers/bing_webmaster/actions.js +113 -0
  55. package/src/providers/bing_webmaster/executors.d.ts +4 -0
  56. package/src/providers/bing_webmaster/executors.js +104 -0
  57. package/src/providers/bing_webmaster/management-actions.d.ts +2 -0
  58. package/src/providers/bing_webmaster/management-actions.js +241 -0
  59. package/src/providers/bing_webmaster/reporting-actions.d.ts +2 -0
  60. package/src/providers/bing_webmaster/reporting-actions.js +300 -0
  61. package/src/providers/bing_webmaster/schemas.d.ts +33 -0
  62. package/src/providers/bing_webmaster/schemas.js +313 -0
  63. package/src/providers/buzzsprout/executors.d.ts +4 -0
  64. package/src/providers/buzzsprout/executors.js +21 -0
  65. package/src/providers/buzzsprout/runtime.d.ts +12 -0
  66. package/src/providers/buzzsprout/runtime.js +237 -0
  67. package/src/providers/dropbox/executors.js +21 -3
  68. package/src/providers/feishu/shared/drive-actions.d.ts +1 -0
  69. package/src/providers/feishu/shared/drive-actions.js +13 -9
  70. package/src/providers/feishu/shared/drive-runtime.js +15 -3
  71. package/src/providers/feishu/shared/wiki-actions.js +4 -2
  72. package/src/providers/feishu_app_bot/scopes.js +1 -1
  73. package/src/providers/hithink_finance/runtime.js +39 -60
  74. package/src/providers/linkfox/actions.js +2 -0
  75. package/src/providers/linkfox/runtime.js +70 -1
  76. package/src/providers/linkfox/sif-actions.d.ts +10 -0
  77. package/src/providers/linkfox/sif-actions.js +193 -0
  78. package/src/providers/mcp-client.d.ts +1 -0
  79. package/src/providers/mcp-client.js +41 -27
  80. package/src/providers/metatraderapi/executors.d.ts +4 -0
  81. package/src/providers/metatraderapi/executors.js +18 -0
  82. package/src/providers/metatraderapi/runtime.d.ts +7 -0
  83. package/src/providers/metatraderapi/runtime.js +216 -0
  84. package/src/providers/mktindex/actions-mmi.d.ts +2 -0
  85. package/src/providers/mktindex/actions-mmi.js +510 -0
  86. package/src/providers/mktindex/actions.d.ts +2 -0
  87. package/src/providers/mktindex/actions.js +2 -0
  88. package/src/providers/mktindex/executors.d.ts +4 -0
  89. package/src/providers/mktindex/executors.js +27 -0
  90. package/src/providers/mktindex/request.d.ts +17 -0
  91. package/src/providers/mktindex/request.js +48 -0
  92. package/src/providers/mktindex/runtime.d.ts +9 -0
  93. package/src/providers/mktindex/runtime.js +492 -0
  94. package/src/providers/mojo_helpdesk/executors.d.ts +4 -0
  95. package/src/providers/mojo_helpdesk/executors.js +18 -0
  96. package/src/providers/mojo_helpdesk/runtime.d.ts +7 -0
  97. package/src/providers/mojo_helpdesk/runtime.js +173 -0
  98. package/src/providers/mumble/executors.d.ts +4 -0
  99. package/src/providers/mumble/executors.js +99 -0
  100. package/src/providers/notion/executors.d.ts +9 -0
  101. package/src/providers/notion/executors.js +161 -6
  102. package/src/providers/omise/executors.d.ts +4 -0
  103. package/src/providers/omise/executors.js +120 -0
  104. package/src/providers/panjiva/actions.d.ts +14 -0
  105. package/src/providers/panjiva/actions.js +389 -0
  106. package/src/providers/panjiva/executors.d.ts +4 -0
  107. package/src/providers/panjiva/executors.js +136 -0
  108. package/src/providers/papertrail/executors.d.ts +4 -0
  109. package/src/providers/papertrail/executors.js +15 -0
  110. package/src/providers/papertrail/runtime.d.ts +7 -0
  111. package/src/providers/papertrail/runtime.js +167 -0
  112. package/src/providers/peec/executors.d.ts +4 -0
  113. package/src/providers/peec/executors.js +15 -0
  114. package/src/providers/peec/runtime.d.ts +7 -0
  115. package/src/providers/peec/runtime.js +128 -0
  116. package/src/providers/polygon_io/actions.d.ts +2 -0
  117. package/src/providers/polygon_io/actions.js +282 -0
  118. package/src/providers/polygon_io/expanded-actions.d.ts +2 -0
  119. package/src/providers/polygon_io/expanded-actions.js +375 -0
  120. package/src/providers/polygon_io/expanded-runtime.d.ts +16 -0
  121. package/src/providers/polygon_io/expanded-runtime.js +277 -0
  122. package/src/providers/polygon_io/runtime.js +21 -2
  123. package/src/providers/quant_data/executors.d.ts +4 -0
  124. package/src/providers/quant_data/executors.js +15 -0
  125. package/src/providers/quant_data/runtime.d.ts +7 -0
  126. package/src/providers/quant_data/runtime.js +118 -0
  127. package/src/providers/registry.generated.js +20 -0
  128. package/src/providers/riddle_quiz_maker/executors.d.ts +4 -0
  129. package/src/providers/riddle_quiz_maker/executors.js +15 -0
  130. package/src/providers/riddle_quiz_maker/runtime.d.ts +7 -0
  131. package/src/providers/riddle_quiz_maker/runtime.js +145 -0
  132. package/src/providers/sellersprite_mcp/executors.js +2 -1
  133. package/src/providers/slack/actions.js +106 -3
  134. package/src/providers/slack/runtime.js +262 -38
  135. package/src/providers/slackbot/actions.js +1 -1
  136. package/src/providers/templatedocs/executors.d.ts +4 -0
  137. package/src/providers/templatedocs/executors.js +18 -0
  138. package/src/providers/templatedocs/runtime.d.ts +13 -0
  139. package/src/providers/templatedocs/runtime.js +151 -0
  140. package/src/providers/terminus_app/executors.d.ts +4 -0
  141. package/src/providers/terminus_app/executors.js +15 -0
  142. package/src/providers/terminus_app/runtime.d.ts +7 -0
  143. package/src/providers/terminus_app/runtime.js +172 -0
  144. package/src/providers/ticket_tailor/executors.d.ts +4 -0
  145. package/src/providers/ticket_tailor/executors.js +15 -0
  146. package/src/providers/ticket_tailor/runtime.d.ts +7 -0
  147. package/src/providers/ticket_tailor/runtime.js +152 -0
  148. package/src/providers/tongdaxin/actions.d.ts +1 -0
  149. package/src/providers/tongdaxin/actions.js +6 -3
  150. package/src/providers/tongdaxin/executors.js +55 -13
  151. package/src/providers/tongdaxin/named-action-output.d.ts +1 -0
  152. package/src/providers/tongdaxin/named-action-output.js +143 -0
  153. package/src/providers/tongdaxin/named-action-routing.d.ts +9 -0
  154. package/src/providers/tongdaxin/named-action-routing.js +417 -0
  155. package/src/providers/tongdaxin/named-actions.d.ts +2 -0
  156. package/src/providers/tongdaxin/named-actions.js +373 -0
  157. package/src/providers/twenty_crm/runtime.js +4 -2
  158. package/src/providers/veremark/executors.d.ts +4 -0
  159. package/src/providers/veremark/executors.js +129 -0
  160. package/src/providers/walletap/executors.d.ts +4 -0
  161. package/src/providers/walletap/executors.js +15 -0
  162. package/src/providers/walletap/runtime.d.ts +7 -0
  163. package/src/providers/walletap/runtime.js +147 -0
  164. package/src/providers/weixin_official_account/access-token.js +31 -7
  165. package/src/providers/weixin_store/access-token.js +33 -7
  166. package/src/providers/xiaohongshu_store/executors.js +152 -3
  167. package/src/server/api/openapi.js +3 -0
  168. package/src/server/connector-assets.d.ts +4 -0
  169. package/src/server/connector-assets.js +12 -0
  170. package/src/server/connector-build.d.ts +33 -0
  171. package/src/server/connector-build.js +73 -0
  172. package/src/server/connector-runtime.d.ts +1 -2
  173. package/src/server/connector-runtime.js +2 -8
  174. package/src/server/server-assets.d.ts +0 -28
  175. package/src/server/server-assets.js +0 -50
@@ -1,33 +1,12 @@
1
- import { compactObject } from "../../core/cast.js";
2
- import { runProviderRequest, ProviderRequestError, providerUserAgent } from "../provider-runtime.js";
1
+ import { compactObject, optionalInteger, optionalNumber, optionalString, optionalStringArray, } from "../../core/cast.js";
2
+ import { requiredInputNumber, requiredInputString, runProviderRequest, ProviderRequestError, providerUserAgent, } from "../provider-runtime.js";
3
3
  import { createMarketDumpHandlers } from "./market-dumps.js";
4
- function requiredString(value, fieldName) {
5
- if (typeof value !== "string" || !value.trim()) {
6
- throw hithinkError("invalid_input", `${fieldName} is required`, 400);
7
- }
8
- return value.trim();
9
- }
10
- function optionalString(value) {
11
- return typeof value === "string" && value.trim() ? value.trim() : undefined;
12
- }
13
- function optionalStringArray(value) {
14
- return Array.isArray(value) && value.every((item) => typeof item === "string") ? value : undefined;
15
- }
16
4
  function requiredStringArray(value, fieldName) {
17
5
  const result = optionalStringArray(value);
18
6
  if (!result || result.length === 0) {
19
7
  throw hithinkError("invalid_input", `${fieldName} is required`, 400);
20
8
  }
21
- return result.map((item, index) => requiredString(item, `${fieldName}[${index}]`));
22
- }
23
- function optionalNumber(value) {
24
- return typeof value === "number" ? value : undefined;
25
- }
26
- function requiredNumber(value, fieldName) {
27
- if (typeof value !== "number" || !Number.isFinite(value)) {
28
- throw hithinkError("invalid_input", `${fieldName} is required`, 400);
29
- }
30
- return value;
9
+ return result.map((item, index) => requiredInputString(item, `${fieldName}[${index}]`));
31
10
  }
32
11
  export const hithinkFinanceProxyMaxResponseBytes = 4 * 1024 * 1024;
33
12
  const hithinkFinanceActionMaxResponseBytes = 16 * 1024 * 1024;
@@ -75,7 +54,7 @@ export async function fetchHithinkFinanceProxy(input) {
75
54
  }
76
55
  throw error;
77
56
  }
78
- const code = readInteger(payload.code);
57
+ const code = optionalInteger(payload.code);
79
58
  if (!response.ok || code !== 0) {
80
59
  throw buildProviderError(response.status, code, payload, "execute");
81
60
  }
@@ -130,7 +109,7 @@ async function readBoundedResponse(response, maximumBytes, tooLargeError, emptyM
130
109
  export const hithinkFinanceActionHandlers = {
131
110
  search_tickers(input, context) {
132
111
  return get("/api/meta/tickers/search", {
133
- q: requiredString(input.query, "query"),
112
+ q: requiredInputString(input.query, "query"),
134
113
  exchange: optionalString(input.exchange),
135
114
  asset_type: optionalStringArray(input.assetTypes)?.join(","),
136
115
  limit: optionalNumber(input.limit),
@@ -153,17 +132,17 @@ export const hithinkFinanceActionHandlers = {
153
132
  },
154
133
  get_stock_history(input, context) {
155
134
  return get("/api/a-share/prices/historical", {
156
- thscode: requiredString(input.thscode, "thscode"),
135
+ thscode: requiredInputString(input.thscode, "thscode"),
157
136
  interval: "1d",
158
- start: requiredNumber(input.startTimeMs, "startTimeMs"),
159
- end: requiredNumber(input.endTimeMs, "endTimeMs"),
137
+ start: requiredInputNumber(input.startTimeMs, "startTimeMs"),
138
+ end: requiredInputNumber(input.endTimeMs, "endTimeMs"),
160
139
  adjust: optionalString(input.adjust),
161
140
  offset: optionalNumber(input.offset),
162
141
  }, context);
163
142
  },
164
143
  get_adjustment_factors(input, context) {
165
144
  return get("/api/a-share/corporate-actions/adjustment-factors", {
166
- thscode: requiredString(input.thscode, "thscode"),
145
+ thscode: requiredInputString(input.thscode, "thscode"),
167
146
  from: optionalString(input.from),
168
147
  to: optionalString(input.to),
169
148
  }, context);
@@ -179,8 +158,8 @@ export const hithinkFinanceActionHandlers = {
179
158
  },
180
159
  get_financial_indicators(input, context) {
181
160
  return get("/api/a-share/financials/indicators", {
182
- thscode: requiredString(input.thscode, "thscode"),
183
- report: requiredString(input.report, "report"),
161
+ thscode: requiredInputString(input.thscode, "thscode"),
162
+ report: requiredInputString(input.report, "report"),
184
163
  }, context);
185
164
  },
186
165
  get_valuation_snapshot(input, context) {
@@ -193,17 +172,17 @@ export const hithinkFinanceActionHandlers = {
193
172
  return get("/api/a-share-index/catalog/ths-index-list", { tag: optionalString(input.tag) }, context);
194
173
  },
195
174
  get_index_constituents(input, context) {
196
- return get("/api/a-share-index/constituents/ths-stock-list", { thscode: requiredString(input.thscode, "thscode") }, context);
175
+ return get("/api/a-share-index/constituents/ths-stock-list", { thscode: requiredInputString(input.thscode, "thscode") }, context);
197
176
  },
198
177
  get_index_snapshot(input, context) {
199
178
  return get("/api/a-share-index/prices/snapshot", { thscodes: requiredStringArray(input.thscodes, "thscodes").join(",") }, context);
200
179
  },
201
180
  get_index_history(input, context) {
202
181
  return get("/api/a-share-index/prices/historical", {
203
- thscode: requiredString(input.thscode, "thscode"),
182
+ thscode: requiredInputString(input.thscode, "thscode"),
204
183
  interval: "1d",
205
- start: requiredNumber(input.startTimeMs, "startTimeMs"),
206
- end: requiredNumber(input.endTimeMs, "endTimeMs"),
184
+ start: requiredInputNumber(input.startTimeMs, "startTimeMs"),
185
+ end: requiredInputNumber(input.endTimeMs, "endTimeMs"),
207
186
  }, context);
208
187
  },
209
188
  get_auction_snapshot(input, context) {
@@ -242,26 +221,26 @@ function createFundHandlers(get) {
242
221
  });
243
222
  },
244
223
  get_fund_market_snapshot(input, context) {
245
- return get("/api/fund/market/snapshot", { thscode: requiredString(input.thscode, "thscode") }, context);
224
+ return get("/api/fund/market/snapshot", { thscode: requiredInputString(input.thscode, "thscode") }, context);
246
225
  },
247
226
  get_fund_market_history(input, context) {
248
227
  return get("/api/fund/market/historical", {
249
- thscode: requiredString(input.thscode, "thscode"),
228
+ thscode: requiredInputString(input.thscode, "thscode"),
250
229
  interval: "1d",
251
- start: requiredNumber(input.startTimeMs, "startTimeMs"),
252
- end: requiredNumber(input.endTimeMs, "endTimeMs"),
230
+ start: requiredInputNumber(input.startTimeMs, "startTimeMs"),
231
+ end: requiredInputNumber(input.endTimeMs, "endTimeMs"),
253
232
  }, context);
254
233
  },
255
234
  get_fund_company(input, context) {
256
- return get("/api/fund/companies/detail", { company_id: requiredString(input.companyId, "companyId") }, context);
235
+ return get("/api/fund/companies/detail", { company_id: requiredInputString(input.companyId, "companyId") }, context);
257
236
  },
258
237
  get_fund_industry_allocation(input, context) {
259
238
  return getFund(get, "/api/fund/portfolio/industry-allocation", input, context);
260
239
  },
261
240
  get_fund_performance_indicators(input, context) {
262
241
  return getFund(get, "/api/fund/performance/indicators-historical", input, context, {
263
- start: requiredNumber(input.startTimeMs, "startTimeMs"),
264
- end: requiredNumber(input.endTimeMs, "endTimeMs"),
242
+ start: requiredInputNumber(input.startTimeMs, "startTimeMs"),
243
+ end: requiredInputNumber(input.endTimeMs, "endTimeMs"),
265
244
  });
266
245
  },
267
246
  get_fund_drawdowns(input, context) {
@@ -292,7 +271,7 @@ function createFundHandlers(get) {
292
271
  },
293
272
  get_fund_manager_performance(input, context) {
294
273
  return getManager(get, "/api/fund/managers/performance", input, context, {
295
- range: requiredString(input.range, "range"),
274
+ range: requiredInputString(input.range, "range"),
296
275
  });
297
276
  },
298
277
  get_fund_manager_experience(input, context) {
@@ -308,7 +287,7 @@ function createFundHandlers(get) {
308
287
  });
309
288
  },
310
289
  list_fund_offerings(input, context) {
311
- return get("/api/fund/offerings/list", { subscribe: requiredString(input.subscriptionStatus, "subscriptionStatus") }, context);
290
+ return get("/api/fund/offerings/list", { subscribe: requiredInputString(input.subscriptionStatus, "subscriptionStatus") }, context);
312
291
  },
313
292
  get_fund_stock_holdings_history(input, context) {
314
293
  return getFundHoldingsHistory(get, "/api/fund/portfolio/stock-history", input, context);
@@ -329,8 +308,8 @@ function createFundHandlers(get) {
329
308
  }
330
309
  function getFund(get, path, input, context, extra = {}) {
331
310
  return get(path, {
332
- fund_type: requiredString(input.fundType, "fundType"),
333
- thscode: requiredString(input.thscode, "thscode"),
311
+ fund_type: requiredInputString(input.fundType, "fundType"),
312
+ thscode: requiredInputString(input.thscode, "thscode"),
334
313
  ...extra,
335
314
  }, context);
336
315
  }
@@ -348,12 +327,12 @@ function normalizeNavTypes(value) {
348
327
  return undefined;
349
328
  }
350
329
  function getManager(get, path, input, context, extra = {}) {
351
- return get(path, { manager_id: requiredString(input.managerId, "managerId"), ...extra }, context);
330
+ return get(path, { manager_id: requiredInputString(input.managerId, "managerId"), ...extra }, context);
352
331
  }
353
332
  function getFundHoldingsHistory(get, path, input, context) {
354
333
  return getFund(get, path, input, context, {
355
- report_type: requiredString(input.reportType, "reportType"),
356
- end_date: requiredString(input.endDate, "endDate"),
334
+ report_type: requiredInputString(input.reportType, "reportType"),
335
+ end_date: requiredInputString(input.endDate, "endDate"),
357
336
  });
358
337
  }
359
338
  function getFundReportDates(get, path, input, context) {
@@ -382,13 +361,13 @@ function createSpecialDataHandlers(get) {
382
361
  return get("/api/a-share/special-data/hot-stock-list", { period: optionalString(input.period) }, context);
383
362
  },
384
363
  get_hot_stock_history(input, context) {
385
- return get("/api/a-share/special-data/hot-stock-list-history", { date: requiredString(input.date, "date") }, context);
364
+ return get("/api/a-share/special-data/hot-stock-list-history", { date: requiredInputString(input.date, "date") }, context);
386
365
  },
387
366
  get_hot_stock_rank_trend(input, context) {
388
367
  return get("/api/a-share/special-data/hot-stock-rank-trend", {
389
- thscode: requiredString(input.thscode, "thscode"),
390
- start_date: requiredString(input.startDate, "startDate"),
391
- end_date: requiredString(input.endDate, "endDate"),
368
+ thscode: requiredInputString(input.thscode, "thscode"),
369
+ start_date: requiredInputString(input.startDate, "startDate"),
370
+ end_date: requiredInputString(input.endDate, "endDate"),
392
371
  }, context);
393
372
  },
394
373
  get_dragon_tiger_list(input, context) {
@@ -413,7 +392,7 @@ function getPool(get, path, input, context) {
413
392
  }
414
393
  function getFinancialStatements(path, input, context) {
415
394
  return get(path, {
416
- thscode: requiredString(input.thscode, "thscode"),
395
+ thscode: requiredInputString(input.thscode, "thscode"),
417
396
  period: optionalString(input.period),
418
397
  limit: optionalNumber(input.limit),
419
398
  start: optionalNumber(input.startTimeMs),
@@ -455,7 +434,7 @@ async function hithinkFinanceGet(path, query, apiKey, fetcher, phase, signal) {
455
434
  }
456
435
  throw error;
457
436
  }
458
- const code = readInteger(payload.code);
437
+ const code = optionalInteger(payload.code);
459
438
  if (!response.ok || code !== 0) {
460
439
  throw buildProviderError(response.status, code, payload, phase);
461
440
  }
@@ -500,7 +479,10 @@ function buildProviderError(status, code, payload, phase) {
500
479
  return hithinkError(phase === "validate" ? "invalid_input" : "scope_missing", detail, phase === "validate" ? 400 : 403);
501
480
  }
502
481
  if (code === 4001 || status === 429) {
503
- return hithinkError("rate_limited", `${detail}. Reduce request frequency and concurrency, then retry with exponential backoff (up to 3 attempts)`, 429);
482
+ const retryAdvice = message.startsWith("Global request rate limit exceeded")
483
+ ? "This upstream limit is shared across the account. Wait before retrying; reconnecting or sending concurrent retries will not reset it"
484
+ : "Reduce request frequency and concurrency, then retry with exponential backoff (up to 3 attempts)";
485
+ return hithinkError("rate_limited", `${detail}. ${retryAdvice}`, 429);
504
486
  }
505
487
  if (code === 4040) {
506
488
  return hithinkError("provider_error", requestId
@@ -522,9 +504,6 @@ function buildProviderError(status, code, payload, phase) {
522
504
  }
523
505
  return hithinkError("provider_error", detail, status >= 500 ? 502 : 503);
524
506
  }
525
- function readInteger(value) {
526
- return typeof value === "number" && Number.isInteger(value) ? value : undefined;
527
- }
528
507
  function hithinkError(code, message, status) {
529
508
  return new ProviderRequestError(status, message, { code });
530
509
  }
@@ -6,6 +6,7 @@ import { chuhaijiangActions } from "./chuhaijiang-actions.js";
6
6
  import { maidalvAction } from "./maidalv-actions.js";
7
7
  import { mercadoActions } from "./mercado-actions.js";
8
8
  import { seerfarActions } from "./seerfar-actions.js";
9
+ import { sifActions } from "./sif-actions.js";
9
10
  import { zhihuiyaActions } from "./zhihuiya-actions.js";
10
11
  const service = "linkfox";
11
12
  const amazonDomains = [
@@ -974,6 +975,7 @@ const tiktokShopProductInput = s.object("TikTok Shop product detail parameters."
974
975
  region: s.optional(s.stringEnum("The TikTok Shop region.", ["US", "GB", "ID", "MY", "TH", "VN", "PH", "SG", "DE", "FR", "IT", "ES"])),
975
976
  });
976
977
  export const linkfoxActions = [
978
+ ...sifActions,
977
979
  ...mercadoActions,
978
980
  ...zhihuiyaActions,
979
981
  ...chuhaijiangActions,
@@ -4,6 +4,7 @@ import { chuhaijiangOperations } from "./chuhaijiang-actions.js";
4
4
  import { normalizeChuhaijiang, searchChuhaijiangImage } from "./chuhaijiang-runtime.js";
5
5
  import { mercadoOperations } from "./mercado-actions.js";
6
6
  import { seerfarOperations } from "./seerfar-actions.js";
7
+ import { sifOperations } from "./sif-actions.js";
7
8
  import { zhihuiyaOperations } from "./zhihuiya-actions.js";
8
9
  import { validateZhihuiyaInput } from "./zhihuiya-runtime.js";
9
10
  const zhihuiyaOperationsByName = new Map(zhihuiyaOperations.map(({ action, path }) => [action.name, { path }]));
@@ -32,6 +33,10 @@ const directOperations = {
32
33
  normalize: (payload) => requiredResponseRecord(payload, "LinkFox Seerfar response"),
33
34
  },
34
35
  ])),
36
+ ...Object.fromEntries(sifOperations.map(({ action, path }) => [
37
+ action.name,
38
+ { path, gatewayBusinessCodeOnly: true, normalize: normalizeSifResult },
39
+ ])),
35
40
  get_current_account: {
36
41
  path: "/account/currentByAPI",
37
42
  method: "GET",
@@ -299,10 +304,13 @@ export async function executeLinkfoxAction(actionName, input, apiKey, fetcher, p
299
304
  }
300
305
  const direct = directOperations[actionName];
301
306
  if (direct) {
307
+ if (direct.gatewayBusinessCodeOnly)
308
+ validateSifInput(actionName, input);
302
309
  const body = direct.buildBody ? direct.buildBody(input) : input;
303
310
  const payload = await requestLinkfoxPayload(direct.path, {
304
311
  method: direct.method ?? "POST",
305
312
  timeoutMs: direct.timeoutMs,
313
+ gatewayBusinessCodeOnly: direct.gatewayBusinessCodeOnly,
306
314
  ...((direct.method ?? "POST") === "POST" ? { body } : {}),
307
315
  }, apiKey, fetcher, "execute", false, parentSignal);
308
316
  return direct.normalize(payload);
@@ -313,6 +321,32 @@ export async function executeLinkfoxAction(actionName, input, apiKey, fetcher, p
313
321
  }
314
322
  return handler(input, { apiKey, fetcher, signal: parentSignal });
315
323
  }
324
+ function validateSifInput(actionName, input) {
325
+ if (actionName === "list_sif_asin_keywords") {
326
+ const periodType = optionalString(input.timePieceType) ?? "latelyDay";
327
+ const periodValue = optionalString(input.timePieceValue);
328
+ if ((periodType === "month" || periodType === "week") && !periodValue) {
329
+ throw new ProviderRequestError(400, "timePieceValue is required for month or week periods");
330
+ }
331
+ }
332
+ const startDate = optionalString(input.startDate);
333
+ const endDate = optionalString(input.endDate);
334
+ if ((startDate && !endDate) || (!startDate && endDate)) {
335
+ throw new ProviderRequestError(400, "startDate and endDate must be provided together");
336
+ }
337
+ if ((startDate || endDate) && input.last7d !== false) {
338
+ throw new ProviderRequestError(400, "last7d must be false when a date range is provided");
339
+ }
340
+ if (startDate && endDate && startDate > endDate) {
341
+ throw new ProviderRequestError(400, "startDate must not be later than endDate");
342
+ }
343
+ if (actionName === "get_sif_asin_traffic_summary") {
344
+ const asins = optionalString(input.asins);
345
+ if (asins && asins.split(",").length > 10) {
346
+ throw new ProviderRequestError(400, "asins must contain at most 10 comma-separated ASINs");
347
+ }
348
+ }
349
+ }
316
350
  function validateLinkfoxActionInput(actionName, input) {
317
351
  if (actionName === "search_amazon_by_image" && input.deliveryZip && input.countryOrAreaCode) {
318
352
  throw new ProviderRequestError(400, "deliveryZip and countryOrAreaCode cannot be used together");
@@ -422,7 +456,9 @@ async function requestLinkfoxPayload(path, options, apiKey, fetcher, phase = "ex
422
456
  signal,
423
457
  });
424
458
  const payload = await readJsonPayload(response);
425
- const businessCode = readBusinessCode(payload);
459
+ const businessCode = options.gatewayBusinessCodeOnly
460
+ ? readGatewayBusinessCode(payload)
461
+ : readBusinessCode(payload);
426
462
  if (acceptCreditError && businessCode === 402)
427
463
  return payload;
428
464
  if (!response.ok || (businessCode !== undefined && businessCode !== 200)) {
@@ -482,6 +518,17 @@ function readBusinessCode(payload) {
482
518
  }
483
519
  return undefined;
484
520
  }
521
+ function readGatewayBusinessCode(payload) {
522
+ const record = optionalRecord(payload);
523
+ for (const key of ["errcode", "errorCode"]) {
524
+ const value = record?.[key];
525
+ if (typeof value === "number" && Number.isFinite(value))
526
+ return value;
527
+ if (typeof value === "string" && value.trim() && Number.isFinite(Number(value)))
528
+ return Number(value);
529
+ }
530
+ return undefined;
531
+ }
485
532
  function readErrorMessage(payload) {
486
533
  if (typeof payload === "string" && payload.trim()) {
487
534
  return payload.trim();
@@ -522,6 +569,28 @@ function normalizeDataList(payload) {
522
569
  costToken: readNumber(record.costToken),
523
570
  };
524
571
  }
572
+ function normalizeSifResult(payload) {
573
+ const record = requireRecord(payload, "LinkFox returned an invalid SIF response");
574
+ const code = typeof record.code === "string" || typeof record.code === "number" ? String(record.code) : undefined;
575
+ if (code !== "1") {
576
+ throw new ProviderRequestError(502, readString(record.msg) ?? "LinkFox SIF returned an unsuccessful business response", record);
577
+ }
578
+ const data = readArray(record.data);
579
+ if (!data)
580
+ throw new ProviderRequestError(502, "LinkFox SIF response did not include data", record);
581
+ return {
582
+ ...record,
583
+ code,
584
+ msg: readString(record.msg) ?? null,
585
+ total: readInteger(record.total) ?? data.length,
586
+ data,
587
+ columns: readArray(record.columns) ?? [],
588
+ type: readString(record.type) ?? null,
589
+ title: readString(record.title) ?? null,
590
+ costTime: readInteger(record.costTime),
591
+ costToken: readNumber(record.costToken),
592
+ };
593
+ }
525
594
  function normalizeVideoList(payload) {
526
595
  const record = requireRecord(payload, "LinkFox returned an invalid video response");
527
596
  const videos = readArray(record.videos) ?? readArray(record.data) ?? [];
@@ -0,0 +1,10 @@
1
+ import type { ProviderActionDefinition } from "../../core/provider-definition.ts";
2
+ import type { ActionDefinition } from "../../core/types.ts";
3
+ interface SifOperation {
4
+ path: string;
5
+ usage: number;
6
+ action: ProviderActionDefinition;
7
+ }
8
+ export declare const sifOperations: readonly SifOperation[];
9
+ export declare const sifActions: readonly ActionDefinition[];
10
+ export {};
@@ -0,0 +1,193 @@
1
+ import { jsonSchema as s } from "../../core/json-schema.js";
2
+ import { defineProviderAction } from "../../core/provider-definition.js";
3
+ const sifCountries = ["US", "UK", "DE", "CA", "JP", "FR", "ES", "IT", "MX", "AU", "AE", "BR", "SA"];
4
+ const summarySortFields = [
5
+ "totalKeywordNum",
6
+ "naturalKeywordNum",
7
+ "brandKeywordNum",
8
+ "vedioKeywordNum",
9
+ "acKeywordNum",
10
+ "erKeywordNum",
11
+ "trKeywordNum",
12
+ "sumScore",
13
+ "totalNfScore",
14
+ "totalSpSocre",
15
+ "totalBrandScore",
16
+ "totalVedioScore",
17
+ "totalAcScore",
18
+ "totalTrScore",
19
+ "totalErScore",
20
+ ];
21
+ const keywordSummaryConditions = [
22
+ "nfPosition",
23
+ "isSpAd",
24
+ "isVedioAd",
25
+ "isBrandAd",
26
+ "isPPCAd",
27
+ "isSearchRecommend",
28
+ "acAd",
29
+ "totalPeriod.in",
30
+ "nfKeywordCnt.total",
31
+ "nfKeywordCnt.in",
32
+ "adKeywordCnt.total",
33
+ "adKeywordCnt.in",
34
+ "allSpKeywordCnt.total",
35
+ "allSpKeywordCnt.in",
36
+ "spKeywordCnt.total",
37
+ "spKeywordCnt.in",
38
+ "recSpKeywordCnt.total",
39
+ "recSpKeywordCnt.in",
40
+ "allSbKeywordCnt.total",
41
+ "allSbKeywordCnt.in",
42
+ "sbKeywordCnt.total",
43
+ "sbKeywordCnt.in",
44
+ "sbvKeywordCnt.total",
45
+ "sbvKeywordCnt.in",
46
+ ];
47
+ const _asinKeywordConditionValues = [
48
+ "nfPosition",
49
+ "isSpAd",
50
+ "isBrandAd",
51
+ "isVedioAd",
52
+ "isAC",
53
+ "isAccurateKw",
54
+ "isAccurateTailKw",
55
+ "isPurchaseKw",
56
+ "isQualityKw",
57
+ "isStableKw",
58
+ "isLossKw",
59
+ "isInvalidKw",
60
+ "isMultiVariantKw",
61
+ "isSearchVolUpKw",
62
+ "isSearchVolDownKw",
63
+ "totalPeriod.in",
64
+ "nfKeywordCnt.total",
65
+ "nfKeywordCnt.in",
66
+ "adKeywordCnt.total",
67
+ "adKeywordCnt.in",
68
+ "allSpKeywordCnt.total",
69
+ "allSpKeywordCnt.in",
70
+ "spKeywordCnt.total",
71
+ "spKeywordCnt.in",
72
+ "recSpKeywordCnt.total",
73
+ "recSpKeywordCnt.in",
74
+ "allSbKeywordCnt.total",
75
+ "allSbKeywordCnt.in",
76
+ "sbKeywordCnt.total",
77
+ "sbKeywordCnt.in",
78
+ "sbvKeywordCnt.total",
79
+ "sbvKeywordCnt.in",
80
+ ];
81
+ const _asinSummaryConditionValues = ["nf", "sp", "sb", "sbv", "ad", "acAd", "totalPeriod.in"];
82
+ const countrySchema = s.optional(s.stringEnum("The Amazon marketplace code. LinkFox defaults to US when omitted.", sifCountries));
83
+ const nullableInteger = (description) => s.nullable(s.integer(description));
84
+ const nullableNumber = (description) => s.nullable(s.number(description));
85
+ const nullableString = (description) => s.nullable(s.string(description));
86
+ function resultSchema(description, recordDescription, extra = {}) {
87
+ return s.looseRequiredObject(description, {
88
+ code: s.string("The SIF business code; 1 indicates success."),
89
+ msg: nullableString("The SIF response message."),
90
+ total: s.integer("The number of records returned by this request.", { minimum: 0 }),
91
+ data: s.array("The SIF records returned by this request.", s.looseObject(recordDescription)),
92
+ columns: s.array("The LinkFox rendering-column definitions.", s.looseObject("A provider-defined rendering-column definition.")),
93
+ type: nullableString("The LinkFox rendering style when provided."),
94
+ title: nullableString("The result title when provided."),
95
+ costTime: nullableInteger("The upstream processing time in milliseconds."),
96
+ costToken: nullableNumber("The LinkFox token cost when provided."),
97
+ ...extra,
98
+ });
99
+ }
100
+ const asinKeywordsInputBase = s.object("Parameters for reverse-searching one ASIN's SIF keywords.", {
101
+ asin: s.nonEmptyString("The single Amazon ASIN to analyze.", { maxLength: 1000 }),
102
+ country: countrySchema,
103
+ keyword: s.optional(s.string("An optional localized keyword used to filter the result.", { maxLength: 1000 })),
104
+ timePieceType: s.optional(s.stringEnum("The analysis period type. LinkFox defaults to latelyDay.", ["latelyDay", "month", "week"])),
105
+ timePieceValue: s.optional(s.string("The period value: 7 or 30 for latelyDay, YYYY-MM for month, or the week-start date in YYYY-MM-DD format.", { maxLength: 1000 })),
106
+ conditions: s.optional(s.string("Comma-separated SIF keyword filters, including traffic-position, advertising, conversion, stability, and period-entry markers.", { maxLength: 1000 })),
107
+ sortBy: s.optional(s.stringEnum("The keyword sort field. Omit it to use SIF's system order.", [
108
+ "lastRank",
109
+ "adLastRank",
110
+ "updateTime",
111
+ "searchesRank",
112
+ "estSearchesNum",
113
+ ])),
114
+ desc: s.optional(s.boolean("Whether to sort descending. LinkFox defaults to true.")),
115
+ pageNum: s.optional(s.integer("The one-based result page. LinkFox defaults to 1.", { minimum: 1 })),
116
+ pageSize: s.optional(s.integer("The number of keyword records per page. LinkFox defaults to 100.", {
117
+ minimum: 10,
118
+ maximum: 100,
119
+ })),
120
+ });
121
+ const asinKeywordsInput = asinKeywordsInputBase;
122
+ const dateRangeFields = {
123
+ last7d: s.optional(s.boolean("Whether to use the latest seven days. Set false to use startDate and endDate; LinkFox defaults to true.")),
124
+ startDate: s.optional(s.date("The period start date, used when last7d is false.")),
125
+ endDate: s.optional(s.date("The period end date, paired with startDate.")),
126
+ };
127
+ const asinSummaryInputBase = s.object("Parameters for summarizing SIF traffic sources by ASIN.", {
128
+ searchValue: s.nonEmptyString("One to ten comma-separated Amazon ASINs.", { maxLength: 1000 }),
129
+ country: countrySchema,
130
+ ...dateRangeFields,
131
+ conditions: s.optional(s.string("Comma-separated SIF filters: nf, sp, sb, sbv, ad, acAd, or totalPeriod.in.", {
132
+ maxLength: 1000,
133
+ })),
134
+ sortBy: s.optional(s.stringEnum("The ASIN traffic-summary sort field.", summarySortFields)),
135
+ pageNum: s.optional(s.integer("The one-based result page. LinkFox defaults to 1.", { minimum: 1 })),
136
+ pageSize: s.optional(s.integer("The number of ASIN summaries per page. LinkFox defaults to 10000.", {
137
+ minimum: 10,
138
+ maximum: 10_000,
139
+ })),
140
+ desc: s.optional(s.boolean("Whether to sort descending. LinkFox defaults to true.")),
141
+ });
142
+ const asinSummaryInput = asinSummaryInputBase;
143
+ const keywordOverviewInputBase = s.object("Parameters for retrieving a SIF keyword overview.", {
144
+ keyword: s.nonEmptyString("The localized Amazon keyword to analyze.", { maxLength: 1000 }),
145
+ country: countrySchema,
146
+ ...dateRangeFields,
147
+ });
148
+ const keywordOverviewInput = keywordOverviewInputBase;
149
+ const keywordSummaryInputBase = s.object("Parameters for summarizing competitor traffic sources for one keyword.", {
150
+ searchKeyword: s.nonEmptyString("The localized Amazon keyword to analyze.", {
151
+ maxLength: 1000,
152
+ }),
153
+ country: countrySchema,
154
+ asins: s.optional(s.string("An optional comma-separated ASIN filter.", { maxLength: 1000 })),
155
+ condition: s.optional(s.stringEnum("One SIF traffic or period filter, such as nfPosition, isSpAd, isBrandAd, isPPCAd, acAd, or totalPeriod.in.", keywordSummaryConditions)),
156
+ ...dateRangeFields,
157
+ sortBy: s.optional(s.stringEnum("The competitor traffic-summary sort field.", summarySortFields)),
158
+ pageNum: s.optional(s.integer("The one-based result page. LinkFox defaults to 1.", { minimum: 1 })),
159
+ pageSize: s.optional(s.integer("The number of competitor ASINs per page. LinkFox defaults to 100.", {
160
+ minimum: 10,
161
+ maximum: 100,
162
+ })),
163
+ desc: s.optional(s.boolean("Whether to sort descending. LinkFox defaults to true.")),
164
+ });
165
+ const keywordSummaryInput = keywordSummaryInputBase;
166
+ function operation(name, path, description, inputSchema, outputSchema) {
167
+ return {
168
+ path,
169
+ usage: 9,
170
+ action: defineProviderAction("linkfox", {
171
+ name,
172
+ description,
173
+ operationType: "read",
174
+ inputSchema,
175
+ outputSchema,
176
+ }),
177
+ };
178
+ }
179
+ export const sifOperations = [
180
+ operation("list_sif_asin_keywords", "/sif/asinKeywords", "Reverse-search one Amazon ASIN's SIF traffic keywords, ranks, traffic shares, and conversion markers through LinkFox.", asinKeywordsInput, resultSchema("SIF keyword intelligence for one Amazon ASIN.", "A SIF keyword record with ranks, search volume, traffic shares, exposure scores, placements, and conversion markers.", {
181
+ isParentAsin: s.optional(s.boolean("Whether the queried ASIN is a parent ASIN.")),
182
+ hasVaiants: s.optional(s.boolean("Whether the queried product has variants.")),
183
+ abaCreateDateWeek: nullableString("The latest week represented by the ABA data."),
184
+ })),
185
+ operation("get_sif_asin_traffic_summary", "/sif/asinSummary", "Summarize natural, advertising, and recommendation traffic sources for up to ten Amazon ASINs through LinkFox and SIF.", asinSummaryInput, resultSchema("SIF traffic-source summaries for Amazon ASINs.", "A SIF ASIN summary with product context, current and previous exposure scores, traffic shares, keyword counts, entry or exit counts, and source markers.", {
186
+ isParentAsin: s.optional(s.boolean("Whether the search target is a parent ASIN.")),
187
+ variantsNum: nullableInteger("The number of variants with traffic keywords."),
188
+ noKeywordVariantsNum: nullableInteger("The number of variants without traffic keywords."),
189
+ })),
190
+ operation("get_sif_keyword_overview", "/sif/keywordOverview", "Get SIF search demand, supply-demand ratio, and advertising or recommendation competition for one Amazon keyword through LinkFox.", keywordOverviewInput, resultSchema("A SIF market-competition overview for one Amazon keyword.", "A SIF keyword overview with search volume, supply-demand ratio, product counts by traffic placement, tracked ASIN totals, and data-period timestamps.")),
191
+ operation("get_sif_keyword_traffic_summary", "/sif/keywordSummary", "Analyze competitor ASIN traffic shares and natural, advertising, or recommendation exposure for one Amazon keyword through LinkFox and SIF.", keywordSummaryInput, resultSchema("SIF competitor traffic-source summaries for one Amazon keyword.", "A SIF competitor record with product context, overall and queried-keyword exposure scores, traffic shares, and source markers.")),
192
+ ];
193
+ export const sifActions = sifOperations.map(({ action }) => action);
@@ -10,6 +10,7 @@ export interface McpClientOptions {
10
10
  signal?: AbortSignal;
11
11
  protocolVersion?: McpProtocolVersion;
12
12
  terminateSession?: boolean;
13
+ retryOnSessionNotFound?: boolean;
13
14
  mapError?: (error: unknown) => unknown;
14
15
  }
15
16
  export declare function withMcpClient<T>(options: McpClientOptions, run: (client: Client) => Promise<T>): Promise<T>;