@tangle-network/agent-integrations 0.53.49 → 0.53.51

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.
Files changed (50) hide show
  1. package/dist/catalog.d.ts +2 -2
  2. package/dist/catalog.js +8 -8
  3. package/dist/{chunk-H5UCSRF4.js → chunk-BYTP5QJQ.js} +718 -763
  4. package/dist/{chunk-H5UCSRF4.js.map → chunk-BYTP5QJQ.js.map} +1 -1
  5. package/dist/{chunk-5UCHLQ3D.js → chunk-CJ6SZNMU.js} +18 -6
  6. package/dist/chunk-CJ6SZNMU.js.map +1 -0
  7. package/dist/{chunk-ZZA4HOBE.js → chunk-LIY4A33C.js} +2 -2
  8. package/dist/{chunk-W72KPXXX.js → chunk-P4YUWB77.js} +30 -1
  9. package/dist/chunk-P4YUWB77.js.map +1 -0
  10. package/dist/{chunk-GUZA3U6T.js → chunk-R4KVF4KT.js} +104 -27
  11. package/dist/chunk-R4KVF4KT.js.map +1 -0
  12. package/dist/{chunk-UI3U62H6.js → chunk-RBCF44OD.js} +2 -2
  13. package/dist/{chunk-ZSXRS7D7.js → chunk-VV73V64K.js} +10 -6
  14. package/dist/chunk-VV73V64K.js.map +1 -0
  15. package/dist/{chunk-KBYYTHXQ.js → chunk-W2FFWDJ7.js} +2 -2
  16. package/dist/connect/index.d.ts +2 -2
  17. package/dist/connect/index.js +2 -2
  18. package/dist/connectors/adapters/index.d.ts +8 -11
  19. package/dist/connectors/adapters/index.js +2 -2
  20. package/dist/connectors/index.d.ts +25 -12
  21. package/dist/connectors/index.js +13 -3
  22. package/dist/{consumer-DrLnbqYt.d.ts → consumer-48BUPeUQ.d.ts} +1 -1
  23. package/dist/consumer.d.ts +3 -3
  24. package/dist/consumer.js +2 -2
  25. package/dist/{core-types-D26cY5tD.d.ts → core-types-BR9Gv6hE.d.ts} +1 -1
  26. package/dist/coverage-catalog.d.ts +2 -2
  27. package/dist/{importers-CQKts3pm.d.ts → importers-0vMRe5jJ.d.ts} +1 -1
  28. package/dist/index.d.ts +9 -9
  29. package/dist/index.js +18 -8
  30. package/dist/mcp.d.ts +3 -3
  31. package/dist/mcp.js +8 -8
  32. package/dist/middleware/index.d.ts +2 -2
  33. package/dist/middleware/index.js +2 -2
  34. package/dist/registry.d.ts +2 -2
  35. package/dist/registry.js +8 -8
  36. package/dist/runtime.d.ts +2 -2
  37. package/dist/runtime.js +8 -8
  38. package/dist/specs.d.ts +9 -2
  39. package/dist/specs.js +4 -4
  40. package/dist/{tangle-id-BCOVbWrP.d.ts → tangle-id-BRtXszIF.d.ts} +1 -1
  41. package/dist/{types-DpKn0frG.d.ts → types-Hy58Fb8T.d.ts} +17 -1
  42. package/docs/integration-execution-matrix.json +36 -91
  43. package/package.json +1 -1
  44. package/dist/chunk-5UCHLQ3D.js.map +0 -1
  45. package/dist/chunk-GUZA3U6T.js.map +0 -1
  46. package/dist/chunk-W72KPXXX.js.map +0 -1
  47. package/dist/chunk-ZSXRS7D7.js.map +0 -1
  48. /package/dist/{chunk-ZZA4HOBE.js.map → chunk-LIY4A33C.js.map} +0 -0
  49. /package/dist/{chunk-UI3U62H6.js.map → chunk-RBCF44OD.js.map} +0 -0
  50. /package/dist/{chunk-KBYYTHXQ.js.map → chunk-W2FFWDJ7.js.map} +0 -0
@@ -14,7 +14,7 @@ import {
14
14
  TangleIdentityUnreachableError,
15
15
  createTangleIdentityClient,
16
16
  tangleIdentity
17
- } from "./chunk-W72KPXXX.js";
17
+ } from "./chunk-P4YUWB77.js";
18
18
  import {
19
19
  __export
20
20
  } from "./chunk-PZ5AY32C.js";
@@ -1146,7 +1146,7 @@ function hasHttpsHostnameSuffix(value, suffix) {
1146
1146
  try {
1147
1147
  const url = new URL(value);
1148
1148
  const normalized = suffix.toLowerCase();
1149
- return url.protocol === "https:" && normalized.startsWith(".") && url.hostname.toLowerCase().endsWith(normalized);
1149
+ return url.protocol === "https:" && !url.username && !url.password && !url.port && !url.search && !url.hash && normalized.startsWith(".") && url.hostname.toLowerCase().endsWith(normalized);
1150
1150
  } catch {
1151
1151
  return false;
1152
1152
  }
@@ -1645,7 +1645,325 @@ function membershipCapability(name, method, description) {
1645
1645
  }
1646
1646
 
1647
1647
  // src/connectors/adapters/client-credentials-rest.ts
1648
- import { createHash as createHash2 } from "crypto";
1648
+ import { createHash as createHash3 } from "crypto";
1649
+
1650
+ // src/connectors/oauth.ts
1651
+ import { createHash as createHash2, randomBytes } from "crypto";
1652
+ var PENDING_TTL_MS = 10 * 60 * 1e3;
1653
+ var InMemoryOAuthFlowStore = class {
1654
+ pendingFlows = /* @__PURE__ */ new Map();
1655
+ put(state, flow) {
1656
+ this.pendingFlows.set(state, flow);
1657
+ }
1658
+ consume(state) {
1659
+ const flow = this.pendingFlows.get(state);
1660
+ this.pendingFlows.delete(state);
1661
+ if (!flow || flow.expiresAt <= Date.now()) return void 0;
1662
+ return flow;
1663
+ }
1664
+ sweep(now) {
1665
+ for (const [k, v] of this.pendingFlows) {
1666
+ if (v.expiresAt <= now) this.pendingFlows.delete(k);
1667
+ }
1668
+ }
1669
+ clear() {
1670
+ this.pendingFlows.clear();
1671
+ }
1672
+ };
1673
+ var defaultFlowStore = new InMemoryOAuthFlowStore();
1674
+ function startOAuthFlow(input) {
1675
+ const store = input.store ?? defaultFlowStore;
1676
+ const now = input.now ?? Date.now();
1677
+ store.sweep?.(now);
1678
+ const usePkce = (input.pkce ?? "required") !== "unsupported";
1679
+ const codeVerifier = usePkce ? base64Url(randomBytes(48)) : void 0;
1680
+ const codeChallenge = codeVerifier ? base64Url(createHash2("sha256").update(codeVerifier).digest()) : void 0;
1681
+ const state = base64Url(randomBytes(24));
1682
+ store.put(state, {
1683
+ codeVerifier,
1684
+ state,
1685
+ projectId: input.projectId,
1686
+ kind: input.kind,
1687
+ label: input.label,
1688
+ redirectUri: input.redirectUri,
1689
+ expiresAt: now + PENDING_TTL_MS
1690
+ });
1691
+ const url = new URL(input.authorizationUrl);
1692
+ url.searchParams.set("response_type", "code");
1693
+ url.searchParams.set(
1694
+ oauthParameterName(input.authorizationClientIdParam, "client_id"),
1695
+ input.clientId
1696
+ );
1697
+ url.searchParams.set("redirect_uri", input.redirectUri);
1698
+ url.searchParams.set("scope", input.scopes.join(input.scopeSeparator ?? " "));
1699
+ url.searchParams.set("state", state);
1700
+ if (input.extraAuthParams) {
1701
+ for (const [k, v] of Object.entries(input.extraAuthParams)) {
1702
+ url.searchParams.set(k, v);
1703
+ }
1704
+ }
1705
+ if (codeChallenge) {
1706
+ url.searchParams.set("code_challenge", codeChallenge);
1707
+ url.searchParams.set("code_challenge_method", "S256");
1708
+ } else {
1709
+ url.searchParams.delete("code_challenge");
1710
+ url.searchParams.delete("code_challenge_method");
1711
+ }
1712
+ return { authorizationUrl: url.toString(), state };
1713
+ }
1714
+ async function consumePendingFlow(state, store = defaultFlowStore) {
1715
+ await store.sweep?.(Date.now());
1716
+ const flow = await store.consume(state);
1717
+ if (!flow) {
1718
+ throw new Error("Unknown or expired OAuth state: possible CSRF, replay, or stale flow");
1719
+ }
1720
+ return flow;
1721
+ }
1722
+ async function exchangeAuthorizationCode(input) {
1723
+ const usePkce = (input.pkce ?? "required") !== "unsupported";
1724
+ if (usePkce && !input.codeVerifier) {
1725
+ throw new Error("OAuth token exchange requires a PKCE code_verifier");
1726
+ }
1727
+ const body = new URLSearchParams({
1728
+ grant_type: "authorization_code",
1729
+ code: input.code,
1730
+ redirect_uri: input.redirectUri
1731
+ });
1732
+ if (usePkce) body.set("code_verifier", input.codeVerifier);
1733
+ const headers = createOAuthTokenRequestHeaders(input.tokenRequestHeaders);
1734
+ applyTokenClientAuthentication(input, body, headers);
1735
+ const redactionValues = [
1736
+ input.code,
1737
+ ...input.codeVerifier ? [input.codeVerifier] : [],
1738
+ ...oauthClientCredentialRedactionValues(
1739
+ input.clientId,
1740
+ input.clientSecret,
1741
+ headers.authorization
1742
+ )
1743
+ ];
1744
+ let res;
1745
+ try {
1746
+ res = await (input.fetchImpl ?? fetch)(input.tokenUrl, {
1747
+ method: "POST",
1748
+ headers,
1749
+ body,
1750
+ signal: input.signal
1751
+ });
1752
+ } catch (cause) {
1753
+ const detail = redactOAuthSensitiveText(
1754
+ cause?.message ?? "unknown",
1755
+ redactionValues
1756
+ );
1757
+ throw new Error(`OAuth token exchange transport error: ${detail}`);
1758
+ }
1759
+ if (!res.ok) {
1760
+ const text = await res.text().catch(() => "");
1761
+ const statusText = redactOAuthSensitiveText(res.statusText, redactionValues);
1762
+ const detail = redactOAuthSensitiveText(text, redactionValues).slice(0, 200);
1763
+ throw new Error(
1764
+ `OAuth token exchange failed: ${res.status} ${statusText} \u2014 ${detail}`
1765
+ );
1766
+ }
1767
+ let json;
1768
+ try {
1769
+ json = await res.json();
1770
+ } catch {
1771
+ throw new Error("OAuth token exchange returned invalid JSON");
1772
+ }
1773
+ return {
1774
+ accessToken: json.access_token,
1775
+ refreshToken: json.refresh_token,
1776
+ expiresIn: json.expires_in,
1777
+ scope: json.scope,
1778
+ tokenType: json.token_type,
1779
+ idToken: json.id_token
1780
+ };
1781
+ }
1782
+ async function refreshAccessToken(input) {
1783
+ const body = new URLSearchParams({
1784
+ grant_type: "refresh_token",
1785
+ refresh_token: input.refreshToken
1786
+ });
1787
+ const headers = createOAuthTokenRequestHeaders(input.tokenRequestHeaders);
1788
+ applyTokenClientAuthentication(input, body, headers);
1789
+ const redactionValues = [
1790
+ input.refreshToken,
1791
+ ...oauthClientCredentialRedactionValues(
1792
+ input.clientId,
1793
+ input.clientSecret,
1794
+ headers.authorization
1795
+ )
1796
+ ];
1797
+ let res;
1798
+ try {
1799
+ res = await (input.fetchImpl ?? fetch)(input.tokenUrl, {
1800
+ method: "POST",
1801
+ headers,
1802
+ body,
1803
+ signal: input.signal
1804
+ });
1805
+ } catch (cause) {
1806
+ const detail = redactOAuthSensitiveText(
1807
+ cause?.message ?? "unknown",
1808
+ redactionValues
1809
+ );
1810
+ throw new Error(`OAuth refresh transport error: ${detail}`);
1811
+ }
1812
+ if (!res.ok) {
1813
+ const text = await res.text().catch(() => "");
1814
+ const statusText = redactOAuthSensitiveText(res.statusText, redactionValues);
1815
+ const detail = redactOAuthSensitiveText(text, redactionValues).slice(0, 200);
1816
+ throw new Error(`OAuth refresh failed: ${res.status} ${statusText} \u2014 ${detail}`);
1817
+ }
1818
+ let json;
1819
+ try {
1820
+ json = await res.json();
1821
+ } catch {
1822
+ throw new Error("OAuth refresh returned invalid JSON");
1823
+ }
1824
+ return {
1825
+ accessToken: json.access_token,
1826
+ // Some providers omit refresh_token on refresh — keep the previous one
1827
+ // in that case (caller passes through if undefined).
1828
+ refreshToken: json.refresh_token,
1829
+ expiresIn: json.expires_in,
1830
+ scope: json.scope,
1831
+ tokenType: json.token_type,
1832
+ idToken: json.id_token
1833
+ };
1834
+ }
1835
+ function createOAuthTokenRequestHeaders(additional) {
1836
+ const headers = new Headers(additional);
1837
+ headers.set("content-type", "application/x-www-form-urlencoded");
1838
+ headers.set("accept", "application/json");
1839
+ headers.delete("authorization");
1840
+ return Object.fromEntries(headers.entries());
1841
+ }
1842
+ function formEncodeOAuthClientCredential(value) {
1843
+ return new URLSearchParams({ value }).toString().slice("value=".length);
1844
+ }
1845
+ function createOAuthBasicAuthorizationHeader(clientId, clientSecret, encodeBase64 = defaultOAuthBase64Encode) {
1846
+ const encodedClientId = formEncodeOAuthClientCredential(clientId);
1847
+ const encodedClientSecret = formEncodeOAuthClientCredential(clientSecret);
1848
+ return `Basic ${encodeBase64(`${encodedClientId}:${encodedClientSecret}`)}`;
1849
+ }
1850
+ function defaultOAuthBase64Encode(value) {
1851
+ const encode = globalThis.btoa;
1852
+ if (typeof encode !== "function") {
1853
+ throw new Error(
1854
+ "OAuth client_secret_basic requires a base64 encoder in this runtime."
1855
+ );
1856
+ }
1857
+ return encode(value);
1858
+ }
1859
+ function oauthClientCredentialRedactionValues(clientId, clientSecret, authorization) {
1860
+ return [
1861
+ clientId,
1862
+ ...clientSecret ? [clientSecret] : [],
1863
+ ...authorization ? [
1864
+ authorization,
1865
+ ...authorization.startsWith("Basic ") ? [authorization.slice("Basic ".length)] : []
1866
+ ] : []
1867
+ ];
1868
+ }
1869
+ function redactOAuthSensitiveText(text, secrets) {
1870
+ const matchers = /* @__PURE__ */ new Map();
1871
+ for (const secret of new Set(secrets)) {
1872
+ if (secret.length === 0) continue;
1873
+ addOAuthRedactionMatcher(matchers, escapeRegExp(secret), secret.length);
1874
+ const jsonEscaped = JSON.stringify(secret).slice(1, -1);
1875
+ addOAuthRedactionMatcher(
1876
+ matchers,
1877
+ escapeRegExp(jsonEscaped),
1878
+ jsonEscaped.length
1879
+ );
1880
+ const formEncoded = formEncodeOAuthClientCredential(secret);
1881
+ addOAuthRedactionMatcher(
1882
+ matchers,
1883
+ formEncodedRedactionPattern(formEncoded),
1884
+ Math.max(formEncoded.length, formEncoded.replaceAll("+", "%20").length)
1885
+ );
1886
+ }
1887
+ return [...matchers.values()].sort((left, right) => right.representedLength - left.representedLength).reduce(
1888
+ (redacted, matcher) => redacted.replace(matcher.pattern, "[REDACTED]"),
1889
+ text
1890
+ );
1891
+ }
1892
+ function addOAuthRedactionMatcher(matchers, source, representedLength) {
1893
+ const existing = matchers.get(source);
1894
+ if (existing && existing.representedLength >= representedLength) return;
1895
+ matchers.set(source, {
1896
+ pattern: new RegExp(source, "g"),
1897
+ representedLength
1898
+ });
1899
+ }
1900
+ function formEncodedRedactionPattern(formEncoded) {
1901
+ let pattern = "";
1902
+ for (let index = 0; index < formEncoded.length; index += 1) {
1903
+ const character = formEncoded[index];
1904
+ const encodedByte = formEncoded.slice(index + 1, index + 3);
1905
+ if (character === "%" && /^[0-9A-F]{2}$/.test(encodedByte)) {
1906
+ pattern += `%${percentEncodedBytePattern(encodedByte)}`;
1907
+ index += 2;
1908
+ continue;
1909
+ }
1910
+ if (character === "+") {
1911
+ pattern += "(?:\\+|%20)";
1912
+ continue;
1913
+ }
1914
+ pattern += escapeRegExp(character);
1915
+ }
1916
+ return pattern;
1917
+ }
1918
+ function percentEncodedBytePattern(encodedByte) {
1919
+ return [...encodedByte].map(
1920
+ (character) => /[A-F]/.test(character) ? `[${character}${character.toLowerCase()}]` : character
1921
+ ).join("");
1922
+ }
1923
+ function escapeRegExp(value) {
1924
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1925
+ }
1926
+ function applyTokenClientAuthentication(input, body, headers) {
1927
+ const method = input.tokenClientAuthMethod ?? "client_secret_post";
1928
+ if (method === "none") {
1929
+ body.set(oauthParameterName(input.tokenClientIdParam, "client_id"), input.clientId);
1930
+ return;
1931
+ }
1932
+ if (!input.clientSecret) {
1933
+ throw new Error(`OAuth ${method} client authentication requires a client secret`);
1934
+ }
1935
+ if (method === "client_secret_post") {
1936
+ body.set(oauthParameterName(input.tokenClientIdParam, "client_id"), input.clientId);
1937
+ body.set(
1938
+ oauthParameterName(input.tokenClientSecretParam, "client_secret"),
1939
+ input.clientSecret
1940
+ );
1941
+ return;
1942
+ }
1943
+ if (method === "client_secret_basic") {
1944
+ headers.authorization = createOAuthBasicAuthorizationHeader(
1945
+ input.clientId,
1946
+ input.clientSecret
1947
+ );
1948
+ return;
1949
+ }
1950
+ throw new Error("Unsupported OAuth token client authentication method");
1951
+ }
1952
+ function base64Url(buf) {
1953
+ return buf.toString("base64").replace(/=+$/, "").replace(/\+/g, "-").replace(/\//g, "_");
1954
+ }
1955
+ function oauthParameterName(value, fallback) {
1956
+ const name = value ?? fallback;
1957
+ if (!/^[A-Za-z][A-Za-z0-9_.-]{0,63}$/.test(name)) {
1958
+ throw new Error("Invalid OAuth parameter name");
1959
+ }
1960
+ return name;
1961
+ }
1962
+ function _resetPendingFlowsForTests() {
1963
+ defaultFlowStore.clear?.();
1964
+ }
1965
+
1966
+ // src/connectors/adapters/client-credentials-rest.ts
1649
1967
  function clientCredentialsRestConnector(spec) {
1650
1968
  const regionMetadataKey = spec.regionMetadataKey ?? "region";
1651
1969
  const delegated = declarativeRestConnector({
@@ -1764,7 +2082,7 @@ function readRegionName(bundle, metadata, metadataKey, fallback) {
1764
2082
  return (bundle.region ?? metadataRegion ?? fallback).toLowerCase().trim();
1765
2083
  }
1766
2084
  function credentialFingerprint(bundle, region, scope) {
1767
- return createHash2("sha256").update(bundle.clientId).update("\0").update(bundle.clientSecret).update("\0").update(region.tokenUrl).update("\0").update(scope ?? "").digest("hex");
2085
+ return createHash3("sha256").update(bundle.clientId).update("\0").update(bundle.clientSecret).update("\0").update(region.tokenUrl).update("\0").update(scope ?? "").digest("hex");
1768
2086
  }
1769
2087
  function renderConnectionMetadata(template, metadata) {
1770
2088
  const rendered = template.replace(/\{connection\.([a-zA-Z0-9_.-]+)\}/g, (_match, key) => {
@@ -1795,7 +2113,10 @@ async function exchangeClientCredentials(displayName, sourceId, bundle, region,
1795
2113
  "content-type": "application/x-www-form-urlencoded"
1796
2114
  };
1797
2115
  if (credentialPlacement === "basic") {
1798
- headers.authorization = `Basic ${Buffer.from(`${bundle.clientId}:${bundle.clientSecret}`).toString("base64")}`;
2116
+ headers.authorization = createOAuthBasicAuthorizationHeader(
2117
+ bundle.clientId,
2118
+ bundle.clientSecret
2119
+ );
1799
2120
  }
1800
2121
  const response = await fetch(region.tokenUrl, {
1801
2122
  method: "POST",
@@ -12666,16 +12987,31 @@ var giteaConnector = declarativeRestConnector({
12666
12987
  description: "Self-hosted Git service for creating and managing repositories, issues, and pull requests.",
12667
12988
  auth: {
12668
12989
  kind: "oauth2",
12669
- authorizationUrl: "https://api.gitea.io/login/oauth/authorize",
12670
- tokenUrl: "https://api.gitea.io/login/oauth/access_token",
12671
- scopes: ["repo", "admin"],
12990
+ authorizationUrl: "{instanceUrl}/login/oauth/authorize",
12991
+ tokenUrl: "{instanceUrl}/login/oauth/access_token",
12992
+ scopes: [
12993
+ "read:user",
12994
+ "write:user",
12995
+ "read:issue",
12996
+ "write:issue",
12997
+ "read:repository",
12998
+ "write:repository"
12999
+ ],
12672
13000
  clientIdEnv: "GITEA_OAUTH_CLIENT_ID",
12673
- clientSecretEnv: "GITEA_OAUTH_CLIENT_SECRET"
13001
+ clientSecretEnv: "GITEA_OAUTH_CLIENT_SECRET",
13002
+ pkce: "supported",
13003
+ urlTemplateMetadata: {
13004
+ instanceUrl: {
13005
+ kind: "base-url",
13006
+ requirePublicHttps: true
13007
+ }
13008
+ }
12674
13009
  },
12675
13010
  category: "other",
12676
13011
  defaultConsistencyModel: "authoritative",
12677
- baseUrl: "https://api.gitea.io/api/v1",
12678
- test: { method: "GET", path: "/user" },
13012
+ baseUrl: { metadataKey: "instanceUrl" },
13013
+ requirePublicHttpsBaseUrl: true,
13014
+ test: { method: "GET", path: "/api/v1/user" },
12679
13015
  capabilities: [
12680
13016
  {
12681
13017
  name: "repos.list",
@@ -12689,8 +13025,8 @@ var giteaConnector = declarativeRestConnector({
12689
13025
  },
12690
13026
  required: ["owner"]
12691
13027
  },
12692
- request: { method: "GET", path: "/users/{owner}/repos", query: { limit: "{limit}" } },
12693
- requiredScopes: ["repo"]
13028
+ request: { method: "GET", path: "/api/v1/users/{owner}/repos", query: { limit: "{limit}" } },
13029
+ requiredScopes: ["read:user"]
12694
13030
  },
12695
13031
  {
12696
13032
  name: "issues.create",
@@ -12710,7 +13046,7 @@ var giteaConnector = declarativeRestConnector({
12710
13046
  },
12711
13047
  request: {
12712
13048
  method: "POST",
12713
- path: "/repos/{owner}/{repo}/issues",
13049
+ path: "/api/v1/repos/{owner}/{repo}/issues",
12714
13050
  body: {
12715
13051
  title: "{title}",
12716
13052
  body: "{body}",
@@ -12719,7 +13055,7 @@ var giteaConnector = declarativeRestConnector({
12719
13055
  }
12720
13056
  },
12721
13057
  cas: "native-idempotency",
12722
- requiredScopes: ["repo"]
13058
+ requiredScopes: ["write:issue"]
12723
13059
  },
12724
13060
  {
12725
13061
  name: "issues.update",
@@ -12739,7 +13075,7 @@ var giteaConnector = declarativeRestConnector({
12739
13075
  },
12740
13076
  request: {
12741
13077
  method: "PATCH",
12742
- path: "/repos/{owner}/{repo}/issues/{index}",
13078
+ path: "/api/v1/repos/{owner}/{repo}/issues/{index}",
12743
13079
  body: {
12744
13080
  title: "{title}",
12745
13081
  body: "{body}",
@@ -12747,7 +13083,7 @@ var giteaConnector = declarativeRestConnector({
12747
13083
  }
12748
13084
  },
12749
13085
  cas: "etag-if-match",
12750
- requiredScopes: ["repo"]
13086
+ requiredScopes: ["write:issue"]
12751
13087
  },
12752
13088
  {
12753
13089
  name: "comments.create",
@@ -12765,11 +13101,11 @@ var giteaConnector = declarativeRestConnector({
12765
13101
  },
12766
13102
  request: {
12767
13103
  method: "POST",
12768
- path: "/repos/{owner}/{repo}/issues/{index}/comments",
13104
+ path: "/api/v1/repos/{owner}/{repo}/issues/{index}/comments",
12769
13105
  body: { body: "{body}" }
12770
13106
  },
12771
13107
  cas: "native-idempotency",
12772
- requiredScopes: ["repo"]
13108
+ requiredScopes: ["write:issue"]
12773
13109
  },
12774
13110
  {
12775
13111
  name: "pull-requests.list",
@@ -12787,10 +13123,10 @@ var giteaConnector = declarativeRestConnector({
12787
13123
  },
12788
13124
  request: {
12789
13125
  method: "GET",
12790
- path: "/repos/{owner}/{repo}/pulls",
13126
+ path: "/api/v1/repos/{owner}/{repo}/pulls",
12791
13127
  query: { state: "{state}", limit: "{limit}" }
12792
13128
  },
12793
- requiredScopes: ["repo"]
13129
+ requiredScopes: ["read:repository"]
12794
13130
  },
12795
13131
  {
12796
13132
  name: "pull-requests.create",
@@ -12810,7 +13146,7 @@ var giteaConnector = declarativeRestConnector({
12810
13146
  },
12811
13147
  request: {
12812
13148
  method: "POST",
12813
- path: "/repos/{owner}/{repo}/pulls",
13149
+ path: "/api/v1/repos/{owner}/{repo}/pulls",
12814
13150
  body: {
12815
13151
  title: "{title}",
12816
13152
  body: "{body}",
@@ -12819,7 +13155,7 @@ var giteaConnector = declarativeRestConnector({
12819
13155
  }
12820
13156
  },
12821
13157
  cas: "native-idempotency",
12822
- requiredScopes: ["repo"]
13158
+ requiredScopes: ["write:repository"]
12823
13159
  },
12824
13160
  {
12825
13161
  name: "branches.list",
@@ -12835,9 +13171,9 @@ var giteaConnector = declarativeRestConnector({
12835
13171
  },
12836
13172
  request: {
12837
13173
  method: "GET",
12838
- path: "/repos/{owner}/{repo}/branches"
13174
+ path: "/api/v1/repos/{owner}/{repo}/branches"
12839
13175
  },
12840
- requiredScopes: ["repo"]
13176
+ requiredScopes: ["read:repository"]
12841
13177
  },
12842
13178
  {
12843
13179
  name: "repos.create",
@@ -12856,12 +13192,12 @@ var giteaConnector = declarativeRestConnector({
12856
13192
  },
12857
13193
  request: {
12858
13194
  method: "POST",
12859
- path: "/user/repos",
13195
+ path: "/api/v1/user/repos",
12860
13196
  body: "args"
12861
13197
  },
12862
13198
  cas: "native-idempotency",
12863
13199
  externalEffect: true,
12864
- requiredScopes: ["repo"]
13200
+ requiredScopes: ["write:user"]
12865
13201
  },
12866
13202
  {
12867
13203
  name: "repos.delete",
@@ -12877,11 +13213,11 @@ var giteaConnector = declarativeRestConnector({
12877
13213
  },
12878
13214
  request: {
12879
13215
  method: "DELETE",
12880
- path: "/repos/{owner}/{repo}"
13216
+ path: "/api/v1/repos/{owner}/{repo}"
12881
13217
  },
12882
13218
  cas: "native-idempotency",
12883
13219
  externalEffect: true,
12884
- requiredScopes: ["repo", "admin"]
13220
+ requiredScopes: ["write:repository"]
12885
13221
  },
12886
13222
  {
12887
13223
  name: "pull-requests.merge",
@@ -12901,12 +13237,12 @@ var giteaConnector = declarativeRestConnector({
12901
13237
  },
12902
13238
  request: {
12903
13239
  method: "POST",
12904
- path: "/repos/{owner}/{repo}/pulls/{index}/merge",
13240
+ path: "/api/v1/repos/{owner}/{repo}/pulls/{index}/merge",
12905
13241
  body: "args"
12906
13242
  },
12907
13243
  cas: "native-idempotency",
12908
13244
  externalEffect: true,
12909
- requiredScopes: ["repo"]
13245
+ requiredScopes: ["write:repository"]
12910
13246
  }
12911
13247
  ]
12912
13248
  });
@@ -14745,32 +15081,25 @@ var niftyConnector = declarativeRestConnector({
14745
15081
  });
14746
15082
 
14747
15083
  // src/connectors/adapters/opsgenie.ts
15084
+ var OPSGENIE_API_BASE_URLS = [
15085
+ "https://api.opsgenie.com",
15086
+ "https://api.eu.opsgenie.com"
15087
+ ];
14748
15088
  var opsgenieConnector = declarativeRestConnector({
14749
15089
  kind: "opsgenie",
14750
15090
  displayName: "Opsgenie",
14751
- description: "Create, acknowledge, and close Opsgenie alerts and incidents, attach notes, and read schedules, on-call assignments, teams, and users against a connected Opsgenie account.",
15091
+ description: "Use an existing Opsgenie account to manage alerts and incidents, attach notes, and read schedules, on-call assignments, teams, and users.",
14752
15092
  auth: {
14753
- kind: "oauth2",
14754
- authorizationUrl: "https://app.opsgenie.com/oauth/authorize",
14755
- tokenUrl: "https://app.opsgenie.com/oauth/token",
14756
- scopes: [
14757
- "alert.read",
14758
- "alert.write",
14759
- "incident.read",
14760
- "incident.write",
14761
- "schedule.read",
14762
- "oncall.read",
14763
- "team.read",
14764
- "user.read"
14765
- ],
14766
- clientIdEnv: "OPSGENIE_OAUTH_CLIENT_ID",
14767
- clientSecretEnv: "OPSGENIE_OAUTH_CLIENT_SECRET"
15093
+ kind: "api-key",
15094
+ hint: "Opsgenie API key with access to the selected alert, incident, schedule, team, and user operations."
14768
15095
  },
14769
15096
  category: "other",
14770
15097
  defaultConsistencyModel: "authoritative",
14771
15098
  // Default to the US REST host; EU-rooted accounts override
14772
15099
  // metadata.apiBaseUrl to https://api.eu.opsgenie.com.
14773
15100
  baseUrl: { metadataKey: "apiBaseUrl", fallback: "https://api.opsgenie.com" },
15101
+ allowedBaseUrls: OPSGENIE_API_BASE_URLS,
15102
+ credentialPlacement: { kind: "header", header: "authorization", prefix: "GenieKey " },
14774
15103
  defaultHeaders: {
14775
15104
  accept: "application/json",
14776
15105
  "content-type": "application/json"
@@ -14821,8 +15150,7 @@ var opsgenieConnector = declarativeRestConnector({
14821
15150
  sort: "{sort}",
14822
15151
  order: "{order}"
14823
15152
  }
14824
- },
14825
- requiredScopes: ["alert.read"]
15153
+ }
14826
15154
  },
14827
15155
  {
14828
15156
  name: "alerts.get",
@@ -14840,8 +15168,7 @@ var opsgenieConnector = declarativeRestConnector({
14840
15168
  method: "GET",
14841
15169
  path: "/v2/alerts/{identifier}",
14842
15170
  query: { identifierType: "{identifierType}" }
14843
- },
14844
- requiredScopes: ["alert.read"]
15171
+ }
14845
15172
  },
14846
15173
  {
14847
15174
  name: "alerts.create",
@@ -14902,8 +15229,7 @@ var opsgenieConnector = declarativeRestConnector({
14902
15229
  note: "{note}"
14903
15230
  }
14904
15231
  },
14905
- cas: "native-idempotency",
14906
- requiredScopes: ["alert.write"]
15232
+ cas: "native-idempotency"
14907
15233
  },
14908
15234
  {
14909
15235
  name: "alerts.acknowledge",
@@ -14926,8 +15252,7 @@ var opsgenieConnector = declarativeRestConnector({
14926
15252
  query: { identifierType: "{identifierType}" },
14927
15253
  body: { user: "{user}", source: "{source}", note: "{note}" }
14928
15254
  },
14929
- cas: "native-idempotency",
14930
- requiredScopes: ["alert.write"]
15255
+ cas: "native-idempotency"
14931
15256
  },
14932
15257
  {
14933
15258
  name: "alerts.close",
@@ -14950,8 +15275,7 @@ var opsgenieConnector = declarativeRestConnector({
14950
15275
  query: { identifierType: "{identifierType}" },
14951
15276
  body: { user: "{user}", source: "{source}", note: "{note}" }
14952
15277
  },
14953
- cas: "native-idempotency",
14954
- requiredScopes: ["alert.write"]
15278
+ cas: "native-idempotency"
14955
15279
  },
14956
15280
  {
14957
15281
  name: "alerts.notes.list",
@@ -14979,8 +15303,7 @@ var opsgenieConnector = declarativeRestConnector({
14979
15303
  limit: "{limit}",
14980
15304
  order: "{order}"
14981
15305
  }
14982
- },
14983
- requiredScopes: ["alert.read"]
15306
+ }
14984
15307
  },
14985
15308
  {
14986
15309
  name: "alerts.notes.add",
@@ -15003,8 +15326,7 @@ var opsgenieConnector = declarativeRestConnector({
15003
15326
  query: { identifierType: "{identifierType}" },
15004
15327
  body: { note: "{note}", user: "{user}", source: "{source}" }
15005
15328
  },
15006
- cas: "native-idempotency",
15007
- requiredScopes: ["alert.write"]
15329
+ cas: "native-idempotency"
15008
15330
  },
15009
15331
  {
15010
15332
  name: "incidents.list",
@@ -15033,8 +15355,7 @@ var opsgenieConnector = declarativeRestConnector({
15033
15355
  sort: "{sort}",
15034
15356
  order: "{order}"
15035
15357
  }
15036
- },
15037
- requiredScopes: ["incident.read"]
15358
+ }
15038
15359
  },
15039
15360
  {
15040
15361
  name: "incidents.get",
@@ -15052,8 +15373,7 @@ var opsgenieConnector = declarativeRestConnector({
15052
15373
  method: "GET",
15053
15374
  path: "/v1/incidents/{identifier}",
15054
15375
  query: { identifierType: "{identifierType}" }
15055
- },
15056
- requiredScopes: ["incident.read"]
15376
+ }
15057
15377
  },
15058
15378
  {
15059
15379
  name: "incidents.create",
@@ -15099,8 +15419,7 @@ var opsgenieConnector = declarativeRestConnector({
15099
15419
  impactedServices: "{impactedServices}"
15100
15420
  }
15101
15421
  },
15102
- cas: "native-idempotency",
15103
- requiredScopes: ["incident.write"]
15422
+ cas: "native-idempotency"
15104
15423
  },
15105
15424
  {
15106
15425
  name: "incidents.close",
@@ -15121,8 +15440,7 @@ var opsgenieConnector = declarativeRestConnector({
15121
15440
  query: { identifierType: "{identifierType}" },
15122
15441
  body: { note: "{note}" }
15123
15442
  },
15124
- cas: "native-idempotency",
15125
- requiredScopes: ["incident.write"]
15443
+ cas: "native-idempotency"
15126
15444
  },
15127
15445
  {
15128
15446
  name: "incidents.notes.add",
@@ -15143,8 +15461,7 @@ var opsgenieConnector = declarativeRestConnector({
15143
15461
  query: { identifierType: "{identifierType}" },
15144
15462
  body: { note: "{note}" }
15145
15463
  },
15146
- cas: "native-idempotency",
15147
- requiredScopes: ["incident.write"]
15464
+ cas: "native-idempotency"
15148
15465
  },
15149
15466
  {
15150
15467
  name: "schedules.list",
@@ -15164,8 +15481,7 @@ var opsgenieConnector = declarativeRestConnector({
15164
15481
  method: "GET",
15165
15482
  path: "/v2/schedules",
15166
15483
  query: { expand: "{expand}" }
15167
- },
15168
- requiredScopes: ["schedule.read"]
15484
+ }
15169
15485
  },
15170
15486
  {
15171
15487
  name: "schedules.get",
@@ -15183,8 +15499,7 @@ var opsgenieConnector = declarativeRestConnector({
15183
15499
  method: "GET",
15184
15500
  path: "/v2/schedules/{identifier}",
15185
15501
  query: { identifierType: "{identifierType}" }
15186
- },
15187
- requiredScopes: ["schedule.read"]
15502
+ }
15188
15503
  },
15189
15504
  {
15190
15505
  name: "schedules.timeline",
@@ -15215,8 +15530,7 @@ var opsgenieConnector = declarativeRestConnector({
15215
15530
  date: "{date}",
15216
15531
  expand: "{expand}"
15217
15532
  }
15218
- },
15219
- requiredScopes: ["schedule.read"]
15533
+ }
15220
15534
  },
15221
15535
  {
15222
15536
  name: "oncalls.current",
@@ -15240,8 +15554,7 @@ var opsgenieConnector = declarativeRestConnector({
15240
15554
  flat: "{flat}",
15241
15555
  date: "{date}"
15242
15556
  }
15243
- },
15244
- requiredScopes: ["oncall.read"]
15557
+ }
15245
15558
  },
15246
15559
  {
15247
15560
  name: "oncalls.next",
@@ -15265,16 +15578,14 @@ var opsgenieConnector = declarativeRestConnector({
15265
15578
  flat: "{flat}",
15266
15579
  date: "{date}"
15267
15580
  }
15268
- },
15269
- requiredScopes: ["oncall.read"]
15581
+ }
15270
15582
  },
15271
15583
  {
15272
15584
  name: "teams.list",
15273
15585
  class: "read",
15274
15586
  description: "List all teams in the Opsgenie workspace.",
15275
15587
  parameters: { type: "object", properties: {} },
15276
- request: { method: "GET", path: "/v2/teams" },
15277
- requiredScopes: ["team.read"]
15588
+ request: { method: "GET", path: "/v2/teams" }
15278
15589
  },
15279
15590
  {
15280
15591
  name: "teams.get",
@@ -15292,8 +15603,7 @@ var opsgenieConnector = declarativeRestConnector({
15292
15603
  method: "GET",
15293
15604
  path: "/v2/teams/{identifier}",
15294
15605
  query: { identifierType: "{identifierType}" }
15295
- },
15296
- requiredScopes: ["team.read"]
15606
+ }
15297
15607
  },
15298
15608
  {
15299
15609
  name: "users.list",
@@ -15319,8 +15629,7 @@ var opsgenieConnector = declarativeRestConnector({
15319
15629
  sort: "{sort}",
15320
15630
  order: "{order}"
15321
15631
  }
15322
- },
15323
- requiredScopes: ["user.read"]
15632
+ }
15324
15633
  },
15325
15634
  {
15326
15635
  name: "users.get",
@@ -15338,8 +15647,7 @@ var opsgenieConnector = declarativeRestConnector({
15338
15647
  method: "GET",
15339
15648
  path: "/v2/users/{identifier}",
15340
15649
  query: { expand: "{expand}" }
15341
- },
15342
- requiredScopes: ["user.read"]
15650
+ }
15343
15651
  }
15344
15652
  ]
15345
15653
  });
@@ -16148,187 +16456,6 @@ var pushbulletConnector = declarativeRestConnector({
16148
16456
  ]
16149
16457
  });
16150
16458
 
16151
- // src/connectors/oauth.ts
16152
- import { createHash as createHash3, randomBytes } from "crypto";
16153
- var PENDING_TTL_MS = 10 * 60 * 1e3;
16154
- var InMemoryOAuthFlowStore = class {
16155
- pendingFlows = /* @__PURE__ */ new Map();
16156
- put(state, flow) {
16157
- this.pendingFlows.set(state, flow);
16158
- }
16159
- consume(state) {
16160
- const flow = this.pendingFlows.get(state);
16161
- this.pendingFlows.delete(state);
16162
- if (!flow || flow.expiresAt <= Date.now()) return void 0;
16163
- return flow;
16164
- }
16165
- sweep(now) {
16166
- for (const [k, v] of this.pendingFlows) {
16167
- if (v.expiresAt <= now) this.pendingFlows.delete(k);
16168
- }
16169
- }
16170
- clear() {
16171
- this.pendingFlows.clear();
16172
- }
16173
- };
16174
- var defaultFlowStore = new InMemoryOAuthFlowStore();
16175
- function startOAuthFlow(input) {
16176
- const store = input.store ?? defaultFlowStore;
16177
- const now = input.now ?? Date.now();
16178
- store.sweep?.(now);
16179
- const usePkce = (input.pkce ?? "required") !== "unsupported";
16180
- const codeVerifier = usePkce ? base64Url(randomBytes(48)) : void 0;
16181
- const codeChallenge = codeVerifier ? base64Url(createHash3("sha256").update(codeVerifier).digest()) : void 0;
16182
- const state = base64Url(randomBytes(24));
16183
- store.put(state, {
16184
- codeVerifier,
16185
- state,
16186
- projectId: input.projectId,
16187
- kind: input.kind,
16188
- label: input.label,
16189
- redirectUri: input.redirectUri,
16190
- expiresAt: now + PENDING_TTL_MS
16191
- });
16192
- const url = new URL(input.authorizationUrl);
16193
- url.searchParams.set("response_type", "code");
16194
- url.searchParams.set(
16195
- oauthParameterName(input.authorizationClientIdParam, "client_id"),
16196
- input.clientId
16197
- );
16198
- url.searchParams.set("redirect_uri", input.redirectUri);
16199
- url.searchParams.set("scope", input.scopes.join(input.scopeSeparator ?? " "));
16200
- url.searchParams.set("state", state);
16201
- if (input.extraAuthParams) {
16202
- for (const [k, v] of Object.entries(input.extraAuthParams)) {
16203
- url.searchParams.set(k, v);
16204
- }
16205
- }
16206
- if (codeChallenge) {
16207
- url.searchParams.set("code_challenge", codeChallenge);
16208
- url.searchParams.set("code_challenge_method", "S256");
16209
- } else {
16210
- url.searchParams.delete("code_challenge");
16211
- url.searchParams.delete("code_challenge_method");
16212
- }
16213
- return { authorizationUrl: url.toString(), state };
16214
- }
16215
- async function consumePendingFlow(state, store = defaultFlowStore) {
16216
- await store.sweep?.(Date.now());
16217
- const flow = await store.consume(state);
16218
- if (!flow) {
16219
- throw new Error("Unknown or expired OAuth state: possible CSRF, replay, or stale flow");
16220
- }
16221
- return flow;
16222
- }
16223
- async function exchangeAuthorizationCode(input) {
16224
- const usePkce = (input.pkce ?? "required") !== "unsupported";
16225
- if (usePkce && !input.codeVerifier) {
16226
- throw new Error("OAuth token exchange requires a PKCE code_verifier");
16227
- }
16228
- const body = new URLSearchParams({
16229
- grant_type: "authorization_code",
16230
- code: input.code,
16231
- redirect_uri: input.redirectUri
16232
- });
16233
- if (usePkce) body.set("code_verifier", input.codeVerifier);
16234
- const headers = createOAuthTokenRequestHeaders(input.tokenRequestHeaders);
16235
- applyTokenClientAuthentication(input, body, headers);
16236
- const res = await (input.fetchImpl ?? fetch)(input.tokenUrl, {
16237
- method: "POST",
16238
- headers,
16239
- body,
16240
- signal: input.signal
16241
- });
16242
- if (!res.ok) {
16243
- const text = await res.text().catch(() => "");
16244
- throw new Error(`OAuth token exchange failed: ${res.status} ${res.statusText} \u2014 ${text.slice(0, 200)}`);
16245
- }
16246
- const json = await res.json();
16247
- return {
16248
- accessToken: json.access_token,
16249
- refreshToken: json.refresh_token,
16250
- expiresIn: json.expires_in,
16251
- scope: json.scope,
16252
- tokenType: json.token_type,
16253
- idToken: json.id_token
16254
- };
16255
- }
16256
- async function refreshAccessToken(input) {
16257
- const body = new URLSearchParams({
16258
- grant_type: "refresh_token",
16259
- refresh_token: input.refreshToken
16260
- });
16261
- const headers = createOAuthTokenRequestHeaders(input.tokenRequestHeaders);
16262
- applyTokenClientAuthentication(input, body, headers);
16263
- const res = await (input.fetchImpl ?? fetch)(input.tokenUrl, {
16264
- method: "POST",
16265
- headers,
16266
- body,
16267
- signal: input.signal
16268
- });
16269
- if (!res.ok) {
16270
- const text = await res.text().catch(() => "");
16271
- throw new Error(`OAuth refresh failed: ${res.status} ${res.statusText} \u2014 ${text.slice(0, 200)}`);
16272
- }
16273
- const json = await res.json();
16274
- return {
16275
- accessToken: json.access_token,
16276
- // Some providers omit refresh_token on refresh — keep the previous one
16277
- // in that case (caller passes through if undefined).
16278
- refreshToken: json.refresh_token,
16279
- expiresIn: json.expires_in,
16280
- scope: json.scope,
16281
- tokenType: json.token_type,
16282
- idToken: json.id_token
16283
- };
16284
- }
16285
- function createOAuthTokenRequestHeaders(additional) {
16286
- const headers = new Headers(additional);
16287
- headers.set("content-type", "application/x-www-form-urlencoded");
16288
- headers.set("accept", "application/json");
16289
- headers.delete("authorization");
16290
- return Object.fromEntries(headers.entries());
16291
- }
16292
- function applyTokenClientAuthentication(input, body, headers) {
16293
- const method = input.tokenClientAuthMethod ?? "client_secret_post";
16294
- if (method === "none") {
16295
- body.set(oauthParameterName(input.tokenClientIdParam, "client_id"), input.clientId);
16296
- return;
16297
- }
16298
- if (!input.clientSecret) {
16299
- throw new Error(`OAuth ${method} client authentication requires a client secret`);
16300
- }
16301
- if (method === "client_secret_post") {
16302
- body.set(oauthParameterName(input.tokenClientIdParam, "client_id"), input.clientId);
16303
- body.set(
16304
- oauthParameterName(input.tokenClientSecretParam, "client_secret"),
16305
- input.clientSecret
16306
- );
16307
- return;
16308
- }
16309
- if (method === "client_secret_basic") {
16310
- headers.authorization = `Basic ${Buffer.from(
16311
- `${input.clientId}:${input.clientSecret}`,
16312
- "utf8"
16313
- ).toString("base64")}`;
16314
- return;
16315
- }
16316
- throw new Error("Unsupported OAuth token client authentication method");
16317
- }
16318
- function base64Url(buf) {
16319
- return buf.toString("base64").replace(/=+$/, "").replace(/\+/g, "-").replace(/\//g, "_");
16320
- }
16321
- function oauthParameterName(value, fallback) {
16322
- const name = value ?? fallback;
16323
- if (!/^[A-Za-z][A-Za-z0-9_.-]{0,63}$/.test(name)) {
16324
- throw new Error("Invalid OAuth parameter name");
16325
- }
16326
- return name;
16327
- }
16328
- function _resetPendingFlowsForTests() {
16329
- defaultFlowStore.clear?.();
16330
- }
16331
-
16332
16459
  // src/connectors/adapters/reddit.ts
16333
16460
  var REDDIT_USER_AGENT = "web:tools.tangle.integration-hub:v1.0 (contact: https://tangle.tools)";
16334
16461
  var REDDIT_TOKEN_URL = "https://www.reddit.com/api/v1/access_token";
@@ -17511,421 +17638,148 @@ var sendpulseConnector = declarativeRestConnector({
17511
17638
  var snowflakeConnector = declarativeRestConnector({
17512
17639
  kind: "snowflake",
17513
17640
  displayName: "Snowflake",
17514
- description: "Data warehouse built for the cloud. Query, insert, update, delete, and upsert rows.",
17641
+ description: "Execute and monitor SQL statements through a connected Snowflake account SQL API.",
17515
17642
  auth: {
17516
17643
  kind: "oauth2",
17517
- authorizationUrl: "https://app.snowflake.com/oauth/authorize",
17518
- tokenUrl: "https://app.snowflake.com/oauth/token",
17519
- scopes: ["session:role:manage"],
17644
+ authorizationUrl: "{accountUrl}/oauth/authorize",
17645
+ tokenUrl: "{accountUrl}/oauth/token-request",
17646
+ scopes: ["refresh_token"],
17520
17647
  clientIdEnv: "SNOWFLAKE_OAUTH_CLIENT_ID",
17521
- clientSecretEnv: "SNOWFLAKE_OAUTH_CLIENT_SECRET"
17648
+ clientSecretEnv: "SNOWFLAKE_OAUTH_CLIENT_SECRET",
17649
+ tokenClientAuthMethod: "client_secret_post",
17650
+ pkce: "supported",
17651
+ urlTemplateMetadata: {
17652
+ accountUrl: {
17653
+ kind: "base-url",
17654
+ allowedBaseUrlSuffixes: [".snowflakecomputing.com"]
17655
+ }
17656
+ }
17522
17657
  },
17523
17658
  category: "database",
17524
17659
  defaultConsistencyModel: "authoritative",
17525
- baseUrl: "https://api.snowflakecomputing.com/api/v2",
17526
- test: { method: "GET", path: "/accounts/whoami" },
17660
+ baseUrl: { metadataKey: "accountUrl" },
17661
+ allowedBaseUrlSuffixes: [".snowflakecomputing.com"],
17662
+ defaultHeaders: {
17663
+ "content-type": "application/json",
17664
+ "x-snowflake-authorization-token-type": "OAUTH"
17665
+ },
17666
+ test: {
17667
+ method: "POST",
17668
+ path: "/api/v2/statements",
17669
+ body: { statement: "SELECT CURRENT_ACCOUNT(), CURRENT_USER(), CURRENT_ROLE()" }
17670
+ },
17527
17671
  capabilities: [
17528
17672
  {
17529
17673
  name: "queries.run",
17530
- class: "read",
17531
- description: "Run a SQL query.",
17532
- parameters: {
17533
- type: "object",
17534
- properties: { statement: { type: "string" } },
17535
- required: ["statement"]
17536
- },
17537
- request: { method: "POST", path: "/statements", body: { statement: "{statement}" } },
17538
- requiredScopes: ["session:role:manage"]
17539
- },
17540
- {
17541
- name: "queries.runMultiple",
17542
- class: "read",
17543
- description: "Run multiple SQL queries.",
17544
- parameters: {
17545
- type: "object",
17546
- properties: { statements: { type: "array", items: { type: "string" } } },
17547
- required: ["statements"]
17548
- },
17549
- request: { method: "POST", path: "/statements", body: { statements: "{statements}" } },
17550
- requiredScopes: ["session:role:manage"]
17551
- },
17552
- {
17553
- name: "rows.insert",
17554
17674
  class: "mutation",
17555
- description: "Insert a row into a table.",
17675
+ description: "Execute one SQL statement. Every statement requires approval because Snowflake SQL can mutate account data and configuration.",
17556
17676
  parameters: {
17557
17677
  type: "object",
17558
17678
  properties: {
17679
+ statement: { type: "string", description: "One Snowflake SQL statement." },
17680
+ timeout: { type: "integer", minimum: 1, description: "Maximum execution time in seconds." },
17559
17681
  database: { type: "string" },
17560
17682
  schema: { type: "string" },
17561
- table: { type: "string" },
17562
- values: { type: "object" }
17683
+ warehouse: { type: "string" },
17684
+ role: { type: "string" },
17685
+ bindings: {
17686
+ type: "object",
17687
+ description: "Snowflake SQL API bind variables keyed by one-based position."
17688
+ },
17689
+ async: { type: "boolean", description: "Return a statement handle without waiting for completion." }
17563
17690
  },
17564
- required: ["database", "schema", "table", "values"]
17691
+ required: ["statement"]
17565
17692
  },
17566
17693
  request: {
17567
17694
  method: "POST",
17568
- path: "/databases/{database}/schemas/{schema}/tables/{table}/rows",
17569
- body: { values: "{values}" }
17695
+ path: "/api/v2/statements",
17696
+ query: { async: "{async}" },
17697
+ body: {
17698
+ statement: "{statement}",
17699
+ timeout: "{timeout}",
17700
+ database: "{database}",
17701
+ schema: "{schema}",
17702
+ warehouse: "{warehouse}",
17703
+ role: "{role}",
17704
+ bindings: "{bindings}"
17705
+ }
17570
17706
  },
17571
- cas: "native-idempotency",
17572
- requiredScopes: ["session:role:manage"]
17707
+ cas: "none",
17708
+ externalEffect: true
17573
17709
  },
17574
17710
  {
17575
- name: "rows.insertMultiple",
17711
+ name: "queries.runMultiple",
17576
17712
  class: "mutation",
17577
- description: "Insert multiple rows into a table.",
17713
+ description: "Execute a semicolon-delimited SQL string as multiple statements. Snowflake does not support bind variables for this operation.",
17578
17714
  parameters: {
17579
17715
  type: "object",
17580
17716
  properties: {
17717
+ statement: { type: "string", description: "Semicolon-delimited Snowflake SQL statements." },
17718
+ multiStatementCount: {
17719
+ type: "string",
17720
+ pattern: "^[1-9][0-9]*$",
17721
+ description: "Number of statements in the SQL string."
17722
+ },
17723
+ timeout: { type: "integer", minimum: 1 },
17581
17724
  database: { type: "string" },
17582
17725
  schema: { type: "string" },
17583
- table: { type: "string" },
17584
- rows: { type: "array", items: { type: "object" } }
17726
+ warehouse: { type: "string" },
17727
+ role: { type: "string" },
17728
+ async: { type: "boolean" }
17585
17729
  },
17586
- required: ["database", "schema", "table", "rows"]
17730
+ required: ["statement", "multiStatementCount"]
17587
17731
  },
17588
17732
  request: {
17589
17733
  method: "POST",
17590
- path: "/databases/{database}/schemas/{schema}/tables/{table}/rows/bulk",
17591
- body: { rows: "{rows}" }
17592
- },
17593
- cas: "native-idempotency",
17594
- requiredScopes: ["session:role:manage"]
17595
- },
17596
- {
17597
- name: "rows.update",
17598
- class: "mutation",
17599
- description: "Update a row in a table.",
17600
- parameters: {
17601
- type: "object",
17602
- properties: {
17603
- database: { type: "string" },
17604
- schema: { type: "string" },
17605
- table: { type: "string" },
17606
- rowId: { type: "string" },
17607
- values: { type: "object" }
17608
- },
17609
- required: ["database", "schema", "table", "rowId", "values"]
17610
- },
17611
- request: {
17612
- method: "PATCH",
17613
- path: "/databases/{database}/schemas/{schema}/tables/{table}/rows/{rowId}",
17614
- body: { values: "{values}" }
17615
- },
17616
- cas: "optimistic-read-verify",
17617
- requiredScopes: ["session:role:manage"]
17618
- },
17619
- {
17620
- name: "rows.upsert",
17621
- class: "mutation",
17622
- description: "Insert or update a row in a table.",
17623
- parameters: {
17624
- type: "object",
17625
- properties: {
17626
- database: { type: "string" },
17627
- schema: { type: "string" },
17628
- table: { type: "string" },
17629
- values: { type: "object" },
17630
- keyColumns: { type: "array", items: { type: "string" } }
17631
- },
17632
- required: ["database", "schema", "table", "values", "keyColumns"]
17633
- },
17634
- request: {
17635
- method: "PUT",
17636
- path: "/databases/{database}/schemas/{schema}/tables/{table}/rows/upsert",
17637
- body: { values: "{values}", keyColumns: "{keyColumns}" }
17638
- },
17639
- cas: "native-idempotency",
17640
- requiredScopes: ["session:role:manage"]
17641
- },
17642
- {
17643
- name: "rows.delete",
17644
- class: "mutation",
17645
- description: "Delete a row from a table.",
17646
- parameters: {
17647
- type: "object",
17648
- properties: {
17649
- database: { type: "string" },
17650
- schema: { type: "string" },
17651
- table: { type: "string" },
17652
- rowId: { type: "string" }
17653
- },
17654
- required: ["database", "schema", "table", "rowId"]
17655
- },
17656
- request: {
17657
- method: "DELETE",
17658
- path: "/databases/{database}/schemas/{schema}/tables/{table}/rows/{rowId}"
17659
- },
17660
- requiredScopes: ["session:role:manage"]
17661
- },
17662
- {
17663
- name: "rows.getById",
17664
- class: "read",
17665
- description: "Get a row by ID from a table.",
17666
- parameters: {
17667
- type: "object",
17668
- properties: {
17669
- database: { type: "string" },
17670
- schema: { type: "string" },
17671
- table: { type: "string" },
17672
- rowId: { type: "string" }
17673
- },
17674
- required: ["database", "schema", "table", "rowId"]
17675
- },
17676
- request: {
17677
- method: "GET",
17678
- path: "/databases/{database}/schemas/{schema}/tables/{table}/rows/{rowId}"
17679
- },
17680
- requiredScopes: ["session:role:manage"]
17681
- },
17682
- {
17683
- name: "rows.search",
17684
- class: "read",
17685
- description: "Search rows in a table.",
17686
- parameters: {
17687
- type: "object",
17688
- properties: {
17689
- database: { type: "string" },
17690
- schema: { type: "string" },
17691
- table: { type: "string" },
17692
- filter: { type: "object" },
17693
- limit: { type: "integer" }
17694
- },
17695
- required: ["database", "schema", "table"]
17696
- },
17697
- request: {
17698
- method: "GET",
17699
- path: "/databases/{database}/schemas/{schema}/tables/{table}/rows",
17700
- query: { filter: "{filter}", limit: "{limit}" }
17701
- },
17702
- requiredScopes: ["session:role:manage"]
17703
- },
17704
- {
17705
- name: "tables.list",
17706
- class: "read",
17707
- description: "List tables in a schema.",
17708
- parameters: {
17709
- type: "object",
17710
- properties: {
17711
- database: { type: "string" },
17712
- schema: { type: "string" }
17713
- },
17714
- required: ["database", "schema"]
17715
- },
17716
- request: {
17717
- method: "GET",
17718
- path: "/databases/{database}/schemas/{schema}/tables"
17734
+ path: "/api/v2/statements",
17735
+ query: { async: "{async}" },
17736
+ body: {
17737
+ statement: "{statement}",
17738
+ timeout: "{timeout}",
17739
+ database: "{database}",
17740
+ schema: "{schema}",
17741
+ warehouse: "{warehouse}",
17742
+ role: "{role}",
17743
+ parameters: { MULTI_STATEMENT_COUNT: "{multiStatementCount}" }
17744
+ }
17719
17745
  },
17720
- requiredScopes: ["session:role:manage"]
17746
+ cas: "none",
17747
+ externalEffect: true
17721
17748
  },
17722
17749
  {
17723
- name: "tables.getSchema",
17750
+ name: "statements.get",
17724
17751
  class: "read",
17725
- description: "Get the schema of a table.",
17752
+ description: "Check a statement and retrieve one result partition.",
17726
17753
  parameters: {
17727
17754
  type: "object",
17728
17755
  properties: {
17729
- database: { type: "string" },
17730
- schema: { type: "string" },
17731
- table: { type: "string" }
17756
+ statementHandle: { type: "string" },
17757
+ partition: { type: "integer", minimum: 0 }
17732
17758
  },
17733
- required: ["database", "schema", "table"]
17759
+ required: ["statementHandle"]
17734
17760
  },
17735
17761
  request: {
17736
17762
  method: "GET",
17737
- path: "/databases/{database}/schemas/{schema}/tables/{table}/schema"
17738
- },
17739
- requiredScopes: ["session:role:manage"]
17740
- },
17741
- {
17742
- name: "procedures.execute",
17743
- class: "mutation",
17744
- description: "Execute a stored procedure.",
17745
- parameters: {
17746
- type: "object",
17747
- properties: {
17748
- database: { type: "string" },
17749
- schema: { type: "string" },
17750
- procedureName: { type: "string" },
17751
- arguments: { type: "array", items: { type: "string" } }
17752
- },
17753
- required: ["database", "schema", "procedureName"]
17754
- },
17755
- request: {
17756
- method: "POST",
17757
- path: "/databases/{database}/schemas/{schema}/procedures/{procedureName}/execute",
17758
- body: { arguments: "{arguments}" }
17759
- },
17760
- requiredScopes: ["session:role:manage"]
17761
- },
17762
- {
17763
- name: "stages.loadData",
17764
- class: "mutation",
17765
- description: "Load data from a stage into a table.",
17766
- parameters: {
17767
- type: "object",
17768
- properties: {
17769
- database: { type: "string" },
17770
- schema: { type: "string" },
17771
- table: { type: "string" },
17772
- stage: { type: "string" },
17773
- files: { type: "array", items: { type: "string" } }
17774
- },
17775
- required: ["database", "schema", "table", "stage"]
17776
- },
17777
- request: {
17778
- method: "POST",
17779
- path: "/databases/{database}/schemas/{schema}/tables/{table}/load",
17780
- body: { stage: "{stage}", files: "{files}" }
17781
- },
17782
- cas: "native-idempotency",
17783
- requiredScopes: ["session:role:manage"]
17784
- },
17785
- {
17786
- name: "dynamicTables.create",
17787
- class: "mutation",
17788
- description: "Create a dynamic table.",
17789
- parameters: {
17790
- type: "object",
17791
- properties: {
17792
- database: { type: "string" },
17793
- schema: { type: "string" },
17794
- name: { type: "string" },
17795
- query: { type: "string" }
17796
- },
17797
- required: ["database", "schema", "name", "query"]
17798
- },
17799
- request: {
17800
- method: "POST",
17801
- path: "/databases/{database}/schemas/{schema}/dynamic-tables",
17802
- body: { name: "{name}", query: "{query}" }
17803
- },
17804
- cas: "native-idempotency",
17805
- requiredScopes: ["session:role:manage"]
17806
- },
17807
- {
17808
- name: "tables.create",
17809
- class: "mutation",
17810
- description: "Create a table in a schema.",
17811
- parameters: {
17812
- type: "object",
17813
- properties: {
17814
- database: { type: "string" },
17815
- schema: { type: "string" },
17816
- name: { type: "string" },
17817
- columns: {
17818
- type: "array",
17819
- description: 'Column definitions: name + Snowflake type, e.g. {name: "id", type: "NUMBER"}.',
17820
- items: {
17821
- type: "object",
17822
- properties: {
17823
- name: { type: "string" },
17824
- type: { type: "string" },
17825
- nullable: { type: "boolean" },
17826
- default: {}
17827
- },
17828
- required: ["name", "type"]
17829
- }
17830
- }
17831
- },
17832
- required: ["database", "schema", "name", "columns"]
17833
- },
17834
- request: {
17835
- method: "POST",
17836
- path: "/databases/{database}/schemas/{schema}/tables",
17837
- body: { name: "{name}", columns: "{columns}" }
17838
- },
17839
- cas: "native-idempotency",
17840
- externalEffect: true,
17841
- requiredScopes: ["session:role:manage"]
17842
- },
17843
- {
17844
- name: "tables.drop",
17845
- class: "mutation",
17846
- description: "Drop a table from a schema.",
17847
- parameters: {
17848
- type: "object",
17849
- properties: {
17850
- database: { type: "string" },
17851
- schema: { type: "string" },
17852
- table: { type: "string" }
17853
- },
17854
- required: ["database", "schema", "table"]
17855
- },
17856
- request: {
17857
- method: "DELETE",
17858
- path: "/databases/{database}/schemas/{schema}/tables/{table}"
17859
- },
17860
- cas: "native-idempotency",
17861
- externalEffect: true,
17862
- requiredScopes: ["session:role:manage"]
17863
- },
17864
- {
17865
- name: "stages.create",
17866
- class: "mutation",
17867
- description: "Create an internal stage for file loads.",
17868
- parameters: {
17869
- type: "object",
17870
- properties: {
17871
- database: { type: "string" },
17872
- schema: { type: "string" },
17873
- name: { type: "string" },
17874
- fileFormat: { type: "string", description: 'Optional named file format, e.g. "CSV".' },
17875
- comment: { type: "string" }
17876
- },
17877
- required: ["database", "schema", "name"]
17878
- },
17879
- request: {
17880
- method: "POST",
17881
- path: "/databases/{database}/schemas/{schema}/stages",
17882
- body: "args"
17883
- },
17884
- cas: "native-idempotency",
17885
- externalEffect: true,
17886
- requiredScopes: ["session:role:manage"]
17763
+ path: "/api/v2/statements/{statementHandle}",
17764
+ query: { partition: "{partition}" }
17765
+ }
17887
17766
  },
17888
17767
  {
17889
- name: "stages.unloadData",
17768
+ name: "statements.cancel",
17890
17769
  class: "mutation",
17891
- description: "Unload table data to a stage (COPY INTO @stage FROM table).",
17770
+ description: "Cancel a running SQL statement by its Snowflake handle.",
17892
17771
  parameters: {
17893
17772
  type: "object",
17894
- properties: {
17895
- database: { type: "string" },
17896
- schema: { type: "string" },
17897
- table: { type: "string" },
17898
- stage: { type: "string" },
17899
- fileFormat: { type: "string" },
17900
- overwrite: { type: "boolean" }
17901
- },
17902
- required: ["database", "schema", "table", "stage"]
17773
+ properties: { statementHandle: { type: "string" } },
17774
+ required: ["statementHandle"]
17903
17775
  },
17904
17776
  request: {
17905
17777
  method: "POST",
17906
- path: "/databases/{database}/schemas/{schema}/tables/{table}/unload",
17907
- body: "args"
17908
- },
17909
- cas: "native-idempotency",
17910
- externalEffect: true,
17911
- requiredScopes: ["session:role:manage"]
17912
- },
17913
- {
17914
- name: "warehouses.list",
17915
- class: "read",
17916
- description: "List warehouses available to the authenticated identity.",
17917
- parameters: {
17918
- type: "object",
17919
- properties: {
17920
- like: { type: "string", description: "Optional name pattern (SQL LIKE syntax)." }
17921
- }
17922
- },
17923
- request: {
17924
- method: "GET",
17925
- path: "/warehouses",
17926
- query: { like: "{like}" }
17778
+ path: "/api/v2/statements/{statementHandle}/cancel",
17779
+ body: {}
17927
17780
  },
17928
- requiredScopes: ["session:role:manage"]
17781
+ cas: "none",
17782
+ externalEffect: true
17929
17783
  }
17930
17784
  ]
17931
17785
  });
@@ -17934,19 +17788,29 @@ var snowflakeConnector = declarativeRestConnector({
17934
17788
  var teableConnector = declarativeRestConnector({
17935
17789
  kind: "teable",
17936
17790
  displayName: "Teable",
17937
- description: "Create, read, update, and delete records in Teable databases, plus upload attachments.",
17791
+ description: "Read and write records, tables, fields, and views in Teable databases.",
17938
17792
  auth: {
17939
17793
  kind: "oauth2",
17940
- authorizationUrl: "https://app.teable.io/oauth/authorize",
17941
- tokenUrl: "https://app.teable.io/oauth/token",
17942
- scopes: ["database:read", "database:write"],
17794
+ authorizationUrl: "https://app.teable.ai/api/oauth/authorize",
17795
+ tokenUrl: "https://app.teable.ai/api/oauth/access_token",
17796
+ scopes: [
17797
+ "base|read",
17798
+ "table|read",
17799
+ "table|create",
17800
+ "field|create",
17801
+ "view|create",
17802
+ "record|read",
17803
+ "record|create",
17804
+ "record|update"
17805
+ ],
17943
17806
  clientIdEnv: "TEABLE_OAUTH_CLIENT_ID",
17944
- clientSecretEnv: "TEABLE_OAUTH_CLIENT_SECRET"
17807
+ clientSecretEnv: "TEABLE_OAUTH_CLIENT_SECRET",
17808
+ pkce: "supported"
17945
17809
  },
17946
17810
  category: "doc",
17947
17811
  defaultConsistencyModel: "authoritative",
17948
- baseUrl: "https://app.teable.io/api/v1",
17949
- test: { method: "GET", path: "/bases" },
17812
+ baseUrl: "https://app.teable.ai/api",
17813
+ test: { method: "GET", path: "/auth/user/me" },
17950
17814
  capabilities: [
17951
17815
  {
17952
17816
  name: "records.create",
@@ -17956,16 +17820,23 @@ var teableConnector = declarativeRestConnector({
17956
17820
  type: "object",
17957
17821
  properties: {
17958
17822
  tableId: { type: "string" },
17959
- fields: { type: "object" }
17823
+ fields: { type: "object" },
17824
+ fieldKeyType: { type: "string", enum: ["name", "id", "dbFieldName"] },
17825
+ typecast: { type: "boolean" }
17960
17826
  },
17961
17827
  required: ["tableId", "fields"]
17962
17828
  },
17963
17829
  request: {
17964
17830
  method: "POST",
17965
- path: "/tables/{tableId}/records",
17966
- body: { fields: "{fields}" }
17831
+ path: "/table/{tableId}/record",
17832
+ body: {
17833
+ records: [{ fields: "{fields}" }],
17834
+ fieldKeyType: "{fieldKeyType}",
17835
+ typecast: "{typecast}"
17836
+ }
17967
17837
  },
17968
- cas: "native-idempotency"
17838
+ cas: "native-idempotency",
17839
+ requiredScopes: ["record|create"]
17969
17840
  },
17970
17841
  {
17971
17842
  name: "records.find",
@@ -17976,20 +17847,27 @@ var teableConnector = declarativeRestConnector({
17976
17847
  properties: {
17977
17848
  tableId: { type: "string" },
17978
17849
  filter: { type: "string" },
17979
- limit: { type: "integer" },
17980
- offset: { type: "integer" }
17850
+ take: { type: "integer", minimum: 1, maximum: 1e3 },
17851
+ skip: { type: "integer", minimum: 0 },
17852
+ viewId: { type: "string" },
17853
+ fieldKeyType: { type: "string", enum: ["name", "id", "dbFieldName"] },
17854
+ cellFormat: { type: "string", enum: ["json", "text"] }
17981
17855
  },
17982
17856
  required: ["tableId"]
17983
17857
  },
17984
17858
  request: {
17985
17859
  method: "GET",
17986
- path: "/tables/{tableId}/records",
17860
+ path: "/table/{tableId}/record",
17987
17861
  query: {
17988
17862
  filter: "{filter}",
17989
- limit: "{limit}",
17990
- offset: "{offset}"
17863
+ take: "{take}",
17864
+ skip: "{skip}",
17865
+ viewId: "{viewId}",
17866
+ fieldKeyType: "{fieldKeyType}",
17867
+ cellFormat: "{cellFormat}"
17991
17868
  }
17992
- }
17869
+ },
17870
+ requiredScopes: ["record|read"]
17993
17871
  },
17994
17872
  {
17995
17873
  name: "records.get",
@@ -17999,14 +17877,21 @@ var teableConnector = declarativeRestConnector({
17999
17877
  type: "object",
18000
17878
  properties: {
18001
17879
  tableId: { type: "string" },
18002
- recordId: { type: "string" }
17880
+ recordId: { type: "string" },
17881
+ fieldKeyType: { type: "string", enum: ["name", "id", "dbFieldName"] },
17882
+ cellFormat: { type: "string", enum: ["json", "text"] }
18003
17883
  },
18004
17884
  required: ["tableId", "recordId"]
18005
17885
  },
18006
17886
  request: {
18007
17887
  method: "GET",
18008
- path: "/tables/{tableId}/records/{recordId}"
18009
- }
17888
+ path: "/table/{tableId}/record/{recordId}",
17889
+ query: {
17890
+ fieldKeyType: "{fieldKeyType}",
17891
+ cellFormat: "{cellFormat}"
17892
+ }
17893
+ },
17894
+ requiredScopes: ["record|read"]
18010
17895
  },
18011
17896
  {
18012
17897
  name: "records.update",
@@ -18017,60 +17902,23 @@ var teableConnector = declarativeRestConnector({
18017
17902
  properties: {
18018
17903
  tableId: { type: "string" },
18019
17904
  recordId: { type: "string" },
18020
- fields: { type: "object" }
17905
+ fields: { type: "object" },
17906
+ fieldKeyType: { type: "string", enum: ["name", "id", "dbFieldName"] },
17907
+ typecast: { type: "boolean" }
18021
17908
  },
18022
17909
  required: ["tableId", "recordId", "fields"]
18023
17910
  },
18024
17911
  request: {
18025
17912
  method: "PATCH",
18026
- path: "/tables/{tableId}/records/{recordId}",
18027
- body: { fields: "{fields}" }
18028
- },
18029
- cas: "optimistic-read-verify"
18030
- },
18031
- {
18032
- name: "records.delete",
18033
- class: "mutation",
18034
- description: "Delete a record from a Teable table.",
18035
- parameters: {
18036
- type: "object",
18037
- properties: {
18038
- tableId: { type: "string" },
18039
- recordId: { type: "string" }
18040
- },
18041
- required: ["tableId", "recordId"]
18042
- },
18043
- request: {
18044
- method: "DELETE",
18045
- path: "/tables/{tableId}/records/{recordId}"
18046
- },
18047
- cas: "native-idempotency"
18048
- },
18049
- {
18050
- name: "attachments.upload",
18051
- class: "mutation",
18052
- description: "Upload an attachment to a Teable record field.",
18053
- parameters: {
18054
- type: "object",
18055
- properties: {
18056
- tableId: { type: "string" },
18057
- recordId: { type: "string" },
18058
- fieldId: { type: "string" },
18059
- fileUrl: { type: "string" },
18060
- fileName: { type: "string" }
18061
- },
18062
- required: ["tableId", "recordId", "fieldId", "fileUrl"]
18063
- },
18064
- request: {
18065
- method: "POST",
18066
- path: "/tables/{tableId}/records/{recordId}/attachments",
17913
+ path: "/table/{tableId}/record/{recordId}",
18067
17914
  body: {
18068
- fieldId: "{fieldId}",
18069
- fileUrl: "{fileUrl}",
18070
- fileName: "{fileName}"
17915
+ record: { fields: "{fields}" },
17916
+ fieldKeyType: "{fieldKeyType}",
17917
+ typecast: "{typecast}"
18071
17918
  }
18072
17919
  },
18073
- cas: "native-idempotency"
17920
+ cas: "optimistic-read-verify",
17921
+ requiredScopes: ["record|update"]
18074
17922
  },
18075
17923
  {
18076
17924
  name: "tables.list",
@@ -18086,7 +17934,8 @@ var teableConnector = declarativeRestConnector({
18086
17934
  request: {
18087
17935
  method: "GET",
18088
17936
  path: "/base/{baseId}/table"
18089
- }
17937
+ },
17938
+ requiredScopes: ["table|read"]
18090
17939
  },
18091
17940
  {
18092
17941
  name: "tables.create",
@@ -18108,7 +17957,8 @@ var teableConnector = declarativeRestConnector({
18108
17957
  }
18109
17958
  },
18110
17959
  cas: "native-idempotency",
18111
- externalEffect: true
17960
+ externalEffect: true,
17961
+ requiredScopes: ["table|create"]
18112
17962
  },
18113
17963
  {
18114
17964
  name: "fields.create",
@@ -18132,7 +17982,8 @@ var teableConnector = declarativeRestConnector({
18132
17982
  }
18133
17983
  },
18134
17984
  cas: "native-idempotency",
18135
- externalEffect: true
17985
+ externalEffect: true,
17986
+ requiredScopes: ["field|create"]
18136
17987
  },
18137
17988
  {
18138
17989
  name: "views.create",
@@ -18156,7 +18007,8 @@ var teableConnector = declarativeRestConnector({
18156
18007
  }
18157
18008
  },
18158
18009
  cas: "native-idempotency",
18159
- externalEffect: true
18010
+ externalEffect: true,
18011
+ requiredScopes: ["view|create"]
18160
18012
  }
18161
18013
  ]
18162
18014
  });
@@ -19491,21 +19343,42 @@ var zoominfoConnector = declarativeRestConnector({
19491
19343
  });
19492
19344
 
19493
19345
  // src/connectors/adapters/zuora.ts
19346
+ var ZUORA_API_BASE_URLS = [
19347
+ "https://rest.test.zuora.com",
19348
+ "https://rest.sandbox.na.zuora.com",
19349
+ "https://rest.apisandbox.zuora.com",
19350
+ "https://rest.na.zuora.com",
19351
+ "https://rest.zuora.com",
19352
+ "https://rest.test.eu.zuora.com",
19353
+ "https://rest.sandbox.eu.zuora.com",
19354
+ "https://rest.eu.zuora.com",
19355
+ "https://rest.test.ap.zuora.com",
19356
+ "https://rest.ap.zuora.com"
19357
+ ];
19494
19358
  var zuoraConnector = declarativeRestConnector({
19495
19359
  kind: "zuora",
19496
19360
  displayName: "Zuora",
19497
19361
  description: "Cloud-based subscription management platform. Query accounts, products, and rate plans; create invoices.",
19498
19362
  auth: {
19499
19363
  kind: "oauth2",
19500
- authorizationUrl: "https://www.zuora.com/apps/PersonalSettings.do?method=oauth",
19501
- tokenUrl: "https://rest.zuora.com/oauth/token",
19502
- scopes: ["api"],
19364
+ grantType: "client_credentials",
19365
+ tokenUrl: "{apiBaseUrl}/oauth/token",
19366
+ scopes: [],
19503
19367
  clientIdEnv: "ZUORA_OAUTH_CLIENT_ID",
19504
- clientSecretEnv: "ZUORA_OAUTH_CLIENT_SECRET"
19368
+ clientSecretEnv: "ZUORA_OAUTH_CLIENT_SECRET",
19369
+ tokenClientAuthMethod: "client_secret_post",
19370
+ pkce: "unsupported",
19371
+ urlTemplateMetadata: {
19372
+ apiBaseUrl: {
19373
+ kind: "base-url",
19374
+ allowedBaseUrls: ZUORA_API_BASE_URLS
19375
+ }
19376
+ }
19505
19377
  },
19506
19378
  category: "crm",
19507
19379
  defaultConsistencyModel: "authoritative",
19508
- baseUrl: "https://rest.zuora.com",
19380
+ baseUrl: { metadataKey: "apiBaseUrl" },
19381
+ allowedBaseUrls: ZUORA_API_BASE_URLS,
19509
19382
  test: { method: "GET", path: "/v1/accounts" },
19510
19383
  capabilities: [
19511
19384
  {
@@ -19519,8 +19392,7 @@ var zuoraConnector = declarativeRestConnector({
19519
19392
  },
19520
19393
  required: ["accountId"]
19521
19394
  },
19522
- request: { method: "GET", path: "/v1/accounts/{accountId}" },
19523
- requiredScopes: ["api"]
19395
+ request: { method: "GET", path: "/v1/accounts/{accountId}" }
19524
19396
  },
19525
19397
  {
19526
19398
  name: "products.find",
@@ -19533,8 +19405,7 @@ var zuoraConnector = declarativeRestConnector({
19533
19405
  },
19534
19406
  required: ["productId"]
19535
19407
  },
19536
- request: { method: "GET", path: "/v1/products/{productId}" },
19537
- requiredScopes: ["api"]
19408
+ request: { method: "GET", path: "/v1/products/{productId}" }
19538
19409
  },
19539
19410
  {
19540
19411
  name: "products.rate_plans.find",
@@ -19548,8 +19419,7 @@ var zuoraConnector = declarativeRestConnector({
19548
19419
  },
19549
19420
  required: ["productId", "ratePlanId"]
19550
19421
  },
19551
- request: { method: "GET", path: "/v1/products/{productId}/rate-plans/{ratePlanId}" },
19552
- requiredScopes: ["api"]
19422
+ request: { method: "GET", path: "/v1/products/{productId}/rate-plans/{ratePlanId}" }
19553
19423
  },
19554
19424
  {
19555
19425
  name: "invoices.create",
@@ -19573,8 +19443,7 @@ var zuoraConnector = declarativeRestConnector({
19573
19443
  path: "/v1/invoices",
19574
19444
  body: { accountId: "{accountId}", subscriptionId: "{subscriptionId}", items: "{invoiceItems}" }
19575
19445
  },
19576
- cas: "native-idempotency",
19577
- requiredScopes: ["api"]
19446
+ cas: "native-idempotency"
19578
19447
  },
19579
19448
  {
19580
19449
  name: "subscriptions.create",
@@ -19600,8 +19469,7 @@ var zuoraConnector = declarativeRestConnector({
19600
19469
  body: "args"
19601
19470
  },
19602
19471
  cas: "native-idempotency",
19603
- externalEffect: true,
19604
- requiredScopes: ["api"]
19472
+ externalEffect: true
19605
19473
  },
19606
19474
  {
19607
19475
  name: "subscriptions.cancel",
@@ -19629,8 +19497,7 @@ var zuoraConnector = declarativeRestConnector({
19629
19497
  body: "args"
19630
19498
  },
19631
19499
  cas: "native-idempotency",
19632
- externalEffect: true,
19633
- requiredScopes: ["api"]
19500
+ externalEffect: true
19634
19501
  },
19635
19502
  {
19636
19503
  name: "subscriptions.update",
@@ -19653,8 +19520,7 @@ var zuoraConnector = declarativeRestConnector({
19653
19520
  body: "args"
19654
19521
  },
19655
19522
  cas: "native-idempotency",
19656
- externalEffect: true,
19657
- requiredScopes: ["api"]
19523
+ externalEffect: true
19658
19524
  },
19659
19525
  {
19660
19526
  name: "payments.create",
@@ -19682,8 +19548,7 @@ var zuoraConnector = declarativeRestConnector({
19682
19548
  body: "args"
19683
19549
  },
19684
19550
  cas: "native-idempotency",
19685
- externalEffect: true,
19686
- requiredScopes: ["api"]
19551
+ externalEffect: true
19687
19552
  }
19688
19553
  ]
19689
19554
  });
@@ -56026,6 +55891,7 @@ var NOTION_SPEC = {
56026
55891
  scopes: [],
56027
55892
  clientIdEnv: "NOTION_OAUTH_CLIENT_ID",
56028
55893
  clientSecretEnv: "NOTION_OAUTH_CLIENT_SECRET",
55894
+ tokenClientAuthMethod: "client_secret_basic",
56029
55895
  extraAuthParams: { owner: "user" }
56030
55896
  },
56031
55897
  category: "doc",
@@ -56348,11 +56214,9 @@ function notion(opts) {
56348
56214
  ...withNotionOverrides(declarativeRestConnector(NOTION_SPEC)),
56349
56215
  /**
56350
56216
  * Notion's token endpoint follows RFC 6749 with one twist — it REQUIRES
56351
- * HTTP Basic auth (client_id:client_secret) and does NOT accept the client
56352
- * credentials in the form body, so we POST inline rather than via the
56353
- * generic `exchangeAuthorizationCode` helper. The workspace_id/bot_id come
56354
- * back in the response and we stash them in `metadata` so the agent can
56355
- * address resources by workspace where useful.
56217
+ * HTTP Basic auth and returns workspace metadata with the grant. We use
56218
+ * the shared Basic encoding and redaction primitives, then retain that
56219
+ * metadata for resource selection.
56356
56220
  */
56357
56221
  async exchangeOAuth(input) {
56358
56222
  if (!clientId || !clientSecret) {
@@ -56367,22 +56231,62 @@ function notion(opts) {
56367
56231
  redirect_uri: input.redirectUri,
56368
56232
  code_verifier: input.codeVerifier
56369
56233
  });
56370
- const res = await fetch(TOKEN_URL13, {
56371
- method: "POST",
56372
- headers: {
56373
- authorization: `Basic ${Buffer.from(`${clientId}:${clientSecret}`).toString("base64")}`,
56374
- "content-type": "application/x-www-form-urlencoded",
56375
- accept: "application/json",
56376
- "Notion-Version": NOTION_VERSION
56377
- },
56378
- body,
56379
- signal: AbortSignal.timeout(15e3)
56380
- });
56234
+ const authorization = createOAuthBasicAuthorizationHeader(
56235
+ clientId,
56236
+ clientSecret
56237
+ );
56238
+ const redactionValues = [
56239
+ input.code,
56240
+ input.codeVerifier,
56241
+ ...oauthClientCredentialRedactionValues(
56242
+ clientId,
56243
+ clientSecret,
56244
+ authorization
56245
+ )
56246
+ ];
56247
+ let res;
56248
+ try {
56249
+ res = await fetch(TOKEN_URL13, {
56250
+ method: "POST",
56251
+ headers: {
56252
+ authorization,
56253
+ "content-type": "application/x-www-form-urlencoded",
56254
+ accept: "application/json",
56255
+ "Notion-Version": NOTION_VERSION
56256
+ },
56257
+ body,
56258
+ signal: AbortSignal.timeout(15e3)
56259
+ });
56260
+ } catch (cause) {
56261
+ const detail = redactOAuthSensitiveText(
56262
+ cause?.message ?? "unknown",
56263
+ redactionValues
56264
+ );
56265
+ throw new Error(`Notion OAuth token exchange transport error: ${detail}`);
56266
+ }
56381
56267
  if (!res.ok) {
56382
56268
  const text = await res.text().catch(() => "");
56383
- throw new Error(`Notion OAuth token exchange failed: ${res.status} \u2014 ${text.slice(0, 200)}`);
56269
+ const statusText = redactOAuthSensitiveText(
56270
+ res.statusText,
56271
+ redactionValues
56272
+ );
56273
+ const detail = redactOAuthSensitiveText(text, redactionValues).slice(
56274
+ 0,
56275
+ 200
56276
+ );
56277
+ throw new Error(
56278
+ `Notion OAuth token exchange failed: ${res.status} ${statusText} \u2014 ${detail}`
56279
+ );
56280
+ }
56281
+ let json;
56282
+ try {
56283
+ json = await res.json();
56284
+ } catch {
56285
+ throw new Error("Notion OAuth token exchange returned invalid JSON");
56286
+ }
56287
+ if (!json.access_token) {
56288
+ throw new Error("Notion OAuth token exchange returned no access_token");
56384
56289
  }
56385
- const json = await res.json();
56386
56290
  return {
56387
56291
  credentials: {
56388
56292
  kind: "oauth2",
@@ -56413,6 +56317,7 @@ function notion(opts) {
56413
56317
  tokenUrl: TOKEN_URL13,
56414
56318
  clientId,
56415
56319
  clientSecret,
56320
+ tokenClientAuthMethod: "client_secret_basic",
56416
56321
  refreshToken: creds.refreshToken
56417
56322
  });
56418
56323
  return {
@@ -69359,7 +69264,8 @@ var TWITTER_SPEC = {
69359
69264
  tokenUrl: TOKEN_URL19,
69360
69265
  scopes: SCOPES13,
69361
69266
  clientIdEnv: "TWITTER_OAUTH_CLIENT_ID",
69362
- clientSecretEnv: "TWITTER_OAUTH_CLIENT_SECRET"
69267
+ clientSecretEnv: "TWITTER_OAUTH_CLIENT_SECRET",
69268
+ tokenClientAuthMethod: "client_secret_basic"
69363
69269
  },
69364
69270
  {
69365
69271
  kind: "api-key",
@@ -69656,21 +69562,61 @@ function twitter(opts) {
69656
69562
  };
69657
69563
  }
69658
69564
  async function twitterTokenRequest(clientId, clientSecret, params) {
69659
- const res = await fetch(TOKEN_URL19, {
69660
- method: "POST",
69661
- headers: {
69662
- authorization: `Basic ${Buffer.from(`${clientId}:${clientSecret}`).toString("base64")}`,
69663
- "content-type": "application/x-www-form-urlencoded",
69664
- accept: "application/json"
69665
- },
69666
- body: new URLSearchParams(params),
69667
- signal: AbortSignal.timeout(15e3)
69668
- });
69565
+ const authorization = createOAuthBasicAuthorizationHeader(
69566
+ clientId,
69567
+ clientSecret
69568
+ );
69569
+ const requestSecrets = [
69570
+ params.code,
69571
+ params.code_verifier,
69572
+ params.refresh_token
69573
+ ].filter((value) => typeof value === "string" && value.length > 0);
69574
+ const redactionValues = [
69575
+ ...requestSecrets,
69576
+ ...oauthClientCredentialRedactionValues(
69577
+ clientId,
69578
+ clientSecret,
69579
+ authorization
69580
+ )
69581
+ ];
69582
+ let res;
69583
+ try {
69584
+ res = await fetch(TOKEN_URL19, {
69585
+ method: "POST",
69586
+ headers: {
69587
+ authorization,
69588
+ "content-type": "application/x-www-form-urlencoded",
69589
+ accept: "application/json"
69590
+ },
69591
+ body: new URLSearchParams(params),
69592
+ signal: AbortSignal.timeout(15e3)
69593
+ });
69594
+ } catch (cause) {
69595
+ const detail = redactOAuthSensitiveText(
69596
+ cause?.message ?? "unknown",
69597
+ redactionValues
69598
+ );
69599
+ throw new Error(
69600
+ `twitter ${params.grant_type} token transport error: ${detail}`
69601
+ );
69602
+ }
69669
69603
  if (!res.ok) {
69670
69604
  const text = await res.text().catch(() => "");
69671
- throw new Error(`twitter ${params.grant_type} token request failed: ${res.status} ${res.statusText} \u2014 ${text.slice(0, 200)}`);
69605
+ const statusText = redactOAuthSensitiveText(res.statusText, redactionValues);
69606
+ const detail = redactOAuthSensitiveText(text, redactionValues).slice(0, 200);
69607
+ throw new Error(
69608
+ `twitter ${params.grant_type} token request failed: ${res.status} ${statusText} \u2014 ${detail}`
69609
+ );
69610
+ }
69611
+ let json;
69612
+ try {
69613
+ json = await res.json();
69614
+ } catch {
69615
+ throw new Error(`twitter ${params.grant_type} token request returned invalid JSON`);
69616
+ }
69617
+ if (!json.access_token) {
69618
+ throw new Error(`twitter ${params.grant_type} token request returned no access_token`);
69672
69619
  }
69673
- const json = await res.json();
69674
69620
  return {
69675
69621
  accessToken: json.access_token,
69676
69622
  refreshToken: json.refresh_token,
@@ -77669,11 +77615,19 @@ var marketoConnector = declarativeRestConnector({
77669
77615
  description: "Manage Marketo leads, static lists, and smart campaigns through the REST API v1.",
77670
77616
  auth: {
77671
77617
  kind: "oauth2",
77672
- authorizationUrl: "https://app.marketo.com/identity/oauth/authorize",
77673
- tokenUrl: "https://app.marketo.com/identity/oauth/token",
77618
+ grantType: "client_credentials",
77619
+ tokenUrl: "{restEndpoint}/identity/oauth/token",
77674
77620
  scopes: [],
77675
77621
  clientIdEnv: "MARKETO_OAUTH_CLIENT_ID",
77676
- clientSecretEnv: "MARKETO_OAUTH_CLIENT_SECRET"
77622
+ clientSecretEnv: "MARKETO_OAUTH_CLIENT_SECRET",
77623
+ tokenClientAuthMethod: "client_secret_post",
77624
+ pkce: "unsupported",
77625
+ urlTemplateMetadata: {
77626
+ restEndpoint: {
77627
+ kind: "base-url",
77628
+ allowedBaseUrlSuffixes: [".mktorest.com"]
77629
+ }
77630
+ }
77677
77631
  },
77678
77632
  category: "crm",
77679
77633
  defaultConsistencyModel: "authoritative",
@@ -84025,10 +83979,7 @@ var CONNECTOR_ADAPTER_FACTORIES = [
84025
83979
  clientId: "NIFTY_OAUTH_CLIENT_ID",
84026
83980
  clientSecret: "NIFTY_OAUTH_CLIENT_SECRET"
84027
83981
  }),
84028
- defineFactoryAdapter(() => opsgenieConnector, {
84029
- clientId: "OPSGENIE_OAUTH_CLIENT_ID",
84030
- clientSecret: "OPSGENIE_OAUTH_CLIENT_SECRET"
84031
- }),
83982
+ defineFactoryAdapter(() => opsgenieConnector, {}),
84032
83983
  defineFactoryAdapter(() => pagerdutyConnector, {
84033
83984
  clientId: "PAGERDUTY_OAUTH_CLIENT_ID",
84034
83985
  clientSecret: "PAGERDUTY_OAUTH_CLIENT_SECRET"
@@ -148876,6 +148827,10 @@ export {
148876
148827
  exchangeAuthorizationCode,
148877
148828
  refreshAccessToken,
148878
148829
  createOAuthTokenRequestHeaders,
148830
+ formEncodeOAuthClientCredential,
148831
+ createOAuthBasicAuthorizationHeader,
148832
+ oauthClientCredentialRedactionValues,
148833
+ redactOAuthSensitiveText,
148879
148834
  _resetPendingFlowsForTests,
148880
148835
  declarativeRestConnector,
148881
148836
  oktaConnector,
@@ -149533,4 +149488,4 @@ export {
149533
149488
  getresponseConnector,
149534
149489
  adapters_exports
149535
149490
  };
149536
- //# sourceMappingURL=chunk-H5UCSRF4.js.map
149491
+ //# sourceMappingURL=chunk-BYTP5QJQ.js.map