@oomol-lab/open-connector 1.6.2 → 1.6.3
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/README.md +27 -0
- package/assets/open-connector/catalog/apps/assured_platform.json +218 -0
- package/assets/open-connector/catalog/apps/baixiao.json +1080 -0
- package/assets/open-connector/catalog/apps/benchmarkone.json +956 -0
- package/assets/open-connector/catalog/apps/bing_webmaster.json +3097 -0
- package/assets/open-connector/catalog/apps/buzzsprout.json +1979 -0
- package/assets/open-connector/catalog/apps/feishu.json +13 -19
- package/assets/open-connector/catalog/apps/feishu_app_bot.json +10 -17
- package/assets/open-connector/catalog/apps/linkfox.json +836 -0
- package/assets/open-connector/catalog/apps/metatraderapi.json +1077 -0
- package/assets/open-connector/catalog/apps/mktindex.json +2411 -0
- package/assets/open-connector/catalog/apps/mojo_helpdesk.json +660 -0
- package/assets/open-connector/catalog/apps/mumble.json +446 -0
- package/assets/open-connector/catalog/apps/notion.json +112 -3
- package/assets/open-connector/catalog/apps/omise.json +438 -0
- package/assets/open-connector/catalog/apps/panjiva.json +2858 -0
- package/assets/open-connector/catalog/apps/papertrail.json +449 -0
- package/assets/open-connector/catalog/apps/peec.json +747 -0
- package/assets/open-connector/catalog/apps/polygon_io.json +5156 -584
- package/assets/open-connector/catalog/apps/quant_data.json +1928 -0
- package/assets/open-connector/catalog/apps/riddle_quiz_maker.json +621 -0
- package/assets/open-connector/catalog/apps/slack.json +327 -4
- package/assets/open-connector/catalog/apps/slackbot.json +280 -3
- package/assets/open-connector/catalog/apps/templatedocs.json +438 -0
- package/assets/open-connector/catalog/apps/terminus_app.json +510 -0
- package/assets/open-connector/catalog/apps/ticket_tailor.json +584 -0
- package/assets/open-connector/catalog/apps/tongdaxin.json +2612 -79
- package/assets/open-connector/catalog/apps/veremark.json +514 -0
- package/assets/open-connector/catalog/apps/walletap.json +549 -0
- package/assets/open-connector/catalog/apps/xiaohongshu_store.json +955 -39
- package/assets/open-connector/catalog/apps-index.json +1 -1
- package/package.json +5 -1
- package/src/connection-service.d.ts +2 -0
- package/src/connection-service.js +8 -1
- package/src/core/provider-id.d.ts +5 -0
- package/src/core/provider-id.js +12 -0
- package/src/oauth/oauth-credential-refresh-service.js +2 -0
- package/src/oauth/oauth-flow-service.js +2 -0
- package/src/providers/action-contracts.generated.d.ts +27 -7
- package/src/providers/assured_platform/executors.d.ts +4 -0
- package/src/providers/assured_platform/executors.js +18 -0
- package/src/providers/assured_platform/runtime.d.ts +7 -0
- package/src/providers/assured_platform/runtime.js +108 -0
- package/src/providers/baixiao/actions.d.ts +2 -0
- package/src/providers/baixiao/actions.js +377 -0
- package/src/providers/baixiao/executors.d.ts +4 -0
- package/src/providers/baixiao/executors.js +106 -0
- package/src/providers/benchmarkone/executors.d.ts +4 -0
- package/src/providers/benchmarkone/executors.js +26 -0
- package/src/providers/benchmarkone/runtime.d.ts +12 -0
- package/src/providers/benchmarkone/runtime.js +113 -0
- package/src/providers/bing_webmaster/actions.d.ts +2 -0
- package/src/providers/bing_webmaster/actions.js +113 -0
- package/src/providers/bing_webmaster/executors.d.ts +4 -0
- package/src/providers/bing_webmaster/executors.js +104 -0
- package/src/providers/bing_webmaster/management-actions.d.ts +2 -0
- package/src/providers/bing_webmaster/management-actions.js +241 -0
- package/src/providers/bing_webmaster/reporting-actions.d.ts +2 -0
- package/src/providers/bing_webmaster/reporting-actions.js +300 -0
- package/src/providers/bing_webmaster/schemas.d.ts +33 -0
- package/src/providers/bing_webmaster/schemas.js +313 -0
- package/src/providers/buzzsprout/executors.d.ts +4 -0
- package/src/providers/buzzsprout/executors.js +21 -0
- package/src/providers/buzzsprout/runtime.d.ts +12 -0
- package/src/providers/buzzsprout/runtime.js +237 -0
- package/src/providers/feishu/shared/drive-actions.d.ts +1 -0
- package/src/providers/feishu/shared/drive-actions.js +13 -9
- package/src/providers/feishu/shared/drive-runtime.js +15 -3
- package/src/providers/feishu/shared/wiki-actions.js +4 -2
- package/src/providers/hithink_finance/runtime.js +39 -60
- package/src/providers/linkfox/actions.js +2 -0
- package/src/providers/linkfox/runtime.js +70 -1
- package/src/providers/linkfox/sif-actions.d.ts +10 -0
- package/src/providers/linkfox/sif-actions.js +193 -0
- package/src/providers/metatraderapi/executors.d.ts +4 -0
- package/src/providers/metatraderapi/executors.js +18 -0
- package/src/providers/metatraderapi/runtime.d.ts +7 -0
- package/src/providers/metatraderapi/runtime.js +216 -0
- package/src/providers/mktindex/actions-mmi.d.ts +2 -0
- package/src/providers/mktindex/actions-mmi.js +510 -0
- package/src/providers/mktindex/actions.d.ts +2 -0
- package/src/providers/mktindex/actions.js +2 -0
- package/src/providers/mktindex/executors.d.ts +4 -0
- package/src/providers/mktindex/executors.js +27 -0
- package/src/providers/mktindex/request.d.ts +17 -0
- package/src/providers/mktindex/request.js +48 -0
- package/src/providers/mktindex/runtime.d.ts +9 -0
- package/src/providers/mktindex/runtime.js +492 -0
- package/src/providers/mojo_helpdesk/executors.d.ts +4 -0
- package/src/providers/mojo_helpdesk/executors.js +18 -0
- package/src/providers/mojo_helpdesk/runtime.d.ts +7 -0
- package/src/providers/mojo_helpdesk/runtime.js +173 -0
- package/src/providers/mumble/executors.d.ts +4 -0
- package/src/providers/mumble/executors.js +99 -0
- package/src/providers/notion/executors.d.ts +9 -0
- package/src/providers/notion/executors.js +161 -6
- package/src/providers/omise/executors.d.ts +4 -0
- package/src/providers/omise/executors.js +120 -0
- package/src/providers/panjiva/actions.d.ts +14 -0
- package/src/providers/panjiva/actions.js +389 -0
- package/src/providers/panjiva/executors.d.ts +4 -0
- package/src/providers/panjiva/executors.js +136 -0
- package/src/providers/papertrail/executors.d.ts +4 -0
- package/src/providers/papertrail/executors.js +15 -0
- package/src/providers/papertrail/runtime.d.ts +7 -0
- package/src/providers/papertrail/runtime.js +167 -0
- package/src/providers/peec/executors.d.ts +4 -0
- package/src/providers/peec/executors.js +15 -0
- package/src/providers/peec/runtime.d.ts +7 -0
- package/src/providers/peec/runtime.js +128 -0
- package/src/providers/polygon_io/actions.d.ts +2 -0
- package/src/providers/polygon_io/actions.js +282 -0
- package/src/providers/polygon_io/expanded-actions.d.ts +2 -0
- package/src/providers/polygon_io/expanded-actions.js +375 -0
- package/src/providers/polygon_io/expanded-runtime.d.ts +16 -0
- package/src/providers/polygon_io/expanded-runtime.js +277 -0
- package/src/providers/polygon_io/runtime.js +21 -2
- package/src/providers/quant_data/executors.d.ts +4 -0
- package/src/providers/quant_data/executors.js +15 -0
- package/src/providers/quant_data/runtime.d.ts +7 -0
- package/src/providers/quant_data/runtime.js +118 -0
- package/src/providers/registry.generated.js +20 -0
- package/src/providers/riddle_quiz_maker/executors.d.ts +4 -0
- package/src/providers/riddle_quiz_maker/executors.js +15 -0
- package/src/providers/riddle_quiz_maker/runtime.d.ts +7 -0
- package/src/providers/riddle_quiz_maker/runtime.js +145 -0
- package/src/providers/slack/actions.js +106 -3
- package/src/providers/slack/runtime.js +260 -36
- package/src/providers/slackbot/actions.js +1 -1
- package/src/providers/templatedocs/executors.d.ts +4 -0
- package/src/providers/templatedocs/executors.js +18 -0
- package/src/providers/templatedocs/runtime.d.ts +13 -0
- package/src/providers/templatedocs/runtime.js +151 -0
- package/src/providers/terminus_app/executors.d.ts +4 -0
- package/src/providers/terminus_app/executors.js +15 -0
- package/src/providers/terminus_app/runtime.d.ts +7 -0
- package/src/providers/terminus_app/runtime.js +172 -0
- package/src/providers/ticket_tailor/executors.d.ts +4 -0
- package/src/providers/ticket_tailor/executors.js +15 -0
- package/src/providers/ticket_tailor/runtime.d.ts +7 -0
- package/src/providers/ticket_tailor/runtime.js +152 -0
- package/src/providers/tongdaxin/actions.d.ts +1 -0
- package/src/providers/tongdaxin/actions.js +6 -3
- package/src/providers/tongdaxin/executors.js +51 -10
- package/src/providers/tongdaxin/named-action-output.d.ts +1 -0
- package/src/providers/tongdaxin/named-action-output.js +149 -0
- package/src/providers/tongdaxin/named-action-routing.d.ts +9 -0
- package/src/providers/tongdaxin/named-action-routing.js +417 -0
- package/src/providers/tongdaxin/named-actions.d.ts +2 -0
- package/src/providers/tongdaxin/named-actions.js +378 -0
- package/src/providers/veremark/executors.d.ts +4 -0
- package/src/providers/veremark/executors.js +129 -0
- package/src/providers/walletap/executors.d.ts +4 -0
- package/src/providers/walletap/executors.js +15 -0
- package/src/providers/walletap/runtime.d.ts +7 -0
- package/src/providers/walletap/runtime.js +147 -0
- package/src/providers/weixin_official_account/access-token.js +31 -7
- package/src/providers/weixin_store/access-token.js +33 -7
- package/src/providers/xiaohongshu_store/executors.js +152 -3
- package/src/server/api/openapi.js +3 -0
- package/src/server/connector-assets.d.ts +4 -0
- package/src/server/connector-assets.js +12 -0
- package/src/server/connector-build.d.ts +33 -0
- package/src/server/connector-build.js +73 -0
- package/src/server/connector-runtime.d.ts +1 -2
- package/src/server/connector-runtime.js +2 -8
- package/src/server/server-assets.d.ts +0 -28
- package/src/server/server-assets.js +0 -50
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { basename } from "node:path";
|
|
2
|
+
import { compactObject, optionalInteger, optionalRecord, optionalString } from "../../core/cast.js";
|
|
3
|
+
import { readBoundedResponseBytes } from "../../core/request.js";
|
|
4
|
+
import { providerInputError, ProviderRequestError, providerUserAgent, readProviderJsonBody, requiredInputString, runProviderRequest, } from "../provider-runtime.js";
|
|
5
|
+
export const templatedocsApiBaseUrl = "https://templatedocs.io/api";
|
|
6
|
+
export const templatedocsActionHandlers = {
|
|
7
|
+
list_templates(input, context) {
|
|
8
|
+
const pageIndex = optionalInteger(input.pageIndex);
|
|
9
|
+
return requestTemplateDocsJson({
|
|
10
|
+
...context,
|
|
11
|
+
path: `/v1/templates${pageIndex == null ? "" : `?pageIndex=${pageIndex}`}`,
|
|
12
|
+
});
|
|
13
|
+
},
|
|
14
|
+
get_template(input, context) {
|
|
15
|
+
return requestTemplateDocsJson({ ...context, path: templatePath(input.templateId) });
|
|
16
|
+
},
|
|
17
|
+
async update_template(input, context) {
|
|
18
|
+
const name = optionalString(input.name)?.trim();
|
|
19
|
+
const allowGenerationWithWarnings = input.allowGenerationWithWarnings;
|
|
20
|
+
if (!name && allowGenerationWithWarnings == null) {
|
|
21
|
+
throw providerInputError("name or allowGenerationWithWarnings is required");
|
|
22
|
+
}
|
|
23
|
+
await requestTemplateDocs({
|
|
24
|
+
...context,
|
|
25
|
+
path: templatePath(input.templateId),
|
|
26
|
+
method: "PATCH",
|
|
27
|
+
body: compactObject({
|
|
28
|
+
name,
|
|
29
|
+
options: allowGenerationWithWarnings == null ? undefined : { allowGenerationWithWarnings },
|
|
30
|
+
}),
|
|
31
|
+
});
|
|
32
|
+
return { success: true };
|
|
33
|
+
},
|
|
34
|
+
async delete_template(input, context) {
|
|
35
|
+
await requestTemplateDocs({
|
|
36
|
+
...context,
|
|
37
|
+
path: templatePath(input.templateId),
|
|
38
|
+
method: "DELETE",
|
|
39
|
+
});
|
|
40
|
+
return { success: true };
|
|
41
|
+
},
|
|
42
|
+
generate_document: generateDocument,
|
|
43
|
+
};
|
|
44
|
+
export async function validateTemplateDocsCredential(apiKey, fetcher, signal) {
|
|
45
|
+
const payload = await requestTemplateDocsJson({
|
|
46
|
+
apiKey,
|
|
47
|
+
fetcher,
|
|
48
|
+
signal,
|
|
49
|
+
path: "/v1/templates?pageIndex=1",
|
|
50
|
+
});
|
|
51
|
+
const record = optionalRecord(payload);
|
|
52
|
+
return {
|
|
53
|
+
profile: { displayName: "TemplateDocs API Key" },
|
|
54
|
+
grantedScopes: [],
|
|
55
|
+
metadata: compactObject({
|
|
56
|
+
apiBaseUrl: templatedocsApiBaseUrl,
|
|
57
|
+
validationEndpoint: "/v1/templates",
|
|
58
|
+
pageSize: optionalInteger(record?.pageSize),
|
|
59
|
+
}),
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
async function generateDocument(input, context) {
|
|
63
|
+
if (!context.transitFiles)
|
|
64
|
+
throw providerInputError("Transit file storage is not enabled.");
|
|
65
|
+
const format = optionalString(input.format) ?? "docx";
|
|
66
|
+
const response = await requestTemplateDocs({
|
|
67
|
+
...context,
|
|
68
|
+
path: `${templatePath(input.templateId)}/generate`,
|
|
69
|
+
method: "POST",
|
|
70
|
+
body: {
|
|
71
|
+
data: optionalRecord(input.data) ?? {},
|
|
72
|
+
output: compactObject({
|
|
73
|
+
format,
|
|
74
|
+
filename: optionalString(input.filename)?.trim(),
|
|
75
|
+
email: optionalRecord(input.email),
|
|
76
|
+
}),
|
|
77
|
+
},
|
|
78
|
+
});
|
|
79
|
+
const name = generatedFileName(input.filename, format);
|
|
80
|
+
const mimeType = response.headers.get("content-type")?.split(";")[0]?.trim() ?? mimeTypeForFormat(format);
|
|
81
|
+
const bytes = await readBoundedResponseBytes(response, {
|
|
82
|
+
maxBytes: context.transitFiles.maxBytes,
|
|
83
|
+
fieldName: name,
|
|
84
|
+
createError: (message) => new ProviderRequestError(413, message),
|
|
85
|
+
});
|
|
86
|
+
if (bytes.byteLength === 0)
|
|
87
|
+
throw new ProviderRequestError(502, "TemplateDocs returned an empty document");
|
|
88
|
+
const stored = await context.transitFiles.create(new File([Uint8Array.from(bytes)], name, { type: mimeType }));
|
|
89
|
+
return {
|
|
90
|
+
document: {
|
|
91
|
+
name: stored.name,
|
|
92
|
+
mimeType: stored.mimeType,
|
|
93
|
+
downloadUrl: stored.downloadUrl,
|
|
94
|
+
sizeBytes: stored.sizeBytes,
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
async function requestTemplateDocsJson(input) {
|
|
99
|
+
const response = await requestTemplateDocs(input);
|
|
100
|
+
return readProviderJsonBody(response, {
|
|
101
|
+
emptyBody: undefined,
|
|
102
|
+
invalidJsonMessage: "TemplateDocs returned invalid JSON",
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
async function requestTemplateDocs(input) {
|
|
106
|
+
return runProviderRequest({ label: "TemplateDocs", signal: input.signal }, async (signal) => {
|
|
107
|
+
const headers = new Headers({
|
|
108
|
+
accept: "application/json",
|
|
109
|
+
authorization: `Bearer ${input.apiKey}`,
|
|
110
|
+
"user-agent": providerUserAgent,
|
|
111
|
+
});
|
|
112
|
+
if (input.body != null)
|
|
113
|
+
headers.set("content-type", "application/json");
|
|
114
|
+
const response = await input.fetcher(`${templatedocsApiBaseUrl}${input.path}`, {
|
|
115
|
+
method: input.method ?? "GET",
|
|
116
|
+
headers,
|
|
117
|
+
body: input.body == null ? undefined : JSON.stringify(input.body),
|
|
118
|
+
signal,
|
|
119
|
+
});
|
|
120
|
+
if (!response.ok)
|
|
121
|
+
throw await createTemplateDocsError(response);
|
|
122
|
+
return response;
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
async function createTemplateDocsError(response) {
|
|
126
|
+
let message = `TemplateDocs request failed with status ${response.status}`;
|
|
127
|
+
try {
|
|
128
|
+
const payload = optionalRecord(await readProviderJsonBody(response, {
|
|
129
|
+
emptyBody: undefined,
|
|
130
|
+
invalidJsonMessage: "TemplateDocs returned invalid JSON",
|
|
131
|
+
}));
|
|
132
|
+
message = optionalString(optionalRecord(payload?.error)?.message) ?? message;
|
|
133
|
+
}
|
|
134
|
+
catch { }
|
|
135
|
+
return new ProviderRequestError(response.status || 502, message);
|
|
136
|
+
}
|
|
137
|
+
function templatePath(value) {
|
|
138
|
+
return `/v1/templates/${encodeURIComponent(requiredInputString(value, "templateId"))}`;
|
|
139
|
+
}
|
|
140
|
+
function generatedFileName(value, format) {
|
|
141
|
+
const requested = optionalString(value)?.trim();
|
|
142
|
+
if (!requested)
|
|
143
|
+
return `templatedocs-document.${format}`;
|
|
144
|
+
const safeName = basename(requested.replaceAll("\\", "/"));
|
|
145
|
+
return safeName.toLowerCase().endsWith(`.${format}`) ? safeName : `${safeName}.${format}`;
|
|
146
|
+
}
|
|
147
|
+
function mimeTypeForFormat(format) {
|
|
148
|
+
return format === "pdf"
|
|
149
|
+
? "application/pdf"
|
|
150
|
+
: "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
|
|
151
|
+
}
|
|
@@ -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,15 @@
|
|
|
1
|
+
import { defineApiKeyProviderExecutors, defineProviderProxy } from "../provider-runtime.js";
|
|
2
|
+
import { terminusAppActionHandlers, validateTerminusAppCredential } from "./runtime.js";
|
|
3
|
+
const service = "terminus_app";
|
|
4
|
+
export const executors = defineApiKeyProviderExecutors(service, terminusAppActionHandlers);
|
|
5
|
+
export const proxy = defineProviderProxy({
|
|
6
|
+
service,
|
|
7
|
+
baseUrl: "https://api.terminusapp.com",
|
|
8
|
+
auth: { type: "api_key_basic", suffix: ":" },
|
|
9
|
+
skipDnsValidation: true,
|
|
10
|
+
});
|
|
11
|
+
export const credentialValidators = {
|
|
12
|
+
apiKey(input, { fetcher, signal }) {
|
|
13
|
+
return validateTerminusAppCredential(input.apiKey, fetcher, signal);
|
|
14
|
+
},
|
|
15
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { CredentialValidationResult } from "../../core/types.ts";
|
|
2
|
+
import type { ApiKeyProviderContext, ProviderActionHandlers, ProviderFetch } from "../provider-runtime.ts";
|
|
3
|
+
export declare const terminusAppApiBaseUrl = "https://api.terminusapp.com";
|
|
4
|
+
type Handler = (input: Record<string, unknown>, context: ApiKeyProviderContext) => Promise<unknown>;
|
|
5
|
+
export declare const terminusAppActionHandlers: ProviderActionHandlers<"terminus_app", Handler>;
|
|
6
|
+
export declare function validateTerminusAppCredential(apiKey: string, fetcher: ProviderFetch, signal?: AbortSignal): Promise<CredentialValidationResult>;
|
|
7
|
+
export {};
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { compactObject, optionalBoolean, optionalInteger, optionalRecord, optionalString, recordOrEmpty, } from "../../core/cast.js";
|
|
2
|
+
import { readProviderTextBody } from "../provider-runtime.js";
|
|
3
|
+
import { basicAuthorizationHeader, providerUserAgent, ProviderRequestError, requiredInputString, requiredResponseRecord, runProviderRequest, } from "../provider-runtime.js";
|
|
4
|
+
export const terminusAppApiBaseUrl = "https://api.terminusapp.com";
|
|
5
|
+
export const terminusAppActionHandlers = {
|
|
6
|
+
async list_projects(input, context) {
|
|
7
|
+
return normalizeList(await requestTerminusApp({
|
|
8
|
+
...context,
|
|
9
|
+
path: "/v1/projects/",
|
|
10
|
+
phase: "execute",
|
|
11
|
+
query: buildPaginationQuery(input),
|
|
12
|
+
}), "projects");
|
|
13
|
+
},
|
|
14
|
+
async list_conventions(input, context) {
|
|
15
|
+
const projectId = requiredInputString(input.projectId, "projectId");
|
|
16
|
+
return normalizeList(await requestTerminusApp({
|
|
17
|
+
...context,
|
|
18
|
+
path: `/v1/projects/${encodeURIComponent(projectId)}/conventions`,
|
|
19
|
+
phase: "execute",
|
|
20
|
+
query: buildPaginationQuery(input),
|
|
21
|
+
}), "conventions");
|
|
22
|
+
},
|
|
23
|
+
async get_convention(input, context) {
|
|
24
|
+
const projectId = requiredInputString(input.projectId, "projectId");
|
|
25
|
+
const payload = await requestTerminusApp({
|
|
26
|
+
...context,
|
|
27
|
+
path: `/v1/projects/${encodeURIComponent(projectId)}/conventions/${optionalInteger(input.conventionId)}`,
|
|
28
|
+
phase: "execute",
|
|
29
|
+
});
|
|
30
|
+
return { convention: requiredResponseRecord(payload, "Terminus convention response") };
|
|
31
|
+
},
|
|
32
|
+
async list_links(input, context) {
|
|
33
|
+
const projectId = requiredInputString(input.projectId, "projectId");
|
|
34
|
+
const payload = await requestTerminusApp({
|
|
35
|
+
...context,
|
|
36
|
+
path: `/v1/projects/${encodeURIComponent(projectId)}/links`,
|
|
37
|
+
phase: "execute",
|
|
38
|
+
query: {
|
|
39
|
+
...buildPaginationQuery(input),
|
|
40
|
+
"created_at[gt]": stringifyInteger(optionalInteger(input.createdAfter)),
|
|
41
|
+
"updated_at[gt]": stringifyInteger(optionalInteger(input.updatedAfter)),
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
return normalizeList(payload, "links");
|
|
45
|
+
},
|
|
46
|
+
async create_link(input, context) {
|
|
47
|
+
const projectId = requiredInputString(input.projectId, "projectId");
|
|
48
|
+
const payload = await requestTerminusApp({
|
|
49
|
+
...context,
|
|
50
|
+
method: "POST",
|
|
51
|
+
path: `/v1/projects/${encodeURIComponent(projectId)}/links`,
|
|
52
|
+
phase: "execute",
|
|
53
|
+
body: buildCreateLinkBody(input),
|
|
54
|
+
});
|
|
55
|
+
return { link: requiredResponseRecord(payload, "Terminus link response") };
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
export async function validateTerminusAppCredential(apiKey, fetcher, signal) {
|
|
59
|
+
const payload = await requestTerminusApp({
|
|
60
|
+
apiKey,
|
|
61
|
+
fetcher,
|
|
62
|
+
signal,
|
|
63
|
+
path: "/v1/projects/",
|
|
64
|
+
phase: "validate",
|
|
65
|
+
query: { items: "1" },
|
|
66
|
+
});
|
|
67
|
+
normalizeList(payload, "projects");
|
|
68
|
+
return {
|
|
69
|
+
profile: { accountId: "terminus-app", displayName: "Terminus App API Key" },
|
|
70
|
+
grantedScopes: [],
|
|
71
|
+
metadata: { apiBaseUrl: terminusAppApiBaseUrl, validationEndpoint: "/v1/projects/" },
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
function buildPaginationQuery(input) {
|
|
75
|
+
return { page: stringifyInteger(optionalInteger(input.page)), items: stringifyInteger(optionalInteger(input.items)) };
|
|
76
|
+
}
|
|
77
|
+
function stringifyInteger(value) {
|
|
78
|
+
return value === undefined ? undefined : String(value);
|
|
79
|
+
}
|
|
80
|
+
function buildCreateLinkBody(input) {
|
|
81
|
+
const convention = optionalRecord(input.convention);
|
|
82
|
+
const inputFields = Array.isArray(convention?.inputFields)
|
|
83
|
+
? convention.inputFields.map((value) => {
|
|
84
|
+
const field = recordOrEmpty(value);
|
|
85
|
+
return { field_id: optionalInteger(field.fieldId), input_value: optionalString(field.inputValue) };
|
|
86
|
+
})
|
|
87
|
+
: undefined;
|
|
88
|
+
const utm = optionalRecord(input.utm);
|
|
89
|
+
return compactObject({
|
|
90
|
+
url: requiredInputString(input.url, "url"),
|
|
91
|
+
convention: convention ? { id: optionalInteger(convention.id), input_fields: inputFields } : undefined,
|
|
92
|
+
utm: utm ? mapTagObject(utm) : undefined,
|
|
93
|
+
custom: mapOptionalNamedTags(input.custom),
|
|
94
|
+
info: mapOptionalNamedTags(input.info),
|
|
95
|
+
label_names: Array.isArray(input.labelNames) ? input.labelNames : undefined,
|
|
96
|
+
description: optionalString(input.description),
|
|
97
|
+
skip_monitoring: optionalBoolean(input.skipMonitoring),
|
|
98
|
+
short_url_key: optionalString(input.shortUrlKey),
|
|
99
|
+
skip_url_validation: optionalBoolean(input.skipUrlValidation),
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
function mapTagObject(input) {
|
|
103
|
+
return compactObject({
|
|
104
|
+
campaign: optionalRecord(input.campaign),
|
|
105
|
+
medium: optionalRecord(input.medium),
|
|
106
|
+
source: optionalRecord(input.source),
|
|
107
|
+
content: optionalRecord(input.content),
|
|
108
|
+
term: optionalRecord(input.term),
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
function mapOptionalNamedTags(value) {
|
|
112
|
+
const record = optionalRecord(value);
|
|
113
|
+
return record ? Object.fromEntries(Object.entries(record)) : undefined;
|
|
114
|
+
}
|
|
115
|
+
async function requestTerminusApp(input) {
|
|
116
|
+
return runProviderRequest({ label: "Terminus App", signal: input.signal }, async (signal) => {
|
|
117
|
+
const url = new URL(input.path, terminusAppApiBaseUrl);
|
|
118
|
+
for (const [name, value] of Object.entries(input.query ?? {}))
|
|
119
|
+
if (value !== undefined)
|
|
120
|
+
url.searchParams.set(name, value);
|
|
121
|
+
const response = await input.fetcher(url, {
|
|
122
|
+
method: input.method ?? "GET",
|
|
123
|
+
headers: {
|
|
124
|
+
accept: "application/json",
|
|
125
|
+
authorization: basicAuthorizationHeader(`${input.apiKey}:`),
|
|
126
|
+
"content-type": "application/json",
|
|
127
|
+
"user-agent": providerUserAgent,
|
|
128
|
+
},
|
|
129
|
+
body: input.body === undefined ? undefined : JSON.stringify(input.body),
|
|
130
|
+
signal,
|
|
131
|
+
});
|
|
132
|
+
const payload = await readPayload(response);
|
|
133
|
+
if (!response.ok)
|
|
134
|
+
throw createError(response.status, payload, input.phase);
|
|
135
|
+
return payload;
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
async function readPayload(response) {
|
|
139
|
+
const text = await readProviderTextBody(response, "Terminus App response");
|
|
140
|
+
if (!text.trim())
|
|
141
|
+
return null;
|
|
142
|
+
try {
|
|
143
|
+
return JSON.parse(text);
|
|
144
|
+
}
|
|
145
|
+
catch {
|
|
146
|
+
throw new ProviderRequestError(502, "Terminus App returned invalid JSON");
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
function createError(status, payload, phase) {
|
|
150
|
+
const message = extractErrorMessage(payload) ?? `Terminus App request failed with status ${status}`;
|
|
151
|
+
if (status === 429)
|
|
152
|
+
return new ProviderRequestError(429, message, payload);
|
|
153
|
+
if (status === 401)
|
|
154
|
+
return new ProviderRequestError(phase === "validate" ? 400 : 401, message, payload);
|
|
155
|
+
return new ProviderRequestError(status || 502, message, payload);
|
|
156
|
+
}
|
|
157
|
+
function extractErrorMessage(payload) {
|
|
158
|
+
const record = optionalRecord(payload);
|
|
159
|
+
return optionalString(record?.message) ?? optionalString(record?.error) ?? optionalString(record?.detail);
|
|
160
|
+
}
|
|
161
|
+
function normalizeList(payload, outputName) {
|
|
162
|
+
const record = requiredResponseRecord(payload, "Terminus list response");
|
|
163
|
+
return {
|
|
164
|
+
[outputName]: requireArray(record.data, "Terminus list response data"),
|
|
165
|
+
meta: requiredResponseRecord(record.meta, "Terminus list response meta"),
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
function requireArray(value, label) {
|
|
169
|
+
if (Array.isArray(value))
|
|
170
|
+
return value;
|
|
171
|
+
throw new ProviderRequestError(502, `${label} must be an array`);
|
|
172
|
+
}
|
|
@@ -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,15 @@
|
|
|
1
|
+
import { defineApiKeyProviderExecutors, defineProviderProxy } from "../provider-runtime.js";
|
|
2
|
+
import { ticketTailorActionHandlers, validateTicketTailorCredential } from "./runtime.js";
|
|
3
|
+
const service = "ticket_tailor";
|
|
4
|
+
export const executors = defineApiKeyProviderExecutors(service, ticketTailorActionHandlers);
|
|
5
|
+
export const proxy = defineProviderProxy({
|
|
6
|
+
service,
|
|
7
|
+
baseUrl: "https://api.tickettailor.com",
|
|
8
|
+
auth: { type: "api_key_basic", suffix: ":" },
|
|
9
|
+
skipDnsValidation: true,
|
|
10
|
+
});
|
|
11
|
+
export const credentialValidators = {
|
|
12
|
+
apiKey(input, { fetcher, signal }) {
|
|
13
|
+
return validateTicketTailorCredential(input.apiKey, fetcher, signal);
|
|
14
|
+
},
|
|
15
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { CredentialValidationResult } from "../../core/types.ts";
|
|
2
|
+
import type { ApiKeyProviderContext, ProviderActionHandlers, ProviderFetch } from "../provider-runtime.ts";
|
|
3
|
+
export declare const ticketTailorApiBaseUrl = "https://api.tickettailor.com";
|
|
4
|
+
type Handler = (input: Record<string, unknown>, context: ApiKeyProviderContext) => Promise<unknown>;
|
|
5
|
+
export declare const ticketTailorActionHandlers: ProviderActionHandlers<"ticket_tailor", Handler>;
|
|
6
|
+
export declare function validateTicketTailorCredential(apiKey: string, fetcher: ProviderFetch, signal?: AbortSignal): Promise<CredentialValidationResult>;
|
|
7
|
+
export {};
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { compactObject, optionalInteger, optionalRecord, optionalString } from "../../core/cast.js";
|
|
2
|
+
import { readProviderTextBody } from "../provider-runtime.js";
|
|
3
|
+
import { basicAuthorizationHeader, providerUserAgent, ProviderRequestError, requiredInputString, requiredResponseRecord, runProviderRequest, } from "../provider-runtime.js";
|
|
4
|
+
export const ticketTailorApiBaseUrl = "https://api.tickettailor.com";
|
|
5
|
+
const ticketTailorApiKeyHelpUrl = "https://help.tickettailor.com/en/articles/4593218-how-do-i-connect-to-the-ticket-tailor-api";
|
|
6
|
+
const paginationFields = ["starting_after", "ending_before", "limit"];
|
|
7
|
+
const actionRoutes = {
|
|
8
|
+
list_events: {
|
|
9
|
+
collectionPath: "/v1/events",
|
|
10
|
+
queryFields: [
|
|
11
|
+
...paginationFields,
|
|
12
|
+
"start_at",
|
|
13
|
+
"start_at.gt",
|
|
14
|
+
"start_at.gte",
|
|
15
|
+
"start_at.lt",
|
|
16
|
+
"start_at.lte",
|
|
17
|
+
"end_at",
|
|
18
|
+
"end_at.gt",
|
|
19
|
+
"end_at.gte",
|
|
20
|
+
"end_at.lt",
|
|
21
|
+
"end_at.lte",
|
|
22
|
+
"status",
|
|
23
|
+
"name",
|
|
24
|
+
"venue",
|
|
25
|
+
],
|
|
26
|
+
},
|
|
27
|
+
get_event: { collectionPath: "/v1/events", idField: "event_id" },
|
|
28
|
+
list_orders: {
|
|
29
|
+
collectionPath: "/v1/orders",
|
|
30
|
+
queryFields: [
|
|
31
|
+
...paginationFields,
|
|
32
|
+
"created_at",
|
|
33
|
+
"created_at.gt",
|
|
34
|
+
"created_at.gte",
|
|
35
|
+
"created_at.lt",
|
|
36
|
+
"created_at.lte",
|
|
37
|
+
"name",
|
|
38
|
+
"email",
|
|
39
|
+
"txn_id",
|
|
40
|
+
"barcode",
|
|
41
|
+
"event_id",
|
|
42
|
+
"event_series_id",
|
|
43
|
+
"status",
|
|
44
|
+
"store_id",
|
|
45
|
+
"referral_tag",
|
|
46
|
+
],
|
|
47
|
+
},
|
|
48
|
+
get_order: { collectionPath: "/v1/orders", idField: "order_id" },
|
|
49
|
+
list_issued_tickets: {
|
|
50
|
+
collectionPath: "/v1/issued_tickets",
|
|
51
|
+
queryFields: [
|
|
52
|
+
...paginationFields,
|
|
53
|
+
"event_id",
|
|
54
|
+
"event_series_id",
|
|
55
|
+
"order_id",
|
|
56
|
+
"barcode",
|
|
57
|
+
"name",
|
|
58
|
+
"email",
|
|
59
|
+
"reference",
|
|
60
|
+
"status",
|
|
61
|
+
"created_at",
|
|
62
|
+
"created_at.gt",
|
|
63
|
+
"created_at.gte",
|
|
64
|
+
"created_at.lt",
|
|
65
|
+
"created_at.lte",
|
|
66
|
+
],
|
|
67
|
+
},
|
|
68
|
+
get_issued_ticket: { collectionPath: "/v1/issued_tickets", idField: "issued_ticket_id" },
|
|
69
|
+
};
|
|
70
|
+
function createHandler(route) {
|
|
71
|
+
return async (input, context) => {
|
|
72
|
+
const path = route.idField
|
|
73
|
+
? `${route.collectionPath}/${encodeURIComponent(requiredInputString(input[route.idField], route.idField))}`
|
|
74
|
+
: route.collectionPath;
|
|
75
|
+
const payload = await requestTicketTailorJson({
|
|
76
|
+
apiKey: context.apiKey,
|
|
77
|
+
path,
|
|
78
|
+
query: route.idField ? undefined : buildListQuery(input, route.queryFields ?? []),
|
|
79
|
+
fetcher: context.fetcher,
|
|
80
|
+
signal: context.signal,
|
|
81
|
+
});
|
|
82
|
+
if (route.idField)
|
|
83
|
+
return requiredResponseRecord(payload, "Ticket Tailor resource response");
|
|
84
|
+
const response = requiredResponseRecord(payload, "Ticket Tailor list response");
|
|
85
|
+
return { ...response, data: requireArray(response.data, "Ticket Tailor list response data") };
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
export const ticketTailorActionHandlers = Object.fromEntries(Object.entries(actionRoutes).map(([name, route]) => [name, createHandler(route)]));
|
|
89
|
+
export async function validateTicketTailorCredential(apiKey, fetcher, signal) {
|
|
90
|
+
await requestTicketTailorJson({ apiKey, path: "/v1/ping", fetcher, signal });
|
|
91
|
+
return {
|
|
92
|
+
profile: { accountId: "ticket-tailor", displayName: "Ticket Tailor Box Office" },
|
|
93
|
+
grantedScopes: [],
|
|
94
|
+
metadata: {
|
|
95
|
+
apiBaseUrl: ticketTailorApiBaseUrl,
|
|
96
|
+
validationEndpoint: "/v1/ping",
|
|
97
|
+
credentialHelpUrl: ticketTailorApiKeyHelpUrl,
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
function buildListQuery(input, fields) {
|
|
102
|
+
const query = {};
|
|
103
|
+
for (const field of fields)
|
|
104
|
+
query[field] =
|
|
105
|
+
field === "limit" || field.includes("_at") ? optionalInteger(input[field]) : optionalString(input[field]);
|
|
106
|
+
return compactObject(query);
|
|
107
|
+
}
|
|
108
|
+
async function requestTicketTailorJson(input) {
|
|
109
|
+
return runProviderRequest({ label: "Ticket Tailor", signal: input.signal }, async (signal) => {
|
|
110
|
+
const url = new URL(input.path, ticketTailorApiBaseUrl);
|
|
111
|
+
for (const [key, value] of Object.entries(input.query ?? {}))
|
|
112
|
+
if (value !== undefined)
|
|
113
|
+
url.searchParams.set(key, String(value));
|
|
114
|
+
const response = await input.fetcher(url, {
|
|
115
|
+
method: "GET",
|
|
116
|
+
headers: {
|
|
117
|
+
accept: "application/json",
|
|
118
|
+
authorization: basicAuthorizationHeader(`${input.apiKey}:`),
|
|
119
|
+
"user-agent": providerUserAgent,
|
|
120
|
+
},
|
|
121
|
+
signal,
|
|
122
|
+
});
|
|
123
|
+
const payload = await readPayload(response);
|
|
124
|
+
if (!response.ok)
|
|
125
|
+
throw createError(response, payload);
|
|
126
|
+
return payload;
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
async function readPayload(response) {
|
|
130
|
+
const text = await readProviderTextBody(response, "Ticket Tailor response");
|
|
131
|
+
if (!text.trim())
|
|
132
|
+
return {};
|
|
133
|
+
try {
|
|
134
|
+
return JSON.parse(text);
|
|
135
|
+
}
|
|
136
|
+
catch {
|
|
137
|
+
throw new ProviderRequestError(502, "Ticket Tailor returned invalid JSON");
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
function createError(response, payload) {
|
|
141
|
+
const record = optionalRecord(payload) ?? {};
|
|
142
|
+
const upstreamMessage = optionalString(record.message) ??
|
|
143
|
+
optionalString(record.error) ??
|
|
144
|
+
`Ticket Tailor request failed with HTTP ${response.status}`;
|
|
145
|
+
const code = optionalString(record.error_code);
|
|
146
|
+
return new ProviderRequestError(response.status || 502, code ? `[${code}] ${upstreamMessage}` : upstreamMessage, payload, code);
|
|
147
|
+
}
|
|
148
|
+
function requireArray(value, label) {
|
|
149
|
+
if (Array.isArray(value))
|
|
150
|
+
return value;
|
|
151
|
+
throw new ProviderRequestError(502, `${label} must be an array`);
|
|
152
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { s } from "../../core/json-schema.js";
|
|
2
2
|
import { defineProviderAction } from "../../core/provider-definition.js";
|
|
3
|
+
import { tongdaxinNamedActions } from "./named-actions.js";
|
|
3
4
|
const service = "tongdaxin";
|
|
4
5
|
export const tongdaxinReadOnlyToolNames = [
|
|
5
6
|
"tdx_lookup_stock",
|
|
@@ -11,6 +12,7 @@ export const tongdaxinReadOnlyToolNames = [
|
|
|
11
12
|
"wenda_news_query",
|
|
12
13
|
"wenda_notice_query",
|
|
13
14
|
"wenda_report_query",
|
|
15
|
+
"wenda_macro_query",
|
|
14
16
|
];
|
|
15
17
|
const toolAnnotationsSchema = s.looseObject("MCP behavior hints supplied by Tongdaxin.", {
|
|
16
18
|
title: s.optional(s.string("A human-readable title for the tool.")),
|
|
@@ -20,7 +22,7 @@ const toolAnnotationsSchema = s.looseObject("MCP behavior hints supplied by Tong
|
|
|
20
22
|
openWorldHint: s.optional(s.boolean("Whether the tool may interact with entities outside Tongdaxin.")),
|
|
21
23
|
});
|
|
22
24
|
const mcpToolSummarySchema = s.object("A supported read-only financial data tool currently exposed by Tongdaxin MCP.", {
|
|
23
|
-
name: s.
|
|
25
|
+
name: s.nonWhitespaceString("The exact Tongdaxin MCP tool name to pass to call_tool."),
|
|
24
26
|
description: s.string("The current tool description supplied by Tongdaxin MCP."),
|
|
25
27
|
annotations: toolAnnotationsSchema,
|
|
26
28
|
inputSchema: s.looseObject("The current JSON Schema for the tool arguments, supplied by Tongdaxin MCP."),
|
|
@@ -28,7 +30,7 @@ const mcpToolSummarySchema = s.object("A supported read-only financial data tool
|
|
|
28
30
|
export const tongdaxinActions = [
|
|
29
31
|
defineProviderAction(service, {
|
|
30
32
|
name: "list_tools",
|
|
31
|
-
operationType: "
|
|
33
|
+
operationType: "destructive",
|
|
32
34
|
description: "Discover the supported Tongdaxin market data, screening, news, announcement, and research MCP tools with their live input schemas.",
|
|
33
35
|
requiredScopes: [],
|
|
34
36
|
followUpActions: ["tongdaxin.call_tool"],
|
|
@@ -44,11 +46,12 @@ export const tongdaxinActions = [
|
|
|
44
46
|
requiredScopes: [],
|
|
45
47
|
followUpActions: ["tongdaxin.list_tools"],
|
|
46
48
|
inputSchema: s.object("Input for invoking one supported read-only Tongdaxin MCP tool.", {
|
|
47
|
-
toolName: s.
|
|
49
|
+
toolName: s.nonWhitespaceString("The exact Tongdaxin MCP tool to invoke."),
|
|
48
50
|
arguments: s.looseObject("JSON arguments matching the live inputSchema returned for the selected tool."),
|
|
49
51
|
}, { optional: ["arguments"] }),
|
|
50
52
|
outputSchema: s.object("The normalized result returned by Tongdaxin MCP.", {
|
|
51
53
|
result: s.unknown("The tool result. Structured MCP content is returned directly; otherwise the MCP content envelope is preserved."),
|
|
52
54
|
}),
|
|
53
55
|
}),
|
|
56
|
+
...tongdaxinNamedActions,
|
|
54
57
|
];
|