@tangle-network/agent-integrations 0.25.2 → 0.25.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/README.md +13 -1
  2. package/dist/bin/tangle-catalog-runtime.js +5 -1
  3. package/dist/bin/tangle-catalog-runtime.js.map +1 -1
  4. package/dist/catalog.d.ts +4 -0
  5. package/dist/catalog.js +15 -0
  6. package/dist/catalog.js.map +1 -0
  7. package/dist/chunk-376UBTNB.js +1 -0
  8. package/dist/chunk-376UBTNB.js.map +1 -0
  9. package/dist/chunk-6KWCC42J.js +120 -0
  10. package/dist/chunk-6KWCC42J.js.map +1 -0
  11. package/dist/chunk-FQAT4IEE.js +246 -0
  12. package/dist/chunk-FQAT4IEE.js.map +1 -0
  13. package/dist/chunk-IDX3KIPA.js +3233 -0
  14. package/dist/chunk-IDX3KIPA.js.map +1 -0
  15. package/dist/{chunk-VJ57GPYO.js → chunk-MU3UTIOX.js} +3234 -6787
  16. package/dist/chunk-MU3UTIOX.js.map +1 -0
  17. package/dist/connectors/adapters/index.d.ts +1 -0
  18. package/dist/connectors/adapters/index.js +39 -0
  19. package/dist/connectors/adapters/index.js.map +1 -0
  20. package/dist/connectors/index.d.ts +180 -0
  21. package/dist/connectors/index.js +74 -0
  22. package/dist/connectors/index.js.map +1 -0
  23. package/dist/index-BNb1A0Id.d.ts +810 -0
  24. package/dist/index.d.ts +3 -1
  25. package/dist/index.js +51 -44
  26. package/dist/registry.d.ts +1982 -0
  27. package/dist/registry.js +20 -0
  28. package/dist/registry.js.map +1 -0
  29. package/dist/runtime.d.ts +4 -0
  30. package/dist/runtime.js +12 -0
  31. package/dist/runtime.js.map +1 -0
  32. package/dist/specs.d.ts +4 -2962
  33. package/dist/tangle-catalog-runtime.d.ts +4 -0
  34. package/dist/tangle-catalog-runtime.js +22 -0
  35. package/dist/tangle-catalog-runtime.js.map +1 -0
  36. package/docs/platform-control-plane.md +54 -0
  37. package/docs/production-completion-checklist.md +2 -0
  38. package/package.json +31 -1
  39. package/dist/chunk-VJ57GPYO.js.map +0 -1
package/README.md CHANGED
@@ -238,6 +238,17 @@ const bundle = await runtime.buildSandboxBundle({
238
238
  })
239
239
  ```
240
240
 
241
+ Installed apps and published templates can bind to explicit pre-created grants:
242
+
243
+ ```ts
244
+ const bundle = await runtime.buildSandboxBundle({
245
+ grantIds: ['grant_calendar_read'],
246
+ grantee: { type: 'app', id: installedAppId },
247
+ subject: { type: 'sandbox', id: sandboxId },
248
+ ttlMs: 15 * 60_000,
249
+ })
250
+ ```
251
+
241
252
  Generated apps and sandboxes receive scoped capability tokens and tool
242
253
  definitions. They never receive OAuth refresh tokens, API keys, or raw secrets.
243
254
  For sandbox processes, pass the bundle through `buildIntegrationBridgeEnvironment()`;
@@ -272,7 +283,8 @@ lets the product dispatch normalized events to UI workflows, sync jobs, or
272
283
  agent runs.
273
284
 
274
285
  For a full product checklist, see
275
- [External Product Integration](./docs/external-product-integration.md).
286
+ [External Product Integration](./docs/external-product-integration.md) and
287
+ [Platform Control Plane Adoption](./docs/platform-control-plane.md).
276
288
 
277
289
  ## Product Hub Ownership
278
290
 
@@ -4,8 +4,12 @@ import {
4
4
  buildTangleCatalogRuntimePackageManifest,
5
5
  renderTangleCatalogRuntimePnpmAddCommand,
6
6
  startTangleCatalogRuntimeNodeServer
7
- } from "../chunk-VJ57GPYO.js";
7
+ } from "../chunk-MU3UTIOX.js";
8
+ import "../chunk-FQAT4IEE.js";
9
+ import "../chunk-6KWCC42J.js";
8
10
  import "../chunk-4JQ754PA.js";
11
+ import "../chunk-376UBTNB.js";
12
+ import "../chunk-IDX3KIPA.js";
9
13
 
10
14
  // src/bin/tangle-catalog-runtime.ts
11
15
  var args = new Set(process.argv.slice(2));
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/bin/tangle-catalog-runtime.ts"],"sourcesContent":["#!/usr/bin/env node\nimport {\n buildTangleCatalogRuntimePackageManifest,\n renderTangleCatalogRuntimePnpmAddCommand,\n} from '../tangle-catalog.js'\nimport { auditTangleCatalogRuntimePackages } from '../tangle-catalog-runtime.js'\nimport { startTangleCatalogRuntimeNodeServer } from '../tangle-catalog-runtime-server.js'\n\nconst args = new Set(process.argv.slice(2))\nif (args.has('--print-package-json')) {\n console.log(JSON.stringify(buildTangleCatalogRuntimePackageManifest({\n agentIntegrationsVersion: process.env.TANGLE_AGENT_INTEGRATIONS_VERSION,\n }), null, 2))\n process.exit(0)\n}\n\nif (args.has('--print-pnpm-add')) {\n console.log(renderTangleCatalogRuntimePnpmAddCommand({\n agentIntegrationsVersion: process.env.TANGLE_AGENT_INTEGRATIONS_VERSION,\n }))\n process.exit(0)\n}\n\nif (args.has('--audit-packages')) {\n const connectorIds = process.env.TANGLE_CATALOG_AUDIT_CONNECTORS\n ?.split(',')\n .map((id) => id.trim())\n .filter(Boolean)\n console.log(JSON.stringify(await auditTangleCatalogRuntimePackages({ connectorIds }), null, 2))\n process.exit(0)\n}\n\nconst secret = process.env.TANGLE_CATALOG_RUNTIME_SECRET\nif (!secret || secret.length < 32) {\n console.error('TANGLE_CATALOG_RUNTIME_SECRET must be set to at least 32 characters.')\n process.exit(1)\n}\n\nconst authResolverUrl = process.env.TANGLE_CATALOG_AUTH_RESOLVER_URL\nconst authResolverSecret = process.env.TANGLE_CATALOG_AUTH_RESOLVER_SECRET\nif (Boolean(authResolverUrl) !== Boolean(authResolverSecret)) {\n console.error('TANGLE_CATALOG_AUTH_RESOLVER_URL and TANGLE_CATALOG_AUTH_RESOLVER_SECRET must be set together.')\n process.exit(1)\n}\n\nconst port = Number(process.env.PORT ?? process.env.TANGLE_CATALOG_RUNTIME_PORT ?? 4109)\nif (!Number.isInteger(port) || port < 1 || port > 65_535) {\n console.error('PORT must be an integer between 1 and 65535.')\n process.exit(1)\n}\n\nconst server = await startTangleCatalogRuntimeNodeServer({\n secret,\n host: process.env.HOST ?? process.env.TANGLE_CATALOG_RUNTIME_HOST ?? '0.0.0.0',\n port,\n authResolver: authResolverUrl && authResolverSecret\n ? {\n endpoint: authResolverUrl,\n secret: authResolverSecret,\n }\n : false,\n onLog: (event) => {\n const line = JSON.stringify({\n level: event.level,\n message: event.message,\n ...event.metadata,\n })\n if (event.level === 'error') console.error(line)\n else console.log(line)\n },\n})\n\nconsole.log(JSON.stringify({\n level: 'info',\n message: 'Tangle catalog runtime listening.',\n url: server.url,\n}))\n\nfor (const signal of ['SIGINT', 'SIGTERM'] as const) {\n process.once(signal, async () => {\n await server.close()\n process.exit(0)\n })\n}\n"],"mappings":";;;;;;;;;;AAQA,IAAM,OAAO,IAAI,IAAI,QAAQ,KAAK,MAAM,CAAC,CAAC;AAC1C,IAAI,KAAK,IAAI,sBAAsB,GAAG;AACpC,UAAQ,IAAI,KAAK,UAAU,yCAAyC;AAAA,IAClE,0BAA0B,QAAQ,IAAI;AAAA,EACxC,CAAC,GAAG,MAAM,CAAC,CAAC;AACZ,UAAQ,KAAK,CAAC;AAChB;AAEA,IAAI,KAAK,IAAI,kBAAkB,GAAG;AAChC,UAAQ,IAAI,yCAAyC;AAAA,IACnD,0BAA0B,QAAQ,IAAI;AAAA,EACxC,CAAC,CAAC;AACF,UAAQ,KAAK,CAAC;AAChB;AAEA,IAAI,KAAK,IAAI,kBAAkB,GAAG;AAChC,QAAM,eAAe,QAAQ,IAAI,iCAC7B,MAAM,GAAG,EACV,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC,EACrB,OAAO,OAAO;AACjB,UAAQ,IAAI,KAAK,UAAU,MAAM,kCAAkC,EAAE,aAAa,CAAC,GAAG,MAAM,CAAC,CAAC;AAC9F,UAAQ,KAAK,CAAC;AAChB;AAEA,IAAM,SAAS,QAAQ,IAAI;AAC3B,IAAI,CAAC,UAAU,OAAO,SAAS,IAAI;AACjC,UAAQ,MAAM,sEAAsE;AACpF,UAAQ,KAAK,CAAC;AAChB;AAEA,IAAM,kBAAkB,QAAQ,IAAI;AACpC,IAAM,qBAAqB,QAAQ,IAAI;AACvC,IAAI,QAAQ,eAAe,MAAM,QAAQ,kBAAkB,GAAG;AAC5D,UAAQ,MAAM,gGAAgG;AAC9G,UAAQ,KAAK,CAAC;AAChB;AAEA,IAAM,OAAO,OAAO,QAAQ,IAAI,QAAQ,QAAQ,IAAI,+BAA+B,IAAI;AACvF,IAAI,CAAC,OAAO,UAAU,IAAI,KAAK,OAAO,KAAK,OAAO,OAAQ;AACxD,UAAQ,MAAM,8CAA8C;AAC5D,UAAQ,KAAK,CAAC;AAChB;AAEA,IAAM,SAAS,MAAM,oCAAoC;AAAA,EACvD;AAAA,EACA,MAAM,QAAQ,IAAI,QAAQ,QAAQ,IAAI,+BAA+B;AAAA,EACrE;AAAA,EACA,cAAc,mBAAmB,qBAC7B;AAAA,IACE,UAAU;AAAA,IACV,QAAQ;AAAA,EACV,IACA;AAAA,EACJ,OAAO,CAAC,UAAU;AAChB,UAAM,OAAO,KAAK,UAAU;AAAA,MAC1B,OAAO,MAAM;AAAA,MACb,SAAS,MAAM;AAAA,MACf,GAAG,MAAM;AAAA,IACX,CAAC;AACD,QAAI,MAAM,UAAU,QAAS,SAAQ,MAAM,IAAI;AAAA,QAC1C,SAAQ,IAAI,IAAI;AAAA,EACvB;AACF,CAAC;AAED,QAAQ,IAAI,KAAK,UAAU;AAAA,EACzB,OAAO;AAAA,EACP,SAAS;AAAA,EACT,KAAK,OAAO;AACd,CAAC,CAAC;AAEF,WAAW,UAAU,CAAC,UAAU,SAAS,GAAY;AACnD,UAAQ,KAAK,QAAQ,YAAY;AAC/B,UAAM,OAAO,MAAM;AACnB,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AACH;","names":[]}
1
+ {"version":3,"sources":["../../src/bin/tangle-catalog-runtime.ts"],"sourcesContent":["#!/usr/bin/env node\nimport {\n buildTangleCatalogRuntimePackageManifest,\n renderTangleCatalogRuntimePnpmAddCommand,\n} from '../tangle-catalog.js'\nimport { auditTangleCatalogRuntimePackages } from '../tangle-catalog-runtime.js'\nimport { startTangleCatalogRuntimeNodeServer } from '../tangle-catalog-runtime-server.js'\n\nconst args = new Set(process.argv.slice(2))\nif (args.has('--print-package-json')) {\n console.log(JSON.stringify(buildTangleCatalogRuntimePackageManifest({\n agentIntegrationsVersion: process.env.TANGLE_AGENT_INTEGRATIONS_VERSION,\n }), null, 2))\n process.exit(0)\n}\n\nif (args.has('--print-pnpm-add')) {\n console.log(renderTangleCatalogRuntimePnpmAddCommand({\n agentIntegrationsVersion: process.env.TANGLE_AGENT_INTEGRATIONS_VERSION,\n }))\n process.exit(0)\n}\n\nif (args.has('--audit-packages')) {\n const connectorIds = process.env.TANGLE_CATALOG_AUDIT_CONNECTORS\n ?.split(',')\n .map((id) => id.trim())\n .filter(Boolean)\n console.log(JSON.stringify(await auditTangleCatalogRuntimePackages({ connectorIds }), null, 2))\n process.exit(0)\n}\n\nconst secret = process.env.TANGLE_CATALOG_RUNTIME_SECRET\nif (!secret || secret.length < 32) {\n console.error('TANGLE_CATALOG_RUNTIME_SECRET must be set to at least 32 characters.')\n process.exit(1)\n}\n\nconst authResolverUrl = process.env.TANGLE_CATALOG_AUTH_RESOLVER_URL\nconst authResolverSecret = process.env.TANGLE_CATALOG_AUTH_RESOLVER_SECRET\nif (Boolean(authResolverUrl) !== Boolean(authResolverSecret)) {\n console.error('TANGLE_CATALOG_AUTH_RESOLVER_URL and TANGLE_CATALOG_AUTH_RESOLVER_SECRET must be set together.')\n process.exit(1)\n}\n\nconst port = Number(process.env.PORT ?? process.env.TANGLE_CATALOG_RUNTIME_PORT ?? 4109)\nif (!Number.isInteger(port) || port < 1 || port > 65_535) {\n console.error('PORT must be an integer between 1 and 65535.')\n process.exit(1)\n}\n\nconst server = await startTangleCatalogRuntimeNodeServer({\n secret,\n host: process.env.HOST ?? process.env.TANGLE_CATALOG_RUNTIME_HOST ?? '0.0.0.0',\n port,\n authResolver: authResolverUrl && authResolverSecret\n ? {\n endpoint: authResolverUrl,\n secret: authResolverSecret,\n }\n : false,\n onLog: (event) => {\n const line = JSON.stringify({\n level: event.level,\n message: event.message,\n ...event.metadata,\n })\n if (event.level === 'error') console.error(line)\n else console.log(line)\n },\n})\n\nconsole.log(JSON.stringify({\n level: 'info',\n message: 'Tangle catalog runtime listening.',\n url: server.url,\n}))\n\nfor (const signal of ['SIGINT', 'SIGTERM'] as const) {\n process.once(signal, async () => {\n await server.close()\n process.exit(0)\n })\n}\n"],"mappings":";;;;;;;;;;;;;;AAQA,IAAM,OAAO,IAAI,IAAI,QAAQ,KAAK,MAAM,CAAC,CAAC;AAC1C,IAAI,KAAK,IAAI,sBAAsB,GAAG;AACpC,UAAQ,IAAI,KAAK,UAAU,yCAAyC;AAAA,IAClE,0BAA0B,QAAQ,IAAI;AAAA,EACxC,CAAC,GAAG,MAAM,CAAC,CAAC;AACZ,UAAQ,KAAK,CAAC;AAChB;AAEA,IAAI,KAAK,IAAI,kBAAkB,GAAG;AAChC,UAAQ,IAAI,yCAAyC;AAAA,IACnD,0BAA0B,QAAQ,IAAI;AAAA,EACxC,CAAC,CAAC;AACF,UAAQ,KAAK,CAAC;AAChB;AAEA,IAAI,KAAK,IAAI,kBAAkB,GAAG;AAChC,QAAM,eAAe,QAAQ,IAAI,iCAC7B,MAAM,GAAG,EACV,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC,EACrB,OAAO,OAAO;AACjB,UAAQ,IAAI,KAAK,UAAU,MAAM,kCAAkC,EAAE,aAAa,CAAC,GAAG,MAAM,CAAC,CAAC;AAC9F,UAAQ,KAAK,CAAC;AAChB;AAEA,IAAM,SAAS,QAAQ,IAAI;AAC3B,IAAI,CAAC,UAAU,OAAO,SAAS,IAAI;AACjC,UAAQ,MAAM,sEAAsE;AACpF,UAAQ,KAAK,CAAC;AAChB;AAEA,IAAM,kBAAkB,QAAQ,IAAI;AACpC,IAAM,qBAAqB,QAAQ,IAAI;AACvC,IAAI,QAAQ,eAAe,MAAM,QAAQ,kBAAkB,GAAG;AAC5D,UAAQ,MAAM,gGAAgG;AAC9G,UAAQ,KAAK,CAAC;AAChB;AAEA,IAAM,OAAO,OAAO,QAAQ,IAAI,QAAQ,QAAQ,IAAI,+BAA+B,IAAI;AACvF,IAAI,CAAC,OAAO,UAAU,IAAI,KAAK,OAAO,KAAK,OAAO,OAAQ;AACxD,UAAQ,MAAM,8CAA8C;AAC5D,UAAQ,KAAK,CAAC;AAChB;AAEA,IAAM,SAAS,MAAM,oCAAoC;AAAA,EACvD;AAAA,EACA,MAAM,QAAQ,IAAI,QAAQ,QAAQ,IAAI,+BAA+B;AAAA,EACrE;AAAA,EACA,cAAc,mBAAmB,qBAC7B;AAAA,IACE,UAAU;AAAA,IACV,QAAQ;AAAA,EACV,IACA;AAAA,EACJ,OAAO,CAAC,UAAU;AAChB,UAAM,OAAO,KAAK,UAAU;AAAA,MAC1B,OAAO,MAAM;AAAA,MACb,SAAS,MAAM;AAAA,MACf,GAAG,MAAM;AAAA,IACX,CAAC;AACD,QAAI,MAAM,UAAU,QAAS,SAAQ,MAAM,IAAI;AAAA,QAC1C,SAAQ,IAAI,IAAI;AAAA,EACvB;AACF,CAAC;AAED,QAAQ,IAAI,KAAK,UAAU;AAAA,EACzB,OAAO;AAAA,EACP,SAAS;AAAA,EACT,KAAK,OAAO;AACd,CAAC,CAAC;AAEF,WAAW,UAAU,CAAC,UAAU,SAAS,GAAY;AACnD,UAAQ,KAAK,QAAQ,YAAY;AAC/B,UAAM,OAAO,MAAM;AACnB,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AACH;","names":[]}
@@ -0,0 +1,4 @@
1
+ export { I as IntegrationToolDefinition, a as IntegrationToolSearchFilters, b as IntegrationToolSearchResult, M as McpToolDefinition, c as buildIntegrationToolCatalog, i as integrationToolName, p as parseIntegrationToolName, s as searchIntegrationTools, t as toMcpTools } from './registry.js';
2
+ import './index-BNb1A0Id.js';
3
+ import './connectors/index.js';
4
+ import 'node:http';
@@ -0,0 +1,15 @@
1
+ import {
2
+ buildIntegrationToolCatalog,
3
+ integrationToolName,
4
+ parseIntegrationToolName,
5
+ searchIntegrationTools,
6
+ toMcpTools
7
+ } from "./chunk-6KWCC42J.js";
8
+ export {
9
+ buildIntegrationToolCatalog,
10
+ integrationToolName,
11
+ parseIntegrationToolName,
12
+ searchIntegrationTools,
13
+ toMcpTools
14
+ };
15
+ //# sourceMappingURL=catalog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=chunk-376UBTNB.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,120 @@
1
+ // src/catalog.ts
2
+ var riskRank = {
3
+ read: 0,
4
+ write: 1,
5
+ destructive: 2
6
+ };
7
+ function integrationToolName(providerId, connectorId, actionId) {
8
+ return `int_${encodeToolPart(providerId)}_${encodeToolPart(connectorId)}_${encodeToolPart(actionId)}`;
9
+ }
10
+ function parseIntegrationToolName(name) {
11
+ const parts = name.split("_");
12
+ if (parts.length !== 4 || parts[0] !== "int") {
13
+ throw new Error(`Invalid integration tool name: ${name}`);
14
+ }
15
+ return {
16
+ providerId: decodeToolPart(parts[1]),
17
+ connectorId: decodeToolPart(parts[2]),
18
+ actionId: decodeToolPart(parts[3])
19
+ };
20
+ }
21
+ function buildIntegrationToolCatalog(connectors) {
22
+ const tools = [];
23
+ for (const connector of connectors) {
24
+ for (const action of connector.actions) {
25
+ const tags = unique([
26
+ connector.id,
27
+ connector.providerId,
28
+ connector.title,
29
+ connector.category,
30
+ action.id,
31
+ action.title,
32
+ action.risk,
33
+ action.dataClass,
34
+ ...connector.scopes ?? [],
35
+ ...action.requiredScopes ?? []
36
+ ].flatMap(tokenize));
37
+ tools.push({
38
+ name: integrationToolName(connector.providerId, connector.id, action.id),
39
+ title: `${connector.title}: ${action.title}`,
40
+ description: action.description ?? `${action.risk} action ${action.id} on ${connector.title}`,
41
+ providerId: connector.providerId,
42
+ connectorId: connector.id,
43
+ connectorTitle: connector.title,
44
+ category: connector.category,
45
+ action,
46
+ risk: action.risk,
47
+ dataClass: action.dataClass,
48
+ requiredScopes: action.requiredScopes,
49
+ inputSchema: action.inputSchema,
50
+ outputSchema: action.outputSchema,
51
+ tags
52
+ });
53
+ }
54
+ }
55
+ return tools;
56
+ }
57
+ function searchIntegrationTools(catalog, query, filters = {}) {
58
+ const terms = tokenize(query);
59
+ const filtered = catalog.filter((tool) => {
60
+ if (filters.providerId && tool.providerId !== filters.providerId) return false;
61
+ if (filters.connectorId && tool.connectorId !== filters.connectorId) return false;
62
+ if (filters.category && tool.category !== filters.category) return false;
63
+ if (filters.dataClass && tool.dataClass !== filters.dataClass) return false;
64
+ if (filters.maxRisk && riskRank[tool.risk] > riskRank[filters.maxRisk]) return false;
65
+ return true;
66
+ });
67
+ const scored = filtered.map((tool) => scoreTool(tool, terms));
68
+ return scored.filter((result) => terms.length === 0 || result.score > 0).sort((a, b) => b.score - a.score || a.tool.name.localeCompare(b.tool.name)).slice(0, filters.limit ?? 20);
69
+ }
70
+ function toMcpTools(tools) {
71
+ return tools.map((tool) => ({
72
+ name: tool.name,
73
+ description: `${tool.title}. ${tool.description}`,
74
+ inputSchema: tool.inputSchema ?? {
75
+ type: "object",
76
+ additionalProperties: true,
77
+ properties: {}
78
+ }
79
+ }));
80
+ }
81
+ function scoreTool(tool, terms) {
82
+ if (terms.length === 0) return { tool, score: 1, matched: [] };
83
+ const haystack = new Set(tool.tags);
84
+ const matched = [];
85
+ let score = 0;
86
+ for (const term of terms) {
87
+ if (haystack.has(term)) {
88
+ matched.push(term);
89
+ score += 4;
90
+ continue;
91
+ }
92
+ if (tool.tags.some((tag) => tag.includes(term))) {
93
+ matched.push(term);
94
+ score += 1;
95
+ }
96
+ }
97
+ if (tool.risk === "read") score += 0.25;
98
+ return { tool, score, matched: unique(matched) };
99
+ }
100
+ function tokenize(value) {
101
+ return value.toLowerCase().split(/[^a-z0-9]+/g).map((part) => part.trim()).filter(Boolean);
102
+ }
103
+ function encodeToolPart(value) {
104
+ return Buffer.from(value, "utf8").toString("base64url").replace(/_/g, ".");
105
+ }
106
+ function decodeToolPart(value) {
107
+ return Buffer.from(value.replace(/\./g, "_"), "base64url").toString("utf8");
108
+ }
109
+ function unique(values) {
110
+ return [...new Set(values)];
111
+ }
112
+
113
+ export {
114
+ integrationToolName,
115
+ parseIntegrationToolName,
116
+ buildIntegrationToolCatalog,
117
+ searchIntegrationTools,
118
+ toMcpTools
119
+ };
120
+ //# sourceMappingURL=chunk-6KWCC42J.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/catalog.ts"],"sourcesContent":["import type {\n IntegrationConnector,\n IntegrationConnectorAction,\n IntegrationConnectorCategory,\n IntegrationActionRisk,\n IntegrationDataClass,\n} from './index.js'\n\nexport interface IntegrationToolDefinition {\n name: string\n title: string\n description: string\n providerId: string\n connectorId: string\n connectorTitle: string\n category: IntegrationConnectorCategory\n action: IntegrationConnectorAction\n risk: IntegrationActionRisk\n dataClass: IntegrationDataClass\n requiredScopes: string[]\n inputSchema?: unknown\n outputSchema?: unknown\n tags: string[]\n}\n\nexport interface IntegrationToolSearchFilters {\n providerId?: string\n connectorId?: string\n category?: IntegrationConnectorCategory\n maxRisk?: IntegrationActionRisk\n dataClass?: IntegrationDataClass\n limit?: number\n}\n\nexport interface IntegrationToolSearchResult {\n tool: IntegrationToolDefinition\n score: number\n matched: string[]\n}\n\nexport interface McpToolDefinition {\n name: string\n description: string\n inputSchema: unknown\n}\n\nconst riskRank: Record<IntegrationActionRisk, number> = {\n read: 0,\n write: 1,\n destructive: 2,\n}\n\nexport function integrationToolName(providerId: string, connectorId: string, actionId: string): string {\n return `int_${encodeToolPart(providerId)}_${encodeToolPart(connectorId)}_${encodeToolPart(actionId)}`\n}\n\nexport function parseIntegrationToolName(name: string): { providerId: string; connectorId: string; actionId: string } {\n const parts = name.split('_')\n if (parts.length !== 4 || parts[0] !== 'int') {\n throw new Error(`Invalid integration tool name: ${name}`)\n }\n return {\n providerId: decodeToolPart(parts[1]),\n connectorId: decodeToolPart(parts[2]),\n actionId: decodeToolPart(parts[3]),\n }\n}\n\nexport function buildIntegrationToolCatalog(connectors: IntegrationConnector[]): IntegrationToolDefinition[] {\n const tools: IntegrationToolDefinition[] = []\n for (const connector of connectors) {\n for (const action of connector.actions) {\n const tags = unique([\n connector.id,\n connector.providerId,\n connector.title,\n connector.category,\n action.id,\n action.title,\n action.risk,\n action.dataClass,\n ...(connector.scopes ?? []),\n ...(action.requiredScopes ?? []),\n ].flatMap(tokenize))\n tools.push({\n name: integrationToolName(connector.providerId, connector.id, action.id),\n title: `${connector.title}: ${action.title}`,\n description: action.description ?? `${action.risk} action ${action.id} on ${connector.title}`,\n providerId: connector.providerId,\n connectorId: connector.id,\n connectorTitle: connector.title,\n category: connector.category,\n action,\n risk: action.risk,\n dataClass: action.dataClass,\n requiredScopes: action.requiredScopes,\n inputSchema: action.inputSchema,\n outputSchema: action.outputSchema,\n tags,\n })\n }\n }\n return tools\n}\n\nexport function searchIntegrationTools(\n catalog: IntegrationToolDefinition[],\n query: string,\n filters: IntegrationToolSearchFilters = {},\n): IntegrationToolSearchResult[] {\n const terms = tokenize(query)\n const filtered = catalog.filter((tool) => {\n if (filters.providerId && tool.providerId !== filters.providerId) return false\n if (filters.connectorId && tool.connectorId !== filters.connectorId) return false\n if (filters.category && tool.category !== filters.category) return false\n if (filters.dataClass && tool.dataClass !== filters.dataClass) return false\n if (filters.maxRisk && riskRank[tool.risk] > riskRank[filters.maxRisk]) return false\n return true\n })\n const scored = filtered.map((tool) => scoreTool(tool, terms))\n return scored\n .filter((result) => terms.length === 0 || result.score > 0)\n .sort((a, b) => b.score - a.score || a.tool.name.localeCompare(b.tool.name))\n .slice(0, filters.limit ?? 20)\n}\n\nexport function toMcpTools(tools: IntegrationToolDefinition[]): McpToolDefinition[] {\n return tools.map((tool) => ({\n name: tool.name,\n description: `${tool.title}. ${tool.description}`,\n inputSchema: tool.inputSchema ?? {\n type: 'object',\n additionalProperties: true,\n properties: {},\n },\n }))\n}\n\nfunction scoreTool(tool: IntegrationToolDefinition, terms: string[]): IntegrationToolSearchResult {\n if (terms.length === 0) return { tool, score: 1, matched: [] }\n const haystack = new Set(tool.tags)\n const matched: string[] = []\n let score = 0\n for (const term of terms) {\n if (haystack.has(term)) {\n matched.push(term)\n score += 4\n continue\n }\n if (tool.tags.some((tag) => tag.includes(term))) {\n matched.push(term)\n score += 1\n }\n }\n if (tool.risk === 'read') score += 0.25\n return { tool, score, matched: unique(matched) }\n}\n\nfunction tokenize(value: string): string[] {\n return value\n .toLowerCase()\n .split(/[^a-z0-9]+/g)\n .map((part) => part.trim())\n .filter(Boolean)\n}\n\nfunction encodeToolPart(value: string): string {\n return Buffer.from(value, 'utf8').toString('base64url').replace(/_/g, '.')\n}\n\nfunction decodeToolPart(value: string): string {\n return Buffer.from(value.replace(/\\./g, '_'), 'base64url').toString('utf8')\n}\n\nfunction unique<T>(values: T[]): T[] {\n return [...new Set(values)]\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,246 @@
1
+ import {
2
+ buildIntegrationToolCatalog
3
+ } from "./chunk-6KWCC42J.js";
4
+
5
+ // src/runtime.ts
6
+ var InMemoryIntegrationGrantStore = class {
7
+ grants = /* @__PURE__ */ new Map();
8
+ get(grantId) {
9
+ return this.grants.get(grantId);
10
+ }
11
+ put(grant) {
12
+ this.grants.set(grant.id, grant);
13
+ }
14
+ listByManifest(manifestId, grantee) {
15
+ return [...this.grants.values()].filter(
16
+ (grant) => grant.manifestId === manifestId && (!grantee || sameActor(grant.grantee, grantee))
17
+ );
18
+ }
19
+ listByGrantee(grantee) {
20
+ return [...this.grants.values()].filter((grant) => sameActor(grant.grantee, grantee));
21
+ }
22
+ listByIds(grantIds) {
23
+ const wanted = new Set(grantIds);
24
+ return [...this.grants.values()].filter((grant) => wanted.has(grant.id));
25
+ }
26
+ delete(grantId) {
27
+ this.grants.delete(grantId);
28
+ }
29
+ };
30
+ var IntegrationRuntime = class {
31
+ hub;
32
+ grants;
33
+ now;
34
+ constructor(options) {
35
+ this.hub = options.hub;
36
+ this.grants = options.grants ?? new InMemoryIntegrationGrantStore();
37
+ this.now = options.now ?? (() => /* @__PURE__ */ new Date());
38
+ }
39
+ async registry() {
40
+ return this.hub.listRegistry();
41
+ }
42
+ async resolveManifest(manifest, owner) {
43
+ const registry = await this.registry();
44
+ const connections = await this.hub.listConnections(owner);
45
+ const resolutions = manifest.requirements.map(
46
+ (requirement) => resolveRequirement(requirement, owner, registry, connections)
47
+ );
48
+ return {
49
+ manifest,
50
+ owner,
51
+ ready: resolutions.filter((resolution) => resolution.status === "ready"),
52
+ missing: resolutions.filter((resolution) => resolution.status !== "ready" && !resolution.requirement.optional),
53
+ optionalMissing: resolutions.filter((resolution) => resolution.status !== "ready" && resolution.requirement.optional === true)
54
+ };
55
+ }
56
+ async createGrants(input) {
57
+ const resolution = await this.resolveManifest(input.manifest, input.owner);
58
+ if (resolution.missing.length > 0) {
59
+ throw new Error(`Cannot create integration grants; missing requirements: ${resolution.missing.map((r) => r.requirement.id).join(", ")}`);
60
+ }
61
+ const now = this.now().toISOString();
62
+ const grants = resolution.ready.map((ready) => ({
63
+ id: `grant_${input.manifest.id}_${ready.requirement.id}_${ready.connection.id}`,
64
+ manifestId: input.manifest.id,
65
+ requirementId: ready.requirement.id,
66
+ owner: input.owner,
67
+ grantee: input.grantee,
68
+ connectionId: ready.connection.id,
69
+ connectorId: ready.connector.id,
70
+ scopes: requiredScopes(ready.requirement, ready.connector),
71
+ allowedActions: requiredActions(ready.requirement, ready.connector),
72
+ allowedTriggers: requiredTriggers(ready.requirement, ready.connector),
73
+ status: "active",
74
+ createdAt: now,
75
+ updatedAt: now,
76
+ metadata: input.metadata
77
+ }));
78
+ for (const grant of grants) await this.grants.put(grant);
79
+ return grants;
80
+ }
81
+ async buildSandboxBundle(input) {
82
+ const grants = await this.resolveBundleGrants(input);
83
+ const registry = await this.registry();
84
+ const bindings = [];
85
+ const connectors = [];
86
+ let expiresAt = "";
87
+ for (const grant of grants) {
88
+ const entry = registry.byId.get(grant.connectorId);
89
+ if (!entry) continue;
90
+ const connector = {
91
+ ...entry.connector,
92
+ actions: entry.connector.actions.filter((action) => grant.allowedActions.includes(action.id)),
93
+ triggers: entry.connector.triggers?.filter((trigger) => grant.allowedTriggers.includes(trigger.id)),
94
+ scopes: entry.connector.scopes.filter((scope) => grant.scopes.includes(scope))
95
+ };
96
+ const capability = await this.hub.issueCapability({
97
+ subject: input.subject,
98
+ connectionId: grant.connectionId,
99
+ scopes: grant.scopes,
100
+ allowedActions: grant.allowedActions,
101
+ ttlMs: input.ttlMs,
102
+ metadata: {
103
+ manifestId: grant.manifestId,
104
+ grantId: grant.id,
105
+ requirementId: grant.requirementId
106
+ }
107
+ });
108
+ bindings.push({
109
+ requirementId: grant.requirementId,
110
+ connectorId: grant.connectorId,
111
+ connectionId: grant.connectionId,
112
+ grantId: grant.id,
113
+ scopes: grant.scopes,
114
+ allowedActions: grant.allowedActions,
115
+ allowedTriggers: grant.allowedTriggers,
116
+ capability
117
+ });
118
+ connectors.push(connector);
119
+ expiresAt = capability.capability.expiresAt;
120
+ }
121
+ return {
122
+ manifestId: input.manifestId ?? grants[0]?.manifestId ?? "explicit-grants",
123
+ subject: input.subject,
124
+ capabilities: bindings,
125
+ connectors,
126
+ tools: buildIntegrationToolCatalog(connectors),
127
+ expiresAt
128
+ };
129
+ }
130
+ async resolveBundleGrants(input) {
131
+ if (input.grantIds?.length) {
132
+ const uniqueGrantIds = unique(input.grantIds);
133
+ const grants = this.grants.listByIds ? await this.grants.listByIds(uniqueGrantIds) : await Promise.all(uniqueGrantIds.map((grantId) => this.grants.get(grantId)));
134
+ const found = grants.filter((grant) => Boolean(grant));
135
+ const foundIds = new Set(found.map((grant) => grant.id));
136
+ const missing2 = uniqueGrantIds.filter((grantId) => !foundIds.has(grantId));
137
+ if (missing2.length > 0) {
138
+ throw new Error(`Cannot build integration bundle; unknown grant id(s): ${missing2.join(", ")}`);
139
+ }
140
+ const badGrantee = input.grantee ? found.find((grant) => !sameActor(grant.grantee, input.grantee)) : void 0;
141
+ if (badGrantee) {
142
+ throw new Error(`Cannot build integration bundle; grant ${badGrantee.id} belongs to a different grantee.`);
143
+ }
144
+ const badManifest = input.manifestId ? found.find((grant) => grant.manifestId !== input.manifestId) : void 0;
145
+ if (badManifest) {
146
+ throw new Error(`Cannot build integration bundle; grant ${badManifest.id} is not for manifest ${input.manifestId}.`);
147
+ }
148
+ return found.filter((grant) => grant.status === "active");
149
+ }
150
+ if (!input.manifestId) {
151
+ throw new Error("Cannot build integration bundle; manifestId or grantIds is required.");
152
+ }
153
+ return (await this.grants.listByManifest(input.manifestId, input.grantee)).filter((grant) => grant.status === "active");
154
+ }
155
+ };
156
+ function createIntegrationRuntime(options) {
157
+ return new IntegrationRuntime(options);
158
+ }
159
+ function resolveRequirement(requirement, owner, registry, connections) {
160
+ const entry = registry.byId.get(requirement.connectorId);
161
+ if (!entry) {
162
+ return missing(requirement, "unknown_connector", `Unknown connector ${requirement.connectorId}.`);
163
+ }
164
+ const connector = entry.connector;
165
+ if (connector.actions.length === 0 && (connector.triggers?.length ?? 0) === 0) {
166
+ return missing(requirement, "not_executable", `${connector.title} is catalog-only and cannot be invoked yet.`, connector, entry);
167
+ }
168
+ const scopes = requiredScopes(requirement, connector);
169
+ const actions = requiredActions(requirement, connector);
170
+ const triggers = requiredTriggers(requirement, connector);
171
+ const connection = connections.find(
172
+ (candidate) => sameActor(candidate.owner, owner) && candidate.status === "active" && (candidate.connectorId === connector.id || entry.aliases.includes(candidate.connectorId)) && scopes.every((scope) => candidate.grantedScopes.includes(scope))
173
+ );
174
+ if (!connection) {
175
+ return {
176
+ requirement,
177
+ status: "missing_connection",
178
+ connector,
179
+ registryEntry: entry,
180
+ missingScopes: scopes,
181
+ missingActions: actions,
182
+ missingTriggers: triggers,
183
+ message: `${connector.title} needs an active user connection with the required scopes.`
184
+ };
185
+ }
186
+ return {
187
+ requirement,
188
+ status: "ready",
189
+ connector,
190
+ registryEntry: entry,
191
+ connection,
192
+ missingScopes: [],
193
+ missingActions: [],
194
+ missingTriggers: [],
195
+ message: `${connector.title} is ready.`
196
+ };
197
+ }
198
+ function missing(requirement, status, message, connector, registryEntry) {
199
+ return {
200
+ requirement,
201
+ status,
202
+ connector,
203
+ registryEntry,
204
+ missingScopes: [],
205
+ missingActions: [],
206
+ missingTriggers: [],
207
+ message
208
+ };
209
+ }
210
+ function requiredActions(requirement, connector) {
211
+ if (requirement.mode === "trigger") return [];
212
+ if (requirement.requiredActions?.length) return unique(requirement.requiredActions);
213
+ const actions = connector.actions.filter((action) => {
214
+ if (requirement.mode === "read") return action.risk === "read";
215
+ if (requirement.mode === "write") return action.risk !== "read";
216
+ return false;
217
+ });
218
+ return unique(actions.map((action) => action.id));
219
+ }
220
+ function requiredTriggers(requirement, connector) {
221
+ if (requirement.requiredTriggers?.length) return unique(requirement.requiredTriggers);
222
+ if (requirement.mode !== "trigger") return [];
223
+ return unique((connector.triggers ?? []).map((trigger) => trigger.id));
224
+ }
225
+ function requiredScopes(requirement, connector) {
226
+ if (requirement.requiredScopes?.length) return unique(requirement.requiredScopes);
227
+ const actionIds = new Set(requiredActions(requirement, connector));
228
+ const triggerIds = new Set(requiredTriggers(requirement, connector));
229
+ return unique([
230
+ ...connector.actions.filter((action) => actionIds.has(action.id)).flatMap((action) => action.requiredScopes),
231
+ ...(connector.triggers ?? []).filter((trigger) => triggerIds.has(trigger.id)).flatMap((trigger) => trigger.requiredScopes)
232
+ ]);
233
+ }
234
+ function sameActor(a, b) {
235
+ return a.type === b.type && a.id === b.id;
236
+ }
237
+ function unique(values) {
238
+ return [...new Set(values)];
239
+ }
240
+
241
+ export {
242
+ InMemoryIntegrationGrantStore,
243
+ IntegrationRuntime,
244
+ createIntegrationRuntime
245
+ };
246
+ //# sourceMappingURL=chunk-FQAT4IEE.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/runtime.ts"],"sourcesContent":["import {\n buildIntegrationToolCatalog,\n type IntegrationToolDefinition,\n} from './catalog.js'\nimport type {\n IntegrationActor,\n IntegrationConnection,\n IntegrationConnector,\n IssuedIntegrationCapability,\n} from './index.js'\nimport type {\n IntegrationRegistry,\n IntegrationRegistryEntry,\n} from './registry.js'\n\nexport type IntegrationRequirementMode = 'read' | 'write' | 'trigger'\nexport type IntegrationRequirementStatus = 'ready' | 'missing_connection' | 'not_executable' | 'unknown_connector'\n\nexport interface IntegrationRequirement {\n id: string\n connectorId: string\n reason: string\n mode: IntegrationRequirementMode\n requiredActions?: string[]\n requiredTriggers?: string[]\n requiredScopes?: string[]\n optional?: boolean\n}\n\nexport interface IntegrationManifest {\n id: string\n title?: string\n owner?: IntegrationActor\n requirements: IntegrationRequirement[]\n metadata?: Record<string, unknown>\n}\n\nexport interface IntegrationRequirementResolution {\n requirement: IntegrationRequirement\n status: IntegrationRequirementStatus\n connector?: IntegrationConnector\n registryEntry?: IntegrationRegistryEntry\n connection?: IntegrationConnection\n missingScopes: string[]\n missingActions: string[]\n missingTriggers: string[]\n message: string\n}\n\nexport interface IntegrationManifestResolution {\n manifest: IntegrationManifest\n owner: IntegrationActor\n ready: IntegrationRequirementResolution[]\n missing: IntegrationRequirementResolution[]\n optionalMissing: IntegrationRequirementResolution[]\n}\n\nexport interface IntegrationGrant {\n id: string\n manifestId: string\n requirementId: string\n owner: IntegrationActor\n grantee: IntegrationActor\n connectionId: string\n connectorId: string\n scopes: string[]\n allowedActions: string[]\n allowedTriggers: string[]\n status: 'active' | 'revoked'\n createdAt: string\n updatedAt: string\n metadata?: Record<string, unknown>\n}\n\nexport interface IntegrationGrantStore {\n get(grantId: string): Promise<IntegrationGrant | undefined> | IntegrationGrant | undefined\n put(grant: IntegrationGrant): Promise<void> | void\n listByManifest(manifestId: string, grantee?: IntegrationActor): Promise<IntegrationGrant[]> | IntegrationGrant[]\n listByGrantee(grantee: IntegrationActor): Promise<IntegrationGrant[]> | IntegrationGrant[]\n listByIds?(grantIds: string[]): Promise<IntegrationGrant[]> | IntegrationGrant[]\n delete?(grantId: string): Promise<void> | void\n}\n\nexport interface IntegrationCapabilityBinding {\n requirementId: string\n connectorId: string\n connectionId: string\n grantId: string\n scopes: string[]\n allowedActions: string[]\n allowedTriggers: string[]\n capability: IssuedIntegrationCapability\n}\n\nexport interface IntegrationSandboxBundle {\n manifestId: string\n subject: IntegrationActor\n capabilities: IntegrationCapabilityBinding[]\n connectors: IntegrationConnector[]\n tools: IntegrationToolDefinition[]\n expiresAt: string\n}\n\nexport interface IntegrationRuntimeHub {\n listRegistry(): Promise<IntegrationRegistry> | IntegrationRegistry\n listConnections(owner: IntegrationActor): Promise<IntegrationConnection[]> | IntegrationConnection[]\n issueCapability(input: {\n subject: IntegrationActor\n connectionId: string\n scopes: string[]\n allowedActions: string[]\n ttlMs: number\n metadata?: Record<string, unknown>\n }): Promise<IssuedIntegrationCapability> | IssuedIntegrationCapability\n}\n\nexport interface IntegrationRuntimeOptions {\n hub: IntegrationRuntimeHub\n grants?: IntegrationGrantStore\n now?: () => Date\n}\n\nexport class InMemoryIntegrationGrantStore implements IntegrationGrantStore {\n private readonly grants = new Map<string, IntegrationGrant>()\n\n get(grantId: string): IntegrationGrant | undefined {\n return this.grants.get(grantId)\n }\n\n put(grant: IntegrationGrant): void {\n this.grants.set(grant.id, grant)\n }\n\n listByManifest(manifestId: string, grantee?: IntegrationActor): IntegrationGrant[] {\n return [...this.grants.values()].filter((grant) =>\n grant.manifestId === manifestId && (!grantee || sameActor(grant.grantee, grantee))\n )\n }\n\n listByGrantee(grantee: IntegrationActor): IntegrationGrant[] {\n return [...this.grants.values()].filter((grant) => sameActor(grant.grantee, grantee))\n }\n\n listByIds(grantIds: string[]): IntegrationGrant[] {\n const wanted = new Set(grantIds)\n return [...this.grants.values()].filter((grant) => wanted.has(grant.id))\n }\n\n delete(grantId: string): void {\n this.grants.delete(grantId)\n }\n}\n\nexport class IntegrationRuntime {\n private readonly hub: IntegrationRuntimeHub\n private readonly grants: IntegrationGrantStore\n private readonly now: () => Date\n\n constructor(options: IntegrationRuntimeOptions) {\n this.hub = options.hub\n this.grants = options.grants ?? new InMemoryIntegrationGrantStore()\n this.now = options.now ?? (() => new Date())\n }\n\n async registry(): Promise<IntegrationRegistry> {\n return this.hub.listRegistry()\n }\n\n async resolveManifest(manifest: IntegrationManifest, owner: IntegrationActor): Promise<IntegrationManifestResolution> {\n const registry = await this.registry()\n const connections = await this.hub.listConnections(owner)\n const resolutions = manifest.requirements.map((requirement) =>\n resolveRequirement(requirement, owner, registry, connections),\n )\n return {\n manifest,\n owner,\n ready: resolutions.filter((resolution) => resolution.status === 'ready'),\n missing: resolutions.filter((resolution) => resolution.status !== 'ready' && !resolution.requirement.optional),\n optionalMissing: resolutions.filter((resolution) => resolution.status !== 'ready' && resolution.requirement.optional === true),\n }\n }\n\n async createGrants(input: {\n manifest: IntegrationManifest\n owner: IntegrationActor\n grantee: IntegrationActor\n metadata?: Record<string, unknown>\n }): Promise<IntegrationGrant[]> {\n const resolution = await this.resolveManifest(input.manifest, input.owner)\n if (resolution.missing.length > 0) {\n throw new Error(`Cannot create integration grants; missing requirements: ${resolution.missing.map((r) => r.requirement.id).join(', ')}`)\n }\n const now = this.now().toISOString()\n const grants = resolution.ready.map((ready): IntegrationGrant => ({\n id: `grant_${input.manifest.id}_${ready.requirement.id}_${ready.connection!.id}`,\n manifestId: input.manifest.id,\n requirementId: ready.requirement.id,\n owner: input.owner,\n grantee: input.grantee,\n connectionId: ready.connection!.id,\n connectorId: ready.connector!.id,\n scopes: requiredScopes(ready.requirement, ready.connector!),\n allowedActions: requiredActions(ready.requirement, ready.connector!),\n allowedTriggers: requiredTriggers(ready.requirement, ready.connector!),\n status: 'active',\n createdAt: now,\n updatedAt: now,\n metadata: input.metadata,\n }))\n for (const grant of grants) await this.grants.put(grant)\n return grants\n }\n\n async buildSandboxBundle(input: {\n manifestId?: string\n grantIds?: string[]\n subject: IntegrationActor\n ttlMs: number\n grantee?: IntegrationActor\n }): Promise<IntegrationSandboxBundle> {\n const grants = await this.resolveBundleGrants(input)\n const registry = await this.registry()\n const bindings: IntegrationCapabilityBinding[] = []\n const connectors: IntegrationConnector[] = []\n let expiresAt = ''\n\n for (const grant of grants) {\n const entry = registry.byId.get(grant.connectorId)\n if (!entry) continue\n const connector = {\n ...entry.connector,\n actions: entry.connector.actions.filter((action) => grant.allowedActions.includes(action.id)),\n triggers: entry.connector.triggers?.filter((trigger) => grant.allowedTriggers.includes(trigger.id)),\n scopes: entry.connector.scopes.filter((scope) => grant.scopes.includes(scope)),\n }\n const capability = await this.hub.issueCapability({\n subject: input.subject,\n connectionId: grant.connectionId,\n scopes: grant.scopes,\n allowedActions: grant.allowedActions,\n ttlMs: input.ttlMs,\n metadata: {\n manifestId: grant.manifestId,\n grantId: grant.id,\n requirementId: grant.requirementId,\n },\n })\n bindings.push({\n requirementId: grant.requirementId,\n connectorId: grant.connectorId,\n connectionId: grant.connectionId,\n grantId: grant.id,\n scopes: grant.scopes,\n allowedActions: grant.allowedActions,\n allowedTriggers: grant.allowedTriggers,\n capability,\n })\n connectors.push(connector)\n expiresAt = capability.capability.expiresAt\n }\n\n return {\n manifestId: input.manifestId ?? grants[0]?.manifestId ?? 'explicit-grants',\n subject: input.subject,\n capabilities: bindings,\n connectors,\n tools: buildIntegrationToolCatalog(connectors),\n expiresAt,\n }\n }\n\n private async resolveBundleGrants(input: {\n manifestId?: string\n grantIds?: string[]\n grantee?: IntegrationActor\n }): Promise<IntegrationGrant[]> {\n if (input.grantIds?.length) {\n const uniqueGrantIds = unique(input.grantIds)\n const grants = this.grants.listByIds\n ? await this.grants.listByIds(uniqueGrantIds)\n : await Promise.all(uniqueGrantIds.map((grantId) => this.grants.get(grantId)))\n const found = grants.filter((grant): grant is IntegrationGrant => Boolean(grant))\n const foundIds = new Set(found.map((grant) => grant.id))\n const missing = uniqueGrantIds.filter((grantId) => !foundIds.has(grantId))\n if (missing.length > 0) {\n throw new Error(`Cannot build integration bundle; unknown grant id(s): ${missing.join(', ')}`)\n }\n const badGrantee = input.grantee\n ? found.find((grant) => !sameActor(grant.grantee, input.grantee!))\n : undefined\n if (badGrantee) {\n throw new Error(`Cannot build integration bundle; grant ${badGrantee.id} belongs to a different grantee.`)\n }\n const badManifest = input.manifestId\n ? found.find((grant) => grant.manifestId !== input.manifestId)\n : undefined\n if (badManifest) {\n throw new Error(`Cannot build integration bundle; grant ${badManifest.id} is not for manifest ${input.manifestId}.`)\n }\n return found.filter((grant) => grant.status === 'active')\n }\n if (!input.manifestId) {\n throw new Error('Cannot build integration bundle; manifestId or grantIds is required.')\n }\n return (await this.grants.listByManifest(input.manifestId, input.grantee))\n .filter((grant) => grant.status === 'active')\n }\n}\n\nexport function createIntegrationRuntime(options: IntegrationRuntimeOptions): IntegrationRuntime {\n return new IntegrationRuntime(options)\n}\n\nfunction resolveRequirement(\n requirement: IntegrationRequirement,\n owner: IntegrationActor,\n registry: IntegrationRegistry,\n connections: IntegrationConnection[],\n): IntegrationRequirementResolution {\n const entry = registry.byId.get(requirement.connectorId)\n if (!entry) {\n return missing(requirement, 'unknown_connector', `Unknown connector ${requirement.connectorId}.`)\n }\n const connector = entry.connector\n if (connector.actions.length === 0 && (connector.triggers?.length ?? 0) === 0) {\n return missing(requirement, 'not_executable', `${connector.title} is catalog-only and cannot be invoked yet.`, connector, entry)\n }\n const scopes = requiredScopes(requirement, connector)\n const actions = requiredActions(requirement, connector)\n const triggers = requiredTriggers(requirement, connector)\n const connection = connections.find((candidate) =>\n sameActor(candidate.owner, owner)\n && candidate.status === 'active'\n && (candidate.connectorId === connector.id || entry.aliases.includes(candidate.connectorId))\n && scopes.every((scope) => candidate.grantedScopes.includes(scope))\n )\n if (!connection) {\n return {\n requirement,\n status: 'missing_connection',\n connector,\n registryEntry: entry,\n missingScopes: scopes,\n missingActions: actions,\n missingTriggers: triggers,\n message: `${connector.title} needs an active user connection with the required scopes.`,\n }\n }\n return {\n requirement,\n status: 'ready',\n connector,\n registryEntry: entry,\n connection,\n missingScopes: [],\n missingActions: [],\n missingTriggers: [],\n message: `${connector.title} is ready.`,\n }\n}\n\nfunction missing(\n requirement: IntegrationRequirement,\n status: Exclude<IntegrationRequirementStatus, 'ready' | 'missing_connection'>,\n message: string,\n connector?: IntegrationConnector,\n registryEntry?: IntegrationRegistryEntry,\n): IntegrationRequirementResolution {\n return {\n requirement,\n status,\n connector,\n registryEntry,\n missingScopes: [],\n missingActions: [],\n missingTriggers: [],\n message,\n }\n}\n\nfunction requiredActions(requirement: IntegrationRequirement, connector: IntegrationConnector): string[] {\n if (requirement.mode === 'trigger') return []\n if (requirement.requiredActions?.length) return unique(requirement.requiredActions)\n const actions = connector.actions.filter((action) => {\n if (requirement.mode === 'read') return action.risk === 'read'\n if (requirement.mode === 'write') return action.risk !== 'read'\n return false\n })\n return unique(actions.map((action) => action.id))\n}\n\nfunction requiredTriggers(requirement: IntegrationRequirement, connector: IntegrationConnector): string[] {\n if (requirement.requiredTriggers?.length) return unique(requirement.requiredTriggers)\n if (requirement.mode !== 'trigger') return []\n return unique((connector.triggers ?? []).map((trigger) => trigger.id))\n}\n\nfunction requiredScopes(requirement: IntegrationRequirement, connector: IntegrationConnector): string[] {\n if (requirement.requiredScopes?.length) return unique(requirement.requiredScopes)\n const actionIds = new Set(requiredActions(requirement, connector))\n const triggerIds = new Set(requiredTriggers(requirement, connector))\n return unique([\n ...connector.actions\n .filter((action) => actionIds.has(action.id))\n .flatMap((action) => action.requiredScopes),\n ...(connector.triggers ?? [])\n .filter((trigger) => triggerIds.has(trigger.id))\n .flatMap((trigger) => trigger.requiredScopes),\n ])\n}\n\nfunction sameActor(a: IntegrationActor, b: IntegrationActor): boolean {\n return a.type === b.type && a.id === b.id\n}\n\nfunction unique<T>(values: T[]): T[] {\n return [...new Set(values)]\n}\n"],"mappings":"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","names":["missing"]}