@tangle-network/agent-integrations 0.26.0 → 0.27.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 (38) hide show
  1. package/dist/bin/tangle-catalog-runtime.js +5 -2
  2. package/dist/bin/tangle-catalog-runtime.js.map +1 -1
  3. package/dist/catalog.d.ts +4 -1
  4. package/dist/catalog.js +5 -2
  5. package/dist/chunk-ATYHZXLL.js +457 -0
  6. package/dist/chunk-ATYHZXLL.js.map +1 -0
  7. package/dist/{chunk-ALCIWTIR.js → chunk-ICSBYCE2.js} +27 -1
  8. package/dist/chunk-ICSBYCE2.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/connect/index.d.ts +112 -0
  16. package/dist/connect/index.js +14 -0
  17. package/dist/connect/index.js.map +1 -0
  18. package/dist/connectors/adapters/index.d.ts +593 -1
  19. package/dist/connectors/adapters/index.js +15 -1
  20. package/dist/connectors/index.d.ts +2 -1
  21. package/dist/connectors/index.js +19 -5
  22. package/dist/index.d.ts +5 -2
  23. package/dist/index.js +42 -6
  24. package/dist/middleware/index.d.ts +137 -0
  25. package/dist/middleware/index.js +14 -0
  26. package/dist/middleware/index.js.map +1 -0
  27. package/dist/registry.d.ts +28 -2
  28. package/dist/registry.js +5 -2
  29. package/dist/runtime.d.ts +4 -1
  30. package/dist/runtime.js +5 -2
  31. package/dist/specs.d.ts +4 -1
  32. package/dist/tangle-catalog-runtime.d.ts +4 -1
  33. package/dist/tangle-catalog-runtime.js +5 -2
  34. package/dist/tangle-id-CTU4kGId.d.ts +553 -0
  35. package/package.json +11 -1
  36. package/dist/chunk-ALCIWTIR.js.map +0 -1
  37. package/dist/chunk-GA4VTE3U.js.map +0 -1
  38. package/dist/index-D4D4CEKX.d.ts +0 -976
@@ -1 +1,593 @@
1
- export { p as DocuSealOptions, G as GmailOptions, q as GoogleCalendarOptions, r as GoogleDriveOptions, s as GoogleSheetsOptions, H as HubSpotOptions, M as MicrosoftCalendarOptions, N as NotionDatabaseOptions, v as RestConnectorSpec, w as RestCredentialPlacement, x as RestOperationSpec, y as RestRequestSpec, S as SlackOptions, z as airtableConnector, B as asanaConnector, J as declarativeRestConnector, K as docuseal, L as githubConnector, O as gitlabConnector, P as gmail, Q as googleCalendar, T as googleDrive, U as googleSheets, V as hubspot, W as microsoftCalendar, X as notionDatabase, Y as salesforceConnector, Z as slack, _ as slackEventsConnector, $ as stripePackConnector, a0 as stripeWebhookReceiverConnector, a1 as twilioSmsConnector, a3 as webhookConnector } from '../../index-D4D4CEKX.js';
1
+ import { C as ConnectorAdapter } from '../../tangle-id-CTU4kGId.js';
2
+ export { D as DEFAULT_TANGLE_PLATFORM_URL, v as TANGLE_API_KEY_PREFIX, w as TANGLE_SERVICE_TOKEN_PREFIX, b as TangleIdentityClient, T as TangleIdentityOptions, x as TangleIdentityUnreachableError, c as TangleTokenVerifyFailure, y as TangleTokenVerifyResult, a as TangleUserSummary, z as TangleWorkspaceSummary, F as createTangleIdentityClient, G as tangleIdentity } from '../../tangle-id-CTU4kGId.js';
3
+
4
+ /**
5
+ * Google Calendar connector — CAS reference implementation.
6
+ *
7
+ * Scopes: `https://www.googleapis.com/auth/calendar` covers list/insert/
8
+ * patch on the user's calendars. We could split read/write but for v1 the
9
+ * single scope keeps the consent screen simple; an operator who wants
10
+ * read-only-Calendar can pick a different `kind` later (`google-calendar-readonly`).
11
+ *
12
+ * The two capabilities the agent actually needs:
13
+ *
14
+ * list_availability(calendarId, timeMin, timeMax)
15
+ * → {busy: [{start, end}], events: [{id, etag, start, end, summary}]}
16
+ * Read; no CAS. Cheap (events.list).
17
+ *
18
+ * book_slot(calendarId, start, end, summary, attendees?)
19
+ * → {eventId, etag}
20
+ * Mutation. CAS by Calendar's own conflict-detection: we re-list
21
+ * events for the requested window inside the same call, and if any
22
+ * OVERLAP exists we return `conflict` with the next-3 free slots
23
+ * mined from the user's freebusy, instead of inserting.
24
+ *
25
+ * Why pre-flight read-then-insert rather than relying on If-Match:
26
+ * `events.insert` doesn't take If-Match (you can't precondition an
27
+ * insert against a non-existent resource). Calendar's own
28
+ * `freebusy.query` is the canonical conflict signal. The whole flow is:
29
+ *
30
+ * 1. freebusy.query for [start, end] on this calendarId
31
+ * 2. if busy → emit ResourceContention with next-3 free slots
32
+ * (computed by walking forward in 30-min steps until 3 free
33
+ * windows of (end-start) duration found)
34
+ * 3. else events.insert with idempotency-key as `requestId` (a Calendar
35
+ * API feature that gives us per-key dedup at upstream)
36
+ *
37
+ * Step 3's `requestId` parameter means a retry of the same idempotency
38
+ * key on the same calendar will return the original event rather than
39
+ * creating a duplicate, which composes correctly with our MutationGuard's
40
+ * idempotency record (which short-circuits before ever hitting upstream
41
+ * on the second call). Defense-in-depth.
42
+ */
43
+
44
+ /** OAuth client config the factory closes over. Caller resolves these
45
+ * at construction time (env, DB, secret manager — package doesn't care). */
46
+ interface GoogleCalendarOptions {
47
+ clientId: string;
48
+ clientSecret: string;
49
+ }
50
+ declare function googleCalendar(opts: GoogleCalendarOptions): ConnectorAdapter;
51
+
52
+ /**
53
+ * @stable Google Drive connector — doc-flow-in for legal/tax/creative agents.
54
+ *
55
+ * Three capabilities, picked to cover "agent pulls a document the user
56
+ * dropped in a folder" without trying to expose all of Drive's surface:
57
+ *
58
+ * list_files(folderId?, query?, pageSize?)
59
+ * → {files: [{id, name, mimeType, modifiedTime, size?, md5Checksum?}], nextPageToken?}
60
+ * Read. files.list with a `'<folder>' in parents` clause when folderId
61
+ * is provided, otherwise the user's whole Drive scoped by Drive query.
62
+ *
63
+ * read_file(fileId, format?)
64
+ * → {name, mimeType, content: string | base64, encoding: 'utf-8' | 'base64'}
65
+ * Read. For Google-native types (Docs/Sheets/Slides) we use
66
+ * `files.export` with the requested export mime; for binary types
67
+ * (PDF, images, .docx) we use `files.get?alt=media` and base64 the
68
+ * bytes. Caller decides what to do with each.
69
+ *
70
+ * watch_folder(folderId, channelId, address, ttlMs?)
71
+ * → {channelId, resourceId, expiration}
72
+ * Mutation (creates a push notification channel). CAS: native-idempotency
73
+ * by way of the caller-supplied `channelId` — re-issuing the same
74
+ * channelId returns 409, which we surface as `idempotentReplay: true`
75
+ * after pulling the existing channel's `resourceId` from
76
+ * `DataSource.metadata.watchedChannels[channelId]`.
77
+ *
78
+ * Auth: OAuth2 with `drive.readonly` (list/read) + `drive` (watch). We
79
+ * scope to readonly by default and require the operator to opt into the
80
+ * full-write scope only if they intend to use watch_folder. The
81
+ * `requiredScopes` field on each capability gates this in the agent's
82
+ * tool registry — the agent never sees `watch_folder` unless the grant
83
+ * carries `drive`.
84
+ *
85
+ * Why no upload capability in v1: upload is a multi-part / resumable
86
+ * dance that's properly its own connector pack (write-doc workflows
87
+ * need an authoritative consistency model, a separate review path,
88
+ * etc.). Doc-flow-in is the load-bearing case for the five product
89
+ * agents — doc-flow-out lives in the appropriate kind-specific pack
90
+ * (e.g., docuseal-out, gmail send_reply, sheets update_row).
91
+ */
92
+
93
+ /** OAuth client config the factory closes over. */
94
+ interface GoogleDriveOptions {
95
+ clientId: string;
96
+ clientSecret: string;
97
+ /** When true, request the broader `drive` scope at connect-time so
98
+ * the operator can use watch_folder. Default false — request only
99
+ * `drive.readonly` and gate watch_folder via `requiredScopes`. */
100
+ includeWatchScope?: boolean;
101
+ /** Default request timeout in ms. Applied per-fetch via AbortSignal. */
102
+ timeoutMs?: number;
103
+ }
104
+ declare function googleDrive(opts: GoogleDriveOptions): ConnectorAdapter;
105
+
106
+ /**
107
+ * Google Sheets connector — live KB source + writable rows.
108
+ *
109
+ * The flagship for the "agent reads from a live spreadsheet" UX. The
110
+ * customer points the connection at a Sheet (spreadsheetId + sheetName +
111
+ * headerRow). We expose:
112
+ *
113
+ * list_rows(filter?, limit?)
114
+ * → {rows: [{...header→cell}], nextCursor?}
115
+ * Cheap; just spreadsheets.values.get with the configured range.
116
+ *
117
+ * query_rows(predicate)
118
+ * → same shape as list_rows but with a structured filter (k=v pairs
119
+ * ANDed together). Simple and explainable; no SQL.
120
+ *
121
+ * update_row(rowKey, patch)
122
+ * → {row: {...header→cell}, updatedRange}
123
+ * Mutation. CAS via Sheets' spreadsheets.values.update + a
124
+ * pre-flight read of the row's revisionId-equivalent hash. Sheets
125
+ * doesn't expose a per-row etag, so we synthesize one — see
126
+ * `rowFingerprint`. If the fingerprint doesn't match what the agent
127
+ * last read, we surface ResourceContention with the current row in
128
+ * `currentState`.
129
+ *
130
+ * KB binding: when a Sheet is `consistencyModel: 'cache'` (the default
131
+ * for spreadsheets — they're slow-moving), the system also indexes the
132
+ * rows as KB chunks. The KB build pipeline calls `list_rows` and emits
133
+ * one markdown page per row; on a connector-level "refresh" event the
134
+ * agent's KB rebuilds.
135
+ */
136
+
137
+ /** OAuth client config the factory closes over. Caller resolves these
138
+ * at construction time (env, DB, secret manager — package doesn't care). */
139
+ interface GoogleSheetsOptions {
140
+ clientId: string;
141
+ clientSecret: string;
142
+ }
143
+ declare function googleSheets(opts: GoogleSheetsOptions): ConnectorAdapter;
144
+
145
+ /**
146
+ * @stable Gmail connector — email-triggered agent workflows.
147
+ *
148
+ * Four capabilities, picked to cover "agent reads inbox, replies, and
149
+ * watches a label" without exposing all of Gmail's surface:
150
+ *
151
+ * list_messages(labelIds?, query?, maxResults?)
152
+ * → {messages: [{id, threadId, snippet, internalDate, from, to, subject, labelIds}], nextPageToken?}
153
+ * Read. `users.messages.list` + a parallel `users.messages.get` for
154
+ * each id with `format=metadata` so the agent gets actionable header
155
+ * fields, not just ids.
156
+ *
157
+ * read_message(id, format?)
158
+ * → {id, threadId, from, to, subject, internalDate, body: {text?, html?}, attachments: [{filename, mimeType, attachmentId}]}
159
+ * Read. `users.messages.get?format=full` then a small MIME walker that
160
+ * extracts `text/plain` + `text/html` + a flat attachment manifest.
161
+ * Attachment bodies are NOT inlined (could be huge) — the caller can
162
+ * follow up with `get_attachment` if needed.
163
+ *
164
+ * send_reply(threadId, body, replyAll?, cc?)
165
+ * → {id, threadId, labelIds}
166
+ * Mutation. `users.messages.send` with In-Reply-To/References headers
167
+ * pulled from the most recent message in the thread. CAS: native-
168
+ * idempotency. Gmail does not honor an explicit idempotency-key
169
+ * header, so we encode the agent's idempotency key into a
170
+ * `X-Tangle-Idempotency-Key` header AND we annotate the thread with
171
+ * a custom label `tangle-sent-<key>` on success — a retry can list
172
+ * the label and short-circuit without re-sending. The MutationGuard
173
+ * above the connector still short-circuits the common retry case
174
+ * before any upstream call.
175
+ *
176
+ * watch_label(labelIds, topicName, ttlMs?)
177
+ * → {historyId, expiration}
178
+ * Mutation. `users.watch` registers a Cloud Pub/Sub topic that
179
+ * receives a notification on label changes. Caller owns the Pub/Sub
180
+ * topic and routes pushes into the webhook router. Note: Gmail
181
+ * forces re-registration every 7 days; we surface the upstream
182
+ * `expiration` so the caller can schedule a refresh.
183
+ *
184
+ * Auth: OAuth2 with `gmail.readonly` (list/read), `gmail.send` (send),
185
+ * `gmail.modify` (watch). Caller toggles which to include via the
186
+ * `scopes` option.
187
+ */
188
+
189
+ interface GmailOptions {
190
+ clientId: string;
191
+ clientSecret: string;
192
+ /** Scopes requested at connect-time. Default: read + send + modify. */
193
+ scopes?: string[];
194
+ /** Default request timeout in ms. */
195
+ timeoutMs?: number;
196
+ }
197
+ declare function gmail(opts: GmailOptions): ConnectorAdapter;
198
+
199
+ /**
200
+ * Microsoft Graph Calendar connector — the Outlook half of the
201
+ * voice-agent's "book me a slot" surface.
202
+ *
203
+ * Mirrors the Google Calendar pattern almost line-for-line, with two
204
+ * upstream-specific quirks worth calling out:
205
+ *
206
+ * 1. Graph exposes `@odata.etag` on every event resource AND honors
207
+ * `If-Match` on `events.patch` / `events.delete`. So unlike Calendar
208
+ * (insert can't be preconditioned against a non-existent resource),
209
+ * we DO get real etag CAS for updates after the booking. We still
210
+ * use the freebusy pre-flight for the create path, because the
211
+ * "two callers grab the same slot" race happens before any event
212
+ * exists.
213
+ *
214
+ * 2. `getSchedule` is the Graph equivalent of `freeBusy.query`. Same
215
+ * shape: send `[start, end]` plus the calendar's email/UPN, get
216
+ * back a `scheduleItems` list of busy windows.
217
+ *
218
+ * Why the same flow ports cleanly: the conflict mode is identical
219
+ * ("did someone else grab this slot between read and write?"). The
220
+ * mechanism — pre-flight read + idempotent insert — composes regardless
221
+ * of whether upstream gives us a request-id dedup feature. Graph does
222
+ * not have a `requestId` analogue on `events.create`, so we rely
223
+ * exclusively on MutationGuard's idempotency-key short-circuit ABOVE
224
+ * the connector. That layer prevents duplicate inserts on retry.
225
+ */
226
+
227
+ /** OAuth client config the factory closes over. Caller resolves these
228
+ * at construction time (env, DB, secret manager — package doesn't care). */
229
+ interface MicrosoftCalendarOptions {
230
+ clientId: string;
231
+ clientSecret: string;
232
+ }
233
+ declare function microsoftCalendar(opts: MicrosoftCalendarOptions): ConnectorAdapter;
234
+
235
+ /**
236
+ * HubSpot CRM connector — three load-bearing capabilities, picked to
237
+ * cover the voice-agent's CRM hot path without trying to swallow all of
238
+ * HubSpot's surface in v1.
239
+ *
240
+ * find_contact(email)
241
+ * → {contact: {id, properties}} | {found: false}
242
+ * POST /crm/v3/objects/contacts/search with an email-equality filter.
243
+ * Cheap, idempotent, no CAS needed (read).
244
+ *
245
+ * upsert_contact(email, properties)
246
+ * → {contactId, created}
247
+ * Mutation. CAS strategy = native-idempotency, BUT: HubSpot's
248
+ * `idempotencyKey` query param is ONLY available on the v3 *batch*
249
+ * endpoints (`/crm/v3/objects/contacts/batch/upsert`). The
250
+ * single-record endpoints don't honor it. We use the batch endpoint
251
+ * with a single-element array to get native idempotency on retry.
252
+ *
253
+ * create_note(contactId, body)
254
+ * → {noteId}
255
+ * Mutation that logs a note engagement on a contact and associates
256
+ * it. Notes are append-only — there's no conflict to detect — so we
257
+ * use native-idempotency via the same batch trick on
258
+ * `/crm/v3/objects/notes/batch/create`.
259
+ *
260
+ * Why three and not thirty: the agent's leverage on HubSpot is
261
+ * "remember who I just spoke to". `find_contact` lets the agent address
262
+ * a returning caller by name; `upsert_contact` captures a new one
263
+ * without duplicates; `create_note` writes the call's outcome as a CRM
264
+ * activity. Anything beyond these (deals, tickets, lists) lives in
265
+ * Tier-2 specific kinds — keeping the manifest tight keeps the agent's
266
+ * tool registry comprehensible.
267
+ */
268
+
269
+ /** OAuth client config the factory closes over. Caller resolves these
270
+ * at construction time (env, DB, secret manager — package doesn't care). */
271
+ interface HubSpotOptions {
272
+ clientId: string;
273
+ clientSecret: string;
274
+ }
275
+ declare function hubspot(opts: HubSpotOptions): ConnectorAdapter;
276
+
277
+ /**
278
+ * Slack connector — bot-token OAuth, three messaging-oriented capabilities.
279
+ *
280
+ * post_message(channel, text|blocks) → mutation; cas: 'none'
281
+ * lookup_user(email) → read
282
+ * list_channels(types?, limit?) → read
283
+ *
284
+ * Why `cas: 'none'` is acceptable here (and only here in this batch):
285
+ * Slack messages are advisory — we set
286
+ * `defaultConsistencyModel: 'advisory'`. The registry validator allows
287
+ * `cas: 'none'` only on non-authoritative connectors precisely so that
288
+ * append-only messaging surfaces don't have to invent fake CAS theatre.
289
+ * The agent's planner already treats `advisory` data as informational
290
+ * and does not promise outcomes based on its post results without
291
+ * a separate authoritative confirm. MutationGuard's idempotency-key
292
+ * dedup remains in force above the connector — a retry of the same
293
+ * post_message call will short-circuit before reaching Slack.
294
+ *
295
+ * Auth: standard OAuth2. Slack's `/oauth.v2.access` returns a bot
296
+ * `access_token` (`xoxb-…`) but does NOT return a refresh_token unless
297
+ * the app has rotated tokens enabled. Bot tokens are long-lived by
298
+ * default; we surface refreshToken handling but treat its absence as
299
+ * normal rather than an error.
300
+ */
301
+
302
+ /** OAuth client config the factory closes over. Caller resolves these
303
+ * at construction time (env, DB, secret manager — package doesn't care). */
304
+ interface SlackOptions {
305
+ clientId: string;
306
+ clientSecret: string;
307
+ }
308
+ declare function slack(opts: SlackOptions): ConnectorAdapter;
309
+
310
+ /**
311
+ * Notion database connector — query + page-level CRUD against a single
312
+ * connected database.
313
+ *
314
+ * query_database(filter?, pageSize?) → read
315
+ * create_page(properties) → mutation; cas: 'native-idempotency'
316
+ * update_page(pageId, properties) → mutation; cas: 'etag-if-match'
317
+ *
318
+ * CAS quirks worth flagging:
319
+ *
320
+ * 1. Notion added support for the `Idempotency-Key` HTTP header on
321
+ * mutating requests. We forward our SDK's idempotency key on
322
+ * create_page, which gives at-most-once semantics under the same
323
+ * key for ~24h. MutationGuard's record short-circuits above us;
324
+ * Notion's dedup is the second line of defense.
325
+ *
326
+ * 2. Notion does NOT expose a per-page etag the way Graph does. The
327
+ * canonical drift signal is `last_edited_time` (RFC3339). Our
328
+ * `update_page` capability accepts an `expectedLastEditedTime` arg;
329
+ * if supplied, we GET the page first and compare. Mismatch →
330
+ * ResourceContention with the current page state. Conflict-free
331
+ * callers can omit the field (last-write-wins, the Notion default).
332
+ *
333
+ * Auth: standard OAuth2. Notion's token endpoint follows RFC 6749 with
334
+ * one twist — the workspace_id and bot_id come back in the response and
335
+ * we stash them in `metadata` so the agent can address resources by
336
+ * workspace where useful.
337
+ */
338
+
339
+ /** OAuth client config the factory closes over. Caller resolves these
340
+ * at construction time (env, DB, secret manager — package doesn't care). */
341
+ interface NotionDatabaseOptions {
342
+ clientId: string;
343
+ clientSecret: string;
344
+ }
345
+ declare function notionDatabase(opts: NotionDatabaseOptions): ConnectorAdapter;
346
+
347
+ /**
348
+ * @stable DocuSeal connector — e-signature flows for legal/tax agents.
349
+ *
350
+ * Three capabilities + inbound webhook surface:
351
+ *
352
+ * create_submission(templateId, submitters, sendEmail?)
353
+ * → {submissionId, submitters: [{email, slug, url}], status: 'pending'}
354
+ * Mutation. POST /api/submissions with an explicit
355
+ * `external_id = idempotencyKey` so DocuSeal will dedupe the
356
+ * submission across our retries (verified against DocuSeal's
357
+ * external_id uniqueness behavior).
358
+ *
359
+ * get_submission(submissionId)
360
+ * → {submissionId, status, completedAt?, submitters: [{email, status, completedAt?, slug, url}]}
361
+ * Read. GET /api/submissions/:id, normalized so the agent doesn't
362
+ * have to map DocuSeal's per-submitter status (`awaiting`, `sent`,
363
+ * `opened`, `completed`, `declined`) onto a smaller taxonomy.
364
+ *
365
+ * void_submission(submissionId, reason?)
366
+ * → {submissionId, status: 'voided', voidedAt}
367
+ * Mutation. DELETE /api/submissions/:id with `reason` carried as a
368
+ * header. CAS: etag-if-match — DocuSeal emits an updated_at value we
369
+ * thread through as ETag so two concurrent voids don't race.
370
+ *
371
+ * handleInboundEvent (webhook surface)
372
+ * DocuSeal pushes events to a customer-configured URL. We verify a
373
+ * HMAC-SHA256 signature over the raw body keyed by the per-account
374
+ * webhook secret (`X-Docuseal-Signature` header, lowercase hex). The
375
+ * adapter parses the event shape and emits a normalized
376
+ * `InboundEvent` row (eventType = `docuseal.submission.completed`,
377
+ * etc.). Replay protection: DocuSeal does not currently sign a
378
+ * timestamp, so we recommend the receiver pin a per-event-id idempotency
379
+ * row (the `event_id` field on every push payload).
380
+ *
381
+ * Auth: API key (DocuSeal personal API key — every endpoint requires it
382
+ * via the `X-Auth-Token` header). Webhook secret is a separate
383
+ * credential delivered via the same DataSource — we accept either
384
+ * `kind: 'api-key'` (action surface) or `kind: 'custom'` carrying
385
+ * `apiKey` + `webhookSecret` (action + webhook on one connection).
386
+ *
387
+ * Error taxonomy (mapped via integrations/errors.ts):
388
+ * 401 → provider_auth_failed (CredentialsExpired)
389
+ * 404 → action_not_found (Error) — submission id is unknown
390
+ * 409 → action_denied / ResourceContention when status guards
391
+ * 429 → provider_rate_limited (status: 'rate-limited' result)
392
+ * 5xx → provider_unavailable
393
+ */
394
+
395
+ interface DocuSealOptions {
396
+ /** Override the DocuSeal API base URL (self-hosted deployments). */
397
+ baseUrl?: string;
398
+ /** Default request timeout in ms. */
399
+ timeoutMs?: number;
400
+ }
401
+ declare function docuseal(opts?: DocuSealOptions): ConnectorAdapter;
402
+
403
+ type RestCredentialPlacement = {
404
+ kind: 'bearer';
405
+ } | {
406
+ kind: 'header';
407
+ header: string;
408
+ prefix?: string;
409
+ } | {
410
+ kind: 'query';
411
+ parameter: string;
412
+ };
413
+ interface RestConnectorSpec {
414
+ kind: string;
415
+ displayName: string;
416
+ description: string;
417
+ auth: ConnectorAdapter['manifest']['auth'];
418
+ category: ConnectorAdapter['manifest']['category'];
419
+ defaultConsistencyModel: ConnectorAdapter['manifest']['defaultConsistencyModel'];
420
+ baseUrl: string | {
421
+ metadataKey: string;
422
+ fallback?: string;
423
+ };
424
+ credentialPlacement?: RestCredentialPlacement;
425
+ defaultHeaders?: Record<string, string>;
426
+ capabilities: RestOperationSpec[];
427
+ test?: RestRequestSpec;
428
+ }
429
+ interface RestOperationSpec {
430
+ name: string;
431
+ class: 'read' | 'mutation';
432
+ description: string;
433
+ parameters: Record<string, unknown>;
434
+ requiredScopes?: string[];
435
+ request: RestRequestSpec;
436
+ cas?: 'etag-if-match' | 'native-idempotency' | 'optimistic-read-verify' | 'none';
437
+ externalEffect?: boolean;
438
+ }
439
+ interface RestRequestSpec {
440
+ method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
441
+ path: string;
442
+ query?: Record<string, string | number | boolean | undefined>;
443
+ headers?: Record<string, string>;
444
+ body?: 'args' | string | Record<string, unknown>;
445
+ }
446
+ declare function declarativeRestConnector(spec: RestConnectorSpec): ConnectorAdapter;
447
+
448
+ /**
449
+ * Twilio SMS connector — outbound texts + recent-message lookup. The
450
+ * agent's "send the caller a confirmation link" surface.
451
+ *
452
+ * Auth: HTTP Basic (Account SID + Auth Token). Twilio's API key auth
453
+ * also supports SID/Secret pairs; we accept either by treating the
454
+ * stored apiKey envelope as `accountSid:authToken` (or
455
+ * `accountSid:keySid:secret`) — the connector parses it at call time.
456
+ *
457
+ * send_sms(to, body)
458
+ * Mutation. CAS = native-idempotency. Twilio added the
459
+ * `Idempotency-Key` HTTP header to POST /Messages in 2024 — same
460
+ * key + same args within 24h returns the original Message resource
461
+ * instead of sending a second SMS. MutationGuard's record short-
462
+ * circuits before us; Twilio's own dedup is defense-in-depth.
463
+ *
464
+ * lookup_number(phoneNumber)
465
+ * Read. Hits /v1/PhoneNumbers/{e164} on Lookup API. Confirms the
466
+ * number is real, returns carrier info if the caller has Lookup
467
+ * enabled on their account.
468
+ *
469
+ * find_recent_messages(toOrFrom?, limit?)
470
+ * Read. Returns the most recent Messages on the account, optionally
471
+ * filtered by To/From. Useful for "did the confirmation actually
472
+ * send?" introspection inside an agent run.
473
+ */
474
+
475
+ declare const twilioSmsConnector: ConnectorAdapter;
476
+
477
+ /**
478
+ * Stripe pack connector — single connector kind packing customer +
479
+ * invoice + checkout + subscription management capabilities, validating
480
+ * the "connector pack" concept (one auth handshake, multiple related
481
+ * capabilities) without exploding the registry into `stripe-customers`,
482
+ * `stripe-checkout`, `stripe-invoices`, `stripe-subscriptions` n-tuples.
483
+ *
484
+ * find_customer(email) → read; CAS n/a
485
+ * list_subscriptions(customerId, status?) → read; CAS n/a
486
+ * create_invoice(customerId, items) → mutation; cas: 'native-idempotency'
487
+ * create_checkout_session(...) → mutation; cas: 'native-idempotency'
488
+ * cancel_subscription(subscriptionId, atPeriodEnd?) → mutation; cas: 'native-idempotency'
489
+ * create_billing_portal_session(customerId, returnUrl) → mutation; cas: 'native-idempotency'
490
+ *
491
+ * Auth: API key (Stripe restricted key). Operator pastes the key into
492
+ * the Connections UI. We never see their account password / OAuth flow;
493
+ * Stripe restricted keys are the customer's responsibility (they pick
494
+ * which permissions the key carries). The kind exposes a webhook URL
495
+ * post-connect for the operator to paste into the Stripe dashboard —
496
+ * we'll wire the receiver to P-3's inbound webhook surface in a later
497
+ * commit. That URL is returned in `metadata.webhookUrl` so the UI can
498
+ * render it.
499
+ *
500
+ * Why this is the textbook example of `cas: 'native-idempotency'`:
501
+ * Stripe's `Idempotency-Key` HTTP header is THE reference implementation
502
+ * of native idempotency. Same key + same args within 24h returns the
503
+ * stored response (Stripe's words, not ours). Same key + different args
504
+ * → 400 with `idempotency_error`. We forward the SDK's idempotency key
505
+ * directly. MutationGuard short-circuits before us on retry; Stripe's
506
+ * own dedup is the second line of defense.
507
+ */
508
+
509
+ declare const stripePackConnector: ConnectorAdapter;
510
+
511
+ /**
512
+ * Universal webhook connector — the long-tail escape hatch.
513
+ *
514
+ * The user declares a target URL + a JSON-schema for the request body
515
+ * the agent should send, plus an optional shared secret. We sign every
516
+ * outbound POST with HMAC-SHA256 over `timestamp.body` and forward the
517
+ * agent's idempotency key as a header. The receiving system enforces
518
+ * its own idempotency.
519
+ *
520
+ * One adapter, two capabilities. Both arity-1 — `body` is whatever JSON
521
+ * the agent's planner constructs from the operator-defined schema (which
522
+ * lives in DataSource.metadata.requestSchema). The agent's planner reads
523
+ * that schema at request time and constructs valid args.
524
+ *
525
+ * Why one connector covers 50 systems badly and 1 system well: the agent
526
+ * gets a generic "send_event" tool that doesn't *know* what the upstream
527
+ * does with the payload. That's fine for fire-and-forget event posting
528
+ * (Zapier-style); it's wrong for booking against a calendar where you
529
+ * need conflict-resolution. So webhook's `post_event` capability is
530
+ * marked `cas: 'native-idempotency'` (we forward the key — the receiver
531
+ * MUST honor it) and `defaultConsistencyModel: 'advisory'`. Anyone
532
+ * needing real CAS uses a kind-specific connector (Calendar, Sheets, ...).
533
+ */
534
+
535
+ declare const webhookConnector: ConnectorAdapter;
536
+
537
+ /**
538
+ * Stripe inbound-webhook receiver — push-only side of a Stripe connector.
539
+ *
540
+ * The full Stripe connector (charges/customers/invoices read+mutation) is
541
+ * tracked in INTEGRATIONS.md as separate `stripe-customers` / `stripe-invoices`
542
+ * rows. This adapter only ships the inbound surface today: receive a push,
543
+ * verify the signature, persist one `InboundEvent` per Stripe event so the
544
+ * agent's runtime can react (e.g. payment_failed → outbound dunning call).
545
+ *
546
+ * This connector is for the connected account owner: they paste their
547
+ * `whsec_*` and the consuming product listens on a per-data-source URL such
548
+ * as /api/webhooks/inbound/stripe/:dataSourceId.
549
+ *
550
+ * Signature scheme: Stripe's `t=<unix>,v1=<hmac>` header. HMAC is
551
+ * sha256(`${t}.${rawBody}`) keyed by the customer's webhook secret. We use
552
+ * `timingSafeEqual` to defeat timing oracles and bound timestamp skew at
553
+ * 5 minutes (Stripe's recommendation) to thwart replay against captured
554
+ * signatures.
555
+ */
556
+
557
+ declare const stripeWebhookReceiverConnector: ConnectorAdapter;
558
+
559
+ /**
560
+ * Slack Events API inbound receiver.
561
+ *
562
+ * Slack sends two distinct request shapes to the same webhook URL:
563
+ *
564
+ * 1. `url_verification` — a one-off handshake during app-config. The body
565
+ * contains a `challenge` string we MUST echo back as the response body
566
+ * (Slack's app-config UI fails the URL otherwise). No InboundEvent is
567
+ * persisted for this — it's an infrastructure ping, not a user event.
568
+ *
569
+ * 2. `event_callback` — every actual workspace event (message posted,
570
+ * reaction added, channel created, …). We persist one InboundEvent
571
+ * keyed by `event_id` so a Slack retry (Slack retries 3 times on any
572
+ * non-2xx) is deduped at the unique constraint, not after we've
573
+ * double-processed.
574
+ *
575
+ * Signature scheme: `v0=<hmac(sha256, "v0:<timestamp>:<rawBody>")>` keyed by
576
+ * the app's signing secret. Header `X-Slack-Request-Timestamp` carries the
577
+ * timestamp; we reject anything older than 5 minutes (Slack's recommendation)
578
+ * to bound replay risk.
579
+ */
580
+
581
+ declare const slackEventsConnector: ConnectorAdapter;
582
+
583
+ declare const githubConnector: ConnectorAdapter;
584
+
585
+ declare const gitlabConnector: ConnectorAdapter;
586
+
587
+ declare const airtableConnector: ConnectorAdapter;
588
+
589
+ declare const asanaConnector: ConnectorAdapter;
590
+
591
+ declare const salesforceConnector: ConnectorAdapter;
592
+
593
+ export { type DocuSealOptions, type GmailOptions, type GoogleCalendarOptions, type GoogleDriveOptions, type GoogleSheetsOptions, type HubSpotOptions, type MicrosoftCalendarOptions, type NotionDatabaseOptions, type RestConnectorSpec, type RestCredentialPlacement, type RestOperationSpec, type RestRequestSpec, type SlackOptions, airtableConnector, asanaConnector, declarativeRestConnector, docuseal, githubConnector, gitlabConnector, gmail, googleCalendar, googleDrive, googleSheets, hubspot, microsoftCalendar, notionDatabase, salesforceConnector, slack, slackEventsConnector, stripePackConnector, stripeWebhookReceiverConnector, twilioSmsConnector, webhookConnector };
@@ -19,11 +19,24 @@ import {
19
19
  stripeWebhookReceiverConnector,
20
20
  twilioSmsConnector,
21
21
  webhookConnector
22
- } from "../../chunk-GA4VTE3U.js";
22
+ } from "../../chunk-JU25UDN2.js";
23
23
  import "../../chunk-2TW2QKGZ.js";
24
+ import {
25
+ DEFAULT_TANGLE_PLATFORM_URL,
26
+ TANGLE_API_KEY_PREFIX,
27
+ TANGLE_SERVICE_TOKEN_PREFIX,
28
+ TangleIdentityUnreachableError,
29
+ createTangleIdentityClient,
30
+ tangleIdentity
31
+ } from "../../chunk-ATYHZXLL.js";
24
32
  export {
33
+ DEFAULT_TANGLE_PLATFORM_URL,
34
+ TANGLE_API_KEY_PREFIX,
35
+ TANGLE_SERVICE_TOKEN_PREFIX,
36
+ TangleIdentityUnreachableError,
25
37
  airtableConnector,
26
38
  asanaConnector,
39
+ createTangleIdentityClient,
27
40
  declarativeRestConnector,
28
41
  docuseal,
29
42
  githubConnector,
@@ -40,6 +53,7 @@ export {
40
53
  slackEventsConnector,
41
54
  stripePackConnector,
42
55
  stripeWebhookReceiverConnector,
56
+ tangleIdentity,
43
57
  twilioSmsConnector,
44
58
  webhookConnector
45
59
  };
@@ -1,4 +1,5 @@
1
- export { A as AuthSpec, b as CASStrategy, c as Capability, d as CapabilityClass, e as CapabilityMutation, f as CapabilityMutationResult, g as CapabilityParameterSchema, h as CapabilityRead, i as CapabilityReadResult, C as ConnectorAdapter, a as ConnectorCredentials, j as ConnectorInvocation, k as ConnectorManifest, l as ConnectorManifestValidationIssue, m as ConnectorManifestValidationResult, n as ConsistencyModel, o as CredentialsExpired, D as DataSourceMetadata, p as DocuSealOptions, E as EventHandlerResult, G as GmailOptions, q as GoogleCalendarOptions, r as GoogleDriveOptions, s as GoogleSheetsOptions, H as HubSpotOptions, I as InboundEvent, M as MicrosoftCalendarOptions, N as NotionDatabaseOptions, t as RateLimitSpec, R as ResolvedDataSource, u as ResourceContention, v as RestConnectorSpec, w as RestCredentialPlacement, x as RestOperationSpec, y as RestRequestSpec, S as SlackOptions, z as airtableConnector, B as asanaConnector, F as assertValidConnectorManifest, J as declarativeRestConnector, K as docuseal, L as githubConnector, O as gitlabConnector, P as gmail, Q as googleCalendar, T as googleDrive, U as googleSheets, V as hubspot, W as microsoftCalendar, X as notionDatabase, Y as salesforceConnector, Z as slack, _ as slackEventsConnector, $ as stripePackConnector, a0 as stripeWebhookReceiverConnector, a1 as twilioSmsConnector, a2 as validateConnectorManifest, a3 as webhookConnector } from '../index-D4D4CEKX.js';
1
+ export { A as AuthSpec, e as CASStrategy, f as Capability, g as CapabilityClass, h as CapabilityMutation, i as CapabilityMutationResult, j as CapabilityParameterSchema, k as CapabilityRead, l as CapabilityReadResult, C as ConnectorAdapter, d as ConnectorCredentials, m as ConnectorInvocation, n as ConnectorManifest, o as ConnectorManifestValidationIssue, p as ConnectorManifestValidationResult, q as ConsistencyModel, r as CredentialsExpired, D as DEFAULT_TANGLE_PLATFORM_URL, s as DataSourceMetadata, E as EventHandlerResult, I as InboundEvent, t as RateLimitSpec, R as ResolvedDataSource, u as ResourceContention, v as TANGLE_API_KEY_PREFIX, w as TANGLE_SERVICE_TOKEN_PREFIX, b as TangleIdentityClient, T as TangleIdentityOptions, x as TangleIdentityUnreachableError, c as TangleTokenVerifyFailure, y as TangleTokenVerifyResult, a as TangleUserSummary, z as TangleWorkspaceSummary, B as assertValidConnectorManifest, F as createTangleIdentityClient, G as tangleIdentity, H as validateConnectorManifest } from '../tangle-id-CTU4kGId.js';
2
+ export { DocuSealOptions, GmailOptions, GoogleCalendarOptions, GoogleDriveOptions, GoogleSheetsOptions, HubSpotOptions, MicrosoftCalendarOptions, NotionDatabaseOptions, RestConnectorSpec, RestCredentialPlacement, RestOperationSpec, RestRequestSpec, SlackOptions, airtableConnector, asanaConnector, declarativeRestConnector, docuseal, githubConnector, gitlabConnector, gmail, googleCalendar, googleDrive, googleSheets, hubspot, microsoftCalendar, notionDatabase, salesforceConnector, slack, slackEventsConnector, stripePackConnector, stripeWebhookReceiverConnector, twilioSmsConnector, webhookConnector } from './adapters/index.js';
2
3
 
3
4
  /**
4
5
  * Generic OAuth2 helper used by every oauth-shaped connector (Google