@tool-bridge/server 0.1.1 → 0.3.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-V6446SVY.js +792 -0
- package/dist/alt_text_generator_ai-HV7JZPDT.js +72 -0
- package/dist/amap-TTTVB6WS.js +755 -0
- package/dist/anthropic-JH3RA363.js +224 -0
- package/dist/apify-ETNN7ITU.js +262 -0
- package/dist/brave_search-3DDR2MMB.js +322 -0
- package/dist/chunk-CSJEZHQO.js +252 -0
- package/dist/chunk-JLTYA2B3.js +20121 -0
- package/dist/chunk-K7FVSFUX.js +333 -0
- package/dist/{chunk-MQEYFCJB.js → chunk-KGYJEEBI.js} +2770 -21574
- package/dist/circleci-MX3TX3HC.js +409 -0
- package/dist/clerk-MRPORVF4.js +1036 -0
- package/dist/cloudflare_dns-OWP7DD7L.js +605 -0
- package/dist/cohere-GPECP66S.js +197 -0
- package/dist/confluence-BN7LZ6BC.js +436 -0
- package/dist/convertapi-SBEOFOFQ.js +161 -0
- package/dist/currencyapi-P2YY7Y7P.js +306 -0
- package/dist/deepseek-MWB3NYIN.js +205 -0
- package/dist/docker_hub-3JSCIGQ3.js +946 -0
- package/dist/dropbox-RFIBDAXO.js +1308 -0
- package/dist/dub-YVP57ELQ.js +706 -0
- package/dist/e2b-NFSUHTZR.js +305 -0
- package/dist/exa-KTDY6IV3.js +360 -0
- package/dist/fal_ai-OCUENLNQ.js +405 -0
- package/dist/feishu-5CWBQ7E5.js +225 -0
- package/dist/feishu_custom_bot-ZJR22OK6.js +240 -0
- package/dist/figma-YULGANSA.js +798 -0
- package/dist/firehydrant-2V6YSYAP.js +573 -0
- package/dist/fixer-LTCDB3CJ.js +171 -0
- package/dist/fly-IXPKMAML.js +478 -0
- package/dist/front-KRFB4M5X.js +379 -0
- package/dist/geocodio-VVURKYHQ.js +236 -0
- package/dist/ghost-6J2RIOUB.js +341 -0
- package/dist/github-5Z6KQRYH.js +5410 -0
- package/dist/gmail-KU4NZ7VA.js +1894 -0
- package/dist/googlecalendar-X44DFFXG.js +2539 -0
- package/dist/googledocs-WSGLPKSF.js +1322 -0
- package/dist/grafana-4PKSSDXY.js +817 -0
- package/dist/graphhopper-DF65ZNGK.js +336 -0
- package/dist/index.d.ts +181 -2
- package/dist/index.js +2 -1
- package/dist/ip2proxy-UCAQ5P2J.js +118 -0
- package/dist/ipgeolocation_io-UX6FCA2S.js +333 -0
- package/dist/ipqualityscore-MKTRXIZJ.js +287 -0
- package/dist/jina_ai-MRHPCSV5.js +119 -0
- package/dist/jira-EG7ZPOIW.js +627 -0
- package/dist/langsmith-FNO3RCOZ.js +597 -0
- package/dist/lemlist-SN6BJHSG.js +298 -0
- package/dist/linear-H3VU4PSD.js +2163 -0
- package/dist/logsnag-OY2JJT2H.js +167 -0
- package/dist/main.js +246 -2
- package/dist/mattermost-C5SQ7PGD.js +320 -0
- package/dist/mem0-LMLE5BFC.js +567 -0
- package/dist/memos-UWFAMBZC.js +781 -0
- package/dist/metabase-SRYDSDJ6.js +365 -0
- package/dist/mistral_ai-YNIJ7VDM.js +1195 -0
- package/dist/mother_duck-CPGOFEXE.js +322 -0
- package/dist/ngrok-CDJFBSOM.js +375 -0
- package/dist/notes-DIVFH3P3.js +109 -0
- package/dist/notion-HGDKS4HK.js +945 -0
- package/dist/open_exchange_rates-COHHYJDD.js +216 -0
- package/dist/openai-4TRT66GW.js +795 -0
- package/dist/opengraph_io-YKVW4PXI.js +377 -0
- package/dist/openrouter-6CV7B7V5.js +444 -0
- package/dist/outline-YWDUK5F7.js +604 -0
- package/dist/paddle-MEU7HWDZ.js +464 -0
- package/dist/perplexity-MRQUDBIC.js +238 -0
- package/dist/pinecone-JI7X2TAF.js +599 -0
- package/dist/pipedrive-6JQPAW23.js +453 -0
- package/dist/polar-7BF56CMC.js +400 -0
- package/dist/posthog-YPU5ADEN.js +3462 -0
- package/dist/postmark-BEU5OFKU.js +441 -0
- package/dist/prerender-UT5GOOZH.js +180 -0
- package/dist/pubmed-3SGOE24Q.js +1052 -0
- package/dist/railway-CEK4GLRQ.js +452 -0
- package/dist/readwise-DXQUQU67.js +482 -0
- package/dist/render-7TGAU5AW.js +473 -0
- package/dist/replicate-VICFSQ5A.js +347 -0
- package/dist/resend-3E76WK3O.js +100 -0
- package/dist/rootly-36GY46BY.js +345 -0
- package/dist/scrapfly-VDVUYAHX.js +289 -0
- package/dist/scrapingbee-3KTPMAVY.js +247 -0
- package/dist/screenshot_fyi-LKG62C3J.js +116 -0
- package/dist/semantic_scholar-4WREECYO.js +626 -0
- package/dist/sentry-HUQTGXOV.js +1139 -0
- package/dist/shodan-SGRKU4KS.js +303 -0
- package/dist/shopify-YCZ4L5HT.js +620 -0
- package/dist/stripe-OEBKMELB.js +583 -0
- package/dist/supabase-I3DBY7L4.js +937 -0
- package/dist/tavily-B2YHCNRD.js +349 -0
- package/dist/telegram-2VYJELZX.js +1773 -0
- package/dist/telnyx-HHXD3CXL.js +237 -0
- package/dist/todoist-PHFDEEIS.js +672 -0
- package/dist/trello-WUSAK6YN.js +1091 -0
- package/dist/turso-FW56U2B3.js +432 -0
- package/dist/twilio-M5JI7XHA.js +321 -0
- package/dist/umami-HAYODRC4.js +411 -0
- package/dist/unsplash-EDPTNEHJ.js +364 -0
- package/dist/upstash_redis-GC2CLIWD.js +299 -0
- package/dist/uptimerobot-XMSNYLIT.js +481 -0
- package/dist/v2ex-KU4ECD65.js +672 -0
- package/dist/vercel-THPCEFHW.js +1096 -0
- package/dist/wolfram_alpha_api-WHHTH4GU.js +212 -0
- package/dist/wordpress-O6TQEQNF.js +822 -0
- package/dist/workos-A3VHHWI3.js +681 -0
- package/dist/zhihu-BJAI64YJ.js +273 -0
- package/package.json +5 -4
|
@@ -0,0 +1,405 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createProviderPlugin,
|
|
3
|
+
guardedFetch,
|
|
4
|
+
requireApiKey,
|
|
5
|
+
upstreamError
|
|
6
|
+
} from "./chunk-CSJEZHQO.js";
|
|
7
|
+
import "./chunk-K7FVSFUX.js";
|
|
8
|
+
import {
|
|
9
|
+
TBError,
|
|
10
|
+
external_exports
|
|
11
|
+
} from "./chunk-JLTYA2B3.js";
|
|
12
|
+
import "./chunk-MLKGABMK.js";
|
|
13
|
+
|
|
14
|
+
// ../plugins/src/fal_ai/api.ts
|
|
15
|
+
var SERVICE = "fal_ai";
|
|
16
|
+
var PLATFORM_BASE = "https://api.fal.ai";
|
|
17
|
+
var QUEUE_BASE = "https://queue.fal.run";
|
|
18
|
+
function text(value) {
|
|
19
|
+
if (typeof value !== "string") return void 0;
|
|
20
|
+
const trimmed = value.trim();
|
|
21
|
+
return trimmed === "" ? void 0 : trimmed;
|
|
22
|
+
}
|
|
23
|
+
function str(value) {
|
|
24
|
+
return typeof value === "string" ? value : void 0;
|
|
25
|
+
}
|
|
26
|
+
function record(value) {
|
|
27
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
|
|
28
|
+
}
|
|
29
|
+
function compact(input) {
|
|
30
|
+
return Object.fromEntries(Object.entries(input).filter(([, value]) => value !== void 0));
|
|
31
|
+
}
|
|
32
|
+
function objectArray(value) {
|
|
33
|
+
if (!Array.isArray(value)) return [];
|
|
34
|
+
return value.map((item) => record(item)).filter((item) => item !== void 0);
|
|
35
|
+
}
|
|
36
|
+
function stringOrArray(value) {
|
|
37
|
+
if (value === void 0 || typeof value === "string") return value;
|
|
38
|
+
return value.map((item) => String(item));
|
|
39
|
+
}
|
|
40
|
+
function queueRequestPath(modelId, requestId, suffix) {
|
|
41
|
+
const model = modelId.split("/").map((segment) => encodeURIComponent(segment)).join("/");
|
|
42
|
+
const base = `/${model}/requests/${encodeURIComponent(requestId)}`;
|
|
43
|
+
return suffix === void 0 ? base : `${base}/${suffix}`;
|
|
44
|
+
}
|
|
45
|
+
function buildUrl(base, path, query) {
|
|
46
|
+
const url = new URL(`${base}${path}`);
|
|
47
|
+
for (const [key, value] of Object.entries(query ?? {})) {
|
|
48
|
+
if (value === void 0) continue;
|
|
49
|
+
if (Array.isArray(value)) {
|
|
50
|
+
for (const item of value) url.searchParams.append(key, item);
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
url.searchParams.set(key, String(value));
|
|
54
|
+
}
|
|
55
|
+
return url.toString();
|
|
56
|
+
}
|
|
57
|
+
function errorMessage(payload, status) {
|
|
58
|
+
const body = record(payload);
|
|
59
|
+
if (body !== void 0) {
|
|
60
|
+
const detail = typeof body.detail === "string" ? body.detail : record(body.detail) !== void 0 || Array.isArray(body.detail) ? JSON.stringify(body.detail) : void 0;
|
|
61
|
+
const message = text(body.message) ?? text(body.error) ?? detail;
|
|
62
|
+
if (message !== void 0 && message !== "") return message;
|
|
63
|
+
}
|
|
64
|
+
return `fal.ai \u8FD4\u56DE HTTP ${status}`;
|
|
65
|
+
}
|
|
66
|
+
async function request(ctx, input) {
|
|
67
|
+
const response = await guardedFetch(buildUrl(input.base, input.path, input.query), {
|
|
68
|
+
method: input.method ?? (input.body === void 0 ? "GET" : "POST"),
|
|
69
|
+
headers: {
|
|
70
|
+
"authorization": `Key ${requireApiKey(ctx, SERVICE)}`,
|
|
71
|
+
"content-type": "application/json",
|
|
72
|
+
...input.headers
|
|
73
|
+
},
|
|
74
|
+
body: input.body === void 0 ? void 0 : JSON.stringify(input.body)
|
|
75
|
+
});
|
|
76
|
+
const body = await response.text();
|
|
77
|
+
let payload = null;
|
|
78
|
+
if (body !== "") {
|
|
79
|
+
try {
|
|
80
|
+
payload = JSON.parse(body);
|
|
81
|
+
} catch {
|
|
82
|
+
if (response.ok) {
|
|
83
|
+
throw new TBError("unavailable", "fal.ai \u8FD4\u56DE\u4E86\u975E JSON \u54CD\u5E94", { retryable: true });
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
if (!response.ok) throw upstreamError(response.status, errorMessage(payload, response.status));
|
|
88
|
+
return payload;
|
|
89
|
+
}
|
|
90
|
+
function requireRecord(value) {
|
|
91
|
+
const result = record(value);
|
|
92
|
+
if (result === void 0) throw new TBError("unavailable", "fal.ai \u54CD\u5E94\u4E0D\u662F\u5BF9\u8C61", { retryable: true });
|
|
93
|
+
return result;
|
|
94
|
+
}
|
|
95
|
+
function queueLogs(value) {
|
|
96
|
+
return objectArray(value).map((item) => ({
|
|
97
|
+
message: typeof item.message === "string" ? item.message : "",
|
|
98
|
+
level: typeof item.level === "string" ? item.level : "",
|
|
99
|
+
source: typeof item.source === "string" ? item.source : "",
|
|
100
|
+
timestamp: typeof item.timestamp === "string" ? item.timestamp : ""
|
|
101
|
+
}));
|
|
102
|
+
}
|
|
103
|
+
function page(payload, key) {
|
|
104
|
+
const result = requireRecord(payload);
|
|
105
|
+
return {
|
|
106
|
+
[key]: objectArray(result[key]),
|
|
107
|
+
hasMore: result.has_more === true,
|
|
108
|
+
nextCursor: str(result.next_cursor) ?? null
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
async function getModels(input, ctx) {
|
|
112
|
+
const payload = await request(ctx, {
|
|
113
|
+
base: PLATFORM_BASE,
|
|
114
|
+
path: "/v1/models",
|
|
115
|
+
query: compact({
|
|
116
|
+
q: text(input.q),
|
|
117
|
+
limit: input.limit,
|
|
118
|
+
cursor: text(input.cursor),
|
|
119
|
+
expand: stringOrArray(input.expand),
|
|
120
|
+
status: text(input.status),
|
|
121
|
+
category: text(input.category),
|
|
122
|
+
endpoint_id: stringOrArray(input.endpointId)
|
|
123
|
+
})
|
|
124
|
+
});
|
|
125
|
+
return page(payload, "models");
|
|
126
|
+
}
|
|
127
|
+
async function getPricing(input, ctx) {
|
|
128
|
+
const payload = await request(ctx, {
|
|
129
|
+
base: PLATFORM_BASE,
|
|
130
|
+
path: "/v1/models/pricing",
|
|
131
|
+
query: { endpoint_id: stringOrArray(input.endpointId) }
|
|
132
|
+
});
|
|
133
|
+
return page(payload, "prices");
|
|
134
|
+
}
|
|
135
|
+
async function estimatePricing(input, ctx) {
|
|
136
|
+
const payload = requireRecord(await request(ctx, {
|
|
137
|
+
base: PLATFORM_BASE,
|
|
138
|
+
method: "POST",
|
|
139
|
+
path: "/v1/models/pricing/estimate",
|
|
140
|
+
body: {
|
|
141
|
+
estimate_type: input.estimateType,
|
|
142
|
+
endpoints: input.endpoints
|
|
143
|
+
}
|
|
144
|
+
}));
|
|
145
|
+
return {
|
|
146
|
+
estimateType: str(payload.estimate_type) ?? "",
|
|
147
|
+
totalCost: typeof payload.total_cost === "number" ? payload.total_cost : 0,
|
|
148
|
+
currency: str(payload.currency) ?? ""
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
async function getJwks(_input, ctx) {
|
|
152
|
+
const payload = requireRecord(await request(ctx, {
|
|
153
|
+
base: PLATFORM_BASE,
|
|
154
|
+
path: "/.well-known/jwks.json"
|
|
155
|
+
}));
|
|
156
|
+
return { keys: objectArray(payload.keys) };
|
|
157
|
+
}
|
|
158
|
+
async function queueGetStatus(input, ctx) {
|
|
159
|
+
const payload = requireRecord(await request(ctx, {
|
|
160
|
+
base: QUEUE_BASE,
|
|
161
|
+
path: queueRequestPath(input.modelId, input.requestId, "status"),
|
|
162
|
+
// logs: 0 是显式值,要发;只有"没给"才不发。
|
|
163
|
+
query: compact({ logs: input.logs })
|
|
164
|
+
}));
|
|
165
|
+
return {
|
|
166
|
+
status: str(payload.status) ?? "",
|
|
167
|
+
responseUrl: str(payload.response_url) ?? null,
|
|
168
|
+
queuePosition: typeof payload.queue_position === "number" ? payload.queue_position : null,
|
|
169
|
+
logs: queueLogs(payload.logs)
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
function parseSseEvents(payload) {
|
|
173
|
+
return payload.split(/\r?\n\r?\n/).flatMap((chunk) => {
|
|
174
|
+
const lines = chunk.split(/\r?\n/).map((line) => line.trimEnd()).filter((line) => line.length > 0);
|
|
175
|
+
if (lines.length === 0) return [];
|
|
176
|
+
let event;
|
|
177
|
+
const data = [];
|
|
178
|
+
for (const line of lines) {
|
|
179
|
+
if (line.startsWith(":")) continue;
|
|
180
|
+
if (line.startsWith("event:")) {
|
|
181
|
+
event = line.slice("event:".length).trim();
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
if (line.startsWith("data:")) data.push(line.slice("data:".length).trim());
|
|
185
|
+
}
|
|
186
|
+
return [{ event, data: data.join("\n") }];
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
async function queueGetStatusStream(input, ctx) {
|
|
190
|
+
const response = await guardedFetch(
|
|
191
|
+
buildUrl(
|
|
192
|
+
QUEUE_BASE,
|
|
193
|
+
queueRequestPath(input.modelId, input.requestId, "status/stream"),
|
|
194
|
+
compact({ logs: input.logs })
|
|
195
|
+
),
|
|
196
|
+
{
|
|
197
|
+
method: "GET",
|
|
198
|
+
headers: {
|
|
199
|
+
"accept": "text/event-stream",
|
|
200
|
+
"authorization": `Key ${requireApiKey(ctx, SERVICE)}`,
|
|
201
|
+
"content-type": "application/json"
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
);
|
|
205
|
+
const body = await response.text();
|
|
206
|
+
if (!response.ok) {
|
|
207
|
+
let payload = null;
|
|
208
|
+
try {
|
|
209
|
+
payload = JSON.parse(body);
|
|
210
|
+
} catch {
|
|
211
|
+
}
|
|
212
|
+
throw upstreamError(response.status, errorMessage(payload, response.status));
|
|
213
|
+
}
|
|
214
|
+
const updates = parseSseEvents(body).flatMap((event) => {
|
|
215
|
+
if (event.data === "") return [];
|
|
216
|
+
try {
|
|
217
|
+
return [requireRecord(JSON.parse(event.data))];
|
|
218
|
+
} catch {
|
|
219
|
+
return [{ event: event.event ?? "message", data: event.data }];
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
const last = updates.at(-1);
|
|
223
|
+
return {
|
|
224
|
+
updates,
|
|
225
|
+
finalStatus: last === void 0 ? null : str(last.status) ?? null,
|
|
226
|
+
responseUrl: last === void 0 ? null : str(last.response_url) ?? null
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
async function getQueueRequestResult(input, ctx) {
|
|
230
|
+
const payload = requireRecord(await request(ctx, {
|
|
231
|
+
base: QUEUE_BASE,
|
|
232
|
+
path: queueRequestPath(input.modelId, input.requestId)
|
|
233
|
+
}));
|
|
234
|
+
return {
|
|
235
|
+
status: str(payload.status) ?? "",
|
|
236
|
+
logs: queueLogs(payload.logs),
|
|
237
|
+
response: record(payload.response) ?? {}
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
async function cancelQueueRequest(input, ctx) {
|
|
241
|
+
const payload = requireRecord(await request(ctx, {
|
|
242
|
+
base: QUEUE_BASE,
|
|
243
|
+
method: "PUT",
|
|
244
|
+
path: queueRequestPath(input.modelId, input.requestId, "cancel")
|
|
245
|
+
}));
|
|
246
|
+
return { status: str(payload.status) ?? "" };
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// ../plugins/src/fal_ai/schema.ts
|
|
250
|
+
var getModelsInput = external_exports.strictObject({
|
|
251
|
+
q: external_exports.string().describe("The free-text search query for model discovery.").optional(),
|
|
252
|
+
limit: external_exports.int().min(1).describe("The maximum number of models to return.").optional(),
|
|
253
|
+
cursor: external_exports.string().describe("The pagination cursor from a previous response.").optional(),
|
|
254
|
+
expand: external_exports.union([external_exports.string().describe("A single string value."), external_exports.array(external_exports.string().describe("A string value in the list.")).describe("The list of strings.")]).describe("A single string or a list of strings.").optional(),
|
|
255
|
+
status: external_exports.enum(["active", "deprecated"]).describe("Filter models by active or deprecated status.").optional(),
|
|
256
|
+
category: external_exports.string().describe("Filter models by category name.").optional(),
|
|
257
|
+
endpointId: external_exports.union([external_exports.string().describe("A single string value."), external_exports.array(external_exports.string().describe("A string value in the list.")).describe("The list of strings.")]).describe("A single string or a list of strings.").optional()
|
|
258
|
+
}).describe("The input payload for this action.");
|
|
259
|
+
var getModelsOutput = external_exports.strictObject({
|
|
260
|
+
models: external_exports.array(external_exports.record(external_exports.string(), external_exports.unknown().describe("A raw fal property value.")).describe("The raw fal object payload.")).describe("The list of raw fal objects."),
|
|
261
|
+
hasMore: external_exports.boolean().describe("Whether additional result pages are available."),
|
|
262
|
+
nextCursor: external_exports.string().describe("The pagination cursor for the next page of results.").nullable()
|
|
263
|
+
}).describe("The output payload for this action.");
|
|
264
|
+
var getPricingInput = external_exports.strictObject({
|
|
265
|
+
endpointId: external_exports.union([external_exports.string().describe("A single string value."), external_exports.array(external_exports.string().describe("A string value in the list.")).describe("The list of strings.")]).describe("A single string or a list of strings.")
|
|
266
|
+
}).describe("The input payload for this action.");
|
|
267
|
+
var getPricingOutput = external_exports.strictObject({
|
|
268
|
+
prices: external_exports.array(external_exports.record(external_exports.string(), external_exports.unknown().describe("A raw fal property value.")).describe("The raw fal object payload.")).describe("The list of raw fal objects."),
|
|
269
|
+
hasMore: external_exports.boolean().describe("Whether additional result pages are available."),
|
|
270
|
+
nextCursor: external_exports.string().describe("The pagination cursor for the next page of pricing results.").nullable()
|
|
271
|
+
}).describe("The output payload for this action.");
|
|
272
|
+
var estimatePricingInput = external_exports.strictObject({
|
|
273
|
+
estimateType: external_exports.enum(["historical_api_price", "unit_price"]).describe("The pricing estimation method to use."),
|
|
274
|
+
endpoints: external_exports.record(external_exports.string(), external_exports.unknown().describe("A raw fal property value.")).describe("The raw fal object payload.")
|
|
275
|
+
}).describe("The input payload for this action.");
|
|
276
|
+
var estimatePricingOutput = external_exports.strictObject({
|
|
277
|
+
estimateType: external_exports.string().describe("The estimation method that was applied."),
|
|
278
|
+
totalCost: external_exports.number().describe("The aggregate estimated cost across all endpoints."),
|
|
279
|
+
currency: external_exports.string().describe("The ISO 4217 currency code for the estimate.")
|
|
280
|
+
}).describe("The output payload for this action.");
|
|
281
|
+
var getJwksInput = external_exports.strictObject({}).describe("The input payload for this action.");
|
|
282
|
+
var getJwksOutput = external_exports.strictObject({
|
|
283
|
+
keys: external_exports.array(external_exports.record(external_exports.string(), external_exports.unknown().describe("A raw fal property value.")).describe("The raw fal object payload.")).describe("The list of raw fal objects.")
|
|
284
|
+
}).describe("The output payload for this action.");
|
|
285
|
+
var queueGetStatusInput = external_exports.strictObject({
|
|
286
|
+
modelId: external_exports.string().describe("The model identifier in namespace/name format."),
|
|
287
|
+
requestId: external_exports.string().describe("The queued request identifier."),
|
|
288
|
+
logs: external_exports.int().min(0).max(1).describe("Set to 1 to include logs in the response.").optional()
|
|
289
|
+
}).describe("The input payload for this action.");
|
|
290
|
+
var queueGetStatusOutput = external_exports.strictObject({
|
|
291
|
+
status: external_exports.string().describe("The current queue status."),
|
|
292
|
+
responseUrl: external_exports.string().describe("The URL for fetching the final queued response.").nullable().optional(),
|
|
293
|
+
queuePosition: external_exports.int().describe("The current queue position when the request is still queued.").nullable().optional(),
|
|
294
|
+
logs: external_exports.array(external_exports.strictObject({
|
|
295
|
+
message: external_exports.string().describe("The log message text.").optional(),
|
|
296
|
+
level: external_exports.string().describe("The log severity level.").optional(),
|
|
297
|
+
source: external_exports.string().describe("The log source identifier.").optional(),
|
|
298
|
+
timestamp: external_exports.string().describe("The log timestamp in ISO 8601 format.").optional()
|
|
299
|
+
}).describe("A queue log entry.")).describe("The queue processing logs.").optional()
|
|
300
|
+
}).describe("The output payload for this action.");
|
|
301
|
+
var queueGetStatusStreamInput = external_exports.strictObject({
|
|
302
|
+
modelId: external_exports.string().describe("The model identifier in namespace/name format."),
|
|
303
|
+
requestId: external_exports.string().describe("The queued request identifier."),
|
|
304
|
+
logs: external_exports.int().min(0).max(1).describe("Set to 1 to include logs inside streamed updates.").optional()
|
|
305
|
+
}).describe("The input payload for this action.");
|
|
306
|
+
var queueGetStatusStreamOutput = external_exports.strictObject({
|
|
307
|
+
updates: external_exports.array(external_exports.record(external_exports.string(), external_exports.unknown().describe("A raw fal property value.")).describe("The raw fal object payload.")).describe("The list of raw fal objects."),
|
|
308
|
+
finalStatus: external_exports.string().describe("The last status value seen in the stream.").nullable().optional(),
|
|
309
|
+
responseUrl: external_exports.string().describe("The final response URL seen in the stream, if present.").nullable().optional()
|
|
310
|
+
}).describe("The output payload for this action.");
|
|
311
|
+
var getQueueRequestResultInput = external_exports.strictObject({
|
|
312
|
+
modelId: external_exports.string().describe("The model identifier in namespace/name format."),
|
|
313
|
+
requestId: external_exports.string().describe("The queued request identifier.")
|
|
314
|
+
}).describe("The input payload for this action.");
|
|
315
|
+
var getQueueRequestResultOutput = external_exports.strictObject({
|
|
316
|
+
status: external_exports.string().describe("The final request status returned by the queue API."),
|
|
317
|
+
logs: external_exports.array(external_exports.strictObject({
|
|
318
|
+
message: external_exports.string().describe("The log message text.").optional(),
|
|
319
|
+
level: external_exports.string().describe("The log severity level.").optional(),
|
|
320
|
+
source: external_exports.string().describe("The log source identifier.").optional(),
|
|
321
|
+
timestamp: external_exports.string().describe("The log timestamp in ISO 8601 format.").optional()
|
|
322
|
+
}).describe("A queue log entry.")).describe("The logs captured for the queued request."),
|
|
323
|
+
response: external_exports.record(external_exports.string(), external_exports.unknown().describe("A raw fal property value.")).describe("The raw fal object payload.")
|
|
324
|
+
}).describe("The output payload for this action.");
|
|
325
|
+
var cancelQueueRequestInput = external_exports.strictObject({
|
|
326
|
+
modelId: external_exports.string().describe("The model identifier in namespace/name format."),
|
|
327
|
+
requestId: external_exports.string().describe("The queued request identifier.")
|
|
328
|
+
}).describe("The input payload for this action.");
|
|
329
|
+
var cancelQueueRequestOutput = external_exports.strictObject({
|
|
330
|
+
status: external_exports.string().describe("The cancellation result status.")
|
|
331
|
+
}).describe("The output payload for this action.");
|
|
332
|
+
var falAiActions = {
|
|
333
|
+
get_models: {
|
|
334
|
+
description: "Discover fal model endpoints with optional text search, status, category, pagination, endpoint filtering, and response expansion.",
|
|
335
|
+
effect: "read",
|
|
336
|
+
inputSchema: getModelsInput,
|
|
337
|
+
outputSchema: external_exports.toJSONSchema(getModelsOutput, { io: "output", unrepresentable: "any" })
|
|
338
|
+
},
|
|
339
|
+
get_pricing: {
|
|
340
|
+
description: "Retrieve unit pricing information for one or more fal model endpoints, including billing unit and currency.",
|
|
341
|
+
effect: "read",
|
|
342
|
+
inputSchema: getPricingInput,
|
|
343
|
+
outputSchema: external_exports.toJSONSchema(getPricingOutput, { io: "output", unrepresentable: "any" })
|
|
344
|
+
},
|
|
345
|
+
estimate_pricing: {
|
|
346
|
+
description: "Estimate total fal model cost using either historical API call quantities or expected billing-unit quantities.",
|
|
347
|
+
effect: "write",
|
|
348
|
+
inputSchema: estimatePricingInput,
|
|
349
|
+
outputSchema: external_exports.toJSONSchema(estimatePricingOutput, { io: "output", unrepresentable: "any" })
|
|
350
|
+
},
|
|
351
|
+
get_jwks: {
|
|
352
|
+
description: "Retrieve the fal JSON Web Key Set used for webhook signature verification.",
|
|
353
|
+
effect: "read",
|
|
354
|
+
inputSchema: getJwksInput,
|
|
355
|
+
outputSchema: external_exports.toJSONSchema(getJwksOutput, { io: "output", unrepresentable: "any" })
|
|
356
|
+
},
|
|
357
|
+
queue_get_status: {
|
|
358
|
+
description: "Check the status of a queued fal request, with optional log retrieval for in-progress or completed work.",
|
|
359
|
+
effect: "write",
|
|
360
|
+
inputSchema: queueGetStatusInput,
|
|
361
|
+
outputSchema: external_exports.toJSONSchema(queueGetStatusOutput, { io: "output", unrepresentable: "any" })
|
|
362
|
+
},
|
|
363
|
+
queue_get_status_stream: {
|
|
364
|
+
description: "Consume fal queue status updates as a streamed sequence of SSE events until the server closes the stream.",
|
|
365
|
+
effect: "write",
|
|
366
|
+
inputSchema: queueGetStatusStreamInput,
|
|
367
|
+
outputSchema: external_exports.toJSONSchema(queueGetStatusStreamOutput, { io: "output", unrepresentable: "any" })
|
|
368
|
+
},
|
|
369
|
+
get_queue_request_result: {
|
|
370
|
+
description: "Retrieve the stored final result payload for a completed fal queued request.",
|
|
371
|
+
effect: "read",
|
|
372
|
+
inputSchema: getQueueRequestResultInput,
|
|
373
|
+
outputSchema: external_exports.toJSONSchema(getQueueRequestResultOutput, { io: "output", unrepresentable: "any" })
|
|
374
|
+
},
|
|
375
|
+
cancel_queue_request: {
|
|
376
|
+
description: "Request cancellation of a queued or in-progress fal request by model ID and request ID.",
|
|
377
|
+
effect: "destructive",
|
|
378
|
+
inputSchema: cancelQueueRequestInput,
|
|
379
|
+
outputSchema: external_exports.toJSONSchema(cancelQueueRequestOutput, { io: "output", unrepresentable: "any" })
|
|
380
|
+
}
|
|
381
|
+
};
|
|
382
|
+
|
|
383
|
+
// ../plugins/src/fal_ai/index.ts
|
|
384
|
+
function createFalAiPlugin() {
|
|
385
|
+
return createProviderPlugin({
|
|
386
|
+
description: "fal.ai",
|
|
387
|
+
actions: falAiActions,
|
|
388
|
+
credentialProbe: "get_models",
|
|
389
|
+
handlers: {
|
|
390
|
+
get_models: getModels,
|
|
391
|
+
get_pricing: getPricing,
|
|
392
|
+
estimate_pricing: estimatePricing,
|
|
393
|
+
get_jwks: getJwks,
|
|
394
|
+
queue_get_status: queueGetStatus,
|
|
395
|
+
queue_get_status_stream: queueGetStatusStream,
|
|
396
|
+
get_queue_request_result: getQueueRequestResult,
|
|
397
|
+
cancel_queue_request: cancelQueueRequest
|
|
398
|
+
}
|
|
399
|
+
});
|
|
400
|
+
}
|
|
401
|
+
var fal_ai_default = createFalAiPlugin();
|
|
402
|
+
export {
|
|
403
|
+
createFalAiPlugin,
|
|
404
|
+
fal_ai_default as default
|
|
405
|
+
};
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createPlugin
|
|
3
|
+
} from "./chunk-K7FVSFUX.js";
|
|
4
|
+
import {
|
|
5
|
+
TBError,
|
|
6
|
+
isTBError,
|
|
7
|
+
normalizeUpstreamError
|
|
8
|
+
} from "./chunk-JLTYA2B3.js";
|
|
9
|
+
import "./chunk-MLKGABMK.js";
|
|
10
|
+
|
|
11
|
+
// ../plugins/src/feishu/feishuMcp.ts
|
|
12
|
+
import {
|
|
13
|
+
StreamableHTTPClientTransport,
|
|
14
|
+
StreamableHTTPError
|
|
15
|
+
} from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
16
|
+
import { CfWorkerJsonSchemaValidator } from "@modelcontextprotocol/sdk/validation/cfworker";
|
|
17
|
+
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
18
|
+
var DEFAULT_MCP_URL = "https://mcp.feishu.cn/mcp";
|
|
19
|
+
var sessions = /* @__PURE__ */ new Map();
|
|
20
|
+
var noStandaloneSseFetch = (input, init) => {
|
|
21
|
+
const method = init?.method ?? (input instanceof Request ? input.method : "GET");
|
|
22
|
+
if (String(method).toUpperCase() === "GET") {
|
|
23
|
+
return Promise.resolve(new Response(null, { status: 405, statusText: "Method Not Allowed" }));
|
|
24
|
+
}
|
|
25
|
+
return fetch(input, init);
|
|
26
|
+
};
|
|
27
|
+
function isSessionInvalid(err) {
|
|
28
|
+
return err instanceof StreamableHTTPError && (err.code === 404 || err.code === 400);
|
|
29
|
+
}
|
|
30
|
+
function isUnauthorized(err) {
|
|
31
|
+
return err instanceof StreamableHTTPError && err.code === 401;
|
|
32
|
+
}
|
|
33
|
+
async function withSession(cfg, fn) {
|
|
34
|
+
const makeTransport = (sessionId) => new StreamableHTTPClientTransport(new URL(cfg.url), {
|
|
35
|
+
fetch: noStandaloneSseFetch,
|
|
36
|
+
requestInit: {
|
|
37
|
+
headers: {
|
|
38
|
+
"X-Lark-MCP-TAT": cfg.tat,
|
|
39
|
+
"X-Lark-MCP-Allowed-Tools": cfg.allowedTools
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
...sessionId !== void 0 ? { sessionId } : {}
|
|
43
|
+
});
|
|
44
|
+
const makeClient = () => new Client(
|
|
45
|
+
{ name: "tb-plugin-feishu", version: "0.1.0" },
|
|
46
|
+
{ jsonSchemaValidator: new CfWorkerJsonSchemaValidator() }
|
|
47
|
+
);
|
|
48
|
+
const runFresh = async () => {
|
|
49
|
+
const transport = makeTransport(void 0);
|
|
50
|
+
const client = makeClient();
|
|
51
|
+
await client.connect(transport);
|
|
52
|
+
if (transport.sessionId !== void 0) {
|
|
53
|
+
sessions.set(cfg.appId, {
|
|
54
|
+
sessionId: transport.sessionId,
|
|
55
|
+
...transport.protocolVersion !== void 0 ? { protocolVersion: transport.protocolVersion } : {}
|
|
56
|
+
});
|
|
57
|
+
} else {
|
|
58
|
+
sessions.delete(cfg.appId);
|
|
59
|
+
}
|
|
60
|
+
return await fn(client);
|
|
61
|
+
};
|
|
62
|
+
const session = sessions.get(cfg.appId);
|
|
63
|
+
if (session !== void 0) {
|
|
64
|
+
const transport = makeTransport(session.sessionId);
|
|
65
|
+
const client = makeClient();
|
|
66
|
+
await client.connect(transport);
|
|
67
|
+
if (session.protocolVersion !== void 0) {
|
|
68
|
+
transport.setProtocolVersion(session.protocolVersion);
|
|
69
|
+
}
|
|
70
|
+
try {
|
|
71
|
+
return await fn(client);
|
|
72
|
+
} catch (err) {
|
|
73
|
+
if (!isSessionInvalid(err)) throw err;
|
|
74
|
+
sessions.delete(cfg.appId);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return await runFresh();
|
|
78
|
+
}
|
|
79
|
+
async function guard(fn) {
|
|
80
|
+
try {
|
|
81
|
+
return await fn();
|
|
82
|
+
} catch (err) {
|
|
83
|
+
if (isTBError(err) || isUnauthorized(err)) throw err;
|
|
84
|
+
if (err instanceof StreamableHTTPError && err.code !== void 0) {
|
|
85
|
+
throw normalizeUpstreamError({ kind: "http", status: err.code, message: err.message });
|
|
86
|
+
}
|
|
87
|
+
throw normalizeUpstreamError({
|
|
88
|
+
kind: "network",
|
|
89
|
+
message: err instanceof Error ? err.message : String(err)
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
async function listTools(cfg) {
|
|
94
|
+
return guard(async () => {
|
|
95
|
+
const res = await withSession(cfg, (c) => c.listTools());
|
|
96
|
+
if (res.tools.length === 0 && cfg.allowedTools.trim() === "") {
|
|
97
|
+
throw new TBError("unavailable", "FEISHU_ALLOWED_TOOLS \u4E3A\u7A7A:\u98DE\u4E66 MCP \u4E0D\u5BA3\u544A\u4EFB\u4F55\u5DE5\u5177", {
|
|
98
|
+
retryable: false
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
return res.tools;
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
async function callTool(cfg, name, args) {
|
|
105
|
+
return guard(async () => {
|
|
106
|
+
const res = await withSession(cfg, (c) => c.callTool({ name, arguments: args }));
|
|
107
|
+
return res;
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// ../plugins/src/feishu/tat.ts
|
|
112
|
+
var DEFAULT_AUTH_URL = "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal";
|
|
113
|
+
var REFRESH_MARGIN_MS = 5 * 6e4;
|
|
114
|
+
var cache = /* @__PURE__ */ new Map();
|
|
115
|
+
async function tenantAccessToken(cfg, force = false) {
|
|
116
|
+
const cached = cache.get(cfg.appId);
|
|
117
|
+
if (!force && cached !== void 0 && cached.expiresAtMs - Date.now() > REFRESH_MARGIN_MS) {
|
|
118
|
+
return cached.token;
|
|
119
|
+
}
|
|
120
|
+
let resp;
|
|
121
|
+
try {
|
|
122
|
+
resp = await fetch(cfg.authUrl ?? DEFAULT_AUTH_URL, {
|
|
123
|
+
method: "POST",
|
|
124
|
+
headers: { "content-type": "application/json; charset=utf-8" },
|
|
125
|
+
body: JSON.stringify({ app_id: cfg.appId, app_secret: cfg.appSecret })
|
|
126
|
+
});
|
|
127
|
+
} catch (err) {
|
|
128
|
+
throw new TBError(
|
|
129
|
+
"unavailable",
|
|
130
|
+
`\u98DE\u4E66 TAT \u6362\u53D1\u7F51\u7EDC\u5931\u8D25:${err instanceof Error ? err.message : String(err)}`,
|
|
131
|
+
{ retryable: true }
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
const body = await resp.json().catch(() => null);
|
|
135
|
+
if (!resp.ok || body === null || body.code !== 0 || typeof body.tenant_access_token !== "string") {
|
|
136
|
+
throw new TBError(
|
|
137
|
+
"unavailable",
|
|
138
|
+
`\u98DE\u4E66 TAT \u6362\u53D1\u5931\u8D25:HTTP ${resp.status} code=${body?.code ?? "?"} ${body?.msg ?? ""}`.trim(),
|
|
139
|
+
{ retryable: false }
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
const expireSec = typeof body.expire === "number" ? body.expire : 0;
|
|
143
|
+
cache.set(cfg.appId, {
|
|
144
|
+
token: body.tenant_access_token,
|
|
145
|
+
expiresAtMs: Date.now() + expireSec * 1e3
|
|
146
|
+
});
|
|
147
|
+
return body.tenant_access_token;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// ../plugins/src/feishu/index.ts
|
|
151
|
+
function credentialOf(ctx) {
|
|
152
|
+
const values = ctx.credentials;
|
|
153
|
+
if (values === void 0) {
|
|
154
|
+
throw new TBError(
|
|
155
|
+
"unavailable",
|
|
156
|
+
"\u7F3A\u4E0A\u6E38\u51ED\u8BC1:\u6302\u8F7D\u8282\u70B9\u987B\u914D\u7F6E authRef,\u51ED\u8BC1\u7528 `tb secret set <name> --field app_id=... --field app_secret=...` \u5199\u5165",
|
|
157
|
+
{ retryable: false }
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
return { app_id: values.app_id, app_secret: values.app_secret };
|
|
161
|
+
}
|
|
162
|
+
function toSpec(t) {
|
|
163
|
+
const spec = { name: t.name };
|
|
164
|
+
if (t.description !== void 0) spec.description = t.description;
|
|
165
|
+
if (t.inputSchema !== void 0) spec.inputSchema = t.inputSchema;
|
|
166
|
+
if (t.annotations?.readOnlyHint === true) spec.effect = "read";
|
|
167
|
+
else if (t.annotations?.destructiveHint === true) spec.effect = "destructive";
|
|
168
|
+
return spec;
|
|
169
|
+
}
|
|
170
|
+
async function mcpConfig(env, cred, forceTat = false) {
|
|
171
|
+
const tat = await tenantAccessToken(
|
|
172
|
+
{
|
|
173
|
+
appId: cred.app_id,
|
|
174
|
+
appSecret: cred.app_secret,
|
|
175
|
+
...env.FEISHU_AUTH_URL !== void 0 ? { authUrl: env.FEISHU_AUTH_URL } : {}
|
|
176
|
+
},
|
|
177
|
+
forceTat
|
|
178
|
+
);
|
|
179
|
+
return {
|
|
180
|
+
url: env.FEISHU_MCP_URL ?? DEFAULT_MCP_URL,
|
|
181
|
+
appId: cred.app_id,
|
|
182
|
+
tat,
|
|
183
|
+
allowedTools: env.FEISHU_ALLOWED_TOOLS ?? ""
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
async function withTatRetry(ctx, fn) {
|
|
187
|
+
const cred = credentialOf(ctx);
|
|
188
|
+
try {
|
|
189
|
+
return await fn(await mcpConfig(ctx.env, cred));
|
|
190
|
+
} catch (err) {
|
|
191
|
+
if (!isUnauthorized(err)) throw err;
|
|
192
|
+
return await fn(await mcpConfig(ctx.env, cred, true));
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
function createFeishuPlugin() {
|
|
196
|
+
const plugin = createPlugin({ token: (env) => env.PLUGIN_TOKEN });
|
|
197
|
+
plugin.proxyTools("actions", {
|
|
198
|
+
description: "Feishu actions (docs, wiki, messaging) via the official MCP upstream",
|
|
199
|
+
// 飞书自建应用凭证:两个字段,由平台在挂载时校验齐全(见 core PluginExport.credentialFields)。
|
|
200
|
+
credentialFields: [
|
|
201
|
+
{
|
|
202
|
+
key: "app_id",
|
|
203
|
+
label: "App ID",
|
|
204
|
+
required: true,
|
|
205
|
+
description: "\u98DE\u4E66\u81EA\u5EFA\u5E94\u7528\u7684 app_id(\u5F00\u653E\u5E73\u53F0\u300C\u51ED\u8BC1\u4E0E\u57FA\u7840\u4FE1\u606F\u300D\u9875)"
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
key: "app_secret",
|
|
209
|
+
label: "App Secret",
|
|
210
|
+
required: true,
|
|
211
|
+
secret: true,
|
|
212
|
+
description: "\u98DE\u4E66\u81EA\u5EFA\u5E94\u7528\u7684 app_secret,\u7528\u4E8E\u6362\u53D1 tenant_access_token"
|
|
213
|
+
}
|
|
214
|
+
],
|
|
215
|
+
list: async (ctx) => (await withTatRetry(ctx, listTools)).map(toSpec),
|
|
216
|
+
// MCP RPC 业务错误(isError)是正常返回值,原样进 ToolResult。
|
|
217
|
+
call: async ({ name, args }, ctx) => await withTatRetry(ctx, (cfg) => callTool(cfg, name, args))
|
|
218
|
+
});
|
|
219
|
+
return plugin;
|
|
220
|
+
}
|
|
221
|
+
var feishu_default = createFeishuPlugin();
|
|
222
|
+
export {
|
|
223
|
+
createFeishuPlugin,
|
|
224
|
+
feishu_default as default
|
|
225
|
+
};
|