@oomol-lab/open-connector 1.6.3 → 1.6.5

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 (108) hide show
  1. package/assets/open-connector/catalog/apps/aisa.json +568 -0
  2. package/assets/open-connector/catalog/apps/bilibili.json +2586 -0
  3. package/assets/open-connector/catalog/apps/bitwarden.json +1423 -0
  4. package/assets/open-connector/catalog/apps/cronfree.json +303 -0
  5. package/assets/open-connector/catalog/apps/cufinder.json +368 -0
  6. package/assets/open-connector/catalog/apps/feishu_app_bot.json +2 -2
  7. package/assets/open-connector/catalog/apps/gmail.json +73 -0
  8. package/assets/open-connector/catalog/apps/investoday_mcp.json +22228 -197
  9. package/assets/open-connector/catalog/apps/ixspy.json +2274 -0
  10. package/assets/open-connector/catalog/apps/jin10.json +1 -1
  11. package/assets/open-connector/catalog/apps/osv.json +663 -0
  12. package/assets/open-connector/catalog/apps/pdf_vector.json +329 -0
  13. package/assets/open-connector/catalog/apps/pulsetic.json +406 -0
  14. package/assets/open-connector/catalog/apps/shopee.json +1785 -0
  15. package/assets/open-connector/catalog/apps/slack.json +81 -0
  16. package/assets/open-connector/catalog/apps/slackbot.json +81 -0
  17. package/assets/open-connector/catalog/apps/speak_ai.json +360 -0
  18. package/assets/open-connector/catalog/apps/tongdaxin.json +11 -440
  19. package/assets/open-connector/catalog/apps/zyhub.json +1585 -0
  20. package/assets/open-connector/catalog/apps-index.json +1 -1
  21. package/package.json +1 -1
  22. package/src/core/json-schema.d.ts +5 -1
  23. package/src/core/json-schema.js +14 -2
  24. package/src/core/types.d.ts +9 -0
  25. package/src/oauth/oauth-credential-refresh-service.js +3 -1
  26. package/src/oauth/oauth-flow-service.js +17 -2
  27. package/src/oauth/oauth-token.d.ts +13 -0
  28. package/src/providers/action-contracts.generated.d.ts +16 -4
  29. package/src/providers/aisa/executors.d.ts +4 -0
  30. package/src/providers/aisa/executors.js +176 -0
  31. package/src/providers/bilibili/articles.d.ts +3 -0
  32. package/src/providers/bilibili/articles.js +369 -0
  33. package/src/providers/bilibili/executors.d.ts +8 -0
  34. package/src/providers/bilibili/executors.js +262 -0
  35. package/src/providers/bilibili/runtime.d.ts +95 -0
  36. package/src/providers/bilibili/runtime.js +238 -0
  37. package/src/providers/bilibili/upload.d.ts +14 -0
  38. package/src/providers/bilibili/upload.js +105 -0
  39. package/src/providers/bitwarden/executors.d.ts +3 -0
  40. package/src/providers/bitwarden/executors.js +146 -0
  41. package/src/providers/cronfree/executors.d.ts +4 -0
  42. package/src/providers/cronfree/executors.js +89 -0
  43. package/src/providers/cufinder/executors.d.ts +4 -0
  44. package/src/providers/cufinder/executors.js +105 -0
  45. package/src/providers/dropbox/executors.js +21 -3
  46. package/src/providers/elevenreader/runtime.js +6 -5
  47. package/src/providers/feishu_app_bot/scopes.js +1 -1
  48. package/src/providers/gmail/attachment-stream.d.ts +2 -0
  49. package/src/providers/gmail/attachment-stream.js +162 -0
  50. package/src/providers/gmail/executors.d.ts +3 -1
  51. package/src/providers/gmail/executors.js +53 -25
  52. package/src/providers/investoday_mcp/official-actions.js +19 -372
  53. package/src/providers/investoday_mcp/official-tool-types.d.ts +10 -0
  54. package/src/providers/investoday_mcp/official-tool-types.js +4 -0
  55. package/src/providers/investoday_mcp/official-tools/charts.d.ts +2 -0
  56. package/src/providers/investoday_mcp/official-tools/charts.js +32 -0
  57. package/src/providers/investoday_mcp/official-tools/fixed-income.d.ts +2 -0
  58. package/src/providers/investoday_mcp/official-tools/fixed-income.js +326 -0
  59. package/src/providers/investoday_mcp/official-tools/funds.d.ts +2 -0
  60. package/src/providers/investoday_mcp/official-tools/funds.js +1085 -0
  61. package/src/providers/investoday_mcp/official-tools/hong-kong.d.ts +2 -0
  62. package/src/providers/investoday_mcp/official-tools/hong-kong.js +275 -0
  63. package/src/providers/investoday_mcp/official-tools/indices-industries.d.ts +2 -0
  64. package/src/providers/investoday_mcp/official-tools/indices-industries.js +642 -0
  65. package/src/providers/investoday_mcp/official-tools/macro-calendar.d.ts +2 -0
  66. package/src/providers/investoday_mcp/official-tools/macro-calendar.js +398 -0
  67. package/src/providers/investoday_mcp/official-tools/other.d.ts +2 -0
  68. package/src/providers/investoday_mcp/official-tools/other.js +131 -0
  69. package/src/providers/investoday_mcp/official-tools/research-news.d.ts +2 -0
  70. package/src/providers/investoday_mcp/official-tools/research-news.js +302 -0
  71. package/src/providers/investoday_mcp/official-tools/stocks.d.ts +2 -0
  72. package/src/providers/investoday_mcp/official-tools/stocks.js +2829 -0
  73. package/src/providers/ixspy/executors.d.ts +3 -0
  74. package/src/providers/ixspy/executors.js +220 -0
  75. package/src/providers/mcp-client.d.ts +1 -0
  76. package/src/providers/mcp-client.js +41 -27
  77. package/src/providers/osv/executors.d.ts +2 -0
  78. package/src/providers/osv/executors.js +11 -0
  79. package/src/providers/osv/runtime.d.ts +9 -0
  80. package/src/providers/osv/runtime.js +66 -0
  81. package/src/providers/pdf_vector/executors.d.ts +4 -0
  82. package/src/providers/pdf_vector/executors.js +108 -0
  83. package/src/providers/provider-runtime.d.ts +3 -0
  84. package/src/providers/provider-runtime.js +4 -1
  85. package/src/providers/pulsetic/executors.d.ts +4 -0
  86. package/src/providers/pulsetic/executors.js +126 -0
  87. package/src/providers/registry.generated.js +12 -0
  88. package/src/providers/sellersprite_mcp/executors.js +2 -1
  89. package/src/providers/shopee/actions.d.ts +2 -0
  90. package/src/providers/shopee/actions.js +474 -0
  91. package/src/providers/shopee/executors.d.ts +3 -0
  92. package/src/providers/shopee/executors.js +85 -0
  93. package/src/providers/shopee/runtime.d.ts +79 -0
  94. package/src/providers/shopee/runtime.js +693 -0
  95. package/src/providers/slack/actions.js +17 -0
  96. package/src/providers/slack/runtime.js +62 -4
  97. package/src/providers/speak_ai/executors.d.ts +3 -0
  98. package/src/providers/speak_ai/executors.js +187 -0
  99. package/src/providers/tongdaxin/executors.js +5 -4
  100. package/src/providers/tongdaxin/named-action-output.js +3 -9
  101. package/src/providers/tongdaxin/named-action-routing.js +1 -1
  102. package/src/providers/tongdaxin/named-actions.js +1 -6
  103. package/src/providers/tushare/runtime.js +22 -9
  104. package/src/providers/twenty_crm/runtime.js +4 -2
  105. package/src/providers/zyhub/executors.d.ts +3 -0
  106. package/src/providers/zyhub/executors.js +240 -0
  107. package/src/server/files/transit-files.d.ts +3 -2
  108. package/src/server/files/transit-files.js +31 -35
@@ -0,0 +1,3 @@
1
+ import type { CredentialValidators, ProviderExecutors } from "../../core/types.ts";
2
+ export declare const executors: ProviderExecutors;
3
+ export declare const credentialValidators: CredentialValidators;
@@ -0,0 +1,220 @@
1
+ import { compactObject, looseArray, optionalInteger, optionalNumber, optionalRecord, optionalString, } from "../../core/cast.js";
2
+ import { defineApiKeyProviderExecutors, providerInputError, ProviderRequestError, providerResponseError, providerUserAgent, readProviderJsonBody, requiredResponseRecord, runProviderRequest, } from "../provider-runtime.js";
3
+ const service = "ixspy";
4
+ const baseUrl = "https://open.ixspy.com";
5
+ const configs = {
6
+ get_category_resource: { path: "/api/v1/aliexpress/category-resource", kind: "category_resource" },
7
+ list_category_children: { path: "/api/v1/aliexpress/category-children", kind: "category_children" },
8
+ search_categories: { path: "/api/v1/aliexpress/category-lookup", kind: "list" },
9
+ search_products: { path: "/api/v1/aliexpress/product-search", kind: "list" },
10
+ get_product_details: { path: "/api/v1/aliexpress/product-detail", kind: "list" },
11
+ search_stores: { path: "/api/v1/aliexpress/store-search", kind: "list" },
12
+ get_store_details: { path: "/api/v1/aliexpress/store-detail", kind: "list" },
13
+ get_product_sku_sales: { path: "/api/v1/aliexpress/product-orders-sku-stat", kind: "product_statistics" },
14
+ get_product_shipping_stats: { path: "/api/v1/aliexpress/product-orders-shipping-stat", kind: "product_statistics" },
15
+ get_product_region_sales: { path: "/api/v1/aliexpress/product-orders-region-stat", kind: "product_statistics" },
16
+ get_product_trends: { path: "/api/v1/aliexpress/product-trend-data", kind: "product_trends" },
17
+ get_store_category_distribution: { path: "/api/v1/aliexpress/store-category-stat", kind: "store_statistics" },
18
+ get_store_region_sales: { path: "/api/v1/aliexpress/store-orders-region-stat", kind: "store_statistics" },
19
+ get_store_trends: { path: "/api/v1/aliexpress/store-trend-data", kind: "store_trends" },
20
+ get_product_rank: { path: "/api/v1/aliexpress/product-rank", kind: "list" },
21
+ get_region_product_rank: { path: "/api/v1/aliexpress/product-rank-by-region", kind: "list" },
22
+ get_store_rank: { path: "/api/v1/aliexpress/store-rank", kind: "list" },
23
+ get_keyword_rank: { path: "/api/v1/aliexpress/keyword-rank", kind: "list" },
24
+ list_rank_dates: { path: "/api/v1/aliexpress/rank-date-list", kind: "rank_dates", method: "GET" },
25
+ research_categories: { path: "/api/v1/aliexpress/category-research", kind: "list" },
26
+ get_market_insights: { path: "/api/v1/aliexpress/market-insights", kind: "list" },
27
+ };
28
+ const keyOverrides = {
29
+ averagePriceMax: "avg_price_max",
30
+ averagePriceMin: "avg_price_min",
31
+ choiceTypes: "choice_type",
32
+ createdAfter: "created_time_min",
33
+ createdBefore: "created_time_max",
34
+ discoveredAfter: "discovered_time_start",
35
+ discoveredBefore: "discovered_time_end",
36
+ linkIds: "store_link_id",
37
+ merchantIds: "store_merchant_id",
38
+ productIds: "product_id_list",
39
+ sales7dMax: "sales_count_7d_max",
40
+ sales7dMin: "sales_count_7d_min",
41
+ updatedAfter: "updated_time_min",
42
+ updatedBefore: "updated_time_max",
43
+ };
44
+ const orderValues = {
45
+ clickRate: "click_rate",
46
+ conversionRate: "conversion_rate",
47
+ createdTime: "created_time",
48
+ discoveredTime: "discovered_time",
49
+ sales7d: "sales_count_7d",
50
+ searchGrowth: "searches_rise_index",
51
+ searchPopularity: "search_cookies_count",
52
+ totalFollowers: "total_followers",
53
+ totalReviews: "total_reviews",
54
+ totalSales: "total_sales",
55
+ };
56
+ const rankValues = {
57
+ holidayNew: "holiday_new",
58
+ holidayNormal: "holiday_normal",
59
+ holidayRank: "holiday_rank",
60
+ keywordRank: "keyword_rank",
61
+ newGrowth: "new_inc",
62
+ newHot: "new_hot",
63
+ normalGrowth: "normal_inc",
64
+ normalHot: "normal_hot",
65
+ normalRank: "normal_rank",
66
+ };
67
+ const handlers = Object.fromEntries(Object.entries(configs).map(([name, config]) => [
68
+ name,
69
+ async (input, context) => normalize(config.kind, await request(name, config, input, context, false)),
70
+ ]));
71
+ export const executors = defineApiKeyProviderExecutors(service, handlers, {
72
+ skipDnsValidation: true,
73
+ });
74
+ export const credentialValidators = {
75
+ async apiKey(input, context) {
76
+ const payload = await request("list_category_children", configs.list_category_children, { parentId: 0 }, { ...context, apiKey: input.apiKey }, true);
77
+ const data = requiredResponseRecord(payload.data, "IXSPY category data");
78
+ return {
79
+ profile: { accountId: "ixspy-api-key", displayName: "IXSPY API Key" },
80
+ grantedScopes: [],
81
+ metadata: {
82
+ apiBaseUrl: baseUrl,
83
+ validationEndpoint: configs.list_category_children.path,
84
+ categoryCount: optionalInteger(data.count) ?? looseArray(data.children).length,
85
+ },
86
+ };
87
+ },
88
+ };
89
+ async function request(name, config, input, context, validating) {
90
+ const method = config.method ?? "POST";
91
+ const body = upstream(name, input);
92
+ return runProviderRequest({ signal: context.signal, label: "IXSPY" }, async (signal) => {
93
+ const url = new URL(config.path, baseUrl);
94
+ if (method === "GET")
95
+ for (const [key, value] of Object.entries(body)) {
96
+ if (Array.isArray(value))
97
+ for (const item of value)
98
+ url.searchParams.append(key, String(item));
99
+ else
100
+ url.searchParams.set(key, String(value));
101
+ }
102
+ const response = await context.fetcher(url, {
103
+ method,
104
+ headers: {
105
+ accept: "application/json",
106
+ authorization: `Bearer ${context.apiKey}`,
107
+ ...(method === "POST" ? { "content-type": "application/json" } : {}),
108
+ "user-agent": providerUserAgent,
109
+ },
110
+ body: method === "POST" ? JSON.stringify(body) : undefined,
111
+ signal,
112
+ });
113
+ const payload = requiredResponseRecord(await readProviderJsonBody(response, { emptyBody: {}, invalidJsonMessage: "IXSPY returned invalid JSON" }), "IXSPY response");
114
+ const error = optionalRecord(payload.error);
115
+ const code = optionalInteger(error?.code);
116
+ if (code !== undefined && code !== 0)
117
+ throw ixspyError(code, optionalString(error?.message), validating);
118
+ if (!response.ok)
119
+ throw new ProviderRequestError(response.status, optionalString(error?.message) ?? `IXSPY request failed with HTTP ${response.status}`, payload);
120
+ if (code !== 0)
121
+ throw providerResponseError("IXSPY response is missing a success code");
122
+ return payload;
123
+ });
124
+ }
125
+ function upstream(name, input) {
126
+ return compactObject(Object.fromEntries(Object.entries(input).map(([key, value]) => {
127
+ let field = keyOverrides[key] ?? snake(key);
128
+ if ((name === "get_product_rank" || name === "get_region_product_rank") &&
129
+ (key === "priceMin" || key === "priceMax"))
130
+ field = key === "priceMin" ? "product_price_min" : "product_price_max";
131
+ if (key === "hasVideo")
132
+ value = value === true ? 1 : value === false ? 2 : value;
133
+ if ((key === "isLeaf" || key === "styleZone") && typeof value === "boolean")
134
+ value = value ? 1 : 0;
135
+ if (key === "orderBy" && typeof value === "string")
136
+ value = orderValues[value] ?? value;
137
+ if (key === "rankType" && typeof value === "string")
138
+ value = rankValues[value] ?? value;
139
+ return [field, value];
140
+ })));
141
+ }
142
+ function snake(value) {
143
+ let result = "";
144
+ for (const character of value)
145
+ result += character === character.toLowerCase() ? character : `_${character.toLowerCase()}`;
146
+ return result;
147
+ }
148
+ function ixspyError(code, message, validating) {
149
+ const detail = message?.trim() || `IXSPY error ${code}`;
150
+ if (code === 10402 || code === 10404)
151
+ return validating ? providerInputError(detail) : new ProviderRequestError(409, detail);
152
+ if (code === 10429)
153
+ return new ProviderRequestError(429, detail);
154
+ if (code === 5024)
155
+ return new ProviderRequestError(402, detail);
156
+ if (code === 10422)
157
+ return providerInputError(detail);
158
+ return new ProviderRequestError(code === 5016 ? 404 : 502, detail);
159
+ }
160
+ function normalize(kind, payload) {
161
+ const data = requiredResponseRecord(payload.data, "IXSPY data");
162
+ const credits = optionalNumber(payload.credits) ?? null;
163
+ if (kind === "category_resource")
164
+ return { url: responseString(data.link, "category resource link"), credits };
165
+ if (kind === "category_children")
166
+ return {
167
+ parentId: identifier(data.parent_id, "parent category ID"),
168
+ count: optionalInteger(data.count) ?? looseArray(data.children).length,
169
+ categories: looseArray(data.children),
170
+ credits,
171
+ };
172
+ if (kind === "rank_dates")
173
+ return {
174
+ rankType: responseString(data.rank_type, "rank type"),
175
+ dateTypes: looseArray(data.date_type_list),
176
+ credits,
177
+ };
178
+ if (kind === "product_statistics" || kind === "store_statistics")
179
+ return {
180
+ entityId: identifier(data[kind === "product_statistics" ? "product_id" : "store_merchant_id"], "entity ID"),
181
+ statistics: looseArray(data.stat_data),
182
+ credits,
183
+ };
184
+ if (kind === "product_trends" || kind === "store_trends")
185
+ return {
186
+ entityId: identifier(data[kind === "product_trends" ? "product_id" : "store_merchant_id"], "entity ID"),
187
+ startDate: optionalString(data.start_date) ?? null,
188
+ endDate: optionalString(data.end_date) ?? null,
189
+ points: looseArray(data.trend_data),
190
+ credits,
191
+ };
192
+ return {
193
+ items: looseArray(data.list),
194
+ page: numberLike(data.page),
195
+ pages: numberLike(data.pages),
196
+ total: numberLike(data.total),
197
+ credits,
198
+ };
199
+ }
200
+ function identifier(value, label) {
201
+ if (typeof value === "string" || (typeof value === "number" && Number.isFinite(value)))
202
+ return value;
203
+ throw providerResponseError(`IXSPY ${label} is required`);
204
+ }
205
+ function responseString(value, label) {
206
+ const result = optionalString(value);
207
+ if (result != null)
208
+ return result;
209
+ throw providerResponseError(`IXSPY ${label} is required`);
210
+ }
211
+ function numberLike(value) {
212
+ if (typeof value === "number")
213
+ return value;
214
+ if (typeof value === "string" && value.trim()) {
215
+ const result = Number(value);
216
+ if (Number.isFinite(result))
217
+ return result;
218
+ }
219
+ return null;
220
+ }
@@ -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>;
@@ -1,4 +1,4 @@
1
- import { Client } from "@modelcontextprotocol/client";
1
+ import { Client, SdkHttpError } from "@modelcontextprotocol/client";
2
2
  import { SSEClientTransport } from "@modelcontextprotocol/client";
3
3
  import { StreamableHTTPClientTransport } from "@modelcontextprotocol/client";
4
4
  import { CfWorkerJsonSchemaValidator } from "@modelcontextprotocol/client/validators/cf-worker";
@@ -6,33 +6,47 @@ const mcpConnectTimeoutMs = 60_000;
6
6
  const modernMcpProtocolVersion = "2026-07-28";
7
7
  const mcpJsonSchemaValidator = new CfWorkerJsonSchemaValidator();
8
8
  export async function withMcpClient(options, run) {
9
- const transportOptions = {
10
- fetch: options.fetcher,
11
- requestInit: {
12
- headers: options.headers,
13
- redirect: options.redirect,
14
- signal: options.signal,
15
- },
16
- };
17
- const transport = options.transport === "sse"
18
- ? new SSEClientTransport(options.endpoint, transportOptions)
19
- : new StreamableHTTPClientTransport(options.endpoint, transportOptions);
20
- const client = new Client({ name: "open-connector", version: "1.0.0" }, {
21
- jsonSchemaValidator: mcpJsonSchemaValidator,
22
- versionNegotiation: { mode: resolveVersionNegotiationMode(options.protocolVersion) },
23
- });
24
- try {
25
- await client.connect(transport, { timeout: mcpConnectTimeoutMs, signal: options.signal });
26
- return await run(client);
27
- }
28
- catch (error) {
29
- throw options.mapError ? options.mapError(error) : error;
30
- }
31
- finally {
32
- if (options.terminateSession && transport instanceof StreamableHTTPClientTransport) {
33
- await terminateMcpSession(transport);
9
+ let retriedSession = false;
10
+ while (true) {
11
+ const transportOptions = {
12
+ fetch: options.fetcher,
13
+ requestInit: {
14
+ headers: options.headers,
15
+ redirect: options.redirect,
16
+ signal: options.signal,
17
+ },
18
+ };
19
+ const transport = options.transport === "sse"
20
+ ? new SSEClientTransport(options.endpoint, transportOptions)
21
+ : new StreamableHTTPClientTransport(options.endpoint, transportOptions);
22
+ const client = new Client({ name: "open-connector", version: "1.0.0" }, {
23
+ jsonSchemaValidator: mcpJsonSchemaValidator,
24
+ versionNegotiation: { mode: resolveVersionNegotiationMode(options.protocolVersion) },
25
+ });
26
+ let connected = false;
27
+ try {
28
+ await client.connect(transport, { timeout: mcpConnectTimeoutMs, signal: options.signal });
29
+ connected = true;
30
+ return await run(client);
31
+ }
32
+ catch (error) {
33
+ if (connected &&
34
+ options.transport === "streamable_http" &&
35
+ options.retryOnSessionNotFound === true &&
36
+ !retriedSession &&
37
+ error instanceof SdkHttpError &&
38
+ error.status === 404) {
39
+ retriedSession = true;
40
+ continue;
41
+ }
42
+ throw options.mapError ? options.mapError(error) : error;
43
+ }
44
+ finally {
45
+ if (options.terminateSession && transport instanceof StreamableHTTPClientTransport) {
46
+ await terminateMcpSession(transport);
47
+ }
48
+ await client.close().catch(() => undefined);
34
49
  }
35
- await client.close().catch(() => undefined);
36
50
  }
37
51
  }
38
52
  async function terminateMcpSession(transport) {
@@ -0,0 +1,2 @@
1
+ import type { ProviderExecutors } from "../../core/types.ts";
2
+ export declare const executors: ProviderExecutors;
@@ -0,0 +1,11 @@
1
+ import { defineProviderExecutors } from "../provider-runtime.js";
2
+ import { osvActionHandlers } from "./runtime.js";
3
+ const service = "osv";
4
+ export const executors = defineProviderExecutors({
5
+ service,
6
+ handlers: osvActionHandlers,
7
+ skipDnsValidation: true,
8
+ createContext(context, fetcher) {
9
+ return { fetcher, signal: context.signal };
10
+ },
11
+ });
@@ -0,0 +1,9 @@
1
+ import type { ProviderActionHandlers, ProviderFetch } from "../provider-runtime.ts";
2
+ export declare const osvApiBaseUrl = "https://api.osv.dev";
3
+ export interface OsvRuntimeContext {
4
+ fetcher: ProviderFetch;
5
+ signal?: AbortSignal;
6
+ }
7
+ type OsvActionHandler = (input: Record<string, unknown>, context: OsvRuntimeContext) => Promise<unknown>;
8
+ export declare const osvActionHandlers: ProviderActionHandlers<"osv", OsvActionHandler>;
9
+ export {};
@@ -0,0 +1,66 @@
1
+ import { compactObject, optionalRawString, optionalRecord, optionalString } from "../../core/cast.js";
2
+ import { providerResponseError, providerUserAgent, ProviderRequestError, readProviderJsonBody, requiredInputString, requiredResponseRecord, runProviderRequest, } from "../provider-runtime.js";
3
+ export const osvApiBaseUrl = "https://api.osv.dev";
4
+ export const osvActionHandlers = {
5
+ async query_vulnerabilities(input, context) {
6
+ const payload = requiredResponseRecord(await requestOsvJson("/v1/query", {
7
+ method: "POST",
8
+ body: JSON.stringify(compactObject({
9
+ package: {
10
+ ecosystem: requiredInputString(input.ecosystem, "ecosystem"),
11
+ name: requiredInputString(input.package, "package"),
12
+ },
13
+ version: optionalString(input.version),
14
+ page_token: optionalString(input.pageToken),
15
+ })),
16
+ }, context), "OSV query response");
17
+ const vulnerabilities = payload.vulns === undefined ? [] : payload.vulns;
18
+ if (!Array.isArray(vulnerabilities)) {
19
+ throw providerResponseError("OSV query vulnerabilities must be an array of objects");
20
+ }
21
+ if (!vulnerabilities.every((vulnerability) => optionalRecord(vulnerability))) {
22
+ throw providerResponseError("OSV query vulnerabilities must be an array of objects");
23
+ }
24
+ return {
25
+ vulnerabilities,
26
+ nextPageToken: optionalString(payload.next_page_token),
27
+ };
28
+ },
29
+ async get_vulnerability(input, context) {
30
+ const id = encodeURIComponent(requiredInputString(input.id, "id"));
31
+ return requiredResponseRecord(await requestOsvJson(`/v1/vulns/${id}`, { method: "GET" }, context), "OSV vulnerability response");
32
+ },
33
+ };
34
+ async function requestOsvJson(path, init, context) {
35
+ return runProviderRequest({ label: "OSV", signal: context.signal }, async (signal) => {
36
+ const response = await context.fetcher(`${osvApiBaseUrl}${path}`, {
37
+ ...init,
38
+ headers: {
39
+ accept: "application/json",
40
+ "content-type": "application/json",
41
+ "user-agent": providerUserAgent,
42
+ },
43
+ signal,
44
+ });
45
+ const payload = await readProviderJsonBody(response, {
46
+ emptyBody: null,
47
+ invalidJsonMessage: "OSV returned invalid JSON",
48
+ invalidJsonFallback: response.ok ? undefined : (text) => text.trim(),
49
+ });
50
+ if (!response.ok) {
51
+ throw createOsvError(response.status, payload);
52
+ }
53
+ return payload;
54
+ });
55
+ }
56
+ function createOsvError(status, payload) {
57
+ const record = optionalRecord(payload);
58
+ const message = optionalRawString(payload) ??
59
+ optionalString(record?.message) ??
60
+ optionalString(record?.error) ??
61
+ `OSV request failed with status ${status}`;
62
+ if (status === 401 || status === 403) {
63
+ return new ProviderRequestError(502, message, payload);
64
+ }
65
+ return new ProviderRequestError(status || 502, message, payload);
66
+ }
@@ -0,0 +1,4 @@
1
+ import type { CredentialValidators, ProviderExecutors, ProviderProxyExecutor } from "../../core/types.ts";
2
+ export declare const executors: ProviderExecutors;
3
+ export declare const proxy: ProviderProxyExecutor;
4
+ export declare const credentialValidators: CredentialValidators;
@@ -0,0 +1,108 @@
1
+ import { compactObject, optionalRecord, optionalString } from "../../core/cast.js";
2
+ import { defineApiKeyProviderExecutors, defineProviderProxy, providerInputError, ProviderRequestError, providerUserAgent, readProviderJsonBody, requiredInputString, runProviderRequest, } from "../provider-runtime.js";
3
+ const service = "pdf_vector";
4
+ const pdfVectorApiBaseUrl = "https://global.pdfvector.com/api";
5
+ const credentialUrl = "https://global.pdfvector.com/rpc/authenticate/validateCredential";
6
+ const handlers = {
7
+ parse_document(input, context) {
8
+ return executeDocumentAction("/document/parse", input, context);
9
+ },
10
+ ask_document(input, context) {
11
+ return executeDocumentAction("/document/ask", input, context);
12
+ },
13
+ extract_document(input, context) {
14
+ return executeDocumentAction("/document/extract", input, context);
15
+ },
16
+ };
17
+ export const executors = defineApiKeyProviderExecutors(service, handlers, {
18
+ skipDnsValidation: true,
19
+ });
20
+ export const proxy = defineProviderProxy({
21
+ service,
22
+ baseUrl: pdfVectorApiBaseUrl,
23
+ auth: { type: "bearer" },
24
+ skipDnsValidation: true,
25
+ customizeRequest({ headers }) {
26
+ headers.set("accept", "application/json");
27
+ headers.set("x-pdfvector-source", "oomol-connector");
28
+ },
29
+ });
30
+ export const credentialValidators = {
31
+ async apiKey(input, { fetcher, signal }) {
32
+ const payload = await requestJson({
33
+ url: credentialUrl,
34
+ body: {},
35
+ context: { apiKey: input.apiKey, fetcher, signal },
36
+ phase: "validate",
37
+ });
38
+ const version = optionalString(optionalRecord(optionalRecord(payload)?.json)?.version);
39
+ if (!version)
40
+ throw new ProviderRequestError(502, "PDF Vector credential validation response did not include a server version");
41
+ return {
42
+ profile: { accountId: "pdf-vector-api-key", displayName: "PDF Vector API Key" },
43
+ grantedScopes: [],
44
+ metadata: {
45
+ apiBaseUrl: pdfVectorApiBaseUrl,
46
+ validationEndpoint: "/rpc/authenticate/validateCredential",
47
+ serverVersion: version,
48
+ },
49
+ };
50
+ },
51
+ };
52
+ function executeDocumentAction(path, input, context) {
53
+ return requestJson({
54
+ url: `${pdfVectorApiBaseUrl}${path}`,
55
+ body: compactObject({
56
+ url: requiredInputString(input.documentUrl, "documentUrl"),
57
+ model: optionalString(input.model),
58
+ includePages: input.includePages,
59
+ question: optionalString(input.question),
60
+ prompt: optionalString(input.prompt),
61
+ schema: optionalRecord(input.schema),
62
+ }),
63
+ documentId: optionalString(input.documentId),
64
+ context,
65
+ phase: "execute",
66
+ });
67
+ }
68
+ async function requestJson(input) {
69
+ return runProviderRequest({ signal: input.context.signal, label: "PDF Vector" }, async (signal) => {
70
+ const response = await input.context.fetcher(input.url, {
71
+ method: "POST",
72
+ headers: {
73
+ accept: "application/json",
74
+ authorization: `Bearer ${input.context.apiKey}`,
75
+ "content-type": "application/json",
76
+ "user-agent": providerUserAgent,
77
+ "x-pdfvector-source": "oomol-connector",
78
+ ...(input.documentId ? { "x-pdfvector-document-id": input.documentId } : {}),
79
+ },
80
+ body: JSON.stringify(input.body),
81
+ signal,
82
+ });
83
+ const payload = await readProviderJsonBody(response, {
84
+ emptyBody: null,
85
+ invalidJsonMessage: "PDF Vector returned invalid JSON",
86
+ });
87
+ if (!response.ok)
88
+ throw createError(response.status, payload, input.phase);
89
+ return payload;
90
+ });
91
+ }
92
+ function createError(status, payload, phase) {
93
+ const record = optionalRecord(payload);
94
+ const json = optionalRecord(record?.json);
95
+ const error = optionalRecord(record?.error);
96
+ const message = optionalString(json?.message) ??
97
+ optionalString(error?.message) ??
98
+ optionalString(record?.message) ??
99
+ `PDF Vector request failed with status ${status}`;
100
+ const code = optionalString(json?.code) ?? optionalString(error?.code) ?? optionalString(record?.code);
101
+ if (phase === "validate" && status === 401 && code === "UNAUTHORIZED")
102
+ return providerInputError(message);
103
+ if (status === 429)
104
+ return new ProviderRequestError(429, message, payload);
105
+ if (phase === "execute" && [400, 404, 422].includes(status))
106
+ return providerInputError(message);
107
+ return new ProviderRequestError(status || 502, message, payload);
108
+ }
@@ -284,6 +284,8 @@ export interface ProviderProxyDefinition {
284
284
  auth: ProviderProxyAuth;
285
285
  allowedEndpoint?: (endpoint: string) => boolean;
286
286
  customizeRequest?: (input: ProviderProxyRequestCustomizationInput) => Promise<void> | void;
287
+ /** Parse a failed HTTP response using the same provider error rules as actions. */
288
+ readError?: (response: Response) => Promise<ProviderRequestError>;
287
289
  /** Provider-specific credential/signature headers that redirects must not forward cross-origin. */
288
290
  sensitiveHeaders?: readonly string[];
289
291
  /** Exact code-controlled origins that `customizeRequest` may select in addition to the resolved base origin. */
@@ -299,6 +301,7 @@ export interface ProviderProxyDefinition {
299
301
  /** Deliberate provider-specific response byte cap; defaults to the shared 20 MiB limit. */
300
302
  maxResponseBytes?: number;
301
303
  }
304
+ export declare const defaultProviderJsonMaxResponseBytes: number;
302
305
  export declare function createProviderProxyUrl(baseUrl: string, endpointInput: unknown, queryInput?: unknown, allowedOrigins?: readonly string[]): URL;
303
306
  export declare function normalizeProviderProxyEndpoint(endpointInput: unknown, allowedOrigins?: readonly string[]): string;
304
307
  export declare function normalizeProviderProxyQuery(queryInput: unknown): Record<string, string>;
@@ -125,7 +125,7 @@ const blockedProxyRequestHeaders = new Set([
125
125
  "transfer-encoding",
126
126
  ]);
127
127
  const defaultProviderProxyMaxResponseBytes = 20 * 1024 * 1024;
128
- const defaultProviderJsonMaxResponseBytes = 20 * 1024 * 1024;
128
+ export const defaultProviderJsonMaxResponseBytes = 20 * 1024 * 1024;
129
129
  const defaultProviderErrorMaxResponseBytes = 64 * 1024;
130
130
  const defaultProviderRequestTimeoutMs = 30_000;
131
131
  export function createProviderProxyUrl(baseUrl, endpointInput, queryInput, allowedOrigins) {
@@ -356,6 +356,9 @@ export function defineProviderProxy(input) {
356
356
  }
357
357
  const response = await egressFetch(url, init);
358
358
  if (!response.ok) {
359
+ if (input.readError) {
360
+ throw await input.readError(response);
361
+ }
359
362
  throw new ProviderRequestError(response.status, await readProviderProxyErrorMessage(response, `provider request failed with HTTP ${response.status}`));
360
363
  }
361
364
  return {
@@ -0,0 +1,4 @@
1
+ import type { CredentialValidators, ProviderExecutors, ProviderProxyExecutor } from "../../core/types.ts";
2
+ export declare const executors: ProviderExecutors;
3
+ export declare const proxy: ProviderProxyExecutor;
4
+ export declare const credentialValidators: CredentialValidators;