@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.
- package/dist/{airtable-S3T4TAN7.js → airtable-23JBIM6X.js} +106 -114
- package/dist/{alt_text_generator_ai-4DIRIDKL.js → alt_text_generator_ai-ADWBTCIH.js} +25 -16
- package/dist/{amap-LGVGNPML.js → amap-CYQCYW2Z.js} +114 -123
- package/dist/{anthropic-27RFZO35.js → anthropic-5P62HDNR.js} +34 -56
- package/dist/{apify-6WLYAIAS.js → apify-54RZUAGW.js} +31 -49
- package/dist/{brave_search-K2SVJ66F.js → brave_search-AHJ6FTD5.js} +52 -77
- package/dist/{chunk-VK3V2WTY.js → chunk-B4P6YZFS.js} +4 -6
- package/dist/{chunk-BB6ZLMTU.js → chunk-CLEZ6YQ6.js} +2600 -481
- package/dist/chunk-JXHMDBAY.js +45 -0
- package/dist/chunk-LMLX3DJF.js +50 -0
- package/dist/{chunk-YB2FLNWI.js → chunk-OKRZPQ3R.js} +2558 -1926
- package/dist/chunk-SWBNHIO4.js +977 -0
- package/dist/chunk-U67V476Y.js +35 -0
- package/dist/chunk-VLOIDU5U.js +283 -0
- package/dist/{circleci-WV3ITU7Q.js → circleci-UM3NSQJ3.js} +36 -55
- package/dist/{clerk-NFQEFKS4.js → clerk-FE5LQ2CZ.js} +60 -80
- package/dist/{cloudflare_dns-2RK5ASBJ.js → cloudflare_dns-KEZABKUT.js} +90 -113
- package/dist/{cohere-5KEW7LWT.js → cohere-4IPJADXP.js} +33 -49
- package/dist/{confluence-SZE63S46.js → confluence-56QEKNQI.js} +79 -115
- package/dist/{convertapi-QPG2JC5K.js → convertapi-3QRM5K5T.js} +13 -16
- package/dist/{currencyapi-UO2APQRY.js → currencyapi-L6G4OND5.js} +30 -53
- package/dist/{deepseek-LJELIMM3.js → deepseek-LGC6HBFG.js} +30 -38
- package/dist/{docker_hub-2MFXSBOF.js → docker_hub-XDMK3BIU.js} +141 -157
- package/dist/{dropbox-GQYNTTVA.js → dropbox-4QARMFZU.js} +134 -141
- package/dist/{dub-KI2LHXST.js → dub-C6JSJKOT.js} +61 -93
- package/dist/{e2b-WO6ISY3C.js → e2b-6A6TVACJ.js} +39 -69
- package/dist/{exa-IZ7B3BPT.js → exa-SIWWW6AA.js} +49 -77
- package/dist/{fal_ai-LTMF36GJ.js → fal_ai-3IJXOKSP.js} +37 -44
- package/dist/{feishu-WM7SLSFD.js → feishu-L4KDA4DC.js} +4 -6
- package/dist/{feishu_custom_bot-66W3MXH2.js → feishu_custom_bot-SDM75H4P.js} +4 -5
- package/dist/{figma-2Z274VQZ.js → figma-6DD436DN.js} +56 -81
- package/dist/{firehydrant-IFI4R65V.js → firehydrant-SYSGYB3R.js} +40 -53
- package/dist/{fixer-BCCZEB3D.js → fixer-FZG7ASTF.js} +31 -43
- package/dist/{fly-755FXYB5.js → fly-HMRCZBUC.js} +50 -66
- package/dist/{front-4FZKKXXK.js → front-FAFSD7I3.js} +43 -66
- package/dist/{geocodio-WYKDJ3DP.js → geocodio-4D3TWENM.js} +37 -63
- package/dist/{ghost-5BNQTCOH.js → ghost-OSO2FOZS.js} +51 -57
- package/dist/{github-ULELF5VX.js → github-OR4I4RHE.js} +48 -41
- package/dist/{gmail-G34WT64J.js → gmail-5AOPJ63E.js} +26 -36
- package/dist/{googlecalendar-BQU255SC.js → googlecalendar-SOJIJUWH.js} +57 -78
- package/dist/{googledocs-HPCNQXYJ.js → googledocs-QSKN5TLN.js} +14 -22
- package/dist/{grafana-VOV24FIC.js → grafana-R3AIZM7M.js} +95 -122
- package/dist/{graphhopper-D5RXW6AP.js → graphhopper-4CR3QOAX.js} +32 -46
- package/dist/index.d.ts +108 -56
- package/dist/index.js +4 -3
- package/dist/{ip2proxy-DAYO7EKZ.js → ip2proxy-OBCG6X6J.js} +35 -42
- package/dist/{ipgeolocation_io-XD4PSLII.js → ipgeolocation_io-NHH3DTQW.js} +40 -60
- package/dist/{ipqualityscore-K27QEAWK.js → ipqualityscore-7POMCBEC.js} +30 -42
- package/dist/{jina_ai-E6UXFV2P.js → jina_ai-YXVKROV4.js} +32 -58
- package/dist/{jira-ZDSXGQ6W.js → jira-LADO3VJU.js} +116 -126
- package/dist/{langsmith-TIFJRREW.js → langsmith-XZ6UAQFU.js} +101 -121
- package/dist/{lemlist-DASEMJMA.js → lemlist-P74GLNE7.js} +57 -68
- package/dist/{linear-KE6UP4SP.js → linear-CXJ7D37A.js} +109 -118
- package/dist/{logsnag-IMNDN4R5.js → logsnag-EVVHWFLK.js} +31 -48
- package/dist/main.js +103 -102
- package/dist/{mattermost-HHHMUXQA.js → mattermost-WG2MRGBD.js} +45 -62
- package/dist/{mem0-D2FGGOIY.js → mem0-HQWUKG6U.js} +72 -98
- package/dist/{memos-4OVIGFPH.js → memos-SQMJIFOE.js} +68 -122
- package/dist/{metabase-33WCX5YD.js → metabase-E27G2DZI.js} +47 -60
- package/dist/{mistral_ai-QIMZ2JYL.js → mistral_ai-MIL63NIT.js} +35 -40
- package/dist/{mother_duck-M6VWS2VH.js → mother_duck-AIZVCBNR.js} +42 -62
- package/dist/{ngrok-Z2PKQBHH.js → ngrok-XS4DVIQS.js} +42 -58
- package/dist/{notes-SS4RPC4K.js → notes-JEOUSL2Y.js} +3 -5
- package/dist/{notion-FJCNQ6I7.js → notion-U4EZVDW2.js} +83 -97
- package/dist/{open_exchange_rates-WU57WTT5.js → open_exchange_rates-AZSQEYEJ.js} +35 -39
- package/dist/{openai-JODZ4GKT.js → openai-HW3SYMTQ.js} +51 -55
- package/dist/{opengraph_io-SQRAUSV5.js → opengraph_io-QX74MAEL.js} +61 -79
- package/dist/{openrouter-Q5XXEJZ7.js → openrouter-OXSKYL6N.js} +41 -55
- package/dist/{outline-RT2EHJ2X.js → outline-CCQAPDSW.js} +89 -104
- package/dist/{paddle-OF2V7GAC.js → paddle-6KQPSSCK.js} +34 -49
- package/dist/{perplexity-LNZEWLHG.js → perplexity-2TXO7IQE.js} +33 -50
- package/dist/{pinecone-JSJIXZYN.js → pinecone-YOO7NULI.js} +65 -91
- package/dist/{pipedrive-D4CKVUXR.js → pipedrive-Q6RIFIFP.js} +37 -59
- package/dist/{polar-M7ZYP6UR.js → polar-KUMGCES3.js} +43 -53
- package/dist/{posthog-YV7CZOH4.js → posthog-VXQHBSMB.js} +58 -77
- package/dist/{postmark-KYHLECRG.js → postmark-YLIPF52S.js} +52 -71
- package/dist/{prerender-HCMHBKV2.js → prerender-CRY7UJN5.js} +32 -50
- package/dist/{pubmed-WYVLCCN3.js → pubmed-3Z4T5AM7.js} +28 -60
- package/dist/{railway-TWIRD5KR.js → railway-BP37IGFL.js} +32 -39
- package/dist/{readwise-UZ467IQ7.js → readwise-HTKICF4K.js} +62 -78
- package/dist/{render-MECUC5CC.js → render-WIVTUXJH.js} +48 -64
- package/dist/{replicate-A5MEK3SW.js → replicate-JJYPA43D.js} +41 -58
- package/dist/{resend-BC6EAWJQ.js → resend-TKHZVG7A.js} +27 -37
- package/dist/{rootly-ZM3QDUIS.js → rootly-FRSZLG5U.js} +64 -76
- package/dist/{scrapfly-WAML42QJ.js → scrapfly-M5WXGQWE.js} +45 -51
- package/dist/{scrapingbee-DG7PET3V.js → scrapingbee-PMXNLLBK.js} +25 -33
- package/dist/{screenshot_fyi-HY6WTHIO.js → screenshot_fyi-HFW4TAOH.js} +29 -47
- package/dist/{semantic_scholar-C5IZA7IP.js → semantic_scholar-KXVH2VZQ.js} +37 -56
- package/dist/{sentry-OKBPSTDM.js → sentry-WWOT2LRX.js} +66 -85
- package/dist/{shodan-PPC6DYU4.js → shodan-FY635H35.js} +42 -53
- package/dist/{shopify-EWGUHBXO.js → shopify-HQLBVSA5.js} +32 -49
- package/dist/{stripe-6RPDPC5W.js → stripe-GJN2GOHB.js} +4 -5
- package/dist/{supabase-SK7DQ42N.js → supabase-BBNZGQU6.js} +69 -88
- package/dist/{tavily-YCG5VQMH.js → tavily-DPENIBOG.js} +37 -62
- package/dist/{telegram-2OES5FYB.js → telegram-L4NONG6H.js} +168 -177
- package/dist/{telnyx-POOSBBR4.js → telnyx-H67MAEZS.js} +30 -50
- package/dist/{todoist-M7YD6YSS.js → todoist-G2BSP4DX.js} +77 -89
- package/dist/{trello-IS6V5W3E.js → trello-7WMVFDG2.js} +108 -122
- package/dist/{turso-RCFHUFVH.js → turso-ZUAESFC2.js} +52 -64
- package/dist/{twilio-OS2RXFGO.js → twilio-EYFYIX3B.js} +48 -55
- package/dist/{umami-PQ2SJ2LN.js → umami-AXAUDUVF.js} +49 -69
- package/dist/{unsplash-C6BPZO4E.js → unsplash-UCQAWPLR.js} +35 -52
- package/dist/{upstash_redis-WH6UER7H.js → upstash_redis-ZPZ4ASU6.js} +28 -40
- package/dist/{uptimerobot-M3YZGS6Z.js → uptimerobot-4QVKKUD5.js} +11 -12
- package/dist/{v2ex-R4JWTEHN.js → v2ex-VGEFJTYC.js} +36 -61
- package/dist/{vercel-FZVYUOQD.js → vercel-JME4TSCN.js} +124 -150
- package/dist/{webapi-VLM4IKVB.js → webapi-GW5QXWXE.js} +1 -1
- package/dist/{wolfram_alpha_api-2KOLO5DC.js → wolfram_alpha_api-TRGU2MDG.js} +26 -34
- package/dist/{wordpress-XRWGO6LG.js → wordpress-WRUKLCZR.js} +87 -104
- package/dist/{workos-WR4NKOYL.js → workos-ZDW4EHS4.js} +37 -56
- package/dist/{zhihu-BKZIB3WA.js → zhihu-4VI67CWU.js} +35 -57
- package/package.json +3 -3
- package/dist/chunk-2O27H4Y2.js +0 -183
- package/dist/chunk-GKX72JMJ.js +0 -378
- package/dist/chunk-MLKGABMK.js +0 -9
|
@@ -1,27 +1,27 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createProviderHttpClient
|
|
3
|
+
} from "./chunk-VLOIDU5U.js";
|
|
4
|
+
import {
|
|
5
|
+
trimmedText
|
|
6
|
+
} from "./chunk-JXHMDBAY.js";
|
|
1
7
|
import {
|
|
2
8
|
createProviderPlugin,
|
|
3
9
|
requireApiKey,
|
|
4
10
|
upstreamError
|
|
5
|
-
} from "./chunk-
|
|
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
14
|
TBError,
|
|
12
15
|
external_exports
|
|
13
|
-
} from "./chunk-
|
|
14
|
-
import "./chunk-
|
|
16
|
+
} from "./chunk-OKRZPQ3R.js";
|
|
17
|
+
import "./chunk-U67V476Y.js";
|
|
15
18
|
|
|
16
19
|
// ../plugins/src/render/api.ts
|
|
17
20
|
var SERVICE = "render";
|
|
18
21
|
var API_BASE = "https://api.render.com/v1";
|
|
19
|
-
|
|
20
|
-
const trimmed = value?.trim();
|
|
21
|
-
return trimmed === void 0 || trimmed === "" ? void 0 : trimmed;
|
|
22
|
-
}
|
|
22
|
+
var http = createProviderHttpClient({ baseUrl: `${API_BASE}/`, service: SERVICE });
|
|
23
23
|
function pathSegment(value, field) {
|
|
24
|
-
const parsed =
|
|
24
|
+
const parsed = trimmedText(value);
|
|
25
25
|
if (parsed === void 0) throw new TBError("invalid_argument", `${field} \u4E0D\u80FD\u4E3A\u7A7A`);
|
|
26
26
|
return encodeURIComponent(parsed);
|
|
27
27
|
}
|
|
@@ -31,14 +31,10 @@ function firstString(...values) {
|
|
|
31
31
|
}
|
|
32
32
|
return void 0;
|
|
33
33
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
} catch {
|
|
39
|
-
const text = await response.text().catch(() => "");
|
|
40
|
-
return text === "" ? `Render \u8FD4\u56DE HTTP ${response.status}` : text;
|
|
41
|
-
}
|
|
34
|
+
function errorMessage(context) {
|
|
35
|
+
if (context.bodyKind === "empty") return `Render \u8FD4\u56DE HTTP ${context.status}`;
|
|
36
|
+
if (context.bodyKind !== "json") return String(context.data);
|
|
37
|
+
const payload = context.data;
|
|
42
38
|
if (payload !== null && typeof payload === "object" && !Array.isArray(payload)) {
|
|
43
39
|
const object = payload;
|
|
44
40
|
const direct = firstString(object.message, object.error, object.detail, object.title);
|
|
@@ -53,51 +49,41 @@ async function errorMessage(response) {
|
|
|
53
49
|
}
|
|
54
50
|
}
|
|
55
51
|
}
|
|
56
|
-
return `Render \u8FD4\u56DE HTTP ${
|
|
52
|
+
return `Render \u8FD4\u56DE HTTP ${context.status}`;
|
|
57
53
|
}
|
|
58
54
|
async function send(ctx, input) {
|
|
59
55
|
const apiKey = requireApiKey(ctx, SERVICE);
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
method: input.method ?? "GET",
|
|
77
|
-
headers,
|
|
78
|
-
body: input.body === void 0 ? void 0 : JSON.stringify(input.body)
|
|
79
|
-
});
|
|
80
|
-
} catch (error) {
|
|
81
|
-
if (error instanceof TBError) throw error;
|
|
82
|
-
throw new TBError(
|
|
56
|
+
const query = Object.entries(input.query ?? {}).flatMap(([key, value]) => {
|
|
57
|
+
if (Array.isArray(value)) return value.length === 0 ? [] : [[key, value.join(",")]];
|
|
58
|
+
return [[key, value]];
|
|
59
|
+
});
|
|
60
|
+
return await http.request({
|
|
61
|
+
method: input.method ?? "GET",
|
|
62
|
+
path: input.path,
|
|
63
|
+
query,
|
|
64
|
+
headers: {
|
|
65
|
+
accept: "application/json",
|
|
66
|
+
authorization: `Bearer ${apiKey}`
|
|
67
|
+
},
|
|
68
|
+
...input.body === void 0 ? {} : { json: input.body },
|
|
69
|
+
invalidJson: "text",
|
|
70
|
+
mapError: (context) => upstreamError(context.status, errorMessage(context)),
|
|
71
|
+
mapTransportError: ({ message }) => new TBError(
|
|
83
72
|
"unavailable",
|
|
84
|
-
|
|
73
|
+
message === void 0 ? "Render \u8BF7\u6C42\u5931\u8D25" : `Render \u8BF7\u6C42\u5931\u8D25: ${message}`,
|
|
85
74
|
{ retryable: true }
|
|
86
|
-
)
|
|
87
|
-
}
|
|
75
|
+
)
|
|
76
|
+
});
|
|
88
77
|
}
|
|
89
78
|
async function requestJson(ctx, input) {
|
|
90
79
|
const response = await send(ctx, input);
|
|
91
|
-
if (
|
|
92
|
-
try {
|
|
93
|
-
return await response.json();
|
|
94
|
-
} catch {
|
|
80
|
+
if (response.bodyKind !== "json") {
|
|
95
81
|
throw new TBError("unavailable", "Render \u8FD4\u56DE\u4E86\u975E JSON \u54CD\u5E94", { retryable: true });
|
|
96
82
|
}
|
|
83
|
+
return response.data;
|
|
97
84
|
}
|
|
98
85
|
async function requestAck(ctx, input) {
|
|
99
|
-
|
|
100
|
-
if (!response.ok) throw upstreamError(response.status, await errorMessage(response));
|
|
86
|
+
await send(ctx, input);
|
|
101
87
|
}
|
|
102
88
|
function unwrapCursorList(payload, key) {
|
|
103
89
|
if (!Array.isArray(payload)) {
|
|
@@ -115,7 +101,7 @@ function unwrapCursorList(payload, key) {
|
|
|
115
101
|
throw new TBError("unavailable", `Render \u54CD\u5E94\u7F3A\u5C11 ${key}`, { retryable: true });
|
|
116
102
|
}
|
|
117
103
|
items.push(value);
|
|
118
|
-
nextCursor =
|
|
104
|
+
nextCursor = trimmedText(typeof record.cursor === "string" ? record.cursor : void 0) ?? nextCursor;
|
|
119
105
|
}
|
|
120
106
|
return { items, nextCursor };
|
|
121
107
|
}
|
|
@@ -128,7 +114,7 @@ async function listWorkspaces(input, ctx) {
|
|
|
128
114
|
query: {
|
|
129
115
|
name: input.name,
|
|
130
116
|
email: input.email,
|
|
131
|
-
cursor:
|
|
117
|
+
cursor: trimmedText(input.cursor),
|
|
132
118
|
limit: input.limit
|
|
133
119
|
}
|
|
134
120
|
});
|
|
@@ -144,7 +130,7 @@ async function listServices(input, ctx) {
|
|
|
144
130
|
ownerId: input.ownerId,
|
|
145
131
|
suspended: input.suspended,
|
|
146
132
|
includePreviews: input.includePreviews,
|
|
147
|
-
cursor:
|
|
133
|
+
cursor: trimmedText(input.cursor),
|
|
148
134
|
limit: input.limit
|
|
149
135
|
}
|
|
150
136
|
});
|
|
@@ -159,7 +145,7 @@ async function listDeploys(input, ctx) {
|
|
|
159
145
|
path: `/services/${pathSegment(input.serviceId, "serviceId")}/deploys`,
|
|
160
146
|
query: {
|
|
161
147
|
status: input.status,
|
|
162
|
-
cursor:
|
|
148
|
+
cursor: trimmedText(input.cursor),
|
|
163
149
|
limit: input.limit
|
|
164
150
|
}
|
|
165
151
|
});
|
|
@@ -177,22 +163,20 @@ async function triggerDeploy(input, ctx) {
|
|
|
177
163
|
// clearCache 没给时上游也显式发 do_not_clear(而不是省略),保持等价。
|
|
178
164
|
body: {
|
|
179
165
|
clearCache: input.clearCache === true ? "clear" : "do_not_clear",
|
|
180
|
-
...
|
|
181
|
-
...
|
|
166
|
+
...trimmedText(input.commitId) === void 0 ? {} : { commitId: trimmedText(input.commitId) },
|
|
167
|
+
...trimmedText(input.imageUrl) === void 0 ? {} : { imageUrl: trimmedText(input.imageUrl) },
|
|
182
168
|
...input.deployMode === void 0 ? {} : { deployMode: input.deployMode }
|
|
183
169
|
}
|
|
184
170
|
});
|
|
185
|
-
if (!response.ok) throw upstreamError(response.status, await errorMessage(response));
|
|
186
171
|
if (response.status === 202) return { queued: true, serviceId: input.serviceId };
|
|
187
|
-
|
|
188
|
-
return await response.json();
|
|
189
|
-
} catch {
|
|
172
|
+
if (response.bodyKind !== "json") {
|
|
190
173
|
throw new TBError("unavailable", "Render \u8FD4\u56DE\u4E86\u975E JSON \u54CD\u5E94", { retryable: true });
|
|
191
174
|
}
|
|
175
|
+
return response.data;
|
|
192
176
|
}
|
|
193
177
|
async function rollbackDeploy(input, ctx) {
|
|
194
178
|
const serviceId = pathSegment(input.serviceId, "serviceId");
|
|
195
|
-
const deployId =
|
|
179
|
+
const deployId = trimmedText(input.deployId);
|
|
196
180
|
if (deployId === void 0) throw new TBError("invalid_argument", "deployId \u4E0D\u80FD\u4E3A\u7A7A");
|
|
197
181
|
return await requestJson(ctx, {
|
|
198
182
|
path: `/services/${serviceId}/rollback`,
|
|
@@ -1,37 +1,30 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createProviderHttpClient
|
|
3
|
+
} from "./chunk-VLOIDU5U.js";
|
|
4
|
+
import {
|
|
5
|
+
asJsonObject,
|
|
6
|
+
compactDefined,
|
|
7
|
+
trimmedText
|
|
8
|
+
} from "./chunk-JXHMDBAY.js";
|
|
1
9
|
import {
|
|
2
10
|
createProviderPlugin,
|
|
3
11
|
requireApiKey,
|
|
4
12
|
upstreamError
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import
|
|
7
|
-
guardedFetch
|
|
8
|
-
} from "./chunk-2O27H4Y2.js";
|
|
9
|
-
import "./chunk-GKX72JMJ.js";
|
|
13
|
+
} from "./chunk-B4P6YZFS.js";
|
|
14
|
+
import "./chunk-SWBNHIO4.js";
|
|
10
15
|
import {
|
|
11
16
|
TBError,
|
|
12
17
|
external_exports
|
|
13
|
-
} from "./chunk-
|
|
14
|
-
import "./chunk-
|
|
18
|
+
} from "./chunk-OKRZPQ3R.js";
|
|
19
|
+
import "./chunk-U67V476Y.js";
|
|
15
20
|
|
|
16
21
|
// ../plugins/src/replicate/api.ts
|
|
17
22
|
var SERVICE = "replicate";
|
|
18
23
|
var API_BASE = "https://api.replicate.com";
|
|
19
24
|
var ACCOUNT_PATH = "/v1/account";
|
|
20
|
-
|
|
21
|
-
if (typeof value !== "string") return void 0;
|
|
22
|
-
const trimmed = value.trim();
|
|
23
|
-
return trimmed === "" ? void 0 : trimmed;
|
|
24
|
-
}
|
|
25
|
-
function record(value) {
|
|
26
|
-
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
|
|
27
|
-
}
|
|
28
|
-
function compact(input) {
|
|
29
|
-
return Object.fromEntries(
|
|
30
|
-
Object.entries(input).filter(([, value]) => value !== void 0)
|
|
31
|
-
);
|
|
32
|
-
}
|
|
25
|
+
var http = createProviderHttpClient({ baseUrl: `${API_BASE}/`, service: SERVICE });
|
|
33
26
|
function required(value, field) {
|
|
34
|
-
const trimmed =
|
|
27
|
+
const trimmed = trimmedText(value);
|
|
35
28
|
if (trimmed === void 0) throw new TBError("invalid_argument", `${field} \u4E0D\u80FD\u4E3A\u7A7A`);
|
|
36
29
|
return trimmed;
|
|
37
30
|
}
|
|
@@ -39,42 +32,32 @@ function segment(value, field) {
|
|
|
39
32
|
return encodeURIComponent(required(value, field));
|
|
40
33
|
}
|
|
41
34
|
async function request(ctx, input) {
|
|
42
|
-
const url = new URL(`${API_BASE}${input.path}`);
|
|
43
|
-
for (const [key, value] of Object.entries(input.query ?? {})) {
|
|
44
|
-
if (value !== void 0 && value !== "") url.searchParams.set(key, value);
|
|
45
|
-
}
|
|
46
35
|
const headers = {
|
|
47
36
|
accept: "application/json",
|
|
48
37
|
authorization: `Bearer ${requireApiKey(ctx, SERVICE)}`,
|
|
49
38
|
...input.headers
|
|
50
39
|
};
|
|
51
|
-
|
|
52
|
-
const response = await guardedFetch(url.toString(), {
|
|
40
|
+
const response = await http.request({
|
|
53
41
|
method: input.method ?? "GET",
|
|
42
|
+
path: input.path,
|
|
43
|
+
// 上游这里连空串一起跳过(空的 created_after 打出去会被上游当成非法时间戳)。
|
|
44
|
+
query: Object.entries(input.query ?? {}).filter(([, value]) => value !== void 0 && value !== ""),
|
|
54
45
|
headers,
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
if (raw !== "") {
|
|
61
|
-
try {
|
|
62
|
-
payload = JSON.parse(raw);
|
|
63
|
-
} catch {
|
|
64
|
-
isJson = false;
|
|
65
|
-
payload = { detail: raw };
|
|
46
|
+
...input.body === void 0 ? {} : { json: input.body },
|
|
47
|
+
invalidJson: "text",
|
|
48
|
+
mapError: ({ bodyKind, data, status }) => {
|
|
49
|
+
const body = bodyKind === "json" ? asJsonObject(data) ?? {} : { detail: data };
|
|
50
|
+
return upstreamError(status, trimmedText(body.detail) ?? trimmedText(body.title) ?? `Replicate \u8FD4\u56DE HTTP ${status}`);
|
|
66
51
|
}
|
|
52
|
+
});
|
|
53
|
+
if (response.bodyKind === "empty") return {};
|
|
54
|
+
if (response.bodyKind !== "json") {
|
|
55
|
+
throw new TBError("unavailable", "Replicate \u8FD4\u56DE\u4E86\u975E JSON \u54CD\u5E94", { retryable: true });
|
|
67
56
|
}
|
|
68
|
-
|
|
69
|
-
const body = record(payload) ?? {};
|
|
70
|
-
const message = text(body.detail) ?? text(body.title) ?? `Replicate \u8FD4\u56DE HTTP ${response.status}`;
|
|
71
|
-
throw upstreamError(response.status, message);
|
|
72
|
-
}
|
|
73
|
-
if (!isJson) throw new TBError("unavailable", "Replicate \u8FD4\u56DE\u4E86\u975E JSON \u54CD\u5E94", { retryable: true });
|
|
74
|
-
return payload;
|
|
57
|
+
return response.data;
|
|
75
58
|
}
|
|
76
59
|
function requireRecord(value, label) {
|
|
77
|
-
const payload =
|
|
60
|
+
const payload = asJsonObject(value);
|
|
78
61
|
if (payload === void 0) {
|
|
79
62
|
throw new TBError("unavailable", `Replicate \u7684 ${label} \u54CD\u5E94\u4E0D\u662F\u5BF9\u8C61`, { retryable: true });
|
|
80
63
|
}
|
|
@@ -100,9 +83,9 @@ async function getAccount(_input, ctx) {
|
|
|
100
83
|
async function listModels(input, ctx) {
|
|
101
84
|
const payload = await request(ctx, {
|
|
102
85
|
path: "/v1/models",
|
|
103
|
-
query:
|
|
104
|
-
sort_by:
|
|
105
|
-
sort_direction:
|
|
86
|
+
query: compactDefined({
|
|
87
|
+
sort_by: trimmedText(input.sortBy),
|
|
88
|
+
sort_direction: trimmedText(input.sortDirection)
|
|
106
89
|
})
|
|
107
90
|
});
|
|
108
91
|
return pageOf(payload, "models");
|
|
@@ -127,18 +110,18 @@ async function getCollection(input, ctx) {
|
|
|
127
110
|
return wrap(await request(ctx, { path }), "collection");
|
|
128
111
|
}
|
|
129
112
|
async function createPrediction(input, ctx) {
|
|
130
|
-
const headers =
|
|
113
|
+
const headers = compactDefined({
|
|
131
114
|
"Prefer": input.waitSeconds === void 0 ? void 0 : `wait=${input.waitSeconds}`,
|
|
132
|
-
"Cancel-After":
|
|
115
|
+
"Cancel-After": trimmedText(input.cancelAfter)
|
|
133
116
|
});
|
|
134
117
|
const payload = await request(ctx, {
|
|
135
118
|
method: "POST",
|
|
136
119
|
path: "/v1/predictions",
|
|
137
120
|
headers,
|
|
138
|
-
body:
|
|
121
|
+
body: compactDefined({
|
|
139
122
|
version: required(input.version, "version"),
|
|
140
|
-
input:
|
|
141
|
-
webhook:
|
|
123
|
+
input: asJsonObject(input.input) ?? {},
|
|
124
|
+
webhook: trimmedText(input.webhook),
|
|
142
125
|
webhook_events_filter: input.webhookEventsFilter
|
|
143
126
|
})
|
|
144
127
|
});
|
|
@@ -151,10 +134,10 @@ async function getPrediction(input, ctx) {
|
|
|
151
134
|
async function listPredictions(input, ctx) {
|
|
152
135
|
const payload = await request(ctx, {
|
|
153
136
|
path: "/v1/predictions",
|
|
154
|
-
query:
|
|
155
|
-
created_after:
|
|
156
|
-
created_before:
|
|
157
|
-
source:
|
|
137
|
+
query: compactDefined({
|
|
138
|
+
created_after: trimmedText(input.createdAfter),
|
|
139
|
+
created_before: trimmedText(input.createdBefore),
|
|
140
|
+
source: trimmedText(input.source)
|
|
158
141
|
})
|
|
159
142
|
});
|
|
160
143
|
return pageOf(payload, "predictions");
|
|
@@ -1,17 +1,21 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createProviderHttpClient
|
|
3
|
+
} from "./chunk-VLOIDU5U.js";
|
|
4
|
+
import {
|
|
5
|
+
asJsonObject,
|
|
6
|
+
trimmedText
|
|
7
|
+
} from "./chunk-JXHMDBAY.js";
|
|
1
8
|
import {
|
|
2
9
|
createProviderPlugin,
|
|
3
10
|
requireApiKey,
|
|
4
11
|
upstreamError
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import
|
|
7
|
-
guardedFetch
|
|
8
|
-
} from "./chunk-2O27H4Y2.js";
|
|
9
|
-
import "./chunk-GKX72JMJ.js";
|
|
12
|
+
} from "./chunk-B4P6YZFS.js";
|
|
13
|
+
import "./chunk-SWBNHIO4.js";
|
|
10
14
|
import {
|
|
11
15
|
TBError,
|
|
12
16
|
external_exports
|
|
13
|
-
} from "./chunk-
|
|
14
|
-
import "./chunk-
|
|
17
|
+
} from "./chunk-OKRZPQ3R.js";
|
|
18
|
+
import "./chunk-U67V476Y.js";
|
|
15
19
|
|
|
16
20
|
// ../plugins/src/resend/schema.handwritten.ts
|
|
17
21
|
var sendEmailInput = external_exports.strictObject({
|
|
@@ -40,47 +44,33 @@ var resendActions = {
|
|
|
40
44
|
|
|
41
45
|
// ../plugins/src/resend/api.ts
|
|
42
46
|
var SERVICE = "resend";
|
|
43
|
-
var API_BASE = "https://api.resend.com";
|
|
44
47
|
var AUTH_ERROR_NAMES = /* @__PURE__ */ new Set(["invalid_api_key", "missing_api_key"]);
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
try {
|
|
49
|
-
const parsed = JSON.parse(text2);
|
|
50
|
-
return parsed !== null && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
51
|
-
} catch {
|
|
52
|
-
return { message: text2 };
|
|
53
|
-
}
|
|
48
|
+
var http = createProviderHttpClient({ baseUrl: "https://api.resend.com/", service: SERVICE });
|
|
49
|
+
function payloadOf(data) {
|
|
50
|
+
return asJsonObject(data) ?? (typeof data === "string" ? { message: data } : {});
|
|
54
51
|
}
|
|
55
|
-
function
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
const message = text(payload.message) ?? text(payload.error_description) ?? `Resend \u8FD4\u56DE HTTP ${status}`;
|
|
61
|
-
if (AUTH_ERROR_NAMES.has(name)) {
|
|
62
|
-
return new TBError("permission_denied", message, { httpStatus: 401 });
|
|
63
|
-
}
|
|
64
|
-
return upstreamError(status, message);
|
|
52
|
+
function resendError(status, data) {
|
|
53
|
+
const payload = payloadOf(data);
|
|
54
|
+
const name = trimmedText(payload.name) ?? trimmedText(payload.error) ?? "provider_error";
|
|
55
|
+
const message = trimmedText(payload.message) ?? trimmedText(payload.error_description) ?? `Resend \u8FD4\u56DE HTTP ${status}`;
|
|
56
|
+
return AUTH_ERROR_NAMES.has(name) ? new TBError("permission_denied", message, { httpStatus: 401 }) : upstreamError(status, message);
|
|
65
57
|
}
|
|
66
58
|
async function sendEmail(input, ctx) {
|
|
67
|
-
const
|
|
59
|
+
const { data } = await http.request({
|
|
60
|
+
path: "emails",
|
|
68
61
|
method: "POST",
|
|
69
|
-
headers: {
|
|
70
|
-
|
|
71
|
-
"content-type": "application/json"
|
|
72
|
-
},
|
|
73
|
-
body: JSON.stringify({
|
|
62
|
+
headers: { authorization: `Bearer ${requireApiKey(ctx, SERVICE)}` },
|
|
63
|
+
json: {
|
|
74
64
|
from: input.from,
|
|
75
65
|
to: input.to,
|
|
76
66
|
subject: input.subject,
|
|
77
67
|
...input.html === void 0 ? {} : { html: input.html },
|
|
78
68
|
...input.text === void 0 ? {} : { text: input.text }
|
|
79
|
-
}
|
|
69
|
+
},
|
|
70
|
+
invalidJson: "text",
|
|
71
|
+
mapError: ({ data: payload, status }) => resendError(status, payload)
|
|
80
72
|
});
|
|
81
|
-
const
|
|
82
|
-
if (!response.ok) throw resendError(response.status, payload);
|
|
83
|
-
const emailId = text(payload.id);
|
|
73
|
+
const emailId = trimmedText(payloadOf(data).id);
|
|
84
74
|
if (emailId === void 0) {
|
|
85
75
|
throw new TBError("unavailable", "Resend \u7684\u6210\u529F\u54CD\u5E94\u91CC\u6CA1\u6709 email id", { retryable: true });
|
|
86
76
|
}
|
|
@@ -1,69 +1,62 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createProviderHttpClient
|
|
3
|
+
} from "./chunk-VLOIDU5U.js";
|
|
4
|
+
import {
|
|
5
|
+
asJsonObject,
|
|
6
|
+
compactDefined,
|
|
7
|
+
trimmedText
|
|
8
|
+
} from "./chunk-JXHMDBAY.js";
|
|
1
9
|
import {
|
|
2
10
|
createProviderPlugin,
|
|
3
11
|
requireApiKey,
|
|
4
12
|
upstreamError
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import
|
|
7
|
-
guardedFetch
|
|
8
|
-
} from "./chunk-2O27H4Y2.js";
|
|
9
|
-
import "./chunk-GKX72JMJ.js";
|
|
13
|
+
} from "./chunk-B4P6YZFS.js";
|
|
14
|
+
import "./chunk-SWBNHIO4.js";
|
|
10
15
|
import {
|
|
11
16
|
external_exports
|
|
12
|
-
} from "./chunk-
|
|
13
|
-
import "./chunk-
|
|
17
|
+
} from "./chunk-OKRZPQ3R.js";
|
|
18
|
+
import "./chunk-U67V476Y.js";
|
|
14
19
|
|
|
15
20
|
// ../plugins/src/rootly/api.ts
|
|
16
21
|
var SERVICE = "rootly";
|
|
17
22
|
var API_BASE = "https://api.rootly.com/v1";
|
|
18
23
|
var JSON_API_CONTENT_TYPE = "application/vnd.api+json";
|
|
19
|
-
|
|
20
|
-
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
|
|
21
|
-
}
|
|
22
|
-
function text(value) {
|
|
23
|
-
if (typeof value !== "string") return void 0;
|
|
24
|
-
const trimmed = value.trim();
|
|
25
|
-
return trimmed === "" ? void 0 : trimmed;
|
|
26
|
-
}
|
|
24
|
+
var http = createProviderHttpClient({ baseUrl: `${API_BASE}/`, service: SERVICE });
|
|
27
25
|
function requireRecord(value, label) {
|
|
28
|
-
const record =
|
|
26
|
+
const record = asJsonObject(value);
|
|
29
27
|
if (record === void 0) throw upstreamError(502, `${label} was not an object`);
|
|
30
28
|
return record;
|
|
31
29
|
}
|
|
32
|
-
async function readPayload(response) {
|
|
33
|
-
const body = await response.text();
|
|
34
|
-
if (body.trim() === "") return {};
|
|
35
|
-
try {
|
|
36
|
-
return JSON.parse(body);
|
|
37
|
-
} catch {
|
|
38
|
-
if (!response.ok) return { errors: [{ detail: body }] };
|
|
39
|
-
throw upstreamError(502, "Rootly returned invalid JSON");
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
30
|
function errorMessage(payload, status) {
|
|
43
|
-
const object =
|
|
31
|
+
const object = asJsonObject(payload);
|
|
44
32
|
const errors = Array.isArray(object?.errors) ? object.errors : [];
|
|
45
|
-
const first =
|
|
46
|
-
return
|
|
33
|
+
const first = asJsonObject(errors[0]);
|
|
34
|
+
return trimmedText(first?.detail) ?? trimmedText(first?.title) ?? `Rootly request failed with ${status}`;
|
|
47
35
|
}
|
|
48
36
|
async function requestJson(ctx, path, query) {
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
37
|
+
const response = await http.request({
|
|
38
|
+
path,
|
|
39
|
+
query: Object.entries(query),
|
|
52
40
|
headers: {
|
|
53
41
|
"accept": JSON_API_CONTENT_TYPE,
|
|
54
42
|
"authorization": `Bearer ${requireApiKey(ctx, SERVICE)}`,
|
|
55
43
|
"content-type": JSON_API_CONTENT_TYPE
|
|
56
|
-
}
|
|
44
|
+
},
|
|
45
|
+
invalidJson: "text",
|
|
46
|
+
mapError: ({ bodyKind, data, status }) => upstreamError(
|
|
47
|
+
status,
|
|
48
|
+
errorMessage(bodyKind === "json" ? data : { errors: [{ detail: data }] }, status)
|
|
49
|
+
)
|
|
57
50
|
});
|
|
58
|
-
|
|
59
|
-
if (
|
|
60
|
-
return
|
|
51
|
+
if (response.bodyKind === "empty") return {};
|
|
52
|
+
if (response.bodyKind !== "json") throw upstreamError(502, "Rootly returned invalid JSON");
|
|
53
|
+
return response.data;
|
|
61
54
|
}
|
|
62
55
|
function readResource(value, label) {
|
|
63
56
|
const object = requireRecord(value, label);
|
|
64
57
|
const data = object.data === void 0 ? object : requireRecord(object.data, `${label} data`);
|
|
65
|
-
const id =
|
|
66
|
-
const type =
|
|
58
|
+
const id = trimmedText(data.id);
|
|
59
|
+
const type = trimmedText(data.type);
|
|
67
60
|
if (id === void 0 || type === void 0) {
|
|
68
61
|
throw upstreamError(502, `${label} did not include JSON:API id and type`);
|
|
69
62
|
}
|
|
@@ -71,15 +64,15 @@ function readResource(value, label) {
|
|
|
71
64
|
...data,
|
|
72
65
|
id,
|
|
73
66
|
type,
|
|
74
|
-
attributes:
|
|
75
|
-
relationships:
|
|
67
|
+
attributes: asJsonObject(data.attributes) ?? {},
|
|
68
|
+
relationships: asJsonObject(data.relationships) ?? {}
|
|
76
69
|
};
|
|
77
70
|
}
|
|
78
71
|
function readSidecars(payload) {
|
|
79
72
|
const object = requireRecord(payload, "Rootly response");
|
|
80
73
|
const included = Array.isArray(object.included) ? object.included : void 0;
|
|
81
|
-
const links =
|
|
82
|
-
const meta =
|
|
74
|
+
const links = asJsonObject(object.links);
|
|
75
|
+
const meta = asJsonObject(object.meta);
|
|
83
76
|
return {
|
|
84
77
|
...included === void 0 ? {} : { included },
|
|
85
78
|
...links === void 0 ? {} : { links },
|
|
@@ -102,69 +95,64 @@ async function getList(ctx, path, query) {
|
|
|
102
95
|
raw: payload
|
|
103
96
|
};
|
|
104
97
|
}
|
|
105
|
-
function compact(input) {
|
|
106
|
-
return Object.fromEntries(
|
|
107
|
-
Object.entries(input).filter((entry) => entry[1] !== void 0)
|
|
108
|
-
);
|
|
109
|
-
}
|
|
110
98
|
function includeQuery(include) {
|
|
111
99
|
return { include: include === void 0 || include.length === 0 ? void 0 : include.join(",") };
|
|
112
100
|
}
|
|
113
101
|
function pageQuery(input, options = {}) {
|
|
114
102
|
return {
|
|
115
|
-
...options.cursor === true ? { "page[after]":
|
|
103
|
+
...options.cursor === true ? { "page[after]": trimmedText(input.pageAfter) } : {},
|
|
116
104
|
"page[number]": input.pageNumber === void 0 ? void 0 : String(input.pageNumber),
|
|
117
105
|
"page[size]": input.pageSize === void 0 ? void 0 : String(input.pageSize)
|
|
118
106
|
};
|
|
119
107
|
}
|
|
120
108
|
function configurationQuery(input, options = {}) {
|
|
121
|
-
return
|
|
109
|
+
return compactDefined({
|
|
122
110
|
...includeQuery(input.include),
|
|
123
111
|
...pageQuery(input),
|
|
124
|
-
"filter[search]":
|
|
125
|
-
"filter[name]":
|
|
126
|
-
"filter[slug]":
|
|
127
|
-
"filter[external_id]":
|
|
128
|
-
...options.includeColor === true ? { "filter[color]":
|
|
112
|
+
"filter[search]": trimmedText(input.search),
|
|
113
|
+
"filter[name]": trimmedText(input.name),
|
|
114
|
+
"filter[slug]": trimmedText(input.slug),
|
|
115
|
+
"filter[external_id]": trimmedText(input.externalId),
|
|
116
|
+
...options.includeColor === true ? { "filter[color]": trimmedText(input.color) } : {},
|
|
129
117
|
"filter[alert_broadcast_enabled]": input.alertBroadcastEnabled === void 0 ? void 0 : String(input.alertBroadcastEnabled),
|
|
130
118
|
"filter[incident_broadcast_enabled]": input.incidentBroadcastEnabled === void 0 ? void 0 : String(input.incidentBroadcastEnabled),
|
|
131
|
-
"filter[created_at][gt]":
|
|
132
|
-
"filter[created_at][gte]":
|
|
133
|
-
"filter[created_at][lt]":
|
|
134
|
-
"filter[created_at][lte]":
|
|
135
|
-
"sort":
|
|
119
|
+
"filter[created_at][gt]": trimmedText(input.createdAtGt),
|
|
120
|
+
"filter[created_at][gte]": trimmedText(input.createdAtGte),
|
|
121
|
+
"filter[created_at][lt]": trimmedText(input.createdAtLt),
|
|
122
|
+
"filter[created_at][lte]": trimmedText(input.createdAtLte),
|
|
123
|
+
"sort": trimmedText(input.sort)
|
|
136
124
|
});
|
|
137
125
|
}
|
|
138
126
|
function getCurrentUser(_input, ctx) {
|
|
139
127
|
return getSingleResource(ctx, "/users/me", {});
|
|
140
128
|
}
|
|
141
129
|
function listIncidents(input, ctx) {
|
|
142
|
-
return getList(ctx, "/incidents",
|
|
130
|
+
return getList(ctx, "/incidents", compactDefined({
|
|
143
131
|
...pageQuery(input, { cursor: true }),
|
|
144
|
-
"filter[search]":
|
|
145
|
-
"filter[kind]":
|
|
146
|
-
"filter[status]":
|
|
132
|
+
"filter[search]": trimmedText(input.search),
|
|
133
|
+
"filter[kind]": trimmedText(input.kind),
|
|
134
|
+
"filter[status]": trimmedText(input.status),
|
|
147
135
|
"filter[private]": input.private === void 0 ? void 0 : String(input.private),
|
|
148
136
|
"filter[user_id]": input.userId === void 0 ? void 0 : String(input.userId),
|
|
149
|
-
"filter[severity]":
|
|
150
|
-
"filter[severity_id]":
|
|
151
|
-
"filter[labels]":
|
|
152
|
-
"filter[service_ids]":
|
|
153
|
-
"filter[service_names]":
|
|
154
|
-
"filter[team_ids]":
|
|
155
|
-
"filter[team_names]":
|
|
156
|
-
"filter[created_at][gt]":
|
|
157
|
-
"filter[created_at][gte]":
|
|
158
|
-
"filter[created_at][lt]":
|
|
159
|
-
"filter[created_at][lte]":
|
|
160
|
-
"sort":
|
|
137
|
+
"filter[severity]": trimmedText(input.severity),
|
|
138
|
+
"filter[severity_id]": trimmedText(input.severityId),
|
|
139
|
+
"filter[labels]": trimmedText(input.labels),
|
|
140
|
+
"filter[service_ids]": trimmedText(input.serviceIds),
|
|
141
|
+
"filter[service_names]": trimmedText(input.serviceNames),
|
|
142
|
+
"filter[team_ids]": trimmedText(input.teamIds),
|
|
143
|
+
"filter[team_names]": trimmedText(input.teamNames),
|
|
144
|
+
"filter[created_at][gt]": trimmedText(input.createdAtGt),
|
|
145
|
+
"filter[created_at][gte]": trimmedText(input.createdAtGte),
|
|
146
|
+
"filter[created_at][lt]": trimmedText(input.createdAtLt),
|
|
147
|
+
"filter[created_at][lte]": trimmedText(input.createdAtLte),
|
|
148
|
+
"sort": trimmedText(input.sort)
|
|
161
149
|
}));
|
|
162
150
|
}
|
|
163
151
|
function getIncident(input, ctx) {
|
|
164
152
|
return getSingleResource(
|
|
165
153
|
ctx,
|
|
166
154
|
`/incidents/${encodeURIComponent(input.id)}`,
|
|
167
|
-
|
|
155
|
+
compactDefined(includeQuery(input.include))
|
|
168
156
|
);
|
|
169
157
|
}
|
|
170
158
|
function listServices(input, ctx) {
|