@tangle-network/agent-integrations 0.2.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -37,19 +37,49 @@ capability. The sandbox should never receive reusable provider secrets.
37
37
 
38
38
  ## Core Usage
39
39
 
40
+ ### Product Flow
41
+
42
+ For Agent Builder and sandbox apps, the intended flow is:
43
+
44
+ ```txt
45
+ generated app declares required tools
46
+ -> app searches the integration catalog by intent
47
+ -> user connects the missing accounts
48
+ -> runtime issues a short-lived capability to the sandbox
49
+ -> reads run immediately
50
+ -> writes pause for policy approval
51
+ -> every call returns an audit-safe result
52
+ ```
53
+
54
+ The SDK surface for that flow is:
55
+
56
+ - `buildIntegrationToolCatalog` and `searchIntegrationTools` for discoverable
57
+ tool catalogs.
58
+ - `toMcpTools` for MCP-compatible tool export.
59
+ - `IntegrationHub.issueCapability` for scoped sandbox handoff.
60
+ - `createDefaultIntegrationPolicyEngine` for allow / approval / deny decisions.
61
+ - `buildIntegrationInvocationEnvelope` for sandbox-safe tool calls.
62
+ - `createConnectorAdapterProvider` to run first-party adapters through the hub.
63
+
40
64
  ```ts
41
65
  import {
42
66
  InMemoryConnectionStore,
43
67
  IntegrationHub,
68
+ buildIntegrationToolCatalog,
44
69
  createMockIntegrationProvider,
70
+ searchIntegrationTools,
45
71
  } from '@tangle-network/agent-integrations'
46
72
 
73
+ const provider = createMockIntegrationProvider()
47
74
  const hub = new IntegrationHub({
48
- providers: [createMockIntegrationProvider()],
75
+ providers: [provider],
49
76
  store: new InMemoryConnectionStore(),
50
77
  capabilitySecret: 'dev-secret',
51
78
  })
52
79
 
80
+ const catalog = buildIntegrationToolCatalog(await hub.listConnectors())
81
+ const tools = searchIntegrationTools(catalog, 'search unread gmail', { maxRisk: 'read' })
82
+
53
83
  const connection = await hub.upsertConnection({
54
84
  id: 'conn_1',
55
85
  owner: { type: 'user', id: 'user_1' },
package/dist/index.d.ts CHANGED
@@ -903,6 +903,206 @@ declare const stripeWebhookReceiverConnector: ConnectorAdapter;
903
903
 
904
904
  declare const slackEventsConnector: ConnectorAdapter;
905
905
 
906
+ interface IntegrationToolDefinition {
907
+ name: string;
908
+ title: string;
909
+ description: string;
910
+ providerId: string;
911
+ connectorId: string;
912
+ connectorTitle: string;
913
+ category: IntegrationConnectorCategory;
914
+ action: IntegrationConnectorAction;
915
+ risk: IntegrationActionRisk;
916
+ dataClass: IntegrationDataClass;
917
+ requiredScopes: string[];
918
+ inputSchema?: unknown;
919
+ outputSchema?: unknown;
920
+ tags: string[];
921
+ }
922
+ interface IntegrationToolSearchFilters {
923
+ providerId?: string;
924
+ connectorId?: string;
925
+ category?: IntegrationConnectorCategory;
926
+ maxRisk?: IntegrationActionRisk;
927
+ dataClass?: IntegrationDataClass;
928
+ limit?: number;
929
+ }
930
+ interface IntegrationToolSearchResult {
931
+ tool: IntegrationToolDefinition;
932
+ score: number;
933
+ matched: string[];
934
+ }
935
+ interface McpToolDefinition {
936
+ name: string;
937
+ description: string;
938
+ inputSchema: unknown;
939
+ }
940
+ declare function integrationToolName(providerId: string, connectorId: string, actionId: string): string;
941
+ declare function parseIntegrationToolName(name: string): {
942
+ providerId: string;
943
+ connectorId: string;
944
+ actionId: string;
945
+ };
946
+ declare function buildIntegrationToolCatalog(connectors: IntegrationConnector[]): IntegrationToolDefinition[];
947
+ declare function searchIntegrationTools(catalog: IntegrationToolDefinition[], query: string, filters?: IntegrationToolSearchFilters): IntegrationToolSearchResult[];
948
+ declare function toMcpTools(tools: IntegrationToolDefinition[]): McpToolDefinition[];
949
+
950
+ type IntegrationPolicyEffect = 'allow' | 'require_approval' | 'deny';
951
+ interface IntegrationPolicyRule {
952
+ id: string;
953
+ effect: IntegrationPolicyEffect;
954
+ reason: string;
955
+ providerId?: string;
956
+ connectorId?: string;
957
+ action?: string;
958
+ maxRisk?: IntegrationActionRisk;
959
+ risk?: IntegrationActionRisk;
960
+ dataClass?: IntegrationDataClass;
961
+ }
962
+ interface StaticIntegrationPolicyOptions {
963
+ rules?: IntegrationPolicyRule[];
964
+ defaultReadEffect?: IntegrationPolicyEffect;
965
+ defaultWriteEffect?: IntegrationPolicyEffect;
966
+ defaultDestructiveEffect?: IntegrationPolicyEffect;
967
+ now?: () => Date;
968
+ }
969
+ interface IntegrationApprovalResolution {
970
+ approvalId: string;
971
+ approved: boolean;
972
+ resolvedBy: string;
973
+ resolvedAt: string;
974
+ reason?: string;
975
+ metadata?: Record<string, unknown>;
976
+ }
977
+ declare class StaticIntegrationPolicyEngine implements IntegrationPolicyEngine {
978
+ private readonly rules;
979
+ private readonly defaultReadEffect;
980
+ private readonly defaultWriteEffect;
981
+ private readonly defaultDestructiveEffect;
982
+ private readonly now;
983
+ constructor(options?: StaticIntegrationPolicyOptions);
984
+ decide(ctx: IntegrationGuardContext & {
985
+ subject: {
986
+ type: string;
987
+ id: string;
988
+ };
989
+ }): IntegrationPolicyDecision;
990
+ private defaultEffect;
991
+ }
992
+ declare function createDefaultIntegrationPolicyEngine(options?: Omit<StaticIntegrationPolicyOptions, 'rules'>): StaticIntegrationPolicyEngine;
993
+ declare function buildApprovalRequest(ctx: IntegrationGuardContext & {
994
+ subject: {
995
+ type: string;
996
+ id: string;
997
+ };
998
+ }, reason: string, requestedAt: Date): IntegrationApprovalRequest;
999
+ declare function redactApprovalRequest(request: IntegrationApprovalRequest): IntegrationApprovalRequest;
1000
+
1001
+ interface IntegrationInvocationEnvelope {
1002
+ kind: 'integration.invocation';
1003
+ capabilityToken: string;
1004
+ toolName: string;
1005
+ action: string;
1006
+ input?: unknown;
1007
+ idempotencyKey: string;
1008
+ dryRun?: boolean;
1009
+ metadata?: Record<string, unknown>;
1010
+ }
1011
+ type NormalizedIntegrationResult = {
1012
+ status: 'ok';
1013
+ action: string;
1014
+ output?: unknown;
1015
+ metadata?: Record<string, unknown>;
1016
+ } | {
1017
+ status: 'approval_required';
1018
+ action: string;
1019
+ approval: IntegrationApprovalRequest;
1020
+ metadata?: Record<string, unknown>;
1021
+ } | {
1022
+ status: 'failed';
1023
+ action: string;
1024
+ error: string;
1025
+ metadata?: Record<string, unknown>;
1026
+ };
1027
+ declare function buildIntegrationInvocationEnvelope(input: {
1028
+ capabilityToken: string;
1029
+ toolName: string;
1030
+ args?: unknown;
1031
+ idempotencyKey: string;
1032
+ dryRun?: boolean;
1033
+ metadata?: Record<string, unknown>;
1034
+ }): IntegrationInvocationEnvelope;
1035
+ declare function invocationRequestFromEnvelope(envelope: IntegrationInvocationEnvelope): InvokeWithCapabilityRequest;
1036
+ declare function redactInvocationEnvelope(envelope: IntegrationInvocationEnvelope): Omit<IntegrationInvocationEnvelope, 'capabilityToken'> & {
1037
+ capabilityToken: '[REDACTED]';
1038
+ };
1039
+ declare function redactCapability(capability: IntegrationCapability): IntegrationCapability;
1040
+ declare function normalizeIntegrationResult(result: IntegrationActionResult): NormalizedIntegrationResult;
1041
+
1042
+ interface ConnectorAdapterProviderOptions {
1043
+ id?: string;
1044
+ kind?: IntegrationProviderKind;
1045
+ adapters: ConnectorAdapter[];
1046
+ resolveDataSource: (connection: IntegrationConnection) => Promise<ResolvedDataSource> | ResolvedDataSource;
1047
+ now?: () => Date;
1048
+ }
1049
+ declare function createConnectorAdapterProvider(options: ConnectorAdapterProviderOptions): IntegrationProvider;
1050
+ declare function manifestToConnector(providerId: string, adapter: ConnectorAdapter): IntegrationConnector;
1051
+
1052
+ interface ImportCatalogOptions {
1053
+ providerId: string;
1054
+ connectorId: string;
1055
+ connectorTitle: string;
1056
+ category?: IntegrationConnectorCategory;
1057
+ auth?: IntegrationConnector['auth'];
1058
+ scopes?: string[];
1059
+ dataClass?: IntegrationDataClass;
1060
+ defaultRisk?: IntegrationActionRisk;
1061
+ }
1062
+ interface OpenApiDocument {
1063
+ openapi?: string;
1064
+ swagger?: string;
1065
+ info?: {
1066
+ title?: string;
1067
+ };
1068
+ paths?: Record<string, Record<string, OpenApiOperation | unknown>>;
1069
+ }
1070
+ interface OpenApiOperation {
1071
+ operationId?: string;
1072
+ summary?: string;
1073
+ description?: string;
1074
+ parameters?: unknown[];
1075
+ requestBody?: unknown;
1076
+ responses?: unknown;
1077
+ security?: Array<Record<string, string[]>>;
1078
+ tags?: string[];
1079
+ }
1080
+ interface GraphqlOperationSpec {
1081
+ name: string;
1082
+ kind: 'query' | 'mutation';
1083
+ description?: string;
1084
+ inputSchema?: unknown;
1085
+ outputSchema?: unknown;
1086
+ requiredScopes?: string[];
1087
+ }
1088
+ interface McpCatalogTool {
1089
+ name: string;
1090
+ description?: string;
1091
+ inputSchema?: unknown;
1092
+ annotations?: {
1093
+ readOnlyHint?: boolean;
1094
+ destructiveHint?: boolean;
1095
+ openWorldHint?: boolean;
1096
+ title?: string;
1097
+ };
1098
+ }
1099
+ interface McpCatalog {
1100
+ tools: McpCatalogTool[];
1101
+ }
1102
+ declare function importOpenApiConnector(document: OpenApiDocument, options: ImportCatalogOptions): IntegrationConnector;
1103
+ declare function importGraphqlConnector(operations: GraphqlOperationSpec[], options: ImportCatalogOptions): IntegrationConnector;
1104
+ declare function importMcpConnector(catalog: McpCatalog, options: ImportCatalogOptions): IntegrationConnector;
1105
+
906
1106
  type IntegrationProviderKind = 'first_party' | 'nango' | 'pipedream' | 'zapier' | 'activepieces' | 'executor' | 'custom';
907
1107
  type IntegrationConnectorCategory = 'email' | 'calendar' | 'chat' | 'crm' | 'storage' | 'docs' | 'database' | 'webhook' | 'workflow' | 'internal' | 'other';
908
1108
  type IntegrationActionRisk = 'read' | 'write' | 'destructive';
@@ -1100,6 +1300,39 @@ interface IntegrationGuardContext {
1100
1300
  /** The action descriptor from the connector manifest, if discovered. */
1101
1301
  action?: IntegrationConnectorAction;
1102
1302
  }
1303
+ type IntegrationPolicyDecision = {
1304
+ decision: 'allow';
1305
+ reason: string;
1306
+ metadata?: Record<string, unknown>;
1307
+ } | {
1308
+ decision: 'require_approval';
1309
+ reason: string;
1310
+ approval: IntegrationApprovalRequest;
1311
+ metadata?: Record<string, unknown>;
1312
+ } | {
1313
+ decision: 'deny';
1314
+ reason: string;
1315
+ metadata?: Record<string, unknown>;
1316
+ };
1317
+ interface IntegrationApprovalRequest {
1318
+ id: string;
1319
+ connectionId: string;
1320
+ providerId: string;
1321
+ connectorId: string;
1322
+ action: string;
1323
+ actor: IntegrationActor;
1324
+ risk: IntegrationActionRisk;
1325
+ dataClass: IntegrationDataClass;
1326
+ reason: string;
1327
+ requestedAt: string;
1328
+ inputPreview?: unknown;
1329
+ metadata?: Record<string, unknown>;
1330
+ }
1331
+ interface IntegrationPolicyEngine {
1332
+ decide(ctx: IntegrationGuardContext & {
1333
+ subject: IntegrationActor;
1334
+ }): Promise<IntegrationPolicyDecision> | IntegrationPolicyDecision;
1335
+ }
1103
1336
  interface IntegrationHubOptions {
1104
1337
  providers: IntegrationProvider[];
1105
1338
  store: IntegrationConnectionStore;
@@ -1107,6 +1340,10 @@ interface IntegrationHubOptions {
1107
1340
  /** Optional cross-cutting guard. If provided, every invokeAction call
1108
1341
  * passes through it before reaching the provider. See {@link IntegrationActionGuard}. */
1109
1342
  guard?: IntegrationActionGuard;
1343
+ /** Optional policy engine. Runs after capability/scope checks and before
1344
+ * provider invocation. Use it to pause writes, deny destructive actions,
1345
+ * or apply tenant-specific allow rules. */
1346
+ policy?: IntegrationPolicyEngine;
1110
1347
  now?: () => Date;
1111
1348
  }
1112
1349
  interface HttpIntegrationProviderOptions {
@@ -1121,8 +1358,8 @@ interface InvokeWithCapabilityRequest extends Omit<IntegrationActionRequest, 'co
1121
1358
  connectionId?: never;
1122
1359
  }
1123
1360
  declare class IntegrationError extends Error {
1124
- readonly code: 'provider_not_found' | 'connector_not_found' | 'connection_not_found' | 'connection_not_active' | 'auth_not_supported' | 'capability_invalid' | 'capability_expired' | 'scope_denied' | 'action_denied' | 'action_not_found';
1125
- constructor(message: string, code: 'provider_not_found' | 'connector_not_found' | 'connection_not_found' | 'connection_not_active' | 'auth_not_supported' | 'capability_invalid' | 'capability_expired' | 'scope_denied' | 'action_denied' | 'action_not_found');
1361
+ readonly code: 'provider_not_found' | 'connector_not_found' | 'connection_not_found' | 'connection_not_active' | 'auth_not_supported' | 'capability_invalid' | 'capability_expired' | 'scope_denied' | 'action_denied' | 'action_not_found' | 'approval_required' | 'policy_denied';
1362
+ constructor(message: string, code: 'provider_not_found' | 'connector_not_found' | 'connection_not_found' | 'connection_not_active' | 'auth_not_supported' | 'capability_invalid' | 'capability_expired' | 'scope_denied' | 'action_denied' | 'action_not_found' | 'approval_required' | 'policy_denied');
1126
1363
  }
1127
1364
  declare class InMemoryConnectionStore implements IntegrationConnectionStore {
1128
1365
  private readonly connections;
@@ -1136,6 +1373,7 @@ declare class IntegrationHub {
1136
1373
  private readonly store;
1137
1374
  private readonly capabilitySecret;
1138
1375
  private readonly guard;
1376
+ private readonly policy;
1139
1377
  private readonly now;
1140
1378
  constructor(options: IntegrationHubOptions);
1141
1379
  listConnectors(): Promise<IntegrationConnector[]>;
@@ -1161,4 +1399,4 @@ declare function createHttpIntegrationProvider(options: HttpIntegrationProviderO
1161
1399
  declare function signCapability(capability: IntegrationCapability, secret: string): string;
1162
1400
  declare function verifyCapabilityToken(token: string, secret: string): IntegrationCapability;
1163
1401
 
1164
- export { type AuthSpec, type CASStrategy, type Capability, type CapabilityClass, type CapabilityMutation, type CapabilityMutationResult, type CapabilityParameterSchema, type CapabilityRead, type CapabilityReadResult, type CompleteAuthRequest, type ConnectorAdapter, type ConnectorCredentials, type ConnectorInvocation, type ConnectorManifest, type ConnectorManifestValidationIssue, type ConnectorManifestValidationResult, type ConsistencyModel, CredentialsExpired, DEFAULT_SIGNATURE_TOLERANCE_SECONDS, type DataSourceMetadata, type EventHandlerResult, type ExchangeCodeInput, type GenericHmacVerifyOptions, type GoogleCalendarOptions, type GoogleSheetsOptions, type HttpIntegrationProviderOptions, type HubSpotOptions, InMemoryConnectionStore, InMemoryOAuthFlowStore, type InboundEvent, type IntegrationActionGuard, type IntegrationActionRequest, type IntegrationActionResult, type IntegrationActionRisk, type IntegrationActor, type IntegrationCapability, type IntegrationConnection, type IntegrationConnectionStore, type IntegrationConnector, type IntegrationConnectorAction, type IntegrationConnectorCategory, type IntegrationConnectorTrigger, type IntegrationDataClass, IntegrationError, type IntegrationGuardContext, IntegrationHub, type IntegrationHubOptions, type IntegrationProvider, type IntegrationProviderKind, type IntegrationTriggerEvent, type IntegrationTriggerSubscription, type InvokeWithCapabilityRequest, type IssueCapabilityRequest, type IssuedIntegrationCapability, type MicrosoftCalendarOptions, type NotionDatabaseOptions, type OAuthFlowStore, type OAuthTokens, type ParsedStripeSignatureHeader, type PendingOAuthFlow, type RateLimitSpec, type RefreshInput, type ResolvedDataSource, ResourceContention, type SecretRef, type SlackOptions, type SlackVerifyOptions, type StartAuthRequest, type StartAuthResult, type StartOAuthInput, type StartOAuthOutput, type StripeVerifyOptions, _resetPendingFlowsForTests, assertValidConnectorManifest, consumePendingFlow, createHttpIntegrationProvider, createMockIntegrationProvider, exchangeAuthorizationCode, firstHeader, googleCalendar, googleSheets, hubspot, microsoftCalendar, notionDatabase, parseStripeSignatureHeader, refreshAccessToken, sanitizeConnection, signCapability, slack, slackEventsConnector, startOAuthFlow, stripePackConnector, stripeWebhookReceiverConnector, twilioSmsConnector, validateConnectorManifest, verifyCapabilityToken, verifyHmacSignature, verifySlackSignature, verifyStripeSignature, webhookConnector };
1402
+ export { type AuthSpec, type CASStrategy, type Capability, type CapabilityClass, type CapabilityMutation, type CapabilityMutationResult, type CapabilityParameterSchema, type CapabilityRead, type CapabilityReadResult, type CompleteAuthRequest, type ConnectorAdapter, type ConnectorAdapterProviderOptions, type ConnectorCredentials, type ConnectorInvocation, type ConnectorManifest, type ConnectorManifestValidationIssue, type ConnectorManifestValidationResult, type ConsistencyModel, CredentialsExpired, DEFAULT_SIGNATURE_TOLERANCE_SECONDS, type DataSourceMetadata, type EventHandlerResult, type ExchangeCodeInput, type GenericHmacVerifyOptions, type GoogleCalendarOptions, type GoogleSheetsOptions, type GraphqlOperationSpec, type HttpIntegrationProviderOptions, type HubSpotOptions, type ImportCatalogOptions, InMemoryConnectionStore, InMemoryOAuthFlowStore, type InboundEvent, type IntegrationActionGuard, type IntegrationActionRequest, type IntegrationActionResult, type IntegrationActionRisk, type IntegrationActor, type IntegrationApprovalRequest, type IntegrationApprovalResolution, type IntegrationCapability, type IntegrationConnection, type IntegrationConnectionStore, type IntegrationConnector, type IntegrationConnectorAction, type IntegrationConnectorCategory, type IntegrationConnectorTrigger, type IntegrationDataClass, IntegrationError, type IntegrationGuardContext, IntegrationHub, type IntegrationHubOptions, type IntegrationInvocationEnvelope, type IntegrationPolicyDecision, type IntegrationPolicyEffect, type IntegrationPolicyEngine, type IntegrationPolicyRule, type IntegrationProvider, type IntegrationProviderKind, type IntegrationToolDefinition, type IntegrationToolSearchFilters, type IntegrationToolSearchResult, type IntegrationTriggerEvent, type IntegrationTriggerSubscription, type InvokeWithCapabilityRequest, type IssueCapabilityRequest, type IssuedIntegrationCapability, type McpCatalog, type McpCatalogTool, type McpToolDefinition, type MicrosoftCalendarOptions, type NormalizedIntegrationResult, type NotionDatabaseOptions, type OAuthFlowStore, type OAuthTokens, type OpenApiDocument, type OpenApiOperation, type ParsedStripeSignatureHeader, type PendingOAuthFlow, type RateLimitSpec, type RefreshInput, type ResolvedDataSource, ResourceContention, type SecretRef, type SlackOptions, type SlackVerifyOptions, type StartAuthRequest, type StartAuthResult, type StartOAuthInput, type StartOAuthOutput, StaticIntegrationPolicyEngine, type StaticIntegrationPolicyOptions, type StripeVerifyOptions, _resetPendingFlowsForTests, assertValidConnectorManifest, buildApprovalRequest, buildIntegrationInvocationEnvelope, buildIntegrationToolCatalog, consumePendingFlow, createConnectorAdapterProvider, createDefaultIntegrationPolicyEngine, createHttpIntegrationProvider, createMockIntegrationProvider, exchangeAuthorizationCode, firstHeader, googleCalendar, googleSheets, hubspot, importGraphqlConnector, importMcpConnector, importOpenApiConnector, integrationToolName, invocationRequestFromEnvelope, manifestToConnector, microsoftCalendar, normalizeIntegrationResult, notionDatabase, parseIntegrationToolName, parseStripeSignatureHeader, redactApprovalRequest, redactCapability, redactInvocationEnvelope, refreshAccessToken, sanitizeConnection, searchIntegrationTools, signCapability, slack, slackEventsConnector, startOAuthFlow, stripePackConnector, stripeWebhookReceiverConnector, toMcpTools, twilioSmsConnector, validateConnectorManifest, verifyCapabilityToken, verifyHmacSignature, verifySlackSignature, verifyStripeSignature, webhookConnector };