@tangle-network/agent-integrations 0.52.0 → 0.53.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/catalog.js +5 -5
- package/dist/{chunk-BBUJPJRA.js → chunk-CUTII6IW.js} +5 -3
- package/dist/{chunk-BBUJPJRA.js.map → chunk-CUTII6IW.js.map} +1 -1
- package/dist/{chunk-7P2LN4VT.js → chunk-LBPYXEHO.js} +71 -4
- package/dist/chunk-LBPYXEHO.js.map +1 -0
- package/dist/{chunk-PUXYDSXI.js → chunk-NOCFPRQM.js} +2 -2
- package/dist/{chunk-XEJKVCXB.js → chunk-OOGP4SCY.js} +1790 -1
- package/dist/{chunk-XEJKVCXB.js.map → chunk-OOGP4SCY.js.map} +1 -1
- package/dist/{chunk-FOQ7S4TK.js → chunk-QVCO4ZYJ.js} +85 -3
- package/dist/chunk-QVCO4ZYJ.js.map +1 -0
- package/dist/connectors/adapters/index.d.ts +94 -1
- package/dist/connectors/adapters/index.js +11 -1
- package/dist/connectors/index.d.ts +1 -1
- package/dist/connectors/index.js +12 -2
- package/dist/coverage-catalog.d.ts +1 -1
- package/dist/coverage-catalog.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +15 -5
- package/dist/mcp.js +5 -5
- package/dist/registry.js +5 -5
- package/dist/runtime.js +5 -5
- package/dist/specs.js +4 -4
- package/docs/integration-execution-audit.md +143 -20
- package/docs/integration-execution-matrix.json +4541 -1478
- package/package.json +1 -1
- package/dist/chunk-7P2LN4VT.js.map +0 -1
- package/dist/chunk-FOQ7S4TK.js.map +0 -1
- /package/dist/{chunk-PUXYDSXI.js.map → chunk-NOCFPRQM.js.map} +0 -0
|
@@ -32,6 +32,7 @@ __export(adapters_exports, {
|
|
|
32
32
|
acumbamailConnector: () => acumbamailConnector,
|
|
33
33
|
adobeCreativeCloudConnector: () => adobeCreativeCloudConnector,
|
|
34
34
|
adpConnector: () => adpConnector,
|
|
35
|
+
affinityConnector: () => affinityConnector,
|
|
35
36
|
afforaiConnector: () => afforaiConnector,
|
|
36
37
|
agentxConnector: () => agentxConnector,
|
|
37
38
|
aidbaseConnector: () => aidbaseConnector,
|
|
@@ -44,6 +45,7 @@ __export(adapters_exports, {
|
|
|
44
45
|
altTextAiConnector: () => altTextAiConnector,
|
|
45
46
|
alttextifyConnector: () => alttextifyConnector,
|
|
46
47
|
amazonBedrockConnector: () => amazonBedrockConnector,
|
|
48
|
+
amazonS3Connector: () => amazonS3Connector,
|
|
47
49
|
amazonSecretsManagerConnector: () => amazonSecretsManagerConnector,
|
|
48
50
|
amazonSesConnector: () => amazonSesConnector,
|
|
49
51
|
amazonSnsConnector: () => amazonSnsConnector,
|
|
@@ -263,6 +265,7 @@ __export(adapters_exports, {
|
|
|
263
265
|
heyreachConnector: () => heyreachConnector,
|
|
264
266
|
hightouchConnector: () => hightouchConnector,
|
|
265
267
|
housecallProConnector: () => housecallProConnector,
|
|
268
|
+
httpConnector: () => httpConnector,
|
|
266
269
|
hubspot: () => hubspot,
|
|
267
270
|
huggingFaceConnector: () => huggingFaceConnector,
|
|
268
271
|
huggingfaceConnector: () => huggingfaceConnector,
|
|
@@ -443,6 +446,7 @@ __export(adapters_exports, {
|
|
|
443
446
|
ringcentralConnector: () => ringcentralConnector,
|
|
444
447
|
ripplingConnector: () => ripplingConnector,
|
|
445
448
|
robollyConnector: () => robollyConnector,
|
|
449
|
+
rssConnector: () => rssConnector,
|
|
446
450
|
runwareConnector: () => runwareConnector,
|
|
447
451
|
saasticConnector: () => saasticConnector,
|
|
448
452
|
saleorConnector: () => saleorConnector,
|
|
@@ -568,6 +572,7 @@ __export(adapters_exports, {
|
|
|
568
572
|
zohoBookingsConnector: () => zohoBookingsConnector,
|
|
569
573
|
zohoCrmConnector: () => zohoCrmConnector,
|
|
570
574
|
zohoDeskConnector: () => zohoDeskConnector,
|
|
575
|
+
zoomConnector: () => zoomConnector,
|
|
571
576
|
zoominfoConnector: () => zoominfoConnector,
|
|
572
577
|
zuoraConnector: () => zuoraConnector
|
|
573
578
|
});
|
|
@@ -14008,6 +14013,910 @@ function signHeaders(creds, body, idempotencyKey) {
|
|
|
14008
14013
|
return headers;
|
|
14009
14014
|
}
|
|
14010
14015
|
|
|
14016
|
+
// src/connectors/adapters/public-http-target.ts
|
|
14017
|
+
function assertPublicHttpTarget(url, label) {
|
|
14018
|
+
const hostname = url.hostname.toLowerCase().replace(/^\[|\]$/g, "");
|
|
14019
|
+
if (hostname === "localhost" || hostname.endsWith(".localhost") || hostname.endsWith(".local") || hostname === "metadata.google.internal") {
|
|
14020
|
+
throw new Error(`${label} host is not a public network target`);
|
|
14021
|
+
}
|
|
14022
|
+
if (isPrivateIpv4(hostname) || isPrivateIpv6(hostname)) {
|
|
14023
|
+
throw new Error(`${label} host is not a public network target`);
|
|
14024
|
+
}
|
|
14025
|
+
}
|
|
14026
|
+
function isPrivateIpv4(hostname) {
|
|
14027
|
+
const parts = hostname.split(".");
|
|
14028
|
+
if (parts.length !== 4 || parts.some((part) => !/^\d{1,3}$/.test(part))) return false;
|
|
14029
|
+
const octets = parts.map(Number);
|
|
14030
|
+
if (octets.some((octet) => octet > 255)) return false;
|
|
14031
|
+
const [a, b] = octets;
|
|
14032
|
+
return a === 0 || a === 10 || a === 127 || a === 100 && b >= 64 && b <= 127 || a === 169 && b === 254 || a === 172 && b >= 16 && b <= 31 || a === 192 && b === 168 || a === 198 && (b === 18 || b === 19) || a >= 224;
|
|
14033
|
+
}
|
|
14034
|
+
function isPrivateIpv6(hostname) {
|
|
14035
|
+
const normalized = hostname.toLowerCase();
|
|
14036
|
+
if (normalized === "::" || normalized === "::1") return true;
|
|
14037
|
+
if (/^f[cd]/.test(normalized) || /^fe[89ab]/.test(normalized)) return true;
|
|
14038
|
+
const mapped = normalized.match(/^::ffff:(\d+\.\d+\.\d+\.\d+)$/);
|
|
14039
|
+
return mapped ? isPrivateIpv4(mapped[1]) : false;
|
|
14040
|
+
}
|
|
14041
|
+
|
|
14042
|
+
// src/connectors/adapters/http.ts
|
|
14043
|
+
var ALLOWED_SCHEMES = /* @__PURE__ */ new Set(["http:", "https:"]);
|
|
14044
|
+
var READ_METHODS = /* @__PURE__ */ new Set(["GET", "HEAD", "OPTIONS"]);
|
|
14045
|
+
var MUTATION_METHODS = /* @__PURE__ */ new Set(["POST", "PUT", "PATCH", "DELETE"]);
|
|
14046
|
+
var MAX_TIMEOUT_MS = 6e4;
|
|
14047
|
+
var DEFAULT_TIMEOUT_MS = 15e3;
|
|
14048
|
+
var httpConnector = {
|
|
14049
|
+
manifest: {
|
|
14050
|
+
kind: "http",
|
|
14051
|
+
displayName: "HTTP Request",
|
|
14052
|
+
description: "Send an arbitrary HTTP request to any http(s) URL. Useful for hitting one-off APIs, probes, public JSON feeds, or operator-controlled webhooks. No shared auth \u2014 the agent supplies the full URL, method, headers, and body at invocation time.",
|
|
14053
|
+
auth: { kind: "none" },
|
|
14054
|
+
category: "webhook",
|
|
14055
|
+
defaultConsistencyModel: "advisory",
|
|
14056
|
+
capabilities: [
|
|
14057
|
+
{
|
|
14058
|
+
name: "request.fetch",
|
|
14059
|
+
class: "read",
|
|
14060
|
+
description: "Issue a GET/HEAD/OPTIONS request to a URL. Returns the parsed JSON body if the response Content-Type is application/json, otherwise the raw text. The `etag` of the response (when present) is exposed for downstream conditional reads.",
|
|
14061
|
+
parameters: {
|
|
14062
|
+
type: "object",
|
|
14063
|
+
properties: {
|
|
14064
|
+
url: { type: "string", description: "Absolute http(s) URL to fetch." },
|
|
14065
|
+
method: {
|
|
14066
|
+
type: "string",
|
|
14067
|
+
enum: ["GET", "HEAD", "OPTIONS"],
|
|
14068
|
+
description: "HTTP verb. Defaults to GET."
|
|
14069
|
+
},
|
|
14070
|
+
headers: {
|
|
14071
|
+
type: "object",
|
|
14072
|
+
description: "Optional request headers. Header names are lower-cased before send.",
|
|
14073
|
+
additionalProperties: { type: "string" }
|
|
14074
|
+
},
|
|
14075
|
+
query: {
|
|
14076
|
+
type: "object",
|
|
14077
|
+
description: "Optional query-string parameters. Values are coerced to string; arrays become repeated keys.",
|
|
14078
|
+
additionalProperties: true
|
|
14079
|
+
},
|
|
14080
|
+
timeoutMs: {
|
|
14081
|
+
type: "number",
|
|
14082
|
+
description: `Per-request timeout in milliseconds. Defaults to ${DEFAULT_TIMEOUT_MS}, capped at ${MAX_TIMEOUT_MS}.`
|
|
14083
|
+
}
|
|
14084
|
+
},
|
|
14085
|
+
required: ["url"]
|
|
14086
|
+
}
|
|
14087
|
+
},
|
|
14088
|
+
{
|
|
14089
|
+
name: "request.send",
|
|
14090
|
+
class: "mutation",
|
|
14091
|
+
description: "Issue a POST/PUT/PATCH/DELETE request to a URL. The agent supplies the body verbatim \u2014 pass an object for JSON, a string for raw text. The idempotency key is forwarded as the `Idempotency-Key` header; receivers that honour it (Stripe, Square, many SaaS APIs) dedupe automatically.",
|
|
14092
|
+
parameters: {
|
|
14093
|
+
type: "object",
|
|
14094
|
+
properties: {
|
|
14095
|
+
url: { type: "string", description: "Absolute http(s) URL to call." },
|
|
14096
|
+
method: {
|
|
14097
|
+
type: "string",
|
|
14098
|
+
enum: ["POST", "PUT", "PATCH", "DELETE"],
|
|
14099
|
+
description: "HTTP verb. Defaults to POST."
|
|
14100
|
+
},
|
|
14101
|
+
headers: {
|
|
14102
|
+
type: "object",
|
|
14103
|
+
description: "Optional request headers. Header names are lower-cased before send.",
|
|
14104
|
+
additionalProperties: { type: "string" }
|
|
14105
|
+
},
|
|
14106
|
+
query: {
|
|
14107
|
+
type: "object",
|
|
14108
|
+
description: "Optional query-string parameters appended to the URL.",
|
|
14109
|
+
additionalProperties: true
|
|
14110
|
+
},
|
|
14111
|
+
body: {
|
|
14112
|
+
description: "Request body. Objects are JSON-encoded with `content-type: application/json`; strings are sent verbatim with the caller-supplied content-type (defaulting to text/plain)."
|
|
14113
|
+
},
|
|
14114
|
+
timeoutMs: {
|
|
14115
|
+
type: "number",
|
|
14116
|
+
description: `Per-request timeout in milliseconds. Defaults to ${DEFAULT_TIMEOUT_MS}, capped at ${MAX_TIMEOUT_MS}.`
|
|
14117
|
+
}
|
|
14118
|
+
},
|
|
14119
|
+
required: ["url"]
|
|
14120
|
+
},
|
|
14121
|
+
cas: "none",
|
|
14122
|
+
externalEffect: true
|
|
14123
|
+
}
|
|
14124
|
+
]
|
|
14125
|
+
},
|
|
14126
|
+
async executeRead(inv) {
|
|
14127
|
+
const args = inv.args ?? {};
|
|
14128
|
+
const method = readMethod(args.method, "GET", READ_METHODS, "request.fetch");
|
|
14129
|
+
const url = buildUrl(readUrl(args.url), args.query);
|
|
14130
|
+
const headers = mergeHeaders(args.headers, inv.idempotencyKey, false, void 0);
|
|
14131
|
+
const res = await fetch(url.toString(), {
|
|
14132
|
+
method,
|
|
14133
|
+
headers,
|
|
14134
|
+
signal: AbortSignal.timeout(readTimeout(args.timeoutMs))
|
|
14135
|
+
});
|
|
14136
|
+
const data = await parseResponse(res, method);
|
|
14137
|
+
if (!res.ok) {
|
|
14138
|
+
throw new Error(`http ${method} ${url.toString()} failed: ${res.status} ${truncate(stringify(data), 200)}`);
|
|
14139
|
+
}
|
|
14140
|
+
return {
|
|
14141
|
+
data,
|
|
14142
|
+
etag: res.headers.get("etag") ?? void 0,
|
|
14143
|
+
fetchedAt: Date.now()
|
|
14144
|
+
};
|
|
14145
|
+
},
|
|
14146
|
+
async executeMutation(inv) {
|
|
14147
|
+
const args = inv.args ?? {};
|
|
14148
|
+
const method = readMethod(args.method, "POST", MUTATION_METHODS, "request.send");
|
|
14149
|
+
const url = buildUrl(readUrl(args.url), args.query);
|
|
14150
|
+
const { body, contentType } = encodeBody(args.body);
|
|
14151
|
+
const headers = mergeHeaders(args.headers, inv.idempotencyKey, true, contentType);
|
|
14152
|
+
const res = await fetch(url.toString(), {
|
|
14153
|
+
method,
|
|
14154
|
+
headers,
|
|
14155
|
+
body,
|
|
14156
|
+
signal: AbortSignal.timeout(readTimeout(args.timeoutMs))
|
|
14157
|
+
});
|
|
14158
|
+
const data = await parseResponse(res, method);
|
|
14159
|
+
if (res.status === 409) {
|
|
14160
|
+
const message = typeof data === "object" && data !== null && "message" in data && typeof data.message === "string" ? data.message : `http ${method} ${url.toString()} returned 409`;
|
|
14161
|
+
const alternatives = typeof data === "object" && data !== null && Array.isArray(data.alternatives) ? data.alternatives : [];
|
|
14162
|
+
return { status: "conflict", alternatives, message, currentState: data };
|
|
14163
|
+
}
|
|
14164
|
+
if (res.status === 429) {
|
|
14165
|
+
const retryAfter = parseRetryAfterMs(res.headers.get("retry-after"));
|
|
14166
|
+
return {
|
|
14167
|
+
status: "rate-limited",
|
|
14168
|
+
retryAfterMs: retryAfter,
|
|
14169
|
+
message: `http ${method} ${url.toString()} rate-limited; retry after ${retryAfter}ms`
|
|
14170
|
+
};
|
|
14171
|
+
}
|
|
14172
|
+
if (!res.ok) {
|
|
14173
|
+
throw new Error(`http ${method} ${url.toString()} failed: ${res.status} ${truncate(stringify(data), 200)}`);
|
|
14174
|
+
}
|
|
14175
|
+
return {
|
|
14176
|
+
status: "committed",
|
|
14177
|
+
data,
|
|
14178
|
+
etagAfter: res.headers.get("etag") ?? void 0,
|
|
14179
|
+
committedAt: Date.now(),
|
|
14180
|
+
idempotentReplay: false
|
|
14181
|
+
};
|
|
14182
|
+
},
|
|
14183
|
+
async test() {
|
|
14184
|
+
return { ok: true };
|
|
14185
|
+
}
|
|
14186
|
+
};
|
|
14187
|
+
function readUrl(value) {
|
|
14188
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
14189
|
+
throw new Error("http.url is required");
|
|
14190
|
+
}
|
|
14191
|
+
let parsed;
|
|
14192
|
+
try {
|
|
14193
|
+
parsed = new URL(value);
|
|
14194
|
+
} catch {
|
|
14195
|
+
throw new Error(`http.url is not a valid absolute URL: ${value}`);
|
|
14196
|
+
}
|
|
14197
|
+
if (!ALLOWED_SCHEMES.has(parsed.protocol)) {
|
|
14198
|
+
throw new Error(`http.url scheme not allowed: ${parsed.protocol} (only http: and https: are accepted)`);
|
|
14199
|
+
}
|
|
14200
|
+
assertPublicHttpTarget(parsed, "http.url");
|
|
14201
|
+
return parsed;
|
|
14202
|
+
}
|
|
14203
|
+
function readMethod(value, fallback, allowed, capability) {
|
|
14204
|
+
if (value === void 0 || value === null) return fallback;
|
|
14205
|
+
if (typeof value !== "string") {
|
|
14206
|
+
throw new Error(`http.method must be a string for ${capability}`);
|
|
14207
|
+
}
|
|
14208
|
+
const upper = value.toUpperCase();
|
|
14209
|
+
if (!allowed.has(upper)) {
|
|
14210
|
+
throw new Error(
|
|
14211
|
+
`http.method ${upper} not allowed for ${capability} (allowed: ${[...allowed].sort().join(", ")})`
|
|
14212
|
+
);
|
|
14213
|
+
}
|
|
14214
|
+
return upper;
|
|
14215
|
+
}
|
|
14216
|
+
function readTimeout(value) {
|
|
14217
|
+
if (value === void 0 || value === null) return DEFAULT_TIMEOUT_MS;
|
|
14218
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
|
|
14219
|
+
throw new Error("http.timeoutMs must be a positive finite number");
|
|
14220
|
+
}
|
|
14221
|
+
return Math.min(Math.floor(value), MAX_TIMEOUT_MS);
|
|
14222
|
+
}
|
|
14223
|
+
function buildUrl(base, query) {
|
|
14224
|
+
if (query === void 0 || query === null) return base;
|
|
14225
|
+
if (typeof query !== "object") {
|
|
14226
|
+
throw new Error("http.query must be an object of string/number/boolean values (or arrays of those)");
|
|
14227
|
+
}
|
|
14228
|
+
const url = new URL(base.toString());
|
|
14229
|
+
for (const [key, raw] of Object.entries(query)) {
|
|
14230
|
+
if (raw === void 0 || raw === null) continue;
|
|
14231
|
+
if (Array.isArray(raw)) {
|
|
14232
|
+
for (const entry of raw) url.searchParams.append(key, scalarToString(entry, key));
|
|
14233
|
+
continue;
|
|
14234
|
+
}
|
|
14235
|
+
url.searchParams.set(key, scalarToString(raw, key));
|
|
14236
|
+
}
|
|
14237
|
+
return url;
|
|
14238
|
+
}
|
|
14239
|
+
function scalarToString(value, key) {
|
|
14240
|
+
if (typeof value === "string") return value;
|
|
14241
|
+
if (typeof value === "number" || typeof value === "boolean") return String(value);
|
|
14242
|
+
throw new Error(`http.query.${key} must be string, number, boolean, or an array of those`);
|
|
14243
|
+
}
|
|
14244
|
+
function mergeHeaders(raw, idempotencyKey, isMutation, bodyContentType) {
|
|
14245
|
+
const headers = new Headers();
|
|
14246
|
+
headers.set("accept", "application/json, */*;q=0.1");
|
|
14247
|
+
if (raw !== void 0 && raw !== null) {
|
|
14248
|
+
if (typeof raw !== "object") {
|
|
14249
|
+
throw new Error("http.headers must be an object of string values");
|
|
14250
|
+
}
|
|
14251
|
+
for (const [name, value] of Object.entries(raw)) {
|
|
14252
|
+
if (value === void 0 || value === null) continue;
|
|
14253
|
+
if (typeof value !== "string") {
|
|
14254
|
+
throw new Error(`http.headers.${name} must be a string`);
|
|
14255
|
+
}
|
|
14256
|
+
headers.set(name.toLowerCase(), value);
|
|
14257
|
+
}
|
|
14258
|
+
}
|
|
14259
|
+
if (isMutation) {
|
|
14260
|
+
if (bodyContentType && !headers.has("content-type")) {
|
|
14261
|
+
headers.set("content-type", bodyContentType);
|
|
14262
|
+
}
|
|
14263
|
+
if (!headers.has("idempotency-key")) {
|
|
14264
|
+
headers.set("idempotency-key", idempotencyKey);
|
|
14265
|
+
}
|
|
14266
|
+
}
|
|
14267
|
+
return headers;
|
|
14268
|
+
}
|
|
14269
|
+
function encodeBody(raw) {
|
|
14270
|
+
if (raw === void 0 || raw === null) return { body: void 0, contentType: void 0 };
|
|
14271
|
+
if (typeof raw === "string") return { body: raw, contentType: "text/plain;charset=utf-8" };
|
|
14272
|
+
if (typeof raw === "number" || typeof raw === "boolean") {
|
|
14273
|
+
return { body: String(raw), contentType: "text/plain;charset=utf-8" };
|
|
14274
|
+
}
|
|
14275
|
+
if (raw instanceof ArrayBuffer) return { body: raw, contentType: "application/octet-stream" };
|
|
14276
|
+
if (typeof raw === "object") {
|
|
14277
|
+
return { body: JSON.stringify(raw), contentType: "application/json" };
|
|
14278
|
+
}
|
|
14279
|
+
throw new Error(`http.body must be string, number, boolean, object, or ArrayBuffer (got ${typeof raw})`);
|
|
14280
|
+
}
|
|
14281
|
+
async function parseResponse(res, method) {
|
|
14282
|
+
if (method === "HEAD") return null;
|
|
14283
|
+
const contentType = res.headers.get("content-type") ?? "";
|
|
14284
|
+
if (contentType.includes("application/json") || contentType.includes("+json")) {
|
|
14285
|
+
const text = await res.text();
|
|
14286
|
+
if (text.length === 0) return null;
|
|
14287
|
+
try {
|
|
14288
|
+
return JSON.parse(text);
|
|
14289
|
+
} catch {
|
|
14290
|
+
return text;
|
|
14291
|
+
}
|
|
14292
|
+
}
|
|
14293
|
+
return await res.text();
|
|
14294
|
+
}
|
|
14295
|
+
function parseRetryAfterMs(header2) {
|
|
14296
|
+
if (!header2) return 1e3;
|
|
14297
|
+
const seconds = Number(header2);
|
|
14298
|
+
if (Number.isFinite(seconds) && seconds >= 0) return Math.floor(seconds * 1e3);
|
|
14299
|
+
const date = Date.parse(header2);
|
|
14300
|
+
if (!Number.isFinite(date)) return 1e3;
|
|
14301
|
+
return Math.max(0, date - Date.now());
|
|
14302
|
+
}
|
|
14303
|
+
function stringify(value) {
|
|
14304
|
+
if (typeof value === "string") return value;
|
|
14305
|
+
try {
|
|
14306
|
+
return JSON.stringify(value);
|
|
14307
|
+
} catch {
|
|
14308
|
+
return String(value);
|
|
14309
|
+
}
|
|
14310
|
+
}
|
|
14311
|
+
function truncate(value, limit) {
|
|
14312
|
+
return value.length > limit ? `${value.slice(0, limit)}\u2026` : value;
|
|
14313
|
+
}
|
|
14314
|
+
|
|
14315
|
+
// src/connectors/adapters/rss.ts
|
|
14316
|
+
var ALLOWED_SCHEMES2 = /* @__PURE__ */ new Set(["http:", "https:"]);
|
|
14317
|
+
var DEFAULT_LIMIT = 20;
|
|
14318
|
+
var MAX_LIMIT = 200;
|
|
14319
|
+
var DEFAULT_TIMEOUT_MS2 = 15e3;
|
|
14320
|
+
var MAX_BODY_BYTES = 5 * 1024 * 1024;
|
|
14321
|
+
var READ_CAPABILITIES = [
|
|
14322
|
+
{
|
|
14323
|
+
name: "feed.fetch",
|
|
14324
|
+
class: "read",
|
|
14325
|
+
description: "Fetch and parse the RSS/Atom feed URL pinned in DataSource.metadata.feedUrl. Returns normalized entries newest-first. Forwards the upstream ETag/Last-Modified so downstream conditional reads can avoid re-parsing unchanged feeds.",
|
|
14326
|
+
parameters: {
|
|
14327
|
+
type: "object",
|
|
14328
|
+
properties: {
|
|
14329
|
+
limit: {
|
|
14330
|
+
type: "number",
|
|
14331
|
+
description: `Maximum entries to return, newest first. Defaults to ${DEFAULT_LIMIT}, capped at ${MAX_LIMIT}.`
|
|
14332
|
+
},
|
|
14333
|
+
since: {
|
|
14334
|
+
type: "string",
|
|
14335
|
+
description: "ISO-8601 timestamp. When set, entries with `published` (or `updated` for Atom) strictly older than this are dropped."
|
|
14336
|
+
}
|
|
14337
|
+
}
|
|
14338
|
+
}
|
|
14339
|
+
},
|
|
14340
|
+
{
|
|
14341
|
+
name: "feed.lookup",
|
|
14342
|
+
class: "read",
|
|
14343
|
+
description: "Fetch and parse an arbitrary RSS/Atom feed URL the agent constructs at request time (e.g. search-result feeds, comment streams). Same normalization as `feed.fetch`.",
|
|
14344
|
+
parameters: {
|
|
14345
|
+
type: "object",
|
|
14346
|
+
properties: {
|
|
14347
|
+
url: { type: "string", description: "Absolute http(s) URL of the feed to fetch." },
|
|
14348
|
+
limit: {
|
|
14349
|
+
type: "number",
|
|
14350
|
+
description: `Maximum entries to return, newest first. Defaults to ${DEFAULT_LIMIT}, capped at ${MAX_LIMIT}.`
|
|
14351
|
+
},
|
|
14352
|
+
since: {
|
|
14353
|
+
type: "string",
|
|
14354
|
+
description: "ISO-8601 timestamp. When set, entries with `published` (or `updated` for Atom) strictly older than this are dropped."
|
|
14355
|
+
}
|
|
14356
|
+
},
|
|
14357
|
+
required: ["url"]
|
|
14358
|
+
}
|
|
14359
|
+
}
|
|
14360
|
+
];
|
|
14361
|
+
var rssConnector = {
|
|
14362
|
+
manifest: {
|
|
14363
|
+
kind: "rss",
|
|
14364
|
+
displayName: "RSS / Atom Feed",
|
|
14365
|
+
description: "Pull entries from any public RSS 2.0 or Atom 1.0 feed. No auth required \u2014 the operator pins one feed URL at connect time (`feed.fetch`), and the agent can also resolve ad-hoc feed URLs at request time (`feed.lookup`). The connector parses both formats and emits a normalized entry shape so downstream tools do not have to branch on the feed dialect.",
|
|
14366
|
+
auth: { kind: "none" },
|
|
14367
|
+
category: "webhook",
|
|
14368
|
+
defaultConsistencyModel: "cache",
|
|
14369
|
+
capabilities: READ_CAPABILITIES
|
|
14370
|
+
},
|
|
14371
|
+
async executeRead(inv) {
|
|
14372
|
+
const args = inv.args ?? {};
|
|
14373
|
+
const url = inv.capabilityName === "feed.lookup" ? readUrl2(args.url, "feed.lookup.url") : readUrl2(readPinnedFeedUrl(inv.source), "DataSource.metadata.feedUrl");
|
|
14374
|
+
const limit = clampLimit2(args.limit);
|
|
14375
|
+
const since = readSinceMs(args.since);
|
|
14376
|
+
const res = await fetch(url.toString(), {
|
|
14377
|
+
method: "GET",
|
|
14378
|
+
headers: {
|
|
14379
|
+
accept: "application/rss+xml, application/atom+xml, application/xml;q=0.9, text/xml;q=0.8, */*;q=0.1",
|
|
14380
|
+
"user-agent": "tangle-agent-integrations-rss/1.0"
|
|
14381
|
+
},
|
|
14382
|
+
signal: AbortSignal.timeout(DEFAULT_TIMEOUT_MS2)
|
|
14383
|
+
});
|
|
14384
|
+
if (!res.ok) {
|
|
14385
|
+
throw new Error(`rss fetch ${res.status} ${res.statusText} for ${url.toString()}`);
|
|
14386
|
+
}
|
|
14387
|
+
const body = await readBoundedText(res, MAX_BODY_BYTES);
|
|
14388
|
+
const parsed = parseFeed(body, url.toString());
|
|
14389
|
+
const filtered = filterAndLimit(parsed.entries, since, limit);
|
|
14390
|
+
const data = {
|
|
14391
|
+
feedTitle: parsed.feedTitle,
|
|
14392
|
+
feedUrl: url.toString(),
|
|
14393
|
+
feedUpdated: parsed.feedUpdated,
|
|
14394
|
+
entries: filtered,
|
|
14395
|
+
format: parsed.format
|
|
14396
|
+
};
|
|
14397
|
+
return {
|
|
14398
|
+
data,
|
|
14399
|
+
etag: res.headers.get("etag") ?? res.headers.get("last-modified") ?? void 0,
|
|
14400
|
+
fetchedAt: Date.now()
|
|
14401
|
+
};
|
|
14402
|
+
},
|
|
14403
|
+
async test(source) {
|
|
14404
|
+
const raw = source.metadata?.feedUrl;
|
|
14405
|
+
if (typeof raw !== "string" || raw.length === 0) {
|
|
14406
|
+
return { ok: true };
|
|
14407
|
+
}
|
|
14408
|
+
let url;
|
|
14409
|
+
try {
|
|
14410
|
+
url = new URL(raw);
|
|
14411
|
+
} catch {
|
|
14412
|
+
return { ok: false, reason: `feedUrl is not a valid absolute URL: ${raw}` };
|
|
14413
|
+
}
|
|
14414
|
+
if (!ALLOWED_SCHEMES2.has(url.protocol)) {
|
|
14415
|
+
return { ok: false, reason: `feedUrl scheme not allowed: ${url.protocol}` };
|
|
14416
|
+
}
|
|
14417
|
+
try {
|
|
14418
|
+
const res = await fetch(url.toString(), {
|
|
14419
|
+
method: "HEAD",
|
|
14420
|
+
headers: { "user-agent": "tangle-agent-integrations-rss/1.0" },
|
|
14421
|
+
signal: AbortSignal.timeout(8e3)
|
|
14422
|
+
});
|
|
14423
|
+
if (res.status >= 500) return { ok: false, reason: `feedUrl returned ${res.status}` };
|
|
14424
|
+
return { ok: true };
|
|
14425
|
+
} catch (err) {
|
|
14426
|
+
return { ok: false, reason: err instanceof Error ? err.message : String(err) };
|
|
14427
|
+
}
|
|
14428
|
+
}
|
|
14429
|
+
};
|
|
14430
|
+
function readPinnedFeedUrl(source) {
|
|
14431
|
+
return source.metadata?.feedUrl;
|
|
14432
|
+
}
|
|
14433
|
+
function readUrl2(value, label) {
|
|
14434
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
14435
|
+
throw new Error(`${label} is required`);
|
|
14436
|
+
}
|
|
14437
|
+
let parsed;
|
|
14438
|
+
try {
|
|
14439
|
+
parsed = new URL(value);
|
|
14440
|
+
} catch {
|
|
14441
|
+
throw new Error(`${label} is not a valid absolute URL: ${value}`);
|
|
14442
|
+
}
|
|
14443
|
+
if (!ALLOWED_SCHEMES2.has(parsed.protocol)) {
|
|
14444
|
+
throw new Error(`${label} scheme not allowed: ${parsed.protocol} (only http: and https: are accepted)`);
|
|
14445
|
+
}
|
|
14446
|
+
assertPublicHttpTarget(parsed, label);
|
|
14447
|
+
return parsed;
|
|
14448
|
+
}
|
|
14449
|
+
function clampLimit2(value) {
|
|
14450
|
+
if (value === void 0 || value === null) return DEFAULT_LIMIT;
|
|
14451
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
|
|
14452
|
+
throw new Error("rss.limit must be a positive finite number");
|
|
14453
|
+
}
|
|
14454
|
+
return Math.min(Math.floor(value), MAX_LIMIT);
|
|
14455
|
+
}
|
|
14456
|
+
function readSinceMs(value) {
|
|
14457
|
+
if (value === void 0 || value === null) return null;
|
|
14458
|
+
if (typeof value !== "string") {
|
|
14459
|
+
throw new Error("rss.since must be an ISO-8601 string");
|
|
14460
|
+
}
|
|
14461
|
+
const ms = Date.parse(value);
|
|
14462
|
+
if (!Number.isFinite(ms)) {
|
|
14463
|
+
throw new Error(`rss.since is not a valid date: ${value}`);
|
|
14464
|
+
}
|
|
14465
|
+
return ms;
|
|
14466
|
+
}
|
|
14467
|
+
async function readBoundedText(res, maxBytes) {
|
|
14468
|
+
const reader = res.body?.getReader();
|
|
14469
|
+
if (!reader) return await res.text();
|
|
14470
|
+
const decoder = new TextDecoder("utf-8", { fatal: false });
|
|
14471
|
+
let out = "";
|
|
14472
|
+
let total = 0;
|
|
14473
|
+
while (true) {
|
|
14474
|
+
const { value, done } = await reader.read();
|
|
14475
|
+
if (done) break;
|
|
14476
|
+
if (!value) continue;
|
|
14477
|
+
total += value.byteLength;
|
|
14478
|
+
if (total > maxBytes) {
|
|
14479
|
+
try {
|
|
14480
|
+
await reader.cancel();
|
|
14481
|
+
} catch {
|
|
14482
|
+
}
|
|
14483
|
+
throw new Error(`rss feed body exceeded ${maxBytes} bytes`);
|
|
14484
|
+
}
|
|
14485
|
+
out += decoder.decode(value, { stream: true });
|
|
14486
|
+
}
|
|
14487
|
+
out += decoder.decode();
|
|
14488
|
+
return out;
|
|
14489
|
+
}
|
|
14490
|
+
function filterAndLimit(entries, sinceMs, limit) {
|
|
14491
|
+
let filtered = entries;
|
|
14492
|
+
if (sinceMs !== null) {
|
|
14493
|
+
filtered = entries.filter((entry) => {
|
|
14494
|
+
const ts = entry.published ?? entry.updated;
|
|
14495
|
+
if (!ts) return true;
|
|
14496
|
+
const ms = Date.parse(ts);
|
|
14497
|
+
if (!Number.isFinite(ms)) return true;
|
|
14498
|
+
return ms >= sinceMs;
|
|
14499
|
+
});
|
|
14500
|
+
}
|
|
14501
|
+
return filtered.slice(0, limit);
|
|
14502
|
+
}
|
|
14503
|
+
function parseFeed(body, feedUrl) {
|
|
14504
|
+
const text = body.replace(/^/, "").trimStart();
|
|
14505
|
+
const rssIdx = text.search(/<rss\b/i);
|
|
14506
|
+
const atomIdx = text.search(/<feed\b/i);
|
|
14507
|
+
if (rssIdx === -1 && atomIdx === -1) {
|
|
14508
|
+
return { feedTitle: null, feedUpdated: null, entries: [], format: "unknown" };
|
|
14509
|
+
}
|
|
14510
|
+
if (atomIdx !== -1 && (rssIdx === -1 || atomIdx < rssIdx)) {
|
|
14511
|
+
return parseAtom(text, feedUrl);
|
|
14512
|
+
}
|
|
14513
|
+
return parseRss(text);
|
|
14514
|
+
}
|
|
14515
|
+
function parseRss(text) {
|
|
14516
|
+
const channelOuter = extractFirstElement(text, "channel");
|
|
14517
|
+
if (!channelOuter) {
|
|
14518
|
+
return { feedTitle: null, feedUpdated: null, entries: [], format: "rss" };
|
|
14519
|
+
}
|
|
14520
|
+
const channelInner = stripAllElements(channelOuter, "item");
|
|
14521
|
+
const feedTitle = decodeXml(firstTagText(channelInner, "title"));
|
|
14522
|
+
const items = collectElements(channelOuter, "item");
|
|
14523
|
+
const entries = items.map((item) => {
|
|
14524
|
+
const guid = firstTagText(item, "guid");
|
|
14525
|
+
const link = firstTagText(item, "link");
|
|
14526
|
+
const title = firstTagText(item, "title");
|
|
14527
|
+
const description = firstTagText(item, "description");
|
|
14528
|
+
const contentEncoded = firstTagText(item, "content:encoded");
|
|
14529
|
+
const pubDate = firstTagText(item, "pubDate");
|
|
14530
|
+
const author = firstTagText(item, "author") ?? firstTagText(item, "dc:creator");
|
|
14531
|
+
const categories = collectElements(item, "category").map((cat) => decodeXml(stripTags(cat)) ?? "").filter(Boolean);
|
|
14532
|
+
const id = decodeXml(guid) ?? decodeXml(link) ?? hash(item);
|
|
14533
|
+
return {
|
|
14534
|
+
id,
|
|
14535
|
+
title: decodeXml(title),
|
|
14536
|
+
link: decodeXml(link),
|
|
14537
|
+
summary: decodeXml(description),
|
|
14538
|
+
content: decodeXml(contentEncoded),
|
|
14539
|
+
published: normalizeDate(decodeXml(pubDate)),
|
|
14540
|
+
updated: null,
|
|
14541
|
+
author: decodeXml(author),
|
|
14542
|
+
categories
|
|
14543
|
+
};
|
|
14544
|
+
});
|
|
14545
|
+
return { feedTitle, feedUpdated: null, entries, format: "rss" };
|
|
14546
|
+
}
|
|
14547
|
+
function parseAtom(text, feedUrl) {
|
|
14548
|
+
const feedOuter = extractFirstElement(text, "feed") ?? text;
|
|
14549
|
+
const feedInner = stripAllElements(feedOuter, "entry");
|
|
14550
|
+
const feedTitle = decodeXml(firstTagText(feedInner, "title"));
|
|
14551
|
+
const feedUpdated = normalizeDate(decodeXml(firstTagText(feedInner, "updated")));
|
|
14552
|
+
const items = collectElements(feedOuter, "entry");
|
|
14553
|
+
const entries = items.map((item) => {
|
|
14554
|
+
const id = decodeXml(firstTagText(item, "id"));
|
|
14555
|
+
const title = decodeXml(firstTagText(item, "title"));
|
|
14556
|
+
const summary = decodeXml(firstTagText(item, "summary"));
|
|
14557
|
+
const contentNode = firstTagText(item, "content");
|
|
14558
|
+
const published = normalizeDate(decodeXml(firstTagText(item, "published")));
|
|
14559
|
+
const updated = normalizeDate(decodeXml(firstTagText(item, "updated")));
|
|
14560
|
+
const author = decodeXml(firstTagText(extractFirstElement(item, "author") ?? "", "name")) ?? decodeXml(firstTagText(item, "author"));
|
|
14561
|
+
const link = pickAtomLink(item);
|
|
14562
|
+
const categories = collectAtomCategories(item);
|
|
14563
|
+
return {
|
|
14564
|
+
id: id ?? link ?? hash(item),
|
|
14565
|
+
title,
|
|
14566
|
+
link,
|
|
14567
|
+
summary,
|
|
14568
|
+
content: decodeXml(contentNode),
|
|
14569
|
+
published,
|
|
14570
|
+
updated,
|
|
14571
|
+
author,
|
|
14572
|
+
categories
|
|
14573
|
+
};
|
|
14574
|
+
});
|
|
14575
|
+
return { feedTitle, feedUpdated, entries, format: "atom" };
|
|
14576
|
+
}
|
|
14577
|
+
function extractFirstElement(text, tag) {
|
|
14578
|
+
const escaped = escapeRegex(tag);
|
|
14579
|
+
const openRe = new RegExp(`<${escaped}\\b([^>]*)>`, "i");
|
|
14580
|
+
const m = openRe.exec(text);
|
|
14581
|
+
if (!m) return null;
|
|
14582
|
+
const openEnd = m.index + m[0].length;
|
|
14583
|
+
if (m[0].endsWith("/>")) return m[0];
|
|
14584
|
+
const closeRe = new RegExp(`</${escaped}\\s*>`, "gi");
|
|
14585
|
+
closeRe.lastIndex = openEnd;
|
|
14586
|
+
const close = closeRe.exec(text);
|
|
14587
|
+
if (!close) return text.slice(m.index);
|
|
14588
|
+
return text.slice(m.index, close.index + close[0].length);
|
|
14589
|
+
}
|
|
14590
|
+
function collectElements(text, tag) {
|
|
14591
|
+
const escaped = escapeRegex(tag);
|
|
14592
|
+
const out = [];
|
|
14593
|
+
const openRe = new RegExp(`<${escaped}\\b([^>]*)>`, "gi");
|
|
14594
|
+
let m;
|
|
14595
|
+
while ((m = openRe.exec(text)) !== null) {
|
|
14596
|
+
const start = m.index;
|
|
14597
|
+
if (m[0].endsWith("/>")) {
|
|
14598
|
+
out.push(m[0]);
|
|
14599
|
+
continue;
|
|
14600
|
+
}
|
|
14601
|
+
const after = m.index + m[0].length;
|
|
14602
|
+
const closeRe = new RegExp(`</${escaped}\\s*>`, "gi");
|
|
14603
|
+
closeRe.lastIndex = after;
|
|
14604
|
+
const close = closeRe.exec(text);
|
|
14605
|
+
if (!close) break;
|
|
14606
|
+
out.push(text.slice(start, close.index + close[0].length));
|
|
14607
|
+
openRe.lastIndex = close.index + close[0].length;
|
|
14608
|
+
}
|
|
14609
|
+
return out;
|
|
14610
|
+
}
|
|
14611
|
+
function stripAllElements(text, tag) {
|
|
14612
|
+
const escaped = escapeRegex(tag);
|
|
14613
|
+
let out = text;
|
|
14614
|
+
const re = new RegExp(`<${escaped}\\b[^>]*>[\\s\\S]*?</${escaped}\\s*>`, "gi");
|
|
14615
|
+
out = out.replace(re, "");
|
|
14616
|
+
const selfRe = new RegExp(`<${escaped}\\b[^>]*/>`, "gi");
|
|
14617
|
+
out = out.replace(selfRe, "");
|
|
14618
|
+
return out;
|
|
14619
|
+
}
|
|
14620
|
+
function firstTagText(text, tag) {
|
|
14621
|
+
const escaped = escapeRegex(tag);
|
|
14622
|
+
const re = new RegExp(`<${escaped}\\b([^>]*)>([\\s\\S]*?)</${escaped}\\s*>`, "i");
|
|
14623
|
+
const m = re.exec(text);
|
|
14624
|
+
if (m) return unwrapCdata(m[2]);
|
|
14625
|
+
const selfRe = new RegExp(`<${escaped}\\b([^>]*)/>`, "i");
|
|
14626
|
+
const sm = selfRe.exec(text);
|
|
14627
|
+
if (sm) return null;
|
|
14628
|
+
return null;
|
|
14629
|
+
}
|
|
14630
|
+
function pickAtomLink(entryOuter) {
|
|
14631
|
+
const linkRe = /<link\b([^>]*)\/?>(?:([\s\S]*?)<\/link\s*>)?/gi;
|
|
14632
|
+
let bestHref = null;
|
|
14633
|
+
let fallback = null;
|
|
14634
|
+
let m;
|
|
14635
|
+
while ((m = linkRe.exec(entryOuter)) !== null) {
|
|
14636
|
+
const attrs = m[1] ?? "";
|
|
14637
|
+
const href = readAttr(attrs, "href");
|
|
14638
|
+
if (!href) continue;
|
|
14639
|
+
const rel = readAttr(attrs, "rel");
|
|
14640
|
+
if (!fallback) fallback = href;
|
|
14641
|
+
if (!rel || rel === "alternate") {
|
|
14642
|
+
bestHref = href;
|
|
14643
|
+
break;
|
|
14644
|
+
}
|
|
14645
|
+
}
|
|
14646
|
+
return bestHref ?? fallback;
|
|
14647
|
+
}
|
|
14648
|
+
function collectAtomCategories(entryOuter) {
|
|
14649
|
+
const out = [];
|
|
14650
|
+
const re = /<category\b([^>]*)(?:\/>|>([\s\S]*?)<\/category\s*>)/gi;
|
|
14651
|
+
let m;
|
|
14652
|
+
while ((m = re.exec(entryOuter)) !== null) {
|
|
14653
|
+
const term = readAttr(m[1] ?? "", "term");
|
|
14654
|
+
if (term) out.push(decodeXml(term) ?? "");
|
|
14655
|
+
else if (m[2]) {
|
|
14656
|
+
const inner = decodeXml(stripTags(m[2]));
|
|
14657
|
+
if (inner) out.push(inner);
|
|
14658
|
+
}
|
|
14659
|
+
}
|
|
14660
|
+
return out.filter(Boolean);
|
|
14661
|
+
}
|
|
14662
|
+
function readAttr(attrs, name) {
|
|
14663
|
+
const re = new RegExp(`\\b${escapeRegex(name)}\\s*=\\s*("([^"]*)"|'([^']*)')`, "i");
|
|
14664
|
+
const m = re.exec(attrs);
|
|
14665
|
+
if (!m) return null;
|
|
14666
|
+
return m[2] ?? m[3] ?? null;
|
|
14667
|
+
}
|
|
14668
|
+
function stripTags(value) {
|
|
14669
|
+
return value.replace(/<[^>]*>/g, "");
|
|
14670
|
+
}
|
|
14671
|
+
function unwrapCdata(value) {
|
|
14672
|
+
const cdata = /<!\[CDATA\[([\s\S]*?)\]\]>/g;
|
|
14673
|
+
let out = "";
|
|
14674
|
+
let lastIdx = 0;
|
|
14675
|
+
let m;
|
|
14676
|
+
while ((m = cdata.exec(value)) !== null) {
|
|
14677
|
+
out += value.slice(lastIdx, m.index);
|
|
14678
|
+
out += m[1];
|
|
14679
|
+
lastIdx = m.index + m[0].length;
|
|
14680
|
+
}
|
|
14681
|
+
out += value.slice(lastIdx);
|
|
14682
|
+
return out;
|
|
14683
|
+
}
|
|
14684
|
+
function decodeXml(value) {
|
|
14685
|
+
if (value === null) return null;
|
|
14686
|
+
const trimmed = value.trim();
|
|
14687
|
+
if (trimmed.length === 0) return null;
|
|
14688
|
+
return trimmed.replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'").replace(/&#(\d+);/g, (_, d) => {
|
|
14689
|
+
const code = Number(d);
|
|
14690
|
+
return Number.isFinite(code) ? String.fromCodePoint(code) : _;
|
|
14691
|
+
}).replace(/&#x([0-9a-fA-F]+);/g, (_, h) => {
|
|
14692
|
+
const code = parseInt(h, 16);
|
|
14693
|
+
return Number.isFinite(code) ? String.fromCodePoint(code) : _;
|
|
14694
|
+
}).replace(/&/g, "&");
|
|
14695
|
+
}
|
|
14696
|
+
function normalizeDate(value) {
|
|
14697
|
+
if (!value) return null;
|
|
14698
|
+
const ms = Date.parse(value);
|
|
14699
|
+
if (!Number.isFinite(ms)) return null;
|
|
14700
|
+
return new Date(ms).toISOString();
|
|
14701
|
+
}
|
|
14702
|
+
function escapeRegex(value) {
|
|
14703
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
14704
|
+
}
|
|
14705
|
+
function hash(value) {
|
|
14706
|
+
let h = 2166136261;
|
|
14707
|
+
for (let i = 0; i < value.length; i++) {
|
|
14708
|
+
h ^= value.charCodeAt(i);
|
|
14709
|
+
h = h + ((h << 1) + (h << 4) + (h << 7) + (h << 8) + (h << 24)) >>> 0;
|
|
14710
|
+
}
|
|
14711
|
+
return `rss-${h.toString(16).padStart(8, "0")}`;
|
|
14712
|
+
}
|
|
14713
|
+
|
|
14714
|
+
// src/connectors/adapters/amazon-s3.ts
|
|
14715
|
+
var amazonS3Connector = declarativeRestConnector({
|
|
14716
|
+
kind: "amazon-s3",
|
|
14717
|
+
displayName: "Amazon S3",
|
|
14718
|
+
description: "Scalable storage in the cloud. Read, upload, delete, and manage files in S3 buckets.",
|
|
14719
|
+
auth: {
|
|
14720
|
+
kind: "api-key",
|
|
14721
|
+
hint: 'AWS credentials as JSON: {"accessKeyId":"AKIA\u2026","secretAccessKey":"\u2026","region":"us-east-1"} for an IAM principal with S3 permissions. Optional "sessionToken" and "endpoint" (S3-compatible stores). Requests are signed with AWS Signature V4; the region selects the s3.<region>.amazonaws.com endpoint.'
|
|
14722
|
+
},
|
|
14723
|
+
category: "storage",
|
|
14724
|
+
defaultConsistencyModel: "authoritative",
|
|
14725
|
+
// S3 REST API, path-style. Each request is signed with AWS Signature V4
|
|
14726
|
+
// (service `s3`, which signs the request path verbatim); the bundle's region
|
|
14727
|
+
// is substituted into the `{region}` host template.
|
|
14728
|
+
credentialPlacement: { kind: "aws-sigv4", service: "s3" },
|
|
14729
|
+
baseUrl: "https://s3.{region}.amazonaws.com",
|
|
14730
|
+
test: { method: "GET", path: "/" },
|
|
14731
|
+
capabilities: [
|
|
14732
|
+
{
|
|
14733
|
+
name: "files.list",
|
|
14734
|
+
class: "read",
|
|
14735
|
+
description: "List files in an S3 bucket folder.",
|
|
14736
|
+
parameters: {
|
|
14737
|
+
type: "object",
|
|
14738
|
+
properties: {
|
|
14739
|
+
prefix: { type: "string", description: "Folder path to filter results (e.g., docs/)" },
|
|
14740
|
+
maxKeys: { type: "integer", description: "Maximum number of files to return (1\u20131000)" }
|
|
14741
|
+
},
|
|
14742
|
+
required: []
|
|
14743
|
+
},
|
|
14744
|
+
request: {
|
|
14745
|
+
method: "GET",
|
|
14746
|
+
path: "/",
|
|
14747
|
+
query: { prefix: "{prefix}", "max-keys": "{maxKeys}" }
|
|
14748
|
+
}
|
|
14749
|
+
},
|
|
14750
|
+
{
|
|
14751
|
+
name: "files.read",
|
|
14752
|
+
class: "read",
|
|
14753
|
+
description: "Read a file from S3.",
|
|
14754
|
+
parameters: {
|
|
14755
|
+
type: "object",
|
|
14756
|
+
properties: {
|
|
14757
|
+
key: { type: "string", description: "The full path to the file in S3" }
|
|
14758
|
+
},
|
|
14759
|
+
required: ["key"]
|
|
14760
|
+
},
|
|
14761
|
+
request: {
|
|
14762
|
+
method: "GET",
|
|
14763
|
+
path: "/{key}"
|
|
14764
|
+
}
|
|
14765
|
+
},
|
|
14766
|
+
{
|
|
14767
|
+
name: "files.upload",
|
|
14768
|
+
class: "mutation",
|
|
14769
|
+
description: "Upload a file to S3.",
|
|
14770
|
+
parameters: {
|
|
14771
|
+
type: "object",
|
|
14772
|
+
properties: {
|
|
14773
|
+
key: { type: "string", description: "The file path and name in S3" },
|
|
14774
|
+
contentType: { type: "string", description: "MIME type of the file" }
|
|
14775
|
+
},
|
|
14776
|
+
required: ["key"]
|
|
14777
|
+
},
|
|
14778
|
+
request: {
|
|
14779
|
+
method: "PUT",
|
|
14780
|
+
path: "/{key}",
|
|
14781
|
+
headers: { "Content-Type": "{contentType}" }
|
|
14782
|
+
},
|
|
14783
|
+
cas: "native-idempotency"
|
|
14784
|
+
},
|
|
14785
|
+
{
|
|
14786
|
+
name: "files.delete",
|
|
14787
|
+
class: "mutation",
|
|
14788
|
+
description: "Delete a file from S3.",
|
|
14789
|
+
parameters: {
|
|
14790
|
+
type: "object",
|
|
14791
|
+
properties: {
|
|
14792
|
+
key: { type: "string", description: "The full path to the file to delete" }
|
|
14793
|
+
},
|
|
14794
|
+
required: ["key"]
|
|
14795
|
+
},
|
|
14796
|
+
request: {
|
|
14797
|
+
method: "DELETE",
|
|
14798
|
+
path: "/{key}"
|
|
14799
|
+
},
|
|
14800
|
+
cas: "optimistic-read-verify"
|
|
14801
|
+
},
|
|
14802
|
+
{
|
|
14803
|
+
name: "files.generateSignedUrl",
|
|
14804
|
+
class: "read",
|
|
14805
|
+
description: "Generate a signed URL for temporary access to a file.",
|
|
14806
|
+
parameters: {
|
|
14807
|
+
type: "object",
|
|
14808
|
+
properties: {
|
|
14809
|
+
key: { type: "string", description: "The file path in S3" },
|
|
14810
|
+
expiresIn: { type: "integer", description: "URL validity duration in minutes" }
|
|
14811
|
+
},
|
|
14812
|
+
required: ["key", "expiresIn"]
|
|
14813
|
+
},
|
|
14814
|
+
request: {
|
|
14815
|
+
method: "GET",
|
|
14816
|
+
path: "/{key}",
|
|
14817
|
+
query: { "X-Amz-Expires": "{expiresIn}" }
|
|
14818
|
+
}
|
|
14819
|
+
},
|
|
14820
|
+
{
|
|
14821
|
+
name: "files.moveFile",
|
|
14822
|
+
class: "mutation",
|
|
14823
|
+
description: "Move a file to a different location in S3.",
|
|
14824
|
+
parameters: {
|
|
14825
|
+
type: "object",
|
|
14826
|
+
properties: {
|
|
14827
|
+
sourceKey: { type: "string", description: "Current file path" },
|
|
14828
|
+
destinationKey: { type: "string", description: "New file path" }
|
|
14829
|
+
},
|
|
14830
|
+
required: ["sourceKey", "destinationKey"]
|
|
14831
|
+
},
|
|
14832
|
+
request: {
|
|
14833
|
+
method: "PUT",
|
|
14834
|
+
path: "/{destinationKey}",
|
|
14835
|
+
headers: { "x-amz-copy-source": "{sourceKey}" }
|
|
14836
|
+
},
|
|
14837
|
+
cas: "optimistic-read-verify"
|
|
14838
|
+
},
|
|
14839
|
+
{
|
|
14840
|
+
name: "files.copyFile",
|
|
14841
|
+
class: "mutation",
|
|
14842
|
+
description: "Server-side copy of an object to a new key. Source is left in place.",
|
|
14843
|
+
parameters: {
|
|
14844
|
+
type: "object",
|
|
14845
|
+
properties: {
|
|
14846
|
+
sourceKey: {
|
|
14847
|
+
type: "string",
|
|
14848
|
+
description: "Existing object identifier as {bucket}/{key}."
|
|
14849
|
+
},
|
|
14850
|
+
destinationKey: {
|
|
14851
|
+
type: "string",
|
|
14852
|
+
description: "New object key (relative to the destination bucket)."
|
|
14853
|
+
}
|
|
14854
|
+
},
|
|
14855
|
+
required: ["sourceKey", "destinationKey"]
|
|
14856
|
+
},
|
|
14857
|
+
request: {
|
|
14858
|
+
method: "PUT",
|
|
14859
|
+
path: "/{destinationKey}",
|
|
14860
|
+
headers: { "x-amz-copy-source": "{sourceKey}" }
|
|
14861
|
+
},
|
|
14862
|
+
cas: "native-idempotency",
|
|
14863
|
+
externalEffect: true
|
|
14864
|
+
},
|
|
14865
|
+
{
|
|
14866
|
+
name: "files.setMetadata",
|
|
14867
|
+
class: "mutation",
|
|
14868
|
+
description: "Replace object metadata in place via the S3 copy-self pattern (x-amz-metadata-directive: REPLACE).",
|
|
14869
|
+
parameters: {
|
|
14870
|
+
type: "object",
|
|
14871
|
+
properties: {
|
|
14872
|
+
key: { type: "string", description: "Object key whose metadata should be replaced." },
|
|
14873
|
+
contentType: { type: "string", description: "New Content-Type for the object." },
|
|
14874
|
+
metadata: {
|
|
14875
|
+
type: "string",
|
|
14876
|
+
description: "Serialized x-amz-meta-* JSON forwarded as the x-amz-meta-user header (caller-controlled)."
|
|
14877
|
+
}
|
|
14878
|
+
},
|
|
14879
|
+
required: ["key"]
|
|
14880
|
+
},
|
|
14881
|
+
request: {
|
|
14882
|
+
method: "PUT",
|
|
14883
|
+
path: "/{key}",
|
|
14884
|
+
headers: {
|
|
14885
|
+
"x-amz-copy-source": "{key}",
|
|
14886
|
+
"x-amz-metadata-directive": "REPLACE",
|
|
14887
|
+
"Content-Type": "{contentType}",
|
|
14888
|
+
"x-amz-meta-user": "{metadata}"
|
|
14889
|
+
}
|
|
14890
|
+
},
|
|
14891
|
+
cas: "native-idempotency",
|
|
14892
|
+
externalEffect: true
|
|
14893
|
+
},
|
|
14894
|
+
{
|
|
14895
|
+
name: "files.createBucket",
|
|
14896
|
+
class: "mutation",
|
|
14897
|
+
description: "Create a new bucket in the configured region. Request is a PUT against the bucket name path.",
|
|
14898
|
+
parameters: {
|
|
14899
|
+
type: "object",
|
|
14900
|
+
properties: {
|
|
14901
|
+
bucket: { type: "string", description: "Bucket name to create." },
|
|
14902
|
+
region: {
|
|
14903
|
+
type: "string",
|
|
14904
|
+
description: "AWS region for the bucket (sent via x-amz-bucket-region)."
|
|
14905
|
+
}
|
|
14906
|
+
},
|
|
14907
|
+
required: ["bucket"]
|
|
14908
|
+
},
|
|
14909
|
+
request: {
|
|
14910
|
+
method: "PUT",
|
|
14911
|
+
path: "/{bucket}",
|
|
14912
|
+
headers: { "x-amz-bucket-region": "{region}" }
|
|
14913
|
+
},
|
|
14914
|
+
cas: "native-idempotency",
|
|
14915
|
+
externalEffect: true
|
|
14916
|
+
}
|
|
14917
|
+
]
|
|
14918
|
+
});
|
|
14919
|
+
|
|
14011
14920
|
// src/connectors/adapters/stripe-webhook-receiver.ts
|
|
14012
14921
|
var stripeWebhookReceiverConnector = {
|
|
14013
14922
|
manifest: {
|
|
@@ -93359,6 +94268,881 @@ var granolaConnector = declarativeRestConnector({
|
|
|
93359
94268
|
]
|
|
93360
94269
|
});
|
|
93361
94270
|
|
|
94271
|
+
// src/connectors/adapters/zoom.ts
|
|
94272
|
+
var zoomConnector = declarativeRestConnector({
|
|
94273
|
+
kind: "zoom",
|
|
94274
|
+
displayName: "Zoom",
|
|
94275
|
+
description: "Create and manage Zoom meetings, webinars, users, and cloud recordings via the Zoom API v2.",
|
|
94276
|
+
auth: {
|
|
94277
|
+
kind: "oauth2",
|
|
94278
|
+
authorizationUrl: "https://zoom.us/oauth/authorize",
|
|
94279
|
+
tokenUrl: "https://zoom.us/oauth/token",
|
|
94280
|
+
scopes: [
|
|
94281
|
+
"user:read:user",
|
|
94282
|
+
"user:write:user",
|
|
94283
|
+
"meeting:read:meeting",
|
|
94284
|
+
"meeting:write:meeting",
|
|
94285
|
+
"meeting:update:meeting",
|
|
94286
|
+
"meeting:delete:meeting",
|
|
94287
|
+
"webinar:read:webinar",
|
|
94288
|
+
"webinar:write:webinar",
|
|
94289
|
+
"webinar:update:webinar",
|
|
94290
|
+
"webinar:delete:webinar",
|
|
94291
|
+
"recording:read:recording",
|
|
94292
|
+
"recording:write:recording"
|
|
94293
|
+
],
|
|
94294
|
+
clientIdEnv: "ZOOM_OAUTH_CLIENT_ID",
|
|
94295
|
+
clientSecretEnv: "ZOOM_OAUTH_CLIENT_SECRET"
|
|
94296
|
+
},
|
|
94297
|
+
category: "calendar",
|
|
94298
|
+
defaultConsistencyModel: "authoritative",
|
|
94299
|
+
baseUrl: "https://api.zoom.us",
|
|
94300
|
+
test: { method: "GET", path: "/v2/users/me" },
|
|
94301
|
+
capabilities: [
|
|
94302
|
+
{
|
|
94303
|
+
name: "users.get",
|
|
94304
|
+
class: "read",
|
|
94305
|
+
description: 'Read a Zoom user by id, email, or the "me" alias for the authenticated user.',
|
|
94306
|
+
parameters: {
|
|
94307
|
+
type: "object",
|
|
94308
|
+
properties: {
|
|
94309
|
+
userId: { type: "string", description: 'User id, email address, or "me".' }
|
|
94310
|
+
},
|
|
94311
|
+
required: ["userId"]
|
|
94312
|
+
},
|
|
94313
|
+
request: { method: "GET", path: "/v2/users/{userId}" },
|
|
94314
|
+
requiredScopes: ["user:read:user"]
|
|
94315
|
+
},
|
|
94316
|
+
{
|
|
94317
|
+
name: "users.list",
|
|
94318
|
+
class: "read",
|
|
94319
|
+
description: "List users on the Zoom account.",
|
|
94320
|
+
parameters: {
|
|
94321
|
+
type: "object",
|
|
94322
|
+
properties: {
|
|
94323
|
+
status: { type: "string", enum: ["active", "inactive", "pending"] },
|
|
94324
|
+
page_size: { type: "integer", minimum: 1, maximum: 300 },
|
|
94325
|
+
next_page_token: { type: "string" },
|
|
94326
|
+
role_id: { type: "string" }
|
|
94327
|
+
}
|
|
94328
|
+
},
|
|
94329
|
+
request: {
|
|
94330
|
+
method: "GET",
|
|
94331
|
+
path: "/v2/users",
|
|
94332
|
+
query: {
|
|
94333
|
+
status: "{status}",
|
|
94334
|
+
page_size: "{page_size}",
|
|
94335
|
+
next_page_token: "{next_page_token}",
|
|
94336
|
+
role_id: "{role_id}"
|
|
94337
|
+
}
|
|
94338
|
+
},
|
|
94339
|
+
requiredScopes: ["user:read:user"]
|
|
94340
|
+
},
|
|
94341
|
+
{
|
|
94342
|
+
name: "meetings.list",
|
|
94343
|
+
class: "read",
|
|
94344
|
+
description: "List meetings for a user (scheduled, live, or upcoming).",
|
|
94345
|
+
parameters: {
|
|
94346
|
+
type: "object",
|
|
94347
|
+
properties: {
|
|
94348
|
+
userId: { type: "string", description: 'User id, email, or "me".' },
|
|
94349
|
+
type: {
|
|
94350
|
+
type: "string",
|
|
94351
|
+
enum: ["scheduled", "live", "upcoming", "upcoming_meetings", "previous_meetings"],
|
|
94352
|
+
description: "Subset of meetings to return; defaults to scheduled."
|
|
94353
|
+
},
|
|
94354
|
+
page_size: { type: "integer", minimum: 1, maximum: 300 },
|
|
94355
|
+
next_page_token: { type: "string" }
|
|
94356
|
+
},
|
|
94357
|
+
required: ["userId"]
|
|
94358
|
+
},
|
|
94359
|
+
request: {
|
|
94360
|
+
method: "GET",
|
|
94361
|
+
path: "/v2/users/{userId}/meetings",
|
|
94362
|
+
query: {
|
|
94363
|
+
type: "{type}",
|
|
94364
|
+
page_size: "{page_size}",
|
|
94365
|
+
next_page_token: "{next_page_token}"
|
|
94366
|
+
}
|
|
94367
|
+
},
|
|
94368
|
+
requiredScopes: ["meeting:read:meeting"]
|
|
94369
|
+
},
|
|
94370
|
+
{
|
|
94371
|
+
name: "meetings.get",
|
|
94372
|
+
class: "read",
|
|
94373
|
+
description: "Read a Zoom meeting by numeric meeting id.",
|
|
94374
|
+
parameters: {
|
|
94375
|
+
type: "object",
|
|
94376
|
+
properties: {
|
|
94377
|
+
meetingId: { type: "string", description: "Numeric Zoom meeting id." },
|
|
94378
|
+
occurrence_id: { type: "string", description: "Optional recurring-meeting occurrence id." }
|
|
94379
|
+
},
|
|
94380
|
+
required: ["meetingId"]
|
|
94381
|
+
},
|
|
94382
|
+
request: {
|
|
94383
|
+
method: "GET",
|
|
94384
|
+
path: "/v2/meetings/{meetingId}",
|
|
94385
|
+
query: { occurrence_id: "{occurrence_id}" }
|
|
94386
|
+
},
|
|
94387
|
+
requiredScopes: ["meeting:read:meeting"]
|
|
94388
|
+
},
|
|
94389
|
+
{
|
|
94390
|
+
name: "meetings.create",
|
|
94391
|
+
class: "mutation",
|
|
94392
|
+
description: "Schedule a Zoom meeting for a user. Body follows the v2 meetings contract (topic, start_time, duration, type, settings, ...).",
|
|
94393
|
+
parameters: {
|
|
94394
|
+
type: "object",
|
|
94395
|
+
properties: {
|
|
94396
|
+
userId: { type: "string", description: 'User id, email, or "me".' },
|
|
94397
|
+
topic: { type: "string" },
|
|
94398
|
+
type: {
|
|
94399
|
+
type: "integer",
|
|
94400
|
+
enum: [1, 2, 3, 8],
|
|
94401
|
+
description: "1=instant, 2=scheduled, 3=recurring no fixed time, 8=recurring with fixed time."
|
|
94402
|
+
},
|
|
94403
|
+
start_time: { type: "string", description: "ISO-8601 start time (UTC or with offset)." },
|
|
94404
|
+
duration: { type: "integer", description: "Meeting length in minutes." },
|
|
94405
|
+
timezone: { type: "string" },
|
|
94406
|
+
password: { type: "string" },
|
|
94407
|
+
agenda: { type: "string" },
|
|
94408
|
+
settings: { type: "object" },
|
|
94409
|
+
recurrence: { type: "object" },
|
|
94410
|
+
tracking_fields: { type: "array", items: { type: "object" } }
|
|
94411
|
+
},
|
|
94412
|
+
required: ["userId", "topic"]
|
|
94413
|
+
},
|
|
94414
|
+
request: {
|
|
94415
|
+
method: "POST",
|
|
94416
|
+
path: "/v2/users/{userId}/meetings",
|
|
94417
|
+
body: {
|
|
94418
|
+
topic: "{topic}",
|
|
94419
|
+
type: "{type}",
|
|
94420
|
+
start_time: "{start_time}",
|
|
94421
|
+
duration: "{duration}",
|
|
94422
|
+
timezone: "{timezone}",
|
|
94423
|
+
password: "{password}",
|
|
94424
|
+
agenda: "{agenda}",
|
|
94425
|
+
settings: "{settings}",
|
|
94426
|
+
recurrence: "{recurrence}",
|
|
94427
|
+
tracking_fields: "{tracking_fields}"
|
|
94428
|
+
}
|
|
94429
|
+
},
|
|
94430
|
+
cas: "none",
|
|
94431
|
+
externalEffect: true,
|
|
94432
|
+
requiredScopes: ["meeting:write:meeting"]
|
|
94433
|
+
},
|
|
94434
|
+
{
|
|
94435
|
+
name: "meetings.update",
|
|
94436
|
+
class: "mutation",
|
|
94437
|
+
description: "Update a scheduled Zoom meeting in place.",
|
|
94438
|
+
parameters: {
|
|
94439
|
+
type: "object",
|
|
94440
|
+
properties: {
|
|
94441
|
+
meetingId: { type: "string" },
|
|
94442
|
+
occurrence_id: { type: "string" },
|
|
94443
|
+
topic: { type: "string" },
|
|
94444
|
+
start_time: { type: "string" },
|
|
94445
|
+
duration: { type: "integer" },
|
|
94446
|
+
timezone: { type: "string" },
|
|
94447
|
+
password: { type: "string" },
|
|
94448
|
+
agenda: { type: "string" },
|
|
94449
|
+
settings: { type: "object" },
|
|
94450
|
+
recurrence: { type: "object" }
|
|
94451
|
+
},
|
|
94452
|
+
required: ["meetingId"]
|
|
94453
|
+
},
|
|
94454
|
+
request: {
|
|
94455
|
+
method: "PATCH",
|
|
94456
|
+
path: "/v2/meetings/{meetingId}",
|
|
94457
|
+
query: { occurrence_id: "{occurrence_id}" },
|
|
94458
|
+
body: {
|
|
94459
|
+
topic: "{topic}",
|
|
94460
|
+
start_time: "{start_time}",
|
|
94461
|
+
duration: "{duration}",
|
|
94462
|
+
timezone: "{timezone}",
|
|
94463
|
+
password: "{password}",
|
|
94464
|
+
agenda: "{agenda}",
|
|
94465
|
+
settings: "{settings}",
|
|
94466
|
+
recurrence: "{recurrence}"
|
|
94467
|
+
}
|
|
94468
|
+
},
|
|
94469
|
+
cas: "native-idempotency",
|
|
94470
|
+
requiredScopes: ["meeting:update:meeting"]
|
|
94471
|
+
},
|
|
94472
|
+
{
|
|
94473
|
+
name: "meetings.delete",
|
|
94474
|
+
class: "mutation",
|
|
94475
|
+
description: "Delete a Zoom meeting. Optionally notify hosts/registrants and scope to a single occurrence.",
|
|
94476
|
+
parameters: {
|
|
94477
|
+
type: "object",
|
|
94478
|
+
properties: {
|
|
94479
|
+
meetingId: { type: "string" },
|
|
94480
|
+
occurrence_id: { type: "string" },
|
|
94481
|
+
schedule_for_reminder: { type: "boolean" },
|
|
94482
|
+
cancel_meeting_reminder: { type: "boolean" }
|
|
94483
|
+
},
|
|
94484
|
+
required: ["meetingId"]
|
|
94485
|
+
},
|
|
94486
|
+
request: {
|
|
94487
|
+
method: "DELETE",
|
|
94488
|
+
path: "/v2/meetings/{meetingId}",
|
|
94489
|
+
query: {
|
|
94490
|
+
occurrence_id: "{occurrence_id}",
|
|
94491
|
+
schedule_for_reminder: "{schedule_for_reminder}",
|
|
94492
|
+
cancel_meeting_reminder: "{cancel_meeting_reminder}"
|
|
94493
|
+
}
|
|
94494
|
+
},
|
|
94495
|
+
cas: "native-idempotency",
|
|
94496
|
+
externalEffect: true,
|
|
94497
|
+
requiredScopes: ["meeting:delete:meeting"]
|
|
94498
|
+
},
|
|
94499
|
+
{
|
|
94500
|
+
name: "meetings.list-registrants",
|
|
94501
|
+
class: "read",
|
|
94502
|
+
description: "List registrants for a Zoom meeting.",
|
|
94503
|
+
parameters: {
|
|
94504
|
+
type: "object",
|
|
94505
|
+
properties: {
|
|
94506
|
+
meetingId: { type: "string" },
|
|
94507
|
+
occurrence_id: { type: "string" },
|
|
94508
|
+
status: { type: "string", enum: ["pending", "approved", "denied"] },
|
|
94509
|
+
page_size: { type: "integer", minimum: 1, maximum: 300 },
|
|
94510
|
+
next_page_token: { type: "string" }
|
|
94511
|
+
},
|
|
94512
|
+
required: ["meetingId"]
|
|
94513
|
+
},
|
|
94514
|
+
request: {
|
|
94515
|
+
method: "GET",
|
|
94516
|
+
path: "/v2/meetings/{meetingId}/registrants",
|
|
94517
|
+
query: {
|
|
94518
|
+
occurrence_id: "{occurrence_id}",
|
|
94519
|
+
status: "{status}",
|
|
94520
|
+
page_size: "{page_size}",
|
|
94521
|
+
next_page_token: "{next_page_token}"
|
|
94522
|
+
}
|
|
94523
|
+
},
|
|
94524
|
+
requiredScopes: ["meeting:read:meeting"]
|
|
94525
|
+
},
|
|
94526
|
+
{
|
|
94527
|
+
name: "meetings.add-registrant",
|
|
94528
|
+
class: "mutation",
|
|
94529
|
+
description: "Register a participant for a Zoom meeting that requires registration.",
|
|
94530
|
+
parameters: {
|
|
94531
|
+
type: "object",
|
|
94532
|
+
properties: {
|
|
94533
|
+
meetingId: { type: "string" },
|
|
94534
|
+
occurrence_ids: { type: "string", description: "Comma-separated occurrence ids for recurring meetings." },
|
|
94535
|
+
email: { type: "string" },
|
|
94536
|
+
first_name: { type: "string" },
|
|
94537
|
+
last_name: { type: "string" },
|
|
94538
|
+
address: { type: "string" },
|
|
94539
|
+
city: { type: "string" },
|
|
94540
|
+
country: { type: "string" },
|
|
94541
|
+
zip: { type: "string" },
|
|
94542
|
+
state: { type: "string" },
|
|
94543
|
+
phone: { type: "string" },
|
|
94544
|
+
industry: { type: "string" },
|
|
94545
|
+
org: { type: "string" },
|
|
94546
|
+
job_title: { type: "string" },
|
|
94547
|
+
purchasing_time_frame: { type: "string" },
|
|
94548
|
+
role_in_purchase_process: { type: "string" },
|
|
94549
|
+
no_of_employees: { type: "string" },
|
|
94550
|
+
comments: { type: "string" },
|
|
94551
|
+
custom_questions: { type: "array", items: { type: "object" } },
|
|
94552
|
+
language: { type: "string" },
|
|
94553
|
+
auto_approve: { type: "boolean" }
|
|
94554
|
+
},
|
|
94555
|
+
required: ["meetingId", "email", "first_name"]
|
|
94556
|
+
},
|
|
94557
|
+
request: {
|
|
94558
|
+
method: "POST",
|
|
94559
|
+
path: "/v2/meetings/{meetingId}/registrants",
|
|
94560
|
+
query: { occurrence_ids: "{occurrence_ids}" },
|
|
94561
|
+
body: {
|
|
94562
|
+
email: "{email}",
|
|
94563
|
+
first_name: "{first_name}",
|
|
94564
|
+
last_name: "{last_name}",
|
|
94565
|
+
address: "{address}",
|
|
94566
|
+
city: "{city}",
|
|
94567
|
+
country: "{country}",
|
|
94568
|
+
zip: "{zip}",
|
|
94569
|
+
state: "{state}",
|
|
94570
|
+
phone: "{phone}",
|
|
94571
|
+
industry: "{industry}",
|
|
94572
|
+
org: "{org}",
|
|
94573
|
+
job_title: "{job_title}",
|
|
94574
|
+
purchasing_time_frame: "{purchasing_time_frame}",
|
|
94575
|
+
role_in_purchase_process: "{role_in_purchase_process}",
|
|
94576
|
+
no_of_employees: "{no_of_employees}",
|
|
94577
|
+
comments: "{comments}",
|
|
94578
|
+
custom_questions: "{custom_questions}",
|
|
94579
|
+
language: "{language}",
|
|
94580
|
+
auto_approve: "{auto_approve}"
|
|
94581
|
+
}
|
|
94582
|
+
},
|
|
94583
|
+
cas: "native-idempotency",
|
|
94584
|
+
requiredScopes: ["meeting:write:meeting"]
|
|
94585
|
+
},
|
|
94586
|
+
{
|
|
94587
|
+
name: "webinars.list",
|
|
94588
|
+
class: "read",
|
|
94589
|
+
description: "List webinars for a user.",
|
|
94590
|
+
parameters: {
|
|
94591
|
+
type: "object",
|
|
94592
|
+
properties: {
|
|
94593
|
+
userId: { type: "string" },
|
|
94594
|
+
page_size: { type: "integer", minimum: 1, maximum: 300 },
|
|
94595
|
+
next_page_token: { type: "string" }
|
|
94596
|
+
},
|
|
94597
|
+
required: ["userId"]
|
|
94598
|
+
},
|
|
94599
|
+
request: {
|
|
94600
|
+
method: "GET",
|
|
94601
|
+
path: "/v2/users/{userId}/webinars",
|
|
94602
|
+
query: {
|
|
94603
|
+
page_size: "{page_size}",
|
|
94604
|
+
next_page_token: "{next_page_token}"
|
|
94605
|
+
}
|
|
94606
|
+
},
|
|
94607
|
+
requiredScopes: ["webinar:read:webinar"]
|
|
94608
|
+
},
|
|
94609
|
+
{
|
|
94610
|
+
name: "webinars.get",
|
|
94611
|
+
class: "read",
|
|
94612
|
+
description: "Read a Zoom webinar by id.",
|
|
94613
|
+
parameters: {
|
|
94614
|
+
type: "object",
|
|
94615
|
+
properties: {
|
|
94616
|
+
webinarId: { type: "string" },
|
|
94617
|
+
occurrence_id: { type: "string" }
|
|
94618
|
+
},
|
|
94619
|
+
required: ["webinarId"]
|
|
94620
|
+
},
|
|
94621
|
+
request: {
|
|
94622
|
+
method: "GET",
|
|
94623
|
+
path: "/v2/webinars/{webinarId}",
|
|
94624
|
+
query: { occurrence_id: "{occurrence_id}" }
|
|
94625
|
+
},
|
|
94626
|
+
requiredScopes: ["webinar:read:webinar"]
|
|
94627
|
+
},
|
|
94628
|
+
{
|
|
94629
|
+
name: "webinars.create",
|
|
94630
|
+
class: "mutation",
|
|
94631
|
+
description: "Schedule a Zoom webinar for a user.",
|
|
94632
|
+
parameters: {
|
|
94633
|
+
type: "object",
|
|
94634
|
+
properties: {
|
|
94635
|
+
userId: { type: "string" },
|
|
94636
|
+
topic: { type: "string" },
|
|
94637
|
+
type: {
|
|
94638
|
+
type: "integer",
|
|
94639
|
+
enum: [5, 6, 9],
|
|
94640
|
+
description: "5=scheduled, 6=recurring no fixed time, 9=recurring with fixed time."
|
|
94641
|
+
},
|
|
94642
|
+
start_time: { type: "string" },
|
|
94643
|
+
duration: { type: "integer" },
|
|
94644
|
+
timezone: { type: "string" },
|
|
94645
|
+
password: { type: "string" },
|
|
94646
|
+
agenda: { type: "string" },
|
|
94647
|
+
settings: { type: "object" },
|
|
94648
|
+
recurrence: { type: "object" }
|
|
94649
|
+
},
|
|
94650
|
+
required: ["userId", "topic"]
|
|
94651
|
+
},
|
|
94652
|
+
request: {
|
|
94653
|
+
method: "POST",
|
|
94654
|
+
path: "/v2/users/{userId}/webinars",
|
|
94655
|
+
body: {
|
|
94656
|
+
topic: "{topic}",
|
|
94657
|
+
type: "{type}",
|
|
94658
|
+
start_time: "{start_time}",
|
|
94659
|
+
duration: "{duration}",
|
|
94660
|
+
timezone: "{timezone}",
|
|
94661
|
+
password: "{password}",
|
|
94662
|
+
agenda: "{agenda}",
|
|
94663
|
+
settings: "{settings}",
|
|
94664
|
+
recurrence: "{recurrence}"
|
|
94665
|
+
}
|
|
94666
|
+
},
|
|
94667
|
+
cas: "none",
|
|
94668
|
+
externalEffect: true,
|
|
94669
|
+
requiredScopes: ["webinar:write:webinar"]
|
|
94670
|
+
},
|
|
94671
|
+
{
|
|
94672
|
+
name: "recordings.list",
|
|
94673
|
+
class: "read",
|
|
94674
|
+
description: "List cloud recordings for a user.",
|
|
94675
|
+
parameters: {
|
|
94676
|
+
type: "object",
|
|
94677
|
+
properties: {
|
|
94678
|
+
userId: { type: "string", description: 'User id, email, or "me".' },
|
|
94679
|
+
from: { type: "string", description: "YYYY-MM-DD lower bound." },
|
|
94680
|
+
to: { type: "string", description: "YYYY-MM-DD upper bound." },
|
|
94681
|
+
page_size: { type: "integer", minimum: 1, maximum: 300 },
|
|
94682
|
+
next_page_token: { type: "string" },
|
|
94683
|
+
mc: { type: "string" },
|
|
94684
|
+
trash: { type: "boolean" },
|
|
94685
|
+
trash_type: { type: "string", enum: ["meeting_recordings", "recording_file"] }
|
|
94686
|
+
},
|
|
94687
|
+
required: ["userId"]
|
|
94688
|
+
},
|
|
94689
|
+
request: {
|
|
94690
|
+
method: "GET",
|
|
94691
|
+
path: "/v2/users/{userId}/recordings",
|
|
94692
|
+
query: {
|
|
94693
|
+
from: "{from}",
|
|
94694
|
+
to: "{to}",
|
|
94695
|
+
page_size: "{page_size}",
|
|
94696
|
+
next_page_token: "{next_page_token}",
|
|
94697
|
+
mc: "{mc}",
|
|
94698
|
+
trash: "{trash}",
|
|
94699
|
+
trash_type: "{trash_type}"
|
|
94700
|
+
}
|
|
94701
|
+
},
|
|
94702
|
+
requiredScopes: ["recording:read:recording"]
|
|
94703
|
+
},
|
|
94704
|
+
{
|
|
94705
|
+
// Zoom does not expose a DELETE /meetings/{id}/live; ending an in-flight
|
|
94706
|
+
// meeting is modeled as a status PUT with `action: "end"`. The endpoint
|
|
94707
|
+
// is idempotent — repeating it on an already-ended meeting returns 204.
|
|
94708
|
+
name: "meetings.end",
|
|
94709
|
+
class: "mutation",
|
|
94710
|
+
description: 'End a live Zoom meeting via the status endpoint (PUT /meetings/{id}/status, action="end").',
|
|
94711
|
+
parameters: {
|
|
94712
|
+
type: "object",
|
|
94713
|
+
properties: {
|
|
94714
|
+
meetingId: { type: "string", description: "Numeric Zoom meeting id of the live meeting to end." }
|
|
94715
|
+
},
|
|
94716
|
+
required: ["meetingId"]
|
|
94717
|
+
},
|
|
94718
|
+
request: {
|
|
94719
|
+
method: "PUT",
|
|
94720
|
+
path: "/v2/meetings/{meetingId}/status",
|
|
94721
|
+
body: { action: "end" }
|
|
94722
|
+
},
|
|
94723
|
+
cas: "native-idempotency",
|
|
94724
|
+
externalEffect: true,
|
|
94725
|
+
requiredScopes: ["meeting:update:meeting"]
|
|
94726
|
+
},
|
|
94727
|
+
{
|
|
94728
|
+
// Mirrors the meeting update contract: a PATCH against the webinar
|
|
94729
|
+
// record. Zoom returns 204 on success and rejects with 300/400 on
|
|
94730
|
+
// schedule conflicts; the declarative-rest layer surfaces both.
|
|
94731
|
+
name: "webinars.update",
|
|
94732
|
+
class: "mutation",
|
|
94733
|
+
description: "Update a scheduled Zoom webinar in place.",
|
|
94734
|
+
parameters: {
|
|
94735
|
+
type: "object",
|
|
94736
|
+
properties: {
|
|
94737
|
+
webinarId: { type: "string" },
|
|
94738
|
+
occurrence_id: { type: "string" },
|
|
94739
|
+
topic: { type: "string" },
|
|
94740
|
+
start_time: { type: "string" },
|
|
94741
|
+
duration: { type: "integer" },
|
|
94742
|
+
timezone: { type: "string" },
|
|
94743
|
+
password: { type: "string" },
|
|
94744
|
+
agenda: { type: "string" },
|
|
94745
|
+
settings: { type: "object" },
|
|
94746
|
+
recurrence: { type: "object" }
|
|
94747
|
+
},
|
|
94748
|
+
required: ["webinarId"]
|
|
94749
|
+
},
|
|
94750
|
+
request: {
|
|
94751
|
+
// Optional-field forest: any of topic/start_time/duration/etc. may be
|
|
94752
|
+
// absent, and the bare {x} body template requires every placeholder.
|
|
94753
|
+
// body: 'args' passes the resolved arg bag through verbatim, dropping
|
|
94754
|
+
// webinarId-on-path duplication via Zoom's lenient PATCH (extra
|
|
94755
|
+
// fields are ignored). Keeps the caller's optional-field semantics
|
|
94756
|
+
// exact instead of forcing them to send every field.
|
|
94757
|
+
method: "PATCH",
|
|
94758
|
+
path: "/v2/webinars/{webinarId}",
|
|
94759
|
+
query: { occurrence_id: "{occurrence_id}" },
|
|
94760
|
+
body: "args"
|
|
94761
|
+
},
|
|
94762
|
+
cas: "native-idempotency",
|
|
94763
|
+
externalEffect: true,
|
|
94764
|
+
requiredScopes: ["webinar:update:webinar"]
|
|
94765
|
+
},
|
|
94766
|
+
{
|
|
94767
|
+
name: "webinars.delete",
|
|
94768
|
+
class: "mutation",
|
|
94769
|
+
description: "Delete a Zoom webinar. Optionally scope to a single occurrence and toggle host/panelist cancellation notifications.",
|
|
94770
|
+
parameters: {
|
|
94771
|
+
type: "object",
|
|
94772
|
+
properties: {
|
|
94773
|
+
webinarId: { type: "string" },
|
|
94774
|
+
occurrence_id: { type: "string" },
|
|
94775
|
+
cancel_webinar_reminder: { type: "boolean" }
|
|
94776
|
+
},
|
|
94777
|
+
required: ["webinarId"]
|
|
94778
|
+
},
|
|
94779
|
+
request: {
|
|
94780
|
+
method: "DELETE",
|
|
94781
|
+
path: "/v2/webinars/{webinarId}",
|
|
94782
|
+
query: {
|
|
94783
|
+
occurrence_id: "{occurrence_id}",
|
|
94784
|
+
cancel_webinar_reminder: "{cancel_webinar_reminder}"
|
|
94785
|
+
}
|
|
94786
|
+
},
|
|
94787
|
+
cas: "native-idempotency",
|
|
94788
|
+
externalEffect: true,
|
|
94789
|
+
requiredScopes: ["webinar:delete:webinar"]
|
|
94790
|
+
},
|
|
94791
|
+
{
|
|
94792
|
+
// `action=trash` moves the recording to the cloud trash (recoverable for
|
|
94793
|
+
// 30 days); `action=delete` permanently deletes. The caller picks the
|
|
94794
|
+
// mode — we won't default to one because the destructive variant is
|
|
94795
|
+
// unrecoverable and the safe variant breaks downstream search indexes
|
|
94796
|
+
// that watch the trash queue.
|
|
94797
|
+
name: "recordings.delete",
|
|
94798
|
+
class: "mutation",
|
|
94799
|
+
description: 'Delete (or trash) a cloud recording for a meeting. action="trash" is recoverable; action="delete" is permanent.',
|
|
94800
|
+
parameters: {
|
|
94801
|
+
type: "object",
|
|
94802
|
+
properties: {
|
|
94803
|
+
meetingId: { type: "string", description: "Meeting id or recording UUID." },
|
|
94804
|
+
action: { type: "string", enum: ["trash", "delete"], description: "trash (default, recoverable) or delete (permanent)." }
|
|
94805
|
+
},
|
|
94806
|
+
required: ["meetingId"]
|
|
94807
|
+
},
|
|
94808
|
+
request: {
|
|
94809
|
+
method: "DELETE",
|
|
94810
|
+
path: "/v2/meetings/{meetingId}/recordings",
|
|
94811
|
+
query: { action: "{action}" }
|
|
94812
|
+
},
|
|
94813
|
+
cas: "native-idempotency",
|
|
94814
|
+
externalEffect: true,
|
|
94815
|
+
requiredScopes: ["recording:write:recording"]
|
|
94816
|
+
},
|
|
94817
|
+
{
|
|
94818
|
+
// Zoom user provisioning is a single POST with an `action` discriminator:
|
|
94819
|
+
// create (manual invite), autoCreate (provision into the account), or
|
|
94820
|
+
// custCreate (custom-managed user). The user_info sub-object carries
|
|
94821
|
+
// email/type/first_name/last_name. We expose `action` + `user_info`
|
|
94822
|
+
// verbatim so callers can hit any of the three provisioning modes.
|
|
94823
|
+
name: "users.create",
|
|
94824
|
+
class: "mutation",
|
|
94825
|
+
description: "Create a user in the Zoom account. `action` selects the provisioning mode; user_info carries the user payload.",
|
|
94826
|
+
parameters: {
|
|
94827
|
+
type: "object",
|
|
94828
|
+
properties: {
|
|
94829
|
+
action: {
|
|
94830
|
+
type: "string",
|
|
94831
|
+
enum: ["create", "autoCreate", "custCreate", "ssoCreate"],
|
|
94832
|
+
description: "Provisioning mode: create (invite), autoCreate (provision), custCreate (custom-managed), ssoCreate (SSO)."
|
|
94833
|
+
},
|
|
94834
|
+
user_info: {
|
|
94835
|
+
type: "object",
|
|
94836
|
+
description: "User payload (email, type, first_name, last_name, password for custCreate, etc.)."
|
|
94837
|
+
}
|
|
94838
|
+
},
|
|
94839
|
+
required: ["action", "user_info"]
|
|
94840
|
+
},
|
|
94841
|
+
request: {
|
|
94842
|
+
method: "POST",
|
|
94843
|
+
path: "/v2/users",
|
|
94844
|
+
body: { action: "{action}", user_info: "{user_info}" }
|
|
94845
|
+
},
|
|
94846
|
+
cas: "native-idempotency",
|
|
94847
|
+
externalEffect: true,
|
|
94848
|
+
requiredScopes: ["user:write:user"]
|
|
94849
|
+
},
|
|
94850
|
+
{
|
|
94851
|
+
name: "recordings.get",
|
|
94852
|
+
class: "read",
|
|
94853
|
+
description: 'List recording files for a meeting or recording id (use a double-encoded UUID if it begins with "/" or contains "//").',
|
|
94854
|
+
parameters: {
|
|
94855
|
+
type: "object",
|
|
94856
|
+
properties: {
|
|
94857
|
+
meetingId: { type: "string", description: "Meeting id or recording UUID." },
|
|
94858
|
+
include_fields: { type: "string", description: "Comma-separated extra fields to include (e.g. download_access_token)." },
|
|
94859
|
+
ttl: { type: "integer", description: "TTL in seconds for download_access_token (max 604800)." }
|
|
94860
|
+
},
|
|
94861
|
+
required: ["meetingId"]
|
|
94862
|
+
},
|
|
94863
|
+
request: {
|
|
94864
|
+
method: "GET",
|
|
94865
|
+
path: "/v2/meetings/{meetingId}/recordings",
|
|
94866
|
+
query: {
|
|
94867
|
+
include_fields: "{include_fields}",
|
|
94868
|
+
ttl: "{ttl}"
|
|
94869
|
+
}
|
|
94870
|
+
},
|
|
94871
|
+
requiredScopes: ["recording:read:recording"]
|
|
94872
|
+
}
|
|
94873
|
+
]
|
|
94874
|
+
});
|
|
94875
|
+
|
|
94876
|
+
// src/connectors/adapters/affinity.ts
|
|
94877
|
+
var affinityConnector = declarativeRestConnector({
|
|
94878
|
+
kind: "affinity",
|
|
94879
|
+
displayName: "Affinity",
|
|
94880
|
+
description: "Synchronize Affinity people, organizations, opportunities, lists, notes, interactions, and field values.",
|
|
94881
|
+
auth: {
|
|
94882
|
+
kind: "api-key",
|
|
94883
|
+
hint: "Affinity API key from Settings > API. Availability depends on the workspace plan and key owner permissions."
|
|
94884
|
+
},
|
|
94885
|
+
category: "crm",
|
|
94886
|
+
defaultConsistencyModel: "authoritative",
|
|
94887
|
+
baseUrl: "https://api.affinity.co",
|
|
94888
|
+
test: { method: "GET", path: "/auth/whoami" },
|
|
94889
|
+
capabilities: [
|
|
94890
|
+
collectionRead("people.list", "List or search people.", "/persons", "person"),
|
|
94891
|
+
entityRead("people.get", "Read one person, including current organizations and opportunities.", "/persons/{personId}", "personId"),
|
|
94892
|
+
entityCreate("people.create", "Create a person.", "/persons"),
|
|
94893
|
+
entityUpdate("people.update", "Update a person.", "/persons/{personId}", "personId"),
|
|
94894
|
+
entityDelete("people.delete", "Delete a person.", "/persons/{personId}", "personId"),
|
|
94895
|
+
collectionRead("organizations.list", "List or search organizations.", "/organizations", "organization"),
|
|
94896
|
+
entityRead("organizations.get", "Read one organization.", "/organizations/{organizationId}", "organizationId"),
|
|
94897
|
+
entityCreate("organizations.create", "Create an organization.", "/organizations"),
|
|
94898
|
+
entityUpdate("organizations.update", "Update an organization.", "/organizations/{organizationId}", "organizationId"),
|
|
94899
|
+
entityDelete("organizations.delete", "Delete an organization.", "/organizations/{organizationId}", "organizationId"),
|
|
94900
|
+
collectionRead("opportunities.list", "List or search opportunities.", "/opportunities", "opportunity"),
|
|
94901
|
+
entityRead("opportunities.get", "Read one opportunity.", "/opportunities/{opportunityId}", "opportunityId"),
|
|
94902
|
+
entityCreate("opportunities.create", "Create an opportunity.", "/opportunities"),
|
|
94903
|
+
entityUpdate("opportunities.update", "Update an opportunity.", "/opportunities/{opportunityId}", "opportunityId"),
|
|
94904
|
+
entityDelete("opportunities.delete", "Delete an opportunity.", "/opportunities/{opportunityId}", "opportunityId"),
|
|
94905
|
+
collectionRead("lists.list", "List CRM lists.", "/lists", "list"),
|
|
94906
|
+
entityRead("lists.get", "Read one CRM list and its field definitions.", "/lists/{listId}", "listId"),
|
|
94907
|
+
{
|
|
94908
|
+
name: "list-entries.list",
|
|
94909
|
+
class: "read",
|
|
94910
|
+
description: "List entries in an Affinity list.",
|
|
94911
|
+
parameters: {
|
|
94912
|
+
type: "object",
|
|
94913
|
+
properties: {
|
|
94914
|
+
listId: { type: "integer" },
|
|
94915
|
+
page_size: { type: "integer", minimum: 1, maximum: 500 },
|
|
94916
|
+
page_token: { type: "string" }
|
|
94917
|
+
},
|
|
94918
|
+
required: ["listId"]
|
|
94919
|
+
},
|
|
94920
|
+
request: {
|
|
94921
|
+
method: "GET",
|
|
94922
|
+
path: "/lists/{listId}/list-entries",
|
|
94923
|
+
query: { page_size: "{page_size}", page_token: "{page_token}" }
|
|
94924
|
+
}
|
|
94925
|
+
},
|
|
94926
|
+
{
|
|
94927
|
+
name: "list-entries.create",
|
|
94928
|
+
class: "mutation",
|
|
94929
|
+
description: "Add an entity to an Affinity list.",
|
|
94930
|
+
parameters: {
|
|
94931
|
+
type: "object",
|
|
94932
|
+
properties: {
|
|
94933
|
+
listId: { type: "integer" },
|
|
94934
|
+
entity_id: { type: "integer" }
|
|
94935
|
+
},
|
|
94936
|
+
required: ["listId", "entity_id"]
|
|
94937
|
+
},
|
|
94938
|
+
request: { method: "POST", path: "/lists/{listId}/list-entries", body: { entity_id: "{entity_id}" } },
|
|
94939
|
+
cas: "native-idempotency",
|
|
94940
|
+
externalEffect: true
|
|
94941
|
+
},
|
|
94942
|
+
{
|
|
94943
|
+
name: "list-entries.delete",
|
|
94944
|
+
class: "mutation",
|
|
94945
|
+
description: "Remove a list entry.",
|
|
94946
|
+
parameters: idParameters("listEntryId"),
|
|
94947
|
+
request: { method: "DELETE", path: "/list-entries/{listEntryId}" },
|
|
94948
|
+
cas: "native-idempotency",
|
|
94949
|
+
externalEffect: true
|
|
94950
|
+
},
|
|
94951
|
+
{
|
|
94952
|
+
name: "field-values.list",
|
|
94953
|
+
class: "read",
|
|
94954
|
+
description: "Read mapped custom-field values for one person, organization, opportunity, or list entry.",
|
|
94955
|
+
parameters: {
|
|
94956
|
+
type: "object",
|
|
94957
|
+
properties: {
|
|
94958
|
+
person_id: { type: "integer" },
|
|
94959
|
+
organization_id: { type: "integer" },
|
|
94960
|
+
opportunity_id: { type: "integer" },
|
|
94961
|
+
list_entry_id: { type: "integer" }
|
|
94962
|
+
}
|
|
94963
|
+
},
|
|
94964
|
+
request: {
|
|
94965
|
+
method: "GET",
|
|
94966
|
+
path: "/field-values",
|
|
94967
|
+
query: {
|
|
94968
|
+
person_id: "{person_id}",
|
|
94969
|
+
organization_id: "{organization_id}",
|
|
94970
|
+
opportunity_id: "{opportunity_id}",
|
|
94971
|
+
list_entry_id: "{list_entry_id}"
|
|
94972
|
+
}
|
|
94973
|
+
}
|
|
94974
|
+
},
|
|
94975
|
+
entityCreate("field-values.create", "Create a custom-field value.", "/field-values"),
|
|
94976
|
+
entityUpdate("field-values.update", "Update a custom-field value.", "/field-values/{fieldValueId}", "fieldValueId"),
|
|
94977
|
+
entityDelete("field-values.delete", "Delete a custom-field value.", "/field-values/{fieldValueId}", "fieldValueId"),
|
|
94978
|
+
{
|
|
94979
|
+
name: "field-value-changes.list",
|
|
94980
|
+
class: "read",
|
|
94981
|
+
description: "Read custom-field change history for synchronization and evidence.",
|
|
94982
|
+
parameters: {
|
|
94983
|
+
type: "object",
|
|
94984
|
+
properties: {
|
|
94985
|
+
field_id: { type: "integer" },
|
|
94986
|
+
action_type: { type: "integer" },
|
|
94987
|
+
page_size: { type: "integer", minimum: 1, maximum: 500 },
|
|
94988
|
+
page_token: { type: "string" }
|
|
94989
|
+
},
|
|
94990
|
+
required: ["field_id"]
|
|
94991
|
+
},
|
|
94992
|
+
request: {
|
|
94993
|
+
method: "GET",
|
|
94994
|
+
path: "/field-value-changes",
|
|
94995
|
+
query: {
|
|
94996
|
+
field_id: "{field_id}",
|
|
94997
|
+
action_type: "{action_type}",
|
|
94998
|
+
page_size: "{page_size}",
|
|
94999
|
+
page_token: "{page_token}"
|
|
95000
|
+
}
|
|
95001
|
+
}
|
|
95002
|
+
},
|
|
95003
|
+
{
|
|
95004
|
+
name: "interactions.list",
|
|
95005
|
+
class: "read",
|
|
95006
|
+
description: "List email, meeting, call, and chat interactions for a person or organization.",
|
|
95007
|
+
parameters: {
|
|
95008
|
+
type: "object",
|
|
95009
|
+
properties: {
|
|
95010
|
+
person_id: { type: "integer" },
|
|
95011
|
+
organization_id: { type: "integer" },
|
|
95012
|
+
type: { type: "integer" },
|
|
95013
|
+
start_time: { type: "string" },
|
|
95014
|
+
end_time: { type: "string" },
|
|
95015
|
+
page_size: { type: "integer", minimum: 1, maximum: 500 },
|
|
95016
|
+
page_token: { type: "string" }
|
|
95017
|
+
}
|
|
95018
|
+
},
|
|
95019
|
+
request: {
|
|
95020
|
+
method: "GET",
|
|
95021
|
+
path: "/interactions",
|
|
95022
|
+
query: {
|
|
95023
|
+
person_id: "{person_id}",
|
|
95024
|
+
organization_id: "{organization_id}",
|
|
95025
|
+
type: "{type}",
|
|
95026
|
+
start_time: "{start_time}",
|
|
95027
|
+
end_time: "{end_time}",
|
|
95028
|
+
page_size: "{page_size}",
|
|
95029
|
+
page_token: "{page_token}"
|
|
95030
|
+
}
|
|
95031
|
+
}
|
|
95032
|
+
},
|
|
95033
|
+
{
|
|
95034
|
+
name: "notes.list",
|
|
95035
|
+
class: "read",
|
|
95036
|
+
description: "List notes linked to people, organizations, or opportunities.",
|
|
95037
|
+
parameters: {
|
|
95038
|
+
type: "object",
|
|
95039
|
+
properties: {
|
|
95040
|
+
person_id: { type: "integer" },
|
|
95041
|
+
organization_id: { type: "integer" },
|
|
95042
|
+
opportunity_id: { type: "integer" },
|
|
95043
|
+
page_size: { type: "integer", minimum: 1, maximum: 500 },
|
|
95044
|
+
page_token: { type: "string" }
|
|
95045
|
+
}
|
|
95046
|
+
},
|
|
95047
|
+
request: {
|
|
95048
|
+
method: "GET",
|
|
95049
|
+
path: "/notes",
|
|
95050
|
+
query: {
|
|
95051
|
+
person_id: "{person_id}",
|
|
95052
|
+
organization_id: "{organization_id}",
|
|
95053
|
+
opportunity_id: "{opportunity_id}",
|
|
95054
|
+
page_size: "{page_size}",
|
|
95055
|
+
page_token: "{page_token}"
|
|
95056
|
+
}
|
|
95057
|
+
}
|
|
95058
|
+
},
|
|
95059
|
+
entityCreate("notes.create", "Create a note linked to CRM records.", "/notes"),
|
|
95060
|
+
entityUpdate("notes.update", "Update a note.", "/notes/{noteId}", "noteId"),
|
|
95061
|
+
entityDelete("notes.delete", "Delete a note.", "/notes/{noteId}", "noteId")
|
|
95062
|
+
]
|
|
95063
|
+
});
|
|
95064
|
+
function collectionRead(name, description, path, entity) {
|
|
95065
|
+
return {
|
|
95066
|
+
name,
|
|
95067
|
+
class: "read",
|
|
95068
|
+
description,
|
|
95069
|
+
parameters: {
|
|
95070
|
+
type: "object",
|
|
95071
|
+
properties: {
|
|
95072
|
+
term: { type: "string", description: `Search ${entity} names and identifiers.` },
|
|
95073
|
+
page_size: { type: "integer", minimum: 1, maximum: 500 },
|
|
95074
|
+
page_token: { type: "string" }
|
|
95075
|
+
}
|
|
95076
|
+
},
|
|
95077
|
+
request: {
|
|
95078
|
+
method: "GET",
|
|
95079
|
+
path,
|
|
95080
|
+
query: { term: "{term}", page_size: "{page_size}", page_token: "{page_token}" }
|
|
95081
|
+
}
|
|
95082
|
+
};
|
|
95083
|
+
}
|
|
95084
|
+
function entityRead(name, description, path, id) {
|
|
95085
|
+
return {
|
|
95086
|
+
name,
|
|
95087
|
+
class: "read",
|
|
95088
|
+
description,
|
|
95089
|
+
parameters: idParameters(id),
|
|
95090
|
+
request: { method: "GET", path }
|
|
95091
|
+
};
|
|
95092
|
+
}
|
|
95093
|
+
function entityCreate(name, description, path) {
|
|
95094
|
+
return {
|
|
95095
|
+
name,
|
|
95096
|
+
class: "mutation",
|
|
95097
|
+
description,
|
|
95098
|
+
parameters: arbitraryBodyParameters(),
|
|
95099
|
+
request: { method: "POST", path, body: "args" },
|
|
95100
|
+
cas: "native-idempotency",
|
|
95101
|
+
externalEffect: true
|
|
95102
|
+
};
|
|
95103
|
+
}
|
|
95104
|
+
function entityUpdate(name, description, path, id) {
|
|
95105
|
+
return {
|
|
95106
|
+
name,
|
|
95107
|
+
class: "mutation",
|
|
95108
|
+
description,
|
|
95109
|
+
parameters: {
|
|
95110
|
+
type: "object",
|
|
95111
|
+
properties: { [id]: { type: "integer" } },
|
|
95112
|
+
required: [id],
|
|
95113
|
+
additionalProperties: true
|
|
95114
|
+
},
|
|
95115
|
+
request: { method: "PUT", path, body: "args" },
|
|
95116
|
+
cas: "optimistic-read-verify",
|
|
95117
|
+
externalEffect: true
|
|
95118
|
+
};
|
|
95119
|
+
}
|
|
95120
|
+
function entityDelete(name, description, path, id) {
|
|
95121
|
+
return {
|
|
95122
|
+
name,
|
|
95123
|
+
class: "mutation",
|
|
95124
|
+
description,
|
|
95125
|
+
parameters: idParameters(id),
|
|
95126
|
+
request: { method: "DELETE", path },
|
|
95127
|
+
cas: "native-idempotency",
|
|
95128
|
+
externalEffect: true
|
|
95129
|
+
};
|
|
95130
|
+
}
|
|
95131
|
+
function idParameters(id) {
|
|
95132
|
+
return {
|
|
95133
|
+
type: "object",
|
|
95134
|
+
properties: { [id]: { type: "integer" } },
|
|
95135
|
+
required: [id]
|
|
95136
|
+
};
|
|
95137
|
+
}
|
|
95138
|
+
function arbitraryBodyParameters() {
|
|
95139
|
+
return {
|
|
95140
|
+
type: "object",
|
|
95141
|
+
additionalProperties: true,
|
|
95142
|
+
properties: {}
|
|
95143
|
+
};
|
|
95144
|
+
}
|
|
95145
|
+
|
|
93362
95146
|
// src/connectors/adapters/griptape.ts
|
|
93363
95147
|
var griptapeConnector = declarativeRestConnector({
|
|
93364
95148
|
kind: "griptape",
|
|
@@ -125448,6 +127232,9 @@ export {
|
|
|
125448
127232
|
phonyConnector,
|
|
125449
127233
|
stripePackConnector,
|
|
125450
127234
|
webhookConnector,
|
|
127235
|
+
httpConnector,
|
|
127236
|
+
rssConnector,
|
|
127237
|
+
amazonS3Connector,
|
|
125451
127238
|
stripeWebhookReceiverConnector,
|
|
125452
127239
|
slackEventsConnector,
|
|
125453
127240
|
githubConnector,
|
|
@@ -125769,6 +127556,8 @@ export {
|
|
|
125769
127556
|
gptzeroDetectAiConnector,
|
|
125770
127557
|
gristConnector,
|
|
125771
127558
|
granolaConnector,
|
|
127559
|
+
zoomConnector,
|
|
127560
|
+
affinityConnector,
|
|
125772
127561
|
griptapeConnector,
|
|
125773
127562
|
heartbeatConnector,
|
|
125774
127563
|
hedyConnector,
|
|
@@ -125956,4 +127745,4 @@ export {
|
|
|
125956
127745
|
demandbaseConnector,
|
|
125957
127746
|
adapters_exports
|
|
125958
127747
|
};
|
|
125959
|
-
//# sourceMappingURL=chunk-
|
|
127748
|
+
//# sourceMappingURL=chunk-OOGP4SCY.js.map
|