@tangle-network/agent-integrations 0.5.0 → 0.7.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/index.js CHANGED
@@ -1986,6 +1986,204 @@ function readMetaString3(meta, key) {
1986
1986
  return v;
1987
1987
  }
1988
1988
 
1989
+ // src/connectors/adapters/declarative-rest.ts
1990
+ function declarativeRestConnector(spec) {
1991
+ const capabilities = spec.capabilities.map(operationToCapability);
1992
+ const adapter = {
1993
+ manifest: {
1994
+ kind: spec.kind,
1995
+ displayName: spec.displayName,
1996
+ description: spec.description,
1997
+ auth: spec.auth,
1998
+ category: spec.category,
1999
+ defaultConsistencyModel: spec.defaultConsistencyModel,
2000
+ capabilities
2001
+ },
2002
+ async executeRead(inv) {
2003
+ const op = readOperation(spec, inv.capabilityName, "read");
2004
+ const response = await executeRestRequest(spec, op.request, inv);
2005
+ return {
2006
+ data: response.data,
2007
+ etag: response.etag,
2008
+ fetchedAt: Date.now()
2009
+ };
2010
+ },
2011
+ async executeMutation(inv) {
2012
+ const op = readOperation(spec, inv.capabilityName, "mutation");
2013
+ const response = await executeRestRequest(spec, op.request, inv);
2014
+ return {
2015
+ status: "committed",
2016
+ data: response.data,
2017
+ etagAfter: response.etag,
2018
+ committedAt: Date.now(),
2019
+ idempotentReplay: false
2020
+ };
2021
+ },
2022
+ async test(source) {
2023
+ if (!spec.test) return { ok: true };
2024
+ try {
2025
+ await executeRestRequest(spec, spec.test, {
2026
+ source,
2027
+ capabilityName: "__test__",
2028
+ args: {},
2029
+ idempotencyKey: "test"
2030
+ });
2031
+ return { ok: true };
2032
+ } catch (error) {
2033
+ return { ok: false, reason: error instanceof Error ? error.message : "unknown error" };
2034
+ }
2035
+ }
2036
+ };
2037
+ return adapter;
2038
+ }
2039
+ function operationToCapability(op) {
2040
+ const base = {
2041
+ name: op.name,
2042
+ description: op.description,
2043
+ parameters: op.parameters,
2044
+ requiredScopes: op.requiredScopes
2045
+ };
2046
+ if (op.class === "read") {
2047
+ return { ...base, class: "read" };
2048
+ }
2049
+ return {
2050
+ ...base,
2051
+ class: "mutation",
2052
+ cas: op.cas ?? "native-idempotency",
2053
+ externalEffect: op.externalEffect ?? true
2054
+ };
2055
+ }
2056
+ function readOperation(spec, name, expected) {
2057
+ const op = spec.capabilities.find((candidate) => candidate.name === name);
2058
+ if (!op || op.class !== expected) {
2059
+ throw new Error(`${spec.kind}: unknown ${expected} capability ${name}`);
2060
+ }
2061
+ return op;
2062
+ }
2063
+ async function executeRestRequest(spec, request, inv) {
2064
+ const baseUrl = resolveBaseUrl(spec.baseUrl, inv.source.metadata);
2065
+ const url = new URL(interpolate(request.path, inv.args), baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`);
2066
+ for (const [key, value] of Object.entries(request.query ?? {})) {
2067
+ const rendered = renderQueryValue(value, inv.args);
2068
+ if (rendered !== void 0 && rendered !== "") url.searchParams.set(key, String(rendered));
2069
+ }
2070
+ const headers = {
2071
+ accept: "application/json",
2072
+ ...spec.defaultHeaders,
2073
+ ...renderHeaders(request.headers ?? {}, inv.args)
2074
+ };
2075
+ applyCredentials(headers, url, spec.credentialPlacement ?? { kind: "bearer" }, inv.source.credentials);
2076
+ if (inv.expectedEtag) headers["if-match"] = inv.expectedEtag;
2077
+ if (request.method !== "GET" && request.method !== "DELETE") {
2078
+ headers["content-type"] = headers["content-type"] ?? "application/json";
2079
+ }
2080
+ const res = await fetch(url, {
2081
+ method: request.method,
2082
+ headers,
2083
+ body: request.method === "GET" || request.method === "DELETE" ? void 0 : JSON.stringify(resolveBody(request.body, inv.args)),
2084
+ signal: AbortSignal.timeout(2e4)
2085
+ });
2086
+ if (res.status === 401 || res.status === 403) {
2087
+ throw new CredentialsExpired(`${spec.displayName} rejected credentials (${res.status})`, inv.source.id);
2088
+ }
2089
+ if (res.status === 409 || res.status === 412) {
2090
+ return {
2091
+ data: {
2092
+ status: "conflict",
2093
+ message: await safeErrorText(res)
2094
+ },
2095
+ etag: res.headers.get("etag") ?? void 0
2096
+ };
2097
+ }
2098
+ if (res.status === 429) {
2099
+ return {
2100
+ data: {
2101
+ status: "rate-limited",
2102
+ retryAfter: res.headers.get("retry-after") ?? void 0,
2103
+ message: await safeErrorText(res)
2104
+ }
2105
+ };
2106
+ }
2107
+ if (!res.ok) {
2108
+ throw new Error(`${spec.kind} ${request.method} ${url.pathname} HTTP ${res.status}: ${(await safeErrorText(res)).slice(0, 300)}`);
2109
+ }
2110
+ const text = await res.text();
2111
+ const data = text ? JSON.parse(text) : null;
2112
+ return { data, etag: res.headers.get("etag") ?? void 0 };
2113
+ }
2114
+ function resolveBaseUrl(baseUrl, metadata) {
2115
+ if (typeof baseUrl === "string") return baseUrl;
2116
+ const value = metadata[baseUrl.metadataKey];
2117
+ if (typeof value === "string" && value.trim()) return value;
2118
+ if (baseUrl.fallback) return baseUrl.fallback;
2119
+ throw new Error(`missing metadata.${baseUrl.metadataKey} base URL`);
2120
+ }
2121
+ function applyCredentials(headers, url, placement, credentials) {
2122
+ const token = credentialToken(credentials);
2123
+ if (placement.kind === "bearer") headers.authorization = `Bearer ${token}`;
2124
+ if (placement.kind === "header") headers[placement.header] = `${placement.prefix ?? ""}${token}`;
2125
+ if (placement.kind === "query") url.searchParams.set(placement.parameter, token);
2126
+ }
2127
+ function credentialToken(credentials) {
2128
+ if (credentials.kind === "oauth2") return credentials.accessToken;
2129
+ if (credentials.kind === "api-key") return credentials.apiKey;
2130
+ throw new Error(`declarative REST connectors require oauth2 or api-key credentials, got ${credentials.kind}`);
2131
+ }
2132
+ function resolveBody(body, args) {
2133
+ if (!body || body === "args") return args;
2134
+ if (typeof body === "string") return renderValue(body, args);
2135
+ return renderObject(body, args);
2136
+ }
2137
+ function renderHeaders(headers, args) {
2138
+ return Object.fromEntries(Object.entries(headers).map(([key, value]) => [key, interpolate(value, args)]));
2139
+ }
2140
+ function renderObject(input, args) {
2141
+ return Object.fromEntries(Object.entries(input).map(([key, value]) => [key, renderValue(value, args)]));
2142
+ }
2143
+ function renderValue(value, args) {
2144
+ if (typeof value === "string") {
2145
+ const exact = value.match(/^\{([a-zA-Z0-9_.-]+)\}$/);
2146
+ if (exact) return readRequiredPath(args, exact[1]);
2147
+ return interpolate(value, args);
2148
+ }
2149
+ return value;
2150
+ }
2151
+ function renderQueryValue(value, args) {
2152
+ if (typeof value !== "string") return value;
2153
+ const exact = value.match(/^\{([a-zA-Z0-9_.-]+)\}$/);
2154
+ if (exact) return readPath(args, exact[1]);
2155
+ try {
2156
+ return interpolate(value, args);
2157
+ } catch {
2158
+ return void 0;
2159
+ }
2160
+ }
2161
+ function interpolate(template, args) {
2162
+ return template.replace(/\{([a-zA-Z0-9_.-]+)\}/g, (_match, key) => {
2163
+ const value = readPath(args, key);
2164
+ if (value === void 0 || value === null) {
2165
+ throw new Error(`missing required argument: ${key}`);
2166
+ }
2167
+ return encodeURIComponent(String(value));
2168
+ });
2169
+ }
2170
+ function readRequiredPath(input, path) {
2171
+ const value = readPath(input, path);
2172
+ if (value === void 0 || value === null) throw new Error(`missing required argument: ${path}`);
2173
+ return value;
2174
+ }
2175
+ function readPath(input, path) {
2176
+ return path.split(".").reduce((value, part) => {
2177
+ if (value && typeof value === "object" && part in value) {
2178
+ return value[part];
2179
+ }
2180
+ return void 0;
2181
+ }, input);
2182
+ }
2183
+ async function safeErrorText(res) {
2184
+ return await res.text().catch(() => res.statusText) || res.statusText;
2185
+ }
2186
+
1989
2187
  // src/connectors/adapters/twilio-sms.ts
1990
2188
  var API4 = "https://api.twilio.com/2010-04-01";
1991
2189
  var LOOKUP_API = "https://lookups.twilio.com/v1";
@@ -2654,6 +2852,349 @@ var slackEventsConnector = {
2654
2852
  }
2655
2853
  };
2656
2854
 
2855
+ // src/connectors/adapters/github.ts
2856
+ var repoParams = {
2857
+ type: "object",
2858
+ properties: {
2859
+ owner: { type: "string" },
2860
+ repo: { type: "string" }
2861
+ },
2862
+ required: ["owner", "repo"]
2863
+ };
2864
+ var githubConnector = declarativeRestConnector({
2865
+ kind: "github",
2866
+ displayName: "GitHub",
2867
+ description: "Search repositories/issues and create or update GitHub issues through a user-scoped token.",
2868
+ auth: { kind: "api-key", hint: "GitHub fine-grained personal access token or installation token." },
2869
+ category: "other",
2870
+ defaultConsistencyModel: "authoritative",
2871
+ baseUrl: "https://api.github.com",
2872
+ defaultHeaders: {
2873
+ "x-github-api-version": "2022-11-28"
2874
+ },
2875
+ test: { method: "GET", path: "/user" },
2876
+ capabilities: [
2877
+ {
2878
+ name: "repositories.get",
2879
+ class: "read",
2880
+ description: "Read repository metadata.",
2881
+ parameters: repoParams,
2882
+ request: { method: "GET", path: "/repos/{owner}/{repo}" }
2883
+ },
2884
+ {
2885
+ name: "issues.search",
2886
+ class: "read",
2887
+ description: "Search GitHub issues and pull requests.",
2888
+ parameters: {
2889
+ type: "object",
2890
+ properties: { q: { type: "string" }, per_page: { type: "integer", minimum: 1, maximum: 100 } },
2891
+ required: ["q"]
2892
+ },
2893
+ request: { method: "GET", path: "/search/issues", query: { q: "{q}", per_page: "{per_page}" } }
2894
+ },
2895
+ {
2896
+ name: "issues.create",
2897
+ class: "mutation",
2898
+ description: "Create an issue in a repository.",
2899
+ parameters: {
2900
+ type: "object",
2901
+ properties: {
2902
+ owner: { type: "string" },
2903
+ repo: { type: "string" },
2904
+ title: { type: "string" },
2905
+ body: { type: "string" },
2906
+ labels: { type: "array", items: { type: "string" } }
2907
+ },
2908
+ required: ["owner", "repo", "title"]
2909
+ },
2910
+ request: { method: "POST", path: "/repos/{owner}/{repo}/issues", body: "args" },
2911
+ cas: "native-idempotency"
2912
+ },
2913
+ {
2914
+ name: "issues.update",
2915
+ class: "mutation",
2916
+ description: "Update an issue by number.",
2917
+ parameters: {
2918
+ type: "object",
2919
+ properties: {
2920
+ owner: { type: "string" },
2921
+ repo: { type: "string" },
2922
+ issue_number: { type: "integer" },
2923
+ title: { type: "string" },
2924
+ body: { type: "string" },
2925
+ state: { type: "string", enum: ["open", "closed"] }
2926
+ },
2927
+ required: ["owner", "repo", "issue_number"]
2928
+ },
2929
+ request: { method: "PATCH", path: "/repos/{owner}/{repo}/issues/{issue_number}", body: "args" },
2930
+ cas: "etag-if-match"
2931
+ }
2932
+ ]
2933
+ });
2934
+
2935
+ // src/connectors/adapters/gitlab.ts
2936
+ var gitlabConnector = declarativeRestConnector({
2937
+ kind: "gitlab",
2938
+ displayName: "GitLab",
2939
+ description: "Search GitLab projects/issues and create or update issues through a personal, project, or group token.",
2940
+ auth: { kind: "api-key", hint: "GitLab access token with api/read_api scope." },
2941
+ category: "other",
2942
+ defaultConsistencyModel: "authoritative",
2943
+ baseUrl: { metadataKey: "baseUrl", fallback: "https://gitlab.com/api/v4" },
2944
+ credentialPlacement: { kind: "header", header: "PRIVATE-TOKEN" },
2945
+ test: { method: "GET", path: "/user" },
2946
+ capabilities: [
2947
+ {
2948
+ name: "projects.search",
2949
+ class: "read",
2950
+ description: "Search projects visible to the token.",
2951
+ parameters: {
2952
+ type: "object",
2953
+ properties: { search: { type: "string" }, per_page: { type: "integer", minimum: 1, maximum: 100 } },
2954
+ required: ["search"]
2955
+ },
2956
+ request: { method: "GET", path: "/projects", query: { search: "{search}", per_page: "{per_page}" } }
2957
+ },
2958
+ {
2959
+ name: "issues.search",
2960
+ class: "read",
2961
+ description: "Search issues in a project.",
2962
+ parameters: {
2963
+ type: "object",
2964
+ properties: { projectId: { type: "string" }, search: { type: "string" }, per_page: { type: "integer" } },
2965
+ required: ["projectId", "search"]
2966
+ },
2967
+ request: { method: "GET", path: "/projects/{projectId}/issues", query: { search: "{search}", per_page: "{per_page}" } }
2968
+ },
2969
+ {
2970
+ name: "issues.create",
2971
+ class: "mutation",
2972
+ description: "Create a GitLab project issue.",
2973
+ parameters: {
2974
+ type: "object",
2975
+ properties: { projectId: { type: "string" }, title: { type: "string" }, description: { type: "string" } },
2976
+ required: ["projectId", "title"]
2977
+ },
2978
+ request: { method: "POST", path: "/projects/{projectId}/issues", body: "args" },
2979
+ cas: "native-idempotency"
2980
+ },
2981
+ {
2982
+ name: "issues.update",
2983
+ class: "mutation",
2984
+ description: "Update a GitLab issue.",
2985
+ parameters: {
2986
+ type: "object",
2987
+ properties: { projectId: { type: "string" }, issueIid: { type: "integer" }, title: { type: "string" }, description: { type: "string" }, state_event: { type: "string" } },
2988
+ required: ["projectId", "issueIid"]
2989
+ },
2990
+ request: { method: "PUT", path: "/projects/{projectId}/issues/{issueIid}", body: "args" },
2991
+ cas: "etag-if-match"
2992
+ }
2993
+ ]
2994
+ });
2995
+
2996
+ // src/connectors/adapters/airtable.ts
2997
+ var baseTableParams = {
2998
+ type: "object",
2999
+ properties: {
3000
+ baseId: { type: "string" },
3001
+ tableName: { type: "string" }
3002
+ },
3003
+ required: ["baseId", "tableName"]
3004
+ };
3005
+ var airtableConnector = declarativeRestConnector({
3006
+ kind: "airtable",
3007
+ displayName: "Airtable",
3008
+ description: "Query and update Airtable records for lightweight operational databases.",
3009
+ auth: { kind: "api-key", hint: "Airtable personal access token." },
3010
+ category: "spreadsheet",
3011
+ defaultConsistencyModel: "authoritative",
3012
+ baseUrl: "https://api.airtable.com",
3013
+ test: { method: "GET", path: "/v0/meta/whoami" },
3014
+ capabilities: [
3015
+ {
3016
+ name: "records.list",
3017
+ class: "read",
3018
+ description: "List records in a table.",
3019
+ parameters: {
3020
+ ...baseTableParams,
3021
+ properties: {
3022
+ ...baseTableParams.properties,
3023
+ maxRecords: { type: "integer", minimum: 1, maximum: 100 },
3024
+ filterByFormula: { type: "string" }
3025
+ }
3026
+ },
3027
+ request: { method: "GET", path: "/v0/{baseId}/{tableName}", query: { maxRecords: "{maxRecords}", filterByFormula: "{filterByFormula}" } }
3028
+ },
3029
+ {
3030
+ name: "records.get",
3031
+ class: "read",
3032
+ description: "Read a single Airtable record.",
3033
+ parameters: {
3034
+ type: "object",
3035
+ properties: { baseId: { type: "string" }, tableName: { type: "string" }, recordId: { type: "string" } },
3036
+ required: ["baseId", "tableName", "recordId"]
3037
+ },
3038
+ request: { method: "GET", path: "/v0/{baseId}/{tableName}/{recordId}" }
3039
+ },
3040
+ {
3041
+ name: "records.create",
3042
+ class: "mutation",
3043
+ description: "Create an Airtable record.",
3044
+ parameters: {
3045
+ type: "object",
3046
+ properties: { baseId: { type: "string" }, tableName: { type: "string" }, fields: { type: "object" } },
3047
+ required: ["baseId", "tableName", "fields"]
3048
+ },
3049
+ request: { method: "POST", path: "/v0/{baseId}/{tableName}", body: { fields: "{fields}" } },
3050
+ cas: "native-idempotency"
3051
+ },
3052
+ {
3053
+ name: "records.update",
3054
+ class: "mutation",
3055
+ description: "Update an Airtable record.",
3056
+ parameters: {
3057
+ type: "object",
3058
+ properties: { baseId: { type: "string" }, tableName: { type: "string" }, recordId: { type: "string" }, fields: { type: "object" } },
3059
+ required: ["baseId", "tableName", "recordId", "fields"]
3060
+ },
3061
+ request: { method: "PATCH", path: "/v0/{baseId}/{tableName}/{recordId}", body: { fields: "{fields}" } },
3062
+ cas: "optimistic-read-verify"
3063
+ }
3064
+ ]
3065
+ });
3066
+
3067
+ // src/connectors/adapters/asana.ts
3068
+ var asanaConnector = declarativeRestConnector({
3069
+ kind: "asana",
3070
+ displayName: "Asana",
3071
+ description: "Search projects/tasks and create or update Asana tasks.",
3072
+ auth: { kind: "api-key", hint: "Asana personal access token." },
3073
+ category: "other",
3074
+ defaultConsistencyModel: "authoritative",
3075
+ baseUrl: "https://app.asana.com/api/1.0",
3076
+ test: { method: "GET", path: "/users/me" },
3077
+ capabilities: [
3078
+ {
3079
+ name: "projects.search",
3080
+ class: "read",
3081
+ description: "List or search projects in a workspace.",
3082
+ parameters: {
3083
+ type: "object",
3084
+ properties: { workspace: { type: "string" }, archived: { type: "boolean" }, limit: { type: "integer" } },
3085
+ required: ["workspace"]
3086
+ },
3087
+ request: { method: "GET", path: "/projects", query: { workspace: "{workspace}", archived: "{archived}", limit: "{limit}" } }
3088
+ },
3089
+ {
3090
+ name: "tasks.search",
3091
+ class: "read",
3092
+ description: "Search tasks in a workspace.",
3093
+ parameters: {
3094
+ type: "object",
3095
+ properties: { workspace: { type: "string" }, text: { type: "string" }, limit: { type: "integer" } },
3096
+ required: ["workspace"]
3097
+ },
3098
+ request: { method: "GET", path: "/workspaces/{workspace}/tasks/search", query: { text: "{text}", limit: "{limit}" } }
3099
+ },
3100
+ {
3101
+ name: "tasks.create",
3102
+ class: "mutation",
3103
+ description: "Create an Asana task.",
3104
+ parameters: {
3105
+ type: "object",
3106
+ properties: { data: { type: "object" } },
3107
+ required: ["data"]
3108
+ },
3109
+ request: { method: "POST", path: "/tasks", body: { data: "{data}" } },
3110
+ cas: "native-idempotency"
3111
+ },
3112
+ {
3113
+ name: "tasks.update",
3114
+ class: "mutation",
3115
+ description: "Update an Asana task.",
3116
+ parameters: {
3117
+ type: "object",
3118
+ properties: { taskGid: { type: "string" }, data: { type: "object" } },
3119
+ required: ["taskGid", "data"]
3120
+ },
3121
+ request: { method: "PUT", path: "/tasks/{taskGid}", body: { data: "{data}" } },
3122
+ cas: "optimistic-read-verify"
3123
+ }
3124
+ ]
3125
+ });
3126
+
3127
+ // src/connectors/adapters/salesforce.ts
3128
+ var salesforceConnector = declarativeRestConnector({
3129
+ kind: "salesforce",
3130
+ displayName: "Salesforce",
3131
+ description: "Query Salesforce records with SOQL and create or update sObjects.",
3132
+ auth: {
3133
+ kind: "oauth2",
3134
+ authorizationUrl: "https://login.salesforce.com/services/oauth2/authorize",
3135
+ tokenUrl: "https://login.salesforce.com/services/oauth2/token",
3136
+ scopes: ["api", "refresh_token"],
3137
+ clientIdEnv: "SALESFORCE_OAUTH_CLIENT_ID",
3138
+ clientSecretEnv: "SALESFORCE_OAUTH_CLIENT_SECRET"
3139
+ },
3140
+ category: "crm",
3141
+ defaultConsistencyModel: "authoritative",
3142
+ baseUrl: { metadataKey: "instanceUrl" },
3143
+ test: { method: "GET", path: "/services/data/v61.0/" },
3144
+ capabilities: [
3145
+ {
3146
+ name: "records.query",
3147
+ class: "read",
3148
+ description: "Run a SOQL query.",
3149
+ parameters: {
3150
+ type: "object",
3151
+ properties: { q: { type: "string" } },
3152
+ required: ["q"]
3153
+ },
3154
+ request: { method: "GET", path: "/services/data/v61.0/query", query: { q: "{q}" } },
3155
+ requiredScopes: ["api"]
3156
+ },
3157
+ {
3158
+ name: "records.get",
3159
+ class: "read",
3160
+ description: "Read a Salesforce sObject record.",
3161
+ parameters: {
3162
+ type: "object",
3163
+ properties: { objectName: { type: "string" }, recordId: { type: "string" } },
3164
+ required: ["objectName", "recordId"]
3165
+ },
3166
+ request: { method: "GET", path: "/services/data/v61.0/sobjects/{objectName}/{recordId}" },
3167
+ requiredScopes: ["api"]
3168
+ },
3169
+ {
3170
+ name: "records.create",
3171
+ class: "mutation",
3172
+ description: "Create a Salesforce sObject record.",
3173
+ parameters: {
3174
+ type: "object",
3175
+ properties: { objectName: { type: "string" }, fields: { type: "object" } },
3176
+ required: ["objectName", "fields"]
3177
+ },
3178
+ request: { method: "POST", path: "/services/data/v61.0/sobjects/{objectName}", body: "{fields}" },
3179
+ cas: "native-idempotency",
3180
+ requiredScopes: ["api"]
3181
+ },
3182
+ {
3183
+ name: "records.update",
3184
+ class: "mutation",
3185
+ description: "Update a Salesforce sObject record.",
3186
+ parameters: {
3187
+ type: "object",
3188
+ properties: { objectName: { type: "string" }, recordId: { type: "string" }, fields: { type: "object" } },
3189
+ required: ["objectName", "recordId", "fields"]
3190
+ },
3191
+ request: { method: "PATCH", path: "/services/data/v61.0/sobjects/{objectName}/{recordId}", body: "{fields}" },
3192
+ cas: "etag-if-match",
3193
+ requiredScopes: ["api"]
3194
+ }
3195
+ ]
3196
+ });
3197
+
2657
3198
  // src/catalog.ts
2658
3199
  var riskRank = {
2659
3200
  read: 0,
@@ -3229,6 +3770,317 @@ function unique2(values) {
3229
3770
  return [...new Set(values)];
3230
3771
  }
3231
3772
 
3773
+ // src/coverage-catalog.ts
3774
+ var DEFAULT_PROVIDER_KINDS = ["first_party", "nango", "pipedream", "activepieces", "custom"];
3775
+ var COVERAGE_SPECS = [
3776
+ ["gmail", "Gmail", "email", "email", "tier_0", "email,google,workspace,inbox"],
3777
+ ["outlook-mail", "Outlook Mail", "email", "email", "tier_0", "email,microsoft,office,inbox"],
3778
+ ["google-calendar", "Google Calendar", "calendar", "calendar", "tier_0", "calendar,google,workspace,scheduling"],
3779
+ ["outlook-calendar", "Outlook Calendar", "calendar", "calendar", "tier_0", "calendar,microsoft,office,scheduling"],
3780
+ ["slack", "Slack", "chat", "chat", "tier_0", "chat,collaboration,internal-comms"],
3781
+ ["microsoft-teams", "Microsoft Teams", "chat", "chat", "tier_0", "chat,microsoft,collaboration"],
3782
+ ["google-drive", "Google Drive", "storage", "storage", "tier_0", "files,google,workspace,storage"],
3783
+ ["onedrive", "OneDrive", "storage", "storage", "tier_0", "files,microsoft,office,storage"],
3784
+ ["dropbox", "Dropbox", "storage", "storage", "tier_1", "files,storage"],
3785
+ ["box", "Box", "storage", "storage", "tier_1", "files,enterprise,storage"],
3786
+ ["google-docs", "Google Docs", "docs", "docs", "tier_0", "docs,google,workspace"],
3787
+ ["google-sheets", "Google Sheets", "database", "database", "tier_0", "sheets,spreadsheet,google,database"],
3788
+ ["microsoft-excel", "Microsoft Excel", "database", "database", "tier_0", "sheets,spreadsheet,microsoft,database"],
3789
+ ["notion", "Notion", "docs", "docs", "tier_0", "docs,wiki,knowledge"],
3790
+ ["airtable", "Airtable", "database", "database", "tier_0", "database,spreadsheet,ops"],
3791
+ ["coda", "Coda", "docs", "docs", "tier_1", "docs,wiki,ops"],
3792
+ ["confluence", "Confluence", "docs", "docs", "tier_1", "docs,wiki,atlassian"],
3793
+ ["sharepoint", "SharePoint", "storage", "storage", "tier_1", "files,microsoft,enterprise"],
3794
+ ["hubspot", "HubSpot", "crm", "crm", "tier_0", "crm,sales,marketing"],
3795
+ ["salesforce", "Salesforce", "crm", "crm", "tier_0", "crm,sales,enterprise"],
3796
+ ["pipedrive", "Pipedrive", "crm", "crm", "tier_1", "crm,sales"],
3797
+ ["zoho-crm", "Zoho CRM", "crm", "crm", "tier_1", "crm,sales"],
3798
+ ["close", "Close", "crm", "crm", "tier_1", "crm,sales"],
3799
+ ["attio", "Attio", "crm", "crm", "tier_1", "crm,sales,startups"],
3800
+ ["linear", "Linear", "workflow", "project", "tier_0", "project,engineering,tickets"],
3801
+ ["jira", "Jira", "workflow", "project", "tier_0", "project,engineering,tickets,atlassian"],
3802
+ ["github", "GitHub", "workflow", "dev", "tier_0", "code,dev,issues,git"],
3803
+ ["gitlab", "GitLab", "workflow", "dev", "tier_1", "code,dev,issues,git"],
3804
+ ["bitbucket", "Bitbucket", "workflow", "dev", "tier_2", "code,dev,git,atlassian"],
3805
+ ["asana", "Asana", "workflow", "project", "tier_1", "project,tasks"],
3806
+ ["trello", "Trello", "workflow", "project", "tier_1", "project,tasks,atlassian"],
3807
+ ["monday", "monday.com", "workflow", "project", "tier_1", "project,tasks,ops"],
3808
+ ["clickup", "ClickUp", "workflow", "project", "tier_1", "project,tasks,ops"],
3809
+ ["basecamp", "Basecamp", "workflow", "project", "tier_2", "project,tasks"],
3810
+ ["zendesk", "Zendesk", "crm", "support", "tier_0", "support,tickets,customer-success"],
3811
+ ["intercom", "Intercom", "crm", "support", "tier_0", "support,chat,customer-success"],
3812
+ ["freshdesk", "Freshdesk", "crm", "support", "tier_1", "support,tickets"],
3813
+ ["helpscout", "Help Scout", "crm", "support", "tier_1", "support,tickets"],
3814
+ ["front", "Front", "email", "support", "tier_1", "support,email,shared-inbox"],
3815
+ ["gorgias", "Gorgias", "crm", "support", "tier_1", "support,ecommerce"],
3816
+ ["stripe", "Stripe", "workflow", "finance", "tier_0", "payments,billing,finance"],
3817
+ ["quickbooks", "QuickBooks", "workflow", "finance", "tier_0", "accounting,finance"],
3818
+ ["xero", "Xero", "workflow", "finance", "tier_1", "accounting,finance"],
3819
+ ["netsuite", "NetSuite", "workflow", "finance", "tier_1", "erp,finance,enterprise"],
3820
+ ["sage", "Sage", "workflow", "finance", "tier_2", "accounting,finance"],
3821
+ ["plaid", "Plaid", "workflow", "finance", "tier_1", "banking,finance"],
3822
+ ["shopify", "Shopify", "workflow", "commerce", "tier_0", "ecommerce,orders,commerce"],
3823
+ ["woocommerce", "WooCommerce", "workflow", "commerce", "tier_1", "ecommerce,orders,wordpress"],
3824
+ ["bigcommerce", "BigCommerce", "workflow", "commerce", "tier_1", "ecommerce,orders"],
3825
+ ["amazon-seller-central", "Amazon Seller Central", "workflow", "commerce", "tier_1", "marketplace,ecommerce"],
3826
+ ["ebay", "eBay", "workflow", "commerce", "tier_2", "marketplace,ecommerce"],
3827
+ ["etsy", "Etsy", "workflow", "commerce", "tier_2", "marketplace,ecommerce"],
3828
+ ["mailchimp", "Mailchimp", "workflow", "marketing", "tier_0", "email-marketing,marketing"],
3829
+ ["klaviyo", "Klaviyo", "workflow", "marketing", "tier_0", "email-marketing,ecommerce,marketing"],
3830
+ ["marketo", "Marketo", "workflow", "marketing", "tier_1", "marketing,enterprise"],
3831
+ ["braze", "Braze", "workflow", "marketing", "tier_1", "marketing,lifecycle"],
3832
+ ["customer-io", "Customer.io", "workflow", "marketing", "tier_1", "marketing,lifecycle"],
3833
+ ["sendgrid", "SendGrid", "email", "email", "tier_1", "email,transactional"],
3834
+ ["postmark", "Postmark", "email", "email", "tier_1", "email,transactional"],
3835
+ ["twilio", "Twilio", "chat", "chat", "tier_0", "sms,voice,communications"],
3836
+ ["discord", "Discord", "chat", "chat", "tier_1", "chat,community"],
3837
+ ["telegram", "Telegram", "chat", "chat", "tier_1", "chat,community"],
3838
+ ["whatsapp-business", "WhatsApp Business", "chat", "chat", "tier_1", "chat,meta,customer-comms"],
3839
+ ["facebook-pages", "Facebook Pages", "workflow", "marketing", "tier_1", "social,meta,marketing"],
3840
+ ["instagram-business", "Instagram Business", "workflow", "marketing", "tier_1", "social,meta,marketing"],
3841
+ ["linkedin", "LinkedIn", "workflow", "sales", "tier_1", "social,sales,gtm"],
3842
+ ["x-twitter", "X / Twitter", "workflow", "marketing", "tier_1", "social,marketing"],
3843
+ ["youtube", "YouTube", "storage", "storage", "tier_1", "video,content"],
3844
+ ["tiktok", "TikTok", "workflow", "marketing", "tier_2", "social,video,marketing"],
3845
+ ["google-analytics", "Google Analytics", "database", "analytics", "tier_0", "analytics,web,marketing"],
3846
+ ["mixpanel", "Mixpanel", "database", "analytics", "tier_1", "analytics,product"],
3847
+ ["amplitude", "Amplitude", "database", "analytics", "tier_1", "analytics,product"],
3848
+ ["segment", "Segment", "database", "analytics", "tier_1", "analytics,cdp"],
3849
+ ["snowflake", "Snowflake", "database", "database", "tier_0", "warehouse,data"],
3850
+ ["bigquery", "BigQuery", "database", "database", "tier_0", "warehouse,google,data"],
3851
+ ["redshift", "Redshift", "database", "database", "tier_1", "warehouse,aws,data"],
3852
+ ["postgres", "Postgres", "database", "database", "tier_0", "database,sql"],
3853
+ ["mysql", "MySQL", "database", "database", "tier_1", "database,sql"],
3854
+ ["mongodb", "MongoDB", "database", "database", "tier_1", "database,nosql"],
3855
+ ["supabase", "Supabase", "database", "database", "tier_1", "database,postgres"],
3856
+ ["firebase", "Firebase", "database", "database", "tier_1", "database,google,app"],
3857
+ ["redis", "Redis", "database", "database", "tier_2", "database,cache"],
3858
+ ["aws-s3", "Amazon S3", "storage", "storage", "tier_0", "files,aws,storage"],
3859
+ ["aws-lambda", "AWS Lambda", "workflow", "dev", "tier_1", "aws,serverless,dev"],
3860
+ ["aws-cloudwatch", "AWS CloudWatch", "database", "analytics", "tier_1", "aws,logs,observability"],
3861
+ ["google-cloud-storage", "Google Cloud Storage", "storage", "storage", "tier_1", "files,gcp,storage"],
3862
+ ["azure-blob-storage", "Azure Blob Storage", "storage", "storage", "tier_1", "files,azure,storage"],
3863
+ ["vercel", "Vercel", "workflow", "dev", "tier_1", "deployments,dev"],
3864
+ ["netlify", "Netlify", "workflow", "dev", "tier_2", "deployments,dev"],
3865
+ ["cloudflare", "Cloudflare", "workflow", "dev", "tier_1", "edge,dev,dns"],
3866
+ ["sentry", "Sentry", "workflow", "dev", "tier_1", "errors,observability,dev"],
3867
+ ["datadog", "Datadog", "database", "analytics", "tier_1", "observability,logs,metrics"],
3868
+ ["new-relic", "New Relic", "database", "analytics", "tier_2", "observability,logs,metrics"],
3869
+ ["pagerduty", "PagerDuty", "workflow", "project", "tier_1", "incident,on-call"],
3870
+ ["opsgenie", "Opsgenie", "workflow", "project", "tier_2", "incident,on-call,atlassian"],
3871
+ ["okta", "Okta", "internal", "workflow", "tier_1", "identity,security"],
3872
+ ["auth0", "Auth0", "internal", "workflow", "tier_1", "identity,security"],
3873
+ ["workday", "Workday", "workflow", "hr", "tier_1", "hr,finance,enterprise"],
3874
+ ["bamboohr", "BambooHR", "workflow", "hr", "tier_1", "hr,people"],
3875
+ ["greenhouse", "Greenhouse", "workflow", "hr", "tier_1", "recruiting,hr"],
3876
+ ["lever", "Lever", "workflow", "hr", "tier_1", "recruiting,hr"],
3877
+ ["gusto", "Gusto", "workflow", "hr", "tier_1", "payroll,hr"],
3878
+ ["rippling", "Rippling", "workflow", "hr", "tier_1", "hr,it,identity"],
3879
+ ["docusign", "DocuSign", "docs", "docs", "tier_1", "contracts,signature,legal"],
3880
+ ["pandadoc", "PandaDoc", "docs", "docs", "tier_1", "contracts,signature,sales"],
3881
+ ["hellosign", "Dropbox Sign", "docs", "docs", "tier_2", "contracts,signature"],
3882
+ ["clio", "Clio", "workflow", "project", "tier_1", "legal,practice-management"],
3883
+ ["ironclad", "Ironclad", "docs", "docs", "tier_1", "legal,contracts"],
3884
+ ["lexisnexis", "LexisNexis", "docs", "docs", "tier_2", "legal,research"],
3885
+ ["calendly", "Calendly", "calendar", "calendar", "tier_0", "scheduling,calendar"],
3886
+ ["cal-com", "Cal.com", "calendar", "calendar", "tier_1", "scheduling,calendar"],
3887
+ ["zoom", "Zoom", "calendar", "calendar", "tier_0", "meetings,video,calendar"],
3888
+ ["google-meet", "Google Meet", "calendar", "calendar", "tier_1", "meetings,google,video"],
3889
+ ["microsoft-graph", "Microsoft Graph", "internal", "workflow", "tier_0", "microsoft,enterprise,identity"],
3890
+ ["openai", "OpenAI", "workflow", "ai", "tier_0", "ai,llm"],
3891
+ ["anthropic", "Anthropic", "workflow", "ai", "tier_1", "ai,llm"],
3892
+ ["gemini", "Google Gemini", "workflow", "ai", "tier_1", "ai,llm,google"],
3893
+ ["huggingface", "Hugging Face", "workflow", "ai", "tier_1", "ai,models"],
3894
+ ["pinecone", "Pinecone", "database", "database", "tier_1", "vector,database,ai"],
3895
+ ["weaviate", "Weaviate", "database", "database", "tier_1", "vector,database,ai"],
3896
+ ["qdrant", "Qdrant", "database", "database", "tier_1", "vector,database,ai"],
3897
+ ["zapier", "Zapier", "workflow", "workflow", "tier_1", "automation,workflow"],
3898
+ ["make", "Make", "workflow", "workflow", "tier_1", "automation,workflow"],
3899
+ ["nango", "Nango", "workflow", "workflow", "tier_1", "integration-platform,oauth"],
3900
+ ["pipedream", "Pipedream", "workflow", "workflow", "tier_1", "integration-platform,workflow"],
3901
+ ["activepieces", "Activepieces", "workflow", "workflow", "tier_1", "automation,workflow,open-source"],
3902
+ ["webhook", "Generic Webhook", "webhook", "webhook", "tier_0", "webhook,http,events", "none"],
3903
+ ["http", "HTTP Request", "workflow", "webhook", "tier_0", "http,api,webhook", "none"],
3904
+ ["rss", "RSS", "webhook", "webhook", "tier_1", "feeds,content", "none"],
3905
+ ["zapier-transfer", "Zapier Transfer", "workflow", "workflow", "long_tail", "automation,migration"],
3906
+ ["typeform", "Typeform", "workflow", "marketing", "tier_1", "forms,marketing"],
3907
+ ["google-forms", "Google Forms", "workflow", "marketing", "tier_1", "forms,google"],
3908
+ ["jotform", "Jotform", "workflow", "marketing", "tier_2", "forms"],
3909
+ ["webflow", "Webflow", "workflow", "marketing", "tier_1", "cms,website"],
3910
+ ["wordpress", "WordPress", "workflow", "marketing", "tier_1", "cms,website"],
3911
+ ["contentful", "Contentful", "docs", "docs", "tier_1", "cms,content"],
3912
+ ["sanity", "Sanity", "docs", "docs", "tier_1", "cms,content"],
3913
+ ["figma", "Figma", "docs", "docs", "tier_0", "design,creative"],
3914
+ ["canva", "Canva", "docs", "docs", "tier_1", "design,creative"],
3915
+ ["adobe-creative-cloud", "Adobe Creative Cloud", "storage", "storage", "tier_1", "design,creative,files"],
3916
+ ["miro", "Miro", "docs", "docs", "tier_1", "whiteboard,collaboration"],
3917
+ ["figjam", "FigJam", "docs", "docs", "tier_2", "whiteboard,design"]
3918
+ ];
3919
+ function listIntegrationCoverageSpecs() {
3920
+ return COVERAGE_SPECS.map(([id, title, category, actionPack2, priority, domains, auth = "oauth2"]) => ({
3921
+ id,
3922
+ title,
3923
+ category,
3924
+ actionPack: actionPack2,
3925
+ priority,
3926
+ auth,
3927
+ providerKinds: providerKindsFor(auth),
3928
+ domains: domains.split(",").map((domain) => domain.trim()).filter(Boolean),
3929
+ scopes: scopesFor(id, actionPack2)
3930
+ }));
3931
+ }
3932
+ function buildIntegrationCoverageConnectors(options = {}) {
3933
+ const providerId = options.providerId ?? "coverage";
3934
+ return listIntegrationCoverageSpecs().filter((spec) => !options.priorities || options.priorities.includes(spec.priority)).filter((spec) => !options.categories || options.categories.includes(spec.category)).filter((spec) => !options.actionPacks || options.actionPacks.includes(spec.actionPack)).map((spec) => specToConnector(spec, providerId));
3935
+ }
3936
+ function integrationCoverageChecklistMarkdown() {
3937
+ const specs = listIntegrationCoverageSpecs();
3938
+ const lines = [
3939
+ "# Agent Integrations Coverage Checklist",
3940
+ "",
3941
+ "Generated from `listIntegrationCoverageSpecs()`. Catalog presence means the product can plan/request/connect the integration; executable first-party adapters are promoted separately behind the same provider contract.",
3942
+ "",
3943
+ "## Summary",
3944
+ "",
3945
+ `- Total cataloged integrations: ${specs.length}`,
3946
+ `- Tier 0: ${specs.filter((spec) => spec.priority === "tier_0").length}`,
3947
+ `- Tier 1: ${specs.filter((spec) => spec.priority === "tier_1").length}`,
3948
+ `- Tier 2: ${specs.filter((spec) => spec.priority === "tier_2").length}`,
3949
+ `- Long tail: ${specs.filter((spec) => spec.priority === "long_tail").length}`,
3950
+ "",
3951
+ "## Checklist",
3952
+ ""
3953
+ ];
3954
+ for (const spec of specs) {
3955
+ lines.push(`- [ ] ${spec.priority} / ${spec.category} / ${spec.title} (${spec.id}) - ${spec.domains.join(", ")}`);
3956
+ }
3957
+ return `${lines.join("\n")}
3958
+ `;
3959
+ }
3960
+ function specToConnector(spec, providerId) {
3961
+ const actions = actionPack(spec.actionPack, spec.scopes ?? []);
3962
+ return {
3963
+ id: spec.id,
3964
+ providerId,
3965
+ title: spec.title,
3966
+ category: spec.category,
3967
+ auth: spec.auth,
3968
+ scopes: spec.scopes ?? [],
3969
+ actions,
3970
+ triggers: triggersFor(spec.actionPack, spec.scopes ?? []),
3971
+ metadata: {
3972
+ source: "coverage-catalog",
3973
+ priority: spec.priority,
3974
+ domains: spec.domains,
3975
+ providerKinds: spec.providerKinds,
3976
+ executable: false
3977
+ }
3978
+ };
3979
+ }
3980
+ function actionPack(pack, scopes) {
3981
+ const readScope = scopes.find((scope2) => scope2.endsWith(".read")) ?? scopes[0];
3982
+ const writeScope = scopes.find((scope2) => scope2.endsWith(".write")) ?? scopes[1] ?? readScope;
3983
+ const scope = (value) => value ? [value] : [];
3984
+ const read = (id, title, description) => ({
3985
+ id,
3986
+ title,
3987
+ description,
3988
+ risk: "read",
3989
+ requiredScopes: scope(readScope),
3990
+ dataClass: dataClassFor(pack),
3991
+ inputSchema: objectSchema()
3992
+ });
3993
+ const write = (id, title, description) => ({
3994
+ id,
3995
+ title,
3996
+ description,
3997
+ risk: "write",
3998
+ requiredScopes: scope(writeScope),
3999
+ dataClass: dataClassFor(pack),
4000
+ approvalRequired: true,
4001
+ inputSchema: objectSchema()
4002
+ });
4003
+ const destructive = (id, title, description) => ({
4004
+ id,
4005
+ title,
4006
+ description,
4007
+ risk: "destructive",
4008
+ requiredScopes: scope(writeScope),
4009
+ dataClass: dataClassFor(pack),
4010
+ approvalRequired: true,
4011
+ inputSchema: objectSchema()
4012
+ });
4013
+ switch (pack) {
4014
+ case "email":
4015
+ return [read("messages.search", "Search messages", "Search messages and threads."), read("messages.read", "Read message", "Read a message by id."), write("drafts.create", "Create draft", "Create an email draft."), write("messages.send", "Send message", "Send or reply to an email message.")];
4016
+ case "calendar":
4017
+ return [read("events.search", "Search events", "Search calendar events."), read("availability.read", "Read availability", "Read availability windows."), write("events.create", "Create event", "Create a calendar event."), write("events.update", "Update event", "Update a calendar event."), destructive("events.cancel", "Cancel event", "Cancel a calendar event.")];
4018
+ case "chat":
4019
+ return [read("messages.search", "Search messages", "Search channel or direct messages."), read("channels.list", "List channels", "List channels or rooms."), write("messages.post", "Post message", "Post a message."), write("threads.reply", "Reply in thread", "Reply to a thread or conversation.")];
4020
+ case "crm":
4021
+ return [read("records.search", "Search records", "Search contacts, companies, and deals."), read("records.read", "Read record", "Read a CRM record."), write("records.upsert", "Upsert record", "Create or update a CRM record."), write("notes.create", "Create note", "Add a note or activity.")];
4022
+ case "storage":
4023
+ return [read("files.search", "Search files", "Search files and folders."), read("files.read", "Read file", "Read file metadata or content."), write("files.upload", "Upload file", "Upload a file."), write("files.update", "Update file", "Update file metadata or content.")];
4024
+ case "docs":
4025
+ return [read("documents.search", "Search documents", "Search documents or pages."), read("documents.read", "Read document", "Read a document."), write("documents.create", "Create document", "Create a document or page."), write("documents.update", "Update document", "Update a document or page.")];
4026
+ case "database":
4027
+ return [read("records.query", "Query records", "Query rows, records, or objects."), read("records.read", "Read record", "Read one row, record, or object."), write("records.upsert", "Upsert record", "Create or update a row, record, or object."), destructive("records.delete", "Delete record", "Delete a row, record, or object.")];
4028
+ case "project":
4029
+ return [read("tasks.search", "Search tasks", "Search tasks, tickets, or issues."), read("tasks.read", "Read task", "Read a task, ticket, or issue."), write("tasks.create", "Create task", "Create a task, ticket, or issue."), write("tasks.update", "Update task", "Update a task, ticket, or issue.")];
4030
+ case "support":
4031
+ return [read("tickets.search", "Search tickets", "Search support tickets or conversations."), read("customers.read", "Read customer", "Read a customer profile."), write("tickets.reply", "Reply to ticket", "Reply to a support ticket."), write("tickets.update", "Update ticket", "Update ticket status, tags, or assignee.")];
4032
+ case "marketing":
4033
+ return [read("contacts.search", "Search contacts", "Search marketing contacts or audiences."), read("campaigns.read", "Read campaign", "Read campaign metadata and performance."), write("contacts.upsert", "Upsert contact", "Create or update a contact."), write("campaigns.create", "Create campaign", "Create a campaign draft.")];
4034
+ case "sales":
4035
+ return [read("prospects.search", "Search prospects", "Search prospects, leads, or accounts."), read("activities.read", "Read activities", "Read sales activity history."), write("prospects.upsert", "Upsert prospect", "Create or update a prospect."), write("sequence.enqueue", "Enroll in sequence", "Enroll a prospect in a sales sequence.")];
4036
+ case "commerce":
4037
+ return [read("orders.search", "Search orders", "Search orders."), read("customers.read", "Read customer", "Read customer and purchase history."), write("orders.update", "Update order", "Update order metadata or fulfillment state."), write("products.update", "Update product", "Update product metadata.")];
4038
+ case "finance":
4039
+ return [read("transactions.search", "Search transactions", "Search transactions, invoices, or payments."), read("accounts.read", "Read account", "Read account or customer financial record."), write("invoices.create", "Create invoice", "Create an invoice or payment object."), write("records.sync", "Sync record", "Sync a finance or accounting record.")];
4040
+ case "hr":
4041
+ return [read("people.search", "Search people", "Search employees, candidates, or contractors."), read("people.read", "Read person", "Read a person profile."), write("people.update", "Update person", "Update a person profile."), write("events.create", "Create HR event", "Create a recruiting or HR event.")];
4042
+ case "dev":
4043
+ return [read("resources.search", "Search resources", "Search issues, repos, deployments, logs, or incidents."), read("resources.read", "Read resource", "Read a developer resource."), write("resources.create", "Create resource", "Create an issue, deployment, incident, or config."), write("resources.update", "Update resource", "Update a developer resource.")];
4044
+ case "ai":
4045
+ return [read("models.list", "List models", "List available models or endpoints."), write("responses.create", "Create response", "Create an AI response or job."), write("embeddings.create", "Create embeddings", "Create embeddings or vector jobs."), read("usage.read", "Read usage", "Read usage metadata.")];
4046
+ case "analytics":
4047
+ return [read("reports.query", "Query reports", "Query analytics reports."), read("events.search", "Search events", "Search analytics events."), write("events.track", "Track event", "Track an analytics event."), write("audiences.sync", "Sync audience", "Sync an audience or cohort.")];
4048
+ case "workflow":
4049
+ return [read("runs.search", "Search runs", "Search workflow runs or jobs."), read("templates.list", "List templates", "List workflow templates."), write("runs.start", "Start run", "Start a workflow run."), write("webhooks.dispatch", "Dispatch webhook", "Dispatch a workflow webhook.")];
4050
+ case "webhook":
4051
+ return [write("requests.send", "Send request", "Send an HTTP request or webhook event."), read("events.search", "Search events", "Search received webhook events."), write("subscriptions.create", "Create subscription", "Create a webhook subscription."), destructive("subscriptions.delete", "Delete subscription", "Delete a webhook subscription.")];
4052
+ }
4053
+ }
4054
+ function triggersFor(pack, scopes) {
4055
+ const readScope = scopes.find((scope) => scope.endsWith(".read")) ?? scopes[0];
4056
+ const requiredScopes = readScope ? [readScope] : [];
4057
+ if (pack === "email") return [{ id: "message.received", title: "Message received", requiredScopes, dataClass: "private" }];
4058
+ if (pack === "calendar") return [{ id: "event.changed", title: "Event changed", requiredScopes, dataClass: "private" }];
4059
+ if (pack === "chat") return [{ id: "message.posted", title: "Message posted", requiredScopes, dataClass: "private" }];
4060
+ if (pack === "crm") return [{ id: "record.changed", title: "Record changed", requiredScopes, dataClass: "private" }];
4061
+ if (pack === "support") return [{ id: "ticket.changed", title: "Ticket changed", requiredScopes, dataClass: "private" }];
4062
+ if (pack === "commerce") return [{ id: "order.changed", title: "Order changed", requiredScopes, dataClass: "sensitive" }];
4063
+ if (pack === "finance") return [{ id: "transaction.changed", title: "Transaction changed", requiredScopes, dataClass: "sensitive" }];
4064
+ if (pack === "workflow" || pack === "webhook") return [{ id: "event.received", title: "Event received", requiredScopes, dataClass: "internal" }];
4065
+ return void 0;
4066
+ }
4067
+ function scopesFor(id, pack) {
4068
+ if (pack === "webhook") return [];
4069
+ return [`${id}.read`, `${id}.write`];
4070
+ }
4071
+ function providerKindsFor(auth) {
4072
+ if (auth === "none") return ["first_party", "pipedream", "activepieces", "custom"];
4073
+ return DEFAULT_PROVIDER_KINDS;
4074
+ }
4075
+ function dataClassFor(pack) {
4076
+ if (pack === "finance" || pack === "commerce" || pack === "hr") return "sensitive";
4077
+ if (pack === "workflow" || pack === "webhook" || pack === "dev" || pack === "analytics") return "internal";
4078
+ return "private";
4079
+ }
4080
+ function objectSchema() {
4081
+ return { type: "object", additionalProperties: true, properties: {} };
4082
+ }
4083
+
3232
4084
  // src/index.ts
3233
4085
  var IntegrationError = class extends Error {
3234
4086
  constructor(message, code) {
@@ -3563,8 +4415,11 @@ export {
3563
4415
  ResourceContention,
3564
4416
  StaticIntegrationPolicyEngine,
3565
4417
  _resetPendingFlowsForTests,
4418
+ airtableConnector,
4419
+ asanaConnector,
3566
4420
  assertValidConnectorManifest,
3567
4421
  buildApprovalRequest,
4422
+ buildIntegrationCoverageConnectors,
3568
4423
  buildIntegrationInvocationEnvelope,
3569
4424
  buildIntegrationToolCatalog,
3570
4425
  consumePendingFlow,
@@ -3572,16 +4427,21 @@ export {
3572
4427
  createDefaultIntegrationPolicyEngine,
3573
4428
  createHttpIntegrationProvider,
3574
4429
  createMockIntegrationProvider,
4430
+ declarativeRestConnector,
3575
4431
  exchangeAuthorizationCode,
3576
4432
  firstHeader,
4433
+ githubConnector,
4434
+ gitlabConnector,
3577
4435
  googleCalendar,
3578
4436
  googleSheets,
3579
4437
  hubspot,
3580
4438
  importGraphqlConnector,
3581
4439
  importMcpConnector,
3582
4440
  importOpenApiConnector,
4441
+ integrationCoverageChecklistMarkdown,
3583
4442
  integrationToolName,
3584
4443
  invocationRequestFromEnvelope,
4444
+ listIntegrationCoverageSpecs,
3585
4445
  manifestToConnector,
3586
4446
  microsoftCalendar,
3587
4447
  normalizeIntegrationResult,
@@ -3592,6 +4452,7 @@ export {
3592
4452
  redactCapability,
3593
4453
  redactInvocationEnvelope,
3594
4454
  refreshAccessToken,
4455
+ salesforceConnector,
3595
4456
  sanitizeConnection,
3596
4457
  searchIntegrationTools,
3597
4458
  signCapability,