@tangle-network/agent-integrations 0.26.0 → 0.28.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.
Files changed (46) hide show
  1. package/dist/bin/tangle-catalog-runtime.js +6 -2
  2. package/dist/bin/tangle-catalog-runtime.js.map +1 -1
  3. package/dist/catalog.d.ts +5 -1
  4. package/dist/catalog.js +6 -2
  5. package/dist/chunk-ATYHZXLL.js +457 -0
  6. package/dist/chunk-ATYHZXLL.js.map +1 -0
  7. package/dist/chunk-H4XYLS7T.js +75 -0
  8. package/dist/chunk-H4XYLS7T.js.map +1 -0
  9. package/dist/{chunk-GA4VTE3U.js → chunk-JU25UDN2.js} +5 -58
  10. package/dist/chunk-JU25UDN2.js.map +1 -0
  11. package/dist/chunk-P24T3MLM.js +106 -0
  12. package/dist/chunk-P24T3MLM.js.map +1 -0
  13. package/dist/chunk-SVQ4PHDZ.js +129 -0
  14. package/dist/chunk-SVQ4PHDZ.js.map +1 -0
  15. package/dist/{chunk-ALCIWTIR.js → chunk-UWRYFPJW.js} +41 -83
  16. package/dist/chunk-UWRYFPJW.js.map +1 -0
  17. package/dist/connect/index.d.ts +112 -0
  18. package/dist/connect/index.js +14 -0
  19. package/dist/connect/index.js.map +1 -0
  20. package/dist/connectors/adapters/index.d.ts +593 -1
  21. package/dist/connectors/adapters/index.js +15 -1
  22. package/dist/connectors/index.d.ts +2 -1
  23. package/dist/connectors/index.js +19 -5
  24. package/dist/errors-Bg3_rxnQ.d.ts +32 -0
  25. package/dist/index.d.ts +6 -2
  26. package/dist/index.js +47 -9
  27. package/dist/middleware/index.d.ts +137 -0
  28. package/dist/middleware/index.js +14 -0
  29. package/dist/middleware/index.js.map +1 -0
  30. package/dist/registry.d.ts +29 -33
  31. package/dist/registry.js +6 -2
  32. package/dist/router-BncoovUh.d.ts +149 -0
  33. package/dist/runtime.d.ts +5 -1
  34. package/dist/runtime.js +6 -2
  35. package/dist/specs.d.ts +5 -1
  36. package/dist/stripe/index.d.ts +812 -0
  37. package/dist/stripe/index.js +866 -0
  38. package/dist/stripe/index.js.map +1 -0
  39. package/dist/tangle-catalog-runtime.d.ts +5 -1
  40. package/dist/tangle-catalog-runtime.js +6 -2
  41. package/dist/tangle-id-CTU4kGId.d.ts +553 -0
  42. package/dist/webhooks/index.d.ts +3 -148
  43. package/package.json +16 -1
  44. package/dist/chunk-ALCIWTIR.js.map +0 -1
  45. package/dist/chunk-GA4VTE3U.js.map +0 -1
  46. package/dist/index-D4D4CEKX.d.ts +0 -976
@@ -1,976 +0,0 @@
1
- /**
2
- * Connector primitives — the contract a concrete first-party integration
3
- * (Google Calendar, HubSpot, Stripe, ...) implements. Lower level than the
4
- * hub-side `IntegrationProvider` interface from `../index.ts`: a single
5
- * `IntegrationProvider` typically wraps several connectors (e.g., a
6
- * "first-party" provider that lists all your shipped connectors as a
7
- * single catalog).
8
- *
9
- * Layering:
10
- *
11
- * IntegrationHub — vendor-neutral facade (../index.ts)
12
- * ↓
13
- * IntegrationProvider — one per gateway or first-party provider
14
- * ↓
15
- * ConnectorAdapter (this file) — one per integration (Google Calendar, ...)
16
- * ↓
17
- * upstream HTTP API — vendor SDK / fetch / OAuth
18
- *
19
- * Three load-bearing decisions encoded here:
20
- *
21
- * 1. Capabilities are typed (`read` vs `mutation`). Every mutation MUST
22
- * declare a CAS strategy. Conflict resolution is the SDK's job, not the
23
- * connector's. `validateConnectorManifest()` rejects unsafe manifests
24
- * before a connector is registered.
25
- *
26
- * 2. ConsistencyModel pins what the rest of the system can assume:
27
- * authoritative → the source IS the truth (Calendar, payments)
28
- * cache → we mirror with TTL and may serve stale (price list)
29
- * advisory → informational only (FAQ doc)
30
- * Agent planners can (and should) refuse to promise outcomes based on
31
- * `cache`/`advisory` data without a live `authoritative` confirmation.
32
- *
33
- * 3. Capabilities surface to the calling agent's tool registry by
34
- * transformation, not by hand-wiring. Adding a connector automatically
35
- * expands the agent's toolbelt for that specific user without touching
36
- * the prompt or runner.
37
- */
38
- /** Minimal JSON-schema shape used for capability arg validation. We
39
- * intentionally don't pull `@types/json-schema` — most consumers already
40
- * declare parameters as `Record<string, unknown>` and the
41
- * shape is whatever the LLM SDK's structured-output expects. Keep the
42
- * contract loose at the boundary; tighten via runtime zod where needed. */
43
- type CapabilityParameterSchema = Record<string, unknown>;
44
- /** What the rest of the system is allowed to assume about freshness. */
45
- type ConsistencyModel = 'authoritative' | 'cache' | 'advisory';
46
- /** Capability classes. `read` is safe to retry; `mutation` must go through
47
- * MutationGuard (CAS + idempotency). `subscribe` is reserved for future
48
- * push-driven sources (webhook callbacks) and is not yet wired. */
49
- type CapabilityClass = 'read' | 'mutation' | 'subscribe';
50
- /** Compare-and-swap strategy a mutation uses to detect conflicts. */
51
- type CASStrategy =
52
- /** Upstream returns an etag/sequence on read, accepts If-Match on write
53
- * (Google Calendar, GitHub, GDocs revision_id). The connector returns
54
- * 412 / Precondition Failed on conflict; the SDK maps to ResourceContention. */
55
- 'etag-if-match'
56
- /** Upstream guarantees exactly-once-per-key (Stripe, idempotent webhooks).
57
- * The SDK passes the idempotency key through; no etag check. */
58
- | 'native-idempotency'
59
- /** No upstream concurrency control. Connector MUST do read-then-write
60
- * and verify nothing changed in-between (best-effort). Suitable only
61
- * for low-contention single-user resources; rejected for any
62
- * consistencyModel='authoritative' write that may race. */
63
- | 'optimistic-read-verify'
64
- /** Source is not contended (e.g. logging, telemetry). Mutations are
65
- * fire-and-forget. Marks the capability as not eligible for
66
- * authoritative writes. */
67
- | 'none';
68
- interface CapabilityRead {
69
- name: string;
70
- class: 'read';
71
- description: string;
72
- /** JSON-schema for the tool args the agent passes when invoking. */
73
- parameters: CapabilityParameterSchema;
74
- /** Optional: declare which scopes (per the connector manifest) this
75
- * capability requires. The capability is hidden from the agent's
76
- * tool registry if the user's grant didn't include them. */
77
- requiredScopes?: string[];
78
- }
79
- interface CapabilityMutation {
80
- name: string;
81
- class: 'mutation';
82
- description: string;
83
- parameters: CapabilityParameterSchema;
84
- /** Mandatory: how does the connector guarantee at-most-once + conflict-detect? */
85
- cas: CASStrategy;
86
- /** True for capabilities that affect resources outside the calling user
87
- * (e.g. booking against a shared calendar, charging a card). The agent's
88
- * planner treats these specially: requires explicit caller confirmation
89
- * before the call. */
90
- externalEffect: boolean;
91
- requiredScopes?: string[];
92
- }
93
- type Capability = CapabilityRead | CapabilityMutation;
94
- /** OAuth2 scope catalog the user has granted us, plus arbitrary metadata
95
- * the connector pinned at connect-time (calendar id, sheet id, webhook
96
- * url, …). `metadata` MUST NOT contain secrets — those go in the
97
- * encrypted credentials envelope. */
98
- interface DataSourceMetadata {
99
- scopes: string[];
100
- [key: string]: unknown;
101
- }
102
- /** A connected, authenticated, ready-to-call data source for a project.
103
- * Persistence shape mirrors the product's connection/source row but normalized — the
104
- * encrypted credentials envelope is decrypted at hand-out time and held
105
- * in memory only for the duration of the call. */
106
- interface ResolvedDataSource {
107
- id: string;
108
- projectId: string;
109
- publishedAgentId: string | null;
110
- kind: string;
111
- label: string;
112
- consistencyModel: ConsistencyModel;
113
- scopes: string[];
114
- metadata: Record<string, unknown>;
115
- /** Unwrapped credentials handed to the connector at call-time. Never
116
- * persisted in this shape; never logged. */
117
- credentials: ConnectorCredentials;
118
- status: 'active' | 'revoked' | 'error';
119
- }
120
- /** Discriminated union of credential shapes. Connectors that need new
121
- * shapes extend this union — `kind` is sealed via the tagged pattern so
122
- * TypeScript catches an exhaustiveness gap at compile time. */
123
- type ConnectorCredentials = {
124
- kind: 'oauth2';
125
- accessToken: string;
126
- refreshToken?: string;
127
- expiresAt?: number;
128
- } | {
129
- kind: 'api-key';
130
- apiKey: string;
131
- } | {
132
- kind: 'custom';
133
- values: Record<string, unknown>;
134
- } | {
135
- kind: 'hmac';
136
- secret: string;
137
- } | {
138
- kind: 'none';
139
- };
140
- /** Result of a read capability invocation. */
141
- interface CapabilityReadResult {
142
- /** Free-form payload — the connector's data shape. The agent receives
143
- * this as the tool result; planners consume it via JSON-shape contract
144
- * declared in the capability's `parameters` (output schema). */
145
- data: unknown;
146
- /** Optional etag/sequence the caller can reuse for a subsequent CAS
147
- * mutation. */
148
- etag?: string;
149
- /** When this read happened (UTC ms since epoch). */
150
- fetchedAt: number;
151
- }
152
- /** Result of a mutation capability invocation. Either committed (with the
153
- * resulting etag/sequence so the caller can chain mutations), or
154
- * contended (the upstream rejected with a state mismatch — the agent
155
- * should re-read and retry, or surface alternatives to the caller). */
156
- type CapabilityMutationResult = {
157
- status: 'committed';
158
- data: unknown;
159
- etagAfter?: string;
160
- committedAt: number;
161
- /** True iff this commit was returned from the idempotency store
162
- * rather than executed against upstream. The caller can use this
163
- * to suppress confirmation messages on retry. */
164
- idempotentReplay: boolean;
165
- } | {
166
- status: 'conflict';
167
- /** Best-effort alternative options the upstream surfaced (e.g.,
168
- * next-available calendar slots after a booking conflict). */
169
- alternatives: unknown[];
170
- /** The current authoritative state, if the connector could re-read
171
- * cheaply. */
172
- currentState?: unknown;
173
- message: string;
174
- } | {
175
- status: 'rate-limited';
176
- /** Wall-clock ms the caller should wait before retrying. The SDK
177
- * computes this from the bucket's refill schedule so the agent
178
- * doesn't have to guess. */
179
- retryAfterMs: number;
180
- message: string;
181
- };
182
- /** Inputs the SDK passes into the connector's executeRead / executeMutation. */
183
- interface ConnectorInvocation {
184
- source: ResolvedDataSource;
185
- capabilityName: string;
186
- args: Record<string, unknown>;
187
- /** Idempotency key the caller (or the SDK's defaulting policy) supplied.
188
- * Always present at the connector boundary — the SDK manufactures one
189
- * if the agent didn't pass one. */
190
- idempotencyKey: string;
191
- /** Optional caller-supplied etag the connector should send as If-Match. */
192
- expectedEtag?: string;
193
- /** Product/session id (if any) for forensic logging. */
194
- callSessionId?: string;
195
- }
196
- /** A single inbound event extracted from a push payload. The webhook
197
- * receiver persists one `InboundEvent` row per entry the connector returns. */
198
- interface InboundEvent {
199
- eventType: string;
200
- providerEventId?: string;
201
- payload: Record<string, unknown>;
202
- }
203
- /** Adapter response from an inbound-webhook dispatch. The receiver persists
204
- * every `events[]` entry, then either honors the connector's `response`
205
- * override (Slack `url_verification` echo, provider-specific 2xx body) or
206
- * defaults to `{status: 200, body: {received: true, count: events.length}}`. */
207
- interface EventHandlerResult {
208
- events: InboundEvent[];
209
- /** Optional: how to respond to the provider. Stripe wants 200 within
210
- * 30s; Slack wants the challenge param echoed. */
211
- response?: {
212
- status: number;
213
- body: unknown;
214
- headers?: Record<string, string>;
215
- };
216
- }
217
- /**
218
- * Connector adapter — one per integration kind. Stateless. The SDK holds
219
- * the persistence + crypto + mutation-guard concerns; the adapter only
220
- * knows how to talk to its upstream.
221
- */
222
- interface ConnectorAdapter {
223
- /** Manifest entry the registry uses to render UI + validate args. */
224
- manifest: ConnectorManifest;
225
- /** Read invocation. Required when manifest.capabilities contains reads.
226
- * Should return whatever shape the capability declared
227
- * in its parameters output schema. */
228
- executeRead?(inv: ConnectorInvocation): Promise<CapabilityReadResult>;
229
- /** Mutation invocation. Required when manifest.capabilities contains mutations.
230
- * Throws ResourceContention on a CAS miss; throws
231
- * any other Error for upstream failures. The MutationGuard wraps this
232
- * with idempotency-key short-circuit + audit logging — adapters do
233
- * NOT manage their own dedup. */
234
- executeMutation?(inv: ConnectorInvocation): Promise<CapabilityMutationResult>;
235
- /** Inbound webhook signature verifier. Called BEFORE handleInboundEvent.
236
- * MUST use constant-time comparison (`crypto.timingSafeEqual`) for any
237
- * HMAC check. The receiver returns 401 on `valid=false` without invoking
238
- * handleInboundEvent. Optional: connectors that don't accept push events
239
- * omit this method and the receiver returns 405 for the kind. */
240
- verifySignature?(input: {
241
- rawBody: string;
242
- headers: Record<string, string | string[] | undefined>;
243
- source: ResolvedDataSource;
244
- }): {
245
- valid: boolean;
246
- reason?: string;
247
- };
248
- /** Inbound webhook dispatch. Called AFTER verifySignature passes. The
249
- * adapter parses the provider payload and emits zero-or-more
250
- * `InboundEvent` rows; the receiver persists them as one row each (modulo
251
- * the (dataSourceId, providerEventId) dedup unique). The optional
252
- * `response` overrides the receiver's default 200 (Slack `url_verification`
253
- * needs to echo the challenge in the body to pass Slack's app-config check). */
254
- handleInboundEvent?(input: {
255
- source: ResolvedDataSource;
256
- rawBody: string;
257
- headers: Record<string, string | string[] | undefined>;
258
- }): Promise<EventHandlerResult>;
259
- /** OAuth callback handler — exchanges the auth code for tokens, returns
260
- * the credentials envelope + scopes + metadata. Only present for
261
- * oauth2-style adapters. */
262
- exchangeOAuth?(input: {
263
- code: string;
264
- state: string;
265
- codeVerifier: string;
266
- redirectUri: string;
267
- }): Promise<{
268
- credentials: ConnectorCredentials;
269
- scopes: string[];
270
- metadata: Record<string, unknown>;
271
- }>;
272
- /** Refresh access token. Only required for oauth2 adapters with
273
- * short-lived access tokens. */
274
- refreshToken?(input: ConnectorCredentials): Promise<ConnectorCredentials>;
275
- /** Health check — invoked when the user clicks "Test connection" in the
276
- * UI. Should perform the cheapest possible read that proves the grant
277
- * is still valid. Returns `{ok: false, reason}` rather than throwing
278
- * for the common case (token expired, scope missing). */
279
- test(source: ResolvedDataSource): Promise<{
280
- ok: true;
281
- } | {
282
- ok: false;
283
- reason: string;
284
- }>;
285
- }
286
- /** Static manifest a connector module exports. Drives the UI catalog,
287
- * scope display, capability discovery for the agent's tool registry. */
288
- interface ConnectorManifest {
289
- /** Stable kind id used as the foreign key in DataSource.kind. */
290
- kind: string;
291
- /** Human label shown in the UI catalog. */
292
- displayName: string;
293
- /** One-paragraph description shown next to the connect button. */
294
- description: string;
295
- /** Auth shape this connector requires. */
296
- auth: AuthSpec;
297
- /** Capability catalog — the agent's tool registry derives ToolDefinition
298
- * entries from this list at request time. */
299
- capabilities: Capability[];
300
- /** ConsistencyModel default for this kind — overridable per DataSource
301
- * if a particular instance is special (e.g., a user marks a sheet as
302
- * `cache` because they refresh it nightly). */
303
- defaultConsistencyModel: ConsistencyModel;
304
- /** Connector category for UI grouping. */
305
- category: 'calendar' | 'spreadsheet' | 'crm' | 'doc' | 'webhook' | 'storage' | 'comms' | 'commerce' | 'other';
306
- /** Optional icon URL or named icon. */
307
- icon?: string;
308
- /** Optional per-kind rate-limit budget. The SDK enforces it inside
309
- * `executeGuardedMutation` and the read path of `/invoke`. Omit to
310
- * leave the connector unrestricted. */
311
- rateLimit?: RateLimitSpec;
312
- }
313
- /** Token-bucket budget the SDK enforces against the connector's upstream.
314
- * We meter on OUR side rather than letting the upstream reject so a
315
- * chatty agent can't burn quota that's shared across customers (almost
316
- * every OAuth client is). */
317
- interface RateLimitSpec {
318
- /** Max requests per window. */
319
- requests: number;
320
- /** Window in ms. */
321
- windowMs: number;
322
- /** Whether to apply across all DataSources sharing the same OAuth
323
- * client (true; default), or per-DataSource (false). The former
324
- * matches how upstreams meter (per-app), so almost always pick true. */
325
- scope?: 'oauth-client' | 'data-source';
326
- }
327
- type AuthSpec = {
328
- kind: 'oauth2';
329
- /** Authorization endpoint URL. */
330
- authorizationUrl: string;
331
- /** Token endpoint URL. */
332
- tokenUrl: string;
333
- /** Scopes requested in the authorization grant. The user UI shows
334
- * these so the customer knows what's being shared. */
335
- scopes: string[];
336
- /** Whether the connector supports incremental authorization (Google
337
- * does; many don't). */
338
- incremental?: boolean;
339
- /** Env-var name holding the OAuth client_id. */
340
- clientIdEnv: string;
341
- /** Env-var name holding the OAuth client_secret. */
342
- clientSecretEnv: string;
343
- /** Optional extra params attached to the authorization URL (e.g.,
344
- * Google's `access_type=offline&prompt=consent` to obtain refresh
345
- * tokens). */
346
- extraAuthParams?: Record<string, string>;
347
- } | {
348
- kind: 'api-key';
349
- /** UI hint shown when collecting the key. */
350
- hint: string;
351
- } | {
352
- kind: 'hmac';
353
- } | {
354
- kind: 'none';
355
- };
356
- /** Thrown by `executeMutation` when upstream rejects on CAS — caught and
357
- * rewrapped by MutationGuard. */
358
- declare class ResourceContention extends Error {
359
- readonly alternatives: unknown[];
360
- readonly currentState?: unknown | undefined;
361
- readonly name = "ResourceContention";
362
- constructor(message: string, alternatives?: unknown[], currentState?: unknown | undefined);
363
- }
364
- /** Thrown when the connector finds the user's grant has been revoked or
365
- * the access token is no longer valid AND refresh failed. Surfaces to
366
- * the UI as "Reconnect required". */
367
- declare class CredentialsExpired extends Error {
368
- readonly dataSourceId: string;
369
- readonly name = "CredentialsExpired";
370
- constructor(message: string, dataSourceId: string);
371
- }
372
- interface ConnectorManifestValidationIssue {
373
- path: string;
374
- message: string;
375
- }
376
- interface ConnectorManifestValidationResult {
377
- ok: boolean;
378
- issues: ConnectorManifestValidationIssue[];
379
- }
380
- /** Validate the static connector manifest before a provider registers it.
381
- * This catches the expensive mistakes early: duplicate capability names,
382
- * mutation capabilities without CAS, authoritative fire-and-forget writes,
383
- * and invalid rate-limit specs. */
384
- declare function validateConnectorManifest(manifest: ConnectorManifest): ConnectorManifestValidationResult;
385
- declare function assertValidConnectorManifest(manifest: ConnectorManifest): void;
386
-
387
- /**
388
- * Google Calendar connector — CAS reference implementation.
389
- *
390
- * Scopes: `https://www.googleapis.com/auth/calendar` covers list/insert/
391
- * patch on the user's calendars. We could split read/write but for v1 the
392
- * single scope keeps the consent screen simple; an operator who wants
393
- * read-only-Calendar can pick a different `kind` later (`google-calendar-readonly`).
394
- *
395
- * The two capabilities the agent actually needs:
396
- *
397
- * list_availability(calendarId, timeMin, timeMax)
398
- * → {busy: [{start, end}], events: [{id, etag, start, end, summary}]}
399
- * Read; no CAS. Cheap (events.list).
400
- *
401
- * book_slot(calendarId, start, end, summary, attendees?)
402
- * → {eventId, etag}
403
- * Mutation. CAS by Calendar's own conflict-detection: we re-list
404
- * events for the requested window inside the same call, and if any
405
- * OVERLAP exists we return `conflict` with the next-3 free slots
406
- * mined from the user's freebusy, instead of inserting.
407
- *
408
- * Why pre-flight read-then-insert rather than relying on If-Match:
409
- * `events.insert` doesn't take If-Match (you can't precondition an
410
- * insert against a non-existent resource). Calendar's own
411
- * `freebusy.query` is the canonical conflict signal. The whole flow is:
412
- *
413
- * 1. freebusy.query for [start, end] on this calendarId
414
- * 2. if busy → emit ResourceContention with next-3 free slots
415
- * (computed by walking forward in 30-min steps until 3 free
416
- * windows of (end-start) duration found)
417
- * 3. else events.insert with idempotency-key as `requestId` (a Calendar
418
- * API feature that gives us per-key dedup at upstream)
419
- *
420
- * Step 3's `requestId` parameter means a retry of the same idempotency
421
- * key on the same calendar will return the original event rather than
422
- * creating a duplicate, which composes correctly with our MutationGuard's
423
- * idempotency record (which short-circuits before ever hitting upstream
424
- * on the second call). Defense-in-depth.
425
- */
426
-
427
- /** OAuth client config the factory closes over. Caller resolves these
428
- * at construction time (env, DB, secret manager — package doesn't care). */
429
- interface GoogleCalendarOptions {
430
- clientId: string;
431
- clientSecret: string;
432
- }
433
- declare function googleCalendar(opts: GoogleCalendarOptions): ConnectorAdapter;
434
-
435
- /**
436
- * @stable Google Drive connector — doc-flow-in for legal/tax/creative agents.
437
- *
438
- * Three capabilities, picked to cover "agent pulls a document the user
439
- * dropped in a folder" without trying to expose all of Drive's surface:
440
- *
441
- * list_files(folderId?, query?, pageSize?)
442
- * → {files: [{id, name, mimeType, modifiedTime, size?, md5Checksum?}], nextPageToken?}
443
- * Read. files.list with a `'<folder>' in parents` clause when folderId
444
- * is provided, otherwise the user's whole Drive scoped by Drive query.
445
- *
446
- * read_file(fileId, format?)
447
- * → {name, mimeType, content: string | base64, encoding: 'utf-8' | 'base64'}
448
- * Read. For Google-native types (Docs/Sheets/Slides) we use
449
- * `files.export` with the requested export mime; for binary types
450
- * (PDF, images, .docx) we use `files.get?alt=media` and base64 the
451
- * bytes. Caller decides what to do with each.
452
- *
453
- * watch_folder(folderId, channelId, address, ttlMs?)
454
- * → {channelId, resourceId, expiration}
455
- * Mutation (creates a push notification channel). CAS: native-idempotency
456
- * by way of the caller-supplied `channelId` — re-issuing the same
457
- * channelId returns 409, which we surface as `idempotentReplay: true`
458
- * after pulling the existing channel's `resourceId` from
459
- * `DataSource.metadata.watchedChannels[channelId]`.
460
- *
461
- * Auth: OAuth2 with `drive.readonly` (list/read) + `drive` (watch). We
462
- * scope to readonly by default and require the operator to opt into the
463
- * full-write scope only if they intend to use watch_folder. The
464
- * `requiredScopes` field on each capability gates this in the agent's
465
- * tool registry — the agent never sees `watch_folder` unless the grant
466
- * carries `drive`.
467
- *
468
- * Why no upload capability in v1: upload is a multi-part / resumable
469
- * dance that's properly its own connector pack (write-doc workflows
470
- * need an authoritative consistency model, a separate review path,
471
- * etc.). Doc-flow-in is the load-bearing case for the five product
472
- * agents — doc-flow-out lives in the appropriate kind-specific pack
473
- * (e.g., docuseal-out, gmail send_reply, sheets update_row).
474
- */
475
-
476
- /** OAuth client config the factory closes over. */
477
- interface GoogleDriveOptions {
478
- clientId: string;
479
- clientSecret: string;
480
- /** When true, request the broader `drive` scope at connect-time so
481
- * the operator can use watch_folder. Default false — request only
482
- * `drive.readonly` and gate watch_folder via `requiredScopes`. */
483
- includeWatchScope?: boolean;
484
- /** Default request timeout in ms. Applied per-fetch via AbortSignal. */
485
- timeoutMs?: number;
486
- }
487
- declare function googleDrive(opts: GoogleDriveOptions): ConnectorAdapter;
488
-
489
- /**
490
- * Google Sheets connector — live KB source + writable rows.
491
- *
492
- * The flagship for the "agent reads from a live spreadsheet" UX. The
493
- * customer points the connection at a Sheet (spreadsheetId + sheetName +
494
- * headerRow). We expose:
495
- *
496
- * list_rows(filter?, limit?)
497
- * → {rows: [{...header→cell}], nextCursor?}
498
- * Cheap; just spreadsheets.values.get with the configured range.
499
- *
500
- * query_rows(predicate)
501
- * → same shape as list_rows but with a structured filter (k=v pairs
502
- * ANDed together). Simple and explainable; no SQL.
503
- *
504
- * update_row(rowKey, patch)
505
- * → {row: {...header→cell}, updatedRange}
506
- * Mutation. CAS via Sheets' spreadsheets.values.update + a
507
- * pre-flight read of the row's revisionId-equivalent hash. Sheets
508
- * doesn't expose a per-row etag, so we synthesize one — see
509
- * `rowFingerprint`. If the fingerprint doesn't match what the agent
510
- * last read, we surface ResourceContention with the current row in
511
- * `currentState`.
512
- *
513
- * KB binding: when a Sheet is `consistencyModel: 'cache'` (the default
514
- * for spreadsheets — they're slow-moving), the system also indexes the
515
- * rows as KB chunks. The KB build pipeline calls `list_rows` and emits
516
- * one markdown page per row; on a connector-level "refresh" event the
517
- * agent's KB rebuilds.
518
- */
519
-
520
- /** OAuth client config the factory closes over. Caller resolves these
521
- * at construction time (env, DB, secret manager — package doesn't care). */
522
- interface GoogleSheetsOptions {
523
- clientId: string;
524
- clientSecret: string;
525
- }
526
- declare function googleSheets(opts: GoogleSheetsOptions): ConnectorAdapter;
527
-
528
- /**
529
- * @stable Gmail connector — email-triggered agent workflows.
530
- *
531
- * Four capabilities, picked to cover "agent reads inbox, replies, and
532
- * watches a label" without exposing all of Gmail's surface:
533
- *
534
- * list_messages(labelIds?, query?, maxResults?)
535
- * → {messages: [{id, threadId, snippet, internalDate, from, to, subject, labelIds}], nextPageToken?}
536
- * Read. `users.messages.list` + a parallel `users.messages.get` for
537
- * each id with `format=metadata` so the agent gets actionable header
538
- * fields, not just ids.
539
- *
540
- * read_message(id, format?)
541
- * → {id, threadId, from, to, subject, internalDate, body: {text?, html?}, attachments: [{filename, mimeType, attachmentId}]}
542
- * Read. `users.messages.get?format=full` then a small MIME walker that
543
- * extracts `text/plain` + `text/html` + a flat attachment manifest.
544
- * Attachment bodies are NOT inlined (could be huge) — the caller can
545
- * follow up with `get_attachment` if needed.
546
- *
547
- * send_reply(threadId, body, replyAll?, cc?)
548
- * → {id, threadId, labelIds}
549
- * Mutation. `users.messages.send` with In-Reply-To/References headers
550
- * pulled from the most recent message in the thread. CAS: native-
551
- * idempotency. Gmail does not honor an explicit idempotency-key
552
- * header, so we encode the agent's idempotency key into a
553
- * `X-Tangle-Idempotency-Key` header AND we annotate the thread with
554
- * a custom label `tangle-sent-<key>` on success — a retry can list
555
- * the label and short-circuit without re-sending. The MutationGuard
556
- * above the connector still short-circuits the common retry case
557
- * before any upstream call.
558
- *
559
- * watch_label(labelIds, topicName, ttlMs?)
560
- * → {historyId, expiration}
561
- * Mutation. `users.watch` registers a Cloud Pub/Sub topic that
562
- * receives a notification on label changes. Caller owns the Pub/Sub
563
- * topic and routes pushes into the webhook router. Note: Gmail
564
- * forces re-registration every 7 days; we surface the upstream
565
- * `expiration` so the caller can schedule a refresh.
566
- *
567
- * Auth: OAuth2 with `gmail.readonly` (list/read), `gmail.send` (send),
568
- * `gmail.modify` (watch). Caller toggles which to include via the
569
- * `scopes` option.
570
- */
571
-
572
- interface GmailOptions {
573
- clientId: string;
574
- clientSecret: string;
575
- /** Scopes requested at connect-time. Default: read + send + modify. */
576
- scopes?: string[];
577
- /** Default request timeout in ms. */
578
- timeoutMs?: number;
579
- }
580
- declare function gmail(opts: GmailOptions): ConnectorAdapter;
581
-
582
- /**
583
- * Microsoft Graph Calendar connector — the Outlook half of the
584
- * voice-agent's "book me a slot" surface.
585
- *
586
- * Mirrors the Google Calendar pattern almost line-for-line, with two
587
- * upstream-specific quirks worth calling out:
588
- *
589
- * 1. Graph exposes `@odata.etag` on every event resource AND honors
590
- * `If-Match` on `events.patch` / `events.delete`. So unlike Calendar
591
- * (insert can't be preconditioned against a non-existent resource),
592
- * we DO get real etag CAS for updates after the booking. We still
593
- * use the freebusy pre-flight for the create path, because the
594
- * "two callers grab the same slot" race happens before any event
595
- * exists.
596
- *
597
- * 2. `getSchedule` is the Graph equivalent of `freeBusy.query`. Same
598
- * shape: send `[start, end]` plus the calendar's email/UPN, get
599
- * back a `scheduleItems` list of busy windows.
600
- *
601
- * Why the same flow ports cleanly: the conflict mode is identical
602
- * ("did someone else grab this slot between read and write?"). The
603
- * mechanism — pre-flight read + idempotent insert — composes regardless
604
- * of whether upstream gives us a request-id dedup feature. Graph does
605
- * not have a `requestId` analogue on `events.create`, so we rely
606
- * exclusively on MutationGuard's idempotency-key short-circuit ABOVE
607
- * the connector. That layer prevents duplicate inserts on retry.
608
- */
609
-
610
- /** OAuth client config the factory closes over. Caller resolves these
611
- * at construction time (env, DB, secret manager — package doesn't care). */
612
- interface MicrosoftCalendarOptions {
613
- clientId: string;
614
- clientSecret: string;
615
- }
616
- declare function microsoftCalendar(opts: MicrosoftCalendarOptions): ConnectorAdapter;
617
-
618
- /**
619
- * HubSpot CRM connector — three load-bearing capabilities, picked to
620
- * cover the voice-agent's CRM hot path without trying to swallow all of
621
- * HubSpot's surface in v1.
622
- *
623
- * find_contact(email)
624
- * → {contact: {id, properties}} | {found: false}
625
- * POST /crm/v3/objects/contacts/search with an email-equality filter.
626
- * Cheap, idempotent, no CAS needed (read).
627
- *
628
- * upsert_contact(email, properties)
629
- * → {contactId, created}
630
- * Mutation. CAS strategy = native-idempotency, BUT: HubSpot's
631
- * `idempotencyKey` query param is ONLY available on the v3 *batch*
632
- * endpoints (`/crm/v3/objects/contacts/batch/upsert`). The
633
- * single-record endpoints don't honor it. We use the batch endpoint
634
- * with a single-element array to get native idempotency on retry.
635
- *
636
- * create_note(contactId, body)
637
- * → {noteId}
638
- * Mutation that logs a note engagement on a contact and associates
639
- * it. Notes are append-only — there's no conflict to detect — so we
640
- * use native-idempotency via the same batch trick on
641
- * `/crm/v3/objects/notes/batch/create`.
642
- *
643
- * Why three and not thirty: the agent's leverage on HubSpot is
644
- * "remember who I just spoke to". `find_contact` lets the agent address
645
- * a returning caller by name; `upsert_contact` captures a new one
646
- * without duplicates; `create_note` writes the call's outcome as a CRM
647
- * activity. Anything beyond these (deals, tickets, lists) lives in
648
- * Tier-2 specific kinds — keeping the manifest tight keeps the agent's
649
- * tool registry comprehensible.
650
- */
651
-
652
- /** OAuth client config the factory closes over. Caller resolves these
653
- * at construction time (env, DB, secret manager — package doesn't care). */
654
- interface HubSpotOptions {
655
- clientId: string;
656
- clientSecret: string;
657
- }
658
- declare function hubspot(opts: HubSpotOptions): ConnectorAdapter;
659
-
660
- /**
661
- * Slack connector — bot-token OAuth, three messaging-oriented capabilities.
662
- *
663
- * post_message(channel, text|blocks) → mutation; cas: 'none'
664
- * lookup_user(email) → read
665
- * list_channels(types?, limit?) → read
666
- *
667
- * Why `cas: 'none'` is acceptable here (and only here in this batch):
668
- * Slack messages are advisory — we set
669
- * `defaultConsistencyModel: 'advisory'`. The registry validator allows
670
- * `cas: 'none'` only on non-authoritative connectors precisely so that
671
- * append-only messaging surfaces don't have to invent fake CAS theatre.
672
- * The agent's planner already treats `advisory` data as informational
673
- * and does not promise outcomes based on its post results without
674
- * a separate authoritative confirm. MutationGuard's idempotency-key
675
- * dedup remains in force above the connector — a retry of the same
676
- * post_message call will short-circuit before reaching Slack.
677
- *
678
- * Auth: standard OAuth2. Slack's `/oauth.v2.access` returns a bot
679
- * `access_token` (`xoxb-…`) but does NOT return a refresh_token unless
680
- * the app has rotated tokens enabled. Bot tokens are long-lived by
681
- * default; we surface refreshToken handling but treat its absence as
682
- * normal rather than an error.
683
- */
684
-
685
- /** OAuth client config the factory closes over. Caller resolves these
686
- * at construction time (env, DB, secret manager — package doesn't care). */
687
- interface SlackOptions {
688
- clientId: string;
689
- clientSecret: string;
690
- }
691
- declare function slack(opts: SlackOptions): ConnectorAdapter;
692
-
693
- /**
694
- * Notion database connector — query + page-level CRUD against a single
695
- * connected database.
696
- *
697
- * query_database(filter?, pageSize?) → read
698
- * create_page(properties) → mutation; cas: 'native-idempotency'
699
- * update_page(pageId, properties) → mutation; cas: 'etag-if-match'
700
- *
701
- * CAS quirks worth flagging:
702
- *
703
- * 1. Notion added support for the `Idempotency-Key` HTTP header on
704
- * mutating requests. We forward our SDK's idempotency key on
705
- * create_page, which gives at-most-once semantics under the same
706
- * key for ~24h. MutationGuard's record short-circuits above us;
707
- * Notion's dedup is the second line of defense.
708
- *
709
- * 2. Notion does NOT expose a per-page etag the way Graph does. The
710
- * canonical drift signal is `last_edited_time` (RFC3339). Our
711
- * `update_page` capability accepts an `expectedLastEditedTime` arg;
712
- * if supplied, we GET the page first and compare. Mismatch →
713
- * ResourceContention with the current page state. Conflict-free
714
- * callers can omit the field (last-write-wins, the Notion default).
715
- *
716
- * Auth: standard OAuth2. Notion's token endpoint follows RFC 6749 with
717
- * one twist — the workspace_id and bot_id come back in the response and
718
- * we stash them in `metadata` so the agent can address resources by
719
- * workspace where useful.
720
- */
721
-
722
- /** OAuth client config the factory closes over. Caller resolves these
723
- * at construction time (env, DB, secret manager — package doesn't care). */
724
- interface NotionDatabaseOptions {
725
- clientId: string;
726
- clientSecret: string;
727
- }
728
- declare function notionDatabase(opts: NotionDatabaseOptions): ConnectorAdapter;
729
-
730
- /**
731
- * @stable DocuSeal connector — e-signature flows for legal/tax agents.
732
- *
733
- * Three capabilities + inbound webhook surface:
734
- *
735
- * create_submission(templateId, submitters, sendEmail?)
736
- * → {submissionId, submitters: [{email, slug, url}], status: 'pending'}
737
- * Mutation. POST /api/submissions with an explicit
738
- * `external_id = idempotencyKey` so DocuSeal will dedupe the
739
- * submission across our retries (verified against DocuSeal's
740
- * external_id uniqueness behavior).
741
- *
742
- * get_submission(submissionId)
743
- * → {submissionId, status, completedAt?, submitters: [{email, status, completedAt?, slug, url}]}
744
- * Read. GET /api/submissions/:id, normalized so the agent doesn't
745
- * have to map DocuSeal's per-submitter status (`awaiting`, `sent`,
746
- * `opened`, `completed`, `declined`) onto a smaller taxonomy.
747
- *
748
- * void_submission(submissionId, reason?)
749
- * → {submissionId, status: 'voided', voidedAt}
750
- * Mutation. DELETE /api/submissions/:id with `reason` carried as a
751
- * header. CAS: etag-if-match — DocuSeal emits an updated_at value we
752
- * thread through as ETag so two concurrent voids don't race.
753
- *
754
- * handleInboundEvent (webhook surface)
755
- * DocuSeal pushes events to a customer-configured URL. We verify a
756
- * HMAC-SHA256 signature over the raw body keyed by the per-account
757
- * webhook secret (`X-Docuseal-Signature` header, lowercase hex). The
758
- * adapter parses the event shape and emits a normalized
759
- * `InboundEvent` row (eventType = `docuseal.submission.completed`,
760
- * etc.). Replay protection: DocuSeal does not currently sign a
761
- * timestamp, so we recommend the receiver pin a per-event-id idempotency
762
- * row (the `event_id` field on every push payload).
763
- *
764
- * Auth: API key (DocuSeal personal API key — every endpoint requires it
765
- * via the `X-Auth-Token` header). Webhook secret is a separate
766
- * credential delivered via the same DataSource — we accept either
767
- * `kind: 'api-key'` (action surface) or `kind: 'custom'` carrying
768
- * `apiKey` + `webhookSecret` (action + webhook on one connection).
769
- *
770
- * Error taxonomy (mapped via integrations/errors.ts):
771
- * 401 → provider_auth_failed (CredentialsExpired)
772
- * 404 → action_not_found (Error) — submission id is unknown
773
- * 409 → action_denied / ResourceContention when status guards
774
- * 429 → provider_rate_limited (status: 'rate-limited' result)
775
- * 5xx → provider_unavailable
776
- */
777
-
778
- interface DocuSealOptions {
779
- /** Override the DocuSeal API base URL (self-hosted deployments). */
780
- baseUrl?: string;
781
- /** Default request timeout in ms. */
782
- timeoutMs?: number;
783
- }
784
- declare function docuseal(opts?: DocuSealOptions): ConnectorAdapter;
785
-
786
- type RestCredentialPlacement = {
787
- kind: 'bearer';
788
- } | {
789
- kind: 'header';
790
- header: string;
791
- prefix?: string;
792
- } | {
793
- kind: 'query';
794
- parameter: string;
795
- };
796
- interface RestConnectorSpec {
797
- kind: string;
798
- displayName: string;
799
- description: string;
800
- auth: ConnectorAdapter['manifest']['auth'];
801
- category: ConnectorAdapter['manifest']['category'];
802
- defaultConsistencyModel: ConnectorAdapter['manifest']['defaultConsistencyModel'];
803
- baseUrl: string | {
804
- metadataKey: string;
805
- fallback?: string;
806
- };
807
- credentialPlacement?: RestCredentialPlacement;
808
- defaultHeaders?: Record<string, string>;
809
- capabilities: RestOperationSpec[];
810
- test?: RestRequestSpec;
811
- }
812
- interface RestOperationSpec {
813
- name: string;
814
- class: 'read' | 'mutation';
815
- description: string;
816
- parameters: Record<string, unknown>;
817
- requiredScopes?: string[];
818
- request: RestRequestSpec;
819
- cas?: 'etag-if-match' | 'native-idempotency' | 'optimistic-read-verify' | 'none';
820
- externalEffect?: boolean;
821
- }
822
- interface RestRequestSpec {
823
- method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
824
- path: string;
825
- query?: Record<string, string | number | boolean | undefined>;
826
- headers?: Record<string, string>;
827
- body?: 'args' | string | Record<string, unknown>;
828
- }
829
- declare function declarativeRestConnector(spec: RestConnectorSpec): ConnectorAdapter;
830
-
831
- /**
832
- * Twilio SMS connector — outbound texts + recent-message lookup. The
833
- * agent's "send the caller a confirmation link" surface.
834
- *
835
- * Auth: HTTP Basic (Account SID + Auth Token). Twilio's API key auth
836
- * also supports SID/Secret pairs; we accept either by treating the
837
- * stored apiKey envelope as `accountSid:authToken` (or
838
- * `accountSid:keySid:secret`) — the connector parses it at call time.
839
- *
840
- * send_sms(to, body)
841
- * Mutation. CAS = native-idempotency. Twilio added the
842
- * `Idempotency-Key` HTTP header to POST /Messages in 2024 — same
843
- * key + same args within 24h returns the original Message resource
844
- * instead of sending a second SMS. MutationGuard's record short-
845
- * circuits before us; Twilio's own dedup is defense-in-depth.
846
- *
847
- * lookup_number(phoneNumber)
848
- * Read. Hits /v1/PhoneNumbers/{e164} on Lookup API. Confirms the
849
- * number is real, returns carrier info if the caller has Lookup
850
- * enabled on their account.
851
- *
852
- * find_recent_messages(toOrFrom?, limit?)
853
- * Read. Returns the most recent Messages on the account, optionally
854
- * filtered by To/From. Useful for "did the confirmation actually
855
- * send?" introspection inside an agent run.
856
- */
857
-
858
- declare const twilioSmsConnector: ConnectorAdapter;
859
-
860
- /**
861
- * Stripe pack connector — single connector kind packing customer +
862
- * invoice + checkout + subscription management capabilities, validating
863
- * the "connector pack" concept (one auth handshake, multiple related
864
- * capabilities) without exploding the registry into `stripe-customers`,
865
- * `stripe-checkout`, `stripe-invoices`, `stripe-subscriptions` n-tuples.
866
- *
867
- * find_customer(email) → read; CAS n/a
868
- * list_subscriptions(customerId, status?) → read; CAS n/a
869
- * create_invoice(customerId, items) → mutation; cas: 'native-idempotency'
870
- * create_checkout_session(...) → mutation; cas: 'native-idempotency'
871
- * cancel_subscription(subscriptionId, atPeriodEnd?) → mutation; cas: 'native-idempotency'
872
- * create_billing_portal_session(customerId, returnUrl) → mutation; cas: 'native-idempotency'
873
- *
874
- * Auth: API key (Stripe restricted key). Operator pastes the key into
875
- * the Connections UI. We never see their account password / OAuth flow;
876
- * Stripe restricted keys are the customer's responsibility (they pick
877
- * which permissions the key carries). The kind exposes a webhook URL
878
- * post-connect for the operator to paste into the Stripe dashboard —
879
- * we'll wire the receiver to P-3's inbound webhook surface in a later
880
- * commit. That URL is returned in `metadata.webhookUrl` so the UI can
881
- * render it.
882
- *
883
- * Why this is the textbook example of `cas: 'native-idempotency'`:
884
- * Stripe's `Idempotency-Key` HTTP header is THE reference implementation
885
- * of native idempotency. Same key + same args within 24h returns the
886
- * stored response (Stripe's words, not ours). Same key + different args
887
- * → 400 with `idempotency_error`. We forward the SDK's idempotency key
888
- * directly. MutationGuard short-circuits before us on retry; Stripe's
889
- * own dedup is the second line of defense.
890
- */
891
-
892
- declare const stripePackConnector: ConnectorAdapter;
893
-
894
- /**
895
- * Universal webhook connector — the long-tail escape hatch.
896
- *
897
- * The user declares a target URL + a JSON-schema for the request body
898
- * the agent should send, plus an optional shared secret. We sign every
899
- * outbound POST with HMAC-SHA256 over `timestamp.body` and forward the
900
- * agent's idempotency key as a header. The receiving system enforces
901
- * its own idempotency.
902
- *
903
- * One adapter, two capabilities. Both arity-1 — `body` is whatever JSON
904
- * the agent's planner constructs from the operator-defined schema (which
905
- * lives in DataSource.metadata.requestSchema). The agent's planner reads
906
- * that schema at request time and constructs valid args.
907
- *
908
- * Why one connector covers 50 systems badly and 1 system well: the agent
909
- * gets a generic "send_event" tool that doesn't *know* what the upstream
910
- * does with the payload. That's fine for fire-and-forget event posting
911
- * (Zapier-style); it's wrong for booking against a calendar where you
912
- * need conflict-resolution. So webhook's `post_event` capability is
913
- * marked `cas: 'native-idempotency'` (we forward the key — the receiver
914
- * MUST honor it) and `defaultConsistencyModel: 'advisory'`. Anyone
915
- * needing real CAS uses a kind-specific connector (Calendar, Sheets, ...).
916
- */
917
-
918
- declare const webhookConnector: ConnectorAdapter;
919
-
920
- /**
921
- * Stripe inbound-webhook receiver — push-only side of a Stripe connector.
922
- *
923
- * The full Stripe connector (charges/customers/invoices read+mutation) is
924
- * tracked in INTEGRATIONS.md as separate `stripe-customers` / `stripe-invoices`
925
- * rows. This adapter only ships the inbound surface today: receive a push,
926
- * verify the signature, persist one `InboundEvent` per Stripe event so the
927
- * agent's runtime can react (e.g. payment_failed → outbound dunning call).
928
- *
929
- * This connector is for the connected account owner: they paste their
930
- * `whsec_*` and the consuming product listens on a per-data-source URL such
931
- * as /api/webhooks/inbound/stripe/:dataSourceId.
932
- *
933
- * Signature scheme: Stripe's `t=<unix>,v1=<hmac>` header. HMAC is
934
- * sha256(`${t}.${rawBody}`) keyed by the customer's webhook secret. We use
935
- * `timingSafeEqual` to defeat timing oracles and bound timestamp skew at
936
- * 5 minutes (Stripe's recommendation) to thwart replay against captured
937
- * signatures.
938
- */
939
-
940
- declare const stripeWebhookReceiverConnector: ConnectorAdapter;
941
-
942
- /**
943
- * Slack Events API inbound receiver.
944
- *
945
- * Slack sends two distinct request shapes to the same webhook URL:
946
- *
947
- * 1. `url_verification` — a one-off handshake during app-config. The body
948
- * contains a `challenge` string we MUST echo back as the response body
949
- * (Slack's app-config UI fails the URL otherwise). No InboundEvent is
950
- * persisted for this — it's an infrastructure ping, not a user event.
951
- *
952
- * 2. `event_callback` — every actual workspace event (message posted,
953
- * reaction added, channel created, …). We persist one InboundEvent
954
- * keyed by `event_id` so a Slack retry (Slack retries 3 times on any
955
- * non-2xx) is deduped at the unique constraint, not after we've
956
- * double-processed.
957
- *
958
- * Signature scheme: `v0=<hmac(sha256, "v0:<timestamp>:<rawBody>")>` keyed by
959
- * the app's signing secret. Header `X-Slack-Request-Timestamp` carries the
960
- * timestamp; we reject anything older than 5 minutes (Slack's recommendation)
961
- * to bound replay risk.
962
- */
963
-
964
- declare const slackEventsConnector: ConnectorAdapter;
965
-
966
- declare const githubConnector: ConnectorAdapter;
967
-
968
- declare const gitlabConnector: ConnectorAdapter;
969
-
970
- declare const airtableConnector: ConnectorAdapter;
971
-
972
- declare const asanaConnector: ConnectorAdapter;
973
-
974
- declare const salesforceConnector: ConnectorAdapter;
975
-
976
- export { stripePackConnector as $, type AuthSpec as A, asanaConnector as B, type ConnectorAdapter as C, type DataSourceMetadata as D, type EventHandlerResult as E, assertValidConnectorManifest as F, type GmailOptions as G, type HubSpotOptions as H, type InboundEvent as I, declarativeRestConnector as J, docuseal as K, githubConnector as L, type MicrosoftCalendarOptions as M, type NotionDatabaseOptions as N, gitlabConnector as O, gmail as P, googleCalendar as Q, type ResolvedDataSource as R, type SlackOptions as S, googleDrive as T, googleSheets as U, hubspot as V, microsoftCalendar as W, notionDatabase as X, salesforceConnector as Y, slack as Z, slackEventsConnector as _, type ConnectorCredentials as a, stripeWebhookReceiverConnector as a0, twilioSmsConnector as a1, validateConnectorManifest as a2, webhookConnector as a3, type CASStrategy as b, type Capability as c, type CapabilityClass as d, type CapabilityMutation as e, type CapabilityMutationResult as f, type CapabilityParameterSchema as g, type CapabilityRead as h, type CapabilityReadResult as i, type ConnectorInvocation as j, type ConnectorManifest as k, type ConnectorManifestValidationIssue as l, type ConnectorManifestValidationResult as m, type ConsistencyModel as n, CredentialsExpired as o, type DocuSealOptions as p, type GoogleCalendarOptions as q, type GoogleDriveOptions as r, type GoogleSheetsOptions as s, type RateLimitSpec as t, ResourceContention as u, type RestConnectorSpec as v, type RestCredentialPlacement as w, type RestOperationSpec as x, type RestRequestSpec as y, airtableConnector as z };