@tangle-network/agent-integrations 0.29.0 → 0.31.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 (44) hide show
  1. package/dist/bin/tangle-catalog-runtime.js +7 -7
  2. package/dist/catalog.d.ts +2 -2
  3. package/dist/catalog.js +11 -7
  4. package/dist/{chunk-SVQ4PHDZ.js → chunk-CDY2ETYT.js} +2 -2
  5. package/dist/chunk-F4YILONK.js +96875 -0
  6. package/dist/chunk-F4YILONK.js.map +1 -0
  7. package/dist/{chunk-P24T3MLM.js → chunk-JCHD6L3B.js} +2 -2
  8. package/dist/{chunk-TUX6MJJ4.js → chunk-M2RFFAMB.js} +559 -411
  9. package/dist/chunk-M2RFFAMB.js.map +1 -0
  10. package/dist/{chunk-ATYHZXLL.js → chunk-Q5X3QNHR.js} +1 -1
  11. package/dist/chunk-Q5X3QNHR.js.map +1 -0
  12. package/dist/{chunk-YOKNZY2N.js → chunk-S2MVWQYL.js} +2 -2
  13. package/dist/{chunk-4JQ754PA.js → chunk-VVC7U7W7.js} +28 -1
  14. package/dist/{chunk-4JQ754PA.js.map → chunk-VVC7U7W7.js.map} +1 -1
  15. package/dist/connect/index.d.ts +1 -1
  16. package/dist/connect/index.js +2 -2
  17. package/dist/connectors/adapters/index.d.ts +3933 -3
  18. package/dist/connectors/adapters/index.js +940 -4
  19. package/dist/connectors/index.d.ts +2 -2
  20. package/dist/connectors/index.js +940 -4
  21. package/dist/consumer.d.ts +2 -2
  22. package/dist/consumer.js +2 -2
  23. package/dist/index.d.ts +3 -3
  24. package/dist/index.js +955 -9
  25. package/dist/middleware/index.d.ts +1 -1
  26. package/dist/middleware/index.js +2 -2
  27. package/dist/registry.d.ts +200 -47
  28. package/dist/registry.js +9 -7
  29. package/dist/runtime.d.ts +2 -2
  30. package/dist/runtime.js +7 -7
  31. package/dist/specs.d.ts +2 -2
  32. package/dist/specs.js +3 -1
  33. package/dist/tangle-catalog-runtime.d.ts +2 -2
  34. package/dist/tangle-catalog-runtime.js +7 -7
  35. package/dist/{tangle-id-CTU4kGId.d.ts → tangle-id-Dj0ipP4E.d.ts} +8 -1
  36. package/docs/integration-execution-audit.md +1 -1
  37. package/package.json +16 -12
  38. package/dist/chunk-ATYHZXLL.js.map +0 -1
  39. package/dist/chunk-JU25UDN2.js +0 -4260
  40. package/dist/chunk-JU25UDN2.js.map +0 -1
  41. package/dist/chunk-TUX6MJJ4.js.map +0 -1
  42. /package/dist/{chunk-SVQ4PHDZ.js.map → chunk-CDY2ETYT.js.map} +0 -0
  43. /package/dist/{chunk-P24T3MLM.js.map → chunk-JCHD6L3B.js.map} +0 -0
  44. /package/dist/{chunk-YOKNZY2N.js.map → chunk-S2MVWQYL.js.map} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/connectors/oauth.ts","../src/connectors/adapters/google-calendar.ts","../src/connectors/adapters/google-drive.ts","../src/connectors/adapters/google-sheets.ts","../src/connectors/adapters/gmail.ts","../src/connectors/adapters/microsoft-calendar.ts","../src/connectors/adapters/hubspot.ts","../src/connectors/adapters/slack.ts","../src/connectors/adapters/notion-database.ts","../src/connectors/adapters/docuseal.ts","../src/connectors/adapters/declarative-rest.ts","../src/connectors/adapters/twilio-sms.ts","../src/connectors/adapters/stripe-pack.ts","../src/connectors/adapters/webhook.ts","../src/connectors/adapters/stripe-webhook-receiver.ts","../src/connectors/adapters/slack-events.ts","../src/connectors/adapters/github.ts","../src/connectors/adapters/gitlab.ts","../src/connectors/adapters/airtable.ts","../src/connectors/adapters/asana.ts","../src/connectors/adapters/salesforce.ts"],"sourcesContent":["/**\n * Generic OAuth2 helper used by every oauth-shaped connector (Google\n * Calendar, Sheets, Drive, HubSpot, Salesforce, Zoom, ...).\n *\n * Everything PKCE-aware. Opaque-state CSRF guard. Refresh-token aware.\n * No connector-specific logic lives here — adapters hand a `clientId`,\n * `clientSecret`, `tokenUrl`, optional `extraAuthParams` and the rest is\n * mechanical.\n *\n * State and code_verifier are kept in a short-TTL flow store keyed by the\n * opaque `state` we round-trip through the provider. The default store is\n * in-memory for local/dev and tests. Production deployments should inject a\n * durable store backed by KV/Redis/D1/etc. so callbacks can land on any worker.\n */\n\nimport { createHash, randomBytes } from 'crypto'\n\nexport interface PendingOAuthFlow {\n /** code_verifier for PKCE. */\n codeVerifier: string\n /** Opaque-state value also returned in the OAuth redirect. */\n state: string\n /** Project the user is connecting under. */\n projectId: string\n /** Connector kind (e.g. 'google-calendar'). */\n kind: string\n /** Operator-supplied label that becomes DataSource.label. */\n label: string\n /** When we drop the entry. */\n expiresAt: number\n /** The redirectUri we used in the start step — must match exactly on\n * the callback exchange. */\n redirectUri: string\n}\n\nconst PENDING_TTL_MS = 10 * 60 * 1000\n\nexport interface OAuthFlowStore {\n put(state: string, flow: PendingOAuthFlow): Promise<void> | void\n consume(state: string): Promise<PendingOAuthFlow | undefined> | PendingOAuthFlow | undefined\n sweep?(now: number): Promise<void> | void\n clear?(): Promise<void> | void\n}\n\nexport class InMemoryOAuthFlowStore implements OAuthFlowStore {\n private readonly pendingFlows = new Map<string, PendingOAuthFlow>()\n\n put(state: string, flow: PendingOAuthFlow): void {\n this.pendingFlows.set(state, flow)\n }\n\n consume(state: string): PendingOAuthFlow | undefined {\n const flow = this.pendingFlows.get(state)\n this.pendingFlows.delete(state)\n if (!flow || flow.expiresAt <= Date.now()) return undefined\n return flow\n }\n\n sweep(now: number): void {\n for (const [k, v] of this.pendingFlows) {\n if (v.expiresAt <= now) this.pendingFlows.delete(k)\n }\n }\n\n clear(): void {\n this.pendingFlows.clear()\n }\n}\n\nconst defaultFlowStore = new InMemoryOAuthFlowStore()\n\nexport interface StartOAuthInput {\n projectId: string\n kind: string\n label: string\n authorizationUrl: string\n scopes: string[]\n clientId: string\n redirectUri: string\n /** Optional extra query params; Google needs `access_type=offline` and\n * `prompt=consent` to issue refresh tokens reliably. */\n extraAuthParams?: Record<string, string>\n /** Optional flow store. Use a durable store in distributed production\n * runtimes; omitted means local in-memory storage. */\n store?: OAuthFlowStore\n /** Override clock for tests. */\n now?: number\n}\n\nexport interface StartOAuthOutput {\n /** URL the SPA should redirect the user to. */\n authorizationUrl: string\n /** State token — caller stashes this in localStorage to verify on\n * callback. */\n state: string\n}\n\n/** Build the authorization URL + state. SPA navigates the user there;\n * user consents; provider redirects back to redirectUri with `code` +\n * `state`. The caller's callback then invokes `consumePendingFlow`. */\nexport function startOAuthFlow(input: StartOAuthInput): StartOAuthOutput {\n const store = input.store ?? defaultFlowStore\n const now = input.now ?? Date.now()\n store.sweep?.(now)\n const codeVerifier = base64Url(randomBytes(48))\n const codeChallenge = base64Url(createHash('sha256').update(codeVerifier).digest())\n const state = base64Url(randomBytes(24))\n\n store.put(state, {\n codeVerifier,\n state,\n projectId: input.projectId,\n kind: input.kind,\n label: input.label,\n redirectUri: input.redirectUri,\n expiresAt: now + PENDING_TTL_MS,\n })\n\n const url = new URL(input.authorizationUrl)\n url.searchParams.set('response_type', 'code')\n url.searchParams.set('client_id', input.clientId)\n url.searchParams.set('redirect_uri', input.redirectUri)\n url.searchParams.set('scope', input.scopes.join(' '))\n url.searchParams.set('state', state)\n url.searchParams.set('code_challenge', codeChallenge)\n url.searchParams.set('code_challenge_method', 'S256')\n if (input.extraAuthParams) {\n for (const [k, v] of Object.entries(input.extraAuthParams)) {\n url.searchParams.set(k, v)\n }\n }\n return { authorizationUrl: url.toString(), state }\n}\n\n/** Look up + remove the pending flow record. Throws if state is unknown\n * or expired (CSRF guard / replay protection). */\nexport async function consumePendingFlow(state: string, store: OAuthFlowStore = defaultFlowStore): Promise<PendingOAuthFlow> {\n await store.sweep?.(Date.now())\n const flow = await store.consume(state)\n if (!flow) {\n throw new Error('Unknown or expired OAuth state: possible CSRF, replay, or stale flow')\n }\n return flow\n}\n\nexport interface ExchangeCodeInput {\n tokenUrl: string\n clientId: string\n clientSecret: string\n code: string\n codeVerifier: string\n redirectUri: string\n fetchImpl?: typeof fetch\n signal?: AbortSignal\n}\n\nexport interface OAuthTokens {\n accessToken: string\n refreshToken?: string\n expiresIn?: number\n scope?: string\n tokenType?: string\n}\n\n/** POST authorization code → token endpoint. Provider-agnostic; if a\n * provider returns a non-standard JSON shape, the adapter wraps this\n * call rather than reaching into the helper. */\nexport async function exchangeAuthorizationCode(input: ExchangeCodeInput): Promise<OAuthTokens> {\n const body = new URLSearchParams({\n grant_type: 'authorization_code',\n client_id: input.clientId,\n client_secret: input.clientSecret,\n code: input.code,\n redirect_uri: input.redirectUri,\n code_verifier: input.codeVerifier,\n })\n const res = await (input.fetchImpl ?? fetch)(input.tokenUrl, {\n method: 'POST',\n headers: { 'content-type': 'application/x-www-form-urlencoded', accept: 'application/json' },\n body,\n signal: input.signal,\n })\n if (!res.ok) {\n const text = await res.text().catch(() => '')\n throw new Error(`OAuth token exchange failed: ${res.status} ${res.statusText} — ${text.slice(0, 200)}`)\n }\n const json = (await res.json()) as {\n access_token: string\n refresh_token?: string\n expires_in?: number\n scope?: string\n token_type?: string\n }\n return {\n accessToken: json.access_token,\n refreshToken: json.refresh_token,\n expiresIn: json.expires_in,\n scope: json.scope,\n tokenType: json.token_type,\n }\n}\n\nexport interface RefreshInput {\n tokenUrl: string\n clientId: string\n clientSecret: string\n refreshToken: string\n fetchImpl?: typeof fetch\n signal?: AbortSignal\n}\n\n/** Refresh an access token. Returns the new tokens — the connector layer\n * is responsible for re-encrypting + persisting the envelope. */\nexport async function refreshAccessToken(input: RefreshInput): Promise<OAuthTokens> {\n const body = new URLSearchParams({\n grant_type: 'refresh_token',\n client_id: input.clientId,\n client_secret: input.clientSecret,\n refresh_token: input.refreshToken,\n })\n const res = await (input.fetchImpl ?? fetch)(input.tokenUrl, {\n method: 'POST',\n headers: { 'content-type': 'application/x-www-form-urlencoded', accept: 'application/json' },\n body,\n signal: input.signal,\n })\n if (!res.ok) {\n const text = await res.text().catch(() => '')\n throw new Error(`OAuth refresh failed: ${res.status} ${res.statusText} — ${text.slice(0, 200)}`)\n }\n const json = (await res.json()) as {\n access_token: string\n refresh_token?: string\n expires_in?: number\n scope?: string\n token_type?: string\n }\n return {\n accessToken: json.access_token,\n // Some providers omit refresh_token on refresh — keep the previous one\n // in that case (caller passes through if undefined).\n refreshToken: json.refresh_token,\n expiresIn: json.expires_in,\n scope: json.scope,\n tokenType: json.token_type,\n }\n}\n\nfunction base64Url(buf: Buffer): string {\n return buf.toString('base64').replace(/=+$/, '').replace(/\\+/g, '-').replace(/\\//g, '_')\n}\n\n/** Test-only — drop pending flows between unit-test runs. */\nexport function _resetPendingFlowsForTests(): void {\n defaultFlowStore.clear?.()\n}\n","/**\n * Google Calendar connector — CAS reference implementation.\n *\n * Scopes: `https://www.googleapis.com/auth/calendar` covers list/insert/\n * patch on the user's calendars. We could split read/write but for v1 the\n * single scope keeps the consent screen simple; an operator who wants\n * read-only-Calendar can pick a different `kind` later (`google-calendar-readonly`).\n *\n * The two capabilities the agent actually needs:\n *\n * list_availability(calendarId, timeMin, timeMax)\n * → {busy: [{start, end}], events: [{id, etag, start, end, summary}]}\n * Read; no CAS. Cheap (events.list).\n *\n * book_slot(calendarId, start, end, summary, attendees?)\n * → {eventId, etag}\n * Mutation. CAS by Calendar's own conflict-detection: we re-list\n * events for the requested window inside the same call, and if any\n * OVERLAP exists we return `conflict` with the next-3 free slots\n * mined from the user's freebusy, instead of inserting.\n *\n * Why pre-flight read-then-insert rather than relying on If-Match:\n * `events.insert` doesn't take If-Match (you can't precondition an\n * insert against a non-existent resource). Calendar's own\n * `freebusy.query` is the canonical conflict signal. The whole flow is:\n *\n * 1. freebusy.query for [start, end] on this calendarId\n * 2. if busy → emit ResourceContention with next-3 free slots\n * (computed by walking forward in 30-min steps until 3 free\n * windows of (end-start) duration found)\n * 3. else events.insert with idempotency-key as `requestId` (a Calendar\n * API feature that gives us per-key dedup at upstream)\n *\n * Step 3's `requestId` parameter means a retry of the same idempotency\n * key on the same calendar will return the original event rather than\n * creating a duplicate, which composes correctly with our MutationGuard's\n * idempotency record (which short-circuits before ever hitting upstream\n * on the second call). Defense-in-depth.\n */\n\nimport {\n type ConnectorAdapter,\n type ConnectorInvocation,\n type CapabilityReadResult,\n type CapabilityMutationResult,\n type ConnectorCredentials,\n ResourceContention,\n CredentialsExpired,\n} from '../types.js'\nimport {\n exchangeAuthorizationCode,\n refreshAccessToken,\n} from '../oauth.js'\n\nconst SCOPES = ['https://www.googleapis.com/auth/calendar']\nconst AUTH_URL = 'https://accounts.google.com/o/oauth2/v2/auth'\nconst TOKEN_URL = 'https://oauth2.googleapis.com/token'\n\n/** OAuth client config the factory closes over. Caller resolves these\n * at construction time (env, DB, secret manager — package doesn't care). */\nexport interface GoogleCalendarOptions {\n clientId: string\n clientSecret: string\n}\n\nexport function googleCalendar(opts: GoogleCalendarOptions): ConnectorAdapter {\n const { clientId, clientSecret } = opts\n const adapter: ConnectorAdapter = {\n manifest: {\n kind: 'google-calendar',\n displayName: 'Google Calendar',\n description:\n \"Let your agent check availability and book against a Google Calendar. Conflict-resolved: two callers can't grab the same slot — the second one is offered the next free time.\",\n auth: {\n kind: 'oauth2',\n authorizationUrl: AUTH_URL,\n tokenUrl: TOKEN_URL,\n scopes: SCOPES,\n clientIdEnv: 'GOOGLE_OAUTH_CLIENT_ID',\n clientSecretEnv: 'GOOGLE_OAUTH_CLIENT_SECRET',\n extraAuthParams: { access_type: 'offline', prompt: 'consent', include_granted_scopes: 'true' },\n },\n category: 'calendar',\n defaultConsistencyModel: 'authoritative',\n // Google Calendar's per-project quota is ~600 req/min before\n // throttling kicks in (Calendar API \"Queries per minute per user\",\n // shared per OAuth client). We meter at that rate locally so the\n // FIRST chatty agent doesn't push the shared client into Google's\n // throttle pool and degrade everyone else's quota.\n rateLimit: { requests: 600, windowMs: 60_000, scope: 'oauth-client' },\n capabilities: [\n {\n name: 'list_availability',\n class: 'read',\n description:\n 'Look up busy/free times on the connected calendar between timeMin and timeMax (RFC3339 timestamps).',\n parameters: {\n type: 'object',\n properties: {\n timeMin: { type: 'string', description: 'RFC3339 lower bound (inclusive)' },\n timeMax: { type: 'string', description: 'RFC3339 upper bound (exclusive)' },\n },\n required: ['timeMin', 'timeMax'],\n },\n },\n {\n name: 'book_slot',\n class: 'mutation',\n description:\n 'Reserve a time window on the connected calendar. Returns conflict + alternatives if the slot is no longer free.',\n cas: 'native-idempotency',\n externalEffect: true,\n parameters: {\n type: 'object',\n properties: {\n start: { type: 'string', description: 'RFC3339 start time' },\n end: { type: 'string', description: 'RFC3339 end time' },\n summary: { type: 'string', description: 'Event title shown on the calendar' },\n description: { type: 'string', description: 'Optional event description' },\n attendees: {\n type: 'array',\n items: { type: 'string', description: 'email' },\n },\n },\n required: ['start', 'end', 'summary'],\n },\n },\n ],\n },\n\n async executeRead(inv: ConnectorInvocation): Promise<CapabilityReadResult> {\n if (inv.capabilityName !== 'list_availability') {\n throw new Error(`google-calendar: unknown read capability ${inv.capabilityName}`)\n }\n const calendarId = readMetaString(inv.source.metadata, 'calendarId')\n const { timeMin, timeMax } = inv.args as { timeMin: string; timeMax: string }\n const accessToken = await ensureFreshAccessToken(inv.source.credentials, clientId, clientSecret)\n const fb = await freebusyQuery({ accessToken, calendarId, timeMin, timeMax })\n return {\n data: { busy: fb.busy },\n fetchedAt: Date.now(),\n }\n },\n\n async executeMutation(inv: ConnectorInvocation): Promise<CapabilityMutationResult> {\n if (inv.capabilityName !== 'book_slot') {\n throw new Error(`google-calendar: unknown mutation capability ${inv.capabilityName}`)\n }\n const calendarId = readMetaString(inv.source.metadata, 'calendarId')\n const { start, end, summary, description, attendees } = inv.args as {\n start: string\n end: string\n summary: string\n description?: string\n attendees?: string[]\n }\n const accessToken = await ensureFreshAccessToken(inv.source.credentials, clientId, clientSecret)\n\n // Pre-flight: is the requested window busy?\n const fb = await freebusyQuery({ accessToken, calendarId, timeMin: start, timeMax: end })\n if (fb.busy.length > 0) {\n const startMs = Date.parse(start)\n const endMs = Date.parse(end)\n const durMs = endMs - startMs\n const alternatives = await findNextFreeSlots({\n accessToken,\n calendarId,\n searchFromMs: endMs,\n durationMs: durMs,\n wanted: 3,\n })\n throw new ResourceContention(\n `requested slot ${start}–${end} is no longer free`,\n alternatives,\n { busy: fb.busy },\n )\n }\n\n // Insert. requestId == idempotencyKey gives upstream-side dedup.\n // Calendar requires it to be ≤1024 chars and ASCII.\n const requestId = inv.idempotencyKey.replace(/[^a-zA-Z0-9_:.-]/g, '_').slice(0, 1024)\n const event = {\n summary,\n description,\n start: { dateTime: start },\n end: { dateTime: end },\n attendees: attendees?.map(email => ({ email })),\n }\n const res = await fetch(\n `https://www.googleapis.com/calendar/v3/calendars/${encodeURIComponent(calendarId)}/events?conferenceDataVersion=0&sendUpdates=none&requestId=${encodeURIComponent(requestId)}`,\n {\n method: 'POST',\n headers: {\n authorization: `Bearer ${accessToken}`,\n 'content-type': 'application/json',\n },\n body: JSON.stringify(event),\n signal: AbortSignal.timeout(15_000),\n },\n )\n if (res.status === 409) {\n // Calendar reports duplicate; return as committed by treating the\n // recovered event as the response (idempotent semantics).\n const dup = (await res.json().catch(() => ({}))) as { id?: string; etag?: string }\n return {\n status: 'committed',\n data: dup,\n etagAfter: dup.etag,\n committedAt: Date.now(),\n idempotentReplay: true,\n }\n }\n if (res.status === 401 || res.status === 403) {\n throw new CredentialsExpired(`Google Calendar rejected token (${res.status})`, inv.source.id)\n }\n if (!res.ok) {\n const text = await res.text().catch(() => '')\n throw new Error(`google-calendar book_slot ${res.status}: ${text.slice(0, 200)}`)\n }\n const created = (await res.json()) as { id: string; etag: string; htmlLink?: string }\n return {\n status: 'committed',\n data: { eventId: created.id, htmlLink: created.htmlLink },\n etagAfter: created.etag,\n committedAt: Date.now(),\n idempotentReplay: false,\n }\n },\n\n async exchangeOAuth(input) {\n const tokens = await exchangeAuthorizationCode({\n tokenUrl: TOKEN_URL,\n clientId,\n clientSecret,\n code: input.code,\n codeVerifier: input.codeVerifier,\n redirectUri: input.redirectUri,\n })\n // Pin which calendar this connection points at. Default to the\n // user's primary; the UI lets the user pick a different calendar\n // post-connect by patching DataSource.metadata.calendarId.\n return {\n credentials: {\n kind: 'oauth2',\n accessToken: tokens.accessToken,\n refreshToken: tokens.refreshToken,\n expiresAt: tokens.expiresIn ? Date.now() + tokens.expiresIn * 1000 : undefined,\n },\n scopes: tokens.scope?.split(/\\s+/) ?? SCOPES,\n metadata: { calendarId: 'primary' },\n }\n },\n\n async refreshToken(creds) {\n if (creds.kind !== 'oauth2' || !creds.refreshToken) {\n throw new Error('google-calendar.refreshToken: missing refresh token')\n }\n const refreshed = await refreshAccessToken({\n tokenUrl: TOKEN_URL,\n clientId,\n clientSecret,\n refreshToken: creds.refreshToken,\n })\n return {\n kind: 'oauth2',\n accessToken: refreshed.accessToken,\n refreshToken: refreshed.refreshToken ?? creds.refreshToken,\n expiresAt: refreshed.expiresIn ? Date.now() + refreshed.expiresIn * 1000 : undefined,\n }\n },\n\n async test(source) {\n try {\n const accessToken = await ensureFreshAccessToken(source.credentials, clientId, clientSecret)\n const calendarId = readMetaString(source.metadata, 'calendarId')\n const url = `https://www.googleapis.com/calendar/v3/calendars/${encodeURIComponent(calendarId)}`\n const res = await fetch(url, {\n headers: { authorization: `Bearer ${accessToken}` },\n signal: AbortSignal.timeout(8_000),\n })\n if (res.status === 401 || res.status === 403) {\n return { ok: false, reason: `Google rejected token (${res.status}) — reconnect required` }\n }\n if (!res.ok) return { ok: false, reason: `Google returned ${res.status}` }\n return { ok: true }\n } catch (err) {\n return { ok: false, reason: err instanceof Error ? err.message : String(err) }\n }\n },\n }\n return adapter\n}\n\ninterface FreeBusyResult {\n busy: Array<{ start: string; end: string }>\n}\n\nasync function freebusyQuery(input: {\n accessToken: string\n calendarId: string\n timeMin: string\n timeMax: string\n}): Promise<FreeBusyResult> {\n const res = await fetch('https://www.googleapis.com/calendar/v3/freeBusy', {\n method: 'POST',\n headers: {\n authorization: `Bearer ${input.accessToken}`,\n 'content-type': 'application/json',\n },\n body: JSON.stringify({\n timeMin: input.timeMin,\n timeMax: input.timeMax,\n items: [{ id: input.calendarId }],\n }),\n signal: AbortSignal.timeout(10_000),\n })\n if (!res.ok) {\n const text = await res.text().catch(() => '')\n throw new Error(`freebusy ${res.status}: ${text.slice(0, 200)}`)\n }\n const json = (await res.json()) as {\n calendars?: Record<string, { busy?: Array<{ start: string; end: string }> }>\n }\n return { busy: json.calendars?.[input.calendarId]?.busy ?? [] }\n}\n\n/** Given a starting point and a duration, walk forward looking up\n * freebusy in 24-hour windows, mining (wanted) free slots that are at\n * least durationMs long. Stops at a horizon of 14 days from search\n * start — past that and the agent should propose a different day. */\nasync function findNextFreeSlots(input: {\n accessToken: string\n calendarId: string\n searchFromMs: number\n durationMs: number\n wanted: number\n}): Promise<Array<{ start: string; end: string }>> {\n const horizonMs = input.searchFromMs + 14 * 24 * 60 * 60 * 1000\n const out: Array<{ start: string; end: string }> = []\n let cursor = input.searchFromMs\n // Step the search window 1 day at a time.\n while (cursor < horizonMs && out.length < input.wanted) {\n const windowEnd = Math.min(cursor + 24 * 60 * 60 * 1000, horizonMs)\n const fb = await freebusyQuery({\n accessToken: input.accessToken,\n calendarId: input.calendarId,\n timeMin: new Date(cursor).toISOString(),\n timeMax: new Date(windowEnd).toISOString(),\n })\n // Walk through free intervals between busy spans inside this window.\n const busy = fb.busy\n .map(b => ({ s: Date.parse(b.start), e: Date.parse(b.end) }))\n .filter(b => Number.isFinite(b.s) && Number.isFinite(b.e))\n .sort((a, b) => a.s - b.s)\n let pos = cursor\n for (const b of busy) {\n if (out.length >= input.wanted) break\n if (b.s > pos && b.s - pos >= input.durationMs) {\n out.push({ start: new Date(pos).toISOString(), end: new Date(pos + input.durationMs).toISOString() })\n }\n pos = Math.max(pos, b.e)\n }\n if (out.length < input.wanted && windowEnd - pos >= input.durationMs) {\n out.push({ start: new Date(pos).toISOString(), end: new Date(pos + input.durationMs).toISOString() })\n }\n cursor = windowEnd\n }\n return out.slice(0, input.wanted)\n}\n\n/** If access token is missing or expired, refresh it. Caller is\n * responsible for persisting the rotated envelope back to the row —\n * for now we mutate the in-memory copy so this single call works, and\n * the route layer handles the persistence on call-completion. */\nasync function ensureFreshAccessToken(\n creds: ConnectorCredentials,\n clientId: string,\n clientSecret: string,\n): Promise<string> {\n if (creds.kind !== 'oauth2') {\n throw new Error('google-calendar: expected oauth2 credentials')\n }\n if (creds.accessToken && (!creds.expiresAt || creds.expiresAt > Date.now() + 60_000)) {\n return creds.accessToken\n }\n if (!creds.refreshToken) {\n throw new CredentialsExpired('Google Calendar access token expired and no refresh token', '')\n }\n const refreshed = await refreshAccessToken({\n tokenUrl: TOKEN_URL,\n clientId,\n clientSecret,\n refreshToken: creds.refreshToken,\n })\n // Mutate so the caller within this request sees the fresh token; the\n // persisting write happens at the route layer on completion.\n creds.accessToken = refreshed.accessToken\n creds.expiresAt = refreshed.expiresIn ? Date.now() + refreshed.expiresIn * 1000 : undefined\n if (refreshed.refreshToken) creds.refreshToken = refreshed.refreshToken\n return creds.accessToken\n}\n\nfunction readMetaString(meta: Record<string, unknown>, key: string): string {\n const v = meta[key]\n if (typeof v !== 'string' || v.length === 0) {\n throw new Error(`google-calendar DataSource.metadata.${key} is missing`)\n }\n return v\n}\n","/**\n * @stable Google Drive connector — doc-flow-in for legal/tax/creative agents.\n *\n * Three capabilities, picked to cover \"agent pulls a document the user\n * dropped in a folder\" without trying to expose all of Drive's surface:\n *\n * list_files(folderId?, query?, pageSize?)\n * → {files: [{id, name, mimeType, modifiedTime, size?, md5Checksum?}], nextPageToken?}\n * Read. files.list with a `'<folder>' in parents` clause when folderId\n * is provided, otherwise the user's whole Drive scoped by Drive query.\n *\n * read_file(fileId, format?)\n * → {name, mimeType, content: string | base64, encoding: 'utf-8' | 'base64'}\n * Read. For Google-native types (Docs/Sheets/Slides) we use\n * `files.export` with the requested export mime; for binary types\n * (PDF, images, .docx) we use `files.get?alt=media` and base64 the\n * bytes. Caller decides what to do with each.\n *\n * watch_folder(folderId, channelId, address, ttlMs?)\n * → {channelId, resourceId, expiration}\n * Mutation (creates a push notification channel). CAS: native-idempotency\n * by way of the caller-supplied `channelId` — re-issuing the same\n * channelId returns 409, which we surface as `idempotentReplay: true`\n * after pulling the existing channel's `resourceId` from\n * `DataSource.metadata.watchedChannels[channelId]`.\n *\n * Auth: OAuth2 with `drive.readonly` (list/read) + `drive` (watch). We\n * scope to readonly by default and require the operator to opt into the\n * full-write scope only if they intend to use watch_folder. The\n * `requiredScopes` field on each capability gates this in the agent's\n * tool registry — the agent never sees `watch_folder` unless the grant\n * carries `drive`.\n *\n * Why no upload capability in v1: upload is a multi-part / resumable\n * dance that's properly its own connector pack (write-doc workflows\n * need an authoritative consistency model, a separate review path,\n * etc.). Doc-flow-in is the load-bearing case for the five product\n * agents — doc-flow-out lives in the appropriate kind-specific pack\n * (e.g., docuseal-out, gmail send_reply, sheets update_row).\n */\n\nimport {\n type ConnectorAdapter,\n type ConnectorInvocation,\n type CapabilityReadResult,\n type CapabilityMutationResult,\n type ConnectorCredentials,\n CredentialsExpired,\n} from '../types.js'\nimport {\n exchangeAuthorizationCode,\n refreshAccessToken,\n} from '../oauth.js'\n\nconst SCOPES_READONLY = ['https://www.googleapis.com/auth/drive.readonly']\nconst SCOPE_WATCH = 'https://www.googleapis.com/auth/drive'\nconst AUTH_URL = 'https://accounts.google.com/o/oauth2/v2/auth'\nconst TOKEN_URL = 'https://oauth2.googleapis.com/token'\nconst API = 'https://www.googleapis.com/drive/v3'\n\n/** OAuth client config the factory closes over. */\nexport interface GoogleDriveOptions {\n clientId: string\n clientSecret: string\n /** When true, request the broader `drive` scope at connect-time so\n * the operator can use watch_folder. Default false — request only\n * `drive.readonly` and gate watch_folder via `requiredScopes`. */\n includeWatchScope?: boolean\n /** Default request timeout in ms. Applied per-fetch via AbortSignal. */\n timeoutMs?: number\n}\n\nexport function googleDrive(opts: GoogleDriveOptions): ConnectorAdapter {\n const { clientId, clientSecret } = opts\n const timeoutMs = opts.timeoutMs ?? 30_000\n const scopes = opts.includeWatchScope ? [...SCOPES_READONLY, SCOPE_WATCH] : SCOPES_READONLY\n const adapter: ConnectorAdapter = {\n manifest: {\n kind: 'google-drive',\n displayName: 'Google Drive',\n description:\n \"Read and watch files in the user's Google Drive. List a folder, fetch a document's contents (Docs/Sheets/PDFs/.docx), and subscribe to folder changes via push notifications.\",\n auth: {\n kind: 'oauth2',\n authorizationUrl: AUTH_URL,\n tokenUrl: TOKEN_URL,\n scopes,\n clientIdEnv: 'GOOGLE_OAUTH_CLIENT_ID',\n clientSecretEnv: 'GOOGLE_OAUTH_CLIENT_SECRET',\n extraAuthParams: { access_type: 'offline', prompt: 'consent', include_granted_scopes: 'true' },\n },\n category: 'storage',\n defaultConsistencyModel: 'authoritative',\n rateLimit: { requests: 1000, windowMs: 60_000, scope: 'oauth-client' },\n capabilities: [\n {\n name: 'list_files',\n class: 'read',\n description:\n \"List files visible to the connected Drive account. Optionally scope to a folder by id and/or pass a Drive query string (e.g., \\\"mimeType='application/pdf' and modifiedTime > '2025-01-01T00:00:00Z'\\\").\",\n parameters: {\n type: 'object',\n properties: {\n folderId: { type: 'string', description: 'Drive folder id; when present, restricts to direct children.' },\n query: { type: 'string', description: \"Optional Drive query expression; appended with AND if folderId is set.\" },\n pageSize: { type: 'integer', minimum: 1, maximum: 1000, default: 100 },\n pageToken: { type: 'string', description: 'Continuation token returned by a previous call.' },\n },\n },\n },\n {\n name: 'read_file',\n class: 'read',\n description:\n \"Read a file's contents. Google-native types are exported (Docs → text/plain by default, Sheets → text/csv, Slides → application/pdf); binary types are returned as base64.\",\n parameters: {\n type: 'object',\n properties: {\n fileId: { type: 'string' },\n exportMime: {\n type: 'string',\n description:\n \"Export mime override for Google-native types. Defaults: Docs=text/plain, Sheets=text/csv, Slides=application/pdf.\",\n },\n },\n required: ['fileId'],\n },\n },\n {\n name: 'watch_folder',\n class: 'mutation',\n description:\n \"Create a push-notification channel for a folder. Drive POSTs change notifications to `address`; the channel expires at `expiration` (max 7 days). Pass the same channelId on retry to replay the existing channel.\",\n cas: 'native-idempotency',\n externalEffect: true,\n requiredScopes: [SCOPE_WATCH],\n parameters: {\n type: 'object',\n properties: {\n folderId: { type: 'string' },\n channelId: { type: 'string', description: 'Caller-controlled UUID; also used as idempotency key.' },\n address: { type: 'string', description: 'HTTPS URL Drive will POST change notifications to.' },\n ttlMs: { type: 'integer', minimum: 60_000, description: 'Channel lifetime in ms. Drive caps at 7 days.' },\n },\n required: ['folderId', 'channelId', 'address'],\n },\n },\n ],\n },\n\n async executeRead(inv: ConnectorInvocation): Promise<CapabilityReadResult> {\n const accessToken = await ensureFreshAccessToken(inv.source.credentials, clientId, clientSecret)\n if (inv.capabilityName === 'list_files') return listFiles(inv, accessToken, timeoutMs)\n if (inv.capabilityName === 'read_file') return readFile(inv, accessToken, timeoutMs)\n throw new Error(`google-drive: unknown read capability ${inv.capabilityName}`)\n },\n\n async executeMutation(inv: ConnectorInvocation): Promise<CapabilityMutationResult> {\n if (inv.capabilityName !== 'watch_folder') {\n throw new Error(`google-drive: unknown mutation capability ${inv.capabilityName}`)\n }\n const accessToken = await ensureFreshAccessToken(inv.source.credentials, clientId, clientSecret)\n return watchFolder(inv, accessToken, timeoutMs)\n },\n\n async exchangeOAuth(input) {\n const tokens = await exchangeAuthorizationCode({\n tokenUrl: TOKEN_URL,\n clientId,\n clientSecret,\n code: input.code,\n codeVerifier: input.codeVerifier,\n redirectUri: input.redirectUri,\n })\n return {\n credentials: {\n kind: 'oauth2',\n accessToken: tokens.accessToken,\n refreshToken: tokens.refreshToken,\n expiresAt: tokens.expiresIn ? Date.now() + tokens.expiresIn * 1000 : undefined,\n },\n scopes: tokens.scope?.split(/\\s+/) ?? scopes,\n metadata: {},\n }\n },\n\n async refreshToken(creds) {\n if (creds.kind !== 'oauth2' || !creds.refreshToken) {\n throw new Error('google-drive.refreshToken: missing refresh token')\n }\n const refreshed = await refreshAccessToken({\n tokenUrl: TOKEN_URL,\n clientId,\n clientSecret,\n refreshToken: creds.refreshToken,\n })\n return {\n kind: 'oauth2',\n accessToken: refreshed.accessToken,\n refreshToken: refreshed.refreshToken ?? creds.refreshToken,\n expiresAt: refreshed.expiresIn ? Date.now() + refreshed.expiresIn * 1000 : undefined,\n }\n },\n\n async test(source) {\n try {\n const accessToken = await ensureFreshAccessToken(source.credentials, clientId, clientSecret)\n const res = await fetch(`${API}/about?fields=user`, {\n headers: { authorization: `Bearer ${accessToken}` },\n signal: AbortSignal.timeout(8_000),\n })\n if (res.status === 401 || res.status === 403) {\n return { ok: false, reason: `Google rejected Drive token (${res.status}) — reconnect required` }\n }\n if (!res.ok) return { ok: false, reason: `Google Drive returned ${res.status}` }\n return { ok: true }\n } catch (err) {\n return { ok: false, reason: err instanceof Error ? err.message : String(err) }\n }\n },\n }\n return adapter\n}\n\nasync function listFiles(\n inv: ConnectorInvocation,\n accessToken: string,\n timeoutMs: number,\n): Promise<CapabilityReadResult> {\n const args = (inv.args ?? {}) as {\n folderId?: string\n query?: string\n pageSize?: number\n pageToken?: string\n }\n const q: string[] = []\n if (args.folderId) q.push(`'${args.folderId.replace(/'/g, \"\\\\'\")}' in parents`)\n if (args.query) q.push(`(${args.query})`)\n q.push('trashed = false')\n const params = new URLSearchParams({\n q: q.join(' and '),\n pageSize: String(args.pageSize ?? 100),\n fields: 'nextPageToken, files(id,name,mimeType,modifiedTime,size,md5Checksum,parents)',\n })\n if (args.pageToken) params.set('pageToken', args.pageToken)\n const res = await fetch(`${API}/files?${params.toString()}`, {\n headers: { authorization: `Bearer ${accessToken}` },\n signal: AbortSignal.timeout(timeoutMs),\n })\n if (res.status === 401 || res.status === 403) {\n throw new CredentialsExpired(`Google Drive rejected token (${res.status})`, inv.source.id)\n }\n if (!res.ok) {\n const text = await res.text().catch(() => '')\n throw new Error(`google-drive list_files ${res.status}: ${text.slice(0, 200)}`)\n }\n const json = (await res.json()) as {\n nextPageToken?: string\n files?: Array<Record<string, unknown>>\n }\n return {\n data: { files: json.files ?? [], nextPageToken: json.nextPageToken },\n fetchedAt: Date.now(),\n }\n}\n\nconst GOOGLE_NATIVE_DEFAULTS: Record<string, string> = {\n 'application/vnd.google-apps.document': 'text/plain',\n 'application/vnd.google-apps.spreadsheet': 'text/csv',\n 'application/vnd.google-apps.presentation': 'application/pdf',\n}\n\nasync function readFile(\n inv: ConnectorInvocation,\n accessToken: string,\n timeoutMs: number,\n): Promise<CapabilityReadResult> {\n const { fileId, exportMime } = (inv.args ?? {}) as { fileId: string; exportMime?: string }\n const metaRes = await fetch(`${API}/files/${encodeURIComponent(fileId)}?fields=id,name,mimeType,modifiedTime`, {\n headers: { authorization: `Bearer ${accessToken}` },\n signal: AbortSignal.timeout(timeoutMs),\n })\n if (metaRes.status === 401 || metaRes.status === 403) {\n throw new CredentialsExpired(`Google Drive rejected token (${metaRes.status})`, inv.source.id)\n }\n if (metaRes.status === 404) {\n throw new Error(`google-drive read_file: file ${fileId} not found`)\n }\n if (!metaRes.ok) {\n const text = await metaRes.text().catch(() => '')\n throw new Error(`google-drive read_file meta ${metaRes.status}: ${text.slice(0, 200)}`)\n }\n const meta = (await metaRes.json()) as { id: string; name: string; mimeType: string; modifiedTime?: string }\n\n const isNative = meta.mimeType.startsWith('application/vnd.google-apps.')\n const fetchedAt = Date.now()\n if (isNative) {\n const targetMime = exportMime ?? GOOGLE_NATIVE_DEFAULTS[meta.mimeType] ?? 'text/plain'\n const res = await fetch(`${API}/files/${encodeURIComponent(fileId)}/export?mimeType=${encodeURIComponent(targetMime)}`, {\n headers: { authorization: `Bearer ${accessToken}` },\n signal: AbortSignal.timeout(timeoutMs),\n })\n if (!res.ok) {\n const text = await res.text().catch(() => '')\n throw new Error(`google-drive read_file export ${res.status}: ${text.slice(0, 200)}`)\n }\n const isTextLike = /^text\\/|application\\/(json|xml|csv|javascript)/.test(targetMime)\n if (isTextLike) {\n const content = await res.text()\n return {\n data: { name: meta.name, mimeType: targetMime, content, encoding: 'utf-8', modifiedTime: meta.modifiedTime },\n fetchedAt,\n }\n }\n const buf = Buffer.from(await res.arrayBuffer())\n return {\n data: { name: meta.name, mimeType: targetMime, content: buf.toString('base64'), encoding: 'base64', modifiedTime: meta.modifiedTime },\n fetchedAt,\n }\n }\n\n const res = await fetch(`${API}/files/${encodeURIComponent(fileId)}?alt=media`, {\n headers: { authorization: `Bearer ${accessToken}` },\n signal: AbortSignal.timeout(timeoutMs),\n })\n if (!res.ok) {\n const text = await res.text().catch(() => '')\n throw new Error(`google-drive read_file media ${res.status}: ${text.slice(0, 200)}`)\n }\n const isTextLike = /^text\\/|application\\/(json|xml|csv|javascript)/.test(meta.mimeType)\n if (isTextLike) {\n const content = await res.text()\n return {\n data: { name: meta.name, mimeType: meta.mimeType, content, encoding: 'utf-8', modifiedTime: meta.modifiedTime },\n fetchedAt,\n }\n }\n const buf = Buffer.from(await res.arrayBuffer())\n return {\n data: { name: meta.name, mimeType: meta.mimeType, content: buf.toString('base64'), encoding: 'base64', modifiedTime: meta.modifiedTime },\n fetchedAt,\n }\n}\n\nasync function watchFolder(\n inv: ConnectorInvocation,\n accessToken: string,\n timeoutMs: number,\n): Promise<CapabilityMutationResult> {\n const { folderId, channelId, address, ttlMs } = inv.args as {\n folderId: string\n channelId: string\n address: string\n ttlMs?: number\n }\n const body: Record<string, unknown> = {\n id: channelId,\n type: 'web_hook',\n address,\n }\n if (ttlMs && ttlMs > 0) body.expiration = String(Date.now() + ttlMs)\n const res = await fetch(`${API}/files/${encodeURIComponent(folderId)}/watch`, {\n method: 'POST',\n headers: {\n authorization: `Bearer ${accessToken}`,\n 'content-type': 'application/json',\n },\n body: JSON.stringify(body),\n signal: AbortSignal.timeout(timeoutMs),\n })\n if (res.status === 401 || res.status === 403) {\n throw new CredentialsExpired(`Google Drive rejected token (${res.status})`, inv.source.id)\n }\n if (res.status === 409) {\n // Channel id collision — Drive returns the existing record info via\n // the metadata bag on our side. We surface it as an idempotent replay\n // so callers can keep using the same channelId across retries.\n const cached = (inv.source.metadata.watchedChannels as Record<string, { resourceId: string; expiration?: string }> | undefined)?.[channelId]\n return {\n status: 'committed',\n data: { channelId, resourceId: cached?.resourceId, expiration: cached?.expiration },\n committedAt: Date.now(),\n idempotentReplay: true,\n }\n }\n if (!res.ok) {\n const text = await res.text().catch(() => '')\n throw new Error(`google-drive watch_folder ${res.status}: ${text.slice(0, 200)}`)\n }\n const json = (await res.json()) as { id: string; resourceId: string; expiration?: string }\n return {\n status: 'committed',\n data: { channelId: json.id, resourceId: json.resourceId, expiration: json.expiration },\n committedAt: Date.now(),\n idempotentReplay: false,\n }\n}\n\nasync function ensureFreshAccessToken(\n creds: ConnectorCredentials,\n clientId: string,\n clientSecret: string,\n): Promise<string> {\n if (creds.kind !== 'oauth2') {\n throw new Error('google-drive: expected oauth2 credentials')\n }\n if (creds.accessToken && (!creds.expiresAt || creds.expiresAt > Date.now() + 60_000)) {\n return creds.accessToken\n }\n if (!creds.refreshToken) {\n throw new CredentialsExpired('Google Drive access token expired and no refresh token', '')\n }\n const refreshed = await refreshAccessToken({\n tokenUrl: TOKEN_URL,\n clientId,\n clientSecret,\n refreshToken: creds.refreshToken,\n })\n creds.accessToken = refreshed.accessToken\n creds.expiresAt = refreshed.expiresIn ? Date.now() + refreshed.expiresIn * 1000 : undefined\n if (refreshed.refreshToken) creds.refreshToken = refreshed.refreshToken\n return creds.accessToken\n}\n","/**\n * Google Sheets connector — live KB source + writable rows.\n *\n * The flagship for the \"agent reads from a live spreadsheet\" UX. The\n * customer points the connection at a Sheet (spreadsheetId + sheetName +\n * headerRow). We expose:\n *\n * list_rows(filter?, limit?)\n * → {rows: [{...header→cell}], nextCursor?}\n * Cheap; just spreadsheets.values.get with the configured range.\n *\n * query_rows(predicate)\n * → same shape as list_rows but with a structured filter (k=v pairs\n * ANDed together). Simple and explainable; no SQL.\n *\n * update_row(rowKey, patch)\n * → {row: {...header→cell}, updatedRange}\n * Mutation. CAS via Sheets' spreadsheets.values.update + a\n * pre-flight read of the row's revisionId-equivalent hash. Sheets\n * doesn't expose a per-row etag, so we synthesize one — see\n * `rowFingerprint`. If the fingerprint doesn't match what the agent\n * last read, we surface ResourceContention with the current row in\n * `currentState`.\n *\n * KB binding: when a Sheet is `consistencyModel: 'cache'` (the default\n * for spreadsheets — they're slow-moving), the system also indexes the\n * rows as KB chunks. The KB build pipeline calls `list_rows` and emits\n * one markdown page per row; on a connector-level \"refresh\" event the\n * agent's KB rebuilds.\n */\n\nimport { createHash } from 'crypto'\nimport {\n type ConnectorAdapter,\n type ConnectorInvocation,\n type CapabilityReadResult,\n type CapabilityMutationResult,\n type ConnectorCredentials,\n ResourceContention,\n CredentialsExpired,\n} from '../types.js'\nimport { exchangeAuthorizationCode, refreshAccessToken } from '../oauth.js'\n\nconst SCOPES = ['https://www.googleapis.com/auth/spreadsheets']\nconst AUTH_URL = 'https://accounts.google.com/o/oauth2/v2/auth'\nconst TOKEN_URL = 'https://oauth2.googleapis.com/token'\n\n/** OAuth client config the factory closes over. Caller resolves these\n * at construction time (env, DB, secret manager — package doesn't care). */\nexport interface GoogleSheetsOptions {\n clientId: string\n clientSecret: string\n}\n\nexport function googleSheets(opts: GoogleSheetsOptions): ConnectorAdapter {\n const { clientId, clientSecret } = opts\n const adapter: ConnectorAdapter = {\n manifest: {\n kind: 'google-sheets',\n displayName: 'Google Sheets',\n description:\n \"Bind your agent's knowledge base or pricing/availability lookup to a live Google Sheet. Edit the sheet, and the agent picks up changes — no redeploys.\",\n auth: {\n kind: 'oauth2',\n authorizationUrl: AUTH_URL,\n tokenUrl: TOKEN_URL,\n scopes: SCOPES,\n clientIdEnv: 'GOOGLE_OAUTH_CLIENT_ID',\n clientSecretEnv: 'GOOGLE_OAUTH_CLIENT_SECRET',\n extraAuthParams: { access_type: 'offline', prompt: 'consent', include_granted_scopes: 'true' },\n },\n category: 'spreadsheet',\n defaultConsistencyModel: 'cache',\n // Sheets API caps OAuth-client-wide reads + writes at 300 req/min\n // each (Google's published quotas: \"Read requests per minute per\n // project\" and the matching write bucket). We meter the tighter of\n // the two so neither side exhausts before us.\n rateLimit: { requests: 300, windowMs: 60_000, scope: 'oauth-client' },\n capabilities: [\n {\n name: 'list_rows',\n class: 'read',\n description: 'Return rows from the connected sheet. Each row is keyed by the header cells declared at connect time.',\n parameters: {\n type: 'object',\n properties: {\n limit: { type: 'integer', minimum: 1, maximum: 500, default: 100 },\n },\n },\n },\n {\n name: 'query_rows',\n class: 'read',\n description: 'Return rows matching every key=value pair in `predicate` (string equality, case-insensitive).',\n parameters: {\n type: 'object',\n properties: {\n predicate: {\n type: 'object',\n additionalProperties: { type: 'string' },\n },\n limit: { type: 'integer', minimum: 1, maximum: 500, default: 100 },\n },\n required: ['predicate'],\n },\n },\n {\n name: 'update_row',\n class: 'mutation',\n description: 'Update a row identified by `rowKey` (the value in the configured key column). Patch is a {column: newValue} map. Returns conflict if the row changed since the agent last read it.',\n cas: 'optimistic-read-verify',\n externalEffect: true,\n parameters: {\n type: 'object',\n properties: {\n rowKey: { type: 'string', description: 'Value in the key column identifying the row to update.' },\n patch: {\n type: 'object',\n additionalProperties: { type: 'string' },\n },\n expectedFingerprint: {\n type: 'string',\n description: 'Optional. The fingerprint the agent read on its last list_rows/query_rows call. If supplied and stale, the update is rejected with conflict.',\n },\n },\n required: ['rowKey', 'patch'],\n },\n },\n ],\n },\n\n async executeRead(inv: ConnectorInvocation): Promise<CapabilityReadResult> {\n const meta = readSheetMeta(inv.source.metadata)\n const accessToken = await ensureFreshAccessToken(inv.source.credentials, clientId, clientSecret)\n const rows = await fetchAllRows(accessToken, meta)\n const limit = clampLimit(inv.args.limit, 100)\n let filtered = rows\n if (inv.capabilityName === 'query_rows') {\n const predicate = (inv.args.predicate ?? {}) as Record<string, string>\n filtered = rows.filter(row => matchesPredicate(row, predicate))\n } else if (inv.capabilityName !== 'list_rows') {\n throw new Error(`google-sheets: unknown read ${inv.capabilityName}`)\n }\n const sliced = filtered.slice(0, limit)\n return {\n data: {\n rows: sliced.map(r => ({ ...r.values, _fingerprint: r.fingerprint, _rowIndex: r.rowIndex })),\n total: filtered.length,\n truncated: filtered.length > sliced.length,\n },\n etag: meta.etag, // currently undefined — Sheets values.get doesn't surface etag; row-level fingerprints are the conflict signal\n fetchedAt: Date.now(),\n }\n },\n\n async executeMutation(inv: ConnectorInvocation): Promise<CapabilityMutationResult> {\n if (inv.capabilityName !== 'update_row') {\n throw new Error(`google-sheets: unknown mutation ${inv.capabilityName}`)\n }\n const meta = readSheetMeta(inv.source.metadata)\n const accessToken = await ensureFreshAccessToken(inv.source.credentials, clientId, clientSecret)\n const { rowKey, patch, expectedFingerprint } = inv.args as {\n rowKey: string\n patch: Record<string, string>\n expectedFingerprint?: string\n }\n\n // Pre-flight: read the row, compute fingerprint, compare.\n const rows = await fetchAllRows(accessToken, meta)\n const target = rows.find(r => normalizeKey(r.values[meta.keyColumn]) === normalizeKey(rowKey))\n if (!target) {\n throw new ResourceContention(\n `row with key \"${rowKey}\" not found`,\n [],\n { availableRows: rows.length },\n )\n }\n if (expectedFingerprint && expectedFingerprint !== target.fingerprint) {\n throw new ResourceContention(\n `row \"${rowKey}\" was modified since the agent last read it; re-read and try again`,\n [],\n { current: target.values, currentFingerprint: target.fingerprint },\n )\n }\n\n // Build the new row preserving column order.\n const updatedValues: string[] = meta.headers.map(h =>\n h in patch ? String(patch[h]) : (target.values[h] ?? ''),\n )\n const range = `${meta.sheetName}!A${target.rowIndex + 1}:${columnIndexToLetter(meta.headers.length - 1)}${target.rowIndex + 1}`\n const url = `https://sheets.googleapis.com/v4/spreadsheets/${encodeURIComponent(meta.spreadsheetId)}/values/${encodeURIComponent(range)}?valueInputOption=USER_ENTERED`\n const res = await fetch(url, {\n method: 'PUT',\n headers: {\n authorization: `Bearer ${accessToken}`,\n 'content-type': 'application/json',\n },\n body: JSON.stringify({ values: [updatedValues] }),\n signal: AbortSignal.timeout(15_000),\n })\n if (res.status === 401 || res.status === 403) {\n throw new CredentialsExpired(`Google Sheets rejected token (${res.status})`, inv.source.id)\n }\n if (!res.ok) {\n const text = await res.text().catch(() => '')\n throw new Error(`google-sheets update_row ${res.status}: ${text.slice(0, 200)}`)\n }\n const updatedValuesByHeader = Object.fromEntries(\n meta.headers.map((h, i) => [h, updatedValues[i] ?? '']),\n )\n return {\n status: 'committed',\n data: {\n row: updatedValuesByHeader,\n fingerprint: rowFingerprint(updatedValuesByHeader),\n updatedRange: range,\n },\n etagAfter: rowFingerprint(updatedValuesByHeader),\n committedAt: Date.now(),\n idempotentReplay: false,\n }\n },\n\n async exchangeOAuth(input) {\n const tokens = await exchangeAuthorizationCode({\n tokenUrl: TOKEN_URL,\n clientId,\n clientSecret,\n code: input.code,\n codeVerifier: input.codeVerifier,\n redirectUri: input.redirectUri,\n })\n return {\n credentials: {\n kind: 'oauth2',\n accessToken: tokens.accessToken,\n refreshToken: tokens.refreshToken,\n expiresAt: tokens.expiresIn ? Date.now() + tokens.expiresIn * 1000 : undefined,\n },\n scopes: tokens.scope?.split(/\\s+/) ?? SCOPES,\n // Operator must select the spreadsheet + range post-connect; we\n // can't infer it during the OAuth handshake.\n metadata: { spreadsheetId: '', sheetName: 'Sheet1', headerRow: 1, keyColumn: '' },\n }\n },\n\n async refreshToken(creds) {\n if (creds.kind !== 'oauth2' || !creds.refreshToken) {\n throw new Error('google-sheets.refreshToken: missing refresh token')\n }\n const refreshed = await refreshAccessToken({\n tokenUrl: TOKEN_URL,\n clientId,\n clientSecret,\n refreshToken: creds.refreshToken,\n })\n return {\n kind: 'oauth2',\n accessToken: refreshed.accessToken,\n refreshToken: refreshed.refreshToken ?? creds.refreshToken,\n expiresAt: refreshed.expiresIn ? Date.now() + refreshed.expiresIn * 1000 : undefined,\n }\n },\n\n async test(source) {\n try {\n const accessToken = await ensureFreshAccessToken(source.credentials, clientId, clientSecret)\n const meta = readSheetMeta(source.metadata)\n if (!meta.spreadsheetId) {\n return { ok: false, reason: 'spreadsheetId not configured — pick a sheet in the connection settings' }\n }\n const url = `https://sheets.googleapis.com/v4/spreadsheets/${encodeURIComponent(meta.spreadsheetId)}?fields=spreadsheetId,properties.title`\n const res = await fetch(url, {\n headers: { authorization: `Bearer ${accessToken}` },\n signal: AbortSignal.timeout(8_000),\n })\n if (res.status === 401 || res.status === 403) {\n return { ok: false, reason: `Google rejected token (${res.status}) — reconnect required` }\n }\n if (!res.ok) return { ok: false, reason: `Google returned ${res.status}` }\n return { ok: true }\n } catch (err) {\n return { ok: false, reason: err instanceof Error ? err.message : String(err) }\n }\n },\n }\n return adapter\n}\n\ninterface SheetMeta {\n spreadsheetId: string\n sheetName: string\n /** 1-indexed header row in the sheet. */\n headerRow: number\n /** Header name that uniquely identifies a row (used by update_row). */\n keyColumn: string\n /** Cached column headers — populated on first fetch. Optional in metadata\n * because we resolve them at fetch time and write back via the route\n * layer when the user pins the connection. */\n headers: string[]\n /** Whatever the upstream surfaces as a top-level revision identifier;\n * if absent we synthesize per-row fingerprints instead. */\n etag?: string\n}\n\nfunction readSheetMeta(meta: Record<string, unknown>): SheetMeta {\n const spreadsheetId = String(meta.spreadsheetId ?? '')\n const sheetName = String(meta.sheetName ?? 'Sheet1')\n const headerRow = Number(meta.headerRow ?? 1)\n const keyColumn = String(meta.keyColumn ?? '')\n const headers = Array.isArray(meta.headers) ? (meta.headers as string[]).map(String) : []\n if (!spreadsheetId || !keyColumn) {\n throw new Error('google-sheets metadata missing spreadsheetId or keyColumn')\n }\n return { spreadsheetId, sheetName, headerRow, keyColumn, headers }\n}\n\ninterface ResolvedRow {\n rowIndex: number // 0-indexed offset from the data start (NOT including header)\n values: Record<string, string>\n fingerprint: string\n}\n\n/** Fetch every row in the configured sheet/range and project to keyed\n * records. We don't paginate — Sheets values.get returns the whole range\n * in one call. For very wide sheets the operator can split the\n * connection into multiple DataSources, each with a narrower range. */\nasync function fetchAllRows(accessToken: string, meta: SheetMeta): Promise<ResolvedRow[]> {\n const range = `${meta.sheetName}`\n const url = `https://sheets.googleapis.com/v4/spreadsheets/${encodeURIComponent(meta.spreadsheetId)}/values/${encodeURIComponent(range)}`\n const res = await fetch(url, {\n headers: { authorization: `Bearer ${accessToken}` },\n signal: AbortSignal.timeout(15_000),\n })\n if (res.status === 401 || res.status === 403) {\n throw new CredentialsExpired(`Google Sheets rejected token (${res.status})`, '')\n }\n if (!res.ok) {\n const text = await res.text().catch(() => '')\n throw new Error(`google-sheets values.get ${res.status}: ${text.slice(0, 200)}`)\n }\n const json = (await res.json()) as { values?: string[][] }\n const grid = json.values ?? []\n if (grid.length === 0) return []\n const headers = meta.headers.length > 0 ? meta.headers : grid[meta.headerRow - 1] ?? []\n if (headers.length === 0) return []\n const dataRows = grid.slice(meta.headerRow)\n return dataRows.map((rowCells, i) => {\n const values: Record<string, string> = {}\n for (let c = 0; c < headers.length; c++) {\n values[headers[c]] = (rowCells[c] ?? '').toString()\n }\n return {\n // rowIndex is the absolute row in the sheet (1-indexed) where this\n // row's data lives. Header is at meta.headerRow. So this row is at\n // headerRow + i + 1 (1-indexed).\n rowIndex: meta.headerRow + i,\n values,\n fingerprint: rowFingerprint(values),\n }\n })\n}\n\n/** Stable fingerprint of a row's cells. Used as a synthetic etag for\n * optimistic-read-verify CAS. */\nfunction rowFingerprint(values: Record<string, string>): string {\n const keys = Object.keys(values).sort()\n const blob = keys.map(k => `${k}=${values[k]}`).join('\u0001')\n return createHash('sha256').update(blob).digest('hex').slice(0, 16)\n}\n\nfunction matchesPredicate(row: ResolvedRow, predicate: Record<string, string>): boolean {\n for (const [k, v] of Object.entries(predicate)) {\n const cell = row.values[k]\n if (cell === undefined) return false\n if (cell.toLowerCase().trim() !== String(v).toLowerCase().trim()) return false\n }\n return true\n}\n\nfunction normalizeKey(s: string | undefined): string {\n return (s ?? '').trim().toLowerCase()\n}\n\nfunction clampLimit(v: unknown, dflt: number): number {\n const n = typeof v === 'number' ? v : Number(v)\n if (!Number.isFinite(n) || n <= 0) return dflt\n return Math.min(Math.max(1, Math.floor(n)), 500)\n}\n\nfunction columnIndexToLetter(idx: number): string {\n // 0 → A, 25 → Z, 26 → AA, 27 → AB ...\n let n = idx\n let s = ''\n while (n >= 0) {\n s = String.fromCharCode((n % 26) + 65) + s\n n = Math.floor(n / 26) - 1\n }\n return s\n}\n\nasync function ensureFreshAccessToken(creds: ConnectorCredentials, clientId: string, clientSecret: string): Promise<string> {\n if (creds.kind !== 'oauth2') {\n throw new Error('google-sheets: expected oauth2 credentials')\n }\n if (creds.accessToken && (!creds.expiresAt || creds.expiresAt > Date.now() + 60_000)) {\n return creds.accessToken\n }\n if (!creds.refreshToken) {\n throw new CredentialsExpired('Google Sheets access token expired and no refresh token', '')\n }\n const refreshed = await refreshAccessToken({\n tokenUrl: TOKEN_URL,\n clientId,\n clientSecret,\n refreshToken: creds.refreshToken,\n })\n creds.accessToken = refreshed.accessToken\n creds.expiresAt = refreshed.expiresIn ? Date.now() + refreshed.expiresIn * 1000 : undefined\n if (refreshed.refreshToken) creds.refreshToken = refreshed.refreshToken\n return creds.accessToken\n}\n","/**\n * @stable Gmail connector — email-triggered agent workflows.\n *\n * Four capabilities, picked to cover \"agent reads inbox, replies, and\n * watches a label\" without exposing all of Gmail's surface:\n *\n * list_messages(labelIds?, query?, maxResults?)\n * → {messages: [{id, threadId, snippet, internalDate, from, to, subject, labelIds}], nextPageToken?}\n * Read. `users.messages.list` + a parallel `users.messages.get` for\n * each id with `format=metadata` so the agent gets actionable header\n * fields, not just ids.\n *\n * read_message(id, format?)\n * → {id, threadId, from, to, subject, internalDate, body: {text?, html?}, attachments: [{filename, mimeType, attachmentId}]}\n * Read. `users.messages.get?format=full` then a small MIME walker that\n * extracts `text/plain` + `text/html` + a flat attachment manifest.\n * Attachment bodies are NOT inlined (could be huge) — the caller can\n * follow up with `get_attachment` if needed.\n *\n * send_reply(threadId, body, replyAll?, cc?)\n * → {id, threadId, labelIds}\n * Mutation. `users.messages.send` with In-Reply-To/References headers\n * pulled from the most recent message in the thread. CAS: native-\n * idempotency. Gmail does not honor an explicit idempotency-key\n * header, so we encode the agent's idempotency key into a\n * `X-Tangle-Idempotency-Key` header AND we annotate the thread with\n * a custom label `tangle-sent-<key>` on success — a retry can list\n * the label and short-circuit without re-sending. The MutationGuard\n * above the connector still short-circuits the common retry case\n * before any upstream call.\n *\n * watch_label(labelIds, topicName, ttlMs?)\n * → {historyId, expiration}\n * Mutation. `users.watch` registers a Cloud Pub/Sub topic that\n * receives a notification on label changes. Caller owns the Pub/Sub\n * topic and routes pushes into the webhook router. Note: Gmail\n * forces re-registration every 7 days; we surface the upstream\n * `expiration` so the caller can schedule a refresh.\n *\n * Auth: OAuth2 with `gmail.readonly` (list/read), `gmail.send` (send),\n * `gmail.modify` (watch). Caller toggles which to include via the\n * `scopes` option.\n */\n\nimport {\n type ConnectorAdapter,\n type ConnectorInvocation,\n type CapabilityReadResult,\n type CapabilityMutationResult,\n type ConnectorCredentials,\n CredentialsExpired,\n} from '../types.js'\nimport {\n exchangeAuthorizationCode,\n refreshAccessToken,\n} from '../oauth.js'\n\nconst SCOPE_READ = 'https://www.googleapis.com/auth/gmail.readonly'\nconst SCOPE_SEND = 'https://www.googleapis.com/auth/gmail.send'\nconst SCOPE_MODIFY = 'https://www.googleapis.com/auth/gmail.modify'\nconst AUTH_URL = 'https://accounts.google.com/o/oauth2/v2/auth'\nconst TOKEN_URL = 'https://oauth2.googleapis.com/token'\nconst API = 'https://gmail.googleapis.com/gmail/v1/users/me'\n\nexport interface GmailOptions {\n clientId: string\n clientSecret: string\n /** Scopes requested at connect-time. Default: read + send + modify. */\n scopes?: string[]\n /** Default request timeout in ms. */\n timeoutMs?: number\n}\n\nexport function gmail(opts: GmailOptions): ConnectorAdapter {\n const { clientId, clientSecret } = opts\n const timeoutMs = opts.timeoutMs ?? 30_000\n const scopes = opts.scopes ?? [SCOPE_READ, SCOPE_SEND, SCOPE_MODIFY]\n const adapter: ConnectorAdapter = {\n manifest: {\n kind: 'gmail',\n displayName: 'Gmail',\n description:\n \"Read inbox messages by label or query, fetch a single message including MIME bodies and attachment manifests, reply on a thread, and watch a label for new mail (Cloud Pub/Sub push).\",\n auth: {\n kind: 'oauth2',\n authorizationUrl: AUTH_URL,\n tokenUrl: TOKEN_URL,\n scopes,\n clientIdEnv: 'GOOGLE_OAUTH_CLIENT_ID',\n clientSecretEnv: 'GOOGLE_OAUTH_CLIENT_SECRET',\n extraAuthParams: { access_type: 'offline', prompt: 'consent', include_granted_scopes: 'true' },\n },\n category: 'comms',\n defaultConsistencyModel: 'authoritative',\n rateLimit: { requests: 250, windowMs: 1_000, scope: 'oauth-client' },\n capabilities: [\n {\n name: 'list_messages',\n class: 'read',\n description:\n \"List inbox messages. Filter by labelIds (default INBOX) and/or a Gmail query (e.g., 'from:billing@stripe.com newer_than:7d'). Returns headers (from/to/subject/date) not bodies.\",\n requiredScopes: [SCOPE_READ],\n parameters: {\n type: 'object',\n properties: {\n labelIds: { type: 'array', items: { type: 'string' }, description: 'Default: [\"INBOX\"]' },\n query: { type: 'string', description: \"Gmail query syntax.\" },\n maxResults: { type: 'integer', minimum: 1, maximum: 500, default: 25 },\n pageToken: { type: 'string' },\n },\n },\n },\n {\n name: 'read_message',\n class: 'read',\n description:\n \"Read a single Gmail message including parsed text and html bodies and a flat manifest of attachments. Bodies are inlined; attachment bytes are not.\",\n requiredScopes: [SCOPE_READ],\n parameters: {\n type: 'object',\n properties: {\n id: { type: 'string' },\n },\n required: ['id'],\n },\n },\n {\n name: 'send_reply',\n class: 'mutation',\n description:\n \"Send a reply on a thread. Pulls In-Reply-To/References from the latest message in the thread. Body is text/plain.\",\n cas: 'native-idempotency',\n externalEffect: true,\n requiredScopes: [SCOPE_SEND, SCOPE_READ],\n parameters: {\n type: 'object',\n properties: {\n threadId: { type: 'string' },\n body: { type: 'string', description: 'text/plain body' },\n replyAll: { type: 'boolean', default: false },\n cc: { type: 'array', items: { type: 'string' } },\n },\n required: ['threadId', 'body'],\n },\n },\n {\n name: 'watch_label',\n class: 'mutation',\n description:\n \"Register a Cloud Pub/Sub topic to receive push notifications when a label changes. Returns the upstream historyId + expiration. Re-issue every 7 days.\",\n cas: 'native-idempotency',\n externalEffect: true,\n requiredScopes: [SCOPE_MODIFY],\n parameters: {\n type: 'object',\n properties: {\n labelIds: { type: 'array', items: { type: 'string' }, description: 'Default: [\"INBOX\"]' },\n topicName: { type: 'string', description: 'projects/<id>/topics/<name>' },\n labelFilterAction: { type: 'string', enum: ['include', 'exclude'], default: 'include' },\n },\n required: ['topicName'],\n },\n },\n ],\n },\n\n async executeRead(inv: ConnectorInvocation): Promise<CapabilityReadResult> {\n const accessToken = await ensureFreshAccessToken(inv.source.credentials, clientId, clientSecret)\n if (inv.capabilityName === 'list_messages') return listMessages(inv, accessToken, timeoutMs)\n if (inv.capabilityName === 'read_message') return readMessage(inv, accessToken, timeoutMs)\n throw new Error(`gmail: unknown read capability ${inv.capabilityName}`)\n },\n\n async executeMutation(inv: ConnectorInvocation): Promise<CapabilityMutationResult> {\n const accessToken = await ensureFreshAccessToken(inv.source.credentials, clientId, clientSecret)\n if (inv.capabilityName === 'send_reply') return sendReply(inv, accessToken, timeoutMs)\n if (inv.capabilityName === 'watch_label') return watchLabel(inv, accessToken, timeoutMs)\n throw new Error(`gmail: unknown mutation capability ${inv.capabilityName}`)\n },\n\n async exchangeOAuth(input) {\n const tokens = await exchangeAuthorizationCode({\n tokenUrl: TOKEN_URL,\n clientId,\n clientSecret,\n code: input.code,\n codeVerifier: input.codeVerifier,\n redirectUri: input.redirectUri,\n })\n return {\n credentials: {\n kind: 'oauth2',\n accessToken: tokens.accessToken,\n refreshToken: tokens.refreshToken,\n expiresAt: tokens.expiresIn ? Date.now() + tokens.expiresIn * 1000 : undefined,\n },\n scopes: tokens.scope?.split(/\\s+/) ?? scopes,\n metadata: {},\n }\n },\n\n async refreshToken(creds) {\n if (creds.kind !== 'oauth2' || !creds.refreshToken) {\n throw new Error('gmail.refreshToken: missing refresh token')\n }\n const refreshed = await refreshAccessToken({\n tokenUrl: TOKEN_URL,\n clientId,\n clientSecret,\n refreshToken: creds.refreshToken,\n })\n return {\n kind: 'oauth2',\n accessToken: refreshed.accessToken,\n refreshToken: refreshed.refreshToken ?? creds.refreshToken,\n expiresAt: refreshed.expiresIn ? Date.now() + refreshed.expiresIn * 1000 : undefined,\n }\n },\n\n async test(source) {\n try {\n const accessToken = await ensureFreshAccessToken(source.credentials, clientId, clientSecret)\n const res = await fetch(`${API}/profile`, {\n headers: { authorization: `Bearer ${accessToken}` },\n signal: AbortSignal.timeout(8_000),\n })\n if (res.status === 401 || res.status === 403) {\n return { ok: false, reason: `Google rejected Gmail token (${res.status}) — reconnect required` }\n }\n if (!res.ok) return { ok: false, reason: `Gmail returned ${res.status}` }\n return { ok: true }\n } catch (err) {\n return { ok: false, reason: err instanceof Error ? err.message : String(err) }\n }\n },\n }\n return adapter\n}\n\ninterface MessageMetadata {\n id: string\n threadId: string\n snippet?: string\n internalDate?: string\n labelIds?: string[]\n payload?: { headers?: Array<{ name: string; value: string }> }\n}\n\nasync function listMessages(\n inv: ConnectorInvocation,\n accessToken: string,\n timeoutMs: number,\n): Promise<CapabilityReadResult> {\n const args = (inv.args ?? {}) as {\n labelIds?: string[]\n query?: string\n maxResults?: number\n pageToken?: string\n }\n const params = new URLSearchParams({\n maxResults: String(args.maxResults ?? 25),\n })\n for (const id of args.labelIds ?? ['INBOX']) params.append('labelIds', id)\n if (args.query) params.set('q', args.query)\n if (args.pageToken) params.set('pageToken', args.pageToken)\n const listRes = await fetch(`${API}/messages?${params.toString()}`, {\n headers: { authorization: `Bearer ${accessToken}` },\n signal: AbortSignal.timeout(timeoutMs),\n })\n if (listRes.status === 401 || listRes.status === 403) {\n throw new CredentialsExpired(`Gmail rejected token (${listRes.status})`, inv.source.id)\n }\n if (!listRes.ok) {\n const text = await listRes.text().catch(() => '')\n throw new Error(`gmail list_messages ${listRes.status}: ${text.slice(0, 200)}`)\n }\n const listJson = (await listRes.json()) as {\n messages?: Array<{ id: string; threadId: string }>\n nextPageToken?: string\n }\n const ids = listJson.messages ?? []\n const metas = await Promise.all(\n ids.map(async ({ id }) => {\n const res = await fetch(`${API}/messages/${encodeURIComponent(id)}?format=metadata&metadataHeaders=From&metadataHeaders=To&metadataHeaders=Subject&metadataHeaders=Date`, {\n headers: { authorization: `Bearer ${accessToken}` },\n signal: AbortSignal.timeout(timeoutMs),\n })\n if (!res.ok) return null\n return (await res.json()) as MessageMetadata\n }),\n )\n const messages = metas.filter((m): m is MessageMetadata => Boolean(m)).map(toMessageSummary)\n return {\n data: { messages, nextPageToken: listJson.nextPageToken },\n fetchedAt: Date.now(),\n }\n}\n\nfunction toMessageSummary(meta: MessageMetadata): Record<string, unknown> {\n const headers = new Map((meta.payload?.headers ?? []).map((h) => [h.name.toLowerCase(), h.value]))\n return {\n id: meta.id,\n threadId: meta.threadId,\n snippet: meta.snippet,\n internalDate: meta.internalDate,\n labelIds: meta.labelIds ?? [],\n from: headers.get('from'),\n to: headers.get('to'),\n subject: headers.get('subject'),\n date: headers.get('date'),\n }\n}\n\ninterface FullMessage {\n id: string\n threadId: string\n internalDate?: string\n labelIds?: string[]\n payload?: MimePart\n}\n\ninterface MimePart {\n partId?: string\n mimeType?: string\n filename?: string\n headers?: Array<{ name: string; value: string }>\n body?: { size?: number; data?: string; attachmentId?: string }\n parts?: MimePart[]\n}\n\nasync function readMessage(\n inv: ConnectorInvocation,\n accessToken: string,\n timeoutMs: number,\n): Promise<CapabilityReadResult> {\n const { id } = inv.args as { id: string }\n const res = await fetch(`${API}/messages/${encodeURIComponent(id)}?format=full`, {\n headers: { authorization: `Bearer ${accessToken}` },\n signal: AbortSignal.timeout(timeoutMs),\n })\n if (res.status === 401 || res.status === 403) {\n throw new CredentialsExpired(`Gmail rejected token (${res.status})`, inv.source.id)\n }\n if (res.status === 404) {\n throw new Error(`gmail read_message: message ${id} not found`)\n }\n if (!res.ok) {\n const text = await res.text().catch(() => '')\n throw new Error(`gmail read_message ${res.status}: ${text.slice(0, 200)}`)\n }\n const full = (await res.json()) as FullMessage\n const headers = new Map((full.payload?.headers ?? []).map((h) => [h.name.toLowerCase(), h.value]))\n const body: { text?: string; html?: string } = {}\n const attachments: Array<{ filename: string; mimeType: string; attachmentId: string; size: number }> = []\n walkParts(full.payload, body, attachments)\n return {\n data: {\n id: full.id,\n threadId: full.threadId,\n internalDate: full.internalDate,\n labelIds: full.labelIds ?? [],\n from: headers.get('from'),\n to: headers.get('to'),\n cc: headers.get('cc'),\n subject: headers.get('subject'),\n date: headers.get('date'),\n body,\n attachments,\n },\n fetchedAt: Date.now(),\n }\n}\n\nfunction walkParts(\n part: MimePart | undefined,\n body: { text?: string; html?: string },\n attachments: Array<{ filename: string; mimeType: string; attachmentId: string; size: number }>,\n): void {\n if (!part) return\n if (part.body?.data && part.mimeType === 'text/plain' && !body.text) {\n body.text = decodeBase64Url(part.body.data)\n } else if (part.body?.data && part.mimeType === 'text/html' && !body.html) {\n body.html = decodeBase64Url(part.body.data)\n }\n if (part.filename && part.body?.attachmentId) {\n attachments.push({\n filename: part.filename,\n mimeType: part.mimeType ?? 'application/octet-stream',\n attachmentId: part.body.attachmentId,\n size: part.body.size ?? 0,\n })\n }\n for (const child of part.parts ?? []) walkParts(child, body, attachments)\n}\n\nfunction decodeBase64Url(s: string): string {\n return Buffer.from(s.replace(/-/g, '+').replace(/_/g, '/'), 'base64').toString('utf-8')\n}\n\nfunction encodeBase64Url(s: string): string {\n return Buffer.from(s, 'utf-8').toString('base64').replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '')\n}\n\nasync function sendReply(\n inv: ConnectorInvocation,\n accessToken: string,\n timeoutMs: number,\n): Promise<CapabilityMutationResult> {\n const { threadId, body, replyAll, cc } = inv.args as {\n threadId: string\n body: string\n replyAll?: boolean\n cc?: string[]\n }\n const threadRes = await fetch(`${API}/threads/${encodeURIComponent(threadId)}?format=metadata&metadataHeaders=From&metadataHeaders=To&metadataHeaders=Cc&metadataHeaders=Subject&metadataHeaders=Message-ID&metadataHeaders=References`, {\n headers: { authorization: `Bearer ${accessToken}` },\n signal: AbortSignal.timeout(timeoutMs),\n })\n if (threadRes.status === 401 || threadRes.status === 403) {\n throw new CredentialsExpired(`Gmail rejected token (${threadRes.status})`, inv.source.id)\n }\n if (!threadRes.ok) {\n const text = await threadRes.text().catch(() => '')\n throw new Error(`gmail send_reply thread fetch ${threadRes.status}: ${text.slice(0, 200)}`)\n }\n const thread = (await threadRes.json()) as { messages?: FullMessage[] }\n const last = thread.messages?.[thread.messages.length - 1]\n if (!last) throw new Error(`gmail send_reply: thread ${threadId} has no messages`)\n const lastHeaders = new Map((last.payload?.headers ?? []).map((h) => [h.name.toLowerCase(), h.value]))\n const inReplyTo = lastHeaders.get('message-id')\n const refsHeader = lastHeaders.get('references')\n const refs = refsHeader ? `${refsHeader} ${inReplyTo ?? ''}`.trim() : inReplyTo\n const fromHeader = lastHeaders.get('from')\n const toHeader = lastHeaders.get('to')\n const ccHeader = lastHeaders.get('cc')\n const subject = lastHeaders.get('subject') ?? ''\n\n const rfcHeaders: string[] = []\n if (fromHeader) rfcHeaders.push(`To: ${fromHeader}`)\n if (replyAll) {\n const extra = [toHeader, ccHeader].filter(Boolean).join(', ')\n if (extra) rfcHeaders.push(`Cc: ${extra}`)\n }\n if (cc?.length) {\n const existing = rfcHeaders.findIndex((h) => h.startsWith('Cc: '))\n if (existing >= 0) rfcHeaders[existing] = `${rfcHeaders[existing]}, ${cc.join(', ')}`\n else rfcHeaders.push(`Cc: ${cc.join(', ')}`)\n }\n rfcHeaders.push(`Subject: ${subject.toLowerCase().startsWith('re:') ? subject : 'Re: ' + subject}`)\n if (inReplyTo) rfcHeaders.push(`In-Reply-To: ${inReplyTo}`)\n if (refs) rfcHeaders.push(`References: ${refs}`)\n rfcHeaders.push(`X-Tangle-Idempotency-Key: ${inv.idempotencyKey}`)\n rfcHeaders.push('Content-Type: text/plain; charset=\"UTF-8\"')\n rfcHeaders.push('MIME-Version: 1.0')\n\n const raw = `${rfcHeaders.join('\\r\\n')}\\r\\n\\r\\n${body}`\n const sendBody = { threadId, raw: encodeBase64Url(raw) }\n const sendRes = await fetch(`${API}/messages/send`, {\n method: 'POST',\n headers: {\n authorization: `Bearer ${accessToken}`,\n 'content-type': 'application/json',\n },\n body: JSON.stringify(sendBody),\n signal: AbortSignal.timeout(timeoutMs),\n })\n if (sendRes.status === 401 || sendRes.status === 403) {\n throw new CredentialsExpired(`Gmail rejected token (${sendRes.status})`, inv.source.id)\n }\n if (!sendRes.ok) {\n const text = await sendRes.text().catch(() => '')\n throw new Error(`gmail send_reply ${sendRes.status}: ${text.slice(0, 200)}`)\n }\n const sent = (await sendRes.json()) as { id: string; threadId: string; labelIds?: string[] }\n return {\n status: 'committed',\n data: { id: sent.id, threadId: sent.threadId, labelIds: sent.labelIds ?? [] },\n committedAt: Date.now(),\n idempotentReplay: false,\n }\n}\n\nasync function watchLabel(\n inv: ConnectorInvocation,\n accessToken: string,\n timeoutMs: number,\n): Promise<CapabilityMutationResult> {\n const { labelIds, topicName, labelFilterAction } = inv.args as {\n labelIds?: string[]\n topicName: string\n labelFilterAction?: 'include' | 'exclude'\n }\n const body: Record<string, unknown> = {\n topicName,\n labelIds: labelIds ?? ['INBOX'],\n labelFilterAction: labelFilterAction ?? 'include',\n }\n const res = await fetch(`${API}/watch`, {\n method: 'POST',\n headers: {\n authorization: `Bearer ${accessToken}`,\n 'content-type': 'application/json',\n },\n body: JSON.stringify(body),\n signal: AbortSignal.timeout(timeoutMs),\n })\n if (res.status === 401 || res.status === 403) {\n throw new CredentialsExpired(`Gmail rejected token (${res.status})`, inv.source.id)\n }\n if (!res.ok) {\n const text = await res.text().catch(() => '')\n throw new Error(`gmail watch_label ${res.status}: ${text.slice(0, 200)}`)\n }\n const json = (await res.json()) as { historyId: string; expiration: string }\n return {\n status: 'committed',\n data: { historyId: json.historyId, expiration: json.expiration, topicName, labelIds: body.labelIds },\n committedAt: Date.now(),\n idempotentReplay: false,\n }\n}\n\nasync function ensureFreshAccessToken(\n creds: ConnectorCredentials,\n clientId: string,\n clientSecret: string,\n): Promise<string> {\n if (creds.kind !== 'oauth2') {\n throw new Error('gmail: expected oauth2 credentials')\n }\n if (creds.accessToken && (!creds.expiresAt || creds.expiresAt > Date.now() + 60_000)) {\n return creds.accessToken\n }\n if (!creds.refreshToken) {\n throw new CredentialsExpired('Gmail access token expired and no refresh token', '')\n }\n const refreshed = await refreshAccessToken({\n tokenUrl: TOKEN_URL,\n clientId,\n clientSecret,\n refreshToken: creds.refreshToken,\n })\n creds.accessToken = refreshed.accessToken\n creds.expiresAt = refreshed.expiresIn ? Date.now() + refreshed.expiresIn * 1000 : undefined\n if (refreshed.refreshToken) creds.refreshToken = refreshed.refreshToken\n return creds.accessToken\n}\n","/**\n * Microsoft Graph Calendar connector — the Outlook half of the\n * voice-agent's \"book me a slot\" surface.\n *\n * Mirrors the Google Calendar pattern almost line-for-line, with two\n * upstream-specific quirks worth calling out:\n *\n * 1. Graph exposes `@odata.etag` on every event resource AND honors\n * `If-Match` on `events.patch` / `events.delete`. So unlike Calendar\n * (insert can't be preconditioned against a non-existent resource),\n * we DO get real etag CAS for updates after the booking. We still\n * use the freebusy pre-flight for the create path, because the\n * \"two callers grab the same slot\" race happens before any event\n * exists.\n *\n * 2. `getSchedule` is the Graph equivalent of `freeBusy.query`. Same\n * shape: send `[start, end]` plus the calendar's email/UPN, get\n * back a `scheduleItems` list of busy windows.\n *\n * Why the same flow ports cleanly: the conflict mode is identical\n * (\"did someone else grab this slot between read and write?\"). The\n * mechanism — pre-flight read + idempotent insert — composes regardless\n * of whether upstream gives us a request-id dedup feature. Graph does\n * not have a `requestId` analogue on `events.create`, so we rely\n * exclusively on MutationGuard's idempotency-key short-circuit ABOVE\n * the connector. That layer prevents duplicate inserts on retry.\n */\n\nimport {\n type ConnectorAdapter,\n type ConnectorInvocation,\n type CapabilityReadResult,\n type CapabilityMutationResult,\n type ConnectorCredentials,\n ResourceContention,\n CredentialsExpired,\n} from '../types.js'\nimport { exchangeAuthorizationCode, refreshAccessToken } from '../oauth.js'\n\nconst SCOPES = [\n 'https://graph.microsoft.com/Calendars.ReadWrite',\n // offline_access is required to receive a refresh_token from the v2.0\n // endpoint; without it Graph hands back access tokens only and the\n // connection silently dies after ~1 hour.\n 'offline_access',\n]\nconst AUTH_URL = 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize'\nconst TOKEN_URL = 'https://login.microsoftonline.com/common/oauth2/v2.0/token'\n\n/** OAuth client config the factory closes over. Caller resolves these\n * at construction time (env, DB, secret manager — package doesn't care). */\nexport interface MicrosoftCalendarOptions {\n clientId: string\n clientSecret: string\n}\n\nexport function microsoftCalendar(opts: MicrosoftCalendarOptions): ConnectorAdapter {\n const { clientId, clientSecret } = opts\n const adapter: ConnectorAdapter = {\n manifest: {\n kind: 'microsoft-calendar',\n displayName: 'Microsoft Calendar (Outlook 365)',\n description:\n \"Let your agent check availability and book against an Outlook / Microsoft 365 calendar. Conflict-resolved via Graph's getSchedule pre-flight; etag-guarded on event updates.\",\n auth: {\n kind: 'oauth2',\n authorizationUrl: AUTH_URL,\n tokenUrl: TOKEN_URL,\n scopes: SCOPES,\n clientIdEnv: 'MS_OAUTH_CLIENT_ID',\n clientSecretEnv: 'MS_OAUTH_CLIENT_SECRET',\n // Microsoft v2.0 doesn't need extra params to issue a refresh_token\n // as long as `offline_access` is in scopes (above).\n },\n category: 'calendar',\n defaultConsistencyModel: 'authoritative',\n capabilities: [\n {\n name: 'list_availability',\n class: 'read',\n description:\n 'Look up busy windows on the connected Outlook calendar between timeMin and timeMax (RFC3339 timestamps).',\n parameters: {\n type: 'object',\n properties: {\n timeMin: { type: 'string', description: 'ISO8601 lower bound (inclusive)' },\n timeMax: { type: 'string', description: 'ISO8601 upper bound (exclusive)' },\n },\n required: ['timeMin', 'timeMax'],\n },\n },\n {\n name: 'book_slot',\n class: 'mutation',\n description:\n 'Reserve a time window on the connected Outlook calendar. Returns conflict + alternatives if the slot is no longer free.',\n cas: 'native-idempotency',\n externalEffect: true,\n parameters: {\n type: 'object',\n properties: {\n start: { type: 'string', description: 'ISO8601 start time' },\n end: { type: 'string', description: 'ISO8601 end time' },\n summary: { type: 'string', description: 'Event title (subject)' },\n description: { type: 'string', description: 'Optional event body' },\n attendees: {\n type: 'array',\n items: { type: 'string', description: 'attendee email' },\n },\n },\n required: ['start', 'end', 'summary'],\n },\n },\n ],\n },\n\n async executeRead(inv: ConnectorInvocation): Promise<CapabilityReadResult> {\n if (inv.capabilityName !== 'list_availability') {\n throw new Error(`microsoft-calendar: unknown read capability ${inv.capabilityName}`)\n }\n const userPrincipal = readMetaString(inv.source.metadata, 'userPrincipal')\n const { timeMin, timeMax } = inv.args as { timeMin: string; timeMax: string }\n const accessToken = await ensureFreshAccessToken(inv.source.credentials, clientId, clientSecret)\n const busy = await getScheduleBusy({ accessToken, userPrincipal, timeMin, timeMax })\n return {\n data: { busy },\n fetchedAt: Date.now(),\n }\n },\n\n async executeMutation(inv: ConnectorInvocation): Promise<CapabilityMutationResult> {\n if (inv.capabilityName !== 'book_slot') {\n throw new Error(`microsoft-calendar: unknown mutation capability ${inv.capabilityName}`)\n }\n const userPrincipal = readMetaString(inv.source.metadata, 'userPrincipal')\n const { start, end, summary, description, attendees } = inv.args as {\n start: string\n end: string\n summary: string\n description?: string\n attendees?: string[]\n }\n const accessToken = await ensureFreshAccessToken(inv.source.credentials, clientId, clientSecret)\n\n // Pre-flight: getSchedule for [start, end] on this user.\n const busy = await getScheduleBusy({ accessToken, userPrincipal, timeMin: start, timeMax: end })\n if (busy.length > 0) {\n const startMs = Date.parse(start)\n const endMs = Date.parse(end)\n const durMs = endMs - startMs\n const alternatives = await findNextFreeSlots({\n accessToken,\n userPrincipal,\n searchFromMs: endMs,\n durationMs: durMs,\n wanted: 3,\n })\n throw new ResourceContention(\n `requested slot ${start}–${end} is no longer free`,\n alternatives,\n { busy },\n )\n }\n\n const event = {\n subject: summary,\n body: description ? { contentType: 'text', content: description } : undefined,\n start: { dateTime: start, timeZone: 'UTC' },\n end: { dateTime: end, timeZone: 'UTC' },\n attendees: attendees?.map(email => ({\n emailAddress: { address: email },\n type: 'required',\n })),\n }\n const res = await fetch('https://graph.microsoft.com/v1.0/me/events', {\n method: 'POST',\n headers: {\n authorization: `Bearer ${accessToken}`,\n 'content-type': 'application/json',\n },\n body: JSON.stringify(event),\n signal: AbortSignal.timeout(15_000),\n })\n if (res.status === 401 || res.status === 403) {\n throw new CredentialsExpired(`Microsoft Graph rejected token (${res.status})`, inv.source.id)\n }\n if (res.status === 412 || res.status === 409) {\n // 412 = If-Match precondition failed (not used on insert but Graph\n // can return it under specific concurrent-update races). 409 covers\n // duplicate resourceId on rare retries.\n throw new ResourceContention(\n `Microsoft Graph reported conflict on book_slot (${res.status})`,\n [],\n )\n }\n if (!res.ok) {\n const text = await res.text().catch(() => '')\n throw new Error(`microsoft-calendar book_slot ${res.status}: ${text.slice(0, 200)}`)\n }\n const created = (await res.json()) as { id: string; '@odata.etag'?: string; webLink?: string }\n return {\n status: 'committed',\n data: { eventId: created.id, webLink: created.webLink },\n etagAfter: created['@odata.etag'],\n committedAt: Date.now(),\n idempotentReplay: false,\n }\n },\n\n async exchangeOAuth(input) {\n if (!clientId || !clientSecret) {\n throw new Error('Microsoft OAuth client not configured (MS_OAUTH_CLIENT_ID / _SECRET)')\n }\n const tokens = await exchangeAuthorizationCode({\n tokenUrl: TOKEN_URL,\n clientId,\n clientSecret,\n code: input.code,\n codeVerifier: input.codeVerifier,\n redirectUri: input.redirectUri,\n })\n return {\n credentials: {\n kind: 'oauth2',\n accessToken: tokens.accessToken,\n refreshToken: tokens.refreshToken,\n expiresAt: tokens.expiresIn ? Date.now() + tokens.expiresIn * 1000 : undefined,\n },\n scopes: tokens.scope?.split(/\\s+/) ?? SCOPES,\n // Operator picks the shared mailbox / room calendar post-connect.\n // Default to the authenticated user's own primary calendar via 'me'.\n metadata: { userPrincipal: 'me' },\n }\n },\n\n async refreshToken(creds) {\n if (creds.kind !== 'oauth2' || !creds.refreshToken) {\n throw new Error('microsoft-calendar.refreshToken: missing refresh token')\n }\n const refreshed = await refreshAccessToken({\n tokenUrl: TOKEN_URL,\n clientId,\n clientSecret,\n refreshToken: creds.refreshToken,\n })\n return {\n kind: 'oauth2',\n accessToken: refreshed.accessToken,\n refreshToken: refreshed.refreshToken ?? creds.refreshToken,\n expiresAt: refreshed.expiresIn ? Date.now() + refreshed.expiresIn * 1000 : undefined,\n }\n },\n\n async test(source) {\n try {\n const accessToken = await ensureFreshAccessToken(source.credentials, clientId, clientSecret)\n // Cheapest possible Graph call that proves the grant: GET /me.\n const res = await fetch('https://graph.microsoft.com/v1.0/me?$select=id', {\n headers: { authorization: `Bearer ${accessToken}` },\n signal: AbortSignal.timeout(8_000),\n })\n if (res.status === 401 || res.status === 403) {\n return { ok: false, reason: `Microsoft rejected token (${res.status}) — reconnect required` }\n }\n if (!res.ok) return { ok: false, reason: `Microsoft Graph returned ${res.status}` }\n return { ok: true }\n } catch (err) {\n return { ok: false, reason: err instanceof Error ? err.message : String(err) }\n }\n },\n }\n return adapter\n}\n\ninterface BusyWindow {\n start: string\n end: string\n}\n\n/** Graph's getSchedule returns scheduleItems[].status in {free, busy,\n * tentative, oof, workingElsewhere, unknown}. We treat anything other\n * than 'free' as busy — same conservative reading Outlook uses. */\nasync function getScheduleBusy(input: {\n accessToken: string\n userPrincipal: string\n timeMin: string\n timeMax: string\n}): Promise<BusyWindow[]> {\n // 'me' shorthand only resolves on /me/calendar/getSchedule; if a\n // specific UPN was pinned in metadata we'd have to use the user-id\n // form. /me/calendar/getSchedule with schedules=[upn or 'me'] handles\n // both.\n const target = input.userPrincipal === 'me' ? 'me' : input.userPrincipal\n const url = 'https://graph.microsoft.com/v1.0/me/calendar/getSchedule'\n const res = await fetch(url, {\n method: 'POST',\n headers: {\n authorization: `Bearer ${input.accessToken}`,\n 'content-type': 'application/json',\n },\n body: JSON.stringify({\n schedules: [target],\n startTime: { dateTime: input.timeMin, timeZone: 'UTC' },\n endTime: { dateTime: input.timeMax, timeZone: 'UTC' },\n availabilityViewInterval: 30,\n }),\n signal: AbortSignal.timeout(10_000),\n })\n if (res.status === 401 || res.status === 403) {\n throw new CredentialsExpired(`Microsoft Graph rejected token (${res.status})`, '')\n }\n if (!res.ok) {\n const text = await res.text().catch(() => '')\n throw new Error(`microsoft-calendar getSchedule ${res.status}: ${text.slice(0, 200)}`)\n }\n const json = (await res.json()) as {\n value?: Array<{\n scheduleItems?: Array<{\n status?: string\n start?: { dateTime: string }\n end?: { dateTime: string }\n }>\n }>\n }\n const items = json.value?.[0]?.scheduleItems ?? []\n return items\n .filter(it => it.status && it.status !== 'free' && it.start && it.end)\n .map(it => ({ start: it.start!.dateTime, end: it.end!.dateTime }))\n}\n\nasync function findNextFreeSlots(input: {\n accessToken: string\n userPrincipal: string\n searchFromMs: number\n durationMs: number\n wanted: number\n}): Promise<BusyWindow[]> {\n const horizonMs = input.searchFromMs + 14 * 24 * 60 * 60 * 1000\n const out: BusyWindow[] = []\n let cursor = input.searchFromMs\n while (cursor < horizonMs && out.length < input.wanted) {\n const windowEnd = Math.min(cursor + 24 * 60 * 60 * 1000, horizonMs)\n const busy = await getScheduleBusy({\n accessToken: input.accessToken,\n userPrincipal: input.userPrincipal,\n timeMin: new Date(cursor).toISOString(),\n timeMax: new Date(windowEnd).toISOString(),\n })\n const norm = busy\n .map(b => ({ s: Date.parse(b.start), e: Date.parse(b.end) }))\n .filter(b => Number.isFinite(b.s) && Number.isFinite(b.e))\n .sort((a, b) => a.s - b.s)\n let pos = cursor\n for (const b of norm) {\n if (out.length >= input.wanted) break\n if (b.s > pos && b.s - pos >= input.durationMs) {\n out.push({ start: new Date(pos).toISOString(), end: new Date(pos + input.durationMs).toISOString() })\n }\n pos = Math.max(pos, b.e)\n }\n if (out.length < input.wanted && windowEnd - pos >= input.durationMs) {\n out.push({ start: new Date(pos).toISOString(), end: new Date(pos + input.durationMs).toISOString() })\n }\n cursor = windowEnd\n }\n return out.slice(0, input.wanted)\n}\n\nasync function ensureFreshAccessToken(creds: ConnectorCredentials, clientId: string, clientSecret: string): Promise<string> {\n if (creds.kind !== 'oauth2') {\n throw new Error('microsoft-calendar: expected oauth2 credentials')\n }\n if (creds.accessToken && (!creds.expiresAt || creds.expiresAt > Date.now() + 60_000)) {\n return creds.accessToken\n }\n if (!creds.refreshToken) {\n throw new CredentialsExpired('Microsoft Calendar access token expired and no refresh token', '')\n }\n const refreshed = await refreshAccessToken({\n tokenUrl: TOKEN_URL,\n clientId,\n clientSecret,\n refreshToken: creds.refreshToken,\n })\n creds.accessToken = refreshed.accessToken\n creds.expiresAt = refreshed.expiresIn ? Date.now() + refreshed.expiresIn * 1000 : undefined\n if (refreshed.refreshToken) creds.refreshToken = refreshed.refreshToken\n return creds.accessToken\n}\n\nfunction readMetaString(meta: Record<string, unknown>, key: string): string {\n const v = meta[key]\n if (typeof v !== 'string' || v.length === 0) {\n throw new Error(`microsoft-calendar DataSource.metadata.${key} is missing`)\n }\n return v\n}\n","/**\n * HubSpot CRM connector — three load-bearing capabilities, picked to\n * cover the voice-agent's CRM hot path without trying to swallow all of\n * HubSpot's surface in v1.\n *\n * find_contact(email)\n * → {contact: {id, properties}} | {found: false}\n * POST /crm/v3/objects/contacts/search with an email-equality filter.\n * Cheap, idempotent, no CAS needed (read).\n *\n * upsert_contact(email, properties)\n * → {contactId, created}\n * Mutation. CAS strategy = native-idempotency, BUT: HubSpot's\n * `idempotencyKey` query param is ONLY available on the v3 *batch*\n * endpoints (`/crm/v3/objects/contacts/batch/upsert`). The\n * single-record endpoints don't honor it. We use the batch endpoint\n * with a single-element array to get native idempotency on retry.\n *\n * create_note(contactId, body)\n * → {noteId}\n * Mutation that logs a note engagement on a contact and associates\n * it. Notes are append-only — there's no conflict to detect — so we\n * use native-idempotency via the same batch trick on\n * `/crm/v3/objects/notes/batch/create`.\n *\n * Why three and not thirty: the agent's leverage on HubSpot is\n * \"remember who I just spoke to\". `find_contact` lets the agent address\n * a returning caller by name; `upsert_contact` captures a new one\n * without duplicates; `create_note` writes the call's outcome as a CRM\n * activity. Anything beyond these (deals, tickets, lists) lives in\n * Tier-2 specific kinds — keeping the manifest tight keeps the agent's\n * tool registry comprehensible.\n */\n\nimport {\n type ConnectorAdapter,\n type ConnectorInvocation,\n type CapabilityReadResult,\n type CapabilityMutationResult,\n type ConnectorCredentials,\n ResourceContention,\n CredentialsExpired,\n} from '../types.js'\nimport { exchangeAuthorizationCode, refreshAccessToken } from '../oauth.js'\n\nconst SCOPES = [\n 'crm.objects.contacts.read',\n 'crm.objects.contacts.write',\n]\nconst AUTH_URL = 'https://app.hubspot.com/oauth/authorize'\nconst TOKEN_URL = 'https://api.hubapi.com/oauth/v1/token'\nconst API = 'https://api.hubapi.com'\n\n/** OAuth client config the factory closes over. Caller resolves these\n * at construction time (env, DB, secret manager — package doesn't care). */\nexport interface HubSpotOptions {\n clientId: string\n clientSecret: string\n}\n\nexport function hubspot(opts: HubSpotOptions): ConnectorAdapter {\n const { clientId, clientSecret } = opts\n const adapter: ConnectorAdapter = {\n manifest: {\n kind: 'hubspot',\n displayName: 'HubSpot CRM',\n description:\n \"Look up callers in HubSpot, upsert contacts without duplicates, and log call notes as CRM activities. Three capabilities — the voice-agent's CRM hot path.\",\n auth: {\n kind: 'oauth2',\n authorizationUrl: AUTH_URL,\n tokenUrl: TOKEN_URL,\n scopes: SCOPES,\n clientIdEnv: 'HUBSPOT_OAUTH_CLIENT_ID',\n clientSecretEnv: 'HUBSPOT_OAUTH_CLIENT_SECRET',\n },\n category: 'crm',\n defaultConsistencyModel: 'authoritative',\n capabilities: [\n {\n name: 'find_contact',\n class: 'read',\n description: 'Search HubSpot contacts by email. Returns the first match or {found:false}.',\n parameters: {\n type: 'object',\n properties: { email: { type: 'string', description: 'Email to search for (case-insensitive).' } },\n required: ['email'],\n },\n },\n {\n name: 'upsert_contact',\n class: 'mutation',\n description:\n 'Create-or-update a contact identified by email. Returns the contact id and a `created` flag indicating whether the row was new.',\n cas: 'native-idempotency',\n externalEffect: true,\n parameters: {\n type: 'object',\n properties: {\n email: { type: 'string' },\n properties: {\n type: 'object',\n additionalProperties: { type: 'string' },\n description: 'Property map (firstname, lastname, phone, company, …).',\n },\n },\n required: ['email'],\n },\n },\n {\n name: 'create_note',\n class: 'mutation',\n description:\n 'Log a note engagement against a contact. Append-only — note bodies do not conflict.',\n cas: 'native-idempotency',\n externalEffect: true,\n parameters: {\n type: 'object',\n properties: {\n contactId: { type: 'string' },\n body: { type: 'string', description: 'Note body (HTML or plain text).' },\n },\n required: ['contactId', 'body'],\n },\n },\n ],\n },\n\n async executeRead(inv: ConnectorInvocation): Promise<CapabilityReadResult> {\n if (inv.capabilityName !== 'find_contact') {\n throw new Error(`hubspot: unknown read capability ${inv.capabilityName}`)\n }\n const { email } = inv.args as { email: string }\n const accessToken = await ensureFreshAccessToken(inv.source.credentials, clientId, clientSecret)\n const res = await fetch(`${API}/crm/v3/objects/contacts/search`, {\n method: 'POST',\n headers: {\n authorization: `Bearer ${accessToken}`,\n 'content-type': 'application/json',\n },\n body: JSON.stringify({\n filterGroups: [\n {\n filters: [{ propertyName: 'email', operator: 'EQ', value: email.toLowerCase() }],\n },\n ],\n properties: ['email', 'firstname', 'lastname', 'phone', 'company'],\n limit: 1,\n }),\n signal: AbortSignal.timeout(10_000),\n })\n if (res.status === 401) {\n throw new CredentialsExpired(`HubSpot rejected token (401)`, inv.source.id)\n }\n if (!res.ok) {\n const text = await res.text().catch(() => '')\n throw new Error(`hubspot find_contact ${res.status}: ${text.slice(0, 200)}`)\n }\n const json = (await res.json()) as {\n results?: Array<{ id: string; properties: Record<string, string> }>\n }\n const first = json.results?.[0]\n return {\n data: first\n ? { found: true, contact: { id: first.id, properties: first.properties } }\n : { found: false },\n fetchedAt: Date.now(),\n }\n },\n\n async executeMutation(inv: ConnectorInvocation): Promise<CapabilityMutationResult> {\n const accessToken = await ensureFreshAccessToken(inv.source.credentials, clientId, clientSecret)\n if (inv.capabilityName === 'upsert_contact') {\n return upsertContact(inv, accessToken)\n }\n if (inv.capabilityName === 'create_note') {\n return createNote(inv, accessToken)\n }\n throw new Error(`hubspot: unknown mutation capability ${inv.capabilityName}`)\n },\n\n async exchangeOAuth(input) {\n if (!clientId || !clientSecret) {\n throw new Error('HubSpot OAuth client not configured (HUBSPOT_OAUTH_CLIENT_ID / _SECRET)')\n }\n const tokens = await exchangeAuthorizationCode({\n tokenUrl: TOKEN_URL,\n clientId,\n clientSecret,\n code: input.code,\n codeVerifier: input.codeVerifier,\n redirectUri: input.redirectUri,\n })\n return {\n credentials: {\n kind: 'oauth2',\n accessToken: tokens.accessToken,\n refreshToken: tokens.refreshToken,\n expiresAt: tokens.expiresIn ? Date.now() + tokens.expiresIn * 1000 : undefined,\n },\n scopes: tokens.scope?.split(/\\s+/) ?? SCOPES,\n metadata: {},\n }\n },\n\n async refreshToken(creds) {\n if (creds.kind !== 'oauth2' || !creds.refreshToken) {\n throw new Error('hubspot.refreshToken: missing refresh token')\n }\n const refreshed = await refreshAccessToken({\n tokenUrl: TOKEN_URL,\n clientId,\n clientSecret,\n refreshToken: creds.refreshToken,\n })\n return {\n kind: 'oauth2',\n accessToken: refreshed.accessToken,\n refreshToken: refreshed.refreshToken ?? creds.refreshToken,\n expiresAt: refreshed.expiresIn ? Date.now() + refreshed.expiresIn * 1000 : undefined,\n }\n },\n\n async test(source) {\n try {\n const accessToken = await ensureFreshAccessToken(source.credentials, clientId, clientSecret)\n // /oauth/v1/access-tokens/{token} is the cheapest grant-validity probe.\n const res = await fetch(`${API}/oauth/v1/access-tokens/${encodeURIComponent(accessToken)}`, {\n signal: AbortSignal.timeout(8_000),\n })\n if (res.status === 401 || res.status === 403 || res.status === 404) {\n return { ok: false, reason: `HubSpot rejected token (${res.status}) — reconnect required` }\n }\n if (!res.ok) return { ok: false, reason: `HubSpot returned ${res.status}` }\n return { ok: true }\n } catch (err) {\n return { ok: false, reason: err instanceof Error ? err.message : String(err) }\n }\n },\n }\n return adapter\n}\n\nasync function upsertContact(inv: ConnectorInvocation, accessToken: string): Promise<CapabilityMutationResult> {\n const { email, properties } = inv.args as { email: string; properties?: Record<string, string> }\n const idemKey = sanitizeIdempotencyKey(inv.idempotencyKey)\n // Batch-upsert is the only HubSpot endpoint that honors `idempotencyKey`.\n // See https://developers.hubspot.com/docs/api/crm/contacts batch upsert.\n const url = `${API}/crm/v3/objects/contacts/batch/upsert?idempotencyKey=${encodeURIComponent(idemKey)}`\n const body = {\n inputs: [\n {\n idProperty: 'email',\n id: email.toLowerCase(),\n properties: { email: email.toLowerCase(), ...(properties ?? {}) },\n },\n ],\n }\n const res = await fetch(url, {\n method: 'POST',\n headers: {\n authorization: `Bearer ${accessToken}`,\n 'content-type': 'application/json',\n },\n body: JSON.stringify(body),\n signal: AbortSignal.timeout(15_000),\n })\n if (res.status === 401) {\n throw new CredentialsExpired(`HubSpot rejected token (401)`, inv.source.id)\n }\n if (res.status === 409) {\n // HubSpot returns 409 when the upsert targets a record that's been\n // concurrently mutated in a way batch can't reconcile.\n const text = await res.text().catch(() => '')\n throw new ResourceContention(`hubspot upsert_contact conflict: ${text.slice(0, 200)}`)\n }\n if (!res.ok) {\n const text = await res.text().catch(() => '')\n throw new Error(`hubspot upsert_contact ${res.status}: ${text.slice(0, 200)}`)\n }\n const json = (await res.json()) as {\n results?: Array<{ id: string; createdAt?: string; updatedAt?: string }>\n status?: string\n }\n const first = json.results?.[0]\n if (!first) {\n throw new Error('hubspot upsert_contact: empty results array')\n }\n const created = first.createdAt && first.updatedAt && first.createdAt === first.updatedAt\n return {\n status: 'committed',\n data: { contactId: first.id, created: Boolean(created) },\n committedAt: Date.now(),\n idempotentReplay: false,\n }\n}\n\nasync function createNote(inv: ConnectorInvocation, accessToken: string): Promise<CapabilityMutationResult> {\n const { contactId, body } = inv.args as { contactId: string; body: string }\n const idemKey = sanitizeIdempotencyKey(inv.idempotencyKey)\n const url = `${API}/crm/v3/objects/notes/batch/create?idempotencyKey=${encodeURIComponent(idemKey)}`\n const payload = {\n inputs: [\n {\n properties: {\n hs_note_body: body,\n hs_timestamp: new Date().toISOString(),\n },\n associations: [\n {\n to: { id: contactId },\n // 202 = note→contact association type id (standard HubSpot mapping)\n types: [{ associationCategory: 'HUBSPOT_DEFINED', associationTypeId: 202 }],\n },\n ],\n },\n ],\n }\n const res = await fetch(url, {\n method: 'POST',\n headers: {\n authorization: `Bearer ${accessToken}`,\n 'content-type': 'application/json',\n },\n body: JSON.stringify(payload),\n signal: AbortSignal.timeout(15_000),\n })\n if (res.status === 401) {\n throw new CredentialsExpired(`HubSpot rejected token (401)`, inv.source.id)\n }\n if (res.status === 409) {\n const text = await res.text().catch(() => '')\n throw new ResourceContention(`hubspot create_note conflict: ${text.slice(0, 200)}`)\n }\n if (!res.ok) {\n const text = await res.text().catch(() => '')\n throw new Error(`hubspot create_note ${res.status}: ${text.slice(0, 200)}`)\n }\n const json = (await res.json()) as { results?: Array<{ id: string }> }\n const first = json.results?.[0]\n if (!first) {\n throw new Error('hubspot create_note: empty results array')\n }\n return {\n status: 'committed',\n data: { noteId: first.id },\n committedAt: Date.now(),\n idempotentReplay: false,\n }\n}\n\n/** HubSpot's `idempotencyKey` requires URL-safe ASCII, ≤ 64 chars. */\nfunction sanitizeIdempotencyKey(k: string): string {\n return k.replace(/[^A-Za-z0-9_-]/g, '_').slice(0, 64)\n}\n\nasync function ensureFreshAccessToken(creds: ConnectorCredentials, clientId: string, clientSecret: string): Promise<string> {\n if (creds.kind !== 'oauth2') {\n throw new Error('hubspot: expected oauth2 credentials')\n }\n if (creds.accessToken && (!creds.expiresAt || creds.expiresAt > Date.now() + 60_000)) {\n return creds.accessToken\n }\n if (!creds.refreshToken) {\n throw new CredentialsExpired('HubSpot access token expired and no refresh token', '')\n }\n const refreshed = await refreshAccessToken({\n tokenUrl: TOKEN_URL,\n clientId,\n clientSecret,\n refreshToken: creds.refreshToken,\n })\n creds.accessToken = refreshed.accessToken\n creds.expiresAt = refreshed.expiresIn ? Date.now() + refreshed.expiresIn * 1000 : undefined\n if (refreshed.refreshToken) creds.refreshToken = refreshed.refreshToken\n return creds.accessToken\n}\n","/**\n * Slack connector — bot-token OAuth, three messaging-oriented capabilities.\n *\n * post_message(channel, text|blocks) → mutation; cas: 'none'\n * lookup_user(email) → read\n * list_channels(types?, limit?) → read\n *\n * Why `cas: 'none'` is acceptable here (and only here in this batch):\n * Slack messages are advisory — we set\n * `defaultConsistencyModel: 'advisory'`. The registry validator allows\n * `cas: 'none'` only on non-authoritative connectors precisely so that\n * append-only messaging surfaces don't have to invent fake CAS theatre.\n * The agent's planner already treats `advisory` data as informational\n * and does not promise outcomes based on its post results without\n * a separate authoritative confirm. MutationGuard's idempotency-key\n * dedup remains in force above the connector — a retry of the same\n * post_message call will short-circuit before reaching Slack.\n *\n * Auth: standard OAuth2. Slack's `/oauth.v2.access` returns a bot\n * `access_token` (`xoxb-…`) but does NOT return a refresh_token unless\n * the app has rotated tokens enabled. Bot tokens are long-lived by\n * default; we surface refreshToken handling but treat its absence as\n * normal rather than an error.\n */\n\nimport {\n type ConnectorAdapter,\n type ConnectorInvocation,\n type CapabilityReadResult,\n type CapabilityMutationResult,\n type ConnectorCredentials,\n CredentialsExpired,\n} from '../types.js'\nimport { exchangeAuthorizationCode, refreshAccessToken } from '../oauth.js'\n\nconst SCOPES = ['chat:write', 'users:read', 'users:read.email', 'channels:read']\nconst AUTH_URL = 'https://slack.com/oauth/v2/authorize'\nconst TOKEN_URL = 'https://slack.com/api/oauth.v2.access'\nconst API = 'https://slack.com/api'\n\n/** OAuth client config the factory closes over. Caller resolves these\n * at construction time (env, DB, secret manager — package doesn't care). */\nexport interface SlackOptions {\n clientId: string\n clientSecret: string\n}\n\nexport function slack(opts: SlackOptions): ConnectorAdapter {\n const { clientId, clientSecret } = opts\n const adapter: ConnectorAdapter = {\n manifest: {\n // The inbound Events API receiver registers kind `slack-inbound`\n // (hmac signing-secret auth). This connector — kind `slack` —\n // carries the OAuth bot-token outbound surface. Two kinds, one\n // logical product, deliberately split because the credential shapes\n // are different (HMAC secret vs bot OAuth) and operators commonly\n // wire one without the other.\n kind: 'slack',\n displayName: 'Slack',\n description:\n \"Post messages from the agent into Slack, look up users by email, and list channels. Advisory surface — Slack posts are informational, not transactional.\",\n auth: {\n kind: 'oauth2',\n authorizationUrl: AUTH_URL,\n tokenUrl: TOKEN_URL,\n scopes: SCOPES,\n clientIdEnv: 'SLACK_OAUTH_CLIENT_ID',\n clientSecretEnv: 'SLACK_OAUTH_CLIENT_SECRET',\n },\n category: 'comms',\n defaultConsistencyModel: 'advisory',\n capabilities: [\n {\n name: 'post_message',\n class: 'mutation',\n description: 'Post a message from the bot to a channel or user DM. Append-only — no CAS.',\n cas: 'none',\n externalEffect: true,\n parameters: {\n type: 'object',\n properties: {\n channel: { type: 'string', description: 'Channel id (C…) or user id (U…) for DM.' },\n text: { type: 'string' },\n blocks: { type: 'array', description: 'Optional Slack Block Kit blocks.' },\n },\n required: ['channel'],\n },\n },\n {\n name: 'lookup_user',\n class: 'read',\n description: 'Look up a Slack workspace user by email.',\n parameters: {\n type: 'object',\n properties: { email: { type: 'string' } },\n required: ['email'],\n },\n },\n {\n name: 'list_channels',\n class: 'read',\n description: 'List channels visible to the bot. `types` defaults to public_channel,private_channel.',\n parameters: {\n type: 'object',\n properties: {\n types: { type: 'string', description: 'Comma-separated channel types.' },\n limit: { type: 'integer', minimum: 1, maximum: 1000, default: 200 },\n },\n },\n },\n ],\n },\n\n async executeRead(inv: ConnectorInvocation): Promise<CapabilityReadResult> {\n const accessToken = readBotToken(inv.source.credentials)\n if (inv.capabilityName === 'lookup_user') {\n const { email } = inv.args as { email: string }\n const url = `${API}/users.lookupByEmail?email=${encodeURIComponent(email)}`\n const json = await slackGet(url, accessToken, inv.source.id)\n if (!json.ok) {\n if (json.error === 'users_not_found') {\n return { data: { found: false }, fetchedAt: Date.now() }\n }\n throw new Error(`slack lookup_user: ${json.error ?? 'unknown'}`)\n }\n const u = json.user as { id: string; name?: string; real_name?: string; profile?: unknown } | undefined\n return {\n data: { found: true, user: u ? { id: u.id, name: u.name, realName: u.real_name } : null },\n fetchedAt: Date.now(),\n }\n }\n if (inv.capabilityName === 'list_channels') {\n const { types, limit } = inv.args as { types?: string; limit?: number }\n const params = new URLSearchParams({\n limit: String(Math.min(Math.max(1, limit ?? 200), 1000)),\n types: types ?? 'public_channel,private_channel',\n })\n const json = await slackGet(`${API}/conversations.list?${params.toString()}`, accessToken, inv.source.id)\n if (!json.ok) {\n throw new Error(`slack list_channels: ${json.error ?? 'unknown'}`)\n }\n const channels = (json.channels as Array<{ id: string; name: string; is_private?: boolean }>) ?? []\n return {\n data: { channels: channels.map(c => ({ id: c.id, name: c.name, isPrivate: c.is_private ?? false })) },\n fetchedAt: Date.now(),\n }\n }\n throw new Error(`slack: unknown read capability ${inv.capabilityName}`)\n },\n\n async executeMutation(inv: ConnectorInvocation): Promise<CapabilityMutationResult> {\n if (inv.capabilityName !== 'post_message') {\n throw new Error(`slack: unknown mutation capability ${inv.capabilityName}`)\n }\n const accessToken = readBotToken(inv.source.credentials)\n const { channel, text, blocks } = inv.args as {\n channel: string\n text?: string\n blocks?: unknown[]\n }\n const res = await fetch(`${API}/chat.postMessage`, {\n method: 'POST',\n headers: {\n authorization: `Bearer ${accessToken}`,\n 'content-type': 'application/json; charset=utf-8',\n },\n body: JSON.stringify({ channel, text, blocks }),\n signal: AbortSignal.timeout(15_000),\n })\n if (res.status === 401) {\n throw new CredentialsExpired('Slack rejected token (401)', inv.source.id)\n }\n if (!res.ok) {\n const t = await res.text().catch(() => '')\n throw new Error(`slack post_message HTTP ${res.status}: ${t.slice(0, 200)}`)\n }\n // Slack returns 200 with `ok:false` on logical errors. Map common\n // auth/scope failures back to CredentialsExpired so the UI can prompt\n // a reconnect.\n const json = (await res.json()) as {\n ok?: boolean\n error?: string\n ts?: string\n channel?: string\n }\n if (!json.ok) {\n if (\n json.error === 'invalid_auth' ||\n json.error === 'token_expired' ||\n json.error === 'not_authed' ||\n json.error === 'token_revoked'\n ) {\n throw new CredentialsExpired(`Slack rejected token: ${json.error}`, inv.source.id)\n }\n throw new Error(`slack post_message: ${json.error ?? 'unknown'}`)\n }\n return {\n status: 'committed',\n data: { ts: json.ts, channel: json.channel },\n committedAt: Date.now(),\n idempotentReplay: false,\n }\n },\n\n async exchangeOAuth(input) {\n if (!clientId || !clientSecret) {\n throw new Error('Slack OAuth client not configured (SLACK_OAUTH_CLIENT_ID / _SECRET)')\n }\n // Slack's oauth.v2.access response is non-standard: the bot token\n // lives at `access_token` inside the top-level response (NOT nested\n // — that's the v1 quirk). We use exchangeAuthorizationCode for the\n // POST mechanics, then re-tag the result.\n const tokens = await exchangeAuthorizationCode({\n tokenUrl: TOKEN_URL,\n clientId,\n clientSecret,\n code: input.code,\n codeVerifier: input.codeVerifier,\n redirectUri: input.redirectUri,\n })\n return {\n credentials: {\n kind: 'oauth2',\n accessToken: tokens.accessToken,\n refreshToken: tokens.refreshToken,\n expiresAt: tokens.expiresIn ? Date.now() + tokens.expiresIn * 1000 : undefined,\n },\n scopes: tokens.scope?.split(/[,\\s]+/) ?? SCOPES,\n metadata: {},\n }\n },\n\n async refreshToken(creds) {\n if (creds.kind !== 'oauth2' || !creds.refreshToken) {\n // Slack bot tokens are long-lived without rotation; absence of\n // refresh_token is normal. Return creds unchanged so the caller\n // doesn't trigger a reconnect prematurely.\n return creds\n }\n const refreshed = await refreshAccessToken({\n tokenUrl: TOKEN_URL,\n clientId,\n clientSecret,\n refreshToken: creds.refreshToken,\n })\n return {\n kind: 'oauth2',\n accessToken: refreshed.accessToken,\n refreshToken: refreshed.refreshToken ?? creds.refreshToken,\n expiresAt: refreshed.expiresIn ? Date.now() + refreshed.expiresIn * 1000 : undefined,\n }\n },\n\n async test(source) {\n try {\n const accessToken = readBotToken(source.credentials)\n const res = await fetch(`${API}/auth.test`, {\n method: 'POST',\n headers: { authorization: `Bearer ${accessToken}` },\n signal: AbortSignal.timeout(8_000),\n })\n if (!res.ok) return { ok: false, reason: `Slack returned ${res.status}` }\n const json = (await res.json()) as { ok?: boolean; error?: string }\n if (!json.ok) {\n return { ok: false, reason: `Slack auth.test: ${json.error ?? 'unknown'} — reconnect required` }\n }\n return { ok: true }\n } catch (err) {\n return { ok: false, reason: err instanceof Error ? err.message : String(err) }\n }\n },\n }\n return adapter\n}\n\nfunction readBotToken(creds: ConnectorCredentials): string {\n if (creds.kind !== 'oauth2' || typeof creds.accessToken !== 'string') {\n throw new Error('slack: expected oauth2 credentials')\n }\n return creds.accessToken\n}\n\ninterface SlackJsonResponse {\n ok?: boolean\n error?: string\n [k: string]: unknown\n}\n\nasync function slackGet(url: string, accessToken: string, dataSourceId: string): Promise<SlackJsonResponse> {\n const res = await fetch(url, {\n headers: { authorization: `Bearer ${accessToken}` },\n signal: AbortSignal.timeout(10_000),\n })\n if (res.status === 401) {\n throw new CredentialsExpired('Slack rejected token (401)', dataSourceId)\n }\n if (!res.ok) {\n const t = await res.text().catch(() => '')\n throw new Error(`slack HTTP ${res.status}: ${t.slice(0, 200)}`)\n }\n return (await res.json()) as SlackJsonResponse\n}\n","/**\n * Notion database connector — query + page-level CRUD against a single\n * connected database.\n *\n * query_database(filter?, pageSize?) → read\n * create_page(properties) → mutation; cas: 'native-idempotency'\n * update_page(pageId, properties) → mutation; cas: 'etag-if-match'\n *\n * CAS quirks worth flagging:\n *\n * 1. Notion added support for the `Idempotency-Key` HTTP header on\n * mutating requests. We forward our SDK's idempotency key on\n * create_page, which gives at-most-once semantics under the same\n * key for ~24h. MutationGuard's record short-circuits above us;\n * Notion's dedup is the second line of defense.\n *\n * 2. Notion does NOT expose a per-page etag the way Graph does. The\n * canonical drift signal is `last_edited_time` (RFC3339). Our\n * `update_page` capability accepts an `expectedLastEditedTime` arg;\n * if supplied, we GET the page first and compare. Mismatch →\n * ResourceContention with the current page state. Conflict-free\n * callers can omit the field (last-write-wins, the Notion default).\n *\n * Auth: standard OAuth2. Notion's token endpoint follows RFC 6749 with\n * one twist — the workspace_id and bot_id come back in the response and\n * we stash them in `metadata` so the agent can address resources by\n * workspace where useful.\n */\n\nimport {\n type ConnectorAdapter,\n type ConnectorInvocation,\n type CapabilityReadResult,\n type CapabilityMutationResult,\n type ConnectorCredentials,\n ResourceContention,\n CredentialsExpired,\n} from '../types.js'\nimport { exchangeAuthorizationCode, refreshAccessToken } from '../oauth.js'\n\nconst AUTH_URL = 'https://api.notion.com/v1/oauth/authorize'\nconst TOKEN_URL = 'https://api.notion.com/v1/oauth/token'\nconst API = 'https://api.notion.com/v1'\nconst NOTION_VERSION = '2022-06-28'\n\n/** OAuth client config the factory closes over. Caller resolves these\n * at construction time (env, DB, secret manager — package doesn't care). */\nexport interface NotionDatabaseOptions {\n clientId: string\n clientSecret: string\n}\n\nexport function notionDatabase(opts: NotionDatabaseOptions): ConnectorAdapter {\n const { clientId, clientSecret } = opts\n const adapter: ConnectorAdapter = {\n manifest: {\n kind: 'notion-database',\n displayName: 'Notion (database)',\n description:\n \"Query a Notion database, create new pages, and update existing ones with optimistic concurrency via last_edited_time.\",\n auth: {\n kind: 'oauth2',\n authorizationUrl: AUTH_URL,\n tokenUrl: TOKEN_URL,\n // Notion does not use OAuth scopes — the workspace owner picks\n // which pages/databases the integration sees during install. We\n // declare an empty scope list so the consent screen renders cleanly.\n scopes: [],\n clientIdEnv: 'NOTION_OAUTH_CLIENT_ID',\n clientSecretEnv: 'NOTION_OAUTH_CLIENT_SECRET',\n extraAuthParams: { owner: 'user' },\n },\n category: 'doc',\n defaultConsistencyModel: 'authoritative',\n capabilities: [\n {\n name: 'query_database',\n class: 'read',\n description: 'Query the connected Notion database with an optional filter object (Notion query DSL).',\n parameters: {\n type: 'object',\n properties: {\n filter: { type: 'object', description: 'Notion API filter object — passed through verbatim.' },\n pageSize: { type: 'integer', minimum: 1, maximum: 100, default: 50 },\n startCursor: { type: 'string' },\n },\n },\n },\n {\n name: 'create_page',\n class: 'mutation',\n description: 'Create a new page inside the connected database.',\n cas: 'native-idempotency',\n externalEffect: true,\n parameters: {\n type: 'object',\n properties: {\n properties: {\n type: 'object',\n description: 'Notion property map keyed by property name.',\n },\n },\n required: ['properties'],\n },\n },\n {\n name: 'update_page',\n class: 'mutation',\n description:\n 'Update properties on an existing page. If `expectedLastEditedTime` is supplied and stale, the update is rejected with conflict.',\n cas: 'etag-if-match',\n externalEffect: true,\n parameters: {\n type: 'object',\n properties: {\n pageId: { type: 'string' },\n properties: { type: 'object' },\n expectedLastEditedTime: {\n type: 'string',\n description: 'RFC3339 timestamp the agent observed on its last read. Drift triggers ResourceContention.',\n },\n },\n required: ['pageId', 'properties'],\n },\n },\n ],\n },\n\n async executeRead(inv: ConnectorInvocation): Promise<CapabilityReadResult> {\n if (inv.capabilityName !== 'query_database') {\n throw new Error(`notion-database: unknown read capability ${inv.capabilityName}`)\n }\n const accessToken = readToken(inv.source.credentials)\n const databaseId = readMetaString(inv.source.metadata, 'databaseId')\n const { filter, pageSize, startCursor } = inv.args as {\n filter?: unknown\n pageSize?: number\n startCursor?: string\n }\n const body: Record<string, unknown> = {\n page_size: Math.min(Math.max(1, pageSize ?? 50), 100),\n }\n if (filter) body.filter = filter\n if (startCursor) body.start_cursor = startCursor\n\n const res = await fetch(`${API}/databases/${encodeURIComponent(databaseId)}/query`, {\n method: 'POST',\n headers: notionHeaders(accessToken),\n body: JSON.stringify(body),\n signal: AbortSignal.timeout(10_000),\n })\n if (res.status === 401) {\n throw new CredentialsExpired('Notion rejected token (401)', inv.source.id)\n }\n if (!res.ok) {\n const text = await res.text().catch(() => '')\n throw new Error(`notion-database query_database ${res.status}: ${text.slice(0, 200)}`)\n }\n const json = (await res.json()) as {\n results?: Array<{ id: string; last_edited_time: string; properties: unknown; url?: string }>\n has_more?: boolean\n next_cursor?: string | null\n }\n return {\n data: {\n results: json.results ?? [],\n hasMore: json.has_more ?? false,\n nextCursor: json.next_cursor ?? null,\n },\n fetchedAt: Date.now(),\n }\n },\n\n async executeMutation(inv: ConnectorInvocation): Promise<CapabilityMutationResult> {\n const accessToken = readToken(inv.source.credentials)\n if (inv.capabilityName === 'create_page') return createPage(inv, accessToken)\n if (inv.capabilityName === 'update_page') return updatePage(inv, accessToken)\n throw new Error(`notion-database: unknown mutation capability ${inv.capabilityName}`)\n },\n\n async exchangeOAuth(input) {\n if (!clientId || !clientSecret) {\n throw new Error('Notion OAuth client not configured (NOTION_OAUTH_CLIENT_ID / _SECRET)')\n }\n // Notion REQUIRES Basic auth on the token endpoint and does not\n // accept client_id/client_secret in the form body. exchangeAuthorizationCode\n // posts both in the body; Notion ignores the duplicates and accepts\n // the Basic header — but we have to add the header explicitly.\n // We do the POST inline rather than extending the helper's\n // signature, since this is the one upstream that needs Basic.\n const body = new URLSearchParams({\n grant_type: 'authorization_code',\n code: input.code,\n redirect_uri: input.redirectUri,\n code_verifier: input.codeVerifier,\n })\n const res = await fetch(TOKEN_URL, {\n method: 'POST',\n headers: {\n authorization: `Basic ${Buffer.from(`${clientId}:${clientSecret}`).toString('base64')}`,\n 'content-type': 'application/x-www-form-urlencoded',\n accept: 'application/json',\n 'Notion-Version': NOTION_VERSION,\n },\n body,\n })\n if (!res.ok) {\n const text = await res.text().catch(() => '')\n throw new Error(`Notion OAuth token exchange failed: ${res.status} — ${text.slice(0, 200)}`)\n }\n const json = (await res.json()) as {\n access_token: string\n refresh_token?: string\n bot_id?: string\n workspace_id?: string\n workspace_name?: string\n duplicated_template_id?: string\n }\n return {\n credentials: {\n kind: 'oauth2',\n accessToken: json.access_token,\n refreshToken: json.refresh_token,\n },\n scopes: [],\n metadata: {\n botId: json.bot_id,\n workspaceId: json.workspace_id,\n workspaceName: json.workspace_name,\n // Operator picks the database in a follow-up step; default empty.\n databaseId: '',\n },\n }\n },\n\n async refreshToken(creds) {\n if (creds.kind !== 'oauth2' || !creds.refreshToken) {\n // Notion's standard tokens don't expire and don't ship a\n // refresh_token. If we have neither expiresAt nor refreshToken,\n // treat the existing access token as durable.\n if (creds.kind === 'oauth2' && creds.accessToken && !creds.expiresAt) {\n return creds\n }\n throw new Error('notion-database.refreshToken: missing refresh token')\n }\n const refreshed = await refreshAccessToken({\n tokenUrl: TOKEN_URL,\n clientId,\n clientSecret,\n refreshToken: creds.refreshToken,\n })\n return {\n kind: 'oauth2',\n accessToken: refreshed.accessToken,\n refreshToken: refreshed.refreshToken ?? creds.refreshToken,\n expiresAt: refreshed.expiresIn ? Date.now() + refreshed.expiresIn * 1000 : undefined,\n }\n },\n\n async test(source) {\n try {\n const accessToken = readToken(source.credentials)\n // /users/me is the cheapest grant-validity probe.\n const res = await fetch(`${API}/users/me`, {\n headers: notionHeaders(accessToken),\n signal: AbortSignal.timeout(8_000),\n })\n if (res.status === 401) return { ok: false, reason: 'Notion rejected token (401) — reconnect required' }\n if (!res.ok) return { ok: false, reason: `Notion returned ${res.status}` }\n return { ok: true }\n } catch (err) {\n return { ok: false, reason: err instanceof Error ? err.message : String(err) }\n }\n },\n }\n return adapter\n}\n\nasync function createPage(inv: ConnectorInvocation, accessToken: string): Promise<CapabilityMutationResult> {\n const databaseId = readMetaString(inv.source.metadata, 'databaseId')\n const { properties } = inv.args as { properties: Record<string, unknown> }\n const res = await fetch(`${API}/pages`, {\n method: 'POST',\n headers: {\n ...notionHeaders(accessToken),\n 'Idempotency-Key': inv.idempotencyKey,\n },\n body: JSON.stringify({\n parent: { database_id: databaseId },\n properties,\n }),\n signal: AbortSignal.timeout(15_000),\n })\n if (res.status === 401) {\n throw new CredentialsExpired('Notion rejected token (401)', inv.source.id)\n }\n if (res.status === 409) {\n throw new ResourceContention('Notion idempotency-key conflict — different args under same key')\n }\n if (!res.ok) {\n const text = await res.text().catch(() => '')\n throw new Error(`notion-database create_page ${res.status}: ${text.slice(0, 200)}`)\n }\n const created = (await res.json()) as { id: string; url?: string; last_edited_time?: string }\n return {\n status: 'committed',\n data: { pageId: created.id, url: created.url, lastEditedTime: created.last_edited_time },\n etagAfter: created.last_edited_time,\n committedAt: Date.now(),\n idempotentReplay: false,\n }\n}\n\nasync function updatePage(inv: ConnectorInvocation, accessToken: string): Promise<CapabilityMutationResult> {\n const { pageId, properties, expectedLastEditedTime } = inv.args as {\n pageId: string\n properties: Record<string, unknown>\n expectedLastEditedTime?: string\n }\n // Optional pre-flight CAS: if the agent supplied the timestamp it\n // observed on its last read, fetch the page and compare BEFORE\n // committing. The window between this read and the patch isn't\n // closed by Notion (no If-Match), but it shrinks the race to\n // milliseconds — sufficient for typical voice-agent cadences.\n if (expectedLastEditedTime) {\n const headRes = await fetch(`${API}/pages/${encodeURIComponent(pageId)}`, {\n headers: notionHeaders(accessToken),\n signal: AbortSignal.timeout(10_000),\n })\n if (headRes.status === 401) {\n throw new CredentialsExpired('Notion rejected token (401)', inv.source.id)\n }\n if (!headRes.ok) {\n const text = await headRes.text().catch(() => '')\n throw new Error(`notion-database update_page (preflight) ${headRes.status}: ${text.slice(0, 200)}`)\n }\n const page = (await headRes.json()) as { last_edited_time?: string; properties?: unknown }\n if (page.last_edited_time && page.last_edited_time !== expectedLastEditedTime) {\n throw new ResourceContention(\n `Notion page ${pageId} was modified since the agent last read it`,\n [],\n { last_edited_time: page.last_edited_time, properties: page.properties },\n )\n }\n }\n\n const res = await fetch(`${API}/pages/${encodeURIComponent(pageId)}`, {\n method: 'PATCH',\n headers: notionHeaders(accessToken),\n body: JSON.stringify({ properties }),\n signal: AbortSignal.timeout(15_000),\n })\n if (res.status === 401) {\n throw new CredentialsExpired('Notion rejected token (401)', inv.source.id)\n }\n if (res.status === 409 || res.status === 412) {\n throw new ResourceContention(`Notion update_page conflict (${res.status})`)\n }\n if (!res.ok) {\n const text = await res.text().catch(() => '')\n throw new Error(`notion-database update_page ${res.status}: ${text.slice(0, 200)}`)\n }\n const updated = (await res.json()) as { id: string; last_edited_time?: string; url?: string }\n return {\n status: 'committed',\n data: { pageId: updated.id, url: updated.url, lastEditedTime: updated.last_edited_time },\n etagAfter: updated.last_edited_time,\n committedAt: Date.now(),\n idempotentReplay: false,\n }\n}\n\nfunction notionHeaders(accessToken: string): Record<string, string> {\n return {\n authorization: `Bearer ${accessToken}`,\n 'Notion-Version': NOTION_VERSION,\n 'content-type': 'application/json',\n }\n}\n\nfunction readToken(creds: ConnectorCredentials): string {\n if (creds.kind !== 'oauth2' || typeof creds.accessToken !== 'string') {\n throw new Error('notion-database: expected oauth2 credentials')\n }\n return creds.accessToken\n}\n\nfunction readMetaString(meta: Record<string, unknown>, key: string): string {\n const v = meta[key]\n if (typeof v !== 'string' || v.length === 0) {\n throw new Error(`notion-database DataSource.metadata.${key} is missing`)\n }\n return v\n}\n","/**\n * @stable DocuSeal connector — e-signature flows for legal/tax agents.\n *\n * Three capabilities + inbound webhook surface:\n *\n * create_submission(templateId, submitters, sendEmail?)\n * → {submissionId, submitters: [{email, slug, url}], status: 'pending'}\n * Mutation. POST /api/submissions with an explicit\n * `external_id = idempotencyKey` so DocuSeal will dedupe the\n * submission across our retries (verified against DocuSeal's\n * external_id uniqueness behavior).\n *\n * get_submission(submissionId)\n * → {submissionId, status, completedAt?, submitters: [{email, status, completedAt?, slug, url}]}\n * Read. GET /api/submissions/:id, normalized so the agent doesn't\n * have to map DocuSeal's per-submitter status (`awaiting`, `sent`,\n * `opened`, `completed`, `declined`) onto a smaller taxonomy.\n *\n * void_submission(submissionId, reason?)\n * → {submissionId, status: 'voided', voidedAt}\n * Mutation. DELETE /api/submissions/:id with `reason` carried as a\n * header. CAS: etag-if-match — DocuSeal emits an updated_at value we\n * thread through as ETag so two concurrent voids don't race.\n *\n * handleInboundEvent (webhook surface)\n * DocuSeal pushes events to a customer-configured URL. We verify a\n * HMAC-SHA256 signature over the raw body keyed by the per-account\n * webhook secret (`X-Docuseal-Signature` header, lowercase hex). The\n * adapter parses the event shape and emits a normalized\n * `InboundEvent` row (eventType = `docuseal.submission.completed`,\n * etc.). Replay protection: DocuSeal does not currently sign a\n * timestamp, so we recommend the receiver pin a per-event-id idempotency\n * row (the `event_id` field on every push payload).\n *\n * Auth: API key (DocuSeal personal API key — every endpoint requires it\n * via the `X-Auth-Token` header). Webhook secret is a separate\n * credential delivered via the same DataSource — we accept either\n * `kind: 'api-key'` (action surface) or `kind: 'custom'` carrying\n * `apiKey` + `webhookSecret` (action + webhook on one connection).\n *\n * Error taxonomy (mapped via integrations/errors.ts):\n * 401 → provider_auth_failed (CredentialsExpired)\n * 404 → action_not_found (Error) — submission id is unknown\n * 409 → action_denied / ResourceContention when status guards\n * 429 → provider_rate_limited (status: 'rate-limited' result)\n * 5xx → provider_unavailable\n */\n\nimport { createHmac, timingSafeEqual } from 'node:crypto'\nimport {\n type ConnectorAdapter,\n type ConnectorInvocation,\n type CapabilityReadResult,\n type CapabilityMutationResult,\n type EventHandlerResult,\n type InboundEvent,\n ResourceContention,\n CredentialsExpired,\n} from '../types.js'\nimport { firstHeader } from '../webhooks.js'\n\nconst DEFAULT_BASE = 'https://api.docuseal.com'\n\nexport interface DocuSealOptions {\n /** Override the DocuSeal API base URL (self-hosted deployments). */\n baseUrl?: string\n /** Default request timeout in ms. */\n timeoutMs?: number\n}\n\ninterface DocuSealCredentials {\n apiKey: string\n webhookSecret?: string\n}\n\nfunction readDocuSealCredentials(creds: { kind: string; apiKey?: string; secret?: string; values?: Record<string, unknown> }): DocuSealCredentials {\n if (creds.kind === 'api-key' && typeof creds.apiKey === 'string' && creds.apiKey.length > 0) {\n return { apiKey: creds.apiKey }\n }\n if (creds.kind === 'custom' && creds.values && typeof creds.values.apiKey === 'string' && creds.values.apiKey.length > 0) {\n const webhookSecret = typeof creds.values.webhookSecret === 'string' ? creds.values.webhookSecret : undefined\n return { apiKey: creds.values.apiKey, webhookSecret }\n }\n throw new Error('docuseal: expected api-key credentials (apiKey + optional webhookSecret)')\n}\n\nexport function docuseal(opts: DocuSealOptions = {}): ConnectorAdapter {\n const baseUrl = (opts.baseUrl ?? DEFAULT_BASE).replace(/\\/$/, '')\n const timeoutMs = opts.timeoutMs ?? 30_000\n const adapter: ConnectorAdapter = {\n manifest: {\n kind: 'docuseal',\n displayName: 'DocuSeal',\n description:\n \"Send documents for e-signature via DocuSeal, poll submission status, void in-flight submissions, and react to push events when submitters sign.\",\n auth: {\n kind: 'api-key',\n hint: 'Paste a DocuSeal personal API key (settings → API). Optional webhook secret enables push-driven workflows.',\n },\n category: 'doc',\n defaultConsistencyModel: 'authoritative',\n capabilities: [\n {\n name: 'get_submission',\n class: 'read',\n description: 'Fetch the current status of a DocuSeal submission and each submitter.',\n parameters: {\n type: 'object',\n properties: { submissionId: { type: 'string' } },\n required: ['submissionId'],\n },\n },\n {\n name: 'create_submission',\n class: 'mutation',\n description:\n 'Send a template for signature to one or more submitters. external_id is the idempotency key; retries return the original submission.',\n cas: 'native-idempotency',\n externalEffect: true,\n parameters: {\n type: 'object',\n properties: {\n templateId: { type: 'string' },\n submitters: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n email: { type: 'string' },\n name: { type: 'string' },\n role: { type: 'string' },\n values: { type: 'object', additionalProperties: true },\n },\n required: ['email'],\n },\n },\n sendEmail: { type: 'boolean', default: true },\n message: { type: 'string' },\n },\n required: ['templateId', 'submitters'],\n },\n },\n {\n name: 'void_submission',\n class: 'mutation',\n description: 'Cancel an in-flight submission. CAS via updated_at — concurrent voids return ResourceContention.',\n cas: 'etag-if-match',\n externalEffect: true,\n parameters: {\n type: 'object',\n properties: {\n submissionId: { type: 'string' },\n reason: { type: 'string' },\n },\n required: ['submissionId'],\n },\n },\n ],\n },\n\n async executeRead(inv: ConnectorInvocation): Promise<CapabilityReadResult> {\n if (inv.capabilityName !== 'get_submission') {\n throw new Error(`docuseal: unknown read capability ${inv.capabilityName}`)\n }\n const { apiKey } = readDocuSealCredentials(inv.source.credentials)\n const { submissionId } = inv.args as { submissionId: string }\n const res = await fetch(`${baseUrl}/submissions/${encodeURIComponent(submissionId)}`, {\n headers: { 'X-Auth-Token': apiKey, accept: 'application/json' },\n signal: AbortSignal.timeout(timeoutMs),\n })\n if (res.status === 401) throw new CredentialsExpired('DocuSeal rejected API key (401)', inv.source.id)\n if (res.status === 404) {\n throw new Error(`docuseal get_submission: submission ${submissionId} not found`)\n }\n if (!res.ok) {\n const text = await res.text().catch(() => '')\n throw new Error(`docuseal get_submission ${res.status}: ${text.slice(0, 200)}`)\n }\n const json = (await res.json()) as DocuSealSubmission\n return {\n data: normalizeSubmission(json),\n etag: json.updated_at,\n fetchedAt: Date.now(),\n }\n },\n\n async executeMutation(inv: ConnectorInvocation): Promise<CapabilityMutationResult> {\n const { apiKey } = readDocuSealCredentials(inv.source.credentials)\n if (inv.capabilityName === 'create_submission') return createSubmission(inv, apiKey, baseUrl, timeoutMs)\n if (inv.capabilityName === 'void_submission') return voidSubmission(inv, apiKey, baseUrl, timeoutMs)\n throw new Error(`docuseal: unknown mutation capability ${inv.capabilityName}`)\n },\n\n verifySignature({ rawBody, headers, source }) {\n const creds = (() => {\n try {\n return readDocuSealCredentials(source.credentials)\n } catch {\n return null\n }\n })()\n if (!creds?.webhookSecret) return { valid: false, reason: 'missing_webhook_secret' }\n const sig = firstHeader(headers, 'x-docuseal-signature')\n if (!sig) return { valid: false, reason: 'missing_signature_header' }\n const expected = createHmac('sha256', creds.webhookSecret).update(rawBody).digest('hex')\n const a = Buffer.from(sig.toLowerCase(), 'utf-8')\n const b = Buffer.from(expected, 'utf-8')\n if (a.length !== b.length) return { valid: false, reason: 'invalid_signature' }\n return timingSafeEqual(a, b) ? { valid: true } : { valid: false, reason: 'invalid_signature' }\n },\n\n async handleInboundEvent({ rawBody }): Promise<EventHandlerResult> {\n let parsed: unknown\n try {\n parsed = JSON.parse(rawBody)\n } catch {\n return { events: [], response: { status: 400, body: { error: 'invalid_json' } } }\n }\n if (!parsed || typeof parsed !== 'object') {\n return { events: [], response: { status: 400, body: { error: 'invalid_payload' } } }\n }\n const evt = parsed as { event_type?: unknown; event_id?: unknown; timestamp?: unknown; data?: unknown }\n const eventType = typeof evt.event_type === 'string' ? `docuseal.${evt.event_type}` : 'docuseal.unknown'\n const providerEventId = typeof evt.event_id === 'string' ? evt.event_id : undefined\n const events: InboundEvent[] = [\n {\n eventType,\n providerEventId,\n payload: evt as Record<string, unknown>,\n },\n ]\n return { events }\n },\n\n async test(source) {\n try {\n const { apiKey } = readDocuSealCredentials(source.credentials)\n const res = await fetch(`${baseUrl}/templates?limit=1`, {\n headers: { 'X-Auth-Token': apiKey },\n signal: AbortSignal.timeout(8_000),\n })\n if (res.status === 401) return { ok: false, reason: 'DocuSeal rejected API key (401) — reconnect required' }\n if (!res.ok) return { ok: false, reason: `DocuSeal returned ${res.status}` }\n return { ok: true }\n } catch (err) {\n return { ok: false, reason: err instanceof Error ? err.message : String(err) }\n }\n },\n }\n return adapter\n}\n\ninterface DocuSealSubmitter {\n id?: number\n uuid?: string\n email: string\n name?: string\n slug?: string\n status?: string\n completed_at?: string | null\n embed_src?: string\n role?: string\n}\n\ninterface DocuSealSubmission {\n id: number | string\n status?: string\n external_id?: string\n updated_at?: string\n created_at?: string\n completed_at?: string | null\n submitters?: DocuSealSubmitter[]\n audit_log_url?: string\n combined_document_url?: string\n}\n\nfunction normalizeSubmission(s: DocuSealSubmission): Record<string, unknown> {\n return {\n submissionId: String(s.id),\n status: s.status ?? 'pending',\n updatedAt: s.updated_at,\n createdAt: s.created_at,\n completedAt: s.completed_at ?? undefined,\n auditLogUrl: s.audit_log_url,\n combinedDocumentUrl: s.combined_document_url,\n submitters: (s.submitters ?? []).map((sub) => ({\n email: sub.email,\n name: sub.name,\n role: sub.role,\n slug: sub.slug,\n status: sub.status ?? 'awaiting',\n completedAt: sub.completed_at ?? undefined,\n url: sub.embed_src,\n })),\n }\n}\n\nasync function createSubmission(\n inv: ConnectorInvocation,\n apiKey: string,\n baseUrl: string,\n timeoutMs: number,\n): Promise<CapabilityMutationResult> {\n const { templateId, submitters, sendEmail, message } = inv.args as {\n templateId: string\n submitters: Array<{ email: string; name?: string; role?: string; values?: Record<string, unknown> }>\n sendEmail?: boolean\n message?: string\n }\n const body = {\n template_id: templateId,\n external_id: inv.idempotencyKey,\n send_email: sendEmail ?? true,\n message,\n submitters: submitters.map((s) => ({\n email: s.email,\n name: s.name,\n role: s.role,\n values: s.values,\n })),\n }\n const res = await fetch(`${baseUrl}/submissions`, {\n method: 'POST',\n headers: {\n 'X-Auth-Token': apiKey,\n 'content-type': 'application/json',\n accept: 'application/json',\n },\n body: JSON.stringify(body),\n signal: AbortSignal.timeout(timeoutMs),\n })\n if (res.status === 401) throw new CredentialsExpired('DocuSeal rejected API key (401)', inv.source.id)\n if (res.status === 429) {\n const retryAfter = Number(res.headers.get('retry-after') ?? '5')\n return {\n status: 'rate-limited',\n retryAfterMs: Number.isFinite(retryAfter) ? retryAfter * 1000 : 5_000,\n message: 'DocuSeal rate-limited create_submission',\n }\n }\n if (res.status === 409) {\n // External id collision — pull the original submission and surface\n // it as an idempotent replay.\n const conflictJson = (await res.json().catch(() => ({}))) as DocuSealSubmission & { submission?: DocuSealSubmission }\n const original = conflictJson.submission ?? conflictJson\n return {\n status: 'committed',\n data: normalizeSubmission(original),\n etagAfter: original.updated_at,\n committedAt: Date.now(),\n idempotentReplay: true,\n }\n }\n if (!res.ok) {\n const text = await res.text().catch(() => '')\n throw new Error(`docuseal create_submission ${res.status}: ${text.slice(0, 200)}`)\n }\n const created = (await res.json()) as DocuSealSubmission | DocuSealSubmission[]\n const sub = Array.isArray(created) ? created[0] : created\n if (!sub) {\n throw new Error('docuseal create_submission: empty response body')\n }\n return {\n status: 'committed',\n data: normalizeSubmission(sub),\n etagAfter: sub.updated_at,\n committedAt: Date.now(),\n idempotentReplay: false,\n }\n}\n\nasync function voidSubmission(\n inv: ConnectorInvocation,\n apiKey: string,\n baseUrl: string,\n timeoutMs: number,\n): Promise<CapabilityMutationResult> {\n const { submissionId, reason } = inv.args as { submissionId: string; reason?: string }\n const headers: Record<string, string> = {\n 'X-Auth-Token': apiKey,\n accept: 'application/json',\n }\n if (inv.expectedEtag) headers['if-match'] = inv.expectedEtag\n if (reason) headers['x-docuseal-void-reason'] = reason\n const res = await fetch(`${baseUrl}/submissions/${encodeURIComponent(submissionId)}`, {\n method: 'DELETE',\n headers,\n signal: AbortSignal.timeout(timeoutMs),\n })\n if (res.status === 401) throw new CredentialsExpired('DocuSeal rejected API key (401)', inv.source.id)\n if (res.status === 404) {\n throw new Error(`docuseal void_submission: submission ${submissionId} not found`)\n }\n if (res.status === 412) {\n throw new ResourceContention(`docuseal void_submission: submission ${submissionId} updated since last read`)\n }\n if (res.status === 429) {\n const retryAfter = Number(res.headers.get('retry-after') ?? '5')\n return {\n status: 'rate-limited',\n retryAfterMs: Number.isFinite(retryAfter) ? retryAfter * 1000 : 5_000,\n message: 'DocuSeal rate-limited void_submission',\n }\n }\n if (!res.ok) {\n const text = await res.text().catch(() => '')\n throw new Error(`docuseal void_submission ${res.status}: ${text.slice(0, 200)}`)\n }\n const json = (await res.json().catch(() => ({}))) as DocuSealSubmission\n return {\n status: 'committed',\n data: {\n submissionId,\n status: 'voided',\n voidedAt: json.updated_at ?? new Date().toISOString(),\n },\n etagAfter: json.updated_at,\n committedAt: Date.now(),\n idempotentReplay: false,\n }\n}\n","import {\n type Capability,\n type CapabilityMutationResult,\n type CapabilityReadResult,\n type ConnectorAdapter,\n type ConnectorCredentials,\n type ConnectorInvocation,\n CredentialsExpired,\n} from '../types.js'\n\nexport type RestCredentialPlacement =\n | { kind: 'bearer' }\n | { kind: 'header'; header: string; prefix?: string }\n | { kind: 'query'; parameter: string }\n\nexport interface RestConnectorSpec {\n kind: string\n displayName: string\n description: string\n auth: ConnectorAdapter['manifest']['auth']\n category: ConnectorAdapter['manifest']['category']\n defaultConsistencyModel: ConnectorAdapter['manifest']['defaultConsistencyModel']\n baseUrl: string | { metadataKey: string; fallback?: string }\n credentialPlacement?: RestCredentialPlacement\n defaultHeaders?: Record<string, string>\n capabilities: RestOperationSpec[]\n test?: RestRequestSpec\n}\n\nexport interface RestOperationSpec {\n name: string\n class: 'read' | 'mutation'\n description: string\n parameters: Record<string, unknown>\n requiredScopes?: string[]\n request: RestRequestSpec\n cas?: 'etag-if-match' | 'native-idempotency' | 'optimistic-read-verify' | 'none'\n externalEffect?: boolean\n}\n\nexport interface RestRequestSpec {\n method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'\n path: string\n query?: Record<string, string | number | boolean | undefined>\n headers?: Record<string, string>\n body?: 'args' | string | Record<string, unknown>\n}\n\nexport function declarativeRestConnector(spec: RestConnectorSpec): ConnectorAdapter {\n const capabilities = spec.capabilities.map(operationToCapability)\n const adapter: ConnectorAdapter = {\n manifest: {\n kind: spec.kind,\n displayName: spec.displayName,\n description: spec.description,\n auth: spec.auth,\n category: spec.category,\n defaultConsistencyModel: spec.defaultConsistencyModel,\n capabilities,\n },\n\n async executeRead(inv: ConnectorInvocation): Promise<CapabilityReadResult> {\n const op = readOperation(spec, inv.capabilityName, 'read')\n const response = await executeRestRequest(spec, op.request, inv)\n return {\n data: response.data,\n etag: response.etag,\n fetchedAt: Date.now(),\n }\n },\n\n async executeMutation(inv: ConnectorInvocation): Promise<CapabilityMutationResult> {\n const op = readOperation(spec, inv.capabilityName, 'mutation')\n const response = await executeRestRequest(spec, op.request, inv)\n return {\n status: 'committed',\n data: response.data,\n etagAfter: response.etag,\n committedAt: Date.now(),\n idempotentReplay: false,\n }\n },\n\n async test(source) {\n if (!spec.test) return { ok: true }\n try {\n await executeRestRequest(spec, spec.test, {\n source,\n capabilityName: '__test__',\n args: {},\n idempotencyKey: 'test',\n })\n return { ok: true }\n } catch (error) {\n return { ok: false, reason: error instanceof Error ? error.message : 'unknown error' }\n }\n },\n }\n return adapter\n}\n\nfunction operationToCapability(op: RestOperationSpec): Capability {\n const base = {\n name: op.name,\n description: op.description,\n parameters: op.parameters,\n requiredScopes: op.requiredScopes,\n }\n if (op.class === 'read') {\n return { ...base, class: 'read' }\n }\n return {\n ...base,\n class: 'mutation',\n cas: op.cas ?? 'native-idempotency',\n externalEffect: op.externalEffect ?? true,\n }\n}\n\nfunction readOperation(spec: RestConnectorSpec, name: string, expected: 'read' | 'mutation'): RestOperationSpec {\n const op = spec.capabilities.find((candidate) => candidate.name === name)\n if (!op || op.class !== expected) {\n throw new Error(`${spec.kind}: unknown ${expected} capability ${name}`)\n }\n return op\n}\n\nasync function executeRestRequest(\n spec: RestConnectorSpec,\n request: RestRequestSpec,\n inv: ConnectorInvocation,\n): Promise<{ data: unknown; etag?: string }> {\n const baseUrl = resolveBaseUrl(spec.baseUrl, inv.source.metadata)\n const url = new URL(interpolate(request.path, inv.args), baseUrl.endsWith('/') ? baseUrl : `${baseUrl}/`)\n for (const [key, value] of Object.entries(request.query ?? {})) {\n const rendered = renderQueryValue(value, inv.args)\n if (rendered !== undefined && rendered !== '') url.searchParams.set(key, String(rendered))\n }\n const headers: Record<string, string> = {\n accept: 'application/json',\n ...spec.defaultHeaders,\n ...renderHeaders(request.headers ?? {}, inv.args),\n }\n applyCredentials(headers, url, spec.credentialPlacement ?? { kind: 'bearer' }, inv.source.credentials)\n if (inv.expectedEtag) headers['if-match'] = inv.expectedEtag\n if (request.method !== 'GET' && request.method !== 'DELETE') {\n headers['content-type'] = headers['content-type'] ?? 'application/json'\n }\n const res = await fetch(url, {\n method: request.method,\n headers,\n body: request.method === 'GET' || request.method === 'DELETE' ? undefined : JSON.stringify(resolveBody(request.body, inv.args)),\n signal: AbortSignal.timeout(20_000),\n })\n if (res.status === 401 || res.status === 403) {\n throw new CredentialsExpired(`${spec.displayName} rejected credentials (${res.status})`, inv.source.id)\n }\n if (res.status === 409 || res.status === 412) {\n return {\n data: {\n status: 'conflict',\n message: await safeErrorText(res),\n },\n etag: res.headers.get('etag') ?? undefined,\n }\n }\n if (res.status === 429) {\n return {\n data: {\n status: 'rate-limited',\n retryAfter: res.headers.get('retry-after') ?? undefined,\n message: await safeErrorText(res),\n },\n }\n }\n if (!res.ok) {\n throw new Error(`${spec.kind} ${request.method} ${url.pathname} HTTP ${res.status}: ${(await safeErrorText(res)).slice(0, 300)}`)\n }\n const text = await res.text()\n const data = text ? JSON.parse(text) as unknown : null\n return { data, etag: res.headers.get('etag') ?? undefined }\n}\n\nfunction resolveBaseUrl(baseUrl: RestConnectorSpec['baseUrl'], metadata: Record<string, unknown>): string {\n if (typeof baseUrl === 'string') return baseUrl\n const value = metadata[baseUrl.metadataKey]\n if (typeof value === 'string' && value.trim()) return value\n if (baseUrl.fallback) return baseUrl.fallback\n throw new Error(`missing metadata.${baseUrl.metadataKey} base URL`)\n}\n\nfunction applyCredentials(\n headers: Record<string, string>,\n url: URL,\n placement: RestCredentialPlacement,\n credentials: ConnectorCredentials,\n): void {\n const token = credentialToken(credentials)\n if (placement.kind === 'bearer') headers.authorization = `Bearer ${token}`\n if (placement.kind === 'header') headers[placement.header] = `${placement.prefix ?? ''}${token}`\n if (placement.kind === 'query') url.searchParams.set(placement.parameter, token)\n}\n\nfunction credentialToken(credentials: ConnectorCredentials): string {\n if (credentials.kind === 'oauth2') return credentials.accessToken\n if (credentials.kind === 'api-key') return credentials.apiKey\n throw new Error(`declarative REST connectors require oauth2 or api-key credentials, got ${credentials.kind}`)\n}\n\nfunction resolveBody(body: RestRequestSpec['body'], args: Record<string, unknown>): unknown {\n if (!body || body === 'args') return args\n if (typeof body === 'string') return renderValue(body, args)\n return renderObject(body, args)\n}\n\nfunction renderHeaders(headers: Record<string, string>, args: Record<string, unknown>): Record<string, string> {\n return Object.fromEntries(Object.entries(headers).map(([key, value]) => [key, interpolate(value, args)]))\n}\n\nfunction renderObject(input: Record<string, unknown>, args: Record<string, unknown>): Record<string, unknown> {\n return Object.fromEntries(Object.entries(input).map(([key, value]) => [key, renderValue(value, args)]))\n}\n\nfunction renderValue(value: unknown, args: Record<string, unknown>): unknown {\n if (typeof value === 'string') {\n const exact = value.match(/^\\{([a-zA-Z0-9_.-]+)\\}$/)\n if (exact) return readRequiredPath(args, exact[1])\n return interpolate(value, args)\n }\n return value\n}\n\nfunction renderQueryValue(value: unknown, args: Record<string, unknown>): unknown {\n if (typeof value !== 'string') return value\n const exact = value.match(/^\\{([a-zA-Z0-9_.-]+)\\}$/)\n if (exact) return readPath(args, exact[1])\n try {\n return interpolate(value, args)\n } catch {\n return undefined\n }\n}\n\nfunction interpolate(template: string, args: Record<string, unknown>): string {\n return template.replace(/\\{([a-zA-Z0-9_.-]+)\\}/g, (_match, key: string) => {\n const value = readPath(args, key)\n if (value === undefined || value === null) {\n throw new Error(`missing required argument: ${key}`)\n }\n return encodeURIComponent(String(value))\n })\n}\n\nfunction readRequiredPath(input: Record<string, unknown>, path: string): unknown {\n const value = readPath(input, path)\n if (value === undefined || value === null) throw new Error(`missing required argument: ${path}`)\n return value\n}\n\nfunction readPath(input: Record<string, unknown>, path: string): unknown {\n return path.split('.').reduce<unknown>((value, part) => {\n if (value && typeof value === 'object' && part in value) {\n return (value as Record<string, unknown>)[part]\n }\n return undefined\n }, input)\n}\n\nasync function safeErrorText(res: Response): Promise<string> {\n return (await res.text().catch(() => res.statusText)) || res.statusText\n}\n","/**\n * Twilio SMS connector — outbound texts + recent-message lookup. The\n * agent's \"send the caller a confirmation link\" surface.\n *\n * Auth: HTTP Basic (Account SID + Auth Token). Twilio's API key auth\n * also supports SID/Secret pairs; we accept either by treating the\n * stored apiKey envelope as `accountSid:authToken` (or\n * `accountSid:keySid:secret`) — the connector parses it at call time.\n *\n * send_sms(to, body)\n * Mutation. CAS = native-idempotency. Twilio added the\n * `Idempotency-Key` HTTP header to POST /Messages in 2024 — same\n * key + same args within 24h returns the original Message resource\n * instead of sending a second SMS. MutationGuard's record short-\n * circuits before us; Twilio's own dedup is defense-in-depth.\n *\n * lookup_number(phoneNumber)\n * Read. Hits /v1/PhoneNumbers/{e164} on Lookup API. Confirms the\n * number is real, returns carrier info if the caller has Lookup\n * enabled on their account.\n *\n * find_recent_messages(toOrFrom?, limit?)\n * Read. Returns the most recent Messages on the account, optionally\n * filtered by To/From. Useful for \"did the confirmation actually\n * send?\" introspection inside an agent run.\n */\n\nimport {\n type ConnectorAdapter,\n type ConnectorInvocation,\n type CapabilityReadResult,\n type CapabilityMutationResult,\n ResourceContention,\n CredentialsExpired,\n} from '../types.js'\n\nconst API = 'https://api.twilio.com/2010-04-01'\nconst LOOKUP_API = 'https://lookups.twilio.com/v1'\n\nexport const twilioSmsConnector: ConnectorAdapter = {\n manifest: {\n kind: 'twilio-sms',\n displayName: 'Twilio SMS',\n description:\n \"Send outbound SMS, look up phone numbers, and audit recent messages. Twilio's native Idempotency-Key prevents duplicate sends on retry.\",\n auth: {\n kind: 'api-key',\n hint: 'Paste your Twilio credentials as \"AccountSid:AuthToken\" (e.g. \"AC123…:abc…\"). API-key style \"AccountSid:KeySid:Secret\" is also accepted.',\n },\n category: 'comms',\n defaultConsistencyModel: 'authoritative',\n capabilities: [\n {\n name: 'send_sms',\n class: 'mutation',\n description: 'Send an SMS from the configured Twilio number to the supplied destination.',\n cas: 'native-idempotency',\n externalEffect: true,\n parameters: {\n type: 'object',\n properties: {\n to: { type: 'string', description: 'E.164 destination, e.g. +14155551212' },\n body: { type: 'string', description: 'Message body (≤1600 chars after Twilio segments).' },\n from: { type: 'string', description: 'Optional E.164 sender; falls back to metadata.fromNumber.' },\n },\n required: ['to', 'body'],\n },\n },\n {\n name: 'lookup_number',\n class: 'read',\n description: 'Validate a phone number and (if your account has Lookup) retrieve carrier metadata.',\n parameters: {\n type: 'object',\n properties: {\n phoneNumber: { type: 'string', description: 'E.164 number to look up.' },\n includeCarrier: { type: 'boolean', default: false },\n },\n required: ['phoneNumber'],\n },\n },\n {\n name: 'find_recent_messages',\n class: 'read',\n description: 'Return up to `limit` recent Messages on the account, optionally filtered by To or From.',\n parameters: {\n type: 'object',\n properties: {\n to: { type: 'string', description: 'Optional E.164 filter on the To address.' },\n from: { type: 'string', description: 'Optional E.164 filter on the From address.' },\n limit: { type: 'integer', minimum: 1, maximum: 100, default: 20 },\n },\n },\n },\n ],\n },\n\n async executeRead(inv: ConnectorInvocation): Promise<CapabilityReadResult> {\n const auth = parseAuth(inv.source.credentials)\n if (inv.capabilityName === 'lookup_number') {\n const { phoneNumber, includeCarrier } = inv.args as { phoneNumber: string; includeCarrier?: boolean }\n const url = `${LOOKUP_API}/PhoneNumbers/${encodeURIComponent(phoneNumber)}${includeCarrier ? '?Type=carrier' : ''}`\n const res = await fetch(url, {\n headers: { authorization: basicAuth(auth) },\n signal: AbortSignal.timeout(10_000),\n })\n if (res.status === 401) throw new CredentialsExpired('Twilio rejected credentials (401)', inv.source.id)\n if (res.status === 404) {\n return { data: { valid: false }, fetchedAt: Date.now() }\n }\n if (!res.ok) {\n const text = await res.text().catch(() => '')\n throw new Error(`twilio-sms lookup_number ${res.status}: ${text.slice(0, 200)}`)\n }\n const json = (await res.json()) as { phone_number?: string; carrier?: unknown; country_code?: string }\n return {\n data: {\n valid: true,\n phoneNumber: json.phone_number,\n countryCode: json.country_code,\n carrier: json.carrier,\n },\n fetchedAt: Date.now(),\n }\n }\n if (inv.capabilityName === 'find_recent_messages') {\n const { to, from, limit } = inv.args as { to?: string; from?: string; limit?: number }\n const params = new URLSearchParams()\n params.set('PageSize', String(Math.min(Math.max(1, limit ?? 20), 100)))\n if (to) params.set('To', to)\n if (from) params.set('From', from)\n const url = `${API}/Accounts/${encodeURIComponent(auth.accountSid)}/Messages.json?${params.toString()}`\n const res = await fetch(url, {\n headers: { authorization: basicAuth(auth) },\n signal: AbortSignal.timeout(10_000),\n })\n if (res.status === 401) throw new CredentialsExpired('Twilio rejected credentials (401)', inv.source.id)\n if (!res.ok) {\n const text = await res.text().catch(() => '')\n throw new Error(`twilio-sms find_recent_messages ${res.status}: ${text.slice(0, 200)}`)\n }\n const json = (await res.json()) as {\n messages?: Array<{ sid: string; to: string; from: string; body: string; status: string; date_sent?: string }>\n }\n return {\n data: { messages: json.messages ?? [] },\n fetchedAt: Date.now(),\n }\n }\n throw new Error(`twilio-sms: unknown read capability ${inv.capabilityName}`)\n },\n\n async executeMutation(inv: ConnectorInvocation): Promise<CapabilityMutationResult> {\n if (inv.capabilityName !== 'send_sms') {\n throw new Error(`twilio-sms: unknown mutation capability ${inv.capabilityName}`)\n }\n const auth = parseAuth(inv.source.credentials)\n const { to, body, from } = inv.args as { to: string; body: string; from?: string }\n const fromNumber = from ?? readMetaString(inv.source.metadata, 'fromNumber')\n const formBody = new URLSearchParams({ To: to, From: fromNumber, Body: body })\n const url = `${API}/Accounts/${encodeURIComponent(auth.accountSid)}/Messages.json`\n const res = await fetch(url, {\n method: 'POST',\n headers: {\n authorization: basicAuth(auth),\n 'content-type': 'application/x-www-form-urlencoded',\n 'idempotency-key': inv.idempotencyKey,\n },\n body: formBody,\n signal: AbortSignal.timeout(15_000),\n })\n if (res.status === 401) throw new CredentialsExpired('Twilio rejected credentials (401)', inv.source.id)\n if (res.status === 409) {\n // Twilio surfaces 409 when an idempotency-key conflict is detected\n // (same key, different request body).\n throw new ResourceContention('Twilio idempotency-key conflict — different args under same key')\n }\n if (!res.ok) {\n const text = await res.text().catch(() => '')\n throw new Error(`twilio-sms send_sms ${res.status}: ${text.slice(0, 200)}`)\n }\n const created = (await res.json()) as {\n sid: string\n status: string\n to: string\n from: string\n date_sent?: string\n }\n return {\n status: 'committed',\n data: { messageSid: created.sid, deliveryStatus: created.status, to: created.to, from: created.from },\n committedAt: Date.now(),\n idempotentReplay: false,\n }\n },\n\n async test(source) {\n try {\n const auth = parseAuth(source.credentials)\n // GET /Accounts/{sid}.json is the cheapest auth probe.\n const res = await fetch(`${API}/Accounts/${encodeURIComponent(auth.accountSid)}.json`, {\n headers: { authorization: basicAuth(auth) },\n signal: AbortSignal.timeout(8_000),\n })\n if (res.status === 401) return { ok: false, reason: 'Twilio rejected credentials (401) — reconnect required' }\n if (!res.ok) return { ok: false, reason: `Twilio returned ${res.status}` }\n return { ok: true }\n } catch (err) {\n return { ok: false, reason: err instanceof Error ? err.message : String(err) }\n }\n },\n}\n\ninterface TwilioAuth {\n accountSid: string\n /** Either the Account auth token, or an API key SID. */\n username: string\n /** Either the same auth token, or the API key secret. */\n password: string\n}\n\nfunction parseAuth(creds: { kind: string; apiKey?: string }): TwilioAuth {\n if (creds.kind !== 'api-key' || typeof creds.apiKey !== 'string') {\n throw new Error('twilio-sms: expected api-key credentials')\n }\n const parts = creds.apiKey.split(':')\n if (parts.length === 2) {\n // accountSid:authToken — username is the SID, password is the token.\n const [accountSid, authToken] = parts\n if (!accountSid.startsWith('AC')) {\n throw new Error('twilio-sms: AccountSid must start with \"AC\"')\n }\n return { accountSid, username: accountSid, password: authToken }\n }\n if (parts.length === 3) {\n // accountSid:apiKeySid:apiKeySecret — basic-auth username is the\n // API key SID, not the AccountSid.\n const [accountSid, keySid, secret] = parts\n if (!accountSid.startsWith('AC')) {\n throw new Error('twilio-sms: AccountSid must start with \"AC\"')\n }\n return { accountSid, username: keySid, password: secret }\n }\n throw new Error('twilio-sms: apiKey must be \"AccountSid:AuthToken\" or \"AccountSid:KeySid:Secret\"')\n}\n\nfunction basicAuth(auth: TwilioAuth): string {\n return `Basic ${Buffer.from(`${auth.username}:${auth.password}`).toString('base64')}`\n}\n\nfunction readMetaString(meta: Record<string, unknown>, key: string): string {\n const v = meta[key]\n if (typeof v !== 'string' || v.length === 0) {\n throw new Error(`twilio-sms DataSource.metadata.${key} is missing`)\n }\n return v\n}\n","/**\n * Stripe pack connector — single connector kind packing customer +\n * invoice + checkout + subscription management capabilities, validating\n * the \"connector pack\" concept (one auth handshake, multiple related\n * capabilities) without exploding the registry into `stripe-customers`,\n * `stripe-checkout`, `stripe-invoices`, `stripe-subscriptions` n-tuples.\n *\n * find_customer(email) → read; CAS n/a\n * list_subscriptions(customerId, status?) → read; CAS n/a\n * create_invoice(customerId, items) → mutation; cas: 'native-idempotency'\n * create_checkout_session(...) → mutation; cas: 'native-idempotency'\n * cancel_subscription(subscriptionId, atPeriodEnd?) → mutation; cas: 'native-idempotency'\n * create_billing_portal_session(customerId, returnUrl) → mutation; cas: 'native-idempotency'\n *\n * Auth: API key (Stripe restricted key). Operator pastes the key into\n * the Connections UI. We never see their account password / OAuth flow;\n * Stripe restricted keys are the customer's responsibility (they pick\n * which permissions the key carries). The kind exposes a webhook URL\n * post-connect for the operator to paste into the Stripe dashboard —\n * we'll wire the receiver to P-3's inbound webhook surface in a later\n * commit. That URL is returned in `metadata.webhookUrl` so the UI can\n * render it.\n *\n * Why this is the textbook example of `cas: 'native-idempotency'`:\n * Stripe's `Idempotency-Key` HTTP header is THE reference implementation\n * of native idempotency. Same key + same args within 24h returns the\n * stored response (Stripe's words, not ours). Same key + different args\n * → 400 with `idempotency_error`. We forward the SDK's idempotency key\n * directly. MutationGuard short-circuits before us on retry; Stripe's\n * own dedup is the second line of defense.\n */\n\nimport {\n type ConnectorAdapter,\n type ConnectorInvocation,\n type CapabilityReadResult,\n type CapabilityMutationResult,\n ResourceContention,\n CredentialsExpired,\n} from '../types.js'\n\nconst API = 'https://api.stripe.com/v1'\n\nexport const stripePackConnector: ConnectorAdapter = {\n manifest: {\n kind: 'stripe-pack',\n displayName: 'Stripe (customers, invoices, checkout, subscriptions)',\n description:\n \"Look up Stripe customers, draft invoices, spin up hosted Checkout sessions, manage subscriptions, and hand off to the customer billing portal — all from one Stripe restricted key. Idempotency-Key forwarded on every mutation.\",\n auth: {\n kind: 'api-key',\n hint: 'Paste a Stripe restricted key (rk_live_…) with read on customers + subscriptions and write on invoices + checkout + subscriptions + billing portal.',\n },\n category: 'commerce',\n defaultConsistencyModel: 'authoritative',\n capabilities: [\n {\n name: 'find_customer',\n class: 'read',\n description: 'Search Stripe customers by email. Returns the first match or {found:false}.',\n parameters: {\n type: 'object',\n properties: { email: { type: 'string' } },\n required: ['email'],\n },\n },\n {\n name: 'list_subscriptions',\n class: 'read',\n description: \"List a customer's subscriptions. Optionally filter by status ('active', 'past_due', 'canceled', 'all').\",\n parameters: {\n type: 'object',\n properties: {\n customerId: { type: 'string' },\n status: { type: 'string', enum: ['active', 'past_due', 'unpaid', 'canceled', 'incomplete', 'trialing', 'all'], default: 'all' },\n limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 },\n },\n required: ['customerId'],\n },\n },\n {\n name: 'create_invoice',\n class: 'mutation',\n description:\n 'Draft + finalize a Stripe invoice for a customer with line items. Idempotency-Key guarantees at-most-once.',\n cas: 'native-idempotency',\n externalEffect: true,\n parameters: {\n type: 'object',\n properties: {\n customerId: { type: 'string' },\n items: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n description: { type: 'string' },\n amount: { type: 'integer', description: 'Amount in the smallest currency unit (cents).' },\n currency: { type: 'string', description: '3-letter ISO currency code, lowercase.' },\n quantity: { type: 'integer', minimum: 1, default: 1 },\n },\n required: ['amount', 'currency'],\n },\n },\n autoFinalize: { type: 'boolean', default: true },\n },\n required: ['customerId', 'items'],\n },\n },\n {\n name: 'create_checkout_session',\n class: 'mutation',\n description:\n 'Create a Stripe Checkout session and return its hosted URL. Idempotency-Key guarantees at-most-once.',\n cas: 'native-idempotency',\n externalEffect: true,\n parameters: {\n type: 'object',\n properties: {\n customerId: { type: 'string' },\n mode: { type: 'string', enum: ['payment', 'subscription'], default: 'payment' },\n successUrl: { type: 'string' },\n cancelUrl: { type: 'string' },\n lineItems: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n price: { type: 'string', description: 'Stripe price id (price_...)' },\n quantity: { type: 'integer', minimum: 1, default: 1 },\n },\n required: ['price'],\n },\n },\n },\n required: ['successUrl', 'cancelUrl', 'lineItems'],\n },\n },\n {\n name: 'cancel_subscription',\n class: 'mutation',\n description:\n 'Cancel a subscription. Default cancels immediately; pass atPeriodEnd=true to schedule cancellation for the end of the current billing period.',\n cas: 'native-idempotency',\n externalEffect: true,\n parameters: {\n type: 'object',\n properties: {\n subscriptionId: { type: 'string' },\n atPeriodEnd: { type: 'boolean', default: false },\n },\n required: ['subscriptionId'],\n },\n },\n {\n name: 'create_billing_portal_session',\n class: 'mutation',\n description:\n 'Create a Stripe billing portal session and return its URL. Hand-off for the customer to self-serve cancel/upgrade/update-card.',\n cas: 'native-idempotency',\n externalEffect: true,\n parameters: {\n type: 'object',\n properties: {\n customerId: { type: 'string' },\n returnUrl: { type: 'string' },\n },\n required: ['customerId', 'returnUrl'],\n },\n },\n ],\n },\n\n async executeRead(inv: ConnectorInvocation): Promise<CapabilityReadResult> {\n const apiKey = readApiKey(inv.source.credentials)\n if (inv.capabilityName === 'list_subscriptions') return listSubscriptions(inv, apiKey)\n if (inv.capabilityName !== 'find_customer') {\n throw new Error(`stripe-pack: unknown read capability ${inv.capabilityName}`)\n }\n const { email } = inv.args as { email: string }\n // Stripe's /customers/search is the canonical email lookup. Falls\n // back to /customers?email= for accounts on legacy Search-disabled\n // tier — most accounts have Search enabled by default in 2024+.\n const url = `${API}/customers/search?query=${encodeURIComponent(`email:'${email.toLowerCase()}'`)}&limit=1`\n const res = await fetch(url, {\n headers: { authorization: `Bearer ${apiKey}` },\n signal: AbortSignal.timeout(10_000),\n })\n if (res.status === 401) {\n throw new CredentialsExpired('Stripe rejected API key (401)', inv.source.id)\n }\n if (!res.ok) {\n const text = await res.text().catch(() => '')\n throw new Error(`stripe-pack find_customer ${res.status}: ${text.slice(0, 200)}`)\n }\n const json = (await res.json()) as {\n data?: Array<{ id: string; email?: string; name?: string; phone?: string }>\n }\n const first = json.data?.[0]\n return {\n data: first\n ? { found: true, customer: { id: first.id, email: first.email, name: first.name, phone: first.phone } }\n : { found: false },\n fetchedAt: Date.now(),\n }\n },\n\n async executeMutation(inv: ConnectorInvocation): Promise<CapabilityMutationResult> {\n const apiKey = readApiKey(inv.source.credentials)\n if (inv.capabilityName === 'create_invoice') return createInvoice(inv, apiKey)\n if (inv.capabilityName === 'create_checkout_session') return createCheckoutSession(inv, apiKey)\n if (inv.capabilityName === 'cancel_subscription') return cancelSubscription(inv, apiKey)\n if (inv.capabilityName === 'create_billing_portal_session') return createBillingPortalSession(inv, apiKey)\n throw new Error(`stripe-pack: unknown mutation capability ${inv.capabilityName}`)\n },\n\n async test(source) {\n try {\n const apiKey = readApiKey(source.credentials)\n // /v1/account is the cheapest grant-validity probe.\n const res = await fetch(`${API}/account`, {\n headers: { authorization: `Bearer ${apiKey}` },\n signal: AbortSignal.timeout(8_000),\n })\n if (res.status === 401) {\n return { ok: false, reason: 'Stripe rejected API key (401) — reconnect required' }\n }\n if (!res.ok) return { ok: false, reason: `Stripe returned ${res.status}` }\n return { ok: true }\n } catch (err) {\n return { ok: false, reason: err instanceof Error ? err.message : String(err) }\n }\n },\n}\n\nasync function createInvoice(inv: ConnectorInvocation, apiKey: string): Promise<CapabilityMutationResult> {\n const { customerId, items, autoFinalize } = inv.args as {\n customerId: string\n items: Array<{ description?: string; amount: number; currency: string; quantity?: number }>\n autoFinalize?: boolean\n }\n // Stripe requires invoiceitem.create BEFORE invoice.create. We do\n // both under the same idempotency-key prefix so retries are exactly\n // replayed across both calls.\n const idemKey = inv.idempotencyKey\n for (let i = 0; i < items.length; i++) {\n const it = items[i]\n const body = new URLSearchParams({\n customer: customerId,\n amount: String(it.amount),\n currency: it.currency.toLowerCase(),\n quantity: String(it.quantity ?? 1),\n })\n if (it.description) body.set('description', it.description)\n const res = await fetch(`${API}/invoiceitems`, {\n method: 'POST',\n headers: {\n authorization: `Bearer ${apiKey}`,\n 'content-type': 'application/x-www-form-urlencoded',\n 'idempotency-key': `${idemKey}-item-${i}`,\n },\n body,\n signal: AbortSignal.timeout(15_000),\n })\n if (res.status === 401) throw new CredentialsExpired('Stripe rejected API key (401)', inv.source.id)\n if (res.status === 409) {\n throw new ResourceContention('Stripe invoiceitem conflict — retry rejected by idempotency check')\n }\n if (!res.ok) {\n const text = await res.text().catch(() => '')\n throw new Error(`stripe-pack create_invoice (item ${i}) ${res.status}: ${text.slice(0, 200)}`)\n }\n }\n\n const invBody = new URLSearchParams({\n customer: customerId,\n auto_advance: autoFinalize === false ? 'false' : 'true',\n collection_method: 'send_invoice',\n days_until_due: '14',\n })\n const invRes = await fetch(`${API}/invoices`, {\n method: 'POST',\n headers: {\n authorization: `Bearer ${apiKey}`,\n 'content-type': 'application/x-www-form-urlencoded',\n 'idempotency-key': `${idemKey}-invoice`,\n },\n body: invBody,\n signal: AbortSignal.timeout(15_000),\n })\n if (invRes.status === 401) throw new CredentialsExpired('Stripe rejected API key (401)', inv.source.id)\n if (invRes.status === 409) {\n throw new ResourceContention('Stripe invoice conflict — retry rejected by idempotency check')\n }\n if (!invRes.ok) {\n const text = await invRes.text().catch(() => '')\n throw new Error(`stripe-pack create_invoice ${invRes.status}: ${text.slice(0, 200)}`)\n }\n const created = (await invRes.json()) as { id: string; hosted_invoice_url?: string; status?: string }\n return {\n status: 'committed',\n data: { invoiceId: created.id, hostedInvoiceUrl: created.hosted_invoice_url, status: created.status },\n committedAt: Date.now(),\n idempotentReplay: false,\n }\n}\n\nasync function createCheckoutSession(\n inv: ConnectorInvocation,\n apiKey: string,\n): Promise<CapabilityMutationResult> {\n const { customerId, mode, successUrl, cancelUrl, lineItems } = inv.args as {\n customerId?: string\n mode?: 'payment' | 'subscription'\n successUrl: string\n cancelUrl: string\n lineItems: Array<{ price: string; quantity?: number }>\n }\n const body = new URLSearchParams({\n mode: mode ?? 'payment',\n success_url: successUrl,\n cancel_url: cancelUrl,\n })\n if (customerId) body.set('customer', customerId)\n lineItems.forEach((it, i) => {\n body.set(`line_items[${i}][price]`, it.price)\n body.set(`line_items[${i}][quantity]`, String(it.quantity ?? 1))\n })\n const res = await fetch(`${API}/checkout/sessions`, {\n method: 'POST',\n headers: {\n authorization: `Bearer ${apiKey}`,\n 'content-type': 'application/x-www-form-urlencoded',\n 'idempotency-key': inv.idempotencyKey,\n },\n body,\n signal: AbortSignal.timeout(15_000),\n })\n if (res.status === 401) throw new CredentialsExpired('Stripe rejected API key (401)', inv.source.id)\n if (res.status === 409) {\n throw new ResourceContention('Stripe checkout session conflict — retry rejected by idempotency check')\n }\n if (!res.ok) {\n const text = await res.text().catch(() => '')\n throw new Error(`stripe-pack create_checkout_session ${res.status}: ${text.slice(0, 200)}`)\n }\n const created = (await res.json()) as { id: string; url?: string; payment_status?: string }\n return {\n status: 'committed',\n data: { sessionId: created.id, url: created.url, paymentStatus: created.payment_status },\n committedAt: Date.now(),\n idempotentReplay: false,\n }\n}\n\nasync function listSubscriptions(inv: ConnectorInvocation, apiKey: string): Promise<CapabilityReadResult> {\n const { customerId, status, limit } = inv.args as { customerId: string; status?: string; limit?: number }\n const params = new URLSearchParams({ customer: customerId, limit: String(limit ?? 10) })\n if (status && status !== 'all') params.set('status', status)\n else params.set('status', 'all')\n const res = await fetch(`${API}/subscriptions?${params.toString()}`, {\n headers: { authorization: `Bearer ${apiKey}` },\n signal: AbortSignal.timeout(10_000),\n })\n if (res.status === 401) {\n throw new CredentialsExpired('Stripe rejected API key (401)', inv.source.id)\n }\n if (!res.ok) {\n const text = await res.text().catch(() => '')\n throw new Error(`stripe-pack list_subscriptions ${res.status}: ${text.slice(0, 200)}`)\n }\n const json = (await res.json()) as {\n data?: Array<{\n id: string\n status: string\n current_period_end?: number\n cancel_at_period_end?: boolean\n items?: { data?: Array<{ price?: { id: string; product?: string; unit_amount?: number; currency?: string; recurring?: { interval?: string } } }> }\n }>\n }\n const subscriptions = (json.data ?? []).map((sub) => ({\n id: sub.id,\n status: sub.status,\n currentPeriodEnd: sub.current_period_end,\n cancelAtPeriodEnd: sub.cancel_at_period_end ?? false,\n items: (sub.items?.data ?? []).map((it) => ({\n priceId: it.price?.id,\n productId: it.price?.product,\n unitAmount: it.price?.unit_amount,\n currency: it.price?.currency,\n interval: it.price?.recurring?.interval,\n })),\n }))\n return {\n data: { subscriptions },\n fetchedAt: Date.now(),\n }\n}\n\nasync function cancelSubscription(inv: ConnectorInvocation, apiKey: string): Promise<CapabilityMutationResult> {\n const { subscriptionId, atPeriodEnd } = inv.args as { subscriptionId: string; atPeriodEnd?: boolean }\n let res: Response\n if (atPeriodEnd) {\n // Update the subscription to mark cancel_at_period_end=true. The\n // subscription stays active until the end of the current billing\n // period and Stripe automatically cancels at that time.\n const body = new URLSearchParams({ cancel_at_period_end: 'true' })\n res = await fetch(`${API}/subscriptions/${encodeURIComponent(subscriptionId)}`, {\n method: 'POST',\n headers: {\n authorization: `Bearer ${apiKey}`,\n 'content-type': 'application/x-www-form-urlencoded',\n 'idempotency-key': inv.idempotencyKey,\n },\n body,\n signal: AbortSignal.timeout(15_000),\n })\n } else {\n res = await fetch(`${API}/subscriptions/${encodeURIComponent(subscriptionId)}`, {\n method: 'DELETE',\n headers: {\n authorization: `Bearer ${apiKey}`,\n 'idempotency-key': inv.idempotencyKey,\n },\n signal: AbortSignal.timeout(15_000),\n })\n }\n if (res.status === 401) throw new CredentialsExpired('Stripe rejected API key (401)', inv.source.id)\n if (res.status === 404) throw new Error(`stripe-pack cancel_subscription: subscription ${subscriptionId} not found`)\n if (res.status === 409) {\n throw new ResourceContention('Stripe subscription conflict — retry rejected by idempotency check')\n }\n if (!res.ok) {\n const text = await res.text().catch(() => '')\n throw new Error(`stripe-pack cancel_subscription ${res.status}: ${text.slice(0, 200)}`)\n }\n const updated = (await res.json()) as { id: string; status: string; cancel_at_period_end?: boolean; canceled_at?: number; current_period_end?: number }\n return {\n status: 'committed',\n data: {\n id: updated.id,\n status: updated.status,\n cancelAtPeriodEnd: updated.cancel_at_period_end ?? false,\n canceledAt: updated.canceled_at,\n currentPeriodEnd: updated.current_period_end,\n },\n committedAt: Date.now(),\n idempotentReplay: false,\n }\n}\n\nasync function createBillingPortalSession(inv: ConnectorInvocation, apiKey: string): Promise<CapabilityMutationResult> {\n const { customerId, returnUrl } = inv.args as { customerId: string; returnUrl: string }\n const body = new URLSearchParams({ customer: customerId, return_url: returnUrl })\n const res = await fetch(`${API}/billing_portal/sessions`, {\n method: 'POST',\n headers: {\n authorization: `Bearer ${apiKey}`,\n 'content-type': 'application/x-www-form-urlencoded',\n 'idempotency-key': inv.idempotencyKey,\n },\n body,\n signal: AbortSignal.timeout(15_000),\n })\n if (res.status === 401) throw new CredentialsExpired('Stripe rejected API key (401)', inv.source.id)\n if (res.status === 409) {\n throw new ResourceContention('Stripe billing portal session conflict — retry rejected by idempotency check')\n }\n if (!res.ok) {\n const text = await res.text().catch(() => '')\n throw new Error(`stripe-pack create_billing_portal_session ${res.status}: ${text.slice(0, 200)}`)\n }\n const created = (await res.json()) as { id: string; url: string; return_url?: string }\n return {\n status: 'committed',\n data: { sessionId: created.id, url: created.url, returnUrl: created.return_url },\n committedAt: Date.now(),\n idempotentReplay: false,\n }\n}\n\nfunction readApiKey(creds: { kind: string; apiKey?: string }): string {\n if (creds.kind !== 'api-key' || typeof creds.apiKey !== 'string' || creds.apiKey.length === 0) {\n throw new Error('stripe-pack: expected api-key credentials')\n }\n return creds.apiKey\n}\n","/**\n * Universal webhook connector — the long-tail escape hatch.\n *\n * The user declares a target URL + a JSON-schema for the request body\n * the agent should send, plus an optional shared secret. We sign every\n * outbound POST with HMAC-SHA256 over `timestamp.body` and forward the\n * agent's idempotency key as a header. The receiving system enforces\n * its own idempotency.\n *\n * One adapter, two capabilities. Both arity-1 — `body` is whatever JSON\n * the agent's planner constructs from the operator-defined schema (which\n * lives in DataSource.metadata.requestSchema). The agent's planner reads\n * that schema at request time and constructs valid args.\n *\n * Why one connector covers 50 systems badly and 1 system well: the agent\n * gets a generic \"send_event\" tool that doesn't *know* what the upstream\n * does with the payload. That's fine for fire-and-forget event posting\n * (Zapier-style); it's wrong for booking against a calendar where you\n * need conflict-resolution. So webhook's `post_event` capability is\n * marked `cas: 'native-idempotency'` (we forward the key — the receiver\n * MUST honor it) and `defaultConsistencyModel: 'advisory'`. Anyone\n * needing real CAS uses a kind-specific connector (Calendar, Sheets, ...).\n */\n\nimport { createHmac } from 'crypto'\nimport {\n type ConnectorAdapter,\n type ConnectorInvocation,\n type CapabilityReadResult,\n type CapabilityMutationResult,\n} from '../types.js'\n\nexport const webhookConnector: ConnectorAdapter = {\n manifest: {\n kind: 'webhook',\n displayName: 'Webhook (custom URL)',\n description:\n \"Fire signed HTTP POSTs from your agent to any URL you control. The escape hatch when there's no native connector — receive the agent's intent, run your own logic, return a result.\",\n auth: { kind: 'hmac' },\n category: 'webhook',\n defaultConsistencyModel: 'advisory',\n capabilities: [\n {\n name: 'post_event',\n class: 'mutation',\n description:\n 'Send a JSON event to the configured webhook URL. The receiver SHOULD return 200 on accept and 409 on conflict (the agent will offer alternatives if you include them in the response).',\n cas: 'native-idempotency',\n externalEffect: true,\n parameters: {\n type: 'object',\n additionalProperties: true,\n description: 'Whatever JSON the operator declared at connect time. The DataSource.metadata.requestSchema is the source of truth at runtime.',\n },\n },\n {\n name: 'fetch_state',\n class: 'read',\n description: 'GET the configured webhook URL with the agent-supplied query params. Returns whatever JSON the receiver responds with.',\n parameters: {\n type: 'object',\n additionalProperties: true,\n },\n },\n ],\n },\n\n async executeRead(inv: ConnectorInvocation): Promise<CapabilityReadResult> {\n const url = readMetaString(inv.source.metadata, 'url')\n const params = inv.args && typeof inv.args === 'object' ? inv.args : {}\n const u = new URL(url)\n for (const [k, v] of Object.entries(params)) {\n u.searchParams.set(k, typeof v === 'string' ? v : JSON.stringify(v))\n }\n const res = await fetch(u.toString(), {\n method: 'GET',\n headers: signHeaders(inv.source.credentials, '', inv.idempotencyKey),\n signal: AbortSignal.timeout(15_000),\n })\n if (!res.ok) {\n throw new Error(`webhook fetch_state ${res.status}: ${(await res.text()).slice(0, 200)}`)\n }\n const data = (await res.json()) as unknown\n return {\n data,\n etag: res.headers.get('etag') ?? undefined,\n fetchedAt: Date.now(),\n }\n },\n\n async executeMutation(inv: ConnectorInvocation): Promise<CapabilityMutationResult> {\n const url = readMetaString(inv.source.metadata, 'url')\n const body = JSON.stringify(inv.args ?? {})\n const res = await fetch(url, {\n method: 'POST',\n headers: signHeaders(inv.source.credentials, body, inv.idempotencyKey),\n body,\n signal: AbortSignal.timeout(15_000),\n })\n if (res.status === 409) {\n // Conflict by convention — receiver returns alternatives in the body.\n const json = (await res.json().catch(() => ({}))) as { alternatives?: unknown[]; message?: string }\n return {\n status: 'conflict',\n alternatives: json.alternatives ?? [],\n message: json.message ?? 'webhook receiver returned 409',\n }\n }\n if (!res.ok) {\n throw new Error(`webhook post_event ${res.status}: ${(await res.text()).slice(0, 200)}`)\n }\n const data = (await res.json().catch(() => ({}))) as unknown\n return {\n status: 'committed',\n data,\n etagAfter: res.headers.get('etag') ?? undefined,\n committedAt: Date.now(),\n idempotentReplay: false,\n }\n },\n\n async test(source) {\n try {\n const url = readMetaString(source.metadata, 'url')\n // HEAD if the receiver supports it, otherwise GET. Either way a\n // non-5xx response counts as healthy — we don't validate semantics.\n const res = await fetch(url, {\n method: 'HEAD',\n headers: signHeaders(source.credentials, '', `health-${Date.now()}`),\n signal: AbortSignal.timeout(8_000),\n })\n if (res.status >= 500) return { ok: false, reason: `webhook returned ${res.status}` }\n return { ok: true }\n } catch (err) {\n return { ok: false, reason: err instanceof Error ? err.message : String(err) }\n }\n },\n}\n\nfunction readMetaString(meta: Record<string, unknown>, key: string): string {\n const v = meta[key]\n if (typeof v !== 'string' || v.length === 0) {\n throw new Error(`webhook DataSource.metadata.${key} is missing`)\n }\n return v\n}\n\nfunction signHeaders(\n creds: { kind: string; secret?: string; [k: string]: unknown },\n body: string,\n idempotencyKey: string,\n): Record<string, string> {\n const ts = Math.floor(Date.now() / 1000).toString()\n const headers: Record<string, string> = {\n 'content-type': 'application/json',\n 'x-phony-timestamp': ts,\n 'x-phony-idempotency-key': idempotencyKey,\n }\n if (creds.kind === 'hmac' && typeof creds.secret === 'string' && creds.secret.length > 0) {\n const sig = createHmac('sha256', creds.secret).update(`${ts}.${body}`).digest('hex')\n headers['x-phony-signature'] = `sha256=${sig}`\n }\n return headers\n}\n","/**\n * Stripe inbound-webhook receiver — push-only side of a Stripe connector.\n *\n * The full Stripe connector (charges/customers/invoices read+mutation) is\n * tracked in INTEGRATIONS.md as separate `stripe-customers` / `stripe-invoices`\n * rows. This adapter only ships the inbound surface today: receive a push,\n * verify the signature, persist one `InboundEvent` per Stripe event so the\n * agent's runtime can react (e.g. payment_failed → outbound dunning call).\n *\n * This connector is for the connected account owner: they paste their\n * `whsec_*` and the consuming product listens on a per-data-source URL such\n * as /api/webhooks/inbound/stripe/:dataSourceId.\n *\n * Signature scheme: Stripe's `t=<unix>,v1=<hmac>` header. HMAC is\n * sha256(`${t}.${rawBody}`) keyed by the customer's webhook secret. We use\n * `timingSafeEqual` to defeat timing oracles and bound timestamp skew at\n * 5 minutes (Stripe's recommendation) to thwart replay against captured\n * signatures.\n */\n\nimport {\n type ConnectorAdapter,\n type EventHandlerResult,\n type InboundEvent,\n} from '../types.js'\nimport { firstHeader, verifyStripeSignature } from '../webhooks.js'\n\nexport const stripeWebhookReceiverConnector: ConnectorAdapter = {\n manifest: {\n kind: 'stripe',\n displayName: 'Stripe (inbound events)',\n description:\n \"Receive Stripe webhook events from your own Stripe account. Paste your endpoint signing secret (whsec_*) at connect time; we'll verify every push and feed events to your agent's runtime.\",\n auth: { kind: 'hmac' },\n category: 'commerce',\n // Inbound-only. Stripe events are advisory in this incarnation — the\n // agent reacts to them but doesn't compete for writes against the same\n // resource.\n defaultConsistencyModel: 'advisory',\n capabilities: [],\n },\n\n verifySignature({ rawBody, headers, source }) {\n if (source.credentials.kind !== 'hmac') return { valid: false, reason: 'missing_hmac_secret' }\n const sig = firstHeader(headers, 'stripe-signature')\n if (!sig) return { valid: false, reason: 'missing_stripe_signature_header' }\n const ok = verifyStripeSignature(rawBody, sig, source.credentials.secret)\n return ok ? { valid: true } : { valid: false, reason: 'invalid_signature' }\n },\n\n async handleInboundEvent({ rawBody }): Promise<EventHandlerResult> {\n let parsed: unknown\n try {\n parsed = JSON.parse(rawBody)\n } catch {\n return { events: [], response: { status: 400, body: { error: 'invalid_json' } } }\n }\n if (!parsed || typeof parsed !== 'object') {\n return { events: [], response: { status: 400, body: { error: 'invalid_payload' } } }\n }\n const evt = parsed as { id?: unknown; type?: unknown; data?: unknown; created?: unknown }\n const eventType = typeof evt.type === 'string' ? evt.type : 'stripe.unknown'\n const providerEventId = typeof evt.id === 'string' ? evt.id : undefined\n const events: InboundEvent[] = [\n {\n eventType,\n providerEventId,\n payload: evt as Record<string, unknown>,\n },\n ]\n return { events }\n },\n\n async test(source) {\n if (source.credentials.kind !== 'hmac' || !source.credentials.secret) {\n return { ok: false, reason: 'webhook secret not configured' }\n }\n return { ok: true }\n },\n}\n","/**\n * Slack Events API inbound receiver.\n *\n * Slack sends two distinct request shapes to the same webhook URL:\n *\n * 1. `url_verification` — a one-off handshake during app-config. The body\n * contains a `challenge` string we MUST echo back as the response body\n * (Slack's app-config UI fails the URL otherwise). No InboundEvent is\n * persisted for this — it's an infrastructure ping, not a user event.\n *\n * 2. `event_callback` — every actual workspace event (message posted,\n * reaction added, channel created, …). We persist one InboundEvent\n * keyed by `event_id` so a Slack retry (Slack retries 3 times on any\n * non-2xx) is deduped at the unique constraint, not after we've\n * double-processed.\n *\n * Signature scheme: `v0=<hmac(sha256, \"v0:<timestamp>:<rawBody>\")>` keyed by\n * the app's signing secret. Header `X-Slack-Request-Timestamp` carries the\n * timestamp; we reject anything older than 5 minutes (Slack's recommendation)\n * to bound replay risk.\n */\n\nimport {\n type ConnectorAdapter,\n type EventHandlerResult,\n type InboundEvent,\n} from '../types.js'\nimport { firstHeader, verifySlackSignature } from '../webhooks.js'\n\nexport const slackEventsConnector: ConnectorAdapter = {\n manifest: {\n // NOTE: `slack` is owned by the OAuth bot connector in slack.ts (post_message,\n // lookup_user, list_channels). This adapter is the HMAC-only inbound-events\n // sibling — distinct kind so a customer can stand up the Events API receiver\n // without granting bot OAuth, and so the registry doesn't reject duplicate\n // kinds at boot.\n kind: 'slack-inbound',\n displayName: 'Slack (Events API)',\n description:\n \"Receive workspace events (messages, reactions, app mentions, …) from Slack's Events API. Outbound bot messaging will land in a follow-up.\",\n auth: { kind: 'hmac' },\n category: 'comms',\n // Inbound-only. Events are advisory in this incarnation — agents observe\n // and react, no CAS.\n defaultConsistencyModel: 'advisory',\n capabilities: [],\n },\n\n verifySignature({ rawBody, headers, source }) {\n if (source.credentials.kind !== 'hmac') return { valid: false, reason: 'missing_hmac_secret' }\n const sig = firstHeader(headers, 'x-slack-signature')\n const ts = firstHeader(headers, 'x-slack-request-timestamp')\n if (!sig || !ts) return { valid: false, reason: 'missing_slack_headers' }\n const ok = verifySlackSignature(rawBody, sig, ts, source.credentials.secret)\n return ok ? { valid: true } : { valid: false, reason: 'invalid_signature' }\n },\n\n async handleInboundEvent({ rawBody }): Promise<EventHandlerResult> {\n let parsed: unknown\n try {\n parsed = JSON.parse(rawBody)\n } catch {\n return { events: [], response: { status: 400, body: { error: 'invalid_json' } } }\n }\n if (!parsed || typeof parsed !== 'object') {\n return { events: [], response: { status: 400, body: { error: 'invalid_payload' } } }\n }\n const obj = parsed as Record<string, unknown>\n\n // Handshake: echo the challenge. No event persisted.\n if (obj.type === 'url_verification') {\n const challenge = typeof obj.challenge === 'string' ? obj.challenge : ''\n return {\n events: [],\n response: { status: 200, body: { challenge } },\n }\n }\n\n // Workspace event: persist one row keyed by Slack's event_id.\n if (obj.type === 'event_callback') {\n const inner = obj.event\n const innerType =\n inner && typeof inner === 'object' && 'type' in inner && typeof (inner as { type?: unknown }).type === 'string'\n ? (inner as { type: string }).type\n : 'slack.event'\n const providerEventId = typeof obj.event_id === 'string' ? obj.event_id : undefined\n const event: InboundEvent = {\n eventType: `slack.${innerType}`,\n providerEventId,\n payload: obj,\n }\n return { events: [event] }\n }\n\n // Unknown envelope (Slack adds new top-level types occasionally) — ack\n // so Slack stops retrying, but don't persist a malformed row.\n return { events: [] }\n },\n\n async test(source) {\n if (source.credentials.kind !== 'hmac' || !source.credentials.secret) {\n return { ok: false, reason: 'signing secret not configured' }\n }\n return { ok: true }\n },\n}\n","import { declarativeRestConnector } from './declarative-rest.js'\n\nconst repoParams = {\n type: 'object',\n properties: {\n owner: { type: 'string' },\n repo: { type: 'string' },\n },\n required: ['owner', 'repo'],\n}\n\nexport const githubConnector = declarativeRestConnector({\n kind: 'github',\n displayName: 'GitHub',\n description: 'Search repositories/issues and create or update GitHub issues through a user-scoped token.',\n auth: { kind: 'api-key', hint: 'GitHub fine-grained personal access token or installation token.' },\n category: 'other',\n defaultConsistencyModel: 'authoritative',\n baseUrl: 'https://api.github.com',\n defaultHeaders: {\n 'x-github-api-version': '2022-11-28',\n },\n test: { method: 'GET', path: '/user' },\n capabilities: [\n {\n name: 'repositories.get',\n class: 'read',\n description: 'Read repository metadata.',\n parameters: repoParams,\n request: { method: 'GET', path: '/repos/{owner}/{repo}' },\n },\n {\n name: 'issues.search',\n class: 'read',\n description: 'Search GitHub issues and pull requests.',\n parameters: {\n type: 'object',\n properties: { q: { type: 'string' }, per_page: { type: 'integer', minimum: 1, maximum: 100 } },\n required: ['q'],\n },\n request: { method: 'GET', path: '/search/issues', query: { q: '{q}', per_page: '{per_page}' } },\n },\n {\n name: 'issues.create',\n class: 'mutation',\n description: 'Create an issue in a repository.',\n parameters: {\n type: 'object',\n properties: {\n owner: { type: 'string' },\n repo: { type: 'string' },\n title: { type: 'string' },\n body: { type: 'string' },\n labels: { type: 'array', items: { type: 'string' } },\n },\n required: ['owner', 'repo', 'title'],\n },\n request: { method: 'POST', path: '/repos/{owner}/{repo}/issues', body: 'args' },\n cas: 'native-idempotency',\n },\n {\n name: 'issues.update',\n class: 'mutation',\n description: 'Update an issue by number.',\n parameters: {\n type: 'object',\n properties: {\n owner: { type: 'string' },\n repo: { type: 'string' },\n issue_number: { type: 'integer' },\n title: { type: 'string' },\n body: { type: 'string' },\n state: { type: 'string', enum: ['open', 'closed'] },\n },\n required: ['owner', 'repo', 'issue_number'],\n },\n request: { method: 'PATCH', path: '/repos/{owner}/{repo}/issues/{issue_number}', body: 'args' },\n cas: 'etag-if-match',\n },\n ],\n})\n","import { declarativeRestConnector } from './declarative-rest.js'\n\nexport const gitlabConnector = declarativeRestConnector({\n kind: 'gitlab',\n displayName: 'GitLab',\n description: 'Search GitLab projects/issues and create or update issues through a personal, project, or group token.',\n auth: { kind: 'api-key', hint: 'GitLab access token with api/read_api scope.' },\n category: 'other',\n defaultConsistencyModel: 'authoritative',\n baseUrl: { metadataKey: 'baseUrl', fallback: 'https://gitlab.com/api/v4' },\n credentialPlacement: { kind: 'header', header: 'PRIVATE-TOKEN' },\n test: { method: 'GET', path: '/user' },\n capabilities: [\n {\n name: 'projects.search',\n class: 'read',\n description: 'Search projects visible to the token.',\n parameters: {\n type: 'object',\n properties: { search: { type: 'string' }, per_page: { type: 'integer', minimum: 1, maximum: 100 } },\n required: ['search'],\n },\n request: { method: 'GET', path: '/projects', query: { search: '{search}', per_page: '{per_page}' } },\n },\n {\n name: 'issues.search',\n class: 'read',\n description: 'Search issues in a project.',\n parameters: {\n type: 'object',\n properties: { projectId: { type: 'string' }, search: { type: 'string' }, per_page: { type: 'integer' } },\n required: ['projectId', 'search'],\n },\n request: { method: 'GET', path: '/projects/{projectId}/issues', query: { search: '{search}', per_page: '{per_page}' } },\n },\n {\n name: 'issues.create',\n class: 'mutation',\n description: 'Create a GitLab project issue.',\n parameters: {\n type: 'object',\n properties: { projectId: { type: 'string' }, title: { type: 'string' }, description: { type: 'string' } },\n required: ['projectId', 'title'],\n },\n request: { method: 'POST', path: '/projects/{projectId}/issues', body: 'args' },\n cas: 'native-idempotency',\n },\n {\n name: 'issues.update',\n class: 'mutation',\n description: 'Update a GitLab issue.',\n parameters: {\n type: 'object',\n properties: { projectId: { type: 'string' }, issueIid: { type: 'integer' }, title: { type: 'string' }, description: { type: 'string' }, state_event: { type: 'string' } },\n required: ['projectId', 'issueIid'],\n },\n request: { method: 'PUT', path: '/projects/{projectId}/issues/{issueIid}', body: 'args' },\n cas: 'etag-if-match',\n },\n ],\n})\n","import { declarativeRestConnector } from './declarative-rest.js'\n\nconst baseTableParams = {\n type: 'object',\n properties: {\n baseId: { type: 'string' },\n tableName: { type: 'string' },\n },\n required: ['baseId', 'tableName'],\n}\n\nexport const airtableConnector = declarativeRestConnector({\n kind: 'airtable',\n displayName: 'Airtable',\n description: 'Query and update Airtable records for lightweight operational databases.',\n auth: { kind: 'api-key', hint: 'Airtable personal access token.' },\n category: 'spreadsheet',\n defaultConsistencyModel: 'authoritative',\n baseUrl: 'https://api.airtable.com',\n test: { method: 'GET', path: '/v0/meta/whoami' },\n capabilities: [\n {\n name: 'records.list',\n class: 'read',\n description: 'List records in a table.',\n parameters: {\n ...baseTableParams,\n properties: {\n ...baseTableParams.properties,\n maxRecords: { type: 'integer', minimum: 1, maximum: 100 },\n filterByFormula: { type: 'string' },\n },\n },\n request: { method: 'GET', path: '/v0/{baseId}/{tableName}', query: { maxRecords: '{maxRecords}', filterByFormula: '{filterByFormula}' } },\n },\n {\n name: 'records.get',\n class: 'read',\n description: 'Read a single Airtable record.',\n parameters: {\n type: 'object',\n properties: { baseId: { type: 'string' }, tableName: { type: 'string' }, recordId: { type: 'string' } },\n required: ['baseId', 'tableName', 'recordId'],\n },\n request: { method: 'GET', path: '/v0/{baseId}/{tableName}/{recordId}' },\n },\n {\n name: 'records.create',\n class: 'mutation',\n description: 'Create an Airtable record.',\n parameters: {\n type: 'object',\n properties: { baseId: { type: 'string' }, tableName: { type: 'string' }, fields: { type: 'object' } },\n required: ['baseId', 'tableName', 'fields'],\n },\n request: { method: 'POST', path: '/v0/{baseId}/{tableName}', body: { fields: '{fields}' } },\n cas: 'native-idempotency',\n },\n {\n name: 'records.update',\n class: 'mutation',\n description: 'Update an Airtable record.',\n parameters: {\n type: 'object',\n properties: { baseId: { type: 'string' }, tableName: { type: 'string' }, recordId: { type: 'string' }, fields: { type: 'object' } },\n required: ['baseId', 'tableName', 'recordId', 'fields'],\n },\n request: { method: 'PATCH', path: '/v0/{baseId}/{tableName}/{recordId}', body: { fields: '{fields}' } },\n cas: 'optimistic-read-verify',\n },\n ],\n})\n","import { declarativeRestConnector } from './declarative-rest.js'\n\nexport const asanaConnector = declarativeRestConnector({\n kind: 'asana',\n displayName: 'Asana',\n description: 'Search projects/tasks and create or update Asana tasks.',\n auth: { kind: 'api-key', hint: 'Asana personal access token.' },\n category: 'other',\n defaultConsistencyModel: 'authoritative',\n baseUrl: 'https://app.asana.com/api/1.0',\n test: { method: 'GET', path: '/users/me' },\n capabilities: [\n {\n name: 'projects.search',\n class: 'read',\n description: 'List or search projects in a workspace.',\n parameters: {\n type: 'object',\n properties: { workspace: { type: 'string' }, archived: { type: 'boolean' }, limit: { type: 'integer' } },\n required: ['workspace'],\n },\n request: { method: 'GET', path: '/projects', query: { workspace: '{workspace}', archived: '{archived}', limit: '{limit}' } },\n },\n {\n name: 'tasks.search',\n class: 'read',\n description: 'Search tasks in a workspace.',\n parameters: {\n type: 'object',\n properties: { workspace: { type: 'string' }, text: { type: 'string' }, limit: { type: 'integer' } },\n required: ['workspace'],\n },\n request: { method: 'GET', path: '/workspaces/{workspace}/tasks/search', query: { text: '{text}', limit: '{limit}' } },\n },\n {\n name: 'tasks.create',\n class: 'mutation',\n description: 'Create an Asana task.',\n parameters: {\n type: 'object',\n properties: { data: { type: 'object' } },\n required: ['data'],\n },\n request: { method: 'POST', path: '/tasks', body: { data: '{data}' } },\n cas: 'native-idempotency',\n },\n {\n name: 'tasks.update',\n class: 'mutation',\n description: 'Update an Asana task.',\n parameters: {\n type: 'object',\n properties: { taskGid: { type: 'string' }, data: { type: 'object' } },\n required: ['taskGid', 'data'],\n },\n request: { method: 'PUT', path: '/tasks/{taskGid}', body: { data: '{data}' } },\n cas: 'optimistic-read-verify',\n },\n ],\n})\n","import { declarativeRestConnector } from './declarative-rest.js'\n\nexport const salesforceConnector = declarativeRestConnector({\n kind: 'salesforce',\n displayName: 'Salesforce',\n description: 'Query Salesforce records with SOQL and create or update sObjects.',\n auth: {\n kind: 'oauth2',\n authorizationUrl: 'https://login.salesforce.com/services/oauth2/authorize',\n tokenUrl: 'https://login.salesforce.com/services/oauth2/token',\n scopes: ['api', 'refresh_token'],\n clientIdEnv: 'SALESFORCE_OAUTH_CLIENT_ID',\n clientSecretEnv: 'SALESFORCE_OAUTH_CLIENT_SECRET',\n },\n category: 'crm',\n defaultConsistencyModel: 'authoritative',\n baseUrl: { metadataKey: 'instanceUrl' },\n test: { method: 'GET', path: '/services/data/v61.0/' },\n capabilities: [\n {\n name: 'records.query',\n class: 'read',\n description: 'Run a SOQL query.',\n parameters: {\n type: 'object',\n properties: { q: { type: 'string' } },\n required: ['q'],\n },\n request: { method: 'GET', path: '/services/data/v61.0/query', query: { q: '{q}' } },\n requiredScopes: ['api'],\n },\n {\n name: 'records.get',\n class: 'read',\n description: 'Read a Salesforce sObject record.',\n parameters: {\n type: 'object',\n properties: { objectName: { type: 'string' }, recordId: { type: 'string' } },\n required: ['objectName', 'recordId'],\n },\n request: { method: 'GET', path: '/services/data/v61.0/sobjects/{objectName}/{recordId}' },\n requiredScopes: ['api'],\n },\n {\n name: 'records.create',\n class: 'mutation',\n description: 'Create a Salesforce sObject record.',\n parameters: {\n type: 'object',\n properties: { objectName: { type: 'string' }, fields: { type: 'object' } },\n required: ['objectName', 'fields'],\n },\n request: { method: 'POST', path: '/services/data/v61.0/sobjects/{objectName}', body: '{fields}' },\n cas: 'native-idempotency',\n requiredScopes: ['api'],\n },\n {\n name: 'records.update',\n class: 'mutation',\n description: 'Update a Salesforce sObject record.',\n parameters: {\n type: 'object',\n properties: { objectName: { type: 'string' }, recordId: { type: 'string' }, fields: { type: 'object' } },\n required: ['objectName', 'recordId', 'fields'],\n },\n request: { method: 'PATCH', path: '/services/data/v61.0/sobjects/{objectName}/{recordId}', body: '{fields}' },\n cas: 'etag-if-match',\n requiredScopes: ['api'],\n },\n ],\n})\n"],"mappings":"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","names":["AUTH_URL","TOKEN_URL","ensureFreshAccessToken","res","isTextLike","buf","createHash","SCOPES","AUTH_URL","TOKEN_URL","ensureFreshAccessToken","createHash","AUTH_URL","TOKEN_URL","API","ensureFreshAccessToken","SCOPES","AUTH_URL","TOKEN_URL","readMetaString","ensureFreshAccessToken","findNextFreeSlots","SCOPES","AUTH_URL","TOKEN_URL","API","ensureFreshAccessToken","SCOPES","AUTH_URL","TOKEN_URL","API","AUTH_URL","TOKEN_URL","API","readMetaString","API","readMetaString","API","createHmac","readMetaString"]}