@tangle-network/agent-integrations 0.16.0 → 0.16.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,3 +1,25 @@
1
+ import {
2
+ INTEGRATION_FAMILIES,
3
+ assertValidIntegrationSpec,
4
+ buildHealthcheckPlan,
5
+ buildIntegrationCoverageConnectors,
6
+ consoleStepsToText,
7
+ getIntegrationFamily,
8
+ getIntegrationSpec,
9
+ integrationCoverageChecklistMarkdown,
10
+ integrationSpecToConnector,
11
+ listExecutableIntegrationSpecs,
12
+ listIntegrationCoverageSpecs,
13
+ listIntegrationSpecs,
14
+ renderAgentToolDescription,
15
+ renderConsoleSteps,
16
+ renderRunbookMarkdown,
17
+ specAuthToConnectorAuth,
18
+ validateCredentialFormat,
19
+ validateCredentialSet,
20
+ validateIntegrationSpec
21
+ } from "./chunk-DIJ3I66K.js";
22
+
1
23
  // src/index.ts
2
24
  import { createHmac as createHmac3, randomUUID as randomUUID3, timingSafeEqual as timingSafeEqual2 } from "crypto";
3
25
 
@@ -210,867 +232,6 @@ function dataClassFor(category) {
210
232
  return "internal";
211
233
  }
212
234
 
213
- // src/coverage-catalog.ts
214
- var DEFAULT_PROVIDER_KINDS = ["first_party", "nango", "pipedream", "activepieces", "custom"];
215
- var COVERAGE_SPECS = [
216
- ["gmail", "Gmail", "email", "email", "tier_0", "email,google,workspace,inbox"],
217
- ["outlook-mail", "Outlook Mail", "email", "email", "tier_0", "email,microsoft,office,inbox"],
218
- ["google-calendar", "Google Calendar", "calendar", "calendar", "tier_0", "calendar,google,workspace,scheduling"],
219
- ["outlook-calendar", "Outlook Calendar", "calendar", "calendar", "tier_0", "calendar,microsoft,office,scheduling"],
220
- ["slack", "Slack", "chat", "chat", "tier_0", "chat,collaboration,internal-comms"],
221
- ["microsoft-teams", "Microsoft Teams", "chat", "chat", "tier_0", "chat,microsoft,collaboration"],
222
- ["google-drive", "Google Drive", "storage", "storage", "tier_0", "files,google,workspace,storage"],
223
- ["onedrive", "OneDrive", "storage", "storage", "tier_0", "files,microsoft,office,storage"],
224
- ["dropbox", "Dropbox", "storage", "storage", "tier_1", "files,storage"],
225
- ["box", "Box", "storage", "storage", "tier_1", "files,enterprise,storage"],
226
- ["google-docs", "Google Docs", "docs", "docs", "tier_0", "docs,google,workspace"],
227
- ["google-sheets", "Google Sheets", "database", "database", "tier_0", "sheets,spreadsheet,google,database"],
228
- ["microsoft-excel", "Microsoft Excel", "database", "database", "tier_0", "sheets,spreadsheet,microsoft,database"],
229
- ["notion", "Notion", "docs", "docs", "tier_0", "docs,wiki,knowledge"],
230
- ["airtable", "Airtable", "database", "database", "tier_0", "database,spreadsheet,ops"],
231
- ["coda", "Coda", "docs", "docs", "tier_1", "docs,wiki,ops"],
232
- ["confluence", "Confluence", "docs", "docs", "tier_1", "docs,wiki,atlassian"],
233
- ["sharepoint", "SharePoint", "storage", "storage", "tier_1", "files,microsoft,enterprise"],
234
- ["hubspot", "HubSpot", "crm", "crm", "tier_0", "crm,sales,marketing"],
235
- ["salesforce", "Salesforce", "crm", "crm", "tier_0", "crm,sales,enterprise"],
236
- ["pipedrive", "Pipedrive", "crm", "crm", "tier_1", "crm,sales"],
237
- ["zoho-crm", "Zoho CRM", "crm", "crm", "tier_1", "crm,sales"],
238
- ["close", "Close", "crm", "crm", "tier_1", "crm,sales"],
239
- ["attio", "Attio", "crm", "crm", "tier_1", "crm,sales,startups"],
240
- ["linear", "Linear", "workflow", "project", "tier_0", "project,engineering,tickets"],
241
- ["jira", "Jira", "workflow", "project", "tier_0", "project,engineering,tickets,atlassian"],
242
- ["github", "GitHub", "workflow", "dev", "tier_0", "code,dev,issues,git"],
243
- ["gitlab", "GitLab", "workflow", "dev", "tier_1", "code,dev,issues,git"],
244
- ["bitbucket", "Bitbucket", "workflow", "dev", "tier_2", "code,dev,git,atlassian"],
245
- ["asana", "Asana", "workflow", "project", "tier_1", "project,tasks"],
246
- ["trello", "Trello", "workflow", "project", "tier_1", "project,tasks,atlassian"],
247
- ["monday", "monday.com", "workflow", "project", "tier_1", "project,tasks,ops"],
248
- ["clickup", "ClickUp", "workflow", "project", "tier_1", "project,tasks,ops"],
249
- ["basecamp", "Basecamp", "workflow", "project", "tier_2", "project,tasks"],
250
- ["zendesk", "Zendesk", "crm", "support", "tier_0", "support,tickets,customer-success"],
251
- ["intercom", "Intercom", "crm", "support", "tier_0", "support,chat,customer-success"],
252
- ["freshdesk", "Freshdesk", "crm", "support", "tier_1", "support,tickets"],
253
- ["helpscout", "Help Scout", "crm", "support", "tier_1", "support,tickets"],
254
- ["front", "Front", "email", "support", "tier_1", "support,email,shared-inbox"],
255
- ["gorgias", "Gorgias", "crm", "support", "tier_1", "support,ecommerce"],
256
- ["stripe", "Stripe", "workflow", "finance", "tier_0", "payments,billing,finance"],
257
- ["quickbooks", "QuickBooks", "workflow", "finance", "tier_0", "accounting,finance"],
258
- ["xero", "Xero", "workflow", "finance", "tier_1", "accounting,finance"],
259
- ["netsuite", "NetSuite", "workflow", "finance", "tier_1", "erp,finance,enterprise"],
260
- ["sage", "Sage", "workflow", "finance", "tier_2", "accounting,finance"],
261
- ["plaid", "Plaid", "workflow", "finance", "tier_1", "banking,finance"],
262
- ["shopify", "Shopify", "workflow", "commerce", "tier_0", "ecommerce,orders,commerce"],
263
- ["woocommerce", "WooCommerce", "workflow", "commerce", "tier_1", "ecommerce,orders,wordpress"],
264
- ["bigcommerce", "BigCommerce", "workflow", "commerce", "tier_1", "ecommerce,orders"],
265
- ["amazon-seller-central", "Amazon Seller Central", "workflow", "commerce", "tier_1", "marketplace,ecommerce"],
266
- ["ebay", "eBay", "workflow", "commerce", "tier_2", "marketplace,ecommerce"],
267
- ["etsy", "Etsy", "workflow", "commerce", "tier_2", "marketplace,ecommerce"],
268
- ["mailchimp", "Mailchimp", "workflow", "marketing", "tier_0", "email-marketing,marketing"],
269
- ["klaviyo", "Klaviyo", "workflow", "marketing", "tier_0", "email-marketing,ecommerce,marketing"],
270
- ["marketo", "Marketo", "workflow", "marketing", "tier_1", "marketing,enterprise"],
271
- ["braze", "Braze", "workflow", "marketing", "tier_1", "marketing,lifecycle"],
272
- ["customer-io", "Customer.io", "workflow", "marketing", "tier_1", "marketing,lifecycle"],
273
- ["sendgrid", "SendGrid", "email", "email", "tier_1", "email,transactional"],
274
- ["postmark", "Postmark", "email", "email", "tier_1", "email,transactional"],
275
- ["twilio", "Twilio", "chat", "chat", "tier_0", "sms,voice,communications"],
276
- ["discord", "Discord", "chat", "chat", "tier_1", "chat,community"],
277
- ["telegram", "Telegram", "chat", "chat", "tier_1", "chat,community"],
278
- ["whatsapp-business", "WhatsApp Business", "chat", "chat", "tier_1", "chat,meta,customer-comms"],
279
- ["facebook-pages", "Facebook Pages", "workflow", "marketing", "tier_1", "social,meta,marketing"],
280
- ["instagram-business", "Instagram Business", "workflow", "marketing", "tier_1", "social,meta,marketing"],
281
- ["linkedin", "LinkedIn", "workflow", "sales", "tier_1", "social,sales,gtm"],
282
- ["x-twitter", "X / Twitter", "workflow", "marketing", "tier_1", "social,marketing"],
283
- ["youtube", "YouTube", "storage", "storage", "tier_1", "video,content"],
284
- ["tiktok", "TikTok", "workflow", "marketing", "tier_2", "social,video,marketing"],
285
- ["google-analytics", "Google Analytics", "database", "analytics", "tier_0", "analytics,web,marketing"],
286
- ["mixpanel", "Mixpanel", "database", "analytics", "tier_1", "analytics,product"],
287
- ["amplitude", "Amplitude", "database", "analytics", "tier_1", "analytics,product"],
288
- ["segment", "Segment", "database", "analytics", "tier_1", "analytics,cdp"],
289
- ["snowflake", "Snowflake", "database", "database", "tier_0", "warehouse,data"],
290
- ["bigquery", "BigQuery", "database", "database", "tier_0", "warehouse,google,data"],
291
- ["redshift", "Redshift", "database", "database", "tier_1", "warehouse,aws,data"],
292
- ["postgres", "Postgres", "database", "database", "tier_0", "database,sql"],
293
- ["mysql", "MySQL", "database", "database", "tier_1", "database,sql"],
294
- ["mongodb", "MongoDB", "database", "database", "tier_1", "database,nosql"],
295
- ["supabase", "Supabase", "database", "database", "tier_1", "database,postgres"],
296
- ["firebase", "Firebase", "database", "database", "tier_1", "database,google,app"],
297
- ["redis", "Redis", "database", "database", "tier_2", "database,cache"],
298
- ["aws-s3", "Amazon S3", "storage", "storage", "tier_0", "files,aws,storage"],
299
- ["aws-lambda", "AWS Lambda", "workflow", "dev", "tier_1", "aws,serverless,dev"],
300
- ["aws-cloudwatch", "AWS CloudWatch", "database", "analytics", "tier_1", "aws,logs,observability"],
301
- ["google-cloud-storage", "Google Cloud Storage", "storage", "storage", "tier_1", "files,gcp,storage"],
302
- ["azure-blob-storage", "Azure Blob Storage", "storage", "storage", "tier_1", "files,azure,storage"],
303
- ["vercel", "Vercel", "workflow", "dev", "tier_1", "deployments,dev"],
304
- ["netlify", "Netlify", "workflow", "dev", "tier_2", "deployments,dev"],
305
- ["cloudflare", "Cloudflare", "workflow", "dev", "tier_1", "edge,dev,dns"],
306
- ["sentry", "Sentry", "workflow", "dev", "tier_1", "errors,observability,dev"],
307
- ["datadog", "Datadog", "database", "analytics", "tier_1", "observability,logs,metrics"],
308
- ["new-relic", "New Relic", "database", "analytics", "tier_2", "observability,logs,metrics"],
309
- ["pagerduty", "PagerDuty", "workflow", "project", "tier_1", "incident,on-call"],
310
- ["opsgenie", "Opsgenie", "workflow", "project", "tier_2", "incident,on-call,atlassian"],
311
- ["okta", "Okta", "internal", "workflow", "tier_1", "identity,security"],
312
- ["auth0", "Auth0", "internal", "workflow", "tier_1", "identity,security"],
313
- ["workday", "Workday", "workflow", "hr", "tier_1", "hr,finance,enterprise"],
314
- ["bamboohr", "BambooHR", "workflow", "hr", "tier_1", "hr,people"],
315
- ["greenhouse", "Greenhouse", "workflow", "hr", "tier_1", "recruiting,hr"],
316
- ["lever", "Lever", "workflow", "hr", "tier_1", "recruiting,hr"],
317
- ["gusto", "Gusto", "workflow", "hr", "tier_1", "payroll,hr"],
318
- ["rippling", "Rippling", "workflow", "hr", "tier_1", "hr,it,identity"],
319
- ["docusign", "DocuSign", "docs", "docs", "tier_1", "contracts,signature,legal"],
320
- ["pandadoc", "PandaDoc", "docs", "docs", "tier_1", "contracts,signature,sales"],
321
- ["hellosign", "Dropbox Sign", "docs", "docs", "tier_2", "contracts,signature"],
322
- ["clio", "Clio", "workflow", "project", "tier_1", "legal,practice-management"],
323
- ["ironclad", "Ironclad", "docs", "docs", "tier_1", "legal,contracts"],
324
- ["lexisnexis", "LexisNexis", "docs", "docs", "tier_2", "legal,research"],
325
- ["calendly", "Calendly", "calendar", "calendar", "tier_0", "scheduling,calendar"],
326
- ["cal-com", "Cal.com", "calendar", "calendar", "tier_1", "scheduling,calendar"],
327
- ["zoom", "Zoom", "calendar", "calendar", "tier_0", "meetings,video,calendar"],
328
- ["google-meet", "Google Meet", "calendar", "calendar", "tier_1", "meetings,google,video"],
329
- ["microsoft-graph", "Microsoft Graph", "internal", "workflow", "tier_0", "microsoft,enterprise,identity"],
330
- ["openai", "OpenAI", "workflow", "ai", "tier_0", "ai,llm"],
331
- ["anthropic", "Anthropic", "workflow", "ai", "tier_1", "ai,llm"],
332
- ["gemini", "Google Gemini", "workflow", "ai", "tier_1", "ai,llm,google"],
333
- ["huggingface", "Hugging Face", "workflow", "ai", "tier_1", "ai,models"],
334
- ["pinecone", "Pinecone", "database", "database", "tier_1", "vector,database,ai"],
335
- ["weaviate", "Weaviate", "database", "database", "tier_1", "vector,database,ai"],
336
- ["qdrant", "Qdrant", "database", "database", "tier_1", "vector,database,ai"],
337
- ["zapier", "Zapier", "workflow", "workflow", "tier_1", "automation,workflow"],
338
- ["make", "Make", "workflow", "workflow", "tier_1", "automation,workflow"],
339
- ["nango", "Nango", "workflow", "workflow", "tier_1", "integration-platform,oauth"],
340
- ["pipedream", "Pipedream", "workflow", "workflow", "tier_1", "integration-platform,workflow"],
341
- ["activepieces", "Activepieces", "workflow", "workflow", "tier_1", "automation,workflow,open-source"],
342
- ["webhook", "Generic Webhook", "webhook", "webhook", "tier_0", "webhook,http,events", "none"],
343
- ["http", "HTTP Request", "workflow", "webhook", "tier_0", "http,api,webhook", "none"],
344
- ["rss", "RSS", "webhook", "webhook", "tier_1", "feeds,content", "none"],
345
- ["zapier-transfer", "Zapier Transfer", "workflow", "workflow", "long_tail", "automation,migration"],
346
- ["typeform", "Typeform", "workflow", "marketing", "tier_1", "forms,marketing"],
347
- ["google-forms", "Google Forms", "workflow", "marketing", "tier_1", "forms,google"],
348
- ["jotform", "Jotform", "workflow", "marketing", "tier_2", "forms"],
349
- ["webflow", "Webflow", "workflow", "marketing", "tier_1", "cms,website"],
350
- ["wordpress", "WordPress", "workflow", "marketing", "tier_1", "cms,website"],
351
- ["contentful", "Contentful", "docs", "docs", "tier_1", "cms,content"],
352
- ["sanity", "Sanity", "docs", "docs", "tier_1", "cms,content"],
353
- ["figma", "Figma", "docs", "docs", "tier_0", "design,creative"],
354
- ["canva", "Canva", "docs", "docs", "tier_1", "design,creative"],
355
- ["adobe-creative-cloud", "Adobe Creative Cloud", "storage", "storage", "tier_1", "design,creative,files"],
356
- ["miro", "Miro", "docs", "docs", "tier_1", "whiteboard,collaboration"],
357
- ["figjam", "FigJam", "docs", "docs", "tier_2", "whiteboard,design"]
358
- ];
359
- function listIntegrationCoverageSpecs() {
360
- return COVERAGE_SPECS.map(([id, title, category, actionPack2, priority, domains, auth = "oauth2"]) => ({
361
- id,
362
- title,
363
- category,
364
- actionPack: actionPack2,
365
- priority,
366
- auth,
367
- providerKinds: providerKindsFor(auth),
368
- domains: domains.split(",").map((domain) => domain.trim()).filter(Boolean),
369
- scopes: scopesFor(id, actionPack2)
370
- }));
371
- }
372
- function buildIntegrationCoverageConnectors(options = {}) {
373
- const providerId = options.providerId ?? "coverage";
374
- return listIntegrationCoverageSpecs().filter((spec) => !options.priorities || options.priorities.includes(spec.priority)).filter((spec) => !options.categories || options.categories.includes(spec.category)).filter((spec) => !options.actionPacks || options.actionPacks.includes(spec.actionPack)).map((spec) => specToConnector(spec, providerId));
375
- }
376
- function integrationCoverageChecklistMarkdown() {
377
- const specs = listIntegrationCoverageSpecs();
378
- const lines = [
379
- "# Agent Integrations Coverage Checklist",
380
- "",
381
- "Generated from `listIntegrationCoverageSpecs()`. Catalog presence means the product can plan/request/connect the integration; executable first-party adapters are promoted separately behind the same provider contract.",
382
- "",
383
- "## Summary",
384
- "",
385
- `- Total cataloged integrations: ${specs.length}`,
386
- `- Tier 0: ${specs.filter((spec) => spec.priority === "tier_0").length}`,
387
- `- Tier 1: ${specs.filter((spec) => spec.priority === "tier_1").length}`,
388
- `- Tier 2: ${specs.filter((spec) => spec.priority === "tier_2").length}`,
389
- `- Long tail: ${specs.filter((spec) => spec.priority === "long_tail").length}`,
390
- "",
391
- "## Checklist",
392
- ""
393
- ];
394
- for (const spec of specs) {
395
- lines.push(`- [ ] ${spec.priority} / ${spec.category} / ${spec.title} (${spec.id}) - ${spec.domains.join(", ")}`);
396
- }
397
- return `${lines.join("\n")}
398
- `;
399
- }
400
- function specToConnector(spec, providerId) {
401
- const actions = actionPack(spec.actionPack, spec.scopes ?? []);
402
- return {
403
- id: spec.id,
404
- providerId,
405
- title: spec.title,
406
- category: spec.category,
407
- auth: spec.auth,
408
- scopes: spec.scopes ?? [],
409
- actions,
410
- triggers: triggersFor(spec.actionPack, spec.scopes ?? []),
411
- metadata: {
412
- source: "coverage-catalog",
413
- priority: spec.priority,
414
- domains: spec.domains,
415
- providerKinds: spec.providerKinds,
416
- executable: false
417
- }
418
- };
419
- }
420
- function actionPack(pack, scopes) {
421
- const readScope = scopes.find((scope2) => scope2.endsWith(".read")) ?? scopes[0];
422
- const writeScope = scopes.find((scope2) => scope2.endsWith(".write")) ?? scopes[1] ?? readScope;
423
- const scope = (value) => value ? [value] : [];
424
- const read = (id, title, description) => ({
425
- id,
426
- title,
427
- description,
428
- risk: "read",
429
- requiredScopes: scope(readScope),
430
- dataClass: dataClassFor2(pack),
431
- inputSchema: objectSchema()
432
- });
433
- const write = (id, title, description) => ({
434
- id,
435
- title,
436
- description,
437
- risk: "write",
438
- requiredScopes: scope(writeScope),
439
- dataClass: dataClassFor2(pack),
440
- approvalRequired: true,
441
- inputSchema: objectSchema()
442
- });
443
- const destructive = (id, title, description) => ({
444
- id,
445
- title,
446
- description,
447
- risk: "destructive",
448
- requiredScopes: scope(writeScope),
449
- dataClass: dataClassFor2(pack),
450
- approvalRequired: true,
451
- inputSchema: objectSchema()
452
- });
453
- switch (pack) {
454
- case "email":
455
- return [read("messages.search", "Search messages", "Search messages and threads."), read("messages.read", "Read message", "Read a message by id."), write("drafts.create", "Create draft", "Create an email draft."), write("messages.send", "Send message", "Send or reply to an email message.")];
456
- case "calendar":
457
- return [read("events.search", "Search events", "Search calendar events."), read("availability.read", "Read availability", "Read availability windows."), write("events.create", "Create event", "Create a calendar event."), write("events.update", "Update event", "Update a calendar event."), destructive("events.cancel", "Cancel event", "Cancel a calendar event.")];
458
- case "chat":
459
- return [read("messages.search", "Search messages", "Search channel or direct messages."), read("channels.list", "List channels", "List channels or rooms."), write("messages.post", "Send message", "Send a message to a channel or direct message."), write("threads.reply", "Reply in thread", "Reply to a thread or conversation.")];
460
- case "crm":
461
- return [read("records.search", "Search records", "Search contacts, companies, and deals."), read("records.read", "Read record", "Read a CRM record."), write("records.upsert", "Upsert record", "Create or update a CRM record."), write("notes.create", "Create note", "Add a note or activity.")];
462
- case "storage":
463
- return [read("files.search", "Search files", "Search files and folders."), read("files.read", "Read file", "Read file metadata or content."), write("files.upload", "Upload file", "Upload a file."), write("files.update", "Update file", "Update file metadata or content.")];
464
- case "docs":
465
- return [read("documents.search", "Search documents", "Search documents or pages."), read("documents.read", "Read document", "Read a document."), write("documents.create", "Create document", "Create a document or page."), write("documents.update", "Update document", "Update a document or page.")];
466
- case "database":
467
- return [read("records.query", "Query records", "Query rows, records, or objects."), read("records.read", "Read record", "Read one row, record, or object."), write("records.upsert", "Upsert record", "Create or update a row, record, or object."), destructive("records.delete", "Delete record", "Delete a row, record, or object.")];
468
- case "project":
469
- return [read("tasks.search", "Search tasks", "Search tasks, tickets, or issues."), read("tasks.read", "Read task", "Read a task, ticket, or issue."), write("tasks.create", "Create task", "Create a task, ticket, or issue."), write("tasks.update", "Update task", "Update a task, ticket, or issue.")];
470
- case "support":
471
- return [read("tickets.search", "Search tickets", "Search support tickets or conversations."), read("customers.read", "Read customer", "Read a customer profile."), write("tickets.reply", "Reply to ticket", "Reply to a support ticket."), write("tickets.update", "Update ticket", "Update ticket status, tags, or assignee.")];
472
- case "marketing":
473
- return [read("contacts.search", "Search contacts", "Search marketing contacts or audiences."), read("campaigns.read", "Read campaign", "Read campaign metadata and performance."), write("contacts.upsert", "Upsert contact", "Create or update a contact."), write("campaigns.create", "Create campaign", "Create a campaign draft.")];
474
- case "sales":
475
- return [read("prospects.search", "Search prospects", "Search prospects, leads, or accounts."), read("activities.read", "Read activities", "Read sales activity history."), write("prospects.upsert", "Upsert prospect", "Create or update a prospect."), write("sequence.enqueue", "Enroll in sequence", "Enroll a prospect in a sales sequence.")];
476
- case "commerce":
477
- return [read("orders.search", "Search orders", "Search orders."), read("customers.read", "Read customer", "Read customer and purchase history."), write("orders.update", "Update order", "Update order metadata or fulfillment state."), write("products.update", "Update product", "Update product metadata.")];
478
- case "finance":
479
- return [read("transactions.search", "Search transactions", "Search transactions, invoices, or payments."), read("accounts.read", "Read account", "Read account or customer financial record."), write("invoices.create", "Create invoice", "Create an invoice or payment object."), write("records.sync", "Sync record", "Sync a finance or accounting record.")];
480
- case "hr":
481
- return [read("people.search", "Search people", "Search employees, candidates, or contractors."), read("people.read", "Read person", "Read a person profile."), write("people.update", "Update person", "Update a person profile."), write("events.create", "Create HR event", "Create a recruiting or HR event.")];
482
- case "dev":
483
- return [read("resources.search", "Search resources", "Search issues, repos, deployments, logs, or incidents."), read("resources.read", "Read resource", "Read a developer resource."), write("resources.create", "Create resource", "Create an issue, deployment, incident, or config."), write("resources.update", "Update resource", "Update a developer resource.")];
484
- case "ai":
485
- return [read("models.list", "List models", "List available models or endpoints."), write("responses.create", "Create response", "Create an AI response or job."), write("embeddings.create", "Create embeddings", "Create embeddings or vector jobs."), read("usage.read", "Read usage", "Read usage metadata.")];
486
- case "analytics":
487
- return [read("reports.query", "Query reports", "Query analytics reports."), read("events.search", "Search events", "Search analytics events."), write("events.track", "Track event", "Track an analytics event."), write("audiences.sync", "Sync audience", "Sync an audience or cohort.")];
488
- case "workflow":
489
- return [read("runs.search", "Search runs", "Search workflow runs or jobs."), read("templates.list", "List templates", "List workflow templates."), write("runs.start", "Start run", "Start a workflow run."), write("webhooks.dispatch", "Dispatch webhook", "Dispatch a workflow webhook.")];
490
- case "webhook":
491
- return [write("requests.send", "Send request", "Send an HTTP request or webhook event."), read("events.search", "Search events", "Search received webhook events."), write("subscriptions.create", "Create subscription", "Create a webhook subscription."), destructive("subscriptions.delete", "Delete subscription", "Delete a webhook subscription.")];
492
- }
493
- }
494
- function triggersFor(pack, scopes) {
495
- const readScope = scopes.find((scope) => scope.endsWith(".read")) ?? scopes[0];
496
- const requiredScopes2 = readScope ? [readScope] : [];
497
- if (pack === "email") return [{ id: "message.received", title: "Message received", requiredScopes: requiredScopes2, dataClass: "private" }];
498
- if (pack === "calendar") return [{ id: "event.changed", title: "Event changed", requiredScopes: requiredScopes2, dataClass: "private" }];
499
- if (pack === "chat") return [{ id: "message.posted", title: "Message posted", requiredScopes: requiredScopes2, dataClass: "private" }];
500
- if (pack === "crm") return [{ id: "record.changed", title: "Record changed", requiredScopes: requiredScopes2, dataClass: "private" }];
501
- if (pack === "support") return [{ id: "ticket.changed", title: "Ticket changed", requiredScopes: requiredScopes2, dataClass: "private" }];
502
- if (pack === "commerce") return [{ id: "order.changed", title: "Order changed", requiredScopes: requiredScopes2, dataClass: "sensitive" }];
503
- if (pack === "finance") return [{ id: "transaction.changed", title: "Transaction changed", requiredScopes: requiredScopes2, dataClass: "sensitive" }];
504
- if (pack === "workflow" || pack === "webhook") return [{ id: "event.received", title: "Event received", requiredScopes: requiredScopes2, dataClass: "internal" }];
505
- return void 0;
506
- }
507
- function scopesFor(id, pack) {
508
- if (pack === "webhook") return [];
509
- return [`${id}.read`, `${id}.write`];
510
- }
511
- function providerKindsFor(auth) {
512
- if (auth === "none") return ["first_party", "pipedream", "activepieces", "custom"];
513
- return DEFAULT_PROVIDER_KINDS;
514
- }
515
- function dataClassFor2(pack) {
516
- if (pack === "finance" || pack === "commerce" || pack === "hr") return "sensitive";
517
- if (pack === "workflow" || pack === "webhook" || pack === "dev" || pack === "analytics") return "internal";
518
- return "private";
519
- }
520
- function objectSchema() {
521
- return { type: "object", additionalProperties: true, properties: {} };
522
- }
523
-
524
- // src/specs/families.ts
525
- var INTEGRATION_FAMILIES = {
526
- google: {
527
- id: "google",
528
- title: "Google OAuth",
529
- authMode: "oauth2",
530
- consoleUrl: "https://console.cloud.google.com/apis/credentials",
531
- authorizationUrl: "https://accounts.google.com/o/oauth2/v2/auth",
532
- tokenUrl: "https://oauth2.googleapis.com/token",
533
- redirectUriTemplate: "https://{host}/api/integrations/oauth/google/callback",
534
- credentialFields: [
535
- { label: "Client ID", env: "GOOGLE_OAUTH_CLIENT_ID", description: "Google OAuth client ID.", example: "1234567890-abc.apps.googleusercontent.com", regex: "^[0-9]+-[a-zA-Z0-9_-]+\\.apps\\.googleusercontent\\.com$", secret: false },
536
- { label: "Client Secret", env: "GOOGLE_OAUTH_CLIENT_SECRET", description: "Google OAuth client secret.", example: "GOCSPX-...", secret: true }
537
- ],
538
- consoleSteps: [
539
- { id: "project", title: "Select project", detail: "Open Google Cloud Console and select the project that owns the OAuth client." },
540
- { id: "consent", title: "Configure consent screen", detail: "Configure OAuth consent, app name, support email, and publishing status appropriate for the deployment." },
541
- { id: "client", title: "Create web client", detail: "Create an OAuth client of type Web application." },
542
- { id: "redirect", title: "Add redirect URI", detail: "Add {redirectUri} as an authorized redirect URI.", copyValue: "{redirectUri}" },
543
- { id: "scopes", title: "Add scopes", detail: "Add the provider scopes listed in this spec." }
544
- ],
545
- knownQuirks: [
546
- { id: "offline-access", severity: "warning", message: "Use access_type=offline and prompt=consent when refresh tokens are required." },
547
- { id: "verification", severity: "warning", message: "Sensitive or restricted scopes may require Google verification before broad external use." }
548
- ],
549
- lifecycle: { supportsRefresh: true, supportsRevoke: true, supportsIncrementalAuth: true, recommendedHealthcheckIntervalHours: 24 }
550
- },
551
- "microsoft-graph": {
552
- id: "microsoft-graph",
553
- title: "Microsoft Graph OAuth",
554
- authMode: "oauth2",
555
- consoleUrl: "https://entra.microsoft.com/#view/Microsoft_AAD_RegisteredApps/ApplicationsListBlade",
556
- authorizationUrl: "https://login.microsoftonline.com/common/oauth2/v2.0/authorize",
557
- tokenUrl: "https://login.microsoftonline.com/common/oauth2/v2.0/token",
558
- redirectUriTemplate: "https://{host}/api/integrations/oauth/microsoft/callback",
559
- credentialFields: [
560
- { label: "Client ID", env: "MS_OAUTH_CLIENT_ID", description: "Microsoft Entra application client ID.", example: "00000000-0000-0000-0000-000000000000", regex: "^[0-9a-fA-F-]{36}$", secret: false },
561
- { label: "Client Secret", env: "MS_OAUTH_CLIENT_SECRET", description: "Microsoft Entra client secret value.", secret: true }
562
- ],
563
- consoleSteps: [
564
- { id: "app", title: "Register app", detail: "Create or open an app registration in Microsoft Entra." },
565
- { id: "redirect", title: "Add redirect URI", detail: "Add {redirectUri} as a Web redirect URI.", copyValue: "{redirectUri}" },
566
- { id: "secret", title: "Create secret", detail: "Create a client secret and store the secret value, not the secret ID." },
567
- { id: "permissions", title: "Add Graph permissions", detail: "Add the delegated Graph scopes listed in this spec and grant admin consent where required." }
568
- ],
569
- knownQuirks: [
570
- { id: "tenant-common", severity: "info", message: "The common tenant supports multi-tenant OAuth; single-tenant deployments should override the tenant segment." },
571
- { id: "admin-consent", severity: "warning", message: "Some Graph scopes require tenant admin consent." }
572
- ],
573
- lifecycle: { supportsRefresh: true, supportsRevoke: true, supportsIncrementalAuth: true, recommendedHealthcheckIntervalHours: 24 }
574
- },
575
- atlassian: {
576
- id: "atlassian",
577
- title: "Atlassian OAuth",
578
- authMode: "oauth2",
579
- consoleUrl: "https://developer.atlassian.com/console/myapps/",
580
- authorizationUrl: "https://auth.atlassian.com/authorize",
581
- tokenUrl: "https://auth.atlassian.com/oauth/token",
582
- redirectUriTemplate: "https://{host}/api/integrations/oauth/atlassian/callback",
583
- credentialFields: [
584
- { label: "Client ID", description: "Atlassian OAuth client ID.", secret: false },
585
- { label: "Client Secret", description: "Atlassian OAuth client secret.", secret: true }
586
- ],
587
- consoleSteps: [
588
- { id: "app", title: "Create OAuth app", detail: "Create an OAuth 2.0 app in the Atlassian developer console." },
589
- { id: "redirect", title: "Add callback URL", detail: "Add {redirectUri} as the callback URL.", copyValue: "{redirectUri}" },
590
- { id: "apis", title: "Enable APIs", detail: "Enable the Jira or Confluence APIs required by this connector." }
591
- ],
592
- lifecycle: { supportsRefresh: true, supportsRevoke: false, supportsIncrementalAuth: false, recommendedHealthcheckIntervalHours: 24 }
593
- },
594
- salesforce: {
595
- id: "salesforce",
596
- title: "Salesforce OAuth",
597
- authMode: "oauth2",
598
- consoleUrl: "https://login.salesforce.com",
599
- authorizationUrl: "https://login.salesforce.com/services/oauth2/authorize",
600
- tokenUrl: "https://login.salesforce.com/services/oauth2/token",
601
- redirectUriTemplate: "https://{host}/api/integrations/oauth/salesforce/callback",
602
- credentialFields: [
603
- { label: "Client ID", env: "SALESFORCE_OAUTH_CLIENT_ID", description: "Salesforce connected app consumer key.", secret: false },
604
- { label: "Client Secret", env: "SALESFORCE_OAUTH_CLIENT_SECRET", description: "Salesforce connected app consumer secret.", secret: true }
605
- ],
606
- consoleSteps: [
607
- { id: "connected-app", title: "Create connected app", detail: "Create a Salesforce connected app with OAuth enabled." },
608
- { id: "callback", title: "Add callback URL", detail: "Add {redirectUri} as the callback URL.", copyValue: "{redirectUri}" },
609
- { id: "scopes", title: "Select scopes", detail: "Add api and refresh_token/offline_access, plus any connector-specific scopes." }
610
- ],
611
- knownQuirks: [
612
- { id: "instance-url", severity: "critical", message: "Runtime calls must use the instance_url returned by the token response." }
613
- ],
614
- lifecycle: { supportsRefresh: true, supportsRevoke: true, supportsIncrementalAuth: false, recommendedHealthcheckIntervalHours: 24 }
615
- },
616
- hubspot: {
617
- id: "hubspot",
618
- title: "HubSpot OAuth",
619
- authMode: "oauth2",
620
- consoleUrl: "https://developers.hubspot.com/",
621
- authorizationUrl: "https://app.hubspot.com/oauth/authorize",
622
- tokenUrl: "https://api.hubapi.com/oauth/v1/token",
623
- redirectUriTemplate: "https://{host}/api/integrations/oauth/hubspot/callback",
624
- credentialFields: [
625
- { label: "Client ID", env: "HUBSPOT_OAUTH_CLIENT_ID", description: "HubSpot app client ID.", secret: false },
626
- { label: "Client Secret", env: "HUBSPOT_OAUTH_CLIENT_SECRET", description: "HubSpot app client secret.", secret: true }
627
- ],
628
- consoleSteps: [
629
- { id: "app", title: "Create private/public app", detail: "Create a HubSpot app and configure OAuth." },
630
- { id: "redirect", title: "Add redirect URL", detail: "Add {redirectUri} to the app redirect URLs.", copyValue: "{redirectUri}" },
631
- { id: "scopes", title: "Add CRM scopes", detail: "Add the CRM object scopes listed in this spec." }
632
- ],
633
- lifecycle: { supportsRefresh: true, supportsRevoke: true, supportsIncrementalAuth: false, recommendedHealthcheckIntervalHours: 24 }
634
- },
635
- slack: {
636
- id: "slack",
637
- title: "Slack OAuth",
638
- authMode: "oauth2",
639
- consoleUrl: "https://api.slack.com/apps",
640
- authorizationUrl: "https://slack.com/oauth/v2/authorize",
641
- tokenUrl: "https://slack.com/api/oauth.v2.access",
642
- redirectUriTemplate: "https://{host}/api/integrations/oauth/slack/callback",
643
- credentialFields: [
644
- { label: "Client ID", env: "SLACK_OAUTH_CLIENT_ID", description: "Slack app client ID.", secret: false },
645
- { label: "Client Secret", env: "SLACK_OAUTH_CLIENT_SECRET", description: "Slack app client secret.", secret: true }
646
- ],
647
- consoleSteps: [
648
- { id: "app", title: "Create Slack app", detail: "Create or open a Slack app." },
649
- { id: "redirect", title: "Add redirect URL", detail: "Add {redirectUri} under OAuth & Permissions.", copyValue: "{redirectUri}" },
650
- { id: "scopes", title: "Add bot scopes", detail: "Add the bot token scopes listed in this spec and reinstall the app." }
651
- ],
652
- knownQuirks: [
653
- { id: "bot-token", severity: "info", message: "Slack usually returns a bot access token; refresh tokens require token rotation." }
654
- ],
655
- lifecycle: { supportsRefresh: false, supportsRevoke: true, supportsIncrementalAuth: false, recommendedHealthcheckIntervalHours: 24 }
656
- },
657
- notion: {
658
- id: "notion",
659
- title: "Notion OAuth",
660
- authMode: "oauth2",
661
- consoleUrl: "https://www.notion.so/my-integrations",
662
- authorizationUrl: "https://api.notion.com/v1/oauth/authorize",
663
- tokenUrl: "https://api.notion.com/v1/oauth/token",
664
- redirectUriTemplate: "https://{host}/api/integrations/oauth/notion/callback",
665
- credentialFields: [
666
- { label: "Client ID", env: "NOTION_OAUTH_CLIENT_ID", description: "Notion integration OAuth client ID.", secret: false },
667
- { label: "Client Secret", env: "NOTION_OAUTH_CLIENT_SECRET", description: "Notion integration OAuth client secret.", secret: true }
668
- ],
669
- consoleSteps: [
670
- { id: "integration", title: "Create integration", detail: "Create a Notion public integration." },
671
- { id: "redirect", title: "Add redirect URI", detail: "Add {redirectUri} as the redirect URI.", copyValue: "{redirectUri}" },
672
- { id: "capabilities", title: "Select capabilities", detail: "Enable read/update/insert capabilities matching this connector." }
673
- ],
674
- lifecycle: { supportsRefresh: true, supportsRevoke: true, supportsIncrementalAuth: false, recommendedHealthcheckIntervalHours: 24 }
675
- },
676
- "standard-oauth2": {
677
- id: "standard-oauth2",
678
- title: "Standard OAuth 2.0",
679
- authMode: "oauth2",
680
- redirectUriTemplate: "https://{host}/api/integrations/oauth/{kind}/callback",
681
- credentialFields: [
682
- { label: "Client ID", description: "OAuth client ID.", secret: false },
683
- { label: "Client Secret", description: "OAuth client secret.", secret: true }
684
- ],
685
- consoleSteps: [
686
- { id: "app", title: "Create OAuth app", detail: "Create an OAuth app in the provider console." },
687
- { id: "redirect", title: "Add redirect URI", detail: "Add {redirectUri} as an allowed redirect URI.", copyValue: "{redirectUri}" },
688
- { id: "scopes", title: "Add scopes", detail: "Add the scopes listed in this spec." }
689
- ],
690
- lifecycle: { supportsRefresh: true, supportsRevoke: false, supportsIncrementalAuth: false, recommendedHealthcheckIntervalHours: 24 }
691
- },
692
- "api-key": {
693
- id: "api-key",
694
- title: "API key",
695
- authMode: "api_key",
696
- credentialFields: [
697
- { label: "API Key", description: "Provider API key or token.", example: "sk_...", secret: true }
698
- ],
699
- consoleSteps: [
700
- { id: "token", title: "Create token", detail: "Create an API key/token in the provider console with the minimum required permissions." }
701
- ],
702
- lifecycle: { supportsRefresh: false, supportsRevoke: true, supportsIncrementalAuth: false, recommendedHealthcheckIntervalHours: 24 }
703
- },
704
- hmac: {
705
- id: "hmac",
706
- title: "HMAC secret",
707
- authMode: "hmac",
708
- credentialFields: [
709
- { label: "Signing Secret", description: "Webhook signing secret.", secret: true }
710
- ],
711
- consoleSteps: [
712
- { id: "secret", title: "Configure signing secret", detail: "Configure the shared signing secret in the sender and receiver." }
713
- ],
714
- lifecycle: { supportsRefresh: false, supportsRevoke: true, supportsIncrementalAuth: false, recommendedHealthcheckIntervalHours: 24 }
715
- },
716
- none: {
717
- id: "none",
718
- title: "No authentication",
719
- authMode: "none",
720
- credentialFields: [],
721
- consoleSteps: [
722
- { id: "configure", title: "Configure endpoint", detail: "No provider credentials are required." }
723
- ],
724
- lifecycle: { supportsRefresh: false, supportsRevoke: false, supportsIncrementalAuth: false }
725
- }
726
- };
727
- function getIntegrationFamily(id) {
728
- return INTEGRATION_FAMILIES[id];
729
- }
730
-
731
- // src/specs/overrides.ts
732
- var INTEGRATION_OVERRIDES = {
733
- // ── Stripe pack ────────────────────────────────────────────────────
734
- // Stripe issues two key types: secret keys (sk_*) and restricted keys
735
- // (rk_*). For voice-agent workloads, restricted keys are the right call
736
- // — least-privilege scoped to the specific resources the agent can
737
- // touch. The hint nudges operators toward that path.
738
- "stripe-pack": {
739
- consoleUrl: "https://dashboard.stripe.com/apikeys",
740
- credentialFields: [
741
- {
742
- label: "Stripe secret key",
743
- description: "Restricted key recommended. Dashboard \u2192 Developers \u2192 API keys \u2192 Create restricted key. Grant write access on Customers, Invoices, and Checkout Sessions.",
744
- example: "sk_live_\u2026 or rk_live_\u2026 (use sk_test_\u2026 / rk_test_\u2026 for staging)",
745
- regex: "^(sk|rk)_(live|test)_[A-Za-z0-9]+$",
746
- secret: true
747
- }
748
- ],
749
- consoleSteps: [
750
- {
751
- id: "open-keys",
752
- title: "Open Stripe API keys",
753
- detail: "Visit https://dashboard.stripe.com/apikeys",
754
- copyValue: "https://dashboard.stripe.com/apikeys"
755
- },
756
- {
757
- id: "create-restricted",
758
- title: "Create a restricted key",
759
- detail: 'Click "Create restricted key". Name it something descriptive (e.g. "ph0ny voice agent \u2014 prod"). Grant WRITE on Customers, Invoices, and Checkout Sessions. Leave everything else NONE.'
760
- },
761
- {
762
- id: "paste",
763
- title: "Paste the key",
764
- detail: "Copy the key Stripe shows once (rk_live_\u2026 or sk_live_\u2026). Paste it into ph0ny. The key is sealed before persistence."
765
- }
766
- ]
767
- },
768
- // ── Twilio SMS ─────────────────────────────────────────────────────
769
- // Twilio's REST API uses Basic auth with two parts: Account SID
770
- // (public-ish, AC…) + Auth Token (secret). The default api-key family
771
- // only exposes one field, which doesn't fit. Providing both fields
772
- // explicitly lets the consumer's UI render two inputs.
773
- "twilio-sms": {
774
- consoleUrl: "https://console.twilio.com/",
775
- credentialFields: [
776
- {
777
- label: "Account SID",
778
- description: "Your Twilio Account SID. Console \u2192 Account \u2192 API keys & tokens.",
779
- example: "AC\u2026 (34 hex chars)",
780
- regex: "^AC[a-f0-9]{32}$",
781
- secret: false
782
- },
783
- {
784
- label: "Auth Token",
785
- description: "Your Twilio Auth Token (or Standard API Key secret). Use a non-primary auth token in production so rotating it won't break other Twilio integrations.",
786
- secret: true
787
- }
788
- ],
789
- consoleSteps: [
790
- {
791
- id: "open",
792
- title: "Open Twilio console",
793
- detail: "Visit https://console.twilio.com/",
794
- copyValue: "https://console.twilio.com/"
795
- },
796
- {
797
- id: "find",
798
- title: "Find your Account SID + Auth Token",
799
- detail: "Account info is on the dashboard home. For better security, create a Standard API Key (Account \u2192 API keys & tokens \u2192 Create API Key) and use the SID + Secret pair instead of the primary auth token."
800
- },
801
- {
802
- id: "paste",
803
- title: "Paste both values",
804
- detail: "Account SID is non-secret; Auth Token is sealed before persistence."
805
- }
806
- ],
807
- knownQuirks: [
808
- {
809
- id: "subaccount-tokens",
810
- severity: "info",
811
- message: "If you use Twilio subaccounts, paste the SID/Token of the subaccount that owns the phone numbers your agent calls \u2014 not the master account."
812
- }
813
- ]
814
- }
815
- };
816
- function getIntegrationOverride(kind) {
817
- return INTEGRATION_OVERRIDES[kind];
818
- }
819
-
820
- // src/specs/registry.ts
821
- var EXECUTABLE_KINDS = /* @__PURE__ */ new Set([
822
- "google-calendar",
823
- "google-sheets",
824
- "outlook-calendar",
825
- "microsoft-calendar",
826
- "slack",
827
- "hubspot",
828
- "notion",
829
- "notion-database",
830
- "salesforce",
831
- "github",
832
- "gitlab",
833
- "airtable",
834
- "asana",
835
- "stripe",
836
- "stripe-pack",
837
- "twilio",
838
- "twilio-sms",
839
- "webhook"
840
- ]);
841
- var KIND_ALIASES = {
842
- "outlook-calendar": "microsoft-calendar",
843
- notion: "notion-database",
844
- stripe: "stripe-pack",
845
- twilio: "twilio-sms"
846
- };
847
- function listIntegrationSpecs() {
848
- const connectors = new Map(buildIntegrationCoverageConnectors({ providerId: "spec" }).map((c) => [c.id, c]));
849
- return listIntegrationCoverageSpecs().map((coverage) => {
850
- const connector = connectors.get(coverage.id);
851
- if (!connector) throw new Error(`missing coverage connector for ${coverage.id}`);
852
- return specFromCoverage(coverage, connector);
853
- });
854
- }
855
- function getIntegrationSpec(kind) {
856
- const canonical = KIND_ALIASES[kind] ?? kind;
857
- return listIntegrationSpecs().find((spec) => spec.kind === canonical || KIND_ALIASES[spec.kind] === canonical);
858
- }
859
- function listExecutableIntegrationSpecs() {
860
- return listIntegrationSpecs().filter((spec) => spec.status === "executable");
861
- }
862
- function integrationSpecToConnector(spec, providerId = "spec") {
863
- return {
864
- id: spec.kind,
865
- providerId,
866
- title: spec.title,
867
- category: spec.category,
868
- auth: spec.auth.mode === "api_key" ? "api_key" : spec.auth.mode === "oauth2" ? "oauth2" : spec.auth.mode === "none" ? "none" : "custom",
869
- scopes: spec.permissions.flatMap((permission) => permission.providerScopes),
870
- actions: spec.actions,
871
- triggers: spec.triggers,
872
- metadata: {
873
- ...spec.metadata ?? {},
874
- source: "integration-spec",
875
- status: spec.status,
876
- family: spec.family,
877
- plannerHints: spec.plannerHints
878
- }
879
- };
880
- }
881
- function specFromCoverage(coverage, connector) {
882
- const kind = KIND_ALIASES[coverage.id] ?? coverage.id;
883
- const family = familyFor(coverage);
884
- const familySpec = getIntegrationFamily(family);
885
- const permissions = permissionsFor(coverage, connector.actions);
886
- const auth = authFor(coverage, family, permissions);
887
- const status = statusFor(kind);
888
- const override = getIntegrationOverride(kind) ?? getIntegrationOverride(coverage.id);
889
- const knownQuirks = override?.knownQuirks ? [...familySpec.knownQuirks ?? [], ...override.knownQuirks] : familySpec.knownQuirks;
890
- return {
891
- kind,
892
- title: connector.title,
893
- category: connector.category,
894
- status,
895
- family,
896
- auth,
897
- permissions,
898
- actions: connector.actions,
899
- triggers: connector.triggers,
900
- setup: {
901
- consoleUrl: override?.consoleUrl ?? familySpec.consoleUrl,
902
- consoleSteps: override?.consoleSteps ?? familySpec.consoleSteps,
903
- credentialFields: override?.credentialFields ?? credentialFieldsFor(auth),
904
- redirectUriTemplate: auth.mode === "oauth2" ? auth.redirectUriTemplate : familySpec.redirectUriTemplate,
905
- knownQuirks,
906
- postSetup: override?.postSetup,
907
- healthcheck: override?.healthcheck ?? healthcheckFor(kind, status, auth)
908
- },
909
- lifecycle: familySpec.lifecycle,
910
- plannerHints: plannerHintsFor(coverage, connector.actions),
911
- metadata: { priority: coverage.priority, domains: coverage.domains }
912
- };
913
- }
914
- function familyFor(spec) {
915
- if (hmacKinds.has(spec.id)) return "hmac";
916
- if (spec.auth === "none") return "none";
917
- if (spec.id.startsWith("google-") || spec.domains.includes("google")) return "google";
918
- if (spec.id.startsWith("microsoft-") || ["outlook-mail", "outlook-calendar", "onedrive", "sharepoint"].includes(spec.id)) return "microsoft-graph";
919
- if (["jira", "confluence", "trello", "bitbucket"].includes(spec.id)) return "atlassian";
920
- if (spec.id === "salesforce") return "salesforce";
921
- if (spec.id === "hubspot") return "hubspot";
922
- if (spec.id === "slack") return "slack";
923
- if (spec.id === "notion") return "notion";
924
- if (apiKeyKinds.has(spec.id)) return "api-key";
925
- return "standard-oauth2";
926
- }
927
- var apiKeyKinds = /* @__PURE__ */ new Set(["github", "gitlab", "airtable", "asana", "stripe", "twilio", "sendgrid", "postmark"]);
928
- var hmacKinds = /* @__PURE__ */ new Set(["webhook"]);
929
- function authFor(spec, family, permissions) {
930
- const f = INTEGRATION_FAMILIES[family];
931
- if (family === "none") return { mode: "none" };
932
- if (family === "hmac") {
933
- return { mode: "hmac", credential: f.credentialFields[0], signatureHeader: `${spec.id}-signature` };
934
- }
935
- if (family === "api-key") {
936
- return { mode: "api_key", credential: apiKeyFieldFor(spec.id), placement: apiKeyPlacementFor(spec.id) };
937
- }
938
- const scopes = permissions.flatMap(
939
- (permission) => permission.providerScopes.map((providerScope) => ({
940
- normalized: permission.normalized,
941
- providerScope,
942
- title: permission.title,
943
- reason: permission.reason,
944
- risk: permission.risk,
945
- dataClass: permission.dataClass
946
- }))
947
- );
948
- return {
949
- mode: "oauth2",
950
- authorizationUrl: f.authorizationUrl ?? `https://example.invalid/${spec.id}/authorize`,
951
- tokenUrl: f.tokenUrl ?? `https://example.invalid/${spec.id}/token`,
952
- clientIdEnv: f.credentialFields.find((field) => !field.secret)?.env,
953
- clientSecretEnv: f.credentialFields.find((field) => field.secret)?.env,
954
- scopes,
955
- extraAuthParams: extraAuthParamsFor(family),
956
- redirectUriTemplate: (f.redirectUriTemplate ?? "https://{host}/api/integrations/oauth/{kind}/callback").replace("{kind}", spec.id),
957
- pkce: family === "google" || family === "microsoft-graph" ? "supported" : "unsupported"
958
- };
959
- }
960
- function credentialFieldsFor(auth) {
961
- if (auth.mode === "api_key" || auth.mode === "hmac") return [auth.credential];
962
- if (auth.mode === "oauth2") {
963
- return [
964
- { label: "Client ID", env: auth.clientIdEnv, description: "OAuth client ID.", secret: false },
965
- { label: "Client Secret", env: auth.clientSecretEnv, description: "OAuth client secret.", secret: true }
966
- ];
967
- }
968
- return [];
969
- }
970
- function permissionsFor(spec, actions) {
971
- const dataClass = dataClassFor3(actions);
972
- const readScope = providerScopeFor(spec, "read");
973
- const writeScope = providerScopeFor(spec, "write");
974
- const permissions = [
975
- {
976
- normalized: `${spec.actionPack}.read`,
977
- providerScopes: readScope ? [readScope] : [],
978
- title: `${spec.title} read`,
979
- risk: "read",
980
- dataClass,
981
- reason: `Read ${spec.title} data for user-authorized agent workflows.`
982
- }
983
- ];
984
- if (actions.some((a) => a.risk !== "read")) {
985
- permissions.push({
986
- normalized: `${spec.actionPack}.write`,
987
- providerScopes: writeScope ? [writeScope] : [],
988
- title: `${spec.title} write`,
989
- risk: "write",
990
- dataClass,
991
- reason: `Create or update ${spec.title} resources after policy approval.`
992
- });
993
- }
994
- return permissions;
995
- }
996
- function providerScopeFor(spec, mode) {
997
- const explicit = explicitScopes[spec.id]?.[mode];
998
- if (explicit) return explicit;
999
- if (spec.auth === "none") return "";
1000
- return `${spec.id}.${mode}`;
1001
- }
1002
- var explicitScopes = {
1003
- gmail: { read: "https://www.googleapis.com/auth/gmail.readonly", write: "https://www.googleapis.com/auth/gmail.modify" },
1004
- "google-calendar": { read: "https://www.googleapis.com/auth/calendar.readonly", write: "https://www.googleapis.com/auth/calendar" },
1005
- "google-sheets": { read: "https://www.googleapis.com/auth/spreadsheets.readonly", write: "https://www.googleapis.com/auth/spreadsheets" },
1006
- "google-drive": { read: "https://www.googleapis.com/auth/drive.readonly", write: "https://www.googleapis.com/auth/drive.file" },
1007
- "google-docs": { read: "https://www.googleapis.com/auth/documents.readonly", write: "https://www.googleapis.com/auth/documents" },
1008
- "outlook-mail": { read: "Mail.Read", write: "Mail.Send" },
1009
- "outlook-calendar": { read: "Calendars.Read", write: "Calendars.ReadWrite" },
1010
- "microsoft-teams": { read: "ChannelMessage.Read.All", write: "ChannelMessage.Send" },
1011
- onedrive: { read: "Files.Read", write: "Files.ReadWrite" },
1012
- sharepoint: { read: "Sites.Read.All", write: "Sites.ReadWrite.All" },
1013
- slack: { read: "channels:read", write: "chat:write" },
1014
- hubspot: { read: "crm.objects.contacts.read", write: "crm.objects.contacts.write" },
1015
- salesforce: { read: "api", write: "api" },
1016
- notion: { read: "", write: "" },
1017
- github: { read: "repo:read", write: "repo" },
1018
- gitlab: { read: "read_api", write: "api" },
1019
- airtable: { read: "data.records:read", write: "data.records:write" },
1020
- asana: { read: "default", write: "default" },
1021
- stripe: { read: "read_only", write: "standard" },
1022
- twilio: { read: "api_key", write: "api_key" }
1023
- };
1024
- function plannerHintsFor(spec, actions) {
1025
- return {
1026
- useFor: spec.domains.map((domain) => domain.replace(/-/g, " ")),
1027
- dataFreshness: ["calendar", "chat", "commerce", "finance", "support"].includes(spec.actionPack) ? "near_realtime" : "eventual",
1028
- writeRisk: actions.some((a) => a.risk === "destructive") ? "high" : actions.some((a) => a.risk === "write") ? "medium" : "low"
1029
- };
1030
- }
1031
- function healthcheckFor(kind, status, auth) {
1032
- if (status !== "executable") {
1033
- return { id: `${kind}.static`, level: "static", description: "Catalog-only integration; no executable connector healthcheck is available yet." };
1034
- }
1035
- if (auth.mode === "oauth2") {
1036
- return { id: `${kind}.connection`, level: "connection", description: "Validate a user connection by calling the connector test endpoint." };
1037
- }
1038
- if (auth.mode === "api_key") {
1039
- return { id: `${kind}.connection`, level: "connection", description: "Validate API credentials by calling the connector test endpoint." };
1040
- }
1041
- if (auth.mode === "hmac") {
1042
- return { id: `${kind}.webhook`, level: "webhook", description: "Validate webhook signing configuration with a signed test payload." };
1043
- }
1044
- return { id: `${kind}.static`, level: "static", description: "No credentials are required." };
1045
- }
1046
- function statusFor(kind) {
1047
- return EXECUTABLE_KINDS.has(kind) ? "executable" : "catalog";
1048
- }
1049
- function dataClassFor3(actions) {
1050
- if (actions.some((a) => a.dataClass === "secret")) return "secret";
1051
- if (actions.some((a) => a.dataClass === "sensitive")) return "sensitive";
1052
- if (actions.some((a) => a.dataClass === "private")) return "private";
1053
- if (actions.some((a) => a.dataClass === "internal")) return "internal";
1054
- return "public";
1055
- }
1056
- function apiKeyFieldFor(kind) {
1057
- return {
1058
- label: `${kind} API key`,
1059
- description: `API key or token for ${kind}.`,
1060
- example: kind === "stripe" ? "sk_live_..." : void 0,
1061
- secret: true
1062
- };
1063
- }
1064
- function apiKeyPlacementFor(kind) {
1065
- if (kind === "gitlab") return "header";
1066
- return "bearer";
1067
- }
1068
- function extraAuthParamsFor(family) {
1069
- if (family === "google") return { access_type: "offline", prompt: "consent", include_granted_scopes: "true" };
1070
- if (family === "notion") return { owner: "user" };
1071
- return void 0;
1072
- }
1073
-
1074
235
  // src/registry.ts
1075
236
  var DEFAULT_ALIASES = {
1076
237
  notion: "notion-database",
@@ -1578,7 +739,7 @@ function googleCalendarConnector(providerId) {
1578
739
  requiredScopes: ["https://www.googleapis.com/auth/calendar.readonly"],
1579
740
  dataClass: "private",
1580
741
  description: "Read events from a Google Calendar over a bounded time range.",
1581
- inputSchema: objectSchema2({
742
+ inputSchema: objectSchema({
1582
743
  calendarId: { type: "string", default: "primary" },
1583
744
  timeMin: { type: "string", description: "RFC3339 lower bound." },
1584
745
  timeMax: { type: "string", description: "RFC3339 upper bound." }
@@ -1592,7 +753,7 @@ function googleCalendarConnector(providerId) {
1592
753
  dataClass: "private",
1593
754
  approvalRequired: true,
1594
755
  description: "Create an event on a Google Calendar after user approval.",
1595
- inputSchema: objectSchema2({
756
+ inputSchema: objectSchema({
1596
757
  calendarId: { type: "string", default: "primary" },
1597
758
  start: { type: "string", description: "RFC3339 start time." },
1598
759
  end: { type: "string", description: "RFC3339 end time." },
@@ -1621,7 +782,7 @@ function gmailConnector(providerId) {
1621
782
  requiredScopes: ["https://www.googleapis.com/auth/gmail.readonly"],
1622
783
  dataClass: "private",
1623
784
  description: "Search user Gmail messages and return bounded message metadata/snippets.",
1624
- inputSchema: objectSchema2({ query: { type: "string" }, maxResults: { type: "integer", minimum: 1, maximum: 50 } }, ["query"])
785
+ inputSchema: objectSchema({ query: { type: "string" }, maxResults: { type: "integer", minimum: 1, maximum: 50 } }, ["query"])
1625
786
  },
1626
787
  {
1627
788
  id: CANONICAL_INTEGRATION_ACTIONS.gmailMessagesSend,
@@ -1631,7 +792,7 @@ function gmailConnector(providerId) {
1631
792
  dataClass: "private",
1632
793
  approvalRequired: true,
1633
794
  description: "Send an email from the user account after approval.",
1634
- inputSchema: objectSchema2({
795
+ inputSchema: objectSchema({
1635
796
  to: { type: "array", items: { type: "string" } },
1636
797
  subject: { type: "string" },
1637
798
  body: { type: "string" }
@@ -1664,7 +825,7 @@ function googleDriveConnector(providerId) {
1664
825
  requiredScopes: ["https://www.googleapis.com/auth/drive.readonly"],
1665
826
  dataClass: "private",
1666
827
  description: "Search user-visible Google Drive files.",
1667
- inputSchema: objectSchema2({ query: { type: "string" }, maxResults: { type: "integer", minimum: 1, maximum: 50 } }, ["query"])
828
+ inputSchema: objectSchema({ query: { type: "string" }, maxResults: { type: "integer", minimum: 1, maximum: 50 } }, ["query"])
1668
829
  },
1669
830
  {
1670
831
  id: CANONICAL_INTEGRATION_ACTIONS.googleDriveFilesRead,
@@ -1673,7 +834,7 @@ function googleDriveConnector(providerId) {
1673
834
  requiredScopes: ["https://www.googleapis.com/auth/drive.readonly"],
1674
835
  dataClass: "private",
1675
836
  description: "Read metadata and content for an authorized Drive file.",
1676
- inputSchema: objectSchema2({ fileId: { type: "string" } }, ["fileId"])
837
+ inputSchema: objectSchema({ fileId: { type: "string" } }, ["fileId"])
1677
838
  }
1678
839
  ],
1679
840
  metadata: { source: "canonical-launch", supportTier: "setupReady" }
@@ -1688,10 +849,10 @@ function githubConnector(providerId) {
1688
849
  auth: "oauth2",
1689
850
  scopes: ["repo", "read:user"],
1690
851
  actions: [
1691
- readAction(CANONICAL_INTEGRATION_ACTIONS.githubRepositoriesGet, "Read repository metadata", ["repo"], objectSchema2({ owner: { type: "string" }, repo: { type: "string" } }, ["owner", "repo"])),
1692
- readAction(CANONICAL_INTEGRATION_ACTIONS.githubIssuesSearch, "Search issues and pull requests", ["repo"], objectSchema2({ query: { type: "string" }, limit: { type: "integer", minimum: 1, maximum: 50 } }, ["query"])),
1693
- writeAction(CANONICAL_INTEGRATION_ACTIONS.githubIssuesCreate, "Create issue", ["repo"], objectSchema2({ owner: { type: "string" }, repo: { type: "string" }, title: { type: "string" }, body: { type: "string" } }, ["owner", "repo", "title"])),
1694
- writeAction(CANONICAL_INTEGRATION_ACTIONS.githubPullRequestsComment, "Comment on pull request", ["repo"], objectSchema2({ owner: { type: "string" }, repo: { type: "string" }, pullNumber: { type: "integer" }, body: { type: "string" } }, ["owner", "repo", "pullNumber", "body"]))
852
+ readAction(CANONICAL_INTEGRATION_ACTIONS.githubRepositoriesGet, "Read repository metadata", ["repo"], objectSchema({ owner: { type: "string" }, repo: { type: "string" } }, ["owner", "repo"])),
853
+ readAction(CANONICAL_INTEGRATION_ACTIONS.githubIssuesSearch, "Search issues and pull requests", ["repo"], objectSchema({ query: { type: "string" }, limit: { type: "integer", minimum: 1, maximum: 50 } }, ["query"])),
854
+ writeAction(CANONICAL_INTEGRATION_ACTIONS.githubIssuesCreate, "Create issue", ["repo"], objectSchema({ owner: { type: "string" }, repo: { type: "string" }, title: { type: "string" }, body: { type: "string" } }, ["owner", "repo", "title"])),
855
+ writeAction(CANONICAL_INTEGRATION_ACTIONS.githubPullRequestsComment, "Comment on pull request", ["repo"], objectSchema({ owner: { type: "string" }, repo: { type: "string" }, pullNumber: { type: "integer" }, body: { type: "string" } }, ["owner", "repo", "pullNumber", "body"]))
1695
856
  ],
1696
857
  metadata: { source: "canonical-launch", supportTier: "setupReady" }
1697
858
  };
@@ -1705,9 +866,9 @@ function slackConnector(providerId) {
1705
866
  auth: "oauth2",
1706
867
  scopes: ["channels:read", "search:read", "chat:write"],
1707
868
  actions: [
1708
- readAction(CANONICAL_INTEGRATION_ACTIONS.slackChannelsList, "List Slack channels", ["channels:read"], objectSchema2({ limit: { type: "integer", minimum: 1, maximum: 200 } })),
1709
- readAction(CANONICAL_INTEGRATION_ACTIONS.slackMessagesSearch, "Search Slack messages", ["search:read"], objectSchema2({ query: { type: "string" }, count: { type: "integer", minimum: 1, maximum: 50 } }, ["query"])),
1710
- writeAction(CANONICAL_INTEGRATION_ACTIONS.slackMessagesPost, "Post Slack message", ["chat:write"], objectSchema2({ channel: { type: "string" }, text: { type: "string" }, blocks: { type: "array" } }, ["channel", "text"]))
869
+ readAction(CANONICAL_INTEGRATION_ACTIONS.slackChannelsList, "List Slack channels", ["channels:read"], objectSchema({ limit: { type: "integer", minimum: 1, maximum: 200 } })),
870
+ readAction(CANONICAL_INTEGRATION_ACTIONS.slackMessagesSearch, "Search Slack messages", ["search:read"], objectSchema({ query: { type: "string" }, count: { type: "integer", minimum: 1, maximum: 50 } }, ["query"])),
871
+ writeAction(CANONICAL_INTEGRATION_ACTIONS.slackMessagesPost, "Post Slack message", ["chat:write"], objectSchema({ channel: { type: "string" }, text: { type: "string" }, blocks: { type: "array" } }, ["channel", "text"]))
1711
872
  ],
1712
873
  triggers: [trigger("slack.message.posted", "Slack message posted", ["channels:read"])],
1713
874
  metadata: { source: "canonical-launch", supportTier: "setupReady" }
@@ -1731,7 +892,7 @@ function providerPassthroughAction(connectorId) {
1731
892
  dataClass: "sensitive",
1732
893
  approvalRequired: true,
1733
894
  description: `Controlled provider-native passthrough for ${connectorId}. Disabled by default by platform policy.`,
1734
- inputSchema: objectSchema2({
895
+ inputSchema: objectSchema({
1735
896
  method: { type: "string", enum: ["GET", "POST", "PUT", "PATCH", "DELETE"] },
1736
897
  path: { type: "string" },
1737
898
  query: { type: "object" },
@@ -1739,7 +900,7 @@ function providerPassthroughAction(connectorId) {
1739
900
  }, ["method", "path"])
1740
901
  };
1741
902
  }
1742
- function objectSchema2(properties, required = []) {
903
+ function objectSchema(properties, required = []) {
1743
904
  return { type: "object", additionalProperties: false, properties, required };
1744
905
  }
1745
906
 
@@ -6869,123 +6030,6 @@ function sameActor2(a, b) {
6869
6030
  return a.type === b.type && a.id === b.id;
6870
6031
  }
6871
6032
 
6872
- // src/specs/types.ts
6873
- function specAuthToConnectorAuth(auth) {
6874
- if (auth.mode === "api_key") return "api_key";
6875
- if (auth.mode === "oauth2") return "oauth2";
6876
- if (auth.mode === "none") return "none";
6877
- return "custom";
6878
- }
6879
-
6880
- // src/specs/renderers.ts
6881
- function renderConsoleSteps(spec, options) {
6882
- const redirectUri = renderRedirectUri(spec, options);
6883
- return spec.setup.consoleSteps.map((step) => ({
6884
- ...step,
6885
- detail: renderTemplate(step.detail, spec, options, redirectUri),
6886
- copyValue: step.copyValue ? renderTemplate(step.copyValue, spec, options, redirectUri) : void 0
6887
- }));
6888
- }
6889
- function renderRunbookMarkdown(spec, options) {
6890
- const steps = renderConsoleSteps(spec, options);
6891
- const lines = [
6892
- `# ${spec.title} Integration Setup`,
6893
- "",
6894
- `- Kind: \`${spec.kind}\``,
6895
- `- Status: \`${spec.status}\``,
6896
- `- Auth: \`${spec.auth.mode}\``,
6897
- `- Family: \`${spec.family}\``
6898
- ];
6899
- if (spec.setup.consoleUrl) lines.push(`- Console: ${spec.setup.consoleUrl}`);
6900
- if (spec.setup.redirectUriTemplate) lines.push(`- Redirect URI: \`${renderRedirectUri(spec, options)}\``);
6901
- lines.push("", "## Credentials", "");
6902
- for (const field of spec.setup.credentialFields) {
6903
- lines.push(`- ${field.secret ? "[secret] " : ""}${field.label}${field.env ? ` (\`${field.env}\`)` : ""}: ${field.description}`);
6904
- }
6905
- lines.push("", "## Permissions", "");
6906
- for (const permission of spec.permissions) {
6907
- lines.push(`- \`${permission.normalized}\`: ${permission.providerScopes.length ? permission.providerScopes.map((scope) => `\`${scope}\``).join(", ") : "no provider scope"} - ${permission.reason}`);
6908
- }
6909
- lines.push("", "## Console Steps", "");
6910
- for (const [i, step] of steps.entries()) {
6911
- lines.push(`${i + 1}. ${step.title}: ${step.detail}`);
6912
- }
6913
- if (spec.setup.knownQuirks?.length) {
6914
- lines.push("", "## Known Quirks", "");
6915
- for (const quirk of spec.setup.knownQuirks) lines.push(`- ${quirk.severity}: ${quirk.message}`);
6916
- }
6917
- return `${lines.join("\n")}
6918
- `;
6919
- }
6920
- function renderAgentToolDescription(spec) {
6921
- const hints = spec.plannerHints;
6922
- const useFor = hints?.useFor?.length ? `Use for ${hints.useFor.join(", ")}.` : `Use for ${spec.title} workflows.`;
6923
- const risk = hints ? `Freshness: ${hints.dataFreshness}. Write risk: ${hints.writeRisk}.` : "";
6924
- return `${spec.title} (${spec.kind}). ${useFor} ${risk}`.trim();
6925
- }
6926
- function buildHealthcheckPlan(spec) {
6927
- const healthcheck = spec.setup.healthcheck ?? { id: `${spec.kind}.static`, level: "static", description: "No healthcheck defined." };
6928
- const requires = [];
6929
- if (healthcheck.level === "connection") requires.push("connection_credentials");
6930
- if (healthcheck.level === "client_config" && spec.auth.mode === "oauth2") requires.push("client_id", "client_secret");
6931
- if (spec.auth.mode === "api_key") requires.push("api_key");
6932
- if (spec.auth.mode === "hmac") requires.push("hmac_secret");
6933
- return {
6934
- kind: spec.kind,
6935
- healthcheck,
6936
- requires,
6937
- message: healthcheck.description
6938
- };
6939
- }
6940
- function renderTemplate(template, spec, options, redirectUri) {
6941
- return template.replaceAll("{host}", options.host).replaceAll("{kind}", spec.kind).replaceAll("{redirectUri}", redirectUri ?? renderRedirectUri(spec, options));
6942
- }
6943
- function renderRedirectUri(spec, options) {
6944
- return (options.callbackPath ?? spec.setup.redirectUriTemplate ?? "").replaceAll("{host}", options.host).replaceAll("{kind}", spec.kind);
6945
- }
6946
- function consoleStepsToText(steps) {
6947
- return steps.map((step, index) => `${index + 1}. ${step.title}: ${step.detail}`).join("\n");
6948
- }
6949
-
6950
- // src/specs/validation.ts
6951
- function validateIntegrationSpec(spec) {
6952
- const issues = [];
6953
- if (!spec.kind.trim()) issues.push({ path: "kind", message: "kind is required" });
6954
- if (!spec.title.trim()) issues.push({ path: "title", message: "title is required" });
6955
- if (!spec.actions.length) issues.push({ path: "actions", message: "at least one action is required" });
6956
- if (!spec.permissions.length) issues.push({ path: "permissions", message: "at least one permission is required" });
6957
- if (spec.auth.mode === "oauth2") {
6958
- if (!spec.auth.authorizationUrl) issues.push({ path: "auth.authorizationUrl", message: "authorizationUrl is required" });
6959
- if (!spec.auth.tokenUrl) issues.push({ path: "auth.tokenUrl", message: "tokenUrl is required" });
6960
- if (!spec.auth.redirectUriTemplate) issues.push({ path: "auth.redirectUriTemplate", message: "redirectUriTemplate is required" });
6961
- }
6962
- const actionIds = /* @__PURE__ */ new Set();
6963
- for (const [index, action] of spec.actions.entries()) {
6964
- if (actionIds.has(action.id)) issues.push({ path: `actions[${index}].id`, message: `duplicate action id ${action.id}` });
6965
- actionIds.add(action.id);
6966
- }
6967
- return { ok: issues.length === 0, issues };
6968
- }
6969
- function assertValidIntegrationSpec(spec) {
6970
- const result = validateIntegrationSpec(spec);
6971
- if (!result.ok) {
6972
- throw new Error(`Invalid integration spec ${spec.kind}: ${result.issues.map((i) => `${i.path}: ${i.message}`).join("; ")}`);
6973
- }
6974
- }
6975
- function validateCredentialFormat(field, value) {
6976
- if (!value.trim()) return { ok: false, field: field.label, message: `${field.label} is required` };
6977
- if (field.regex && !new RegExp(field.regex).test(value)) {
6978
- return { ok: false, field: field.label, message: `${field.label} does not match expected format` };
6979
- }
6980
- return { ok: true, field: field.label };
6981
- }
6982
- function validateCredentialSet(spec, values) {
6983
- return spec.setup.credentialFields.map((field) => {
6984
- const key = field.env ?? field.label;
6985
- return validateCredentialFormat(field, values[key] ?? "");
6986
- });
6987
- }
6988
-
6989
6033
  // src/index.ts
6990
6034
  var IntegrationError = class extends Error {
6991
6035
  constructor(message, code) {