@tangle-network/agent-integrations 0.13.0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -128,21 +128,24 @@ function buildActivepiecesConnectors(options = {}) {
128
128
  const override = getActivepiecesOverride(entry.id);
129
129
  const category = override?.category ?? entry.category;
130
130
  const scopes = [`${entry.id}.read`, `${entry.id}.write`];
131
- const actions = entry.actions.length > 0 ? entry.actions.map((action) => toAction(applyActionOverride(action, override), scopes, dataClassFor(category))) : defaultActions(entry.id, scopes, dataClassFor(category));
131
+ const catalogActions = entry.actions.length > 0 ? entry.actions.map((action) => toAction(applyActionOverride(action, override), scopes, dataClassFor(category))) : defaultActions(entry.id, scopes, dataClassFor(category));
132
+ const catalogTriggers = entry.triggers.map((trigger) => toTrigger(trigger, scopes, dataClassFor(category)));
132
133
  return {
133
134
  id: entry.id,
134
135
  providerId,
135
136
  title: entry.title,
136
137
  category,
137
138
  auth: entry.auth,
138
- scopes,
139
- actions,
140
- triggers: entry.triggers.map((trigger) => toTrigger(trigger, scopes, dataClassFor(category))),
139
+ scopes: options.includeCatalogActions ? scopes : [],
140
+ actions: options.includeCatalogActions ? catalogActions : [],
141
+ triggers: options.includeCatalogActions ? catalogTriggers : void 0,
141
142
  metadata: {
142
143
  source: "activepieces-community",
143
144
  executable: false,
144
145
  runtime: "activepieces-piece",
145
146
  catalogOnly: true,
147
+ catalogActionCount: catalogActions.length,
148
+ catalogTriggerCount: catalogTriggers.length,
146
149
  npmPackage: entry.npmPackage,
147
150
  version: entry.version,
148
151
  license: entry.source.license,
@@ -490,15 +493,15 @@ function actionPack(pack, scopes) {
490
493
  }
491
494
  function triggersFor(pack, scopes) {
492
495
  const readScope = scopes.find((scope) => scope.endsWith(".read")) ?? scopes[0];
493
- const requiredScopes = readScope ? [readScope] : [];
494
- if (pack === "email") return [{ id: "message.received", title: "Message received", requiredScopes, dataClass: "private" }];
495
- if (pack === "calendar") return [{ id: "event.changed", title: "Event changed", requiredScopes, dataClass: "private" }];
496
- if (pack === "chat") return [{ id: "message.posted", title: "Message posted", requiredScopes, dataClass: "private" }];
497
- if (pack === "crm") return [{ id: "record.changed", title: "Record changed", requiredScopes, dataClass: "private" }];
498
- if (pack === "support") return [{ id: "ticket.changed", title: "Ticket changed", requiredScopes, dataClass: "private" }];
499
- if (pack === "commerce") return [{ id: "order.changed", title: "Order changed", requiredScopes, dataClass: "sensitive" }];
500
- if (pack === "finance") return [{ id: "transaction.changed", title: "Transaction changed", requiredScopes, dataClass: "sensitive" }];
501
- if (pack === "workflow" || pack === "webhook") return [{ id: "event.received", title: "Event received", requiredScopes, dataClass: "internal" }];
496
+ const requiredScopes2 = readScope ? [readScope] : [];
497
+ if (pack === "email") return [{ id: "message.received", title: "Message received", requiredScopes: requiredScopes2, dataClass: "private" }];
498
+ if (pack === "calendar") return [{ id: "event.changed", title: "Event changed", requiredScopes: requiredScopes2, dataClass: "private" }];
499
+ if (pack === "chat") return [{ id: "message.posted", title: "Message posted", requiredScopes: requiredScopes2, dataClass: "private" }];
500
+ if (pack === "crm") return [{ id: "record.changed", title: "Record changed", requiredScopes: requiredScopes2, dataClass: "private" }];
501
+ if (pack === "support") return [{ id: "ticket.changed", title: "Ticket changed", requiredScopes: requiredScopes2, dataClass: "private" }];
502
+ if (pack === "commerce") return [{ id: "order.changed", title: "Order changed", requiredScopes: requiredScopes2, dataClass: "sensitive" }];
503
+ if (pack === "finance") return [{ id: "transaction.changed", title: "Transaction changed", requiredScopes: requiredScopes2, dataClass: "sensitive" }];
504
+ if (pack === "workflow" || pack === "webhook") return [{ id: "event.received", title: "Event received", requiredScopes: requiredScopes2, dataClass: "internal" }];
502
505
  return void 0;
503
506
  }
504
507
  function scopesFor(id, pack) {
@@ -1175,6 +1178,8 @@ function inferIntegrationSupportTier(connector) {
1175
1178
  if (metadata.source === "first-party-adapter" || connector.providerId === "first-party") return "firstPartyExecutable";
1176
1179
  if (metadata.source === "gateway-catalog" && metadata.executable === true) return "gatewayExecutable";
1177
1180
  if (metadata.source === "integration-spec") return "setupReady";
1181
+ if (metadata.source === "coverage-catalog" || metadata.source === "activepieces-community" || metadata.catalogOnly === true) return "catalogOnly";
1182
+ if (connector.actions.length > 0) return "gatewayExecutable";
1178
1183
  return "catalogOnly";
1179
1184
  }
1180
1185
  function registryEntry(canonicalId, candidates, precedence, aliases) {
@@ -1221,7 +1226,7 @@ function registryEntry(canonicalId, candidates, precedence, aliases) {
1221
1226
  sources,
1222
1227
  conflicts,
1223
1228
  toolBindable: actions.length > 0,
1224
- catalogOnlyActionCount: ordered.filter((candidate) => candidate.supportTier === "catalogOnly").reduce((sum, candidate) => sum + candidate.connector.actions.length, 0)
1229
+ catalogOnlyActionCount: ordered.filter((candidate) => candidate.supportTier === "catalogOnly").reduce((sum, candidate) => sum + catalogActionCount(candidate.connector), 0)
1225
1230
  }
1226
1231
  }
1227
1232
  }
@@ -1252,6 +1257,10 @@ function toolBindableCandidates(candidates) {
1252
1257
  const bindable = candidates.filter((candidate) => candidate.supportTier !== "catalogOnly");
1253
1258
  return bindable.length > 0 ? bindable : [];
1254
1259
  }
1260
+ function catalogActionCount(connector) {
1261
+ const value = connector.metadata?.catalogActionCount;
1262
+ return typeof value === "number" ? value : connector.actions.length;
1263
+ }
1255
1264
  function conflictDiagnostics(candidates) {
1256
1265
  return [
1257
1266
  conflictFor("auth", candidates.map((candidate) => ({
@@ -5244,6 +5253,295 @@ function unique4(values) {
5244
5253
  return [...new Set(values)];
5245
5254
  }
5246
5255
 
5256
+ // src/runtime.ts
5257
+ var InMemoryIntegrationGrantStore = class {
5258
+ grants = /* @__PURE__ */ new Map();
5259
+ get(grantId) {
5260
+ return this.grants.get(grantId);
5261
+ }
5262
+ put(grant) {
5263
+ this.grants.set(grant.id, grant);
5264
+ }
5265
+ listByManifest(manifestId, grantee) {
5266
+ return [...this.grants.values()].filter(
5267
+ (grant) => grant.manifestId === manifestId && (!grantee || sameActor(grant.grantee, grantee))
5268
+ );
5269
+ }
5270
+ listByGrantee(grantee) {
5271
+ return [...this.grants.values()].filter((grant) => sameActor(grant.grantee, grantee));
5272
+ }
5273
+ delete(grantId) {
5274
+ this.grants.delete(grantId);
5275
+ }
5276
+ };
5277
+ var IntegrationRuntime = class {
5278
+ hub;
5279
+ grants;
5280
+ now;
5281
+ constructor(options) {
5282
+ this.hub = options.hub;
5283
+ this.grants = options.grants ?? new InMemoryIntegrationGrantStore();
5284
+ this.now = options.now ?? (() => /* @__PURE__ */ new Date());
5285
+ }
5286
+ async registry() {
5287
+ return this.hub.listRegistry();
5288
+ }
5289
+ async resolveManifest(manifest, owner) {
5290
+ const registry = await this.registry();
5291
+ const connections = await this.hub.listConnections(owner);
5292
+ const resolutions = manifest.requirements.map(
5293
+ (requirement) => resolveRequirement(requirement, owner, registry, connections)
5294
+ );
5295
+ return {
5296
+ manifest,
5297
+ owner,
5298
+ ready: resolutions.filter((resolution) => resolution.status === "ready"),
5299
+ missing: resolutions.filter((resolution) => resolution.status !== "ready" && !resolution.requirement.optional),
5300
+ optionalMissing: resolutions.filter((resolution) => resolution.status !== "ready" && resolution.requirement.optional === true)
5301
+ };
5302
+ }
5303
+ async createGrants(input) {
5304
+ const resolution = await this.resolveManifest(input.manifest, input.owner);
5305
+ if (resolution.missing.length > 0) {
5306
+ throw new Error(`Cannot create integration grants; missing requirements: ${resolution.missing.map((r) => r.requirement.id).join(", ")}`);
5307
+ }
5308
+ const now = this.now().toISOString();
5309
+ const grants = resolution.ready.map((ready) => ({
5310
+ id: `grant_${input.manifest.id}_${ready.requirement.id}_${ready.connection.id}`,
5311
+ manifestId: input.manifest.id,
5312
+ requirementId: ready.requirement.id,
5313
+ owner: input.owner,
5314
+ grantee: input.grantee,
5315
+ connectionId: ready.connection.id,
5316
+ connectorId: ready.connector.id,
5317
+ scopes: requiredScopes(ready.requirement, ready.connector),
5318
+ allowedActions: requiredActions(ready.requirement, ready.connector),
5319
+ allowedTriggers: requiredTriggers(ready.requirement, ready.connector),
5320
+ status: "active",
5321
+ createdAt: now,
5322
+ updatedAt: now,
5323
+ metadata: input.metadata
5324
+ }));
5325
+ for (const grant of grants) await this.grants.put(grant);
5326
+ return grants;
5327
+ }
5328
+ async buildSandboxBundle(input) {
5329
+ const grants = (await this.grants.listByManifest(input.manifestId, input.grantee)).filter((grant) => grant.status === "active");
5330
+ const registry = await this.registry();
5331
+ const bindings = [];
5332
+ const connectors = [];
5333
+ let expiresAt = "";
5334
+ for (const grant of grants) {
5335
+ const entry = registry.byId.get(grant.connectorId);
5336
+ if (!entry) continue;
5337
+ const connector = {
5338
+ ...entry.connector,
5339
+ actions: entry.connector.actions.filter((action) => grant.allowedActions.includes(action.id)),
5340
+ triggers: entry.connector.triggers?.filter((trigger) => grant.allowedTriggers.includes(trigger.id)),
5341
+ scopes: entry.connector.scopes.filter((scope) => grant.scopes.includes(scope))
5342
+ };
5343
+ const capability = await this.hub.issueCapability({
5344
+ subject: input.subject,
5345
+ connectionId: grant.connectionId,
5346
+ scopes: grant.scopes,
5347
+ allowedActions: grant.allowedActions,
5348
+ ttlMs: input.ttlMs,
5349
+ metadata: {
5350
+ manifestId: grant.manifestId,
5351
+ grantId: grant.id,
5352
+ requirementId: grant.requirementId
5353
+ }
5354
+ });
5355
+ bindings.push({
5356
+ requirementId: grant.requirementId,
5357
+ connectorId: grant.connectorId,
5358
+ connectionId: grant.connectionId,
5359
+ grantId: grant.id,
5360
+ scopes: grant.scopes,
5361
+ allowedActions: grant.allowedActions,
5362
+ allowedTriggers: grant.allowedTriggers,
5363
+ capability
5364
+ });
5365
+ connectors.push(connector);
5366
+ expiresAt = capability.capability.expiresAt;
5367
+ }
5368
+ return {
5369
+ manifestId: input.manifestId,
5370
+ subject: input.subject,
5371
+ capabilities: bindings,
5372
+ connectors,
5373
+ tools: buildIntegrationToolCatalog(connectors),
5374
+ expiresAt
5375
+ };
5376
+ }
5377
+ };
5378
+ function createIntegrationRuntime(options) {
5379
+ return new IntegrationRuntime(options);
5380
+ }
5381
+ function resolveRequirement(requirement, owner, registry, connections) {
5382
+ const entry = registry.byId.get(requirement.connectorId);
5383
+ if (!entry) {
5384
+ return missing(requirement, "unknown_connector", `Unknown connector ${requirement.connectorId}.`);
5385
+ }
5386
+ const connector = entry.connector;
5387
+ if (connector.actions.length === 0 && (connector.triggers?.length ?? 0) === 0) {
5388
+ return missing(requirement, "not_executable", `${connector.title} is catalog-only and cannot be invoked yet.`, connector, entry);
5389
+ }
5390
+ const scopes = requiredScopes(requirement, connector);
5391
+ const actions = requiredActions(requirement, connector);
5392
+ const triggers = requiredTriggers(requirement, connector);
5393
+ const connection = connections.find(
5394
+ (candidate) => sameActor(candidate.owner, owner) && candidate.status === "active" && (candidate.connectorId === connector.id || entry.aliases.includes(candidate.connectorId)) && scopes.every((scope) => candidate.grantedScopes.includes(scope))
5395
+ );
5396
+ if (!connection) {
5397
+ return {
5398
+ requirement,
5399
+ status: "missing_connection",
5400
+ connector,
5401
+ registryEntry: entry,
5402
+ missingScopes: scopes,
5403
+ missingActions: actions,
5404
+ missingTriggers: triggers,
5405
+ message: `${connector.title} needs an active user connection with the required scopes.`
5406
+ };
5407
+ }
5408
+ return {
5409
+ requirement,
5410
+ status: "ready",
5411
+ connector,
5412
+ registryEntry: entry,
5413
+ connection,
5414
+ missingScopes: [],
5415
+ missingActions: [],
5416
+ missingTriggers: [],
5417
+ message: `${connector.title} is ready.`
5418
+ };
5419
+ }
5420
+ function missing(requirement, status, message, connector, registryEntry2) {
5421
+ return {
5422
+ requirement,
5423
+ status,
5424
+ connector,
5425
+ registryEntry: registryEntry2,
5426
+ missingScopes: [],
5427
+ missingActions: [],
5428
+ missingTriggers: [],
5429
+ message
5430
+ };
5431
+ }
5432
+ function requiredActions(requirement, connector) {
5433
+ if (requirement.mode === "trigger") return [];
5434
+ if (requirement.requiredActions?.length) return unique5(requirement.requiredActions);
5435
+ const actions = connector.actions.filter((action) => {
5436
+ if (requirement.mode === "read") return action.risk === "read";
5437
+ if (requirement.mode === "write") return action.risk !== "read";
5438
+ return false;
5439
+ });
5440
+ return unique5(actions.map((action) => action.id));
5441
+ }
5442
+ function requiredTriggers(requirement, connector) {
5443
+ if (requirement.requiredTriggers?.length) return unique5(requirement.requiredTriggers);
5444
+ if (requirement.mode !== "trigger") return [];
5445
+ return unique5((connector.triggers ?? []).map((trigger) => trigger.id));
5446
+ }
5447
+ function requiredScopes(requirement, connector) {
5448
+ if (requirement.requiredScopes?.length) return unique5(requirement.requiredScopes);
5449
+ const actionIds = new Set(requiredActions(requirement, connector));
5450
+ const triggerIds = new Set(requiredTriggers(requirement, connector));
5451
+ return unique5([
5452
+ ...connector.actions.filter((action) => actionIds.has(action.id)).flatMap((action) => action.requiredScopes),
5453
+ ...(connector.triggers ?? []).filter((trigger) => triggerIds.has(trigger.id)).flatMap((trigger) => trigger.requiredScopes)
5454
+ ]);
5455
+ }
5456
+ function sameActor(a, b) {
5457
+ return a.type === b.type && a.id === b.id;
5458
+ }
5459
+ function unique5(values) {
5460
+ return [...new Set(values)];
5461
+ }
5462
+
5463
+ // src/workflow.ts
5464
+ var InMemoryIntegrationWorkflowStore = class {
5465
+ workflows = /* @__PURE__ */ new Map();
5466
+ put(workflow) {
5467
+ this.workflows.set(workflow.id, workflow);
5468
+ }
5469
+ get(id) {
5470
+ return this.workflows.get(id);
5471
+ }
5472
+ list() {
5473
+ return [...this.workflows.values()];
5474
+ }
5475
+ listByWorkflow(workflowId) {
5476
+ return [...this.workflows.values()].filter((workflow) => workflow.workflowId === workflowId);
5477
+ }
5478
+ listByOwner(owner) {
5479
+ return [...this.workflows.values()].filter((workflow) => sameActor2(workflow.owner, owner));
5480
+ }
5481
+ };
5482
+ var IntegrationWorkflowRuntime = class {
5483
+ runtime;
5484
+ hub;
5485
+ grants;
5486
+ store;
5487
+ now;
5488
+ constructor(options) {
5489
+ this.runtime = options.runtime;
5490
+ this.hub = options.hub;
5491
+ this.grants = options.grants;
5492
+ this.store = options.store ?? new InMemoryIntegrationWorkflowStore();
5493
+ this.now = options.now ?? (() => /* @__PURE__ */ new Date());
5494
+ }
5495
+ async install(input) {
5496
+ const grants = await this.runtime.createGrants({
5497
+ manifest: input.workflow.manifest,
5498
+ owner: input.owner,
5499
+ grantee: input.grantee,
5500
+ metadata: { workflowId: input.workflow.id }
5501
+ });
5502
+ const triggerGrant = findTriggerGrant(grants, input.workflow.trigger.requirementId, input.workflow.trigger.triggerId);
5503
+ const subscription = await this.hub.subscribeTrigger(
5504
+ triggerGrant.connectionId,
5505
+ input.workflow.trigger.triggerId,
5506
+ input.workflow.trigger.targetUrl
5507
+ );
5508
+ const installed = {
5509
+ id: `workflow_${input.workflow.id}_${triggerGrant.id}`,
5510
+ workflowId: input.workflow.id,
5511
+ manifestId: input.workflow.manifest.id,
5512
+ owner: input.owner,
5513
+ grantee: input.grantee,
5514
+ triggerGrantId: triggerGrant.id,
5515
+ subscription,
5516
+ status: "active",
5517
+ createdAt: this.now().toISOString(),
5518
+ metadata: input.workflow.metadata
5519
+ };
5520
+ await this.store.put(installed);
5521
+ return installed;
5522
+ }
5523
+ async dispatchEvent(event, handler) {
5524
+ const workflows = (await this.store.list()).filter(
5525
+ (workflow) => workflow.status === "active" && workflow.subscription.connectionId === event.connectionId && workflow.subscription.trigger === event.trigger
5526
+ );
5527
+ await handler({ event, workflows });
5528
+ return { matched: workflows };
5529
+ }
5530
+ };
5531
+ function createIntegrationWorkflowRuntime(options) {
5532
+ return new IntegrationWorkflowRuntime(options);
5533
+ }
5534
+ function findTriggerGrant(grants, requirementId, triggerId) {
5535
+ const grant = grants.find(
5536
+ (candidate) => candidate.requirementId === requirementId && candidate.allowedTriggers.includes(triggerId)
5537
+ );
5538
+ if (!grant) throw new Error(`Missing trigger grant ${requirementId}/${triggerId}.`);
5539
+ return grant;
5540
+ }
5541
+ function sameActor2(a, b) {
5542
+ return a.type === b.type && a.id === b.id;
5543
+ }
5544
+
5247
5545
  // src/specs/types.ts
5248
5546
  function specAuthToConnectorAuth(auth) {
5249
5547
  if (auth.mode === "api_key") return "api_key";
@@ -5433,6 +5731,9 @@ var IntegrationHub = class {
5433
5731
  await this.store.put(connection);
5434
5732
  return connection;
5435
5733
  }
5734
+ async listConnections(owner) {
5735
+ return this.store.listByOwner(owner);
5736
+ }
5436
5737
  async issueCapability(request) {
5437
5738
  const connection = await this.requireConnection(request.connectionId);
5438
5739
  this.assertConnectionActive(connection);
@@ -5442,8 +5743,8 @@ var IntegrationHub = class {
5442
5743
  id: `cap_${randomUUID2()}`,
5443
5744
  subject: request.subject,
5444
5745
  connectionId: request.connectionId,
5445
- scopes: unique5(request.scopes),
5446
- allowedActions: unique5(request.allowedActions),
5746
+ scopes: unique6(request.scopes),
5747
+ allowedActions: unique6(request.allowedActions),
5447
5748
  issuedAt: now.toISOString(),
5448
5749
  expiresAt: new Date(now.getTime() + request.ttlMs).toISOString(),
5449
5750
  metadata: request.metadata
@@ -5671,9 +5972,9 @@ async function postJson(fetcher, url, body, bearer) {
5671
5972
  if (!response.ok) throw new IntegrationError(`Integration provider returned HTTP ${response.status}.`, "provider_not_found");
5672
5973
  return response.json();
5673
5974
  }
5674
- function assertScopes(connection, requiredScopes) {
5675
- const missing = requiredScopes.filter((scope) => !connection.grantedScopes.includes(scope));
5676
- if (missing.length > 0) throw new IntegrationError(`Missing integration scopes: ${missing.join(", ")}`, "scope_denied");
5975
+ function assertScopes(connection, requiredScopes2) {
5976
+ const missing2 = requiredScopes2.filter((scope) => !connection.grantedScopes.includes(scope));
5977
+ if (missing2.length > 0) throw new IntegrationError(`Missing integration scopes: ${missing2.join(", ")}`, "scope_denied");
5677
5978
  }
5678
5979
  function hmac(payload, secret) {
5679
5980
  return createHmac3("sha256", secret).update(payload).digest("base64url");
@@ -5689,7 +5990,7 @@ function base64UrlEncode(value) {
5689
5990
  function base64UrlDecode(value) {
5690
5991
  return Buffer.from(value, "base64url").toString("utf8");
5691
5992
  }
5692
- function unique5(values) {
5993
+ function unique6(values) {
5693
5994
  return [...new Set(values)];
5694
5995
  }
5695
5996
  export {
@@ -5698,9 +5999,13 @@ export {
5698
5999
  DEFAULT_SIGNATURE_TOLERANCE_SECONDS,
5699
6000
  INTEGRATION_FAMILIES,
5700
6001
  InMemoryConnectionStore,
6002
+ InMemoryIntegrationGrantStore,
6003
+ InMemoryIntegrationWorkflowStore,
5701
6004
  InMemoryOAuthFlowStore,
5702
6005
  IntegrationError,
5703
6006
  IntegrationHub,
6007
+ IntegrationRuntime,
6008
+ IntegrationWorkflowRuntime,
5704
6009
  ResourceContention,
5705
6010
  StaticIntegrationPolicyEngine,
5706
6011
  _resetPendingFlowsForTests,
@@ -5723,6 +6028,8 @@ export {
5723
6028
  createDefaultIntegrationPolicyEngine,
5724
6029
  createGatewayCatalogProvider,
5725
6030
  createHttpIntegrationProvider,
6031
+ createIntegrationRuntime,
6032
+ createIntegrationWorkflowRuntime,
5726
6033
  createMockIntegrationProvider,
5727
6034
  declarativeRestConnector,
5728
6035
  exchangeAuthorizationCode,