@tangle-network/agent-integrations 0.25.1 → 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 (43) hide show
  1. package/README.md +28 -5
  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/adapter-triage.md +1 -1
  37. package/docs/platform-control-plane.md +54 -0
  38. package/docs/product-hub-ownership.md +126 -0
  39. package/docs/production-completion-checklist.md +2 -0
  40. package/docs/provider-decision-matrix.md +3 -3
  41. package/examples/calendar-exercise-app.ts +3 -3
  42. package/package.json +40 -12
  43. package/dist/chunk-VJ57GPYO.js.map +0 -1
package/README.md CHANGED
@@ -25,6 +25,7 @@ provider SDK.
25
25
  - [Product Adoption](#product-adoption)
26
26
  - [Provider Strategy](#provider-strategy)
27
27
  - [Executable Coverage](#executable-coverage)
28
+ - [Product Hub Ownership](#product-hub-ownership)
28
29
  - [Examples](#examples)
29
30
  - [Security Model](#security-model)
30
31
  - [Development](#development)
@@ -48,9 +49,9 @@ provider SDK.
48
49
  executable backend state explicit.
49
50
  - A canonical registry that deduplicates overlapping catalogs, keeps support
50
51
  tiers explicit, and reports auth/category conflicts.
51
- - App/agent manifests, grants, and sandbox bundles so Builder, generated apps,
52
- domain agents, Blueprint Agent, and executor-backed runtimes can reuse the
53
- same user-owned connections safely.
52
+ - App/agent manifests, grants, and sandbox bundles so generated apps, domain
53
+ agents, and executor-backed runtimes can reuse the same user-owned
54
+ connections safely.
54
55
  - Workflow trigger installation and normalized event dispatch for non-agent UI
55
56
  automation, sync jobs, webhooks, and product workflows.
56
57
  - Approval persistence, audit events, healthchecks, credential resolution,
@@ -237,6 +238,17 @@ const bundle = await runtime.buildSandboxBundle({
237
238
  })
238
239
  ```
239
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
+
240
252
  Generated apps and sandboxes receive scoped capability tokens and tool
241
253
  definitions. They never receive OAuth refresh tokens, API keys, or raw secrets.
242
254
  For sandbox processes, pass the bundle through `buildIntegrationBridgeEnvironment()`;
@@ -246,7 +258,7 @@ Generated app code should use the tiny client instead of raw provider tokens:
246
258
 
247
259
  ```ts
248
260
  const integrations = createTangleIntegrationsClient({
249
- endpoint: 'https://id.tangle.tools',
261
+ endpoint: 'https://integrations.example.com',
250
262
  env: process.env,
251
263
  })
252
264
 
@@ -271,7 +283,18 @@ lets the product dispatch normalized events to UI workflows, sync jobs, or
271
283
  agent runs.
272
284
 
273
285
  For a full product checklist, see
274
- [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).
288
+
289
+ ## Product Hub Ownership
290
+
291
+ Use a hosted hub when multiple apps intentionally share identity, billing,
292
+ consent, and connection custody. Use a product-owned hub when a standalone
293
+ deployment needs its own customer boundary, OAuth branding, vault, policy, or
294
+ data residency. Both modes use the same package contracts.
295
+
296
+ See [Product Hub Ownership](./docs/product-hub-ownership.md) for the
297
+ deployment model and launch gates.
275
298
 
276
299
  ## Provider Strategy
277
300
 
@@ -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"]}