@tangle-network/agent-integrations 0.15.0 → 0.16.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/README.md +27 -0
- package/dist/index.d.ts +218 -52
- package/dist/index.js +759 -156
- package/dist/index.js.map +1 -1
- package/docs/repo-structure.md +47 -0
- package/examples/calendar-exercise-app.ts +78 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -129,7 +129,7 @@ function buildActivepiecesConnectors(options = {}) {
|
|
|
129
129
|
const category = override?.category ?? entry.category;
|
|
130
130
|
const scopes = [`${entry.id}.read`, `${entry.id}.write`];
|
|
131
131
|
const catalogActions = entry.actions.length > 0 ? entry.actions.map((action) => toAction(applyActionOverride(action, override), scopes, dataClassFor(category))) : defaultActions(entry.id, scopes, dataClassFor(category));
|
|
132
|
-
const catalogTriggers = entry.triggers.map((
|
|
132
|
+
const catalogTriggers = entry.triggers.map((trigger2) => toTrigger(trigger2, scopes, dataClassFor(category)));
|
|
133
133
|
return {
|
|
134
134
|
id: entry.id,
|
|
135
135
|
providerId,
|
|
@@ -172,10 +172,10 @@ function toAction(action, scopes, dataClass) {
|
|
|
172
172
|
inputSchema: { type: "object", additionalProperties: true, properties: {} }
|
|
173
173
|
};
|
|
174
174
|
}
|
|
175
|
-
function toTrigger(
|
|
175
|
+
function toTrigger(trigger2, scopes, dataClass) {
|
|
176
176
|
return {
|
|
177
|
-
id:
|
|
178
|
-
title:
|
|
177
|
+
id: trigger2.id,
|
|
178
|
+
title: trigger2.title,
|
|
179
179
|
requiredScopes: [scopes[0]],
|
|
180
180
|
dataClass,
|
|
181
181
|
payloadSchema: { type: "object", additionalProperties: true, properties: {} }
|
|
@@ -1247,8 +1247,8 @@ function mergeActions(candidates) {
|
|
|
1247
1247
|
function mergeTriggers(candidates) {
|
|
1248
1248
|
const out = /* @__PURE__ */ new Map();
|
|
1249
1249
|
for (const candidate of toolBindableCandidates(candidates)) {
|
|
1250
|
-
for (const
|
|
1251
|
-
if (!out.has(
|
|
1250
|
+
for (const trigger2 of candidate.connector.triggers ?? []) {
|
|
1251
|
+
if (!out.has(trigger2.id)) out.set(trigger2.id, trigger2);
|
|
1252
1252
|
}
|
|
1253
1253
|
}
|
|
1254
1254
|
return out.size > 0 ? [...out.values()] : void 0;
|
|
@@ -1521,6 +1521,228 @@ function approvalInputHash(input) {
|
|
|
1521
1521
|
return createHash("sha256").update(JSON.stringify(input ?? null)).digest("base64url");
|
|
1522
1522
|
}
|
|
1523
1523
|
|
|
1524
|
+
// src/actions.ts
|
|
1525
|
+
var CANONICAL_INTEGRATION_ACTIONS = {
|
|
1526
|
+
googleCalendarEventsList: "google-calendar.events.list",
|
|
1527
|
+
googleCalendarEventsCreate: "google-calendar.events.create",
|
|
1528
|
+
gmailMessagesSearch: "gmail.messages.search",
|
|
1529
|
+
gmailMessagesSend: "gmail.messages.send",
|
|
1530
|
+
googleDriveFilesSearch: "google-drive.files.search",
|
|
1531
|
+
googleDriveFilesRead: "google-drive.files.read",
|
|
1532
|
+
githubRepositoriesGet: "github.repositories.get",
|
|
1533
|
+
githubIssuesSearch: "github.issues.search",
|
|
1534
|
+
githubIssuesCreate: "github.issues.create",
|
|
1535
|
+
githubPullRequestsComment: "github.pull-requests.comment",
|
|
1536
|
+
slackChannelsList: "slack.channels.list",
|
|
1537
|
+
slackMessagesSearch: "slack.messages.search",
|
|
1538
|
+
slackMessagesPost: "slack.messages.post",
|
|
1539
|
+
providerHttpRequest: "provider.http.request"
|
|
1540
|
+
};
|
|
1541
|
+
function buildCanonicalLaunchConnectors(options = {}) {
|
|
1542
|
+
const providerId = options.providerId ?? "tangle-platform";
|
|
1543
|
+
const connectors = [
|
|
1544
|
+
googleCalendarConnector(providerId),
|
|
1545
|
+
gmailConnector(providerId),
|
|
1546
|
+
googleDriveConnector(providerId),
|
|
1547
|
+
githubConnector(providerId),
|
|
1548
|
+
slackConnector(providerId)
|
|
1549
|
+
];
|
|
1550
|
+
if (!options.includeProviderPassthrough) return connectors;
|
|
1551
|
+
return connectors.map((connector) => ({
|
|
1552
|
+
...connector,
|
|
1553
|
+
actions: [...connector.actions, providerPassthroughAction(connector.id)]
|
|
1554
|
+
}));
|
|
1555
|
+
}
|
|
1556
|
+
function canonicalActionConnectorId(actionId) {
|
|
1557
|
+
if (actionId.startsWith("google-calendar.")) return "google-calendar";
|
|
1558
|
+
if (actionId.startsWith("gmail.")) return "gmail";
|
|
1559
|
+
if (actionId.startsWith("google-drive.")) return "google-drive";
|
|
1560
|
+
if (actionId.startsWith("github.")) return "github";
|
|
1561
|
+
if (actionId.startsWith("slack.")) return "slack";
|
|
1562
|
+
if (actionId === CANONICAL_INTEGRATION_ACTIONS.providerHttpRequest) return void 0;
|
|
1563
|
+
return actionId.split(".")[0];
|
|
1564
|
+
}
|
|
1565
|
+
function googleCalendarConnector(providerId) {
|
|
1566
|
+
return {
|
|
1567
|
+
id: "google-calendar",
|
|
1568
|
+
providerId,
|
|
1569
|
+
title: "Google Calendar",
|
|
1570
|
+
category: "calendar",
|
|
1571
|
+
auth: "oauth2",
|
|
1572
|
+
scopes: ["https://www.googleapis.com/auth/calendar.readonly", "https://www.googleapis.com/auth/calendar.events"],
|
|
1573
|
+
actions: [
|
|
1574
|
+
{
|
|
1575
|
+
id: CANONICAL_INTEGRATION_ACTIONS.googleCalendarEventsList,
|
|
1576
|
+
title: "List calendar events",
|
|
1577
|
+
risk: "read",
|
|
1578
|
+
requiredScopes: ["https://www.googleapis.com/auth/calendar.readonly"],
|
|
1579
|
+
dataClass: "private",
|
|
1580
|
+
description: "Read events from a Google Calendar over a bounded time range.",
|
|
1581
|
+
inputSchema: objectSchema2({
|
|
1582
|
+
calendarId: { type: "string", default: "primary" },
|
|
1583
|
+
timeMin: { type: "string", description: "RFC3339 lower bound." },
|
|
1584
|
+
timeMax: { type: "string", description: "RFC3339 upper bound." }
|
|
1585
|
+
}, ["timeMin", "timeMax"])
|
|
1586
|
+
},
|
|
1587
|
+
{
|
|
1588
|
+
id: CANONICAL_INTEGRATION_ACTIONS.googleCalendarEventsCreate,
|
|
1589
|
+
title: "Create calendar event",
|
|
1590
|
+
risk: "write",
|
|
1591
|
+
requiredScopes: ["https://www.googleapis.com/auth/calendar.events"],
|
|
1592
|
+
dataClass: "private",
|
|
1593
|
+
approvalRequired: true,
|
|
1594
|
+
description: "Create an event on a Google Calendar after user approval.",
|
|
1595
|
+
inputSchema: objectSchema2({
|
|
1596
|
+
calendarId: { type: "string", default: "primary" },
|
|
1597
|
+
start: { type: "string", description: "RFC3339 start time." },
|
|
1598
|
+
end: { type: "string", description: "RFC3339 end time." },
|
|
1599
|
+
summary: { type: "string" },
|
|
1600
|
+
description: { type: "string" },
|
|
1601
|
+
attendees: { type: "array", items: { type: "string" } }
|
|
1602
|
+
}, ["start", "end", "summary"])
|
|
1603
|
+
}
|
|
1604
|
+
],
|
|
1605
|
+
metadata: { source: "canonical-launch", supportTier: "setupReady" }
|
|
1606
|
+
};
|
|
1607
|
+
}
|
|
1608
|
+
function gmailConnector(providerId) {
|
|
1609
|
+
return {
|
|
1610
|
+
id: "gmail",
|
|
1611
|
+
providerId,
|
|
1612
|
+
title: "Gmail",
|
|
1613
|
+
category: "email",
|
|
1614
|
+
auth: "oauth2",
|
|
1615
|
+
scopes: ["https://www.googleapis.com/auth/gmail.readonly", "https://www.googleapis.com/auth/gmail.send"],
|
|
1616
|
+
actions: [
|
|
1617
|
+
{
|
|
1618
|
+
id: CANONICAL_INTEGRATION_ACTIONS.gmailMessagesSearch,
|
|
1619
|
+
title: "Search Gmail messages",
|
|
1620
|
+
risk: "read",
|
|
1621
|
+
requiredScopes: ["https://www.googleapis.com/auth/gmail.readonly"],
|
|
1622
|
+
dataClass: "private",
|
|
1623
|
+
description: "Search user Gmail messages and return bounded message metadata/snippets.",
|
|
1624
|
+
inputSchema: objectSchema2({ query: { type: "string" }, maxResults: { type: "integer", minimum: 1, maximum: 50 } }, ["query"])
|
|
1625
|
+
},
|
|
1626
|
+
{
|
|
1627
|
+
id: CANONICAL_INTEGRATION_ACTIONS.gmailMessagesSend,
|
|
1628
|
+
title: "Send Gmail message",
|
|
1629
|
+
risk: "write",
|
|
1630
|
+
requiredScopes: ["https://www.googleapis.com/auth/gmail.send"],
|
|
1631
|
+
dataClass: "private",
|
|
1632
|
+
approvalRequired: true,
|
|
1633
|
+
description: "Send an email from the user account after approval.",
|
|
1634
|
+
inputSchema: objectSchema2({
|
|
1635
|
+
to: { type: "array", items: { type: "string" } },
|
|
1636
|
+
subject: { type: "string" },
|
|
1637
|
+
body: { type: "string" }
|
|
1638
|
+
}, ["to", "subject", "body"])
|
|
1639
|
+
}
|
|
1640
|
+
],
|
|
1641
|
+
triggers: [{
|
|
1642
|
+
id: "gmail.messages.received",
|
|
1643
|
+
title: "Gmail message received",
|
|
1644
|
+
requiredScopes: ["https://www.googleapis.com/auth/gmail.readonly"],
|
|
1645
|
+
dataClass: "private",
|
|
1646
|
+
description: "Triggered when a new matching Gmail message is received."
|
|
1647
|
+
}],
|
|
1648
|
+
metadata: { source: "canonical-launch", supportTier: "setupReady" }
|
|
1649
|
+
};
|
|
1650
|
+
}
|
|
1651
|
+
function googleDriveConnector(providerId) {
|
|
1652
|
+
return {
|
|
1653
|
+
id: "google-drive",
|
|
1654
|
+
providerId,
|
|
1655
|
+
title: "Google Drive",
|
|
1656
|
+
category: "storage",
|
|
1657
|
+
auth: "oauth2",
|
|
1658
|
+
scopes: ["https://www.googleapis.com/auth/drive.readonly", "https://www.googleapis.com/auth/drive.file"],
|
|
1659
|
+
actions: [
|
|
1660
|
+
{
|
|
1661
|
+
id: CANONICAL_INTEGRATION_ACTIONS.googleDriveFilesSearch,
|
|
1662
|
+
title: "Search Drive files",
|
|
1663
|
+
risk: "read",
|
|
1664
|
+
requiredScopes: ["https://www.googleapis.com/auth/drive.readonly"],
|
|
1665
|
+
dataClass: "private",
|
|
1666
|
+
description: "Search user-visible Google Drive files.",
|
|
1667
|
+
inputSchema: objectSchema2({ query: { type: "string" }, maxResults: { type: "integer", minimum: 1, maximum: 50 } }, ["query"])
|
|
1668
|
+
},
|
|
1669
|
+
{
|
|
1670
|
+
id: CANONICAL_INTEGRATION_ACTIONS.googleDriveFilesRead,
|
|
1671
|
+
title: "Read Drive file",
|
|
1672
|
+
risk: "read",
|
|
1673
|
+
requiredScopes: ["https://www.googleapis.com/auth/drive.readonly"],
|
|
1674
|
+
dataClass: "private",
|
|
1675
|
+
description: "Read metadata and content for an authorized Drive file.",
|
|
1676
|
+
inputSchema: objectSchema2({ fileId: { type: "string" } }, ["fileId"])
|
|
1677
|
+
}
|
|
1678
|
+
],
|
|
1679
|
+
metadata: { source: "canonical-launch", supportTier: "setupReady" }
|
|
1680
|
+
};
|
|
1681
|
+
}
|
|
1682
|
+
function githubConnector(providerId) {
|
|
1683
|
+
return {
|
|
1684
|
+
id: "github",
|
|
1685
|
+
providerId,
|
|
1686
|
+
title: "GitHub",
|
|
1687
|
+
category: "workflow",
|
|
1688
|
+
auth: "oauth2",
|
|
1689
|
+
scopes: ["repo", "read:user"],
|
|
1690
|
+
actions: [
|
|
1691
|
+
readAction(CANONICAL_INTEGRATION_ACTIONS.githubRepositoriesGet, "Read repository metadata", ["repo"], objectSchema2({ owner: { type: "string" }, repo: { type: "string" } }, ["owner", "repo"])),
|
|
1692
|
+
readAction(CANONICAL_INTEGRATION_ACTIONS.githubIssuesSearch, "Search issues and pull requests", ["repo"], objectSchema2({ query: { type: "string" }, limit: { type: "integer", minimum: 1, maximum: 50 } }, ["query"])),
|
|
1693
|
+
writeAction(CANONICAL_INTEGRATION_ACTIONS.githubIssuesCreate, "Create issue", ["repo"], objectSchema2({ owner: { type: "string" }, repo: { type: "string" }, title: { type: "string" }, body: { type: "string" } }, ["owner", "repo", "title"])),
|
|
1694
|
+
writeAction(CANONICAL_INTEGRATION_ACTIONS.githubPullRequestsComment, "Comment on pull request", ["repo"], objectSchema2({ owner: { type: "string" }, repo: { type: "string" }, pullNumber: { type: "integer" }, body: { type: "string" } }, ["owner", "repo", "pullNumber", "body"]))
|
|
1695
|
+
],
|
|
1696
|
+
metadata: { source: "canonical-launch", supportTier: "setupReady" }
|
|
1697
|
+
};
|
|
1698
|
+
}
|
|
1699
|
+
function slackConnector(providerId) {
|
|
1700
|
+
return {
|
|
1701
|
+
id: "slack",
|
|
1702
|
+
providerId,
|
|
1703
|
+
title: "Slack",
|
|
1704
|
+
category: "chat",
|
|
1705
|
+
auth: "oauth2",
|
|
1706
|
+
scopes: ["channels:read", "search:read", "chat:write"],
|
|
1707
|
+
actions: [
|
|
1708
|
+
readAction(CANONICAL_INTEGRATION_ACTIONS.slackChannelsList, "List Slack channels", ["channels:read"], objectSchema2({ limit: { type: "integer", minimum: 1, maximum: 200 } })),
|
|
1709
|
+
readAction(CANONICAL_INTEGRATION_ACTIONS.slackMessagesSearch, "Search Slack messages", ["search:read"], objectSchema2({ query: { type: "string" }, count: { type: "integer", minimum: 1, maximum: 50 } }, ["query"])),
|
|
1710
|
+
writeAction(CANONICAL_INTEGRATION_ACTIONS.slackMessagesPost, "Post Slack message", ["chat:write"], objectSchema2({ channel: { type: "string" }, text: { type: "string" }, blocks: { type: "array" } }, ["channel", "text"]))
|
|
1711
|
+
],
|
|
1712
|
+
triggers: [trigger("slack.message.posted", "Slack message posted", ["channels:read"])],
|
|
1713
|
+
metadata: { source: "canonical-launch", supportTier: "setupReady" }
|
|
1714
|
+
};
|
|
1715
|
+
}
|
|
1716
|
+
function readAction(id, title, scopes, inputSchema) {
|
|
1717
|
+
return { id, title, risk: "read", requiredScopes: scopes, dataClass: "private", inputSchema };
|
|
1718
|
+
}
|
|
1719
|
+
function writeAction(id, title, scopes, inputSchema) {
|
|
1720
|
+
return { id, title, risk: "write", requiredScopes: scopes, dataClass: "private", approvalRequired: true, inputSchema };
|
|
1721
|
+
}
|
|
1722
|
+
function trigger(id, title, scopes) {
|
|
1723
|
+
return { id, title, requiredScopes: scopes, dataClass: "private" };
|
|
1724
|
+
}
|
|
1725
|
+
function providerPassthroughAction(connectorId) {
|
|
1726
|
+
return {
|
|
1727
|
+
id: CANONICAL_INTEGRATION_ACTIONS.providerHttpRequest,
|
|
1728
|
+
title: "Provider HTTP request",
|
|
1729
|
+
risk: "write",
|
|
1730
|
+
requiredScopes: [],
|
|
1731
|
+
dataClass: "sensitive",
|
|
1732
|
+
approvalRequired: true,
|
|
1733
|
+
description: `Controlled provider-native passthrough for ${connectorId}. Disabled by default by platform policy.`,
|
|
1734
|
+
inputSchema: objectSchema2({
|
|
1735
|
+
method: { type: "string", enum: ["GET", "POST", "PUT", "PATCH", "DELETE"] },
|
|
1736
|
+
path: { type: "string" },
|
|
1737
|
+
query: { type: "object" },
|
|
1738
|
+
body: { type: "object" }
|
|
1739
|
+
}, ["method", "path"])
|
|
1740
|
+
};
|
|
1741
|
+
}
|
|
1742
|
+
function objectSchema2(properties, required = []) {
|
|
1743
|
+
return { type: "object", additionalProperties: false, properties, required };
|
|
1744
|
+
}
|
|
1745
|
+
|
|
1524
1746
|
// src/bridge.ts
|
|
1525
1747
|
var DEFAULT_INTEGRATION_BRIDGE_ENV = "TANGLE_INTEGRATION_BUNDLE";
|
|
1526
1748
|
function buildIntegrationBridgePayload(bundle) {
|
|
@@ -1586,6 +1808,219 @@ function assertBridgePayload(value) {
|
|
|
1586
1808
|
if (!Array.isArray(payload.tools)) throw new Error("Invalid integration bridge tools.");
|
|
1587
1809
|
}
|
|
1588
1810
|
|
|
1811
|
+
// src/errors.ts
|
|
1812
|
+
var IntegrationRuntimeError = class extends Error {
|
|
1813
|
+
code;
|
|
1814
|
+
status;
|
|
1815
|
+
userAction;
|
|
1816
|
+
metadata;
|
|
1817
|
+
constructor(input) {
|
|
1818
|
+
super(input.message);
|
|
1819
|
+
this.name = "IntegrationRuntimeError";
|
|
1820
|
+
this.code = input.code;
|
|
1821
|
+
this.status = input.status ?? statusForCode(input.code);
|
|
1822
|
+
this.userAction = input.userAction;
|
|
1823
|
+
this.metadata = input.metadata;
|
|
1824
|
+
}
|
|
1825
|
+
};
|
|
1826
|
+
function normalizeIntegrationError(error) {
|
|
1827
|
+
if (error instanceof IntegrationRuntimeError) {
|
|
1828
|
+
return {
|
|
1829
|
+
ok: false,
|
|
1830
|
+
code: error.code,
|
|
1831
|
+
message: error.message,
|
|
1832
|
+
status: error.status,
|
|
1833
|
+
userAction: error.userAction,
|
|
1834
|
+
metadata: redactUnknown2(error.metadata)
|
|
1835
|
+
};
|
|
1836
|
+
}
|
|
1837
|
+
const message = error instanceof Error ? error.message : String(error ?? "Unknown integration error.");
|
|
1838
|
+
return {
|
|
1839
|
+
ok: false,
|
|
1840
|
+
code: inferCode(message),
|
|
1841
|
+
message,
|
|
1842
|
+
status: 500
|
|
1843
|
+
};
|
|
1844
|
+
}
|
|
1845
|
+
function statusForCode(code) {
|
|
1846
|
+
if (code === "missing_connection" || code === "missing_grant") return 409;
|
|
1847
|
+
if (code === "approval_required") return 202;
|
|
1848
|
+
if (code === "approval_denied") return 403;
|
|
1849
|
+
if (code === "connection_revoked" || code === "connection_expired" || code === "provider_auth_failed") return 401;
|
|
1850
|
+
if (code === "scope_missing" || code === "action_denied" || code === "passthrough_disabled") return 403;
|
|
1851
|
+
if (code === "action_not_found" || code === "manifest_invalid" || code === "input_invalid") return 400;
|
|
1852
|
+
if (code === "provider_rate_limited") return 429;
|
|
1853
|
+
if (code === "provider_unavailable") return 503;
|
|
1854
|
+
if (code === "capability_expired" || code === "capability_invalid") return 401;
|
|
1855
|
+
return 500;
|
|
1856
|
+
}
|
|
1857
|
+
function inferCode(message) {
|
|
1858
|
+
if (/approval/i.test(message)) return "approval_required";
|
|
1859
|
+
if (/scope/i.test(message)) return "scope_missing";
|
|
1860
|
+
if (/expired/i.test(message)) return "connection_expired";
|
|
1861
|
+
if (/revoked/i.test(message)) return "connection_revoked";
|
|
1862
|
+
if (/rate.?limit|429/i.test(message)) return "provider_rate_limited";
|
|
1863
|
+
if (/unauth|forbidden|401|403/i.test(message)) return "provider_auth_failed";
|
|
1864
|
+
return "unknown";
|
|
1865
|
+
}
|
|
1866
|
+
function redactUnknown2(value) {
|
|
1867
|
+
if (Array.isArray(value)) return value.map(redactUnknown2);
|
|
1868
|
+
if (!value || typeof value !== "object") return value;
|
|
1869
|
+
const out = {};
|
|
1870
|
+
for (const [key, child] of Object.entries(value)) {
|
|
1871
|
+
if (/token|secret|password|authorization|api[_-]?key|credential|refresh/i.test(key)) {
|
|
1872
|
+
out[key] = "[REDACTED]";
|
|
1873
|
+
} else {
|
|
1874
|
+
out[key] = redactUnknown2(child);
|
|
1875
|
+
}
|
|
1876
|
+
}
|
|
1877
|
+
return out;
|
|
1878
|
+
}
|
|
1879
|
+
|
|
1880
|
+
// src/client.ts
|
|
1881
|
+
var TangleIntegrationsClient = class {
|
|
1882
|
+
endpoint;
|
|
1883
|
+
bridge;
|
|
1884
|
+
fetchImpl;
|
|
1885
|
+
getCapabilityToken;
|
|
1886
|
+
constructor(options) {
|
|
1887
|
+
this.endpoint = options.endpoint.replace(/\/$/, "");
|
|
1888
|
+
this.bridge = options.bridge ?? parseIntegrationBridgeEnvironment(
|
|
1889
|
+
options.env ?? readProcessEnv(),
|
|
1890
|
+
{ envVar: options.envVar ?? DEFAULT_INTEGRATION_BRIDGE_ENV }
|
|
1891
|
+
);
|
|
1892
|
+
this.fetchImpl = options.fetchImpl ?? fetch;
|
|
1893
|
+
this.getCapabilityToken = options.getCapabilityToken ?? ((tool) => tool.capabilityToken);
|
|
1894
|
+
}
|
|
1895
|
+
tools() {
|
|
1896
|
+
return [...this.bridge.tools];
|
|
1897
|
+
}
|
|
1898
|
+
findTool(toolOrAction) {
|
|
1899
|
+
const found = this.bridge.tools.find(
|
|
1900
|
+
(tool) => tool.name === toolOrAction || tool.action === toolOrAction || `${tool.connectorId}.${tool.action}` === toolOrAction
|
|
1901
|
+
);
|
|
1902
|
+
if (!found) {
|
|
1903
|
+
throw new IntegrationRuntimeError({
|
|
1904
|
+
code: "action_not_found",
|
|
1905
|
+
message: `Integration tool ${toolOrAction} is not available in this runtime.`,
|
|
1906
|
+
metadata: { available: this.bridge.tools.map((tool) => ({ name: tool.name, action: tool.action, connectorId: tool.connectorId })) }
|
|
1907
|
+
});
|
|
1908
|
+
}
|
|
1909
|
+
return found;
|
|
1910
|
+
}
|
|
1911
|
+
async invoke(input) {
|
|
1912
|
+
try {
|
|
1913
|
+
const tool = this.findTool(input.tool);
|
|
1914
|
+
const token = await this.getCapabilityToken(tool);
|
|
1915
|
+
const response = await this.fetchImpl(`${this.endpoint}/v1/integrations/invoke`, {
|
|
1916
|
+
method: "POST",
|
|
1917
|
+
headers: {
|
|
1918
|
+
"content-type": "application/json",
|
|
1919
|
+
authorization: `Bearer ${token}`
|
|
1920
|
+
},
|
|
1921
|
+
body: JSON.stringify({
|
|
1922
|
+
action: tool.action,
|
|
1923
|
+
input: input.input,
|
|
1924
|
+
idempotencyKey: input.idempotencyKey ?? defaultIdempotencyKey(tool.action),
|
|
1925
|
+
dryRun: input.dryRun,
|
|
1926
|
+
metadata: input.metadata
|
|
1927
|
+
})
|
|
1928
|
+
});
|
|
1929
|
+
const json = await response.json().catch(() => void 0);
|
|
1930
|
+
if (!response.ok && !json) {
|
|
1931
|
+
return { status: "failed", action: tool.action, error: `Integration invoke failed with HTTP ${response.status}` };
|
|
1932
|
+
}
|
|
1933
|
+
return json ?? { status: "failed", action: tool.action, error: "Integration invoke returned an empty response." };
|
|
1934
|
+
} catch (error) {
|
|
1935
|
+
const normalized = normalizeIntegrationError(error);
|
|
1936
|
+
return { status: "failed", action: input.tool, error: normalized.message, metadata: { code: normalized.code, userAction: normalized.userAction } };
|
|
1937
|
+
}
|
|
1938
|
+
}
|
|
1939
|
+
};
|
|
1940
|
+
function createTangleIntegrationsClient(options) {
|
|
1941
|
+
return new TangleIntegrationsClient(options);
|
|
1942
|
+
}
|
|
1943
|
+
function defaultIdempotencyKey(action) {
|
|
1944
|
+
return `${action}:${Date.now()}:${Math.random().toString(36).slice(2)}`;
|
|
1945
|
+
}
|
|
1946
|
+
function readProcessEnv() {
|
|
1947
|
+
if (typeof process !== "undefined" && process.env) return process.env;
|
|
1948
|
+
return {};
|
|
1949
|
+
}
|
|
1950
|
+
|
|
1951
|
+
// src/consent.ts
|
|
1952
|
+
function renderConsentSummary(manifestOrResolution, options = {}) {
|
|
1953
|
+
const manifest = "manifest" in manifestOrResolution ? manifestOrResolution.manifest : manifestOrResolution;
|
|
1954
|
+
const appName = options.appName ?? manifest.title ?? manifest.id;
|
|
1955
|
+
const requirements = manifest.requirements;
|
|
1956
|
+
const risk = aggregateRisk(requirements, options.connectors);
|
|
1957
|
+
const connectorIds = unique2(requirements.map((requirement) => requirement.connectorId));
|
|
1958
|
+
const first = requirements[0];
|
|
1959
|
+
const body = first ? sentenceForRequirement(appName, first) : `${appName} does not request integrations.`;
|
|
1960
|
+
return {
|
|
1961
|
+
title: `${appName} wants to use ${humanList(connectorIds.map(titleize))}`,
|
|
1962
|
+
body,
|
|
1963
|
+
bullets: requirements.map((requirement) => bulletForRequirement(requirement, options.connectors)),
|
|
1964
|
+
primaryAction: risk === "read" ? "Allow access" : risk === "write" ? "Review and allow" : "Review destructive access",
|
|
1965
|
+
risk,
|
|
1966
|
+
connectorIds
|
|
1967
|
+
};
|
|
1968
|
+
}
|
|
1969
|
+
function renderApprovalCopy(input) {
|
|
1970
|
+
return {
|
|
1971
|
+
title: `${input.appName} wants to ${input.action.title.toLowerCase()}`,
|
|
1972
|
+
body: `${input.appName} is requesting permission to run "${input.action.title}" on ${input.connectorTitle}.`,
|
|
1973
|
+
bullets: [
|
|
1974
|
+
`Risk: ${input.action.risk}`,
|
|
1975
|
+
`Data: ${input.action.dataClass}`,
|
|
1976
|
+
...input.approvalId ? [`Approval id: ${input.approvalId}`] : []
|
|
1977
|
+
],
|
|
1978
|
+
primaryAction: input.action.risk === "read" ? "Allow" : "Approve action",
|
|
1979
|
+
risk: input.action.risk,
|
|
1980
|
+
connectorIds: []
|
|
1981
|
+
};
|
|
1982
|
+
}
|
|
1983
|
+
function sentenceForRequirement(appName, requirement) {
|
|
1984
|
+
if (requirement.connectorId === "google-calendar" && requirement.mode === "read") {
|
|
1985
|
+
return `${appName} wants to read your Google Calendar to find schedule-aware recommendations.`;
|
|
1986
|
+
}
|
|
1987
|
+
if (requirement.connectorId === "google-calendar" && requirement.mode === "write") {
|
|
1988
|
+
return `${appName} wants to create or update Google Calendar events after your approval.`;
|
|
1989
|
+
}
|
|
1990
|
+
if (requirement.mode === "read") return `${appName} wants to read ${titleize(requirement.connectorId)} data.`;
|
|
1991
|
+
if (requirement.mode === "write") return `${appName} wants to write ${titleize(requirement.connectorId)} data after approval.`;
|
|
1992
|
+
return `${appName} wants to subscribe to ${titleize(requirement.connectorId)} events.`;
|
|
1993
|
+
}
|
|
1994
|
+
function bulletForRequirement(requirement, connectors = []) {
|
|
1995
|
+
const connector = connectors.find((candidate) => candidate.id === requirement.connectorId);
|
|
1996
|
+
const actions = requirement.requiredActions?.length ? requirement.requiredActions.map((id) => connector?.actions.find((action) => action.id === id)?.title ?? id) : requirement.requiredTriggers ?? [];
|
|
1997
|
+
return `${titleize(requirement.connectorId)}: ${requirement.reason}${actions.length ? ` (${actions.join(", ")})` : ""}`;
|
|
1998
|
+
}
|
|
1999
|
+
function aggregateRisk(requirements, connectors = []) {
|
|
2000
|
+
let rank = 0;
|
|
2001
|
+
for (const requirement of requirements) {
|
|
2002
|
+
if (requirement.mode === "write") rank = Math.max(rank, 1);
|
|
2003
|
+
const connector = connectors.find((candidate) => candidate.id === requirement.connectorId);
|
|
2004
|
+
for (const actionId of requirement.requiredActions ?? []) {
|
|
2005
|
+
const risk = connector?.actions.find((action) => action.id === actionId)?.risk;
|
|
2006
|
+
if (risk === "write") rank = Math.max(rank, 1);
|
|
2007
|
+
if (risk === "destructive") rank = Math.max(rank, 2);
|
|
2008
|
+
}
|
|
2009
|
+
}
|
|
2010
|
+
return rank === 2 ? "destructive" : rank === 1 ? "write" : "read";
|
|
2011
|
+
}
|
|
2012
|
+
function humanList(values) {
|
|
2013
|
+
if (values.length <= 1) return values[0] ?? "integrations";
|
|
2014
|
+
if (values.length === 2) return `${values[0]} and ${values[1]}`;
|
|
2015
|
+
return `${values.slice(0, -1).join(", ")}, and ${values.at(-1)}`;
|
|
2016
|
+
}
|
|
2017
|
+
function titleize(value) {
|
|
2018
|
+
return value.split(/[-_.]/g).filter(Boolean).map((part) => part[0].toUpperCase() + part.slice(1)).join(" ");
|
|
2019
|
+
}
|
|
2020
|
+
function unique2(values) {
|
|
2021
|
+
return [...new Set(values)];
|
|
2022
|
+
}
|
|
2023
|
+
|
|
1589
2024
|
// src/adapter-provider.ts
|
|
1590
2025
|
function createConnectorAdapterProvider(options) {
|
|
1591
2026
|
const providerId = options.id ?? "first-party";
|
|
@@ -2153,6 +2588,256 @@ function rollupHealthStatus(checks) {
|
|
|
2153
2588
|
return "healthy";
|
|
2154
2589
|
}
|
|
2155
2590
|
|
|
2591
|
+
// src/manifest.ts
|
|
2592
|
+
function validateIntegrationManifest(manifest) {
|
|
2593
|
+
const issues = [];
|
|
2594
|
+
if (!manifest.id?.trim()) issues.push({ path: "id", message: "Manifest id is required." });
|
|
2595
|
+
if (!Array.isArray(manifest.requirements)) issues.push({ path: "requirements", message: "Requirements must be an array." });
|
|
2596
|
+
const ids = /* @__PURE__ */ new Set();
|
|
2597
|
+
for (const [index, requirement] of (manifest.requirements ?? []).entries()) {
|
|
2598
|
+
const path = `requirements[${index}]`;
|
|
2599
|
+
if (!requirement.id?.trim()) issues.push({ path: `${path}.id`, message: "Requirement id is required." });
|
|
2600
|
+
if (ids.has(requirement.id)) issues.push({ path: `${path}.id`, message: `Duplicate requirement id ${requirement.id}.` });
|
|
2601
|
+
ids.add(requirement.id);
|
|
2602
|
+
if (!requirement.connectorId?.trim()) issues.push({ path: `${path}.connectorId`, message: "Connector id is required." });
|
|
2603
|
+
if (!["read", "write", "trigger"].includes(requirement.mode)) issues.push({ path: `${path}.mode`, message: "Mode must be read, write, or trigger." });
|
|
2604
|
+
if (!requirement.reason?.trim()) issues.push({ path: `${path}.reason`, message: "Human-readable reason is required." });
|
|
2605
|
+
if (requirement.mode !== "trigger" && !requirement.requiredActions?.length) {
|
|
2606
|
+
issues.push({ path: `${path}.requiredActions`, message: "Non-trigger requirements should list required actions." });
|
|
2607
|
+
}
|
|
2608
|
+
if (requirement.mode === "trigger" && !requirement.requiredTriggers?.length) {
|
|
2609
|
+
issues.push({ path: `${path}.requiredTriggers`, message: "Trigger requirements should list required triggers." });
|
|
2610
|
+
}
|
|
2611
|
+
}
|
|
2612
|
+
return { ok: issues.length === 0, issues };
|
|
2613
|
+
}
|
|
2614
|
+
function assertValidIntegrationManifest(manifest) {
|
|
2615
|
+
const result = validateIntegrationManifest(manifest);
|
|
2616
|
+
if (!result.ok) {
|
|
2617
|
+
throw new Error(`Invalid integration manifest: ${result.issues.map((issue) => `${issue.path}: ${issue.message}`).join("; ")}`);
|
|
2618
|
+
}
|
|
2619
|
+
}
|
|
2620
|
+
function inferIntegrationManifestFromTools(options) {
|
|
2621
|
+
const byConnector = /* @__PURE__ */ new Map();
|
|
2622
|
+
for (const item of options.tools) {
|
|
2623
|
+
const action = typeof item === "string" ? item : item.action;
|
|
2624
|
+
const connectorId = typeof item === "string" ? canonicalActionConnectorId(action) : item.connectorId ?? canonicalActionConnectorId(action);
|
|
2625
|
+
if (!connectorId) continue;
|
|
2626
|
+
const mode = typeof item === "string" ? inferMode(action) : item.mode ?? inferMode(action);
|
|
2627
|
+
const id = `${connectorId}-${mode}`;
|
|
2628
|
+
const existing = byConnector.get(id);
|
|
2629
|
+
const reason = typeof item === "string" ? defaultReason(connectorId, mode) : item.reason ?? defaultReason(connectorId, mode);
|
|
2630
|
+
if (existing) {
|
|
2631
|
+
byConnector.set(id, {
|
|
2632
|
+
...existing,
|
|
2633
|
+
requiredActions: unique3([...existing.requiredActions ?? [], action]),
|
|
2634
|
+
requiredScopes: unique3([...existing.requiredScopes ?? [], ...typeof item === "string" ? [] : item.scopes ?? []])
|
|
2635
|
+
});
|
|
2636
|
+
} else {
|
|
2637
|
+
byConnector.set(id, {
|
|
2638
|
+
id,
|
|
2639
|
+
connectorId,
|
|
2640
|
+
mode,
|
|
2641
|
+
reason,
|
|
2642
|
+
requiredActions: mode === "trigger" ? void 0 : [action],
|
|
2643
|
+
requiredScopes: typeof item === "string" ? void 0 : item.scopes
|
|
2644
|
+
});
|
|
2645
|
+
}
|
|
2646
|
+
}
|
|
2647
|
+
const manifest = {
|
|
2648
|
+
id: options.manifestId,
|
|
2649
|
+
title: options.title,
|
|
2650
|
+
requirements: [...byConnector.values()],
|
|
2651
|
+
metadata: options.metadata
|
|
2652
|
+
};
|
|
2653
|
+
assertValidIntegrationManifest(manifest);
|
|
2654
|
+
return manifest;
|
|
2655
|
+
}
|
|
2656
|
+
function explainMissingRequirements(resolution) {
|
|
2657
|
+
return [...resolution.missing, ...resolution.optionalMissing].map((item) => ({
|
|
2658
|
+
requirementId: item.requirement.id,
|
|
2659
|
+
connectorId: item.requirement.connectorId,
|
|
2660
|
+
status: item.status,
|
|
2661
|
+
message: item.message,
|
|
2662
|
+
userAction: item.requirement.optional ? "ignore_optional" : item.status === "not_executable" ? "enable" : "connect"
|
|
2663
|
+
}));
|
|
2664
|
+
}
|
|
2665
|
+
function calendarExercisePlannerManifest(id = "exercise-calendar-planner") {
|
|
2666
|
+
return {
|
|
2667
|
+
id,
|
|
2668
|
+
title: "Exercise Calendar Planner",
|
|
2669
|
+
requirements: [{
|
|
2670
|
+
id: "calendar-read",
|
|
2671
|
+
connectorId: "google-calendar",
|
|
2672
|
+
mode: "read",
|
|
2673
|
+
reason: "Read busy and free calendar windows to recommend exercise sessions.",
|
|
2674
|
+
requiredActions: [CANONICAL_INTEGRATION_ACTIONS.googleCalendarEventsList],
|
|
2675
|
+
requiredScopes: ["https://www.googleapis.com/auth/calendar.readonly"]
|
|
2676
|
+
}]
|
|
2677
|
+
};
|
|
2678
|
+
}
|
|
2679
|
+
function inferMode(action) {
|
|
2680
|
+
if (/(create|send|post|update|delete|write|comment|request)$/i.test(action)) return "write";
|
|
2681
|
+
return "read";
|
|
2682
|
+
}
|
|
2683
|
+
function defaultReason(connectorId, mode) {
|
|
2684
|
+
if (connectorId === "google-calendar" && mode === "read") return "Read calendar availability for the generated app.";
|
|
2685
|
+
if (connectorId === "google-calendar" && mode === "write") return "Create or update calendar events after user approval.";
|
|
2686
|
+
return `${mode === "read" ? "Read from" : mode === "write" ? "Write to" : "Subscribe to"} ${connectorId} for this app.`;
|
|
2687
|
+
}
|
|
2688
|
+
function unique3(values) {
|
|
2689
|
+
return [...new Set(values)];
|
|
2690
|
+
}
|
|
2691
|
+
|
|
2692
|
+
// src/passthrough.ts
|
|
2693
|
+
var PROVIDER_PASSTHROUGH_ACTION = CANONICAL_INTEGRATION_ACTIONS.providerHttpRequest;
|
|
2694
|
+
function validateProviderPassthroughRequest(input, policy) {
|
|
2695
|
+
if (!policy.enabled) {
|
|
2696
|
+
throw new IntegrationRuntimeError({
|
|
2697
|
+
code: "passthrough_disabled",
|
|
2698
|
+
message: "Provider-native passthrough is disabled for this connector."
|
|
2699
|
+
});
|
|
2700
|
+
}
|
|
2701
|
+
if (!input.path.startsWith("/")) {
|
|
2702
|
+
throw new IntegrationRuntimeError({ code: "input_invalid", message: "Provider passthrough path must start with /." });
|
|
2703
|
+
}
|
|
2704
|
+
if (policy.allowedMethods?.length && !policy.allowedMethods.includes(input.method)) {
|
|
2705
|
+
throw new IntegrationRuntimeError({ code: "action_denied", message: `Provider passthrough method ${input.method} is not allowed.` });
|
|
2706
|
+
}
|
|
2707
|
+
if (policy.allowedPathPrefixes?.length && !policy.allowedPathPrefixes.some((prefix) => input.path.startsWith(prefix))) {
|
|
2708
|
+
throw new IntegrationRuntimeError({ code: "action_denied", message: `Provider passthrough path ${input.path} is not allowed.` });
|
|
2709
|
+
}
|
|
2710
|
+
const maxBodyBytes = policy.maxBodyBytes ?? 64 * 1024;
|
|
2711
|
+
const bodyBytes = Buffer.byteLength(JSON.stringify(input.body ?? null), "utf8");
|
|
2712
|
+
if (bodyBytes > maxBodyBytes) {
|
|
2713
|
+
throw new IntegrationRuntimeError({ code: "input_invalid", message: `Provider passthrough body exceeds ${maxBodyBytes} bytes.` });
|
|
2714
|
+
}
|
|
2715
|
+
for (const key of Object.keys(input.headers ?? {})) {
|
|
2716
|
+
if (/authorization|cookie|token|secret|api[_-]?key/i.test(key)) {
|
|
2717
|
+
throw new IntegrationRuntimeError({ code: "input_invalid", message: `Provider passthrough header ${key} is not caller-settable.` });
|
|
2718
|
+
}
|
|
2719
|
+
}
|
|
2720
|
+
}
|
|
2721
|
+
|
|
2722
|
+
// src/policy.ts
|
|
2723
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
2724
|
+
var StaticIntegrationPolicyEngine = class {
|
|
2725
|
+
rules;
|
|
2726
|
+
defaultReadEffect;
|
|
2727
|
+
defaultWriteEffect;
|
|
2728
|
+
defaultDestructiveEffect;
|
|
2729
|
+
now;
|
|
2730
|
+
constructor(options = {}) {
|
|
2731
|
+
this.rules = options.rules ?? [];
|
|
2732
|
+
this.defaultReadEffect = options.defaultReadEffect ?? "allow";
|
|
2733
|
+
this.defaultWriteEffect = options.defaultWriteEffect ?? "require_approval";
|
|
2734
|
+
this.defaultDestructiveEffect = options.defaultDestructiveEffect ?? "deny";
|
|
2735
|
+
this.now = options.now ?? (() => /* @__PURE__ */ new Date());
|
|
2736
|
+
}
|
|
2737
|
+
decide(ctx) {
|
|
2738
|
+
const action = ctx.action;
|
|
2739
|
+
if (!action) return { decision: "deny", reason: "Integration action is missing from connector catalog." };
|
|
2740
|
+
const matched = this.rules.find((rule) => ruleMatches(rule, ctx));
|
|
2741
|
+
const effect = matched?.effect ?? this.defaultEffect(action.risk);
|
|
2742
|
+
const reason = matched?.reason ?? defaultReason2(effect, action.risk);
|
|
2743
|
+
if (effect === "allow") return { decision: "allow", reason, metadata: matched ? { ruleId: matched.id } : void 0 };
|
|
2744
|
+
if (effect === "deny") return { decision: "deny", reason, metadata: matched ? { ruleId: matched.id } : void 0 };
|
|
2745
|
+
return {
|
|
2746
|
+
decision: "require_approval",
|
|
2747
|
+
reason,
|
|
2748
|
+
approval: buildApprovalRequest(ctx, reason, this.now()),
|
|
2749
|
+
metadata: matched ? { ruleId: matched.id } : void 0
|
|
2750
|
+
};
|
|
2751
|
+
}
|
|
2752
|
+
defaultEffect(risk) {
|
|
2753
|
+
if (risk === "read") return this.defaultReadEffect;
|
|
2754
|
+
if (risk === "write") return this.defaultWriteEffect;
|
|
2755
|
+
return this.defaultDestructiveEffect;
|
|
2756
|
+
}
|
|
2757
|
+
};
|
|
2758
|
+
function createDefaultIntegrationPolicyEngine(options = {}) {
|
|
2759
|
+
return new StaticIntegrationPolicyEngine(options);
|
|
2760
|
+
}
|
|
2761
|
+
function buildApprovalRequest(ctx, reason, requestedAt) {
|
|
2762
|
+
if (!ctx.action) {
|
|
2763
|
+
throw new Error("Cannot build approval request without an action descriptor.");
|
|
2764
|
+
}
|
|
2765
|
+
return {
|
|
2766
|
+
id: `approval_${randomUUID2()}`,
|
|
2767
|
+
connectionId: ctx.connection.id,
|
|
2768
|
+
providerId: ctx.connection.providerId,
|
|
2769
|
+
connectorId: ctx.connection.connectorId,
|
|
2770
|
+
action: ctx.request.action,
|
|
2771
|
+
actor: { type: ctx.subject.type, id: ctx.subject.id },
|
|
2772
|
+
risk: ctx.action.risk,
|
|
2773
|
+
dataClass: ctx.action.dataClass,
|
|
2774
|
+
reason,
|
|
2775
|
+
requestedAt: requestedAt.toISOString(),
|
|
2776
|
+
inputPreview: previewInput(ctx.request.input)
|
|
2777
|
+
};
|
|
2778
|
+
}
|
|
2779
|
+
function redactApprovalRequest(request) {
|
|
2780
|
+
return {
|
|
2781
|
+
...request,
|
|
2782
|
+
inputPreview: redactUnknown3(request.inputPreview)
|
|
2783
|
+
};
|
|
2784
|
+
}
|
|
2785
|
+
function ruleMatches(rule, ctx) {
|
|
2786
|
+
if (!ctx.action) return false;
|
|
2787
|
+
if (rule.providerId && rule.providerId !== ctx.connection.providerId) return false;
|
|
2788
|
+
if (rule.connectorId && rule.connectorId !== ctx.connection.connectorId) return false;
|
|
2789
|
+
if (rule.action && rule.action !== ctx.request.action) return false;
|
|
2790
|
+
if (rule.risk && rule.risk !== ctx.action.risk) return false;
|
|
2791
|
+
if (rule.maxRisk && riskRank(ctx.action.risk) > riskRank(rule.maxRisk)) return false;
|
|
2792
|
+
if (rule.dataClass && rule.dataClass !== ctx.action.dataClass) return false;
|
|
2793
|
+
return true;
|
|
2794
|
+
}
|
|
2795
|
+
function riskRank(risk) {
|
|
2796
|
+
if (risk === "read") return 0;
|
|
2797
|
+
if (risk === "write") return 1;
|
|
2798
|
+
return 2;
|
|
2799
|
+
}
|
|
2800
|
+
function defaultReason2(effect, risk) {
|
|
2801
|
+
if (effect === "allow") return `${risk} integration action allowed by default policy.`;
|
|
2802
|
+
if (effect === "deny") return `${risk} integration action denied by default policy.`;
|
|
2803
|
+
return `${risk} integration action requires approval by default policy.`;
|
|
2804
|
+
}
|
|
2805
|
+
function previewInput(input) {
|
|
2806
|
+
return redactUnknown3(input);
|
|
2807
|
+
}
|
|
2808
|
+
function redactUnknown3(value) {
|
|
2809
|
+
if (Array.isArray(value)) return value.map(redactUnknown3);
|
|
2810
|
+
if (!value || typeof value !== "object") return value;
|
|
2811
|
+
const out = {};
|
|
2812
|
+
for (const [key, child] of Object.entries(value)) {
|
|
2813
|
+
if (/token|secret|password|authorization|api[_-]?key|credential/i.test(key)) {
|
|
2814
|
+
out[key] = "[REDACTED]";
|
|
2815
|
+
} else {
|
|
2816
|
+
out[key] = redactUnknown3(child);
|
|
2817
|
+
}
|
|
2818
|
+
}
|
|
2819
|
+
return out;
|
|
2820
|
+
}
|
|
2821
|
+
|
|
2822
|
+
// src/presets.ts
|
|
2823
|
+
function createPlatformIntegrationPolicyPreset(options = {}) {
|
|
2824
|
+
return new StaticIntegrationPolicyEngine({
|
|
2825
|
+
...options,
|
|
2826
|
+
defaultReadEffect: "allow",
|
|
2827
|
+
defaultWriteEffect: options.allowWritesWithoutApproval ? "allow" : "require_approval",
|
|
2828
|
+
defaultDestructiveEffect: options.allowDestructiveActions ? "require_approval" : "deny",
|
|
2829
|
+
rules: [
|
|
2830
|
+
...options.allowProviderPassthrough ? [] : [{
|
|
2831
|
+
id: "deny-provider-native-passthrough",
|
|
2832
|
+
action: "provider.http.request",
|
|
2833
|
+
effect: "deny",
|
|
2834
|
+
reason: "Provider-native passthrough is disabled by default. Promote the connector action or enable passthrough explicitly."
|
|
2835
|
+
}],
|
|
2836
|
+
...options.rules ?? []
|
|
2837
|
+
]
|
|
2838
|
+
});
|
|
2839
|
+
}
|
|
2840
|
+
|
|
2156
2841
|
// src/connectors/types.ts
|
|
2157
2842
|
var ResourceContention = class extends Error {
|
|
2158
2843
|
constructor(message, alternatives = [], currentState) {
|
|
@@ -5013,7 +5698,7 @@ var repoParams = {
|
|
|
5013
5698
|
},
|
|
5014
5699
|
required: ["owner", "repo"]
|
|
5015
5700
|
};
|
|
5016
|
-
var
|
|
5701
|
+
var githubConnector2 = declarativeRestConnector({
|
|
5017
5702
|
kind: "github",
|
|
5018
5703
|
displayName: "GitHub",
|
|
5019
5704
|
description: "Search repositories/issues and create or update GitHub issues through a user-scoped token.",
|
|
@@ -5348,7 +6033,7 @@ var salesforceConnector = declarativeRestConnector({
|
|
|
5348
6033
|
});
|
|
5349
6034
|
|
|
5350
6035
|
// src/catalog.ts
|
|
5351
|
-
var
|
|
6036
|
+
var riskRank2 = {
|
|
5352
6037
|
read: 0,
|
|
5353
6038
|
write: 1,
|
|
5354
6039
|
destructive: 2
|
|
@@ -5371,7 +6056,7 @@ function buildIntegrationToolCatalog(connectors) {
|
|
|
5371
6056
|
const tools = [];
|
|
5372
6057
|
for (const connector of connectors) {
|
|
5373
6058
|
for (const action of connector.actions) {
|
|
5374
|
-
const tags =
|
|
6059
|
+
const tags = unique4([
|
|
5375
6060
|
connector.id,
|
|
5376
6061
|
connector.providerId,
|
|
5377
6062
|
connector.title,
|
|
@@ -5410,7 +6095,7 @@ function searchIntegrationTools(catalog, query, filters = {}) {
|
|
|
5410
6095
|
if (filters.connectorId && tool.connectorId !== filters.connectorId) return false;
|
|
5411
6096
|
if (filters.category && tool.category !== filters.category) return false;
|
|
5412
6097
|
if (filters.dataClass && tool.dataClass !== filters.dataClass) return false;
|
|
5413
|
-
if (filters.maxRisk &&
|
|
6098
|
+
if (filters.maxRisk && riskRank2[tool.risk] > riskRank2[filters.maxRisk]) return false;
|
|
5414
6099
|
return true;
|
|
5415
6100
|
});
|
|
5416
6101
|
const scored = filtered.map((tool) => scoreTool(tool, terms));
|
|
@@ -5444,7 +6129,7 @@ function scoreTool(tool, terms) {
|
|
|
5444
6129
|
}
|
|
5445
6130
|
}
|
|
5446
6131
|
if (tool.risk === "read") score += 0.25;
|
|
5447
|
-
return { tool, score, matched:
|
|
6132
|
+
return { tool, score, matched: unique4(matched) };
|
|
5448
6133
|
}
|
|
5449
6134
|
function tokenize(value) {
|
|
5450
6135
|
return value.toLowerCase().split(/[^a-z0-9]+/g).map((part) => part.trim()).filter(Boolean);
|
|
@@ -5455,110 +6140,10 @@ function encodeToolPart(value) {
|
|
|
5455
6140
|
function decodeToolPart(value) {
|
|
5456
6141
|
return Buffer.from(value.replace(/\./g, "_"), "base64url").toString("utf8");
|
|
5457
6142
|
}
|
|
5458
|
-
function
|
|
6143
|
+
function unique4(values) {
|
|
5459
6144
|
return [...new Set(values)];
|
|
5460
6145
|
}
|
|
5461
6146
|
|
|
5462
|
-
// src/policy.ts
|
|
5463
|
-
import { randomUUID as randomUUID2 } from "crypto";
|
|
5464
|
-
var StaticIntegrationPolicyEngine = class {
|
|
5465
|
-
rules;
|
|
5466
|
-
defaultReadEffect;
|
|
5467
|
-
defaultWriteEffect;
|
|
5468
|
-
defaultDestructiveEffect;
|
|
5469
|
-
now;
|
|
5470
|
-
constructor(options = {}) {
|
|
5471
|
-
this.rules = options.rules ?? [];
|
|
5472
|
-
this.defaultReadEffect = options.defaultReadEffect ?? "allow";
|
|
5473
|
-
this.defaultWriteEffect = options.defaultWriteEffect ?? "require_approval";
|
|
5474
|
-
this.defaultDestructiveEffect = options.defaultDestructiveEffect ?? "deny";
|
|
5475
|
-
this.now = options.now ?? (() => /* @__PURE__ */ new Date());
|
|
5476
|
-
}
|
|
5477
|
-
decide(ctx) {
|
|
5478
|
-
const action = ctx.action;
|
|
5479
|
-
if (!action) return { decision: "deny", reason: "Integration action is missing from connector catalog." };
|
|
5480
|
-
const matched = this.rules.find((rule) => ruleMatches(rule, ctx));
|
|
5481
|
-
const effect = matched?.effect ?? this.defaultEffect(action.risk);
|
|
5482
|
-
const reason = matched?.reason ?? defaultReason(effect, action.risk);
|
|
5483
|
-
if (effect === "allow") return { decision: "allow", reason, metadata: matched ? { ruleId: matched.id } : void 0 };
|
|
5484
|
-
if (effect === "deny") return { decision: "deny", reason, metadata: matched ? { ruleId: matched.id } : void 0 };
|
|
5485
|
-
return {
|
|
5486
|
-
decision: "require_approval",
|
|
5487
|
-
reason,
|
|
5488
|
-
approval: buildApprovalRequest(ctx, reason, this.now()),
|
|
5489
|
-
metadata: matched ? { ruleId: matched.id } : void 0
|
|
5490
|
-
};
|
|
5491
|
-
}
|
|
5492
|
-
defaultEffect(risk) {
|
|
5493
|
-
if (risk === "read") return this.defaultReadEffect;
|
|
5494
|
-
if (risk === "write") return this.defaultWriteEffect;
|
|
5495
|
-
return this.defaultDestructiveEffect;
|
|
5496
|
-
}
|
|
5497
|
-
};
|
|
5498
|
-
function createDefaultIntegrationPolicyEngine(options = {}) {
|
|
5499
|
-
return new StaticIntegrationPolicyEngine(options);
|
|
5500
|
-
}
|
|
5501
|
-
function buildApprovalRequest(ctx, reason, requestedAt) {
|
|
5502
|
-
if (!ctx.action) {
|
|
5503
|
-
throw new Error("Cannot build approval request without an action descriptor.");
|
|
5504
|
-
}
|
|
5505
|
-
return {
|
|
5506
|
-
id: `approval_${randomUUID2()}`,
|
|
5507
|
-
connectionId: ctx.connection.id,
|
|
5508
|
-
providerId: ctx.connection.providerId,
|
|
5509
|
-
connectorId: ctx.connection.connectorId,
|
|
5510
|
-
action: ctx.request.action,
|
|
5511
|
-
actor: { type: ctx.subject.type, id: ctx.subject.id },
|
|
5512
|
-
risk: ctx.action.risk,
|
|
5513
|
-
dataClass: ctx.action.dataClass,
|
|
5514
|
-
reason,
|
|
5515
|
-
requestedAt: requestedAt.toISOString(),
|
|
5516
|
-
inputPreview: previewInput(ctx.request.input)
|
|
5517
|
-
};
|
|
5518
|
-
}
|
|
5519
|
-
function redactApprovalRequest(request) {
|
|
5520
|
-
return {
|
|
5521
|
-
...request,
|
|
5522
|
-
inputPreview: redactUnknown2(request.inputPreview)
|
|
5523
|
-
};
|
|
5524
|
-
}
|
|
5525
|
-
function ruleMatches(rule, ctx) {
|
|
5526
|
-
if (!ctx.action) return false;
|
|
5527
|
-
if (rule.providerId && rule.providerId !== ctx.connection.providerId) return false;
|
|
5528
|
-
if (rule.connectorId && rule.connectorId !== ctx.connection.connectorId) return false;
|
|
5529
|
-
if (rule.action && rule.action !== ctx.request.action) return false;
|
|
5530
|
-
if (rule.risk && rule.risk !== ctx.action.risk) return false;
|
|
5531
|
-
if (rule.maxRisk && riskRank2(ctx.action.risk) > riskRank2(rule.maxRisk)) return false;
|
|
5532
|
-
if (rule.dataClass && rule.dataClass !== ctx.action.dataClass) return false;
|
|
5533
|
-
return true;
|
|
5534
|
-
}
|
|
5535
|
-
function riskRank2(risk) {
|
|
5536
|
-
if (risk === "read") return 0;
|
|
5537
|
-
if (risk === "write") return 1;
|
|
5538
|
-
return 2;
|
|
5539
|
-
}
|
|
5540
|
-
function defaultReason(effect, risk) {
|
|
5541
|
-
if (effect === "allow") return `${risk} integration action allowed by default policy.`;
|
|
5542
|
-
if (effect === "deny") return `${risk} integration action denied by default policy.`;
|
|
5543
|
-
return `${risk} integration action requires approval by default policy.`;
|
|
5544
|
-
}
|
|
5545
|
-
function previewInput(input) {
|
|
5546
|
-
return redactUnknown2(input);
|
|
5547
|
-
}
|
|
5548
|
-
function redactUnknown2(value) {
|
|
5549
|
-
if (Array.isArray(value)) return value.map(redactUnknown2);
|
|
5550
|
-
if (!value || typeof value !== "object") return value;
|
|
5551
|
-
const out = {};
|
|
5552
|
-
for (const [key, child] of Object.entries(value)) {
|
|
5553
|
-
if (/token|secret|password|authorization|api[_-]?key|credential/i.test(key)) {
|
|
5554
|
-
out[key] = "[REDACTED]";
|
|
5555
|
-
} else {
|
|
5556
|
-
out[key] = redactUnknown2(child);
|
|
5557
|
-
}
|
|
5558
|
-
}
|
|
5559
|
-
return out;
|
|
5560
|
-
}
|
|
5561
|
-
|
|
5562
6147
|
// src/sandbox.ts
|
|
5563
6148
|
function buildIntegrationInvocationEnvelope(input) {
|
|
5564
6149
|
const parsed = parseIntegrationToolName(input.toolName);
|
|
@@ -5617,13 +6202,13 @@ function redactInvocationEnvelope(envelope) {
|
|
|
5617
6202
|
return {
|
|
5618
6203
|
...envelope,
|
|
5619
6204
|
capabilityToken: "[REDACTED]",
|
|
5620
|
-
input:
|
|
6205
|
+
input: redactUnknown4(envelope.input)
|
|
5621
6206
|
};
|
|
5622
6207
|
}
|
|
5623
6208
|
function redactCapability(capability) {
|
|
5624
6209
|
return {
|
|
5625
6210
|
...capability,
|
|
5626
|
-
metadata:
|
|
6211
|
+
metadata: redactUnknown4(capability.metadata)
|
|
5627
6212
|
};
|
|
5628
6213
|
}
|
|
5629
6214
|
function normalizeIntegrationResult(result) {
|
|
@@ -5676,15 +6261,15 @@ var IntegrationSandboxHost = class {
|
|
|
5676
6261
|
return dispatchIntegrationInvocation(envelope, this.options);
|
|
5677
6262
|
}
|
|
5678
6263
|
};
|
|
5679
|
-
function
|
|
5680
|
-
if (Array.isArray(value)) return value.map(
|
|
6264
|
+
function redactUnknown4(value) {
|
|
6265
|
+
if (Array.isArray(value)) return value.map(redactUnknown4);
|
|
5681
6266
|
if (!value || typeof value !== "object") return value;
|
|
5682
6267
|
const out = {};
|
|
5683
6268
|
for (const [key, child] of Object.entries(value)) {
|
|
5684
6269
|
if (/token|secret|password|authorization|api[_-]?key|credential/i.test(key)) {
|
|
5685
6270
|
out[key] = "[REDACTED]";
|
|
5686
6271
|
} else {
|
|
5687
|
-
out[key] =
|
|
6272
|
+
out[key] = redactUnknown4(child);
|
|
5688
6273
|
}
|
|
5689
6274
|
}
|
|
5690
6275
|
return out;
|
|
@@ -5750,7 +6335,7 @@ function importMcpConnector(catalog, options) {
|
|
|
5750
6335
|
}));
|
|
5751
6336
|
}
|
|
5752
6337
|
function connectorFromActions(options, actions) {
|
|
5753
|
-
const scopes =
|
|
6338
|
+
const scopes = unique5([
|
|
5754
6339
|
...options.scopes ?? [],
|
|
5755
6340
|
...actions.flatMap((action) => action.requiredScopes)
|
|
5756
6341
|
]);
|
|
@@ -5782,7 +6367,7 @@ function riskFromMcpTool(tool, fallback) {
|
|
|
5782
6367
|
}
|
|
5783
6368
|
function scopesFromOpenApiOperation(operation, fallback) {
|
|
5784
6369
|
const scopes = (operation.security ?? []).flatMap((entry) => Object.values(entry).flat());
|
|
5785
|
-
return
|
|
6370
|
+
return unique5(scopes.length > 0 ? scopes : fallback);
|
|
5786
6371
|
}
|
|
5787
6372
|
function openApiInputSchema(path, method, operation) {
|
|
5788
6373
|
return {
|
|
@@ -5802,7 +6387,7 @@ function titleFromId(id) {
|
|
|
5802
6387
|
function isObject(value) {
|
|
5803
6388
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
5804
6389
|
}
|
|
5805
|
-
function
|
|
6390
|
+
function unique5(values) {
|
|
5806
6391
|
return [...new Set(values)];
|
|
5807
6392
|
}
|
|
5808
6393
|
|
|
@@ -5853,7 +6438,7 @@ function normalizeGatewayCatalog(entries, options) {
|
|
|
5853
6438
|
title,
|
|
5854
6439
|
category: normalizeCategory(entry.category),
|
|
5855
6440
|
auth: normalizeAuth(entry.auth),
|
|
5856
|
-
scopes:
|
|
6441
|
+
scopes: unique6([
|
|
5857
6442
|
...entry.scopes ?? [],
|
|
5858
6443
|
...actions.flatMap((action) => action.requiredScopes)
|
|
5859
6444
|
]),
|
|
@@ -5883,7 +6468,7 @@ function normalizeActions(actions, fallbackScopes) {
|
|
|
5883
6468
|
id,
|
|
5884
6469
|
title: action.title ?? action.name ?? titleFromId2(id),
|
|
5885
6470
|
risk: normalizeRisk(action.risk),
|
|
5886
|
-
requiredScopes:
|
|
6471
|
+
requiredScopes: unique6([
|
|
5887
6472
|
...action.requiredScopes ?? [],
|
|
5888
6473
|
...action.scopes ?? [],
|
|
5889
6474
|
...action.requiredScopes?.length || action.scopes?.length ? [] : fallbackScopes
|
|
@@ -5897,21 +6482,21 @@ function normalizeActions(actions, fallbackScopes) {
|
|
|
5897
6482
|
}).filter((action) => action.id);
|
|
5898
6483
|
}
|
|
5899
6484
|
function normalizeTriggers(triggers, fallbackScopes) {
|
|
5900
|
-
const normalized = triggers.map((
|
|
5901
|
-
const id = slug2(
|
|
6485
|
+
const normalized = triggers.map((trigger2) => {
|
|
6486
|
+
const id = slug2(trigger2.id ?? trigger2.key ?? trigger2.name ?? trigger2.title ?? "");
|
|
5902
6487
|
return {
|
|
5903
6488
|
id,
|
|
5904
|
-
title:
|
|
5905
|
-
requiredScopes:
|
|
5906
|
-
...
|
|
5907
|
-
...
|
|
5908
|
-
...
|
|
6489
|
+
title: trigger2.title ?? trigger2.name ?? titleFromId2(id),
|
|
6490
|
+
requiredScopes: unique6([
|
|
6491
|
+
...trigger2.requiredScopes ?? [],
|
|
6492
|
+
...trigger2.scopes ?? [],
|
|
6493
|
+
...trigger2.requiredScopes?.length || trigger2.scopes?.length ? [] : fallbackScopes
|
|
5909
6494
|
]),
|
|
5910
|
-
dataClass: normalizeDataClass(
|
|
5911
|
-
description:
|
|
5912
|
-
payloadSchema:
|
|
6495
|
+
dataClass: normalizeDataClass(trigger2.dataClass),
|
|
6496
|
+
description: trigger2.description,
|
|
6497
|
+
payloadSchema: trigger2.payloadSchema
|
|
5913
6498
|
};
|
|
5914
|
-
}).filter((
|
|
6499
|
+
}).filter((trigger2) => trigger2.id);
|
|
5915
6500
|
return normalized.length > 0 ? normalized : void 0;
|
|
5916
6501
|
}
|
|
5917
6502
|
function defaultActionsFor(category, scopes) {
|
|
@@ -5991,7 +6576,7 @@ function slug2(value) {
|
|
|
5991
6576
|
function titleFromId2(id) {
|
|
5992
6577
|
return id.split("-").filter(Boolean).map((part) => part.slice(0, 1).toUpperCase() + part.slice(1)).join(" ");
|
|
5993
6578
|
}
|
|
5994
|
-
function
|
|
6579
|
+
function unique6(values) {
|
|
5995
6580
|
return [...new Set(values)];
|
|
5996
6581
|
}
|
|
5997
6582
|
|
|
@@ -6079,7 +6664,7 @@ var IntegrationRuntime = class {
|
|
|
6079
6664
|
const connector = {
|
|
6080
6665
|
...entry.connector,
|
|
6081
6666
|
actions: entry.connector.actions.filter((action) => grant.allowedActions.includes(action.id)),
|
|
6082
|
-
triggers: entry.connector.triggers?.filter((
|
|
6667
|
+
triggers: entry.connector.triggers?.filter((trigger2) => grant.allowedTriggers.includes(trigger2.id)),
|
|
6083
6668
|
scopes: entry.connector.scopes.filter((scope) => grant.scopes.includes(scope))
|
|
6084
6669
|
};
|
|
6085
6670
|
const capability = await this.hub.issueCapability({
|
|
@@ -6173,32 +6758,32 @@ function missing(requirement, status, message, connector, registryEntry2) {
|
|
|
6173
6758
|
}
|
|
6174
6759
|
function requiredActions(requirement, connector) {
|
|
6175
6760
|
if (requirement.mode === "trigger") return [];
|
|
6176
|
-
if (requirement.requiredActions?.length) return
|
|
6761
|
+
if (requirement.requiredActions?.length) return unique7(requirement.requiredActions);
|
|
6177
6762
|
const actions = connector.actions.filter((action) => {
|
|
6178
6763
|
if (requirement.mode === "read") return action.risk === "read";
|
|
6179
6764
|
if (requirement.mode === "write") return action.risk !== "read";
|
|
6180
6765
|
return false;
|
|
6181
6766
|
});
|
|
6182
|
-
return
|
|
6767
|
+
return unique7(actions.map((action) => action.id));
|
|
6183
6768
|
}
|
|
6184
6769
|
function requiredTriggers(requirement, connector) {
|
|
6185
|
-
if (requirement.requiredTriggers?.length) return
|
|
6770
|
+
if (requirement.requiredTriggers?.length) return unique7(requirement.requiredTriggers);
|
|
6186
6771
|
if (requirement.mode !== "trigger") return [];
|
|
6187
|
-
return
|
|
6772
|
+
return unique7((connector.triggers ?? []).map((trigger2) => trigger2.id));
|
|
6188
6773
|
}
|
|
6189
6774
|
function requiredScopes(requirement, connector) {
|
|
6190
|
-
if (requirement.requiredScopes?.length) return
|
|
6775
|
+
if (requirement.requiredScopes?.length) return unique7(requirement.requiredScopes);
|
|
6191
6776
|
const actionIds = new Set(requiredActions(requirement, connector));
|
|
6192
6777
|
const triggerIds = new Set(requiredTriggers(requirement, connector));
|
|
6193
|
-
return
|
|
6778
|
+
return unique7([
|
|
6194
6779
|
...connector.actions.filter((action) => actionIds.has(action.id)).flatMap((action) => action.requiredScopes),
|
|
6195
|
-
...(connector.triggers ?? []).filter((
|
|
6780
|
+
...(connector.triggers ?? []).filter((trigger2) => triggerIds.has(trigger2.id)).flatMap((trigger2) => trigger2.requiredScopes)
|
|
6196
6781
|
]);
|
|
6197
6782
|
}
|
|
6198
6783
|
function sameActor(a, b) {
|
|
6199
6784
|
return a.type === b.type && a.id === b.id;
|
|
6200
6785
|
}
|
|
6201
|
-
function
|
|
6786
|
+
function unique7(values) {
|
|
6202
6787
|
return [...new Set(values)];
|
|
6203
6788
|
}
|
|
6204
6789
|
|
|
@@ -6485,8 +7070,8 @@ var IntegrationHub = class {
|
|
|
6485
7070
|
id: `cap_${randomUUID3()}`,
|
|
6486
7071
|
subject: request.subject,
|
|
6487
7072
|
connectionId: request.connectionId,
|
|
6488
|
-
scopes:
|
|
6489
|
-
allowedActions:
|
|
7073
|
+
scopes: unique8(request.scopes),
|
|
7074
|
+
allowedActions: unique8(request.allowedActions),
|
|
6490
7075
|
issuedAt: now.toISOString(),
|
|
6491
7076
|
expiresAt: new Date(now.getTime() + request.ttlMs).toISOString(),
|
|
6492
7077
|
metadata: request.metadata
|
|
@@ -6539,18 +7124,18 @@ var IntegrationHub = class {
|
|
|
6539
7124
|
}
|
|
6540
7125
|
return proceed();
|
|
6541
7126
|
}
|
|
6542
|
-
async subscribeTrigger(connectionId,
|
|
7127
|
+
async subscribeTrigger(connectionId, trigger2, targetUrl) {
|
|
6543
7128
|
const connection = await this.requireConnection(connectionId);
|
|
6544
7129
|
this.assertConnectionActive(connection);
|
|
6545
7130
|
const provider = this.requireProvider(connection.providerId);
|
|
6546
7131
|
const connector = await this.requireConnector(provider, connection.connectorId);
|
|
6547
|
-
const spec = connector.triggers?.find((candidate) => candidate.id ===
|
|
6548
|
-
if (!spec) throw new IntegrationError(`Trigger ${
|
|
7132
|
+
const spec = connector.triggers?.find((candidate) => candidate.id === trigger2);
|
|
7133
|
+
if (!spec) throw new IntegrationError(`Trigger ${trigger2} is not defined by connector ${connector.id}.`, "action_not_found");
|
|
6549
7134
|
assertScopes(connection, spec.requiredScopes);
|
|
6550
7135
|
if (!provider.subscribeTrigger) {
|
|
6551
7136
|
throw new IntegrationError(`Provider ${provider.id} does not support triggers.`, "auth_not_supported");
|
|
6552
7137
|
}
|
|
6553
|
-
return provider.subscribeTrigger(connection,
|
|
7138
|
+
return provider.subscribeTrigger(connection, trigger2, targetUrl);
|
|
6554
7139
|
}
|
|
6555
7140
|
requireProvider(providerId) {
|
|
6556
7141
|
const provider = this.providers.get(providerId);
|
|
@@ -6635,10 +7220,10 @@ function createMockIntegrationProvider(options = {}) {
|
|
|
6635
7220
|
action: request.action,
|
|
6636
7221
|
output: { echo: request.input ?? null }
|
|
6637
7222
|
},
|
|
6638
|
-
subscribeTrigger: (connection,
|
|
6639
|
-
id: `sub_${connection.id}_${
|
|
7223
|
+
subscribeTrigger: (connection, trigger2, targetUrl) => ({
|
|
7224
|
+
id: `sub_${connection.id}_${trigger2}`,
|
|
6640
7225
|
connectionId: connection.id,
|
|
6641
|
-
trigger,
|
|
7226
|
+
trigger: trigger2,
|
|
6642
7227
|
targetUrl,
|
|
6643
7228
|
status: "active",
|
|
6644
7229
|
createdAt: (/* @__PURE__ */ new Date(0)).toISOString()
|
|
@@ -6666,10 +7251,10 @@ function createHttpIntegrationProvider(options) {
|
|
|
6666
7251
|
request
|
|
6667
7252
|
}, options.bearer);
|
|
6668
7253
|
},
|
|
6669
|
-
async subscribeTrigger(connection,
|
|
7254
|
+
async subscribeTrigger(connection, trigger2, targetUrl) {
|
|
6670
7255
|
return postJson(fetcher, `${baseUrl}/triggers/subscribe`, {
|
|
6671
7256
|
connection,
|
|
6672
|
-
trigger,
|
|
7257
|
+
trigger: trigger2,
|
|
6673
7258
|
targetUrl
|
|
6674
7259
|
}, options.bearer);
|
|
6675
7260
|
},
|
|
@@ -6732,12 +7317,13 @@ function base64UrlEncode(value) {
|
|
|
6732
7317
|
function base64UrlDecode(value) {
|
|
6733
7318
|
return Buffer.from(value, "base64url").toString("utf8");
|
|
6734
7319
|
}
|
|
6735
|
-
function
|
|
7320
|
+
function unique8(values) {
|
|
6736
7321
|
return [...new Set(values)];
|
|
6737
7322
|
}
|
|
6738
7323
|
export {
|
|
6739
7324
|
ACTIVEPIECES_OVERRIDES,
|
|
6740
7325
|
ApprovalBackedPolicyEngine,
|
|
7326
|
+
CANONICAL_INTEGRATION_ACTIONS,
|
|
6741
7327
|
CredentialsExpired,
|
|
6742
7328
|
DEFAULT_INTEGRATION_BRIDGE_ENV,
|
|
6743
7329
|
DEFAULT_SIGNATURE_TOLERANCE_SECONDS,
|
|
@@ -6756,17 +7342,22 @@ export {
|
|
|
6756
7342
|
IntegrationError,
|
|
6757
7343
|
IntegrationHub,
|
|
6758
7344
|
IntegrationRuntime,
|
|
7345
|
+
IntegrationRuntimeError,
|
|
6759
7346
|
IntegrationSandboxHost,
|
|
6760
7347
|
IntegrationWorkflowRuntime,
|
|
7348
|
+
PROVIDER_PASSTHROUGH_ACTION,
|
|
6761
7349
|
ResourceContention,
|
|
6762
7350
|
StaticIntegrationPolicyEngine,
|
|
7351
|
+
TangleIntegrationsClient,
|
|
6763
7352
|
_resetPendingFlowsForTests,
|
|
6764
7353
|
airtableConnector,
|
|
6765
7354
|
asanaConnector,
|
|
6766
7355
|
assertValidConnectorManifest,
|
|
7356
|
+
assertValidIntegrationManifest,
|
|
6767
7357
|
assertValidIntegrationSpec,
|
|
6768
7358
|
buildActivepiecesConnectors,
|
|
6769
7359
|
buildApprovalRequest,
|
|
7360
|
+
buildCanonicalLaunchConnectors,
|
|
6770
7361
|
buildDefaultIntegrationRegistry,
|
|
6771
7362
|
buildHealthcheckPlan,
|
|
6772
7363
|
buildIntegrationBridgeEnvironment,
|
|
@@ -6774,6 +7365,8 @@ export {
|
|
|
6774
7365
|
buildIntegrationCoverageConnectors,
|
|
6775
7366
|
buildIntegrationInvocationEnvelope,
|
|
6776
7367
|
buildIntegrationToolCatalog,
|
|
7368
|
+
calendarExercisePlannerManifest,
|
|
7369
|
+
canonicalActionConnectorId,
|
|
6777
7370
|
canonicalConnectorId,
|
|
6778
7371
|
composeIntegrationRegistry,
|
|
6779
7372
|
consoleStepsToText,
|
|
@@ -6791,16 +7384,19 @@ export {
|
|
|
6791
7384
|
createIntegrationRuntime,
|
|
6792
7385
|
createIntegrationWorkflowRuntime,
|
|
6793
7386
|
createMockIntegrationProvider,
|
|
7387
|
+
createPlatformIntegrationPolicyPreset,
|
|
7388
|
+
createTangleIntegrationsClient,
|
|
6794
7389
|
declarativeRestConnector,
|
|
6795
7390
|
decodeIntegrationBridgePayload,
|
|
6796
7391
|
dispatchIntegrationInvocation,
|
|
6797
7392
|
encodeIntegrationBridgePayload,
|
|
6798
7393
|
exchangeAuthorizationCode,
|
|
7394
|
+
explainMissingRequirements,
|
|
6799
7395
|
firstHeader,
|
|
6800
7396
|
getActivepiecesOverride,
|
|
6801
7397
|
getIntegrationFamily,
|
|
6802
7398
|
getIntegrationSpec,
|
|
6803
|
-
githubConnector,
|
|
7399
|
+
githubConnector2 as githubConnector,
|
|
6804
7400
|
gitlabConnector,
|
|
6805
7401
|
googleCalendar,
|
|
6806
7402
|
googleSheets,
|
|
@@ -6809,6 +7405,7 @@ export {
|
|
|
6809
7405
|
importGraphqlConnector,
|
|
6810
7406
|
importMcpConnector,
|
|
6811
7407
|
importOpenApiConnector,
|
|
7408
|
+
inferIntegrationManifestFromTools,
|
|
6812
7409
|
inferIntegrationSupportTier,
|
|
6813
7410
|
integrationCoverageChecklistMarkdown,
|
|
6814
7411
|
integrationSpecToConnector,
|
|
@@ -6821,6 +7418,7 @@ export {
|
|
|
6821
7418
|
manifestToConnector,
|
|
6822
7419
|
microsoftCalendar,
|
|
6823
7420
|
normalizeGatewayCatalog,
|
|
7421
|
+
normalizeIntegrationError,
|
|
6824
7422
|
normalizeIntegrationResult,
|
|
6825
7423
|
notionDatabase,
|
|
6826
7424
|
parseIntegrationBridgeEnvironment,
|
|
@@ -6833,6 +7431,8 @@ export {
|
|
|
6833
7431
|
redactInvocationEnvelope,
|
|
6834
7432
|
refreshAccessToken,
|
|
6835
7433
|
renderAgentToolDescription,
|
|
7434
|
+
renderApprovalCopy,
|
|
7435
|
+
renderConsentSummary,
|
|
6836
7436
|
renderConsoleSteps,
|
|
6837
7437
|
renderRunbookMarkdown,
|
|
6838
7438
|
resolveConnectionCredentials,
|
|
@@ -6849,6 +7449,7 @@ export {
|
|
|
6849
7449
|
slackEventsConnector,
|
|
6850
7450
|
specAuthToConnectorAuth,
|
|
6851
7451
|
startOAuthFlow,
|
|
7452
|
+
statusForCode,
|
|
6852
7453
|
storedEventToTriggerEvent,
|
|
6853
7454
|
stripePackConnector,
|
|
6854
7455
|
stripeWebhookReceiverConnector,
|
|
@@ -6859,7 +7460,9 @@ export {
|
|
|
6859
7460
|
validateCredentialFormat,
|
|
6860
7461
|
validateCredentialSet,
|
|
6861
7462
|
validateIntegrationInvocationEnvelope,
|
|
7463
|
+
validateIntegrationManifest,
|
|
6862
7464
|
validateIntegrationSpec,
|
|
7465
|
+
validateProviderPassthroughRequest,
|
|
6863
7466
|
verifyCapabilityToken,
|
|
6864
7467
|
verifyHmacSignature,
|
|
6865
7468
|
verifySlackSignature,
|