@tangle-network/agent-integrations 0.38.0 → 0.39.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.
@@ -196,6 +196,7 @@ __export(adapters_exports, {
196
196
  gitlabConnector: () => gitlabConnector,
197
197
  glideConnector: () => glideConnector,
198
198
  gmail: () => gmail,
199
+ googleAnalyticsConnector: () => googleAnalyticsConnector,
199
200
  googleBigqueryConnector: () => googleBigqueryConnector,
200
201
  googleCalendar: () => googleCalendar,
201
202
  googleCloudStorageConnector: () => googleCloudStorageConnector,
@@ -204,6 +205,7 @@ __export(adapters_exports, {
204
205
  googleDrive: () => googleDrive,
205
206
  googleForms: () => googleForms,
206
207
  googleGeminiConnector: () => googleGeminiConnector,
208
+ googleMeetConnector: () => googleMeetConnector,
207
209
  googleMyBusinessConnector: () => googleMyBusinessConnector,
208
210
  googleSearchConnector: () => googleSearchConnector,
209
211
  googleSearchConsoleConnector: () => googleSearchConsoleConnector,
@@ -319,12 +321,8 @@ __export(adapters_exports, {
319
321
  microsoftDynamicsCrmConnector: () => microsoftDynamicsCrmConnector,
320
322
  microsoftExcel365Connector: () => microsoftExcel365Connector,
321
323
  microsoftGraph: () => microsoftGraph,
322
- microsoftOnedriveConnector: () => microsoftOnedriveConnector,
323
324
  microsoftOnenoteConnector: () => microsoftOnenoteConnector,
324
- microsoftOutlookCalendarConnector: () => microsoftOutlookCalendarConnector,
325
- microsoftOutlookConnector: () => microsoftOutlookConnector,
326
325
  microsoftPowerBiConnector: () => microsoftPowerBiConnector,
327
- microsoftSharepointConnector: () => microsoftSharepointConnector,
328
326
  microsoftTeams: () => microsoftTeams,
329
327
  microsoftTodoConnector: () => microsoftTodoConnector,
330
328
  millionverifierConnector: () => millionverifierConnector,
@@ -342,8 +340,8 @@ __export(adapters_exports, {
342
340
  niftyConnector: () => niftyConnector,
343
341
  ninjapipeConnector: () => ninjapipeConnector,
344
342
  nocodbConnector: () => nocodbConnector,
343
+ notion: () => notion,
345
344
  notionConnector: () => notionConnector,
346
- notionDatabase: () => notionDatabase,
347
345
  ntfyConnector: () => ntfyConnector,
348
346
  odooConnector: () => odooConnector,
349
347
  omniCoConnector: () => omniCoConnector,
@@ -3134,91 +3132,253 @@ function microsoftCalendar(opts) {
3134
3132
  attendees: {
3135
3133
  type: "array",
3136
3134
  items: { type: "string", description: "attendee email" }
3137
- }
3135
+ },
3136
+ // Optional rich create fields (ported from microsoft-outlook-calendar
3137
+ // create.event). All additive — the freebusy pre-flight and
3138
+ // alternative-slot behavior below is unchanged when these are absent.
3139
+ calendarId: {
3140
+ type: "string",
3141
+ description: "Target calendar id; defaults to the user's primary calendar (/me/events) when omitted."
3142
+ },
3143
+ location: {
3144
+ type: "object",
3145
+ description: 'Graph location resource, e.g. { displayName: "Room 1" }.'
3146
+ },
3147
+ recurrence: {
3148
+ type: "object",
3149
+ description: "Graph patternedRecurrence resource ({ pattern, range })."
3150
+ },
3151
+ isOnlineMeeting: { type: "boolean", description: "Provision an online meeting (Teams) for the event." },
3152
+ onlineMeetingProvider: {
3153
+ type: "string",
3154
+ description: "Online meeting provider, e.g. 'teamsForBusiness'."
3155
+ },
3156
+ reminderMinutesBeforeStart: {
3157
+ type: "integer",
3158
+ description: "Minutes before start to fire the reminder."
3159
+ },
3160
+ isAllDay: { type: "boolean", description: "Mark the event as all-day (start/end must be midnight-aligned)." },
3161
+ categories: {
3162
+ type: "array",
3163
+ items: { type: "string", description: "Outlook category name" }
3164
+ },
3165
+ importance: { type: "string", description: "Event importance: 'low' | 'normal' | 'high'." }
3138
3166
  },
3139
3167
  required: ["start", "end", "summary"]
3140
3168
  }
3169
+ },
3170
+ {
3171
+ name: "delete_event",
3172
+ class: "mutation",
3173
+ description: "Delete an event by id from the connected Outlook calendar. Graph returns 204 on success; a re-delete of a missing event surfaces as 404 mapped to an idempotent tombstone. Honors If-Match against the event etag when the caller supplies expectedEtag.",
3174
+ cas: "native-idempotency",
3175
+ externalEffect: true,
3176
+ parameters: {
3177
+ type: "object",
3178
+ properties: {
3179
+ eventId: { type: "string", description: "Graph event id to delete." }
3180
+ },
3181
+ required: ["eventId"]
3182
+ }
3183
+ },
3184
+ {
3185
+ name: "list_events",
3186
+ class: "read",
3187
+ description: "List actual event objects on a calendar with OData paging/filtering ($top, $skip, $filter, $select, $orderby, $search). Targets the user's primary calendar (/me/events) unless calendarId is supplied. Distinct from list_availability, which returns busy windows.",
3188
+ parameters: {
3189
+ type: "object",
3190
+ properties: {
3191
+ calendarId: { type: "string", description: "Calendar id; defaults to the user's primary calendar when omitted." },
3192
+ $top: { type: "integer", description: "Max events to return (OData page size)." },
3193
+ $skip: { type: "integer", description: "Number of events to skip (OData paging offset)." },
3194
+ $filter: { type: "string", description: "OData $filter expression." },
3195
+ $select: { type: "string", description: "Comma-separated event fields to project." },
3196
+ $orderby: { type: "string", description: "OData $orderby expression." },
3197
+ $search: { type: "string", description: "OData $search query." }
3198
+ }
3199
+ }
3141
3200
  }
3142
3201
  ]
3143
3202
  },
3144
3203
  async executeRead(inv) {
3145
- if (inv.capabilityName !== "list_availability") {
3146
- throw new Error(`microsoft-calendar: unknown read capability ${inv.capabilityName}`);
3147
- }
3148
- const userPrincipal = readMetaString2(inv.source.metadata, "userPrincipal");
3149
- const { timeMin, timeMax } = inv.args;
3150
3204
  const accessToken = await ensureFreshAccessToken5(inv.source.credentials, clientId, clientSecret);
3151
- const busy = await getScheduleBusy({ accessToken, userPrincipal, timeMin, timeMax });
3152
- return {
3153
- data: { busy },
3154
- fetchedAt: Date.now()
3155
- };
3205
+ if (inv.capabilityName === "list_availability") {
3206
+ const userPrincipal = readMetaString2(inv.source.metadata, "userPrincipal");
3207
+ const { timeMin, timeMax } = inv.args;
3208
+ const busy = await getScheduleBusy({ accessToken, userPrincipal, timeMin, timeMax });
3209
+ return {
3210
+ data: { busy },
3211
+ fetchedAt: Date.now()
3212
+ };
3213
+ }
3214
+ if (inv.capabilityName === "list_events") {
3215
+ const {
3216
+ calendarId,
3217
+ $top,
3218
+ $skip,
3219
+ $filter,
3220
+ $select,
3221
+ $orderby,
3222
+ $search
3223
+ } = inv.args;
3224
+ const base = calendarId ? `https://graph.microsoft.com/v1.0/me/calendars/${encodeURIComponent(calendarId)}/events` : "https://graph.microsoft.com/v1.0/me/events";
3225
+ const qs = new URLSearchParams();
3226
+ if ($top !== void 0) qs.set("$top", String($top));
3227
+ if ($skip !== void 0) qs.set("$skip", String($skip));
3228
+ if ($filter) qs.set("$filter", $filter);
3229
+ if ($select) qs.set("$select", $select);
3230
+ if ($orderby) qs.set("$orderby", $orderby);
3231
+ if ($search) qs.set("$search", $search);
3232
+ const query = qs.toString();
3233
+ const url = query ? `${base}?${query}` : base;
3234
+ const res = await fetch(url, {
3235
+ headers: { authorization: `Bearer ${accessToken}` },
3236
+ signal: AbortSignal.timeout(15e3)
3237
+ });
3238
+ if (res.status === 401 || res.status === 403) {
3239
+ throw new CredentialsExpired(`Microsoft Graph rejected token (${res.status})`, inv.source.id);
3240
+ }
3241
+ if (!res.ok) {
3242
+ const text = await res.text().catch(() => "");
3243
+ throw new Error(`microsoft-calendar list_events ${res.status}: ${text.slice(0, 200)}`);
3244
+ }
3245
+ const json = await res.json();
3246
+ return {
3247
+ data: { events: json.value ?? [], nextLink: json["@odata.nextLink"] },
3248
+ fetchedAt: Date.now()
3249
+ };
3250
+ }
3251
+ throw new Error(`microsoft-calendar: unknown read capability ${inv.capabilityName}`);
3156
3252
  },
3157
3253
  async executeMutation(inv) {
3158
- if (inv.capabilityName !== "book_slot") {
3159
- throw new Error(`microsoft-calendar: unknown mutation capability ${inv.capabilityName}`);
3160
- }
3161
- const userPrincipal = readMetaString2(inv.source.metadata, "userPrincipal");
3162
- const { start, end, summary, description, attendees } = inv.args;
3163
3254
  const accessToken = await ensureFreshAccessToken5(inv.source.credentials, clientId, clientSecret);
3164
- const busy = await getScheduleBusy({ accessToken, userPrincipal, timeMin: start, timeMax: end });
3165
- if (busy.length > 0) {
3166
- const startMs = Date.parse(start);
3167
- const endMs = Date.parse(end);
3168
- const durMs = endMs - startMs;
3169
- const alternatives = await findNextFreeSlots2({
3170
- accessToken,
3171
- userPrincipal,
3172
- searchFromMs: endMs,
3173
- durationMs: durMs,
3174
- wanted: 3
3255
+ if (inv.capabilityName === "book_slot") {
3256
+ const userPrincipal = readMetaString2(inv.source.metadata, "userPrincipal");
3257
+ const {
3258
+ start,
3259
+ end,
3260
+ summary,
3261
+ description,
3262
+ attendees,
3263
+ calendarId,
3264
+ location,
3265
+ recurrence,
3266
+ isOnlineMeeting,
3267
+ onlineMeetingProvider,
3268
+ reminderMinutesBeforeStart,
3269
+ isAllDay,
3270
+ categories,
3271
+ importance
3272
+ } = inv.args;
3273
+ const busy = await getScheduleBusy({ accessToken, userPrincipal, timeMin: start, timeMax: end });
3274
+ if (busy.length > 0) {
3275
+ const startMs = Date.parse(start);
3276
+ const endMs = Date.parse(end);
3277
+ const durMs = endMs - startMs;
3278
+ const alternatives = await findNextFreeSlots2({
3279
+ accessToken,
3280
+ userPrincipal,
3281
+ searchFromMs: endMs,
3282
+ durationMs: durMs,
3283
+ wanted: 3
3284
+ });
3285
+ throw new ResourceContention(
3286
+ `requested slot ${start}\u2013${end} is no longer free`,
3287
+ alternatives,
3288
+ { busy }
3289
+ );
3290
+ }
3291
+ const event = {
3292
+ subject: summary,
3293
+ body: description ? { contentType: "text", content: description } : void 0,
3294
+ start: { dateTime: start, timeZone: "UTC" },
3295
+ end: { dateTime: end, timeZone: "UTC" },
3296
+ attendees: attendees?.map((email) => ({
3297
+ emailAddress: { address: email },
3298
+ type: "required"
3299
+ }))
3300
+ };
3301
+ if (location !== void 0) event.location = location;
3302
+ if (recurrence !== void 0) event.recurrence = recurrence;
3303
+ if (isOnlineMeeting !== void 0) event.isOnlineMeeting = isOnlineMeeting;
3304
+ if (onlineMeetingProvider !== void 0) event.onlineMeetingProvider = onlineMeetingProvider;
3305
+ if (reminderMinutesBeforeStart !== void 0) event.reminderMinutesBeforeStart = reminderMinutesBeforeStart;
3306
+ if (isAllDay !== void 0) event.isAllDay = isAllDay;
3307
+ if (categories !== void 0) event.categories = categories;
3308
+ if (importance !== void 0) event.importance = importance;
3309
+ const url = calendarId ? `https://graph.microsoft.com/v1.0/me/calendars/${encodeURIComponent(calendarId)}/events` : "https://graph.microsoft.com/v1.0/me/events";
3310
+ const res = await fetch(url, {
3311
+ method: "POST",
3312
+ headers: {
3313
+ authorization: `Bearer ${accessToken}`,
3314
+ "content-type": "application/json"
3315
+ },
3316
+ body: JSON.stringify(event),
3317
+ signal: AbortSignal.timeout(15e3)
3175
3318
  });
3176
- throw new ResourceContention(
3177
- `requested slot ${start}\u2013${end} is no longer free`,
3178
- alternatives,
3179
- { busy }
3180
- );
3181
- }
3182
- const event = {
3183
- subject: summary,
3184
- body: description ? { contentType: "text", content: description } : void 0,
3185
- start: { dateTime: start, timeZone: "UTC" },
3186
- end: { dateTime: end, timeZone: "UTC" },
3187
- attendees: attendees?.map((email) => ({
3188
- emailAddress: { address: email },
3189
- type: "required"
3190
- }))
3191
- };
3192
- const res = await fetch("https://graph.microsoft.com/v1.0/me/events", {
3193
- method: "POST",
3194
- headers: {
3195
- authorization: `Bearer ${accessToken}`,
3196
- "content-type": "application/json"
3197
- },
3198
- body: JSON.stringify(event),
3199
- signal: AbortSignal.timeout(15e3)
3200
- });
3201
- if (res.status === 401 || res.status === 403) {
3202
- throw new CredentialsExpired(`Microsoft Graph rejected token (${res.status})`, inv.source.id);
3319
+ if (res.status === 401 || res.status === 403) {
3320
+ throw new CredentialsExpired(`Microsoft Graph rejected token (${res.status})`, inv.source.id);
3321
+ }
3322
+ if (res.status === 412 || res.status === 409) {
3323
+ throw new ResourceContention(
3324
+ `Microsoft Graph reported conflict on book_slot (${res.status})`,
3325
+ []
3326
+ );
3327
+ }
3328
+ if (!res.ok) {
3329
+ const text = await res.text().catch(() => "");
3330
+ throw new Error(`microsoft-calendar book_slot ${res.status}: ${text.slice(0, 200)}`);
3331
+ }
3332
+ const created = await res.json();
3333
+ return {
3334
+ status: "committed",
3335
+ data: { eventId: created.id, webLink: created.webLink },
3336
+ etagAfter: created["@odata.etag"],
3337
+ committedAt: Date.now(),
3338
+ idempotentReplay: false
3339
+ };
3203
3340
  }
3204
- if (res.status === 412 || res.status === 409) {
3205
- throw new ResourceContention(
3206
- `Microsoft Graph reported conflict on book_slot (${res.status})`,
3207
- []
3341
+ if (inv.capabilityName === "delete_event") {
3342
+ const { eventId } = inv.args;
3343
+ const headers = { authorization: `Bearer ${accessToken}` };
3344
+ if (inv.expectedEtag) headers["if-match"] = inv.expectedEtag;
3345
+ const res = await fetch(
3346
+ `https://graph.microsoft.com/v1.0/me/events/${encodeURIComponent(eventId)}`,
3347
+ {
3348
+ method: "DELETE",
3349
+ headers,
3350
+ signal: AbortSignal.timeout(15e3)
3351
+ }
3208
3352
  );
3353
+ if (res.status === 401 || res.status === 403) {
3354
+ throw new CredentialsExpired(`Microsoft Graph rejected token (${res.status})`, inv.source.id);
3355
+ }
3356
+ if (res.status === 412 || res.status === 409) {
3357
+ throw new ResourceContention(
3358
+ `Microsoft Graph reported conflict on delete_event (${res.status})`,
3359
+ []
3360
+ );
3361
+ }
3362
+ if (res.status === 404) {
3363
+ return {
3364
+ status: "committed",
3365
+ data: { eventId, deleted: true, alreadyMissing: true },
3366
+ committedAt: Date.now(),
3367
+ idempotentReplay: true
3368
+ };
3369
+ }
3370
+ if (!res.ok) {
3371
+ const text = await res.text().catch(() => "");
3372
+ throw new Error(`microsoft-calendar delete_event ${res.status}: ${text.slice(0, 200)}`);
3373
+ }
3374
+ return {
3375
+ status: "committed",
3376
+ data: { eventId, deleted: true },
3377
+ committedAt: Date.now(),
3378
+ idempotentReplay: false
3379
+ };
3209
3380
  }
3210
- if (!res.ok) {
3211
- const text = await res.text().catch(() => "");
3212
- throw new Error(`microsoft-calendar book_slot ${res.status}: ${text.slice(0, 200)}`);
3213
- }
3214
- const created = await res.json();
3215
- return {
3216
- status: "committed",
3217
- data: { eventId: created.id, webLink: created.webLink },
3218
- etagAfter: created["@odata.etag"],
3219
- committedAt: Date.now(),
3220
- idempotentReplay: false
3221
- };
3381
+ throw new Error(`microsoft-calendar: unknown mutation capability ${inv.capabilityName}`);
3222
3382
  },
3223
3383
  async exchangeOAuth(input) {
3224
3384
  if (!clientId || !clientSecret) {
@@ -4438,518 +4598,6 @@ async function uploadFile2(inv, accessToken, timeoutMs) {
4438
4598
  };
4439
4599
  }
4440
4600
 
4441
- // src/connectors/adapters/notion-database.ts
4442
- var AUTH_URL8 = "https://api.notion.com/v1/oauth/authorize";
4443
- var TOKEN_URL8 = "https://api.notion.com/v1/oauth/token";
4444
- var API5 = "https://api.notion.com/v1";
4445
- var NOTION_VERSION = "2022-06-28";
4446
- function notionDatabase(opts) {
4447
- const { clientId, clientSecret } = opts;
4448
- const adapter = {
4449
- manifest: {
4450
- kind: "notion-database",
4451
- displayName: "Notion (database)",
4452
- description: "Query a Notion database, create new pages, and update existing ones with optimistic concurrency via last_edited_time.",
4453
- auth: {
4454
- kind: "oauth2",
4455
- authorizationUrl: AUTH_URL8,
4456
- tokenUrl: TOKEN_URL8,
4457
- // Notion does not use OAuth scopes — the workspace owner picks
4458
- // which pages/databases the integration sees during install. We
4459
- // declare an empty scope list so the consent screen renders cleanly.
4460
- scopes: [],
4461
- clientIdEnv: "NOTION_OAUTH_CLIENT_ID",
4462
- clientSecretEnv: "NOTION_OAUTH_CLIENT_SECRET",
4463
- extraAuthParams: { owner: "user" }
4464
- },
4465
- category: "doc",
4466
- defaultConsistencyModel: "authoritative",
4467
- capabilities: [
4468
- {
4469
- name: "query_database",
4470
- class: "read",
4471
- description: "Query the connected Notion database with an optional filter object (Notion query DSL).",
4472
- parameters: {
4473
- type: "object",
4474
- properties: {
4475
- filter: { type: "object", description: "Notion API filter object \u2014 passed through verbatim." },
4476
- pageSize: { type: "integer", minimum: 1, maximum: 100, default: 50 },
4477
- startCursor: { type: "string" }
4478
- }
4479
- }
4480
- },
4481
- {
4482
- name: "create_page",
4483
- class: "mutation",
4484
- description: "Create a new page inside the connected database.",
4485
- cas: "native-idempotency",
4486
- externalEffect: true,
4487
- parameters: {
4488
- type: "object",
4489
- properties: {
4490
- properties: {
4491
- type: "object",
4492
- description: "Notion property map keyed by property name."
4493
- }
4494
- },
4495
- required: ["properties"]
4496
- }
4497
- },
4498
- {
4499
- name: "update_page",
4500
- class: "mutation",
4501
- description: "Update properties on an existing page. If `expectedLastEditedTime` is supplied and stale, the update is rejected with conflict.",
4502
- cas: "etag-if-match",
4503
- externalEffect: true,
4504
- parameters: {
4505
- type: "object",
4506
- properties: {
4507
- pageId: { type: "string" },
4508
- properties: { type: "object" },
4509
- expectedLastEditedTime: {
4510
- type: "string",
4511
- description: "RFC3339 timestamp the agent observed on its last read. Drift triggers ResourceContention."
4512
- }
4513
- },
4514
- required: ["pageId", "properties"]
4515
- }
4516
- },
4517
- {
4518
- name: "pages.archive",
4519
- class: "mutation",
4520
- description: "Archive (soft-delete) a Notion page. Restorable via update_page with archived:false.",
4521
- cas: "native-idempotency",
4522
- externalEffect: true,
4523
- parameters: {
4524
- type: "object",
4525
- properties: { pageId: { type: "string" } },
4526
- required: ["pageId"]
4527
- }
4528
- },
4529
- {
4530
- name: "databases.create",
4531
- class: "mutation",
4532
- description: "Create a new Notion database underneath a parent page.",
4533
- cas: "native-idempotency",
4534
- externalEffect: true,
4535
- parameters: {
4536
- type: "object",
4537
- properties: {
4538
- parentPageId: { type: "string", description: "Parent page id under which to create the database." },
4539
- title: {
4540
- type: "array",
4541
- description: "Notion rich_text array used as the database title."
4542
- },
4543
- properties: {
4544
- type: "object",
4545
- description: "Schema map \u2014 property name \u2192 Notion property schema."
4546
- }
4547
- },
4548
- required: ["parentPageId", "title", "properties"]
4549
- }
4550
- },
4551
- {
4552
- name: "databases.update",
4553
- class: "mutation",
4554
- description: "Update a database title and/or schema.",
4555
- cas: "native-idempotency",
4556
- externalEffect: true,
4557
- parameters: {
4558
- type: "object",
4559
- properties: {
4560
- databaseId: { type: "string" },
4561
- title: { type: "array", description: "Optional new rich_text title." },
4562
- properties: { type: "object", description: "Optional partial schema update." }
4563
- },
4564
- required: ["databaseId"]
4565
- }
4566
- },
4567
- {
4568
- name: "blocks.append",
4569
- class: "mutation",
4570
- description: "Append child blocks to a page or block.",
4571
- cas: "native-idempotency",
4572
- externalEffect: true,
4573
- parameters: {
4574
- type: "object",
4575
- properties: {
4576
- blockId: { type: "string", description: "Parent page or block id." },
4577
- children: { type: "array", description: "Block descriptor array per Notion schema." }
4578
- },
4579
- required: ["blockId", "children"]
4580
- }
4581
- }
4582
- ]
4583
- },
4584
- async executeRead(inv) {
4585
- if (inv.capabilityName !== "query_database") {
4586
- throw new Error(`notion-database: unknown read capability ${inv.capabilityName}`);
4587
- }
4588
- const accessToken = readToken(inv.source.credentials);
4589
- const databaseId = readMetaString3(inv.source.metadata, "databaseId");
4590
- const { filter, pageSize, startCursor } = inv.args;
4591
- const body = {
4592
- page_size: Math.min(Math.max(1, pageSize ?? 50), 100)
4593
- };
4594
- if (filter) body.filter = filter;
4595
- if (startCursor) body.start_cursor = startCursor;
4596
- const res = await fetch(`${API5}/databases/${encodeURIComponent(databaseId)}/query`, {
4597
- method: "POST",
4598
- headers: notionHeaders(accessToken),
4599
- body: JSON.stringify(body),
4600
- signal: AbortSignal.timeout(1e4)
4601
- });
4602
- if (res.status === 401) {
4603
- throw new CredentialsExpired("Notion rejected token (401)", inv.source.id);
4604
- }
4605
- if (!res.ok) {
4606
- const text = await res.text().catch(() => "");
4607
- throw new Error(`notion-database query_database ${res.status}: ${text.slice(0, 200)}`);
4608
- }
4609
- const json = await res.json();
4610
- return {
4611
- data: {
4612
- results: json.results ?? [],
4613
- hasMore: json.has_more ?? false,
4614
- nextCursor: json.next_cursor ?? null
4615
- },
4616
- fetchedAt: Date.now()
4617
- };
4618
- },
4619
- async executeMutation(inv) {
4620
- const accessToken = readToken(inv.source.credentials);
4621
- if (inv.capabilityName === "create_page") return createPage(inv, accessToken);
4622
- if (inv.capabilityName === "update_page") return updatePage(inv, accessToken);
4623
- if (inv.capabilityName === "pages.archive") return archivePage(inv, accessToken);
4624
- if (inv.capabilityName === "databases.create") return createDatabase(inv, accessToken);
4625
- if (inv.capabilityName === "databases.update") return updateDatabase(inv, accessToken);
4626
- if (inv.capabilityName === "blocks.append") return appendBlocks(inv, accessToken);
4627
- throw new Error(`notion-database: unknown mutation capability ${inv.capabilityName}`);
4628
- },
4629
- async exchangeOAuth(input) {
4630
- if (!clientId || !clientSecret) {
4631
- throw new Error("Notion OAuth client not configured (NOTION_OAUTH_CLIENT_ID / _SECRET)");
4632
- }
4633
- const body = new URLSearchParams({
4634
- grant_type: "authorization_code",
4635
- code: input.code,
4636
- redirect_uri: input.redirectUri,
4637
- code_verifier: input.codeVerifier
4638
- });
4639
- const res = await fetch(TOKEN_URL8, {
4640
- method: "POST",
4641
- headers: {
4642
- authorization: `Basic ${Buffer.from(`${clientId}:${clientSecret}`).toString("base64")}`,
4643
- "content-type": "application/x-www-form-urlencoded",
4644
- accept: "application/json",
4645
- "Notion-Version": NOTION_VERSION
4646
- },
4647
- body
4648
- });
4649
- if (!res.ok) {
4650
- const text = await res.text().catch(() => "");
4651
- throw new Error(`Notion OAuth token exchange failed: ${res.status} \u2014 ${text.slice(0, 200)}`);
4652
- }
4653
- const json = await res.json();
4654
- return {
4655
- credentials: {
4656
- kind: "oauth2",
4657
- accessToken: json.access_token,
4658
- refreshToken: json.refresh_token
4659
- },
4660
- scopes: [],
4661
- metadata: {
4662
- botId: json.bot_id,
4663
- workspaceId: json.workspace_id,
4664
- workspaceName: json.workspace_name,
4665
- // Operator picks the database in a follow-up step; default empty.
4666
- databaseId: ""
4667
- }
4668
- };
4669
- },
4670
- async refreshToken(creds) {
4671
- if (creds.kind !== "oauth2" || !creds.refreshToken) {
4672
- if (creds.kind === "oauth2" && creds.accessToken && !creds.expiresAt) {
4673
- return creds;
4674
- }
4675
- throw new Error("notion-database.refreshToken: missing refresh token");
4676
- }
4677
- const refreshed = await refreshAccessToken({
4678
- tokenUrl: TOKEN_URL8,
4679
- clientId,
4680
- clientSecret,
4681
- refreshToken: creds.refreshToken
4682
- });
4683
- return {
4684
- kind: "oauth2",
4685
- accessToken: refreshed.accessToken,
4686
- refreshToken: refreshed.refreshToken ?? creds.refreshToken,
4687
- expiresAt: refreshed.expiresIn ? Date.now() + refreshed.expiresIn * 1e3 : void 0
4688
- };
4689
- },
4690
- async test(source) {
4691
- try {
4692
- const accessToken = readToken(source.credentials);
4693
- const res = await fetch(`${API5}/users/me`, {
4694
- headers: notionHeaders(accessToken),
4695
- signal: AbortSignal.timeout(8e3)
4696
- });
4697
- if (res.status === 401) return { ok: false, reason: "Notion rejected token (401) \u2014 reconnect required" };
4698
- if (!res.ok) return { ok: false, reason: `Notion returned ${res.status}` };
4699
- return { ok: true };
4700
- } catch (err) {
4701
- return { ok: false, reason: err instanceof Error ? err.message : String(err) };
4702
- }
4703
- }
4704
- };
4705
- return adapter;
4706
- }
4707
- async function createPage(inv, accessToken) {
4708
- const databaseId = readMetaString3(inv.source.metadata, "databaseId");
4709
- const { properties } = inv.args;
4710
- const res = await fetch(`${API5}/pages`, {
4711
- method: "POST",
4712
- headers: {
4713
- ...notionHeaders(accessToken),
4714
- "Idempotency-Key": inv.idempotencyKey
4715
- },
4716
- body: JSON.stringify({
4717
- parent: { database_id: databaseId },
4718
- properties
4719
- }),
4720
- signal: AbortSignal.timeout(15e3)
4721
- });
4722
- if (res.status === 401) {
4723
- throw new CredentialsExpired("Notion rejected token (401)", inv.source.id);
4724
- }
4725
- if (res.status === 409) {
4726
- throw new ResourceContention("Notion idempotency-key conflict \u2014 different args under same key");
4727
- }
4728
- if (!res.ok) {
4729
- const text = await res.text().catch(() => "");
4730
- throw new Error(`notion-database create_page ${res.status}: ${text.slice(0, 200)}`);
4731
- }
4732
- const created = await res.json();
4733
- return {
4734
- status: "committed",
4735
- data: { pageId: created.id, url: created.url, lastEditedTime: created.last_edited_time },
4736
- etagAfter: created.last_edited_time,
4737
- committedAt: Date.now(),
4738
- idempotentReplay: false
4739
- };
4740
- }
4741
- async function updatePage(inv, accessToken) {
4742
- const { pageId, properties, expectedLastEditedTime } = inv.args;
4743
- if (expectedLastEditedTime) {
4744
- const headRes = await fetch(`${API5}/pages/${encodeURIComponent(pageId)}`, {
4745
- headers: notionHeaders(accessToken),
4746
- signal: AbortSignal.timeout(1e4)
4747
- });
4748
- if (headRes.status === 401) {
4749
- throw new CredentialsExpired("Notion rejected token (401)", inv.source.id);
4750
- }
4751
- if (!headRes.ok) {
4752
- const text = await headRes.text().catch(() => "");
4753
- throw new Error(`notion-database update_page (preflight) ${headRes.status}: ${text.slice(0, 200)}`);
4754
- }
4755
- const page = await headRes.json();
4756
- if (page.last_edited_time && page.last_edited_time !== expectedLastEditedTime) {
4757
- throw new ResourceContention(
4758
- `Notion page ${pageId} was modified since the agent last read it`,
4759
- [],
4760
- { last_edited_time: page.last_edited_time, properties: page.properties }
4761
- );
4762
- }
4763
- }
4764
- const res = await fetch(`${API5}/pages/${encodeURIComponent(pageId)}`, {
4765
- method: "PATCH",
4766
- headers: notionHeaders(accessToken),
4767
- body: JSON.stringify({ properties }),
4768
- signal: AbortSignal.timeout(15e3)
4769
- });
4770
- if (res.status === 401) {
4771
- throw new CredentialsExpired("Notion rejected token (401)", inv.source.id);
4772
- }
4773
- if (res.status === 409 || res.status === 412) {
4774
- throw new ResourceContention(`Notion update_page conflict (${res.status})`);
4775
- }
4776
- if (!res.ok) {
4777
- const text = await res.text().catch(() => "");
4778
- throw new Error(`notion-database update_page ${res.status}: ${text.slice(0, 200)}`);
4779
- }
4780
- const updated = await res.json();
4781
- return {
4782
- status: "committed",
4783
- data: { pageId: updated.id, url: updated.url, lastEditedTime: updated.last_edited_time },
4784
- etagAfter: updated.last_edited_time,
4785
- committedAt: Date.now(),
4786
- idempotentReplay: false
4787
- };
4788
- }
4789
- async function archivePage(inv, accessToken) {
4790
- const { pageId } = inv.args;
4791
- if (typeof pageId !== "string" || pageId.length === 0) {
4792
- throw new Error("notion-database pages.archive: pageId is required");
4793
- }
4794
- const res = await fetch(`${API5}/pages/${encodeURIComponent(pageId)}`, {
4795
- method: "PATCH",
4796
- headers: {
4797
- ...notionHeaders(accessToken),
4798
- "Idempotency-Key": inv.idempotencyKey
4799
- },
4800
- body: JSON.stringify({ archived: true }),
4801
- signal: AbortSignal.timeout(15e3)
4802
- });
4803
- if (res.status === 401) {
4804
- throw new CredentialsExpired("Notion rejected token (401)", inv.source.id);
4805
- }
4806
- if (res.status === 409) {
4807
- throw new ResourceContention("Notion idempotency-key conflict \u2014 different args under same key");
4808
- }
4809
- if (!res.ok) {
4810
- const text = await res.text().catch(() => "");
4811
- throw new Error(`notion-database pages.archive ${res.status}: ${text.slice(0, 200)}`);
4812
- }
4813
- const archived = await res.json();
4814
- return {
4815
- status: "committed",
4816
- data: { pageId: archived.id, archived: archived.archived ?? true, lastEditedTime: archived.last_edited_time },
4817
- etagAfter: archived.last_edited_time,
4818
- committedAt: Date.now(),
4819
- idempotentReplay: false
4820
- };
4821
- }
4822
- async function createDatabase(inv, accessToken) {
4823
- const { parentPageId, title, properties } = inv.args;
4824
- if (typeof parentPageId !== "string" || parentPageId.length === 0) {
4825
- throw new Error("notion-database databases.create: parentPageId is required");
4826
- }
4827
- if (!title) throw new Error("notion-database databases.create: title is required");
4828
- if (!properties) throw new Error("notion-database databases.create: properties is required");
4829
- const res = await fetch(`${API5}/databases`, {
4830
- method: "POST",
4831
- headers: {
4832
- ...notionHeaders(accessToken),
4833
- "Idempotency-Key": inv.idempotencyKey
4834
- },
4835
- body: JSON.stringify({
4836
- parent: { type: "page_id", page_id: parentPageId },
4837
- title,
4838
- properties
4839
- }),
4840
- signal: AbortSignal.timeout(15e3)
4841
- });
4842
- if (res.status === 401) {
4843
- throw new CredentialsExpired("Notion rejected token (401)", inv.source.id);
4844
- }
4845
- if (res.status === 409) {
4846
- throw new ResourceContention("Notion idempotency-key conflict \u2014 different args under same key");
4847
- }
4848
- if (!res.ok) {
4849
- const text = await res.text().catch(() => "");
4850
- throw new Error(`notion-database databases.create ${res.status}: ${text.slice(0, 200)}`);
4851
- }
4852
- const created = await res.json();
4853
- return {
4854
- status: "committed",
4855
- data: { databaseId: created.id, url: created.url, lastEditedTime: created.last_edited_time },
4856
- etagAfter: created.last_edited_time,
4857
- committedAt: Date.now(),
4858
- idempotentReplay: false
4859
- };
4860
- }
4861
- async function updateDatabase(inv, accessToken) {
4862
- const { databaseId, title, properties } = inv.args;
4863
- if (typeof databaseId !== "string" || databaseId.length === 0) {
4864
- throw new Error("notion-database databases.update: databaseId is required");
4865
- }
4866
- const body = {};
4867
- if (title !== void 0) body.title = title;
4868
- if (properties !== void 0) body.properties = properties;
4869
- const res = await fetch(`${API5}/databases/${encodeURIComponent(databaseId)}`, {
4870
- method: "PATCH",
4871
- headers: {
4872
- ...notionHeaders(accessToken),
4873
- "Idempotency-Key": inv.idempotencyKey
4874
- },
4875
- body: JSON.stringify(body),
4876
- signal: AbortSignal.timeout(15e3)
4877
- });
4878
- if (res.status === 401) {
4879
- throw new CredentialsExpired("Notion rejected token (401)", inv.source.id);
4880
- }
4881
- if (res.status === 409) {
4882
- throw new ResourceContention("Notion idempotency-key conflict \u2014 different args under same key");
4883
- }
4884
- if (!res.ok) {
4885
- const text = await res.text().catch(() => "");
4886
- throw new Error(`notion-database databases.update ${res.status}: ${text.slice(0, 200)}`);
4887
- }
4888
- const updated = await res.json();
4889
- return {
4890
- status: "committed",
4891
- data: { databaseId: updated.id, url: updated.url, lastEditedTime: updated.last_edited_time },
4892
- etagAfter: updated.last_edited_time,
4893
- committedAt: Date.now(),
4894
- idempotentReplay: false
4895
- };
4896
- }
4897
- async function appendBlocks(inv, accessToken) {
4898
- const { blockId, children } = inv.args;
4899
- if (typeof blockId !== "string" || blockId.length === 0) {
4900
- throw new Error("notion-database blocks.append: blockId is required");
4901
- }
4902
- if (!Array.isArray(children)) {
4903
- throw new Error("notion-database blocks.append: children must be an array");
4904
- }
4905
- const res = await fetch(`${API5}/blocks/${encodeURIComponent(blockId)}/children`, {
4906
- method: "PATCH",
4907
- headers: {
4908
- ...notionHeaders(accessToken),
4909
- "Idempotency-Key": inv.idempotencyKey
4910
- },
4911
- body: JSON.stringify({ children }),
4912
- signal: AbortSignal.timeout(15e3)
4913
- });
4914
- if (res.status === 401) {
4915
- throw new CredentialsExpired("Notion rejected token (401)", inv.source.id);
4916
- }
4917
- if (res.status === 409) {
4918
- throw new ResourceContention("Notion idempotency-key conflict \u2014 different args under same key");
4919
- }
4920
- if (!res.ok) {
4921
- const text = await res.text().catch(() => "");
4922
- throw new Error(`notion-database blocks.append ${res.status}: ${text.slice(0, 200)}`);
4923
- }
4924
- const json = await res.json();
4925
- return {
4926
- status: "committed",
4927
- data: { results: json.results ?? [] },
4928
- committedAt: Date.now(),
4929
- idempotentReplay: false
4930
- };
4931
- }
4932
- function notionHeaders(accessToken) {
4933
- return {
4934
- authorization: `Bearer ${accessToken}`,
4935
- "Notion-Version": NOTION_VERSION,
4936
- "content-type": "application/json"
4937
- };
4938
- }
4939
- function readToken(creds) {
4940
- if (creds.kind !== "oauth2" || typeof creds.accessToken !== "string") {
4941
- throw new Error("notion-database: expected oauth2 credentials");
4942
- }
4943
- return creds.accessToken;
4944
- }
4945
- function readMetaString3(meta, key) {
4946
- const v = meta[key];
4947
- if (typeof v !== "string" || v.length === 0) {
4948
- throw new Error(`notion-database DataSource.metadata.${key} is missing`);
4949
- }
4950
- return v;
4951
- }
4952
-
4953
4601
  // src/connectors/adapters/docuseal.ts
4954
4602
  import { createHmac, timingSafeEqual } from "crypto";
4955
4603
  var DEFAULT_BASE = "https://api.docuseal.com";
@@ -5249,7 +4897,7 @@ async function voidSubmission(inv, apiKey, baseUrl, timeoutMs) {
5249
4897
  }
5250
4898
 
5251
4899
  // src/connectors/adapters/twilio-sms.ts
5252
- var API6 = "https://api.twilio.com/2010-04-01";
4900
+ var API5 = "https://api.twilio.com/2010-04-01";
5253
4901
  var LOOKUP_API = "https://lookups.twilio.com/v1";
5254
4902
  var twilioSmsConnector = {
5255
4903
  manifest: {
@@ -5406,7 +5054,7 @@ var twilioSmsConnector = {
5406
5054
  params.set("PageSize", String(Math.min(Math.max(1, limit ?? 20), 100)));
5407
5055
  if (to) params.set("To", to);
5408
5056
  if (from) params.set("From", from);
5409
- const url = `${API6}/Accounts/${encodeURIComponent(auth.accountSid)}/Messages.json?${params.toString()}`;
5057
+ const url = `${API5}/Accounts/${encodeURIComponent(auth.accountSid)}/Messages.json?${params.toString()}`;
5410
5058
  const res = await fetch(url, {
5411
5059
  headers: { authorization: basicAuth(auth) },
5412
5060
  signal: AbortSignal.timeout(1e4)
@@ -5427,7 +5075,7 @@ var twilioSmsConnector = {
5427
5075
  const params = new URLSearchParams();
5428
5076
  params.set("PageSize", String(Math.min(Math.max(1, limit ?? 50), 100)));
5429
5077
  if (phoneNumber) params.set("PhoneNumber", phoneNumber);
5430
- const url = `${API6}/Accounts/${encodeURIComponent(auth.accountSid)}/IncomingPhoneNumbers.json?${params.toString()}`;
5078
+ const url = `${API5}/Accounts/${encodeURIComponent(auth.accountSid)}/IncomingPhoneNumbers.json?${params.toString()}`;
5431
5079
  const res = await fetch(url, {
5432
5080
  headers: { authorization: basicAuth(auth) },
5433
5081
  signal: AbortSignal.timeout(1e4)
@@ -5449,13 +5097,13 @@ var twilioSmsConnector = {
5449
5097
  const auth = parseAuth(inv.source.credentials);
5450
5098
  if (inv.capabilityName === "send_sms") {
5451
5099
  const { to, body, from } = inv.args;
5452
- const fromNumber = from ?? readMetaString4(inv.source.metadata, "fromNumber");
5100
+ const fromNumber = from ?? readMetaString3(inv.source.metadata, "fromNumber");
5453
5101
  const formBody = new URLSearchParams({ To: to, From: fromNumber, Body: body });
5454
5102
  return await postMessages(inv, auth, formBody, "send_sms");
5455
5103
  }
5456
5104
  if (inv.capabilityName === "send_mms") {
5457
5105
  const { to, body, from, mediaUrl } = inv.args;
5458
- const fromNumber = from ?? readMetaString4(inv.source.metadata, "fromNumber");
5106
+ const fromNumber = from ?? readMetaString3(inv.source.metadata, "fromNumber");
5459
5107
  const formBody = new URLSearchParams();
5460
5108
  formBody.set("To", to);
5461
5109
  formBody.set("From", fromNumber);
@@ -5467,7 +5115,7 @@ var twilioSmsConnector = {
5467
5115
  if (inv.capabilityName === "send_whatsapp") {
5468
5116
  const { to, body, from } = inv.args;
5469
5117
  const ensureWhatsapp = (n) => n.startsWith("whatsapp:") ? n : `whatsapp:${n}`;
5470
- const fromRaw = from ?? readMetaStringOptional(inv.source.metadata, "whatsappFromNumber") ?? readMetaString4(inv.source.metadata, "fromNumber");
5118
+ const fromRaw = from ?? readMetaStringOptional(inv.source.metadata, "whatsappFromNumber") ?? readMetaString3(inv.source.metadata, "fromNumber");
5471
5119
  const formBody = new URLSearchParams({
5472
5120
  To: ensureWhatsapp(to),
5473
5121
  From: ensureWhatsapp(fromRaw),
@@ -5477,7 +5125,7 @@ var twilioSmsConnector = {
5477
5125
  }
5478
5126
  if (inv.capabilityName === "redact_message") {
5479
5127
  const { messageSid } = inv.args;
5480
- const url = `${API6}/Accounts/${encodeURIComponent(auth.accountSid)}/Messages/${encodeURIComponent(messageSid)}.json`;
5128
+ const url = `${API5}/Accounts/${encodeURIComponent(auth.accountSid)}/Messages/${encodeURIComponent(messageSid)}.json`;
5481
5129
  const formBody = new URLSearchParams({ Body: "" });
5482
5130
  const res = await fetch(url, {
5483
5131
  method: "POST",
@@ -5510,7 +5158,7 @@ var twilioSmsConnector = {
5510
5158
  async test(source) {
5511
5159
  try {
5512
5160
  const auth = parseAuth(source.credentials);
5513
- const res = await fetch(`${API6}/Accounts/${encodeURIComponent(auth.accountSid)}.json`, {
5161
+ const res = await fetch(`${API5}/Accounts/${encodeURIComponent(auth.accountSid)}.json`, {
5514
5162
  headers: { authorization: basicAuth(auth) },
5515
5163
  signal: AbortSignal.timeout(8e3)
5516
5164
  });
@@ -5546,7 +5194,7 @@ function parseAuth(creds) {
5546
5194
  function basicAuth(auth) {
5547
5195
  return `Basic ${Buffer.from(`${auth.username}:${auth.password}`).toString("base64")}`;
5548
5196
  }
5549
- function readMetaString4(meta, key) {
5197
+ function readMetaString3(meta, key) {
5550
5198
  const v = meta[key];
5551
5199
  if (typeof v !== "string" || v.length === 0) {
5552
5200
  throw new Error(`twilio-sms DataSource.metadata.${key} is missing`);
@@ -5558,7 +5206,7 @@ function readMetaStringOptional(meta, key) {
5558
5206
  return typeof v === "string" && v.length > 0 ? v : void 0;
5559
5207
  }
5560
5208
  async function postMessages(inv, auth, formBody, label) {
5561
- const url = `${API6}/Accounts/${encodeURIComponent(auth.accountSid)}/Messages.json`;
5209
+ const url = `${API5}/Accounts/${encodeURIComponent(auth.accountSid)}/Messages.json`;
5562
5210
  const res = await fetch(url, {
5563
5211
  method: "POST",
5564
5212
  headers: {
@@ -5587,7 +5235,7 @@ async function postMessages(inv, auth, formBody, label) {
5587
5235
  }
5588
5236
 
5589
5237
  // src/connectors/adapters/phony.ts
5590
- var API7 = "https://api.ph0ny.com";
5238
+ var API6 = "https://api.ph0ny.com";
5591
5239
  var E164 = /^\+[1-9]\d{7,14}$/;
5592
5240
  var phonyConnector = {
5593
5241
  manifest: {
@@ -5857,7 +5505,7 @@ var phonyConnector = {
5857
5505
  const json = await getJson(
5858
5506
  inv,
5859
5507
  token,
5860
- `${API7}/v1/agents?${params.toString()}`,
5508
+ `${API6}/v1/agents?${params.toString()}`,
5861
5509
  "list_agents"
5862
5510
  );
5863
5511
  return {
@@ -5870,7 +5518,7 @@ var phonyConnector = {
5870
5518
  const json = await getJson(
5871
5519
  inv,
5872
5520
  token,
5873
- `${API7}/v1/outbound/${encodeURIComponent(id)}`,
5521
+ `${API6}/v1/outbound/${encodeURIComponent(id)}`,
5874
5522
  "get_call"
5875
5523
  );
5876
5524
  return { data: { call: json.call ?? null }, fetchedAt: Date.now() };
@@ -5883,7 +5531,7 @@ var phonyConnector = {
5883
5531
  const json = await getJson(
5884
5532
  inv,
5885
5533
  token,
5886
- `${API7}/v1/outbound?${params.toString()}`,
5534
+ `${API6}/v1/outbound?${params.toString()}`,
5887
5535
  "list_calls"
5888
5536
  );
5889
5537
  return { data: { calls: json.calls ?? [] }, fetchedAt: Date.now() };
@@ -5894,7 +5542,7 @@ var phonyConnector = {
5894
5542
  if (limit !== void 0) payload.limit = limit;
5895
5543
  if (threshold !== void 0) payload.threshold = threshold;
5896
5544
  if (includeMetadata !== void 0) payload.includeMetadata = includeMetadata;
5897
- const res = await fetch(`${API7}/v1/collections/${encodeURIComponent(collectionId)}/search`, {
5545
+ const res = await fetch(`${API6}/v1/collections/${encodeURIComponent(collectionId)}/search`, {
5898
5546
  method: "POST",
5899
5547
  headers: {
5900
5548
  authorization: `Bearer ${token}`,
@@ -5935,7 +5583,7 @@ var phonyConnector = {
5935
5583
  if (args.callerProfile !== void 0) payload.callerProfile = args.callerProfile;
5936
5584
  if (args.voiceCloneId !== void 0) payload.voiceCloneId = args.voiceCloneId;
5937
5585
  if (args.dryRun !== void 0) payload.dryRun = args.dryRun;
5938
- const res = await fetch(`${API7}/v1/outbound/start`, {
5586
+ const res = await fetch(`${API6}/v1/outbound/start`, {
5939
5587
  method: "POST",
5940
5588
  headers: {
5941
5589
  authorization: `Bearer ${token}`,
@@ -5965,7 +5613,7 @@ var phonyConnector = {
5965
5613
  }
5966
5614
  if (inv.capabilityName === "create_agent") {
5967
5615
  const payload = pick(inv.args, AGENT_FIELDS);
5968
- const json = await postJson(inv, token, `${API7}/v1/agents`, payload, "create_agent");
5616
+ const json = await postJson(inv, token, `${API6}/v1/agents`, payload, "create_agent");
5969
5617
  return {
5970
5618
  status: "committed",
5971
5619
  data: { agent: json },
@@ -5981,7 +5629,7 @@ var phonyConnector = {
5981
5629
  const json = await postJson(
5982
5630
  inv,
5983
5631
  token,
5984
- `${API7}/v1/agents/provision`,
5632
+ `${API6}/v1/agents/provision`,
5985
5633
  payload,
5986
5634
  "provision_agent"
5987
5635
  );
@@ -6001,7 +5649,7 @@ var phonyConnector = {
6001
5649
  const payload = { name };
6002
5650
  if (description !== void 0) payload.description = description;
6003
5651
  if (metadata !== void 0) payload.metadata = metadata;
6004
- const json = await postJson(inv, token, `${API7}/v1/collections`, payload, "kb_create_collection");
5652
+ const json = await postJson(inv, token, `${API6}/v1/collections`, payload, "kb_create_collection");
6005
5653
  return {
6006
5654
  status: "committed",
6007
5655
  data: { collection: json },
@@ -6015,7 +5663,7 @@ var phonyConnector = {
6015
5663
  const json = await postJson(
6016
5664
  inv,
6017
5665
  token,
6018
- `${API7}/v1/collections/${encodeURIComponent(collectionId)}/ingest`,
5666
+ `${API6}/v1/collections/${encodeURIComponent(collectionId)}/ingest`,
6019
5667
  payload,
6020
5668
  "kb_ingest"
6021
5669
  );
@@ -6035,7 +5683,7 @@ var phonyConnector = {
6035
5683
  async test(source) {
6036
5684
  try {
6037
5685
  const token = bearerToken(source.credentials);
6038
- const res = await fetch(`${API7}/v1/outbound?limit=1`, {
5686
+ const res = await fetch(`${API6}/v1/outbound?limit=1`, {
6039
5687
  headers: { authorization: `Bearer ${token}` },
6040
5688
  signal: AbortSignal.timeout(8e3)
6041
5689
  });
@@ -6180,9 +5828,9 @@ var INGEST_FIELDS = [
6180
5828
 
6181
5829
  // src/connectors/adapters/whatsapp-business.ts
6182
5830
  var SCOPES5 = ["whatsapp_business_messaging", "whatsapp_business_management", "business_management"];
6183
- var AUTH_URL9 = "https://www.facebook.com/v21.0/dialog/oauth";
6184
- var TOKEN_URL9 = "https://graph.facebook.com/v21.0/oauth/access_token";
6185
- var API8 = "https://graph.facebook.com/v21.0";
5831
+ var AUTH_URL8 = "https://www.facebook.com/v21.0/dialog/oauth";
5832
+ var TOKEN_URL8 = "https://graph.facebook.com/v21.0/oauth/access_token";
5833
+ var API7 = "https://graph.facebook.com/v21.0";
6186
5834
  function whatsappBusiness(opts) {
6187
5835
  const { clientId, clientSecret } = opts;
6188
5836
  const adapter = {
@@ -6192,8 +5840,8 @@ function whatsappBusiness(opts) {
6192
5840
  description: "Send text and template messages from a verified WhatsApp Business number, and read your approved message templates. Advisory surface \u2014 WhatsApp sends are append-only.",
6193
5841
  auth: {
6194
5842
  kind: "oauth2",
6195
- authorizationUrl: AUTH_URL9,
6196
- tokenUrl: TOKEN_URL9,
5843
+ authorizationUrl: AUTH_URL8,
5844
+ tokenUrl: TOKEN_URL8,
6197
5845
  scopes: SCOPES5,
6198
5846
  clientIdEnv: "WHATSAPP_BUSINESS_OAUTH_CLIENT_ID",
6199
5847
  clientSecretEnv: "WHATSAPP_BUSINESS_OAUTH_CLIENT_SECRET"
@@ -6330,12 +5978,12 @@ function whatsappBusiness(opts) {
6330
5978
  async executeRead(inv) {
6331
5979
  const accessToken = readAccessToken(inv.source.credentials);
6332
5980
  if (inv.capabilityName === "list_message_templates") {
6333
- const wabaId = readMetaString5(inv.source.metadata, "wabaId");
5981
+ const wabaId = readMetaString4(inv.source.metadata, "wabaId");
6334
5982
  const { limit, status } = inv.args;
6335
5983
  const params = new URLSearchParams();
6336
5984
  params.set("limit", String(Math.min(Math.max(1, limit ?? 50), 200)));
6337
5985
  if (status) params.set("status", status);
6338
- const url = `${API8}/${encodeURIComponent(wabaId)}/message_templates?${params.toString()}`;
5986
+ const url = `${API7}/${encodeURIComponent(wabaId)}/message_templates?${params.toString()}`;
6339
5987
  const json = await graphGet(url, accessToken, inv.source.id);
6340
5988
  const data = json.data ?? [];
6341
5989
  return {
@@ -6352,11 +6000,11 @@ function whatsappBusiness(opts) {
6352
6000
  };
6353
6001
  }
6354
6002
  if (inv.capabilityName === "get_business_phone_number") {
6355
- const phoneNumberId = readMetaString5(inv.source.metadata, "phoneNumberId");
6003
+ const phoneNumberId = readMetaString4(inv.source.metadata, "phoneNumberId");
6356
6004
  const params = new URLSearchParams({
6357
6005
  fields: "display_phone_number,verified_name,quality_rating,code_verification_status,platform_type"
6358
6006
  });
6359
- const url = `${API8}/${encodeURIComponent(phoneNumberId)}?${params.toString()}`;
6007
+ const url = `${API7}/${encodeURIComponent(phoneNumberId)}?${params.toString()}`;
6360
6008
  const json = await graphGet(url, accessToken, inv.source.id);
6361
6009
  return {
6362
6010
  data: {
@@ -6382,8 +6030,8 @@ function whatsappBusiness(opts) {
6382
6030
  if (inv.capabilityName === "templates.delete") {
6383
6031
  return deleteTemplate(inv, accessToken);
6384
6032
  }
6385
- const phoneNumberId = readMetaString5(inv.source.metadata, "phoneNumberId");
6386
- const url = `${API8}/${encodeURIComponent(phoneNumberId)}/messages`;
6033
+ const phoneNumberId = readMetaString4(inv.source.metadata, "phoneNumberId");
6034
+ const url = `${API7}/${encodeURIComponent(phoneNumberId)}/messages`;
6387
6035
  let body;
6388
6036
  if (inv.capabilityName === "send_text_message") {
6389
6037
  const { to, body: text, previewUrl } = inv.args;
@@ -6464,7 +6112,7 @@ function whatsappBusiness(opts) {
6464
6112
  throw new Error("WhatsApp Business OAuth client not configured (WHATSAPP_BUSINESS_OAUTH_CLIENT_ID / _SECRET)");
6465
6113
  }
6466
6114
  const tokens = await exchangeAuthorizationCode({
6467
- tokenUrl: TOKEN_URL9,
6115
+ tokenUrl: TOKEN_URL8,
6468
6116
  clientId,
6469
6117
  clientSecret,
6470
6118
  code: input.code,
@@ -6488,7 +6136,7 @@ function whatsappBusiness(opts) {
6488
6136
  try {
6489
6137
  const accessToken = readAccessToken(source.credentials);
6490
6138
  const phoneNumberId = typeof source.metadata.phoneNumberId === "string" ? source.metadata.phoneNumberId : void 0;
6491
- const probeUrl = phoneNumberId ? `${API8}/${encodeURIComponent(phoneNumberId)}?fields=display_phone_number` : `${API8}/me?fields=id`;
6139
+ const probeUrl = phoneNumberId ? `${API7}/${encodeURIComponent(phoneNumberId)}?fields=display_phone_number` : `${API7}/me?fields=id`;
6492
6140
  const res = await fetch(probeUrl, {
6493
6141
  headers: { authorization: `Bearer ${accessToken}` },
6494
6142
  signal: AbortSignal.timeout(8e3)
@@ -6512,7 +6160,7 @@ function readAccessToken(creds) {
6512
6160
  }
6513
6161
  return creds.accessToken;
6514
6162
  }
6515
- function readMetaString5(meta, key) {
6163
+ function readMetaString4(meta, key) {
6516
6164
  const v = meta[key];
6517
6165
  if (typeof v !== "string" || v.length === 0) {
6518
6166
  throw new Error(`whatsapp-business DataSource.metadata.${key} is missing \u2014 set it at connect-time from the Embedded Signup callback`);
@@ -6541,7 +6189,7 @@ function decodeBase64(value) {
6541
6189
  return bytes;
6542
6190
  }
6543
6191
  async function uploadMedia(inv, accessToken) {
6544
- const phoneNumberId = readMetaString5(inv.source.metadata, "phoneNumberId");
6192
+ const phoneNumberId = readMetaString4(inv.source.metadata, "phoneNumberId");
6545
6193
  const { dataBase64, mimeType, filename } = inv.args;
6546
6194
  if (typeof dataBase64 !== "string" || dataBase64.length === 0) {
6547
6195
  throw new Error("whatsapp-business media.upload: dataBase64 is required");
@@ -6554,7 +6202,7 @@ async function uploadMedia(inv, accessToken) {
6554
6202
  form.set("messaging_product", "whatsapp");
6555
6203
  form.set("type", mimeType);
6556
6204
  form.set("file", new Blob([bytes], { type: mimeType }), filename ?? "upload");
6557
- const url = `${API8}/${encodeURIComponent(phoneNumberId)}/media`;
6205
+ const url = `${API7}/${encodeURIComponent(phoneNumberId)}/media`;
6558
6206
  const res = await fetch(url, {
6559
6207
  method: "POST",
6560
6208
  headers: { authorization: `Bearer ${accessToken}` },
@@ -6577,7 +6225,7 @@ async function uploadMedia(inv, accessToken) {
6577
6225
  };
6578
6226
  }
6579
6227
  async function createTemplate(inv, accessToken) {
6580
- const wabaId = readMetaString5(inv.source.metadata, "wabaId");
6228
+ const wabaId = readMetaString4(inv.source.metadata, "wabaId");
6581
6229
  const { name, language, category, components } = inv.args;
6582
6230
  if (typeof name !== "string" || name.length === 0) {
6583
6231
  throw new Error("whatsapp-business templates.create: name is required");
@@ -6591,7 +6239,7 @@ async function createTemplate(inv, accessToken) {
6591
6239
  if (!Array.isArray(components)) {
6592
6240
  throw new Error("whatsapp-business templates.create: components must be an array");
6593
6241
  }
6594
- const url = `${API8}/${encodeURIComponent(wabaId)}/message_templates`;
6242
+ const url = `${API7}/${encodeURIComponent(wabaId)}/message_templates`;
6595
6243
  const res = await fetch(url, {
6596
6244
  method: "POST",
6597
6245
  headers: {
@@ -6617,7 +6265,7 @@ async function createTemplate(inv, accessToken) {
6617
6265
  };
6618
6266
  }
6619
6267
  async function deleteTemplate(inv, accessToken) {
6620
- const wabaId = readMetaString5(inv.source.metadata, "wabaId");
6268
+ const wabaId = readMetaString4(inv.source.metadata, "wabaId");
6621
6269
  const { name, hsmId } = inv.args;
6622
6270
  if (typeof name !== "string" || name.length === 0) {
6623
6271
  throw new Error("whatsapp-business templates.delete: name is required");
@@ -6625,7 +6273,7 @@ async function deleteTemplate(inv, accessToken) {
6625
6273
  const params = new URLSearchParams();
6626
6274
  params.set("name", name);
6627
6275
  if (typeof hsmId === "string" && hsmId.length > 0) params.set("hsm_id", hsmId);
6628
- const url = `${API8}/${encodeURIComponent(wabaId)}/message_templates?${params.toString()}`;
6276
+ const url = `${API7}/${encodeURIComponent(wabaId)}/message_templates?${params.toString()}`;
6629
6277
  const res = await fetch(url, {
6630
6278
  method: "DELETE",
6631
6279
  headers: { authorization: `Bearer ${accessToken}` },
@@ -6648,7 +6296,7 @@ async function deleteTemplate(inv, accessToken) {
6648
6296
  }
6649
6297
 
6650
6298
  // src/connectors/adapters/stripe-pack.ts
6651
- var API9 = "https://api.stripe.com/v1";
6299
+ var API8 = "https://api.stripe.com/v1";
6652
6300
  var stripePackConnector = {
6653
6301
  manifest: {
6654
6302
  kind: "stripe-pack",
@@ -6848,7 +6496,7 @@ var stripePackConnector = {
6848
6496
  throw new Error(`stripe-pack: unknown read capability ${inv.capabilityName}`);
6849
6497
  }
6850
6498
  const { email } = inv.args;
6851
- const url = `${API9}/customers/search?query=${encodeURIComponent(`email:'${email.toLowerCase()}'`)}&limit=1`;
6499
+ const url = `${API8}/customers/search?query=${encodeURIComponent(`email:'${email.toLowerCase()}'`)}&limit=1`;
6852
6500
  const res = await fetch(url, {
6853
6501
  headers: { authorization: `Bearer ${apiKey}` },
6854
6502
  signal: AbortSignal.timeout(1e4)
@@ -6881,7 +6529,7 @@ var stripePackConnector = {
6881
6529
  async test(source) {
6882
6530
  try {
6883
6531
  const apiKey = readApiKey(source.credentials);
6884
- const res = await fetch(`${API9}/account`, {
6532
+ const res = await fetch(`${API8}/account`, {
6885
6533
  headers: { authorization: `Bearer ${apiKey}` },
6886
6534
  signal: AbortSignal.timeout(8e3)
6887
6535
  });
@@ -6907,7 +6555,7 @@ async function createInvoice(inv, apiKey) {
6907
6555
  quantity: String(it.quantity ?? 1)
6908
6556
  });
6909
6557
  if (it.description) body.set("description", it.description);
6910
- const res = await fetch(`${API9}/invoiceitems`, {
6558
+ const res = await fetch(`${API8}/invoiceitems`, {
6911
6559
  method: "POST",
6912
6560
  headers: {
6913
6561
  authorization: `Bearer ${apiKey}`,
@@ -6932,7 +6580,7 @@ async function createInvoice(inv, apiKey) {
6932
6580
  collection_method: "send_invoice",
6933
6581
  days_until_due: "14"
6934
6582
  });
6935
- const invRes = await fetch(`${API9}/invoices`, {
6583
+ const invRes = await fetch(`${API8}/invoices`, {
6936
6584
  method: "POST",
6937
6585
  headers: {
6938
6586
  authorization: `Bearer ${apiKey}`,
@@ -6970,7 +6618,7 @@ async function createCheckoutSession(inv, apiKey) {
6970
6618
  body.set(`line_items[${i}][price]`, it.price);
6971
6619
  body.set(`line_items[${i}][quantity]`, String(it.quantity ?? 1));
6972
6620
  });
6973
- const res = await fetch(`${API9}/checkout/sessions`, {
6621
+ const res = await fetch(`${API8}/checkout/sessions`, {
6974
6622
  method: "POST",
6975
6623
  headers: {
6976
6624
  authorization: `Bearer ${apiKey}`,
@@ -7001,7 +6649,7 @@ async function listSubscriptions(inv, apiKey) {
7001
6649
  const params = new URLSearchParams({ customer: customerId, limit: String(limit ?? 10) });
7002
6650
  if (status && status !== "all") params.set("status", status);
7003
6651
  else params.set("status", "all");
7004
- const res = await fetch(`${API9}/subscriptions?${params.toString()}`, {
6652
+ const res = await fetch(`${API8}/subscriptions?${params.toString()}`, {
7005
6653
  headers: { authorization: `Bearer ${apiKey}` },
7006
6654
  signal: AbortSignal.timeout(1e4)
7007
6655
  });
@@ -7036,7 +6684,7 @@ async function cancelSubscription(inv, apiKey) {
7036
6684
  let res;
7037
6685
  if (atPeriodEnd) {
7038
6686
  const body = new URLSearchParams({ cancel_at_period_end: "true" });
7039
- res = await fetch(`${API9}/subscriptions/${encodeURIComponent(subscriptionId)}`, {
6687
+ res = await fetch(`${API8}/subscriptions/${encodeURIComponent(subscriptionId)}`, {
7040
6688
  method: "POST",
7041
6689
  headers: {
7042
6690
  authorization: `Bearer ${apiKey}`,
@@ -7047,7 +6695,7 @@ async function cancelSubscription(inv, apiKey) {
7047
6695
  signal: AbortSignal.timeout(15e3)
7048
6696
  });
7049
6697
  } else {
7050
- res = await fetch(`${API9}/subscriptions/${encodeURIComponent(subscriptionId)}`, {
6698
+ res = await fetch(`${API8}/subscriptions/${encodeURIComponent(subscriptionId)}`, {
7051
6699
  method: "DELETE",
7052
6700
  headers: {
7053
6701
  authorization: `Bearer ${apiKey}`,
@@ -7082,7 +6730,7 @@ async function cancelSubscription(inv, apiKey) {
7082
6730
  async function createBillingPortalSession(inv, apiKey) {
7083
6731
  const { customerId, returnUrl } = inv.args;
7084
6732
  const body = new URLSearchParams({ customer: customerId, return_url: returnUrl });
7085
- const res = await fetch(`${API9}/billing_portal/sessions`, {
6733
+ const res = await fetch(`${API8}/billing_portal/sessions`, {
7086
6734
  method: "POST",
7087
6735
  headers: {
7088
6736
  authorization: `Bearer ${apiKey}`,
@@ -7130,7 +6778,7 @@ async function createPaymentIntent(inv, apiKey) {
7130
6778
  body.set(`metadata[${k}]`, String(v));
7131
6779
  }
7132
6780
  }
7133
- const res = await fetch(`${API9}/payment_intents`, {
6781
+ const res = await fetch(`${API8}/payment_intents`, {
7134
6782
  method: "POST",
7135
6783
  headers: {
7136
6784
  authorization: `Bearer ${apiKey}`,
@@ -7178,7 +6826,7 @@ async function createRefund(inv, apiKey) {
7178
6826
  if (args.charge) body.set("charge", args.charge);
7179
6827
  if (typeof args.amount === "number") body.set("amount", String(args.amount));
7180
6828
  if (args.reason) body.set("reason", args.reason);
7181
- const res = await fetch(`${API9}/refunds`, {
6829
+ const res = await fetch(`${API8}/refunds`, {
7182
6830
  method: "POST",
7183
6831
  headers: {
7184
6832
  authorization: `Bearer ${apiKey}`,
@@ -7226,7 +6874,7 @@ async function createCustomer(inv, apiKey) {
7226
6874
  body.set(`metadata[${k}]`, String(v));
7227
6875
  }
7228
6876
  }
7229
- const res = await fetch(`${API9}/customers`, {
6877
+ const res = await fetch(`${API8}/customers`, {
7230
6878
  method: "POST",
7231
6879
  headers: {
7232
6880
  authorization: `Bearer ${apiKey}`,
@@ -7302,7 +6950,7 @@ var webhookConnector = {
7302
6950
  ]
7303
6951
  },
7304
6952
  async executeRead(inv) {
7305
- const url = readMetaString6(inv.source.metadata, "url");
6953
+ const url = readMetaString5(inv.source.metadata, "url");
7306
6954
  const params = inv.args && typeof inv.args === "object" ? inv.args : {};
7307
6955
  const u = new URL(url);
7308
6956
  for (const [k, v] of Object.entries(params)) {
@@ -7324,7 +6972,7 @@ var webhookConnector = {
7324
6972
  };
7325
6973
  },
7326
6974
  async executeMutation(inv) {
7327
- const url = readMetaString6(inv.source.metadata, "url");
6975
+ const url = readMetaString5(inv.source.metadata, "url");
7328
6976
  const body = JSON.stringify(inv.args ?? {});
7329
6977
  const res = await fetch(url, {
7330
6978
  method: "POST",
@@ -7354,7 +7002,7 @@ var webhookConnector = {
7354
7002
  },
7355
7003
  async test(source) {
7356
7004
  try {
7357
- const url = readMetaString6(source.metadata, "url");
7005
+ const url = readMetaString5(source.metadata, "url");
7358
7006
  const res = await fetch(url, {
7359
7007
  method: "HEAD",
7360
7008
  headers: signHeaders(source.credentials, "", `health-${Date.now()}`),
@@ -7367,7 +7015,7 @@ var webhookConnector = {
7367
7015
  }
7368
7016
  }
7369
7017
  };
7370
- function readMetaString6(meta, key) {
7018
+ function readMetaString5(meta, key) {
7371
7019
  const v = meta[key];
7372
7020
  if (typeof v !== "string" || v.length === 0) {
7373
7021
  throw new Error(`webhook DataSource.metadata.${key} is missing`);
@@ -37415,8 +37063,8 @@ var SCOPES7 = [
37415
37063
  "request_signature",
37416
37064
  "signature_request_access"
37417
37065
  ];
37418
- var AUTH_URL10 = "https://app.hellosign.com/oauth/authorize";
37419
- var TOKEN_URL10 = "https://app.hellosign.com/oauth/token";
37066
+ var AUTH_URL9 = "https://app.hellosign.com/oauth/authorize";
37067
+ var TOKEN_URL9 = "https://app.hellosign.com/oauth/token";
37420
37068
  var DEFAULT_API_BASE = "https://api.hellosign.com/v3";
37421
37069
  function hellosign(opts) {
37422
37070
  const { clientId, clientSecret } = opts;
@@ -37429,8 +37077,8 @@ function hellosign(opts) {
37429
37077
  description: "Send documents for e-signature via Dropbox Sign templates, poll signature-request status, cancel in-flight requests, and react to push events when signers complete.",
37430
37078
  auth: {
37431
37079
  kind: "oauth2",
37432
- authorizationUrl: AUTH_URL10,
37433
- tokenUrl: TOKEN_URL10,
37080
+ authorizationUrl: AUTH_URL9,
37081
+ tokenUrl: TOKEN_URL9,
37434
37082
  scopes: SCOPES7,
37435
37083
  clientIdEnv: "HELLOSIGN_OAUTH_CLIENT_ID",
37436
37084
  clientSecretEnv: "HELLOSIGN_OAUTH_CLIENT_SECRET",
@@ -37587,7 +37235,7 @@ function hellosign(opts) {
37587
37235
  throw new Error("Dropbox Sign OAuth client not configured (HELLOSIGN_OAUTH_CLIENT_ID / _SECRET)");
37588
37236
  }
37589
37237
  const tokens = await exchangeAuthorizationCode({
37590
- tokenUrl: TOKEN_URL10,
37238
+ tokenUrl: TOKEN_URL9,
37591
37239
  clientId,
37592
37240
  clientSecret,
37593
37241
  code: input.code,
@@ -37610,7 +37258,7 @@ function hellosign(opts) {
37610
37258
  throw new Error("hellosign.refreshToken: missing refresh token");
37611
37259
  }
37612
37260
  const refreshed = await refreshAccessToken({
37613
- tokenUrl: TOKEN_URL10,
37261
+ tokenUrl: TOKEN_URL9,
37614
37262
  clientId,
37615
37263
  clientSecret,
37616
37264
  refreshToken: creds.refreshToken
@@ -37901,7 +37549,7 @@ async function ensureFreshAccessToken7(creds, clientId, clientSecret, inv) {
37901
37549
  throw new CredentialsExpired("Dropbox Sign access token expired and no refresh token", inv?.source.id ?? "");
37902
37550
  }
37903
37551
  const refreshed = await refreshAccessToken({
37904
- tokenUrl: TOKEN_URL10,
37552
+ tokenUrl: TOKEN_URL9,
37905
37553
  clientId,
37906
37554
  clientSecret,
37907
37555
  refreshToken: creds.refreshToken
@@ -37920,12 +37568,12 @@ async function ensureFreshAccessToken7(creds, clientId, clientSecret, inv) {
37920
37568
 
37921
37569
  // src/connectors/adapters/pandadoc.ts
37922
37570
  var SCOPES8 = ["read", "read+write"];
37923
- var AUTH_URL11 = "https://app.pandadoc.com/oauth2/authorize";
37924
- var TOKEN_URL11 = "https://api.pandadoc.com/oauth2/access_token";
37925
- var API10 = "https://api.pandadoc.com/public/v1";
37571
+ var AUTH_URL10 = "https://app.pandadoc.com/oauth2/authorize";
37572
+ var TOKEN_URL10 = "https://api.pandadoc.com/oauth2/access_token";
37573
+ var API9 = "https://api.pandadoc.com/public/v1";
37926
37574
  function pandadoc(opts) {
37927
37575
  const { clientId, clientSecret } = opts;
37928
- const baseUrl = (opts.baseUrl ?? API10).replace(/\/$/, "");
37576
+ const baseUrl = (opts.baseUrl ?? API9).replace(/\/$/, "");
37929
37577
  const timeoutMs = opts.timeoutMs ?? 3e4;
37930
37578
  const adapter = {
37931
37579
  manifest: {
@@ -37934,8 +37582,8 @@ function pandadoc(opts) {
37934
37582
  description: "Draft contracts and proposals from PandaDoc templates, send them for signature, poll signing status, and cancel in-flight documents.",
37935
37583
  auth: {
37936
37584
  kind: "oauth2",
37937
- authorizationUrl: AUTH_URL11,
37938
- tokenUrl: TOKEN_URL11,
37585
+ authorizationUrl: AUTH_URL10,
37586
+ tokenUrl: TOKEN_URL10,
37939
37587
  scopes: SCOPES8,
37940
37588
  clientIdEnv: "PANDADOC_OAUTH_CLIENT_ID",
37941
37589
  clientSecretEnv: "PANDADOC_OAUTH_CLIENT_SECRET"
@@ -38083,7 +37731,7 @@ function pandadoc(opts) {
38083
37731
  throw new Error("PandaDoc OAuth client not configured (PANDADOC_OAUTH_CLIENT_ID / _SECRET)");
38084
37732
  }
38085
37733
  const tokens = await exchangeAuthorizationCode({
38086
- tokenUrl: TOKEN_URL11,
37734
+ tokenUrl: TOKEN_URL10,
38087
37735
  clientId,
38088
37736
  clientSecret,
38089
37737
  code: input.code,
@@ -38106,7 +37754,7 @@ function pandadoc(opts) {
38106
37754
  throw new Error("pandadoc.refreshToken: missing refresh token");
38107
37755
  }
38108
37756
  const refreshed = await refreshAccessToken({
38109
- tokenUrl: TOKEN_URL11,
37757
+ tokenUrl: TOKEN_URL10,
38110
37758
  clientId,
38111
37759
  clientSecret,
38112
37760
  refreshToken: creds.refreshToken
@@ -38414,7 +38062,7 @@ async function ensureFreshAccessTokenFromCreds(creds, clientId, clientSecret, on
38414
38062
  throw new CredentialsExpired("PandaDoc access token expired and no refresh token", "");
38415
38063
  }
38416
38064
  const refreshed = await refreshAccessToken({
38417
- tokenUrl: TOKEN_URL11,
38065
+ tokenUrl: TOKEN_URL10,
38418
38066
  clientId,
38419
38067
  clientSecret,
38420
38068
  refreshToken: creds.refreshToken
@@ -38438,9 +38086,9 @@ var SCOPES9 = [
38438
38086
  "https://www.googleapis.com/auth/documents",
38439
38087
  "https://www.googleapis.com/auth/drive.file"
38440
38088
  ];
38441
- var AUTH_URL12 = "https://accounts.google.com/o/oauth2/v2/auth";
38442
- var TOKEN_URL12 = "https://oauth2.googleapis.com/token";
38443
- var API11 = "https://docs.googleapis.com/v1";
38089
+ var AUTH_URL11 = "https://accounts.google.com/o/oauth2/v2/auth";
38090
+ var TOKEN_URL11 = "https://oauth2.googleapis.com/token";
38091
+ var API10 = "https://docs.googleapis.com/v1";
38444
38092
  var DRIVE_API = "https://www.googleapis.com/drive/v3";
38445
38093
  var EXPORT_MIME = {
38446
38094
  pdf: "application/pdf",
@@ -38464,8 +38112,8 @@ function googleDocs(opts) {
38464
38112
  description: "Read and draft into the user's Google Docs. Fetch a document's plaintext body, create a new doc from a title + initial body, and append text with optional revision-id CAS guarding concurrent edits.",
38465
38113
  auth: {
38466
38114
  kind: "oauth2",
38467
- authorizationUrl: AUTH_URL12,
38468
- tokenUrl: TOKEN_URL12,
38115
+ authorizationUrl: AUTH_URL11,
38116
+ tokenUrl: TOKEN_URL11,
38469
38117
  scopes: SCOPES9,
38470
38118
  clientIdEnv: "GOOGLE_OAUTH_CLIENT_ID",
38471
38119
  clientSecretEnv: "GOOGLE_OAUTH_CLIENT_SECRET",
@@ -38579,7 +38227,7 @@ function googleDocs(opts) {
38579
38227
  throw new Error("Google OAuth client not configured (GOOGLE_OAUTH_CLIENT_ID / _SECRET)");
38580
38228
  }
38581
38229
  const tokens = await exchangeAuthorizationCode({
38582
- tokenUrl: TOKEN_URL12,
38230
+ tokenUrl: TOKEN_URL11,
38583
38231
  clientId,
38584
38232
  clientSecret,
38585
38233
  code: input.code,
@@ -38602,7 +38250,7 @@ function googleDocs(opts) {
38602
38250
  throw new Error("google-docs.refreshToken: missing refresh token");
38603
38251
  }
38604
38252
  const refreshed = await refreshAccessToken({
38605
- tokenUrl: TOKEN_URL12,
38253
+ tokenUrl: TOKEN_URL11,
38606
38254
  clientId,
38607
38255
  clientSecret,
38608
38256
  refreshToken: creds.refreshToken
@@ -38656,7 +38304,7 @@ function findAppendIndex(doc) {
38656
38304
  }
38657
38305
  async function getDocument2(inv, accessToken, timeoutMs) {
38658
38306
  const { documentId } = inv.args ?? {};
38659
- const res = await fetch(`${API11}/documents/${encodeURIComponent(documentId)}`, {
38307
+ const res = await fetch(`${API10}/documents/${encodeURIComponent(documentId)}`, {
38660
38308
  headers: { authorization: `Bearer ${accessToken}` },
38661
38309
  signal: AbortSignal.timeout(timeoutMs)
38662
38310
  });
@@ -38690,7 +38338,7 @@ async function createDocument2(inv, accessToken, timeoutMs) {
38690
38338
  if (!title || typeof title !== "string") {
38691
38339
  throw new Error("google-docs create_document: title is required");
38692
38340
  }
38693
- const createRes = await fetch(`${API11}/documents`, {
38341
+ const createRes = await fetch(`${API10}/documents`, {
38694
38342
  method: "POST",
38695
38343
  headers: {
38696
38344
  authorization: `Bearer ${accessToken}`,
@@ -38710,7 +38358,7 @@ async function createDocument2(inv, accessToken, timeoutMs) {
38710
38358
  let revisionId = created.revisionId;
38711
38359
  if (typeof body === "string" && body.length > 0) {
38712
38360
  const insertRes = await fetch(
38713
- `${API11}/documents/${encodeURIComponent(created.documentId)}:batchUpdate`,
38361
+ `${API10}/documents/${encodeURIComponent(created.documentId)}:batchUpdate`,
38714
38362
  {
38715
38363
  method: "POST",
38716
38364
  headers: {
@@ -38753,7 +38401,7 @@ async function appendText(inv, accessToken, timeoutMs) {
38753
38401
  if (!text) {
38754
38402
  throw new Error("google-docs append_text: text is required");
38755
38403
  }
38756
- const docRes = await fetch(`${API11}/documents/${encodeURIComponent(documentId)}?fields=documentId,revisionId,body(content(endIndex))`, {
38404
+ const docRes = await fetch(`${API10}/documents/${encodeURIComponent(documentId)}?fields=documentId,revisionId,body(content(endIndex))`, {
38757
38405
  headers: { authorization: `Bearer ${accessToken}` },
38758
38406
  signal: AbortSignal.timeout(timeoutMs)
38759
38407
  });
@@ -38783,7 +38431,7 @@ async function appendText(inv, accessToken, timeoutMs) {
38783
38431
  body.writeControl = { requiredRevisionId };
38784
38432
  }
38785
38433
  const res = await fetch(
38786
- `${API11}/documents/${encodeURIComponent(documentId)}:batchUpdate`,
38434
+ `${API10}/documents/${encodeURIComponent(documentId)}:batchUpdate`,
38787
38435
  {
38788
38436
  method: "POST",
38789
38437
  headers: {
@@ -38904,7 +38552,7 @@ async function ensureFreshAccessToken9(creds, clientId, clientSecret) {
38904
38552
  throw new CredentialsExpired("Google Docs access token expired and no refresh token", "");
38905
38553
  }
38906
38554
  const refreshed = await refreshAccessToken({
38907
- tokenUrl: TOKEN_URL12,
38555
+ tokenUrl: TOKEN_URL11,
38908
38556
  clientId,
38909
38557
  clientSecret,
38910
38558
  refreshToken: creds.refreshToken
@@ -38922,9 +38570,9 @@ var SCOPES10 = [
38922
38570
  "https://www.googleapis.com/auth/forms.responses.readonly",
38923
38571
  SCOPE_WRITE3
38924
38572
  ];
38925
- var AUTH_URL13 = "https://accounts.google.com/o/oauth2/v2/auth";
38926
- var TOKEN_URL13 = "https://oauth2.googleapis.com/token";
38927
- var API12 = "https://forms.googleapis.com/v1";
38573
+ var AUTH_URL12 = "https://accounts.google.com/o/oauth2/v2/auth";
38574
+ var TOKEN_URL12 = "https://oauth2.googleapis.com/token";
38575
+ var API11 = "https://forms.googleapis.com/v1";
38928
38576
  function googleForms(opts) {
38929
38577
  const { clientId, clientSecret } = opts;
38930
38578
  const timeoutMs = opts.timeoutMs ?? 3e4;
@@ -38935,8 +38583,8 @@ function googleForms(opts) {
38935
38583
  description: "Read a Google Form's schema and paginate its responses for KB ingest, lead routing, or analytics. Returns answers keyed by questionId with the original item tree available for question\u2192title joins.",
38936
38584
  auth: {
38937
38585
  kind: "oauth2",
38938
- authorizationUrl: AUTH_URL13,
38939
- tokenUrl: TOKEN_URL13,
38586
+ authorizationUrl: AUTH_URL12,
38587
+ tokenUrl: TOKEN_URL12,
38940
38588
  scopes: SCOPES10,
38941
38589
  clientIdEnv: "GOOGLE_OAUTH_CLIENT_ID",
38942
38590
  clientSecretEnv: "GOOGLE_OAUTH_CLIENT_SECRET",
@@ -39080,7 +38728,7 @@ function googleForms(opts) {
39080
38728
  throw new Error("Google OAuth client not configured (GOOGLE_OAUTH_CLIENT_ID / _SECRET)");
39081
38729
  }
39082
38730
  const tokens = await exchangeAuthorizationCode({
39083
- tokenUrl: TOKEN_URL13,
38731
+ tokenUrl: TOKEN_URL12,
39084
38732
  clientId,
39085
38733
  clientSecret,
39086
38734
  code: input.code,
@@ -39103,7 +38751,7 @@ function googleForms(opts) {
39103
38751
  throw new Error("google-forms.refreshToken: missing refresh token");
39104
38752
  }
39105
38753
  const refreshed = await refreshAccessToken({
39106
- tokenUrl: TOKEN_URL13,
38754
+ tokenUrl: TOKEN_URL12,
39107
38755
  clientId,
39108
38756
  clientSecret,
39109
38757
  refreshToken: creds.refreshToken
@@ -39149,7 +38797,7 @@ function flattenAnswers(answers) {
39149
38797
  async function getForm(inv, accessToken, timeoutMs) {
39150
38798
  const { formId } = inv.args ?? {};
39151
38799
  if (!formId) throw new Error("google-forms get_form: formId is required");
39152
- const res = await fetch(`${API12}/forms/${encodeURIComponent(formId)}`, {
38800
+ const res = await fetch(`${API11}/forms/${encodeURIComponent(formId)}`, {
39153
38801
  headers: { authorization: `Bearer ${accessToken}` },
39154
38802
  signal: AbortSignal.timeout(timeoutMs)
39155
38803
  });
@@ -39184,7 +38832,7 @@ async function listResponses(inv, accessToken, timeoutMs) {
39184
38832
  if (pageToken) params.set("pageToken", pageToken);
39185
38833
  if (filter) params.set("filter", filter);
39186
38834
  const qs = params.toString();
39187
- const url = `${API12}/forms/${encodeURIComponent(formId)}/responses${qs ? `?${qs}` : ""}`;
38835
+ const url = `${API11}/forms/${encodeURIComponent(formId)}/responses${qs ? `?${qs}` : ""}`;
39188
38836
  const res = await fetch(url, {
39189
38837
  headers: { authorization: `Bearer ${accessToken}` },
39190
38838
  signal: AbortSignal.timeout(timeoutMs)
@@ -39221,7 +38869,7 @@ async function getResponse(inv, accessToken, timeoutMs) {
39221
38869
  if (!formId) throw new Error("google-forms get_response: formId is required");
39222
38870
  if (!responseId) throw new Error("google-forms get_response: responseId is required");
39223
38871
  const res = await fetch(
39224
- `${API12}/forms/${encodeURIComponent(formId)}/responses/${encodeURIComponent(responseId)}`,
38872
+ `${API11}/forms/${encodeURIComponent(formId)}/responses/${encodeURIComponent(responseId)}`,
39225
38873
  {
39226
38874
  headers: { authorization: `Bearer ${accessToken}` },
39227
38875
  signal: AbortSignal.timeout(timeoutMs)
@@ -39255,7 +38903,7 @@ async function createForm(inv, accessToken, timeoutMs) {
39255
38903
  if (!title) throw new Error("google-forms create_form: title is required");
39256
38904
  const info = { title };
39257
38905
  if (documentTitle) info.documentTitle = documentTitle;
39258
- const res = await fetch(`${API12}/forms`, {
38906
+ const res = await fetch(`${API11}/forms`, {
39259
38907
  method: "POST",
39260
38908
  headers: {
39261
38909
  authorization: `Bearer ${accessToken}`,
@@ -39294,7 +38942,7 @@ async function batchUpdate(inv, accessToken, timeoutMs) {
39294
38942
  const body = { requests };
39295
38943
  if (typeof includeFormInResponse === "boolean") body.includeFormInResponse = includeFormInResponse;
39296
38944
  if (writeControl) body.writeControl = writeControl;
39297
- const res = await fetch(`${API12}/forms/${encodeURIComponent(formId)}:batchUpdate`, {
38945
+ const res = await fetch(`${API11}/forms/${encodeURIComponent(formId)}:batchUpdate`, {
39298
38946
  method: "POST",
39299
38947
  headers: {
39300
38948
  authorization: `Bearer ${accessToken}`,
@@ -39334,7 +38982,7 @@ async function ensureFreshAccessToken10(creds, clientId, clientSecret) {
39334
38982
  throw new CredentialsExpired("Google Forms access token expired and no refresh token", "");
39335
38983
  }
39336
38984
  const refreshed = await refreshAccessToken({
39337
- tokenUrl: TOKEN_URL13,
38985
+ tokenUrl: TOKEN_URL12,
39338
38986
  clientId,
39339
38987
  clientSecret,
39340
38988
  refreshToken: creds.refreshToken
@@ -39355,8 +39003,8 @@ var SCOPES11 = [
39355
39003
  // offline_access is required on v2.0 to receive a refresh_token.
39356
39004
  "offline_access"
39357
39005
  ];
39358
- var AUTH_URL14 = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize";
39359
- var TOKEN_URL14 = "https://login.microsoftonline.com/common/oauth2/v2.0/token";
39006
+ var AUTH_URL13 = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize";
39007
+ var TOKEN_URL13 = "https://login.microsoftonline.com/common/oauth2/v2.0/token";
39360
39008
  var GRAPH = "https://graph.microsoft.com/v1.0";
39361
39009
  function microsoftGraph(opts) {
39362
39010
  const { clientId, clientSecret } = opts;
@@ -39367,8 +39015,8 @@ function microsoftGraph(opts) {
39367
39015
  description: "Query the Microsoft 365 directory \u2014 look up users by email, list organizations, enumerate groups, and resolve group membership. Read-only identity surface shared across the Outlook, Teams, SharePoint, and OneDrive adapters.",
39368
39016
  auth: {
39369
39017
  kind: "oauth2",
39370
- authorizationUrl: AUTH_URL14,
39371
- tokenUrl: TOKEN_URL14,
39018
+ authorizationUrl: AUTH_URL13,
39019
+ tokenUrl: TOKEN_URL13,
39372
39020
  scopes: SCOPES11,
39373
39021
  clientIdEnv: "MS_OAUTH_CLIENT_ID",
39374
39022
  clientSecretEnv: "MS_OAUTH_CLIENT_SECRET"
@@ -39553,7 +39201,7 @@ function microsoftGraph(opts) {
39553
39201
  throw new Error("Microsoft OAuth client not configured (MS_OAUTH_CLIENT_ID / _SECRET)");
39554
39202
  }
39555
39203
  const tokens = await exchangeAuthorizationCode({
39556
- tokenUrl: TOKEN_URL14,
39204
+ tokenUrl: TOKEN_URL13,
39557
39205
  clientId,
39558
39206
  clientSecret,
39559
39207
  code: input.code,
@@ -39576,7 +39224,7 @@ function microsoftGraph(opts) {
39576
39224
  throw new Error("microsoft-graph.refreshToken: missing refresh token");
39577
39225
  }
39578
39226
  const refreshed = await refreshAccessToken({
39579
- tokenUrl: TOKEN_URL14,
39227
+ tokenUrl: TOKEN_URL13,
39580
39228
  clientId,
39581
39229
  clientSecret,
39582
39230
  refreshToken: creds.refreshToken
@@ -39618,7 +39266,7 @@ async function ensureFreshAccessToken11(creds, clientId, clientSecret) {
39618
39266
  throw new CredentialsExpired("Microsoft Graph access token expired and no refresh token", "");
39619
39267
  }
39620
39268
  const refreshed = await refreshAccessToken({
39621
- tokenUrl: TOKEN_URL14,
39269
+ tokenUrl: TOKEN_URL13,
39622
39270
  clientId,
39623
39271
  clientSecret,
39624
39272
  refreshToken: creds.refreshToken
@@ -39655,9 +39303,9 @@ var SCOPE_READ2 = "https://graph.microsoft.com/Mail.Read";
39655
39303
  var SCOPE_SEND2 = "https://graph.microsoft.com/Mail.Send";
39656
39304
  var SCOPE_RW = "https://graph.microsoft.com/Mail.ReadWrite";
39657
39305
  var SCOPE_OFFLINE = "offline_access";
39658
- var AUTH_URL15 = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize";
39659
- var TOKEN_URL15 = "https://login.microsoftonline.com/common/oauth2/v2.0/token";
39660
- var API13 = "https://graph.microsoft.com/v1.0";
39306
+ var AUTH_URL14 = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize";
39307
+ var TOKEN_URL14 = "https://login.microsoftonline.com/common/oauth2/v2.0/token";
39308
+ var API12 = "https://graph.microsoft.com/v1.0";
39661
39309
  function outlookMail(opts) {
39662
39310
  const { clientId, clientSecret } = opts;
39663
39311
  const timeoutMs = opts.timeoutMs ?? 3e4;
@@ -39669,8 +39317,8 @@ function outlookMail(opts) {
39669
39317
  description: "Read inbox messages from a Microsoft 365 / Outlook mailbox, fetch a single message with body + attachment manifest, reply on a conversation, and subscribe to a folder for new mail webhooks.",
39670
39318
  auth: {
39671
39319
  kind: "oauth2",
39672
- authorizationUrl: AUTH_URL15,
39673
- tokenUrl: TOKEN_URL15,
39320
+ authorizationUrl: AUTH_URL14,
39321
+ tokenUrl: TOKEN_URL14,
39674
39322
  scopes,
39675
39323
  clientIdEnv: "MS_OAUTH_CLIENT_ID",
39676
39324
  clientSecretEnv: "MS_OAUTH_CLIENT_SECRET"
@@ -39754,6 +39402,19 @@ function outlookMail(opts) {
39754
39402
  type: "boolean",
39755
39403
  default: false,
39756
39404
  description: "When true, set Graph body.contentType=HTML and send body as HTML; otherwise text. Graph does NOT auto-derive a plain alternative \u2014 set html only when the body is HTML."
39405
+ },
39406
+ attachments: {
39407
+ type: "array",
39408
+ description: "Optional file attachments. Each item is { name, contentType?, contentBytes } where contentBytes is base64-encoded file data. Sent as Graph #microsoft.graph.fileAttachment entries.",
39409
+ items: {
39410
+ type: "object",
39411
+ properties: {
39412
+ name: { type: "string" },
39413
+ contentType: { type: "string" },
39414
+ contentBytes: { type: "string", description: "Base64-encoded attachment bytes." }
39415
+ },
39416
+ required: ["name", "contentBytes"]
39417
+ }
39757
39418
  }
39758
39419
  },
39759
39420
  required: ["to", "subject", "body"]
@@ -39784,6 +39445,19 @@ function outlookMail(opts) {
39784
39445
  type: "boolean",
39785
39446
  default: false,
39786
39447
  description: "When true, set Graph body.contentType=HTML; otherwise text."
39448
+ },
39449
+ attachments: {
39450
+ type: "array",
39451
+ description: "Optional file attachments. Each item is { name, contentType?, contentBytes } where contentBytes is base64-encoded file data. Stored as Graph #microsoft.graph.fileAttachment entries on the draft.",
39452
+ items: {
39453
+ type: "object",
39454
+ properties: {
39455
+ name: { type: "string" },
39456
+ contentType: { type: "string" },
39457
+ contentBytes: { type: "string", description: "Base64-encoded attachment bytes." }
39458
+ },
39459
+ required: ["name", "contentBytes"]
39460
+ }
39787
39461
  }
39788
39462
  },
39789
39463
  required: ["to", "subject", "body"]
@@ -39806,6 +39480,94 @@ function outlookMail(opts) {
39806
39480
  },
39807
39481
  required: ["notificationUrl"]
39808
39482
  }
39483
+ },
39484
+ {
39485
+ name: "forward_message",
39486
+ class: "mutation",
39487
+ description: "Forward an existing message to one or more recipients with an optional comment. Graph POST /me/messages/{id}/forward.",
39488
+ cas: "native-idempotency",
39489
+ externalEffect: true,
39490
+ requiredScopes: [SCOPE_SEND2],
39491
+ parameters: {
39492
+ type: "object",
39493
+ properties: {
39494
+ messageId: { type: "string", description: "Graph message id to forward." },
39495
+ to: {
39496
+ oneOf: [
39497
+ { type: "string" },
39498
+ { type: "array", items: { type: "string" } }
39499
+ ],
39500
+ description: "Recipient address(es). String OR array of strings."
39501
+ },
39502
+ comment: { type: "string", description: "Optional comment prepended to the forwarded body." }
39503
+ },
39504
+ required: ["messageId", "to"]
39505
+ }
39506
+ },
39507
+ {
39508
+ name: "move_message",
39509
+ class: "mutation",
39510
+ description: "Move a message to a destination mail folder by id (or well-known name like inbox/archive). Graph POST /me/messages/{id}/move; returns the relocated message (new id).",
39511
+ cas: "native-idempotency",
39512
+ externalEffect: true,
39513
+ requiredScopes: [SCOPE_RW],
39514
+ parameters: {
39515
+ type: "object",
39516
+ properties: {
39517
+ messageId: { type: "string", description: "Graph message id to move." },
39518
+ destinationId: { type: "string", description: "Destination folder id or well-known name (inbox, archive, deleteditems, ...)." }
39519
+ },
39520
+ required: ["messageId", "destinationId"]
39521
+ }
39522
+ },
39523
+ {
39524
+ name: "set_labels",
39525
+ class: "mutation",
39526
+ description: "Set the full set of Outlook categories (labels) on a message. Graph PATCH /me/messages/{id} replaces the categories array, so supply the complete desired set (the caller computes adds/removes against the current set).",
39527
+ cas: "optimistic-read-verify",
39528
+ externalEffect: false,
39529
+ requiredScopes: [SCOPE_RW],
39530
+ parameters: {
39531
+ type: "object",
39532
+ properties: {
39533
+ messageId: { type: "string", description: "Graph message id to tag." },
39534
+ categories: {
39535
+ type: "array",
39536
+ items: { type: "string" },
39537
+ description: "Full desired category set. Graph replaces (not merges) the categories array."
39538
+ }
39539
+ },
39540
+ required: ["messageId", "categories"]
39541
+ }
39542
+ },
39543
+ {
39544
+ name: "send_draft",
39545
+ class: "mutation",
39546
+ description: "Send a previously created draft message by id. Graph POST /me/messages/{id}/send. Pairs with create_draft.",
39547
+ cas: "native-idempotency",
39548
+ externalEffect: true,
39549
+ requiredScopes: [SCOPE_SEND2],
39550
+ parameters: {
39551
+ type: "object",
39552
+ properties: {
39553
+ messageId: { type: "string", description: "Graph draft message id to send." }
39554
+ },
39555
+ required: ["messageId"]
39556
+ }
39557
+ },
39558
+ {
39559
+ name: "download_attachment",
39560
+ class: "read",
39561
+ description: "Read an attachment record for a message including base64 contentBytes for file attachments. Graph GET /me/messages/{messageId}/attachments/{attachmentId}. Fills the attachment-bytes gap that read_message defers.",
39562
+ requiredScopes: [SCOPE_READ2],
39563
+ parameters: {
39564
+ type: "object",
39565
+ properties: {
39566
+ messageId: { type: "string", description: "Graph message id owning the attachment." },
39567
+ attachmentId: { type: "string", description: "Graph attachment id (from read_message attachments[].id)." }
39568
+ },
39569
+ required: ["messageId", "attachmentId"]
39570
+ }
39809
39571
  }
39810
39572
  ]
39811
39573
  },
@@ -39813,6 +39575,7 @@ function outlookMail(opts) {
39813
39575
  const accessToken = await ensureFreshAccessToken12(inv.source.credentials, clientId, clientSecret, inv.onCredentialsRotated);
39814
39576
  if (inv.capabilityName === "list_messages") return listMessages2(inv, accessToken, timeoutMs);
39815
39577
  if (inv.capabilityName === "read_message") return readMessage2(inv, accessToken, timeoutMs);
39578
+ if (inv.capabilityName === "download_attachment") return downloadAttachment(inv, accessToken, timeoutMs);
39816
39579
  throw new Error(`outlook-mail: unknown read capability ${inv.capabilityName}`);
39817
39580
  },
39818
39581
  async executeMutation(inv) {
@@ -39821,6 +39584,10 @@ function outlookMail(opts) {
39821
39584
  if (inv.capabilityName === "send_message") return sendMessage(inv, accessToken, timeoutMs);
39822
39585
  if (inv.capabilityName === "create_draft") return createDraft(inv, accessToken, timeoutMs);
39823
39586
  if (inv.capabilityName === "subscribe_folder") return subscribeFolder(inv, accessToken, timeoutMs);
39587
+ if (inv.capabilityName === "forward_message") return forwardMessage(inv, accessToken, timeoutMs);
39588
+ if (inv.capabilityName === "move_message") return moveMessage(inv, accessToken, timeoutMs);
39589
+ if (inv.capabilityName === "set_labels") return setLabels(inv, accessToken, timeoutMs);
39590
+ if (inv.capabilityName === "send_draft") return sendDraft(inv, accessToken, timeoutMs);
39824
39591
  throw new Error(`outlook-mail: unknown mutation capability ${inv.capabilityName}`);
39825
39592
  },
39826
39593
  async exchangeOAuth(input) {
@@ -39828,7 +39595,7 @@ function outlookMail(opts) {
39828
39595
  throw new Error("Outlook Mail OAuth client not configured (MS_OAUTH_CLIENT_ID / _SECRET)");
39829
39596
  }
39830
39597
  const tokens = await exchangeAuthorizationCode({
39831
- tokenUrl: TOKEN_URL15,
39598
+ tokenUrl: TOKEN_URL14,
39832
39599
  clientId,
39833
39600
  clientSecret,
39834
39601
  code: input.code,
@@ -39851,7 +39618,7 @@ function outlookMail(opts) {
39851
39618
  throw new Error("outlook-mail.refreshToken: missing refresh token");
39852
39619
  }
39853
39620
  const refreshed = await refreshAccessToken({
39854
- tokenUrl: TOKEN_URL15,
39621
+ tokenUrl: TOKEN_URL14,
39855
39622
  clientId,
39856
39623
  clientSecret,
39857
39624
  refreshToken: creds.refreshToken
@@ -39866,7 +39633,7 @@ function outlookMail(opts) {
39866
39633
  async test(source) {
39867
39634
  try {
39868
39635
  const accessToken = await ensureFreshAccessToken12(source.credentials, clientId, clientSecret);
39869
- const res = await fetch(`${API13}/me?$select=id,userPrincipalName`, {
39636
+ const res = await fetch(`${API12}/me?$select=id,userPrincipalName`, {
39870
39637
  headers: { authorization: `Bearer ${accessToken}` },
39871
39638
  signal: AbortSignal.timeout(8e3)
39872
39639
  });
@@ -39894,7 +39661,7 @@ async function listMessages2(inv, accessToken, timeoutMs) {
39894
39661
  if (args.skipToken) params.set("$skiptoken", args.skipToken);
39895
39662
  const headers = { authorization: `Bearer ${accessToken}` };
39896
39663
  if (args.query) headers["ConsistencyLevel"] = "eventual";
39897
- const res = await fetch(`${API13}/me/mailFolders/${folder}/messages?${params.toString()}`, {
39664
+ const res = await fetch(`${API12}/me/mailFolders/${folder}/messages?${params.toString()}`, {
39898
39665
  headers,
39899
39666
  signal: AbortSignal.timeout(timeoutMs)
39900
39667
  });
@@ -39928,7 +39695,7 @@ function toMessageSummary2(m) {
39928
39695
  }
39929
39696
  async function readMessage2(inv, accessToken, timeoutMs) {
39930
39697
  const { id } = inv.args;
39931
- const url = `${API13}/me/messages/${encodeURIComponent(id)}?$expand=attachments($select=id,name,contentType,size,isInline)`;
39698
+ const url = `${API12}/me/messages/${encodeURIComponent(id)}?$expand=attachments($select=id,name,contentType,size,isInline)`;
39932
39699
  const res = await fetch(url, {
39933
39700
  headers: { authorization: `Bearer ${accessToken}` },
39934
39701
  signal: AbortSignal.timeout(timeoutMs)
@@ -39971,7 +39738,7 @@ async function readMessage2(inv, accessToken, timeoutMs) {
39971
39738
  async function sendReply2(inv, accessToken, timeoutMs) {
39972
39739
  const { messageId, body, bodyType, replyAll, comment } = inv.args;
39973
39740
  const action = replyAll ? "createReplyAll" : "createReply";
39974
- const draftRes = await fetch(`${API13}/me/messages/${encodeURIComponent(messageId)}/${action}`, {
39741
+ const draftRes = await fetch(`${API12}/me/messages/${encodeURIComponent(messageId)}/${action}`, {
39975
39742
  method: "POST",
39976
39743
  headers: {
39977
39744
  authorization: `Bearer ${accessToken}`,
@@ -39994,7 +39761,7 @@ async function sendReply2(inv, accessToken, timeoutMs) {
39994
39761
  { name: "X-Tangle-Idempotency-Key", value: inv.idempotencyKey }
39995
39762
  ]
39996
39763
  };
39997
- const patchRes = await fetch(`${API13}/me/messages/${encodeURIComponent(draft.id)}`, {
39764
+ const patchRes = await fetch(`${API12}/me/messages/${encodeURIComponent(draft.id)}`, {
39998
39765
  method: "PATCH",
39999
39766
  headers: {
40000
39767
  authorization: `Bearer ${accessToken}`,
@@ -40010,7 +39777,7 @@ async function sendReply2(inv, accessToken, timeoutMs) {
40010
39777
  const text = await patchRes.text().catch(() => "");
40011
39778
  throw new Error(`outlook-mail send_reply patch ${patchRes.status}: ${text.slice(0, 200)}`);
40012
39779
  }
40013
- const sendRes = await fetch(`${API13}/me/messages/${encodeURIComponent(draft.id)}/send`, {
39780
+ const sendRes = await fetch(`${API12}/me/messages/${encodeURIComponent(draft.id)}/send`, {
40014
39781
  method: "POST",
40015
39782
  headers: { authorization: `Bearer ${accessToken}` },
40016
39783
  signal: AbortSignal.timeout(timeoutMs)
@@ -40057,12 +39824,25 @@ function buildMessagePayload(args, idempotencyKey, cap) {
40057
39824
  if (args.bcc?.length) {
40058
39825
  payload.bccRecipients = args.bcc.map((address) => ({ emailAddress: { address } }));
40059
39826
  }
39827
+ if (args.attachments?.length) {
39828
+ payload.attachments = args.attachments.map((a) => {
39829
+ if (!a?.name) throw new Error(`outlook-mail ${cap}: attachment \`name\` is required`);
39830
+ if (!a?.contentBytes) throw new Error(`outlook-mail ${cap}: attachment \`contentBytes\` (base64) is required`);
39831
+ const att = {
39832
+ "@odata.type": "#microsoft.graph.fileAttachment",
39833
+ name: a.name,
39834
+ contentBytes: a.contentBytes
39835
+ };
39836
+ if (a.contentType) att.contentType = a.contentType;
39837
+ return att;
39838
+ });
39839
+ }
40060
39840
  return payload;
40061
39841
  }
40062
39842
  async function sendMessage(inv, accessToken, timeoutMs) {
40063
39843
  const args = inv.args ?? {};
40064
39844
  const message = buildMessagePayload(args, inv.idempotencyKey, "send_message");
40065
- const res = await fetch(`${API13}/me/sendMail`, {
39845
+ const res = await fetch(`${API12}/me/sendMail`, {
40066
39846
  method: "POST",
40067
39847
  headers: {
40068
39848
  authorization: `Bearer ${accessToken}`,
@@ -40092,7 +39872,7 @@ async function sendMessage(inv, accessToken, timeoutMs) {
40092
39872
  async function createDraft(inv, accessToken, timeoutMs) {
40093
39873
  const args = inv.args ?? {};
40094
39874
  const message = buildMessagePayload(args, inv.idempotencyKey, "create_draft");
40095
- const res = await fetch(`${API13}/me/messages`, {
39875
+ const res = await fetch(`${API12}/me/messages`, {
40096
39876
  method: "POST",
40097
39877
  headers: {
40098
39878
  authorization: `Bearer ${accessToken}`,
@@ -40133,7 +39913,7 @@ async function subscribeFolder(inv, accessToken, timeoutMs) {
40133
39913
  expirationDateTime,
40134
39914
  clientState: clientState ?? inv.idempotencyKey
40135
39915
  };
40136
- const res = await fetch(`${API13}/subscriptions`, {
39916
+ const res = await fetch(`${API12}/subscriptions`, {
40137
39917
  method: "POST",
40138
39918
  headers: {
40139
39919
  authorization: `Bearer ${accessToken}`,
@@ -40162,6 +39942,162 @@ async function subscribeFolder(inv, accessToken, timeoutMs) {
40162
39942
  idempotentReplay: false
40163
39943
  };
40164
39944
  }
39945
+ async function forwardMessage(inv, accessToken, timeoutMs) {
39946
+ const { messageId, to, comment } = inv.args;
39947
+ if (!messageId) throw new Error("outlook-mail forward_message: `messageId` is required");
39948
+ if (!to || Array.isArray(to) && to.length === 0) {
39949
+ throw new Error("outlook-mail forward_message: `to` is required");
39950
+ }
39951
+ const toList = Array.isArray(to) ? to : [to];
39952
+ const toRecipients = toList.map((address) => ({ emailAddress: { address } }));
39953
+ const fwdBody = {
39954
+ toRecipients
39955
+ };
39956
+ if (comment !== void 0) fwdBody.comment = comment;
39957
+ const res = await fetch(`${API12}/me/messages/${encodeURIComponent(messageId)}/forward`, {
39958
+ method: "POST",
39959
+ headers: {
39960
+ authorization: `Bearer ${accessToken}`,
39961
+ "content-type": "application/json"
39962
+ },
39963
+ body: JSON.stringify(fwdBody),
39964
+ signal: AbortSignal.timeout(timeoutMs)
39965
+ });
39966
+ if (res.status === 401 || res.status === 403) {
39967
+ throw new CredentialsExpired(`Outlook Mail rejected token (${res.status})`, inv.source.id);
39968
+ }
39969
+ if (!res.ok && res.status !== 202) {
39970
+ const text = await res.text().catch(() => "");
39971
+ throw new Error(`outlook-mail forward_message ${res.status}: ${text.slice(0, 200)}`);
39972
+ }
39973
+ return {
39974
+ status: "committed",
39975
+ data: { forwarded: true, messageId, to: toList },
39976
+ committedAt: Date.now(),
39977
+ idempotentReplay: false
39978
+ };
39979
+ }
39980
+ async function moveMessage(inv, accessToken, timeoutMs) {
39981
+ const { messageId, destinationId } = inv.args;
39982
+ if (!messageId) throw new Error("outlook-mail move_message: `messageId` is required");
39983
+ if (!destinationId) throw new Error("outlook-mail move_message: `destinationId` is required");
39984
+ const res = await fetch(`${API12}/me/messages/${encodeURIComponent(messageId)}/move`, {
39985
+ method: "POST",
39986
+ headers: {
39987
+ authorization: `Bearer ${accessToken}`,
39988
+ "content-type": "application/json"
39989
+ },
39990
+ body: JSON.stringify({ destinationId }),
39991
+ signal: AbortSignal.timeout(timeoutMs)
39992
+ });
39993
+ if (res.status === 401 || res.status === 403) {
39994
+ throw new CredentialsExpired(`Outlook Mail rejected token (${res.status})`, inv.source.id);
39995
+ }
39996
+ if (!res.ok) {
39997
+ const text = await res.text().catch(() => "");
39998
+ throw new Error(`outlook-mail move_message ${res.status}: ${text.slice(0, 200)}`);
39999
+ }
40000
+ const json = await res.json().catch(() => ({}));
40001
+ return {
40002
+ status: "committed",
40003
+ data: {
40004
+ moved: true,
40005
+ messageId: json.id ?? messageId,
40006
+ parentFolderId: json.parentFolderId ?? destinationId,
40007
+ destinationId
40008
+ },
40009
+ committedAt: Date.now(),
40010
+ idempotentReplay: false
40011
+ };
40012
+ }
40013
+ async function setLabels(inv, accessToken, timeoutMs) {
40014
+ const { messageId, categories } = inv.args;
40015
+ if (!messageId) throw new Error("outlook-mail set_labels: `messageId` is required");
40016
+ if (!Array.isArray(categories)) {
40017
+ throw new Error("outlook-mail set_labels: `categories` must be an array (the full desired set)");
40018
+ }
40019
+ const res = await fetch(`${API12}/me/messages/${encodeURIComponent(messageId)}`, {
40020
+ method: "PATCH",
40021
+ headers: {
40022
+ authorization: `Bearer ${accessToken}`,
40023
+ "content-type": "application/json"
40024
+ },
40025
+ body: JSON.stringify({ categories }),
40026
+ signal: AbortSignal.timeout(timeoutMs)
40027
+ });
40028
+ if (res.status === 401 || res.status === 403) {
40029
+ throw new CredentialsExpired(`Outlook Mail rejected token (${res.status})`, inv.source.id);
40030
+ }
40031
+ if (!res.ok) {
40032
+ const text = await res.text().catch(() => "");
40033
+ throw new Error(`outlook-mail set_labels ${res.status}: ${text.slice(0, 200)}`);
40034
+ }
40035
+ const json = await res.json().catch(() => ({}));
40036
+ return {
40037
+ status: "committed",
40038
+ data: {
40039
+ messageId: json.id ?? messageId,
40040
+ categories: json.categories ?? categories
40041
+ },
40042
+ committedAt: Date.now(),
40043
+ idempotentReplay: false
40044
+ };
40045
+ }
40046
+ async function sendDraft(inv, accessToken, timeoutMs) {
40047
+ const { messageId } = inv.args;
40048
+ if (!messageId) throw new Error("outlook-mail send_draft: `messageId` is required");
40049
+ const res = await fetch(`${API12}/me/messages/${encodeURIComponent(messageId)}/send`, {
40050
+ method: "POST",
40051
+ headers: { authorization: `Bearer ${accessToken}` },
40052
+ signal: AbortSignal.timeout(timeoutMs)
40053
+ });
40054
+ if (res.status === 401 || res.status === 403) {
40055
+ throw new CredentialsExpired(`Outlook Mail rejected token (${res.status})`, inv.source.id);
40056
+ }
40057
+ if (!res.ok && res.status !== 202) {
40058
+ const text = await res.text().catch(() => "");
40059
+ throw new Error(`outlook-mail send_draft ${res.status}: ${text.slice(0, 200)}`);
40060
+ }
40061
+ return {
40062
+ status: "committed",
40063
+ data: { sent: true, messageId },
40064
+ committedAt: Date.now(),
40065
+ idempotentReplay: false
40066
+ };
40067
+ }
40068
+ async function downloadAttachment(inv, accessToken, timeoutMs) {
40069
+ const { messageId, attachmentId } = inv.args;
40070
+ const url = `${API12}/me/messages/${encodeURIComponent(messageId)}/attachments/${encodeURIComponent(attachmentId)}`;
40071
+ const res = await fetch(url, {
40072
+ headers: { authorization: `Bearer ${accessToken}` },
40073
+ signal: AbortSignal.timeout(timeoutMs)
40074
+ });
40075
+ if (res.status === 401 || res.status === 403) {
40076
+ throw new CredentialsExpired(`Outlook Mail rejected token (${res.status})`, inv.source.id);
40077
+ }
40078
+ if (res.status === 404) {
40079
+ throw new Error(`outlook-mail download_attachment: attachment ${attachmentId} on message ${messageId} not found`);
40080
+ }
40081
+ if (!res.ok) {
40082
+ const text = await res.text().catch(() => "");
40083
+ throw new Error(`outlook-mail download_attachment ${res.status}: ${text.slice(0, 200)}`);
40084
+ }
40085
+ const a = await res.json();
40086
+ return {
40087
+ data: {
40088
+ id: a.id ?? attachmentId,
40089
+ name: a.name ?? "",
40090
+ contentType: a.contentType ?? "application/octet-stream",
40091
+ size: a.size ?? 0,
40092
+ isInline: a.isInline ?? false,
40093
+ attachmentType: a["@odata.type"],
40094
+ // Base64 bytes for file attachments; null for item/reference attachments
40095
+ // which carry no inline contentBytes.
40096
+ contentBytes: a.contentBytes ?? null
40097
+ },
40098
+ fetchedAt: Date.now()
40099
+ };
40100
+ }
40165
40101
  async function ensureFreshAccessToken12(creds, clientId, clientSecret, onCredentialsRotated) {
40166
40102
  if (creds.kind !== "oauth2") {
40167
40103
  throw new Error("outlook-mail: expected oauth2 credentials");
@@ -40173,7 +40109,7 @@ async function ensureFreshAccessToken12(creds, clientId, clientSecret, onCredent
40173
40109
  throw new CredentialsExpired("Outlook Mail access token expired and no refresh token", "");
40174
40110
  }
40175
40111
  const refreshed = await refreshAccessToken({
40176
- tokenUrl: TOKEN_URL15,
40112
+ tokenUrl: TOKEN_URL14,
40177
40113
  clientId,
40178
40114
  clientSecret,
40179
40115
  refreshToken: creds.refreshToken
@@ -40201,8 +40137,8 @@ var SCOPES12 = [
40201
40137
  // offline_access is required on v2.0 to receive a refresh_token.
40202
40138
  "offline_access"
40203
40139
  ];
40204
- var AUTH_URL16 = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize";
40205
- var TOKEN_URL16 = "https://login.microsoftonline.com/common/oauth2/v2.0/token";
40140
+ var AUTH_URL15 = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize";
40141
+ var TOKEN_URL15 = "https://login.microsoftonline.com/common/oauth2/v2.0/token";
40206
40142
  var GRAPH2 = "https://graph.microsoft.com/v1.0";
40207
40143
  function microsoftTeams(opts) {
40208
40144
  const { clientId, clientSecret } = opts;
@@ -40213,8 +40149,8 @@ function microsoftTeams(opts) {
40213
40149
  description: "Post messages from the agent into Microsoft Teams channels and 1:1/group chats, list teams and channels, and look up users by email. Advisory surface \u2014 Teams posts are informational, not transactional.",
40214
40150
  auth: {
40215
40151
  kind: "oauth2",
40216
- authorizationUrl: AUTH_URL16,
40217
- tokenUrl: TOKEN_URL16,
40152
+ authorizationUrl: AUTH_URL15,
40153
+ tokenUrl: TOKEN_URL15,
40218
40154
  scopes: SCOPES12,
40219
40155
  clientIdEnv: "MS_OAUTH_CLIENT_ID",
40220
40156
  clientSecretEnv: "MS_OAUTH_CLIENT_SECRET"
@@ -40400,7 +40336,7 @@ function microsoftTeams(opts) {
40400
40336
  throw new Error("Microsoft OAuth client not configured (MS_OAUTH_CLIENT_ID / _SECRET)");
40401
40337
  }
40402
40338
  const tokens = await exchangeAuthorizationCode({
40403
- tokenUrl: TOKEN_URL16,
40339
+ tokenUrl: TOKEN_URL15,
40404
40340
  clientId,
40405
40341
  clientSecret,
40406
40342
  code: input.code,
@@ -40423,7 +40359,7 @@ function microsoftTeams(opts) {
40423
40359
  throw new Error("microsoft-teams.refreshToken: missing refresh token");
40424
40360
  }
40425
40361
  const refreshed = await refreshAccessToken({
40426
- tokenUrl: TOKEN_URL16,
40362
+ tokenUrl: TOKEN_URL15,
40427
40363
  clientId,
40428
40364
  clientSecret,
40429
40365
  refreshToken: creds.refreshToken
@@ -40465,7 +40401,7 @@ async function ensureFreshAccessToken13(creds, clientId, clientSecret) {
40465
40401
  throw new CredentialsExpired("Microsoft Teams access token expired and no refresh token", "");
40466
40402
  }
40467
40403
  const refreshed = await refreshAccessToken({
40468
- tokenUrl: TOKEN_URL16,
40404
+ tokenUrl: TOKEN_URL15,
40469
40405
  clientId,
40470
40406
  clientSecret,
40471
40407
  refreshToken: creds.refreshToken
@@ -40517,9 +40453,9 @@ function escapeOData2(value) {
40517
40453
  var SCOPE_READ3 = "https://graph.microsoft.com/Files.Read";
40518
40454
  var SCOPE_WRITE4 = "https://graph.microsoft.com/Files.ReadWrite";
40519
40455
  var SCOPE_OFFLINE2 = "offline_access";
40520
- var AUTH_URL17 = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize";
40521
- var TOKEN_URL17 = "https://login.microsoftonline.com/common/oauth2/v2.0/token";
40522
- var API14 = "https://graph.microsoft.com/v1.0";
40456
+ var AUTH_URL16 = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize";
40457
+ var TOKEN_URL16 = "https://login.microsoftonline.com/common/oauth2/v2.0/token";
40458
+ var API13 = "https://graph.microsoft.com/v1.0";
40523
40459
  function oneDrive(opts) {
40524
40460
  const { clientId, clientSecret } = opts;
40525
40461
  const timeoutMs = opts.timeoutMs ?? 3e4;
@@ -40531,8 +40467,8 @@ function oneDrive(opts) {
40531
40467
  description: "Read and watch files in the user's OneDrive. List a folder, fetch a document's contents (Word/Excel/PowerPoint/PDF/images), and subscribe to folder change notifications via Graph subscriptions.",
40532
40468
  auth: {
40533
40469
  kind: "oauth2",
40534
- authorizationUrl: AUTH_URL17,
40535
- tokenUrl: TOKEN_URL17,
40470
+ authorizationUrl: AUTH_URL16,
40471
+ tokenUrl: TOKEN_URL16,
40536
40472
  scopes,
40537
40473
  clientIdEnv: "MS_OAUTH_CLIENT_ID",
40538
40474
  clientSecretEnv: "MS_OAUTH_CLIENT_SECRET"
@@ -40709,7 +40645,7 @@ function oneDrive(opts) {
40709
40645
  throw new Error("OneDrive OAuth client not configured (MS_OAUTH_CLIENT_ID / _SECRET)");
40710
40646
  }
40711
40647
  const tokens = await exchangeAuthorizationCode({
40712
- tokenUrl: TOKEN_URL17,
40648
+ tokenUrl: TOKEN_URL16,
40713
40649
  clientId,
40714
40650
  clientSecret,
40715
40651
  code: input.code,
@@ -40732,7 +40668,7 @@ function oneDrive(opts) {
40732
40668
  throw new Error("onedrive.refreshToken: missing refresh token");
40733
40669
  }
40734
40670
  const refreshed = await refreshAccessToken({
40735
- tokenUrl: TOKEN_URL17,
40671
+ tokenUrl: TOKEN_URL16,
40736
40672
  clientId,
40737
40673
  clientSecret,
40738
40674
  refreshToken: creds.refreshToken
@@ -40747,7 +40683,7 @@ function oneDrive(opts) {
40747
40683
  async test(source) {
40748
40684
  try {
40749
40685
  const accessToken = await ensureFreshAccessToken14(source.credentials, clientId, clientSecret);
40750
- const res = await fetch(`${API14}/me/drive?$select=id`, {
40686
+ const res = await fetch(`${API13}/me/drive?$select=id`, {
40751
40687
  headers: { authorization: `Bearer ${accessToken}` },
40752
40688
  signal: AbortSignal.timeout(8e3)
40753
40689
  });
@@ -40776,7 +40712,7 @@ async function listFiles2(inv, accessToken, timeoutMs) {
40776
40712
  if (args.query) headers["ConsistencyLevel"] = "eventual";
40777
40713
  const path = args.folderId ? `/me/drive/items/${encodeURIComponent(args.folderId)}/children` : "/me/drive/root/children";
40778
40714
  const useSearchEndpoint = !!args.query && !args.folderId;
40779
- const url = useSearchEndpoint ? `${API14}/me/drive/root/search(q=${encodeURIComponent(`'${args.query.replace(/'/g, "''")}'`)})?${stripSearch(params).toString()}` : `${API14}${path}?${params.toString()}`;
40715
+ const url = useSearchEndpoint ? `${API13}/me/drive/root/search(q=${encodeURIComponent(`'${args.query.replace(/'/g, "''")}'`)})?${stripSearch(params).toString()}` : `${API13}${path}?${params.toString()}`;
40780
40716
  const res = await fetch(url, {
40781
40717
  headers,
40782
40718
  signal: AbortSignal.timeout(timeoutMs)
@@ -40806,7 +40742,7 @@ function stripSearch(params) {
40806
40742
  async function readFile2(inv, accessToken, timeoutMs) {
40807
40743
  const { fileId } = inv.args ?? {};
40808
40744
  if (!fileId) throw new Error("onedrive read_file: fileId is required");
40809
- const metaUrl = `${API14}/me/drive/items/${encodeURIComponent(fileId)}?$select=id,name,eTag,lastModifiedDateTime,size,file,folder`;
40745
+ const metaUrl = `${API13}/me/drive/items/${encodeURIComponent(fileId)}?$select=id,name,eTag,lastModifiedDateTime,size,file,folder`;
40810
40746
  const metaRes = await fetch(metaUrl, {
40811
40747
  headers: { authorization: `Bearer ${accessToken}` },
40812
40748
  signal: AbortSignal.timeout(timeoutMs)
@@ -40827,7 +40763,7 @@ async function readFile2(inv, accessToken, timeoutMs) {
40827
40763
  }
40828
40764
  const mimeType = meta.file?.mimeType ?? "application/octet-stream";
40829
40765
  const fetchedAt = Date.now();
40830
- const contentRes = await fetch(`${API14}/me/drive/items/${encodeURIComponent(fileId)}/content`, {
40766
+ const contentRes = await fetch(`${API13}/me/drive/items/${encodeURIComponent(fileId)}/content`, {
40831
40767
  headers: { authorization: `Bearer ${accessToken}` },
40832
40768
  signal: AbortSignal.timeout(timeoutMs)
40833
40769
  });
@@ -40880,7 +40816,7 @@ async function watchFolder2(inv, accessToken, timeoutMs) {
40880
40816
  expirationDateTime,
40881
40817
  clientState: clientState ?? inv.idempotencyKey
40882
40818
  };
40883
- const res = await fetch(`${API14}/subscriptions`, {
40819
+ const res = await fetch(`${API13}/subscriptions`, {
40884
40820
  method: "POST",
40885
40821
  headers: {
40886
40822
  authorization: `Bearer ${accessToken}`,
@@ -40920,7 +40856,7 @@ async function uploadFile3(inv, accessToken, timeoutMs) {
40920
40856
  }
40921
40857
  const body = encoding === "base64" ? Buffer.from(fileContent, "base64") : Buffer.from(fileContent, "utf-8");
40922
40858
  const parentSegment = folderId === "root" ? "/me/drive/root" : `/me/drive/items/${encodeURIComponent(folderId)}`;
40923
- const url = `${API14}${parentSegment}:/${encodeURIComponent(fileName)}:/content`;
40859
+ const url = `${API13}${parentSegment}:/${encodeURIComponent(fileName)}:/content`;
40924
40860
  const res = await fetch(url, {
40925
40861
  method: "PUT",
40926
40862
  headers: {
@@ -40956,7 +40892,7 @@ async function uploadFile3(inv, accessToken, timeoutMs) {
40956
40892
  async function deleteItem(inv, accessToken, timeoutMs) {
40957
40893
  const { itemId } = inv.args ?? {};
40958
40894
  if (!itemId) throw new Error("onedrive files.delete: itemId is required");
40959
- const res = await fetch(`${API14}${itemPath(itemId)}`, {
40895
+ const res = await fetch(`${API13}${itemPath(itemId)}`, {
40960
40896
  method: "DELETE",
40961
40897
  headers: { authorization: `Bearer ${accessToken}` },
40962
40898
  signal: AbortSignal.timeout(timeoutMs)
@@ -40994,7 +40930,7 @@ async function moveItem(inv, accessToken, timeoutMs) {
40994
40930
  body.parentReference = newParentId === "root" ? { path: "/drive/root" } : { id: newParentId };
40995
40931
  }
40996
40932
  if (newName) body.name = newName;
40997
- const res = await fetch(`${API14}${itemPath(itemId)}`, {
40933
+ const res = await fetch(`${API13}${itemPath(itemId)}`, {
40998
40934
  method: "PATCH",
40999
40935
  headers: {
41000
40936
  authorization: `Bearer ${accessToken}`,
@@ -41034,7 +40970,7 @@ async function shareItem(inv, accessToken, timeoutMs) {
41034
40970
  };
41035
40971
  if (password) body.password = password;
41036
40972
  if (expirationDateTime) body.expirationDateTime = expirationDateTime;
41037
- const res = await fetch(`${API14}${itemPath(itemId)}/createLink`, {
40973
+ const res = await fetch(`${API13}${itemPath(itemId)}/createLink`, {
41038
40974
  method: "POST",
41039
40975
  headers: {
41040
40976
  authorization: `Bearer ${accessToken}`,
@@ -41073,7 +41009,7 @@ async function createFolder2(inv, accessToken, timeoutMs) {
41073
41009
  folder: {},
41074
41010
  "@microsoft.graph.conflictBehavior": conflictBehavior ?? "fail"
41075
41011
  };
41076
- const res = await fetch(`${API14}${parentSegment}`, {
41012
+ const res = await fetch(`${API13}${parentSegment}`, {
41077
41013
  method: "POST",
41078
41014
  headers: {
41079
41015
  authorization: `Bearer ${accessToken}`,
@@ -41115,7 +41051,7 @@ async function ensureFreshAccessToken14(creds, clientId, clientSecret, onCredent
41115
41051
  throw new CredentialsExpired("OneDrive access token expired and no refresh token", "");
41116
41052
  }
41117
41053
  const refreshed = await refreshAccessToken({
41118
- tokenUrl: TOKEN_URL17,
41054
+ tokenUrl: TOKEN_URL16,
41119
41055
  clientId,
41120
41056
  clientSecret,
41121
41057
  refreshToken: creds.refreshToken
@@ -41134,13 +41070,13 @@ async function ensureFreshAccessToken14(creds, clientId, clientSecret, onCredent
41134
41070
 
41135
41071
  // src/connectors/adapters/sharepoint.ts
41136
41072
  var SCOPES13 = [
41137
- "https://graph.microsoft.com/Sites.Read.All",
41073
+ "https://graph.microsoft.com/Sites.ReadWrite.All",
41138
41074
  "https://graph.microsoft.com/Files.ReadWrite.All",
41139
41075
  // offline_access is required on v2.0 to receive a refresh_token.
41140
41076
  "offline_access"
41141
41077
  ];
41142
- var AUTH_URL18 = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize";
41143
- var TOKEN_URL18 = "https://login.microsoftonline.com/common/oauth2/v2.0/token";
41078
+ var AUTH_URL17 = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize";
41079
+ var TOKEN_URL17 = "https://login.microsoftonline.com/common/oauth2/v2.0/token";
41144
41080
  var GRAPH3 = "https://graph.microsoft.com/v1.0";
41145
41081
  var MAX_INLINE_BYTES = 4 * 1024 * 1024;
41146
41082
  function sharepoint(opts) {
@@ -41152,8 +41088,8 @@ function sharepoint(opts) {
41152
41088
  description: "Let your agent discover SharePoint sites, list/search their document libraries, read small file contents, upload files, and create folders. Etag-CAS available on every DriveItem for follow-up patch/delete flows.",
41153
41089
  auth: {
41154
41090
  kind: "oauth2",
41155
- authorizationUrl: AUTH_URL18,
41156
- tokenUrl: TOKEN_URL18,
41091
+ authorizationUrl: AUTH_URL17,
41092
+ tokenUrl: TOKEN_URL17,
41157
41093
  scopes: SCOPES13,
41158
41094
  clientIdEnv: "MS_OAUTH_CLIENT_ID",
41159
41095
  clientSecretEnv: "MS_OAUTH_CLIENT_SECRET"
@@ -41356,6 +41292,136 @@ function sharepoint(opts) {
41356
41292
  },
41357
41293
  required: ["siteId", "listId", "fields"]
41358
41294
  }
41295
+ },
41296
+ {
41297
+ name: "get_site_info",
41298
+ class: "read",
41299
+ description: "Read the metadata for a SharePoint site by site id (id, name, displayName, webUrl, description).",
41300
+ parameters: {
41301
+ type: "object",
41302
+ properties: {
41303
+ siteId: { type: "string", description: 'Graph site id (composite "host,site-id,web-id").' }
41304
+ },
41305
+ required: ["siteId"]
41306
+ }
41307
+ },
41308
+ {
41309
+ name: "lists.items.find",
41310
+ class: "read",
41311
+ description: "List items in a SharePoint list, optionally filtered with $filter and shaped with $expand (e.g. fields($select=...)).",
41312
+ parameters: {
41313
+ type: "object",
41314
+ properties: {
41315
+ siteId: { type: "string", description: "Graph site id." },
41316
+ listId: { type: "string", description: "SharePoint list id (or list display name resolved by the caller)." },
41317
+ filter: { type: "string", description: "Optional OData $filter expression." },
41318
+ expand: { type: "string", description: "Optional OData $expand, e.g. fields($select=Title,Status)." },
41319
+ top: { type: "integer", minimum: 1, maximum: 200, default: 50 }
41320
+ },
41321
+ required: ["siteId", "listId"]
41322
+ }
41323
+ },
41324
+ {
41325
+ name: "copy_item",
41326
+ class: "mutation",
41327
+ description: "Copy a file or folder DriveItem. Graph copy is asynchronous \u2014 it returns 202 Accepted with a Location monitor URL rather than the new DriveItem. Supply either a cross-drive parentReference (driveId + id) or a same-site target parent id via targetParentId; optionally rename via name.",
41328
+ cas: "native-idempotency",
41329
+ externalEffect: true,
41330
+ parameters: {
41331
+ type: "object",
41332
+ properties: {
41333
+ siteId: { type: "string", description: "Graph site id." },
41334
+ itemId: { type: "string", description: "DriveItem id of the file or folder to copy." },
41335
+ parentReference: {
41336
+ type: "object",
41337
+ description: "Cross-drive destination reference (driveId + id). Provide this OR targetParentId.",
41338
+ additionalProperties: true
41339
+ },
41340
+ targetParentId: {
41341
+ type: "string",
41342
+ description: "Same-site destination parent folder DriveItem id. Provide this OR parentReference."
41343
+ },
41344
+ name: { type: "string", description: "Optional new name for the copied item." }
41345
+ },
41346
+ required: ["siteId", "itemId"]
41347
+ }
41348
+ },
41349
+ {
41350
+ name: "lists.create",
41351
+ class: "mutation",
41352
+ description: "Create a SharePoint list on the site. displayName is required; columns and list (e.g. { template }) are optional.",
41353
+ cas: "native-idempotency",
41354
+ externalEffect: true,
41355
+ parameters: {
41356
+ type: "object",
41357
+ properties: {
41358
+ siteId: { type: "string", description: "Graph site id." },
41359
+ displayName: { type: "string", description: "Display name of the new list." },
41360
+ columns: {
41361
+ type: "array",
41362
+ description: "Optional column definitions for the list.",
41363
+ items: { type: "object", additionalProperties: true }
41364
+ },
41365
+ list: {
41366
+ type: "object",
41367
+ description: 'Optional list facet, e.g. { template: "genericList" }.',
41368
+ additionalProperties: true
41369
+ }
41370
+ },
41371
+ required: ["siteId", "displayName"]
41372
+ }
41373
+ },
41374
+ {
41375
+ name: "lists.items.update",
41376
+ class: "mutation",
41377
+ description: "Patch the fields on an existing list item. Supports etag-CAS via If-Match \u2014 pass the item's etag to guard against concurrent writes; a mismatch surfaces as ResourceContention.",
41378
+ cas: "etag-if-match",
41379
+ externalEffect: true,
41380
+ parameters: {
41381
+ type: "object",
41382
+ properties: {
41383
+ siteId: { type: "string", description: "Graph site id." },
41384
+ listId: { type: "string", description: "SharePoint list id." },
41385
+ itemId: { type: "string", description: "List item id to update." },
41386
+ fields: {
41387
+ type: "object",
41388
+ description: "Map of column internal-name \u2192 new value.",
41389
+ additionalProperties: true
41390
+ }
41391
+ },
41392
+ required: ["siteId", "listId", "itemId", "fields"]
41393
+ }
41394
+ },
41395
+ {
41396
+ name: "lists.items.delete",
41397
+ class: "mutation",
41398
+ description: "Delete a list item by id. Graph returns 204 on success. (siteId, listId, itemId) is the natural idempotency tuple \u2014 a re-delete of a missing item surfaces as 404 mapped to a tombstone result.",
41399
+ cas: "native-idempotency",
41400
+ externalEffect: true,
41401
+ parameters: {
41402
+ type: "object",
41403
+ properties: {
41404
+ siteId: { type: "string", description: "Graph site id." },
41405
+ listId: { type: "string", description: "SharePoint list id." },
41406
+ itemId: { type: "string", description: "List item id to delete." }
41407
+ },
41408
+ required: ["siteId", "listId", "itemId"]
41409
+ }
41410
+ },
41411
+ {
41412
+ name: "pages.publish",
41413
+ class: "mutation",
41414
+ description: "Publish a SharePoint site page by page id.",
41415
+ cas: "native-idempotency",
41416
+ externalEffect: true,
41417
+ parameters: {
41418
+ type: "object",
41419
+ properties: {
41420
+ siteId: { type: "string", description: "Graph site id." },
41421
+ pageId: { type: "string", description: "Site page id to publish." }
41422
+ },
41423
+ required: ["siteId", "pageId"]
41424
+ }
41359
41425
  }
41360
41426
  ]
41361
41427
  },
@@ -41505,6 +41571,41 @@ function sharepoint(opts) {
41505
41571
  fetchedAt: Date.now()
41506
41572
  };
41507
41573
  }
41574
+ if (inv.capabilityName === "get_site_info") {
41575
+ const { siteId } = inv.args;
41576
+ const url = `${GRAPH3}/sites/${encodeURIComponent(siteId)}?$select=id,name,displayName,webUrl,description`;
41577
+ const site = await graphGet4(url, accessToken, inv.source.id);
41578
+ return {
41579
+ data: {
41580
+ id: site.id,
41581
+ name: site.displayName ?? site.name,
41582
+ webUrl: site.webUrl,
41583
+ description: site.description
41584
+ },
41585
+ fetchedAt: Date.now()
41586
+ };
41587
+ }
41588
+ if (inv.capabilityName === "lists.items.find") {
41589
+ const { siteId, listId, filter, expand, top } = inv.args;
41590
+ const t = clamp(top ?? 50, 1, 200);
41591
+ const params = new URLSearchParams();
41592
+ params.set("$top", String(t));
41593
+ if (typeof filter === "string" && filter.length > 0) params.set("$filter", filter);
41594
+ if (typeof expand === "string" && expand.length > 0) params.set("$expand", expand);
41595
+ const url = `${GRAPH3}/sites/${encodeURIComponent(siteId)}/lists/${encodeURIComponent(listId)}/items?${params.toString()}`;
41596
+ const json = await graphGet4(url, accessToken, inv.source.id);
41597
+ const items = (json.value ?? []).map((it) => ({
41598
+ id: it.id,
41599
+ webUrl: it.webUrl,
41600
+ etag: it.eTag,
41601
+ lastModifiedAt: it.lastModifiedDateTime,
41602
+ fields: it.fields
41603
+ }));
41604
+ return {
41605
+ data: { items, nextLink: json["@odata.nextLink"] },
41606
+ fetchedAt: Date.now()
41607
+ };
41608
+ }
41508
41609
  throw new Error(`sharepoint: unknown read capability ${inv.capabilityName}`);
41509
41610
  },
41510
41611
  async executeMutation(inv) {
@@ -41814,6 +41915,211 @@ function sharepoint(opts) {
41814
41915
  idempotentReplay: false
41815
41916
  };
41816
41917
  }
41918
+ if (inv.capabilityName === "copy_item") {
41919
+ const { siteId, itemId, parentReference, targetParentId, name } = inv.args;
41920
+ const ref = parentReference && Object.keys(parentReference).length > 0 ? parentReference : typeof targetParentId === "string" && targetParentId.length > 0 ? { id: targetParentId } : void 0;
41921
+ if (!ref) {
41922
+ throw new Error(
41923
+ "sharepoint copy_item: provide either parentReference (cross-drive) or targetParentId (same-site)"
41924
+ );
41925
+ }
41926
+ const url = `${GRAPH3}/sites/${encodeURIComponent(siteId)}/drive/items/${encodeURIComponent(itemId)}/copy`;
41927
+ const body = { parentReference: ref };
41928
+ if (typeof name === "string" && name.length > 0) body.name = name;
41929
+ const res = await fetch(url, {
41930
+ method: "POST",
41931
+ headers: {
41932
+ authorization: `Bearer ${accessToken}`,
41933
+ "content-type": "application/json",
41934
+ accept: "application/json"
41935
+ },
41936
+ body: JSON.stringify(body),
41937
+ signal: AbortSignal.timeout(15e3)
41938
+ });
41939
+ if (res.status === 401 || res.status === 403) {
41940
+ throw new CredentialsExpired(
41941
+ `Microsoft Graph rejected token (${res.status})`,
41942
+ inv.source.id
41943
+ );
41944
+ }
41945
+ if (res.status === 409 || res.status === 412) {
41946
+ throw new ResourceContention(
41947
+ `Microsoft Graph reported conflict on copy_item (${res.status})`,
41948
+ []
41949
+ );
41950
+ }
41951
+ if (!res.ok && res.status !== 202) {
41952
+ const text = await res.text().catch(() => "");
41953
+ throw new Error(`sharepoint copy_item ${res.status}: ${text.slice(0, 200)}`);
41954
+ }
41955
+ const monitorUrl = res.headers.get("location") ?? void 0;
41956
+ return {
41957
+ status: "committed",
41958
+ data: { id: itemId, accepted: true, async: true, monitorUrl },
41959
+ committedAt: Date.now(),
41960
+ idempotentReplay: false
41961
+ };
41962
+ }
41963
+ if (inv.capabilityName === "lists.create") {
41964
+ const { siteId, displayName, columns, list } = inv.args;
41965
+ const url = `${GRAPH3}/sites/${encodeURIComponent(siteId)}/lists`;
41966
+ const body = { displayName };
41967
+ if (Array.isArray(columns)) body.columns = columns;
41968
+ if (list && typeof list === "object") body.list = list;
41969
+ const res = await fetch(url, {
41970
+ method: "POST",
41971
+ headers: {
41972
+ authorization: `Bearer ${accessToken}`,
41973
+ "content-type": "application/json",
41974
+ accept: "application/json"
41975
+ },
41976
+ body: JSON.stringify(body),
41977
+ signal: AbortSignal.timeout(15e3)
41978
+ });
41979
+ if (res.status === 401 || res.status === 403) {
41980
+ throw new CredentialsExpired(
41981
+ `Microsoft Graph rejected token (${res.status})`,
41982
+ inv.source.id
41983
+ );
41984
+ }
41985
+ if (res.status === 409 || res.status === 412) {
41986
+ throw new ResourceContention(
41987
+ `Microsoft Graph reported conflict on lists.create (${res.status})`,
41988
+ []
41989
+ );
41990
+ }
41991
+ if (!res.ok) {
41992
+ const text = await res.text().catch(() => "");
41993
+ throw new Error(`sharepoint lists.create ${res.status}: ${text.slice(0, 200)}`);
41994
+ }
41995
+ const created = await res.json();
41996
+ return {
41997
+ status: "committed",
41998
+ data: {
41999
+ id: created.id,
42000
+ displayName: created.displayName ?? created.name,
42001
+ webUrl: created.webUrl
42002
+ },
42003
+ etagAfter: created["@odata.etag"] ?? created.eTag,
42004
+ committedAt: Date.now(),
42005
+ idempotentReplay: false
42006
+ };
42007
+ }
42008
+ if (inv.capabilityName === "lists.items.update") {
42009
+ const { siteId, listId, itemId, fields } = inv.args;
42010
+ const url = `${GRAPH3}/sites/${encodeURIComponent(siteId)}/lists/${encodeURIComponent(listId)}/items/${encodeURIComponent(itemId)}/fields`;
42011
+ const headers = {
42012
+ authorization: `Bearer ${accessToken}`,
42013
+ "content-type": "application/json",
42014
+ accept: "application/json"
42015
+ };
42016
+ if (typeof inv.expectedEtag === "string" && inv.expectedEtag.length > 0) {
42017
+ headers["if-match"] = inv.expectedEtag;
42018
+ }
42019
+ const res = await fetch(url, {
42020
+ method: "PATCH",
42021
+ headers,
42022
+ body: JSON.stringify(fields),
42023
+ signal: AbortSignal.timeout(15e3)
42024
+ });
42025
+ if (res.status === 401 || res.status === 403) {
42026
+ throw new CredentialsExpired(
42027
+ `Microsoft Graph rejected token (${res.status})`,
42028
+ inv.source.id
42029
+ );
42030
+ }
42031
+ if (res.status === 409 || res.status === 412) {
42032
+ throw new ResourceContention(
42033
+ `Microsoft Graph reported conflict on lists.items.update (${res.status})`,
42034
+ []
42035
+ );
42036
+ }
42037
+ if (!res.ok) {
42038
+ const text = await res.text().catch(() => "");
42039
+ throw new Error(`sharepoint lists.items.update ${res.status}: ${text.slice(0, 200)}`);
42040
+ }
42041
+ const updated = await res.json();
42042
+ return {
42043
+ status: "committed",
42044
+ data: { id: itemId, fields: updated },
42045
+ etagAfter: updated["@odata.etag"] ?? updated.eTag,
42046
+ committedAt: Date.now(),
42047
+ idempotentReplay: false
42048
+ };
42049
+ }
42050
+ if (inv.capabilityName === "lists.items.delete") {
42051
+ const { siteId, listId, itemId } = inv.args;
42052
+ const url = `${GRAPH3}/sites/${encodeURIComponent(siteId)}/lists/${encodeURIComponent(listId)}/items/${encodeURIComponent(itemId)}`;
42053
+ const res = await fetch(url, {
42054
+ method: "DELETE",
42055
+ headers: { authorization: `Bearer ${accessToken}` },
42056
+ signal: AbortSignal.timeout(15e3)
42057
+ });
42058
+ if (res.status === 401 || res.status === 403) {
42059
+ throw new CredentialsExpired(
42060
+ `Microsoft Graph rejected token (${res.status})`,
42061
+ inv.source.id
42062
+ );
42063
+ }
42064
+ if (res.status === 412 || res.status === 409) {
42065
+ throw new ResourceContention(
42066
+ `Microsoft Graph reported conflict on lists.items.delete (${res.status})`,
42067
+ []
42068
+ );
42069
+ }
42070
+ if (res.status === 404) {
42071
+ return {
42072
+ status: "committed",
42073
+ data: { id: itemId, deleted: true, alreadyMissing: true },
42074
+ committedAt: Date.now(),
42075
+ idempotentReplay: true
42076
+ };
42077
+ }
42078
+ if (!res.ok) {
42079
+ const text = await res.text().catch(() => "");
42080
+ throw new Error(`sharepoint lists.items.delete ${res.status}: ${text.slice(0, 200)}`);
42081
+ }
42082
+ return {
42083
+ status: "committed",
42084
+ data: { id: itemId, deleted: true },
42085
+ committedAt: Date.now(),
42086
+ idempotentReplay: false
42087
+ };
42088
+ }
42089
+ if (inv.capabilityName === "pages.publish") {
42090
+ const { siteId, pageId } = inv.args;
42091
+ const url = `${GRAPH3}/sites/${encodeURIComponent(siteId)}/pages/${encodeURIComponent(pageId)}/microsoft.graph.sitePage/publish`;
42092
+ const res = await fetch(url, {
42093
+ method: "POST",
42094
+ headers: {
42095
+ authorization: `Bearer ${accessToken}`,
42096
+ accept: "application/json"
42097
+ },
42098
+ signal: AbortSignal.timeout(15e3)
42099
+ });
42100
+ if (res.status === 401 || res.status === 403) {
42101
+ throw new CredentialsExpired(
42102
+ `Microsoft Graph rejected token (${res.status})`,
42103
+ inv.source.id
42104
+ );
42105
+ }
42106
+ if (res.status === 409 || res.status === 412) {
42107
+ throw new ResourceContention(
42108
+ `Microsoft Graph reported conflict on pages.publish (${res.status})`,
42109
+ []
42110
+ );
42111
+ }
42112
+ if (!res.ok) {
42113
+ const text = await res.text().catch(() => "");
42114
+ throw new Error(`sharepoint pages.publish ${res.status}: ${text.slice(0, 200)}`);
42115
+ }
42116
+ return {
42117
+ status: "committed",
42118
+ data: { id: pageId, published: true },
42119
+ committedAt: Date.now(),
42120
+ idempotentReplay: false
42121
+ };
42122
+ }
41817
42123
  throw new Error(`sharepoint: unknown mutation capability ${inv.capabilityName}`);
41818
42124
  },
41819
42125
  async exchangeOAuth(input) {
@@ -41821,7 +42127,7 @@ function sharepoint(opts) {
41821
42127
  throw new Error("Microsoft OAuth client not configured (MS_OAUTH_CLIENT_ID / _SECRET)");
41822
42128
  }
41823
42129
  const tokens = await exchangeAuthorizationCode({
41824
- tokenUrl: TOKEN_URL18,
42130
+ tokenUrl: TOKEN_URL17,
41825
42131
  clientId,
41826
42132
  clientSecret,
41827
42133
  code: input.code,
@@ -41844,7 +42150,7 @@ function sharepoint(opts) {
41844
42150
  throw new Error("sharepoint.refreshToken: missing refresh token");
41845
42151
  }
41846
42152
  const refreshed = await refreshAccessToken({
41847
- tokenUrl: TOKEN_URL18,
42153
+ tokenUrl: TOKEN_URL17,
41848
42154
  clientId,
41849
42155
  clientSecret,
41850
42156
  refreshToken: creds.refreshToken
@@ -41893,7 +42199,7 @@ async function ensureFreshAccessToken15(creds, clientId, clientSecret) {
41893
42199
  throw new CredentialsExpired("SharePoint access token expired and no refresh token", "");
41894
42200
  }
41895
42201
  const refreshed = await refreshAccessToken({
41896
- tokenUrl: TOKEN_URL18,
42202
+ tokenUrl: TOKEN_URL17,
41897
42203
  clientId,
41898
42204
  clientSecret,
41899
42205
  refreshToken: creds.refreshToken
@@ -71101,6 +71407,609 @@ var googleSearchConsoleConnector = declarativeRestConnector({
71101
71407
  ]
71102
71408
  });
71103
71409
 
71410
+ // src/connectors/adapters/google-analytics.ts
71411
+ var googleAnalyticsConnector = declarativeRestConnector({
71412
+ kind: "google-analytics",
71413
+ displayName: "Google Analytics",
71414
+ description: "Run reports, pivot reports, realtime reports, and batch reports against connected GA4 properties. Read-only: GA4 ingest happens through gtag / Measurement Protocol, not the management API.",
71415
+ auth: {
71416
+ kind: "oauth2",
71417
+ authorizationUrl: "https://accounts.google.com/o/oauth2/v2/auth",
71418
+ tokenUrl: "https://oauth2.googleapis.com/token",
71419
+ scopes: ["https://www.googleapis.com/auth/analytics.readonly"],
71420
+ clientIdEnv: "GOOGLE_OAUTH_CLIENT_ID",
71421
+ clientSecretEnv: "GOOGLE_OAUTH_CLIENT_SECRET",
71422
+ extraAuthParams: { access_type: "offline", prompt: "consent", include_granted_scopes: "true" }
71423
+ },
71424
+ category: "database",
71425
+ defaultConsistencyModel: "cache",
71426
+ baseUrl: "https://analyticsdata.googleapis.com",
71427
+ // accountSummaries.list lives on the Admin API host and is the cheapest
71428
+ // probe that confirms the token can reach GA4 at all. Absolute URL routes
71429
+ // around the single-baseUrl constraint of the declarative-rest runtime.
71430
+ test: {
71431
+ method: "GET",
71432
+ path: "https://analyticsadmin.googleapis.com/v1beta/accountSummaries",
71433
+ query: { pageSize: 1 }
71434
+ },
71435
+ capabilities: [
71436
+ {
71437
+ name: "accountSummaries.list",
71438
+ class: "read",
71439
+ description: "List GA4 account summaries reachable by the connected identity. Each summary nests its properties so the agent can discover propertyId values without a second round-trip (GET analyticsadmin.googleapis.com/v1beta/accountSummaries).",
71440
+ parameters: {
71441
+ type: "object",
71442
+ properties: {
71443
+ pageSize: { type: "integer", minimum: 1, maximum: 200, description: "Max account summaries per page; server caps at 200." },
71444
+ pageToken: { type: "string", description: "Continuation token returned by a prior call." }
71445
+ }
71446
+ },
71447
+ request: {
71448
+ method: "GET",
71449
+ path: "https://analyticsadmin.googleapis.com/v1beta/accountSummaries",
71450
+ query: { pageSize: "{pageSize}", pageToken: "{pageToken}" }
71451
+ },
71452
+ requiredScopes: ["https://www.googleapis.com/auth/analytics.readonly"]
71453
+ },
71454
+ {
71455
+ name: "properties.get",
71456
+ class: "read",
71457
+ description: "Fetch GA4 property settings (display name, timezone, currency, industry) by numeric property id (GET analyticsadmin.googleapis.com/v1beta/properties/{propertyId}).",
71458
+ parameters: {
71459
+ type: "object",
71460
+ properties: {
71461
+ propertyId: { type: "string", description: 'Numeric GA4 property id, e.g. "123456789".' }
71462
+ },
71463
+ required: ["propertyId"]
71464
+ },
71465
+ request: {
71466
+ method: "GET",
71467
+ path: "https://analyticsadmin.googleapis.com/v1beta/properties/{propertyId}"
71468
+ },
71469
+ requiredScopes: ["https://www.googleapis.com/auth/analytics.readonly"]
71470
+ },
71471
+ {
71472
+ name: "properties.metadata.get",
71473
+ class: "read",
71474
+ description: "List every dimension and metric available on a GA4 property, including custom dimensions/metrics defined by the customer. Use this before runReport to discover valid dimension/metric names (GET /v1beta/properties/{propertyId}/metadata).",
71475
+ parameters: {
71476
+ type: "object",
71477
+ properties: {
71478
+ propertyId: { type: "string", description: "Numeric GA4 property id." }
71479
+ },
71480
+ required: ["propertyId"]
71481
+ },
71482
+ request: {
71483
+ method: "GET",
71484
+ path: "/v1beta/properties/{propertyId}/metadata"
71485
+ },
71486
+ requiredScopes: ["https://www.googleapis.com/auth/analytics.readonly"]
71487
+ },
71488
+ {
71489
+ name: "properties.runReport",
71490
+ class: "read",
71491
+ description: 'Run a core report against a GA4 property. Pass dimensions, metrics, dateRanges (e.g. {startDate:"7daysAgo",endDate:"today"}), optional filters, ordering, and a row limit. Returns the rows, totals, and metadata GA4 emits in the standard runReport response (POST /v1beta/properties/{propertyId}:runReport).',
71492
+ parameters: {
71493
+ type: "object",
71494
+ properties: {
71495
+ propertyId: { type: "string", description: "Numeric GA4 property id." },
71496
+ dimensions: {
71497
+ type: "array",
71498
+ description: 'Dimension specs, e.g. [{ "name": "country" }, { "name": "deviceCategory" }].',
71499
+ items: {
71500
+ type: "object",
71501
+ properties: {
71502
+ name: { type: "string" },
71503
+ dimensionExpression: { type: "object", description: "Composite/lower-case/concatenate expression (optional)." }
71504
+ },
71505
+ required: ["name"]
71506
+ }
71507
+ },
71508
+ metrics: {
71509
+ type: "array",
71510
+ description: 'Metric specs, e.g. [{ "name": "activeUsers" }, { "name": "sessions" }].',
71511
+ items: {
71512
+ type: "object",
71513
+ properties: {
71514
+ name: { type: "string" },
71515
+ expression: { type: "string", description: "Derived metric expression (optional)." },
71516
+ invisible: { type: "boolean" }
71517
+ },
71518
+ required: ["name"]
71519
+ }
71520
+ },
71521
+ dateRanges: {
71522
+ type: "array",
71523
+ description: 'One or two date ranges; GA4 accepts ISO dates ("2026-05-01"), "today", "yesterday", or "NdaysAgo".',
71524
+ items: {
71525
+ type: "object",
71526
+ properties: {
71527
+ startDate: { type: "string" },
71528
+ endDate: { type: "string" },
71529
+ name: { type: "string", description: "Optional label included in the response row keys when comparing two ranges." }
71530
+ },
71531
+ required: ["startDate", "endDate"]
71532
+ }
71533
+ },
71534
+ dimensionFilter: { type: "object", description: "GA4 FilterExpression (and/or/not) applied to dimensions." },
71535
+ metricFilter: { type: "object", description: "GA4 FilterExpression applied to metrics after aggregation." },
71536
+ orderBys: { type: "array", items: { type: "object" } },
71537
+ limit: { type: "integer", minimum: 1, maximum: 25e4, description: "Max rows per page; GA4 caps at 250000." },
71538
+ offset: { type: "integer", minimum: 0 },
71539
+ keepEmptyRows: { type: "boolean" },
71540
+ returnPropertyQuota: { type: "boolean", description: "Include per-property quota consumption in the response \u2014 useful for back-pressure decisions." },
71541
+ currencyCode: { type: "string", description: "ISO-4217 currency, overrides the property default for monetary metrics." },
71542
+ cohortSpec: { type: "object", description: "CohortSpec for cohort analysis (optional)." }
71543
+ },
71544
+ required: ["propertyId", "metrics", "dateRanges"]
71545
+ },
71546
+ request: {
71547
+ method: "POST",
71548
+ path: "/v1beta/properties/{propertyId}:runReport",
71549
+ body: {
71550
+ dimensions: "{dimensions}",
71551
+ metrics: "{metrics}",
71552
+ dateRanges: "{dateRanges}",
71553
+ dimensionFilter: "{dimensionFilter}",
71554
+ metricFilter: "{metricFilter}",
71555
+ orderBys: "{orderBys}",
71556
+ limit: "{limit}",
71557
+ offset: "{offset}",
71558
+ keepEmptyRows: "{keepEmptyRows}",
71559
+ returnPropertyQuota: "{returnPropertyQuota}",
71560
+ currencyCode: "{currencyCode}",
71561
+ cohortSpec: "{cohortSpec}"
71562
+ }
71563
+ },
71564
+ requiredScopes: ["https://www.googleapis.com/auth/analytics.readonly"]
71565
+ },
71566
+ {
71567
+ name: "properties.batchRunReports",
71568
+ class: "read",
71569
+ description: "Run up to 5 reports against the same GA4 property in a single request \u2014 cheaper than 5 round-trips and counted as fewer quota tokens (POST /v1beta/properties/{propertyId}:batchRunReports).",
71570
+ parameters: {
71571
+ type: "object",
71572
+ properties: {
71573
+ propertyId: { type: "string", description: "Numeric GA4 property id." },
71574
+ requests: {
71575
+ type: "array",
71576
+ description: "Up to 5 report requests; each takes the same shape as runReport (dimensions/metrics/dateRanges/etc.).",
71577
+ items: { type: "object" },
71578
+ maxItems: 5
71579
+ }
71580
+ },
71581
+ required: ["propertyId", "requests"]
71582
+ },
71583
+ request: {
71584
+ method: "POST",
71585
+ path: "/v1beta/properties/{propertyId}:batchRunReports",
71586
+ body: { requests: "{requests}" }
71587
+ },
71588
+ requiredScopes: ["https://www.googleapis.com/auth/analytics.readonly"]
71589
+ },
71590
+ {
71591
+ name: "properties.runPivotReport",
71592
+ class: "read",
71593
+ description: "Run a pivot report \u2014 like runReport but with one or more pivot specifications that rotate dimensions into columns (POST /v1beta/properties/{propertyId}:runPivotReport).",
71594
+ parameters: {
71595
+ type: "object",
71596
+ properties: {
71597
+ propertyId: { type: "string", description: "Numeric GA4 property id." },
71598
+ dimensions: { type: "array", items: { type: "object" } },
71599
+ metrics: { type: "array", items: { type: "object" } },
71600
+ dateRanges: { type: "array", items: { type: "object" } },
71601
+ pivots: {
71602
+ type: "array",
71603
+ description: "Pivot specifications \u2014 each names the dimensions to pivot, an order, a limit, and optional offset.",
71604
+ items: {
71605
+ type: "object",
71606
+ properties: {
71607
+ fieldNames: { type: "array", items: { type: "string" } },
71608
+ orderBys: { type: "array", items: { type: "object" } },
71609
+ offset: { type: "string", description: "String-encoded long." },
71610
+ limit: { type: "string", description: "String-encoded long." },
71611
+ metricAggregations: { type: "array", items: { type: "string" } }
71612
+ },
71613
+ required: ["fieldNames"]
71614
+ }
71615
+ },
71616
+ dimensionFilter: { type: "object" },
71617
+ metricFilter: { type: "object" },
71618
+ currencyCode: { type: "string" },
71619
+ cohortSpec: { type: "object" },
71620
+ keepEmptyRows: { type: "boolean" },
71621
+ returnPropertyQuota: { type: "boolean" }
71622
+ },
71623
+ required: ["propertyId", "metrics", "dateRanges", "pivots"]
71624
+ },
71625
+ request: {
71626
+ method: "POST",
71627
+ path: "/v1beta/properties/{propertyId}:runPivotReport",
71628
+ body: {
71629
+ dimensions: "{dimensions}",
71630
+ metrics: "{metrics}",
71631
+ dateRanges: "{dateRanges}",
71632
+ pivots: "{pivots}",
71633
+ dimensionFilter: "{dimensionFilter}",
71634
+ metricFilter: "{metricFilter}",
71635
+ currencyCode: "{currencyCode}",
71636
+ cohortSpec: "{cohortSpec}",
71637
+ keepEmptyRows: "{keepEmptyRows}",
71638
+ returnPropertyQuota: "{returnPropertyQuota}"
71639
+ }
71640
+ },
71641
+ requiredScopes: ["https://www.googleapis.com/auth/analytics.readonly"]
71642
+ },
71643
+ {
71644
+ name: "properties.runRealtimeReport",
71645
+ class: "read",
71646
+ description: "Run a realtime report \u2014 surfaces events that happened in the last 30 minutes. No dateRanges; the realtime window is implicit (POST /v1beta/properties/{propertyId}:runRealtimeReport).",
71647
+ parameters: {
71648
+ type: "object",
71649
+ properties: {
71650
+ propertyId: { type: "string", description: "Numeric GA4 property id." },
71651
+ dimensions: { type: "array", items: { type: "object" } },
71652
+ metrics: { type: "array", items: { type: "object" } },
71653
+ dimensionFilter: { type: "object" },
71654
+ metricFilter: { type: "object" },
71655
+ limit: { type: "integer", minimum: 1, maximum: 25e4 },
71656
+ metricAggregations: { type: "array", items: { type: "string" } },
71657
+ orderBys: { type: "array", items: { type: "object" } },
71658
+ returnPropertyQuota: { type: "boolean" },
71659
+ minuteRanges: {
71660
+ type: "array",
71661
+ description: 'Optional minute-window specifications, e.g. [{ "name": "last5", "startMinutesAgo": 5, "endMinutesAgo": 0 }]. Defaults to the last 30 minutes.',
71662
+ items: {
71663
+ type: "object",
71664
+ properties: {
71665
+ name: { type: "string" },
71666
+ startMinutesAgo: { type: "integer", minimum: 0, maximum: 29 },
71667
+ endMinutesAgo: { type: "integer", minimum: 0, maximum: 29 }
71668
+ }
71669
+ }
71670
+ }
71671
+ },
71672
+ required: ["propertyId", "metrics"]
71673
+ },
71674
+ request: {
71675
+ method: "POST",
71676
+ path: "/v1beta/properties/{propertyId}:runRealtimeReport",
71677
+ body: {
71678
+ dimensions: "{dimensions}",
71679
+ metrics: "{metrics}",
71680
+ dimensionFilter: "{dimensionFilter}",
71681
+ metricFilter: "{metricFilter}",
71682
+ limit: "{limit}",
71683
+ metricAggregations: "{metricAggregations}",
71684
+ orderBys: "{orderBys}",
71685
+ returnPropertyQuota: "{returnPropertyQuota}",
71686
+ minuteRanges: "{minuteRanges}"
71687
+ }
71688
+ },
71689
+ requiredScopes: ["https://www.googleapis.com/auth/analytics.readonly"]
71690
+ },
71691
+ {
71692
+ name: "properties.checkCompatibility",
71693
+ class: "read",
71694
+ description: "Check whether a given dimension/metric combination is compatible before issuing a full runReport \u2014 GA4 rejects incompatible combos (e.g. cohort dimensions with non-cohort metrics) with a hard error (POST /v1beta/properties/{propertyId}:checkCompatibility).",
71695
+ parameters: {
71696
+ type: "object",
71697
+ properties: {
71698
+ propertyId: { type: "string", description: "Numeric GA4 property id." },
71699
+ dimensions: { type: "array", items: { type: "object" } },
71700
+ metrics: { type: "array", items: { type: "object" } },
71701
+ dimensionFilter: { type: "object" },
71702
+ metricFilter: { type: "object" },
71703
+ compatibilityFilter: {
71704
+ type: "string",
71705
+ enum: ["COMPATIBILITY_UNSPECIFIED", "COMPATIBLE", "INCOMPATIBLE"],
71706
+ description: "Restrict the response to compatible or incompatible entries only."
71707
+ }
71708
+ },
71709
+ required: ["propertyId"]
71710
+ },
71711
+ request: {
71712
+ method: "POST",
71713
+ path: "/v1beta/properties/{propertyId}:checkCompatibility",
71714
+ body: {
71715
+ dimensions: "{dimensions}",
71716
+ metrics: "{metrics}",
71717
+ dimensionFilter: "{dimensionFilter}",
71718
+ metricFilter: "{metricFilter}",
71719
+ compatibilityFilter: "{compatibilityFilter}"
71720
+ }
71721
+ },
71722
+ requiredScopes: ["https://www.googleapis.com/auth/analytics.readonly"]
71723
+ }
71724
+ ]
71725
+ });
71726
+
71727
+ // src/connectors/adapters/google-meet.ts
71728
+ var googleMeetConnector = declarativeRestConnector({
71729
+ kind: "google-meet",
71730
+ displayName: "Google Meet",
71731
+ description: "Create Google Meet spaces, fetch post-meeting conference records, and read participants, recordings, and transcripts via the Google Meet REST API v2.",
71732
+ auth: {
71733
+ kind: "oauth2",
71734
+ authorizationUrl: "https://accounts.google.com/o/oauth2/v2/auth",
71735
+ tokenUrl: "https://oauth2.googleapis.com/token",
71736
+ scopes: [
71737
+ "https://www.googleapis.com/auth/meetings.space.created",
71738
+ "https://www.googleapis.com/auth/meetings.space.readonly",
71739
+ "https://www.googleapis.com/auth/meetings.space.settings",
71740
+ "https://www.googleapis.com/auth/drive.readonly"
71741
+ ],
71742
+ clientIdEnv: "GOOGLE_OAUTH_CLIENT_ID",
71743
+ clientSecretEnv: "GOOGLE_OAUTH_CLIENT_SECRET",
71744
+ extraAuthParams: {
71745
+ access_type: "offline",
71746
+ prompt: "consent",
71747
+ include_granted_scopes: "true"
71748
+ }
71749
+ },
71750
+ category: "calendar",
71751
+ defaultConsistencyModel: "authoritative",
71752
+ baseUrl: "https://meet.googleapis.com",
71753
+ // /v2/spaces/{name} requires a real space id; the cheapest token-validity
71754
+ // probe Meet exposes is creating a throwaway space, which has a side effect
71755
+ // we don't want in a connection test. Skip the in-band test — the adapter
71756
+ // contract treats a missing `test` as ok and connection issuance still
71757
+ // catches the auth handshake at exchange time.
71758
+ capabilities: [
71759
+ {
71760
+ name: "spaces.create",
71761
+ class: "mutation",
71762
+ description: "Create a Meet space and return its meet.google.com URL. The space lives until the calling user deletes it or it expires per Google retention rules.",
71763
+ parameters: {
71764
+ type: "object",
71765
+ properties: {
71766
+ config: {
71767
+ type: "object",
71768
+ description: "Optional SpaceConfig: accessType (OPEN | TRUSTED | RESTRICTED), entryPointAccess (ALL | CREATOR_APP_ONLY), moderation, attendanceReport, artifactConfig, chatRestriction, presentRestriction, defaultJoinAsViewerType."
71769
+ }
71770
+ }
71771
+ },
71772
+ request: {
71773
+ method: "POST",
71774
+ path: "/v2/spaces",
71775
+ body: {
71776
+ config: "{config}"
71777
+ }
71778
+ },
71779
+ // Meet's spaces.create is a pure side-effect; no upstream idempotency
71780
+ // key on this endpoint, so a retry produces a second space. Mark
71781
+ // accordingly so the MutationGuard layer enforces idempotency.
71782
+ cas: "none",
71783
+ externalEffect: true,
71784
+ requiredScopes: ["https://www.googleapis.com/auth/meetings.space.created"]
71785
+ },
71786
+ {
71787
+ name: "spaces.get",
71788
+ class: "read",
71789
+ description: 'Read a Meet space by resource name (e.g. "spaces/abc-defg-hij") or by short meeting code.',
71790
+ parameters: {
71791
+ type: "object",
71792
+ properties: {
71793
+ name: {
71794
+ type: "string",
71795
+ description: 'Resource name like "spaces/{space_id}" or "spaces/{meeting_code}".'
71796
+ }
71797
+ },
71798
+ required: ["name"]
71799
+ },
71800
+ request: {
71801
+ method: "GET",
71802
+ path: "/v2/{name}"
71803
+ },
71804
+ requiredScopes: ["https://www.googleapis.com/auth/meetings.space.readonly"]
71805
+ },
71806
+ {
71807
+ name: "spaces.update",
71808
+ class: "mutation",
71809
+ description: "Patch a Meet space (accessType, entryPointAccess, moderation toggles, artifactConfig, chat/present restrictions). Caller supplies updateMask to specify mutated fields.",
71810
+ parameters: {
71811
+ type: "object",
71812
+ properties: {
71813
+ name: { type: "string", description: 'Resource name like "spaces/{space_id}".' },
71814
+ updateMask: {
71815
+ type: "string",
71816
+ description: 'Comma-separated FieldMask of mutated fields, e.g. "config.accessType,config.moderation".'
71817
+ },
71818
+ config: { type: "object", description: "New SpaceConfig values." }
71819
+ },
71820
+ required: ["name"]
71821
+ },
71822
+ request: {
71823
+ method: "PATCH",
71824
+ path: "/v2/{name}",
71825
+ query: {
71826
+ updateMask: "{updateMask}"
71827
+ },
71828
+ body: {
71829
+ config: "{config}"
71830
+ }
71831
+ },
71832
+ cas: "native-idempotency",
71833
+ externalEffect: true,
71834
+ requiredScopes: ["https://www.googleapis.com/auth/meetings.space.settings"]
71835
+ },
71836
+ {
71837
+ name: "spaces.endActiveConference",
71838
+ class: "mutation",
71839
+ description: "Terminate the currently active conference inside a Meet space. No-op (HTTP 200) if no conference is active.",
71840
+ parameters: {
71841
+ type: "object",
71842
+ properties: {
71843
+ name: { type: "string", description: 'Resource name like "spaces/{space_id}".' }
71844
+ },
71845
+ required: ["name"]
71846
+ },
71847
+ request: {
71848
+ method: "POST",
71849
+ path: "/v2/{name}:endActiveConference",
71850
+ body: {}
71851
+ },
71852
+ cas: "native-idempotency",
71853
+ externalEffect: true,
71854
+ requiredScopes: ["https://www.googleapis.com/auth/meetings.space.created"]
71855
+ },
71856
+ {
71857
+ name: "conferenceRecords.list",
71858
+ class: "read",
71859
+ description: "List conference records for meetings the calling user attended or hosted. Supports server-side filtering by space.name and end_time.",
71860
+ parameters: {
71861
+ type: "object",
71862
+ properties: {
71863
+ pageSize: { type: "integer", minimum: 1, maximum: 100 },
71864
+ pageToken: { type: "string" },
71865
+ filter: {
71866
+ type: "string",
71867
+ description: `EBNF filter, e.g. 'space.name="spaces/abc"' or 'end_time>="2024-01-01T00:00:00Z"'.`
71868
+ }
71869
+ }
71870
+ },
71871
+ request: {
71872
+ method: "GET",
71873
+ path: "/v2/conferenceRecords",
71874
+ query: {
71875
+ pageSize: "{pageSize}",
71876
+ pageToken: "{pageToken}",
71877
+ filter: "{filter}"
71878
+ }
71879
+ },
71880
+ requiredScopes: ["https://www.googleapis.com/auth/meetings.space.readonly"]
71881
+ },
71882
+ {
71883
+ name: "conferenceRecords.get",
71884
+ class: "read",
71885
+ description: 'Read a conference record by resource name (e.g. "conferenceRecords/abc123").',
71886
+ parameters: {
71887
+ type: "object",
71888
+ properties: {
71889
+ name: { type: "string", description: 'Resource name like "conferenceRecords/{conference_record_id}".' }
71890
+ },
71891
+ required: ["name"]
71892
+ },
71893
+ request: {
71894
+ method: "GET",
71895
+ path: "/v2/{name}"
71896
+ },
71897
+ requiredScopes: ["https://www.googleapis.com/auth/meetings.space.readonly"]
71898
+ },
71899
+ {
71900
+ name: "conferenceRecords.participants.list",
71901
+ class: "read",
71902
+ description: "List participants for a finished conference, including anonymous and phone-dial-in attendees.",
71903
+ parameters: {
71904
+ type: "object",
71905
+ properties: {
71906
+ parent: { type: "string", description: "Parent conferenceRecords/{conference_record_id}." },
71907
+ pageSize: { type: "integer", minimum: 1, maximum: 250 },
71908
+ pageToken: { type: "string" },
71909
+ filter: { type: "string", description: `EBNF filter, e.g. 'earliest_start_time<="2024-01-01T00:00:00Z"'.` }
71910
+ },
71911
+ required: ["parent"]
71912
+ },
71913
+ request: {
71914
+ method: "GET",
71915
+ path: "/v2/{parent}/participants",
71916
+ query: {
71917
+ pageSize: "{pageSize}",
71918
+ pageToken: "{pageToken}",
71919
+ filter: "{filter}"
71920
+ }
71921
+ },
71922
+ requiredScopes: ["https://www.googleapis.com/auth/meetings.space.readonly"]
71923
+ },
71924
+ {
71925
+ name: "conferenceRecords.recordings.list",
71926
+ class: "read",
71927
+ description: "List recordings for a conference record. Each entry includes the Drive file id and DriveFileExportUri for downstream Drive fetches.",
71928
+ parameters: {
71929
+ type: "object",
71930
+ properties: {
71931
+ parent: { type: "string", description: "Parent conferenceRecords/{conference_record_id}." },
71932
+ pageSize: { type: "integer", minimum: 1, maximum: 100 },
71933
+ pageToken: { type: "string" }
71934
+ },
71935
+ required: ["parent"]
71936
+ },
71937
+ request: {
71938
+ method: "GET",
71939
+ path: "/v2/{parent}/recordings",
71940
+ query: {
71941
+ pageSize: "{pageSize}",
71942
+ pageToken: "{pageToken}"
71943
+ }
71944
+ },
71945
+ requiredScopes: ["https://www.googleapis.com/auth/meetings.space.readonly"]
71946
+ },
71947
+ {
71948
+ name: "conferenceRecords.recordings.get",
71949
+ class: "read",
71950
+ description: "Read a single recording by resource name.",
71951
+ parameters: {
71952
+ type: "object",
71953
+ properties: {
71954
+ name: {
71955
+ type: "string",
71956
+ description: 'Resource name like "conferenceRecords/{conference_record_id}/recordings/{recording_id}".'
71957
+ }
71958
+ },
71959
+ required: ["name"]
71960
+ },
71961
+ request: {
71962
+ method: "GET",
71963
+ path: "/v2/{name}"
71964
+ },
71965
+ requiredScopes: ["https://www.googleapis.com/auth/meetings.space.readonly"]
71966
+ },
71967
+ {
71968
+ name: "conferenceRecords.transcripts.list",
71969
+ class: "read",
71970
+ description: "List transcripts (auto-generated captions exports) for a conference record.",
71971
+ parameters: {
71972
+ type: "object",
71973
+ properties: {
71974
+ parent: { type: "string", description: "Parent conferenceRecords/{conference_record_id}." },
71975
+ pageSize: { type: "integer", minimum: 1, maximum: 100 },
71976
+ pageToken: { type: "string" }
71977
+ },
71978
+ required: ["parent"]
71979
+ },
71980
+ request: {
71981
+ method: "GET",
71982
+ path: "/v2/{parent}/transcripts",
71983
+ query: {
71984
+ pageSize: "{pageSize}",
71985
+ pageToken: "{pageToken}"
71986
+ }
71987
+ },
71988
+ requiredScopes: ["https://www.googleapis.com/auth/meetings.space.readonly"]
71989
+ },
71990
+ {
71991
+ name: "conferenceRecords.transcripts.get",
71992
+ class: "read",
71993
+ description: "Read a transcript by resource name; payload links to the Drive Doc holding the transcript text.",
71994
+ parameters: {
71995
+ type: "object",
71996
+ properties: {
71997
+ name: {
71998
+ type: "string",
71999
+ description: 'Resource name like "conferenceRecords/{conference_record_id}/transcripts/{transcript_id}".'
72000
+ }
72001
+ },
72002
+ required: ["name"]
72003
+ },
72004
+ request: {
72005
+ method: "GET",
72006
+ path: "/v2/{name}"
72007
+ },
72008
+ requiredScopes: ["https://www.googleapis.com/auth/meetings.space.readonly"]
72009
+ }
72010
+ ]
72011
+ });
72012
+
71104
72013
  // src/connectors/adapters/youtube-data.ts
71105
72014
  var youtubeDataConnector = declarativeRestConnector({
71106
72015
  kind: "youtube",
@@ -86864,123 +87773,6 @@ var microsoftPowerBiConnector = declarativeRestConnector({
86864
87773
  ]
86865
87774
  });
86866
87775
 
86867
- // src/connectors/adapters/microsoft-outlook-calendar.ts
86868
- var microsoftOutlookCalendarConnector = declarativeRestConnector({
86869
- kind: "microsoft-outlook-calendar",
86870
- displayName: "Microsoft Outlook Calendar",
86871
- description: "Create, list, and delete Outlook/Microsoft 365 calendar events via Microsoft Graph.",
86872
- auth: {
86873
- kind: "oauth2",
86874
- authorizationUrl: "https://login.microsoftonline.com/common/oauth2/v2.0/authorize",
86875
- tokenUrl: "https://login.microsoftonline.com/common/oauth2/v2.0/token",
86876
- scopes: ["offline_access", "Calendars.ReadWrite", "User.Read"],
86877
- clientIdEnv: "MS_OAUTH_CLIENT_ID",
86878
- clientSecretEnv: "MS_OAUTH_CLIENT_SECRET"
86879
- },
86880
- category: "calendar",
86881
- defaultConsistencyModel: "authoritative",
86882
- baseUrl: "https://graph.microsoft.com/v1.0",
86883
- test: { method: "GET", path: "/me" },
86884
- capabilities: [
86885
- {
86886
- name: "create.event",
86887
- class: "mutation",
86888
- description: "Create a calendar event on the signed-in user's primary calendar, or on a specific calendarId when supplied.",
86889
- parameters: {
86890
- type: "object",
86891
- properties: {
86892
- calendarId: { type: "string" },
86893
- subject: { type: "string" },
86894
- body: { type: "object" },
86895
- start: { type: "object" },
86896
- end: { type: "object" },
86897
- location: { type: "object" },
86898
- attendees: { type: "array", items: { type: "object" } },
86899
- isOnlineMeeting: { type: "boolean" },
86900
- onlineMeetingProvider: { type: "string" },
86901
- showAs: { type: "string" },
86902
- sensitivity: { type: "string" },
86903
- importance: { type: "string" },
86904
- categories: { type: "array", items: { type: "string" } },
86905
- reminderMinutesBeforeStart: { type: "integer" },
86906
- isAllDay: { type: "boolean" },
86907
- recurrence: { type: "object" },
86908
- transactionId: { type: "string" }
86909
- },
86910
- required: ["subject", "start", "end"]
86911
- },
86912
- request: {
86913
- method: "POST",
86914
- path: "/me/calendars/{calendarId}/events",
86915
- body: {
86916
- subject: "{subject}",
86917
- body: "{body}",
86918
- start: "{start}",
86919
- end: "{end}",
86920
- location: "{location}",
86921
- attendees: "{attendees}",
86922
- isOnlineMeeting: "{isOnlineMeeting}",
86923
- onlineMeetingProvider: "{onlineMeetingProvider}",
86924
- showAs: "{showAs}",
86925
- sensitivity: "{sensitivity}",
86926
- importance: "{importance}",
86927
- categories: "{categories}",
86928
- reminderMinutesBeforeStart: "{reminderMinutesBeforeStart}",
86929
- isAllDay: "{isAllDay}",
86930
- recurrence: "{recurrence}",
86931
- transactionId: "{transactionId}"
86932
- }
86933
- },
86934
- cas: "native-idempotency",
86935
- requiredScopes: ["Calendars.ReadWrite"]
86936
- },
86937
- {
86938
- name: "delete.event",
86939
- class: "mutation",
86940
- description: "Delete a calendar event by id from the signed-in user mailbox.",
86941
- parameters: {
86942
- type: "object",
86943
- properties: { eventId: { type: "string" } },
86944
- required: ["eventId"]
86945
- },
86946
- request: { method: "DELETE", path: "/me/events/{eventId}" },
86947
- cas: "native-idempotency",
86948
- externalEffect: true,
86949
- requiredScopes: ["Calendars.ReadWrite"]
86950
- },
86951
- {
86952
- name: "list.events",
86953
- class: "read",
86954
- description: "List events on a calendar with OData paging/filtering ($top, $skip, $filter, $select, $orderby, $search). Targets the user's primary calendar unless calendarId is supplied.",
86955
- parameters: {
86956
- type: "object",
86957
- properties: {
86958
- calendarId: { type: "string" },
86959
- $top: { type: "integer" },
86960
- $skip: { type: "integer" },
86961
- $filter: { type: "string" },
86962
- $select: { type: "string" },
86963
- $orderby: { type: "string" },
86964
- $search: { type: "string" }
86965
- }
86966
- },
86967
- request: {
86968
- method: "GET",
86969
- path: "/me/calendars/{calendarId}/events",
86970
- query: {
86971
- $top: "{$top}",
86972
- $skip: "{$skip}",
86973
- $filter: "{$filter}",
86974
- $select: "{$select}",
86975
- $orderby: "{$orderby}",
86976
- $search: "{$search}"
86977
- }
86978
- },
86979
- requiredScopes: ["Calendars.ReadWrite"]
86980
- }
86981
- ]
86982
- });
86983
-
86984
87776
  // src/connectors/adapters/microsoft-onenote.ts
86985
87777
  var microsoftOnenoteConnector = declarativeRestConnector({
86986
87778
  kind: "microsoft-onenote",
@@ -87200,299 +87992,6 @@ var microsoftOnenoteConnector = declarativeRestConnector({
87200
87992
  ]
87201
87993
  });
87202
87994
 
87203
- // src/connectors/adapters/microsoft-outlook.ts
87204
- var microsoftOutlookConnector = declarativeRestConnector({
87205
- kind: "microsoft-outlook",
87206
- displayName: "Microsoft Outlook",
87207
- description: "Send, draft, reply to, forward, search, label, and organize email in the signed-in user's Outlook mailbox via Microsoft Graph.",
87208
- auth: {
87209
- kind: "oauth2",
87210
- authorizationUrl: "https://login.microsoftonline.com/common/oauth2/v2.0/authorize",
87211
- tokenUrl: "https://login.microsoftonline.com/common/oauth2/v2.0/token",
87212
- scopes: [
87213
- "offline_access",
87214
- "User.Read",
87215
- "Mail.ReadWrite",
87216
- "Mail.Send",
87217
- "MailboxSettings.Read"
87218
- ],
87219
- clientIdEnv: "MS_OAUTH_CLIENT_ID",
87220
- clientSecretEnv: "MS_OAUTH_CLIENT_SECRET"
87221
- },
87222
- category: "comms",
87223
- defaultConsistencyModel: "authoritative",
87224
- baseUrl: "https://graph.microsoft.com/v1.0",
87225
- test: { method: "GET", path: "/me" },
87226
- capabilities: [
87227
- {
87228
- name: "email.send",
87229
- class: "mutation",
87230
- description: "Send an email immediately from the signed-in user's mailbox. Optionally saves the sent message to the Sent Items folder.",
87231
- parameters: {
87232
- type: "object",
87233
- properties: {
87234
- subject: { type: "string" },
87235
- body: { type: "object" },
87236
- toRecipients: { type: "array", items: { type: "object" } },
87237
- ccRecipients: { type: "array", items: { type: "object" } },
87238
- bccRecipients: { type: "array", items: { type: "object" } },
87239
- attachments: { type: "array", items: { type: "object" } },
87240
- saveToSentItems: { type: "boolean" }
87241
- },
87242
- required: ["subject", "body", "toRecipients"]
87243
- },
87244
- request: {
87245
- method: "POST",
87246
- path: "/me/sendMail",
87247
- body: {
87248
- message: {
87249
- subject: "{subject}",
87250
- body: "{body}",
87251
- toRecipients: "{toRecipients}",
87252
- ccRecipients: "{ccRecipients}",
87253
- bccRecipients: "{bccRecipients}",
87254
- attachments: "{attachments}"
87255
- },
87256
- saveToSentItems: "{saveToSentItems}"
87257
- }
87258
- },
87259
- cas: "none",
87260
- externalEffect: true,
87261
- requiredScopes: ["Mail.Send"]
87262
- },
87263
- {
87264
- name: "email.draft.create",
87265
- class: "mutation",
87266
- description: "Create a draft email in the signed-in user mailbox without sending it.",
87267
- parameters: {
87268
- type: "object",
87269
- properties: {
87270
- subject: { type: "string" },
87271
- body: { type: "object" },
87272
- toRecipients: { type: "array", items: { type: "object" } },
87273
- ccRecipients: { type: "array", items: { type: "object" } },
87274
- bccRecipients: { type: "array", items: { type: "object" } },
87275
- importance: { type: "string" },
87276
- categories: { type: "array", items: { type: "string" } }
87277
- },
87278
- required: ["subject", "body"]
87279
- },
87280
- request: {
87281
- method: "POST",
87282
- path: "/me/messages",
87283
- body: {
87284
- subject: "{subject}",
87285
- body: "{body}",
87286
- toRecipients: "{toRecipients}",
87287
- ccRecipients: "{ccRecipients}",
87288
- bccRecipients: "{bccRecipients}",
87289
- importance: "{importance}",
87290
- categories: "{categories}"
87291
- }
87292
- },
87293
- cas: "native-idempotency",
87294
- requiredScopes: ["Mail.ReadWrite"]
87295
- },
87296
- {
87297
- name: "email.draft.send",
87298
- class: "mutation",
87299
- description: "Send a previously created draft message by id.",
87300
- parameters: {
87301
- type: "object",
87302
- properties: { messageId: { type: "string" } },
87303
- required: ["messageId"]
87304
- },
87305
- request: { method: "POST", path: "/me/messages/{messageId}/send" },
87306
- cas: "none",
87307
- externalEffect: true,
87308
- requiredScopes: ["Mail.Send"]
87309
- },
87310
- {
87311
- name: "email.reply",
87312
- class: "mutation",
87313
- description: "Reply to an existing message. When comment is provided alone, Graph generates the reply body; when message is provided, it overrides recipients/body.",
87314
- parameters: {
87315
- type: "object",
87316
- properties: {
87317
- messageId: { type: "string" },
87318
- comment: { type: "string" },
87319
- message: { type: "object" }
87320
- },
87321
- required: ["messageId"]
87322
- },
87323
- request: {
87324
- method: "POST",
87325
- path: "/me/messages/{messageId}/reply",
87326
- body: { comment: "{comment}", message: "{message}" }
87327
- },
87328
- cas: "none",
87329
- externalEffect: true,
87330
- requiredScopes: ["Mail.Send"]
87331
- },
87332
- {
87333
- name: "email.forward",
87334
- class: "mutation",
87335
- description: "Forward an existing message to one or more recipients with an optional comment.",
87336
- parameters: {
87337
- type: "object",
87338
- properties: {
87339
- messageId: { type: "string" },
87340
- toRecipients: { type: "array", items: { type: "object" } },
87341
- comment: { type: "string" }
87342
- },
87343
- required: ["messageId", "toRecipients"]
87344
- },
87345
- request: {
87346
- method: "POST",
87347
- path: "/me/messages/{messageId}/forward",
87348
- body: { toRecipients: "{toRecipients}", comment: "{comment}" }
87349
- },
87350
- cas: "none",
87351
- externalEffect: true,
87352
- requiredScopes: ["Mail.Send"]
87353
- },
87354
- {
87355
- name: "email.move",
87356
- class: "mutation",
87357
- description: "Move a message to a destination mail folder by id (or well-known name like inbox/archive).",
87358
- parameters: {
87359
- type: "object",
87360
- properties: {
87361
- messageId: { type: "string" },
87362
- destinationId: { type: "string" }
87363
- },
87364
- required: ["messageId", "destinationId"]
87365
- },
87366
- request: {
87367
- method: "POST",
87368
- path: "/me/messages/{messageId}/move",
87369
- body: { destinationId: "{destinationId}" }
87370
- },
87371
- cas: "native-idempotency",
87372
- requiredScopes: ["Mail.ReadWrite"]
87373
- },
87374
- {
87375
- name: "email.label.add",
87376
- class: "mutation",
87377
- description: "Tag a message with one or more Outlook categories (labels). Pass the desired full set; Graph replaces the categories array.",
87378
- parameters: {
87379
- type: "object",
87380
- properties: {
87381
- messageId: { type: "string" },
87382
- categories: { type: "array", items: { type: "string" } }
87383
- },
87384
- required: ["messageId", "categories"]
87385
- },
87386
- request: {
87387
- method: "PATCH",
87388
- path: "/me/messages/{messageId}",
87389
- body: { categories: "{categories}" }
87390
- },
87391
- cas: "optimistic-read-verify",
87392
- requiredScopes: ["Mail.ReadWrite"]
87393
- },
87394
- {
87395
- name: "email.label.remove",
87396
- class: "mutation",
87397
- description: "Remove labels from a message by writing the surviving categories array. Caller computes the remaining set and supplies it explicitly.",
87398
- parameters: {
87399
- type: "object",
87400
- properties: {
87401
- messageId: { type: "string" },
87402
- categories: { type: "array", items: { type: "string" } }
87403
- },
87404
- required: ["messageId", "categories"]
87405
- },
87406
- request: {
87407
- method: "PATCH",
87408
- path: "/me/messages/{messageId}",
87409
- body: { categories: "{categories}" }
87410
- },
87411
- cas: "optimistic-read-verify",
87412
- externalEffect: true,
87413
- requiredScopes: ["Mail.ReadWrite"]
87414
- },
87415
- {
87416
- name: "email.find",
87417
- class: "read",
87418
- description: "Search messages in a folder using OData $search/$filter with $top, $select, $orderby. Folder defaults to the well-known inbox if omitted.",
87419
- parameters: {
87420
- type: "object",
87421
- properties: {
87422
- mailFolderId: { type: "string" },
87423
- $search: { type: "string" },
87424
- $filter: { type: "string" },
87425
- $select: { type: "string" },
87426
- $top: { type: "integer" },
87427
- $orderby: { type: "string" }
87428
- }
87429
- },
87430
- request: {
87431
- method: "GET",
87432
- path: "/me/mailFolders/{mailFolderId}/messages",
87433
- query: {
87434
- $search: "{$search}",
87435
- $filter: "{$filter}",
87436
- $select: "{$select}",
87437
- $top: "{$top}",
87438
- $orderby: "{$orderby}"
87439
- }
87440
- },
87441
- requiredScopes: ["Mail.ReadWrite"]
87442
- },
87443
- {
87444
- name: "email.attachment.download",
87445
- class: "read",
87446
- description: "Read an attachment record (metadata plus base64 contentBytes for file attachments) for a message by attachment id.",
87447
- parameters: {
87448
- type: "object",
87449
- properties: {
87450
- messageId: { type: "string" },
87451
- attachmentId: { type: "string" }
87452
- },
87453
- required: ["messageId", "attachmentId"]
87454
- },
87455
- request: {
87456
- method: "GET",
87457
- path: "/me/messages/{messageId}/attachments/{attachmentId}"
87458
- },
87459
- requiredScopes: ["Mail.ReadWrite"]
87460
- },
87461
- {
87462
- name: "email.approval.request",
87463
- class: "mutation",
87464
- description: "Send an approval-request email by composing a structured message body and sending it through /me/sendMail. The body should encode the approval prompt and reply-handling instructions.",
87465
- parameters: {
87466
- type: "object",
87467
- properties: {
87468
- subject: { type: "string" },
87469
- body: { type: "object" },
87470
- toRecipients: { type: "array", items: { type: "object" } },
87471
- ccRecipients: { type: "array", items: { type: "object" } },
87472
- saveToSentItems: { type: "boolean" }
87473
- },
87474
- required: ["subject", "body", "toRecipients"]
87475
- },
87476
- request: {
87477
- method: "POST",
87478
- path: "/me/sendMail",
87479
- body: {
87480
- message: {
87481
- subject: "{subject}",
87482
- body: "{body}",
87483
- toRecipients: "{toRecipients}",
87484
- ccRecipients: "{ccRecipients}"
87485
- },
87486
- saveToSentItems: "{saveToSentItems}"
87487
- }
87488
- },
87489
- cas: "none",
87490
- externalEffect: true,
87491
- requiredScopes: ["Mail.Send"]
87492
- }
87493
- ]
87494
- });
87495
-
87496
87995
  // src/connectors/adapters/microsoft-excel-365.ts
87497
87996
  var microsoftExcel365Connector = declarativeRestConnector({
87498
87997
  kind: "microsoft-excel-365",
@@ -88366,348 +88865,6 @@ var microsoftTodoConnector = declarativeRestConnector({
88366
88865
  ]
88367
88866
  });
88368
88867
 
88369
- // src/connectors/adapters/microsoft-sharepoint.ts
88370
- var microsoftSharepointConnector = declarativeRestConnector({
88371
- kind: "microsoft-sharepoint",
88372
- displayName: "Microsoft SharePoint",
88373
- description: "Read SharePoint site metadata, list items, and files; create folders, lists, list items, and pages via Microsoft Graph.",
88374
- auth: {
88375
- kind: "oauth2",
88376
- authorizationUrl: "https://login.microsoftonline.com/common/oauth2/v2.0/authorize",
88377
- tokenUrl: "https://login.microsoftonline.com/common/oauth2/v2.0/token",
88378
- scopes: [
88379
- "offline_access",
88380
- "Sites.ReadWrite.All",
88381
- "Files.ReadWrite.All"
88382
- ],
88383
- clientIdEnv: "MICROSOFT_SHAREPOINT_OAUTH_CLIENT_ID",
88384
- clientSecretEnv: "MICROSOFT_SHAREPOINT_OAUTH_CLIENT_SECRET"
88385
- },
88386
- category: "storage",
88387
- defaultConsistencyModel: "authoritative",
88388
- baseUrl: "https://graph.microsoft.com/v1.0",
88389
- test: { method: "GET", path: "/sites/root" },
88390
- capabilities: [
88391
- // ---------- Sites ----------
88392
- {
88393
- name: "find.site",
88394
- class: "read",
88395
- description: "Search SharePoint sites by display name or keyword (Graph $search).",
88396
- parameters: {
88397
- type: "object",
88398
- properties: {
88399
- search: { type: "string" },
88400
- $top: { type: "integer" }
88401
- },
88402
- required: ["search"]
88403
- },
88404
- request: {
88405
- method: "GET",
88406
- path: "/sites",
88407
- query: { search: "{search}", $top: "{$top}" }
88408
- },
88409
- requiredScopes: ["Sites.ReadWrite.All"]
88410
- },
88411
- {
88412
- name: "get.site.information",
88413
- class: "read",
88414
- description: "Read the metadata for a SharePoint site by site id.",
88415
- parameters: {
88416
- type: "object",
88417
- properties: { siteId: { type: "string" } },
88418
- required: ["siteId"]
88419
- },
88420
- request: { method: "GET", path: "/sites/{siteId}" },
88421
- requiredScopes: ["Sites.ReadWrite.All"]
88422
- },
88423
- // ---------- Folders / files ----------
88424
- {
88425
- name: "create.folder",
88426
- class: "mutation",
88427
- description: "Create a folder inside a site drive. Parent is identified by its drive item id (use the drive root id for top-level folders).",
88428
- parameters: {
88429
- type: "object",
88430
- properties: {
88431
- siteId: { type: "string" },
88432
- parentItemId: { type: "string" },
88433
- name: { type: "string" },
88434
- conflictBehavior: { type: "string" }
88435
- },
88436
- required: ["siteId", "parentItemId", "name"]
88437
- },
88438
- request: {
88439
- method: "POST",
88440
- path: "/sites/{siteId}/drive/items/{parentItemId}/children",
88441
- body: {
88442
- name: "{name}",
88443
- folder: {},
88444
- "@microsoft.graph.conflictBehavior": "{conflictBehavior}"
88445
- }
88446
- },
88447
- cas: "native-idempotency",
88448
- requiredScopes: ["Files.ReadWrite.All", "Sites.ReadWrite.All"]
88449
- },
88450
- {
88451
- name: "get.folder.contents",
88452
- class: "read",
88453
- description: "List the children of a folder in a site drive.",
88454
- parameters: {
88455
- type: "object",
88456
- properties: {
88457
- siteId: { type: "string" },
88458
- itemId: { type: "string" },
88459
- $top: { type: "integer" },
88460
- $select: { type: "string" }
88461
- },
88462
- required: ["siteId", "itemId"]
88463
- },
88464
- request: {
88465
- method: "GET",
88466
- path: "/sites/{siteId}/drive/items/{itemId}/children",
88467
- query: { $top: "{$top}", $select: "{$select}" }
88468
- },
88469
- requiredScopes: ["Files.ReadWrite.All", "Sites.ReadWrite.All"]
88470
- },
88471
- {
88472
- name: "find.file",
88473
- class: "read",
88474
- description: "Search drive items inside a site drive by name or content (Graph drive search).",
88475
- parameters: {
88476
- type: "object",
88477
- properties: {
88478
- siteId: { type: "string" },
88479
- query: { type: "string" },
88480
- $top: { type: "integer" }
88481
- },
88482
- required: ["siteId", "query"]
88483
- },
88484
- request: {
88485
- method: "GET",
88486
- path: "/sites/{siteId}/drive/root/search(q='{query}')",
88487
- query: { $top: "{$top}" }
88488
- },
88489
- requiredScopes: ["Files.ReadWrite.All", "Sites.ReadWrite.All"]
88490
- },
88491
- {
88492
- name: "upload.file",
88493
- class: "mutation",
88494
- description: "Upload (or replace) a small file at the given drive path. The body must be the JSON-encoded contents the agent provides as `content` (base64-encoded for binary payloads). For files larger than 4 MiB the caller should use the upload-session flow instead.",
88495
- parameters: {
88496
- type: "object",
88497
- properties: {
88498
- siteId: { type: "string" },
88499
- parentItemId: { type: "string" },
88500
- fileName: { type: "string" },
88501
- content: { type: "string" },
88502
- conflictBehavior: { type: "string" }
88503
- },
88504
- required: ["siteId", "parentItemId", "fileName", "content"]
88505
- },
88506
- request: {
88507
- method: "PUT",
88508
- path: "/sites/{siteId}/drive/items/{parentItemId}:/{fileName}:/content",
88509
- body: "{content}"
88510
- },
88511
- cas: "optimistic-read-verify",
88512
- requiredScopes: ["Files.ReadWrite.All", "Sites.ReadWrite.All"]
88513
- },
88514
- {
88515
- name: "copy.item",
88516
- class: "mutation",
88517
- description: "Copy a drive item into another drive. The destination is identified by a parentReference (driveId + id) and an optional new name.",
88518
- parameters: {
88519
- type: "object",
88520
- properties: {
88521
- siteId: { type: "string" },
88522
- itemId: { type: "string" },
88523
- parentReference: { type: "object" },
88524
- name: { type: "string" }
88525
- },
88526
- required: ["siteId", "itemId", "parentReference"]
88527
- },
88528
- request: {
88529
- method: "POST",
88530
- path: "/sites/{siteId}/drive/items/{itemId}/copy",
88531
- body: { parentReference: "{parentReference}", name: "{name}" }
88532
- },
88533
- cas: "native-idempotency",
88534
- requiredScopes: ["Files.ReadWrite.All", "Sites.ReadWrite.All"]
88535
- },
88536
- {
88537
- name: "copy.item.within.site",
88538
- class: "mutation",
88539
- description: "Copy a drive item to another folder inside the same site drive. The destination parent is identified by the target folder id.",
88540
- parameters: {
88541
- type: "object",
88542
- properties: {
88543
- siteId: { type: "string" },
88544
- itemId: { type: "string" },
88545
- targetParentId: { type: "string" },
88546
- name: { type: "string" }
88547
- },
88548
- required: ["siteId", "itemId", "targetParentId"]
88549
- },
88550
- request: {
88551
- method: "POST",
88552
- path: "/sites/{siteId}/drive/items/{itemId}/copy",
88553
- body: { parentReference: { id: "{targetParentId}" }, name: "{name}" }
88554
- },
88555
- cas: "native-idempotency",
88556
- requiredScopes: ["Files.ReadWrite.All", "Sites.ReadWrite.All"]
88557
- },
88558
- {
88559
- name: "move.file",
88560
- class: "mutation",
88561
- description: "Move (re-parent or rename) a drive item by patching its parentReference and/or name.",
88562
- parameters: {
88563
- type: "object",
88564
- properties: {
88565
- siteId: { type: "string" },
88566
- itemId: { type: "string" },
88567
- parentReference: { type: "object" },
88568
- name: { type: "string" }
88569
- },
88570
- required: ["siteId", "itemId", "parentReference"]
88571
- },
88572
- request: {
88573
- method: "PATCH",
88574
- path: "/sites/{siteId}/drive/items/{itemId}",
88575
- body: { parentReference: "{parentReference}", name: "{name}" }
88576
- },
88577
- cas: "etag-if-match",
88578
- requiredScopes: ["Files.ReadWrite.All", "Sites.ReadWrite.All"]
88579
- },
88580
- // ---------- Lists & list items ----------
88581
- {
88582
- name: "create.list",
88583
- class: "mutation",
88584
- description: "Create a SharePoint list on the site. `displayName` is required; `columns` and `list.template` are optional.",
88585
- parameters: {
88586
- type: "object",
88587
- properties: {
88588
- siteId: { type: "string" },
88589
- displayName: { type: "string" },
88590
- columns: { type: "array", items: { type: "object" } },
88591
- list: { type: "object" }
88592
- },
88593
- required: ["siteId", "displayName"]
88594
- },
88595
- request: {
88596
- method: "POST",
88597
- path: "/sites/{siteId}/lists",
88598
- body: { displayName: "{displayName}", columns: "{columns}", list: "{list}" }
88599
- },
88600
- cas: "native-idempotency",
88601
- requiredScopes: ["Sites.ReadWrite.All"]
88602
- },
88603
- {
88604
- name: "create.list.item",
88605
- class: "mutation",
88606
- description: "Create a new list item. `fields` is the column -> value map.",
88607
- parameters: {
88608
- type: "object",
88609
- properties: {
88610
- siteId: { type: "string" },
88611
- listId: { type: "string" },
88612
- fields: { type: "object" }
88613
- },
88614
- required: ["siteId", "listId", "fields"]
88615
- },
88616
- request: {
88617
- method: "POST",
88618
- path: "/sites/{siteId}/lists/{listId}/items",
88619
- body: { fields: "{fields}" }
88620
- },
88621
- cas: "native-idempotency",
88622
- requiredScopes: ["Sites.ReadWrite.All"]
88623
- },
88624
- {
88625
- name: "update.list.item",
88626
- class: "mutation",
88627
- description: "Patch the fields on an existing list item.",
88628
- parameters: {
88629
- type: "object",
88630
- properties: {
88631
- siteId: { type: "string" },
88632
- listId: { type: "string" },
88633
- itemId: { type: "string" },
88634
- fields: { type: "object" }
88635
- },
88636
- required: ["siteId", "listId", "itemId", "fields"]
88637
- },
88638
- request: {
88639
- method: "PATCH",
88640
- path: "/sites/{siteId}/lists/{listId}/items/{itemId}/fields",
88641
- body: "{fields}"
88642
- },
88643
- cas: "etag-if-match",
88644
- requiredScopes: ["Sites.ReadWrite.All"]
88645
- },
88646
- {
88647
- name: "delete.list.item",
88648
- class: "mutation",
88649
- description: "Delete a list item by id.",
88650
- parameters: {
88651
- type: "object",
88652
- properties: {
88653
- siteId: { type: "string" },
88654
- listId: { type: "string" },
88655
- itemId: { type: "string" }
88656
- },
88657
- required: ["siteId", "listId", "itemId"]
88658
- },
88659
- request: {
88660
- method: "DELETE",
88661
- path: "/sites/{siteId}/lists/{listId}/items/{itemId}"
88662
- },
88663
- cas: "native-idempotency",
88664
- requiredScopes: ["Sites.ReadWrite.All"]
88665
- },
88666
- {
88667
- name: "find.list.item",
88668
- class: "read",
88669
- description: "List items in a SharePoint list, optionally filtered with $filter / $expand=fields($select=...).",
88670
- parameters: {
88671
- type: "object",
88672
- properties: {
88673
- siteId: { type: "string" },
88674
- listId: { type: "string" },
88675
- $filter: { type: "string" },
88676
- $expand: { type: "string" },
88677
- $top: { type: "integer" }
88678
- },
88679
- required: ["siteId", "listId"]
88680
- },
88681
- request: {
88682
- method: "GET",
88683
- path: "/sites/{siteId}/lists/{listId}/items",
88684
- query: { $filter: "{$filter}", $expand: "{$expand}", $top: "{$top}" }
88685
- },
88686
- requiredScopes: ["Sites.ReadWrite.All"]
88687
- },
88688
- // ---------- Pages ----------
88689
- {
88690
- name: "publish.page",
88691
- class: "mutation",
88692
- description: "Publish a SharePoint site page by page id.",
88693
- parameters: {
88694
- type: "object",
88695
- properties: {
88696
- siteId: { type: "string" },
88697
- pageId: { type: "string" }
88698
- },
88699
- required: ["siteId", "pageId"]
88700
- },
88701
- request: {
88702
- method: "POST",
88703
- path: "/sites/{siteId}/pages/{pageId}/microsoft.graph.sitePage/publish"
88704
- },
88705
- cas: "native-idempotency",
88706
- requiredScopes: ["Sites.ReadWrite.All"]
88707
- }
88708
- ]
88709
- });
88710
-
88711
88868
  // src/connectors/adapters/millionverifier.ts
88712
88869
  var millionverifierConnector = declarativeRestConnector({
88713
88870
  kind: "millionverifier",
@@ -92609,82 +92766,6 @@ var mindStudioConnector = declarativeRestConnector({
92609
92766
  ]
92610
92767
  });
92611
92768
 
92612
- // src/connectors/adapters/microsoft-onedrive.ts
92613
- var microsoftOnedriveConnector = declarativeRestConnector({
92614
- kind: "microsoft-onedrive",
92615
- displayName: "Microsoft OneDrive",
92616
- description: "Upload, download, list files and folders in Microsoft OneDrive.",
92617
- auth: {
92618
- kind: "oauth2",
92619
- authorizationUrl: "https://login.microsoftonline.com/common/oauth2/v2.0/authorize",
92620
- tokenUrl: "https://login.microsoftonline.com/common/oauth2/v2.0/token",
92621
- scopes: ["Files.ReadWrite"],
92622
- clientIdEnv: "MICROSOFT_ONEDRIVE_OAUTH_CLIENT_ID",
92623
- clientSecretEnv: "MICROSOFT_ONEDRIVE_OAUTH_CLIENT_SECRET"
92624
- },
92625
- category: "storage",
92626
- defaultConsistencyModel: "authoritative",
92627
- baseUrl: "https://graph.microsoft.com/v1.0/me/drive",
92628
- test: { method: "GET", path: "/root" },
92629
- capabilities: [
92630
- {
92631
- name: "files.list",
92632
- class: "read",
92633
- description: "List files in OneDrive.",
92634
- parameters: {
92635
- type: "object",
92636
- properties: {
92637
- folderId: { type: "string", description: "Folder ID to list files from (optional, defaults to root)" }
92638
- },
92639
- required: []
92640
- },
92641
- request: { method: "GET", path: "/items/{folderId}/children", query: { $select: "id,name,size,webUrl,folder,file" } }
92642
- },
92643
- {
92644
- name: "folders.list",
92645
- class: "read",
92646
- description: "List folders in OneDrive.",
92647
- parameters: {
92648
- type: "object",
92649
- properties: {
92650
- parentId: { type: "string", description: "Parent folder ID (optional, defaults to root)" }
92651
- },
92652
- required: []
92653
- },
92654
- request: { method: "GET", path: "/items/{parentId}/children", query: { $filter: "folder ne null", $select: "id,name,webUrl" } }
92655
- },
92656
- {
92657
- name: "files.download",
92658
- class: "read",
92659
- description: "Download a file from OneDrive.",
92660
- parameters: {
92661
- type: "object",
92662
- properties: {
92663
- fileId: { type: "string" }
92664
- },
92665
- required: ["fileId"]
92666
- },
92667
- request: { method: "GET", path: "/items/{fileId}/content" }
92668
- },
92669
- {
92670
- name: "files.upload",
92671
- class: "mutation",
92672
- description: "Upload a file to OneDrive.",
92673
- parameters: {
92674
- type: "object",
92675
- properties: {
92676
- folderId: { type: "string", description: "Destination folder ID (optional, defaults to root)" },
92677
- fileName: { type: "string", description: "Name of the file to upload" },
92678
- fileContent: { type: "string", description: "File content (base64-encoded or raw)" }
92679
- },
92680
- required: ["fileName", "fileContent"]
92681
- },
92682
- request: { method: "PUT", path: "/items/{folderId}:/{fileName}:/content", body: "{fileContent}" },
92683
- cas: "native-idempotency"
92684
- }
92685
- ]
92686
- });
92687
-
92688
92769
  // src/connectors/adapters/mongodb.ts
92689
92770
  var mongodbConnector = declarativeRestConnector({
92690
92771
  kind: "mongodb",
@@ -93846,7 +93927,9 @@ var nocodbConnector = declarativeRestConnector({
93846
93927
  });
93847
93928
 
93848
93929
  // src/connectors/adapters/notion.ts
93849
- var notionConnector = declarativeRestConnector({
93930
+ var TOKEN_URL18 = "https://api.notion.com/v1/oauth/token";
93931
+ var NOTION_VERSION = "2022-06-28";
93932
+ var NOTION_SPEC = {
93850
93933
  kind: "notion",
93851
93934
  displayName: "Notion",
93852
93935
  description: "Query and manipulate Notion databases, pages, and blocks.",
@@ -93854,13 +93937,21 @@ var notionConnector = declarativeRestConnector({
93854
93937
  kind: "oauth2",
93855
93938
  authorizationUrl: "https://api.notion.com/v1/oauth/authorize",
93856
93939
  tokenUrl: "https://api.notion.com/v1/oauth/token",
93857
- scopes: ["read", "write"],
93940
+ // Notion does not use OAuth scopes the workspace owner picks which
93941
+ // pages/databases the integration sees during install. We declare an
93942
+ // empty scope list so the consent screen renders cleanly.
93943
+ scopes: [],
93858
93944
  clientIdEnv: "NOTION_OAUTH_CLIENT_ID",
93859
- clientSecretEnv: "NOTION_OAUTH_CLIENT_SECRET"
93945
+ clientSecretEnv: "NOTION_OAUTH_CLIENT_SECRET",
93946
+ extraAuthParams: { owner: "user" }
93860
93947
  },
93861
93948
  category: "doc",
93862
93949
  defaultConsistencyModel: "authoritative",
93863
93950
  baseUrl: "https://api.notion.com/v1",
93951
+ // Notion rejects any request without a Notion-Version header (400
93952
+ // invalid_request). The declarative executor merges defaultHeaders into
93953
+ // every read/mutation, so the whole surface carries it.
93954
+ defaultHeaders: { "Notion-Version": NOTION_VERSION },
93864
93955
  test: { method: "GET", path: "/users/me" },
93865
93956
  capabilities: [
93866
93957
  {
@@ -94091,9 +94182,168 @@ var notionConnector = declarativeRestConnector({
94091
94182
  },
94092
94183
  cas: "native-idempotency",
94093
94184
  externalEffect: true
94185
+ },
94186
+ {
94187
+ name: "databases.create",
94188
+ class: "mutation",
94189
+ description: "Create a new Notion database underneath a parent page.",
94190
+ parameters: {
94191
+ type: "object",
94192
+ properties: {
94193
+ parentPageId: { type: "string", description: "Parent page id under which to create the database." },
94194
+ title: {
94195
+ type: "array",
94196
+ description: "Notion rich_text array used as the database title."
94197
+ },
94198
+ properties: {
94199
+ type: "object",
94200
+ description: "Schema map \u2014 property name \u2192 Notion property schema."
94201
+ }
94202
+ },
94203
+ required: ["parentPageId", "title", "properties"]
94204
+ },
94205
+ request: {
94206
+ method: "POST",
94207
+ path: "/databases",
94208
+ body: {
94209
+ parent: { type: "page_id", page_id: "{parentPageId}" },
94210
+ title: "{title}",
94211
+ properties: "{properties}"
94212
+ }
94213
+ },
94214
+ cas: "native-idempotency",
94215
+ externalEffect: true
94216
+ },
94217
+ {
94218
+ name: "databases.update",
94219
+ class: "mutation",
94220
+ description: "Update a database title and/or schema.",
94221
+ parameters: {
94222
+ type: "object",
94223
+ properties: {
94224
+ databaseId: { type: "string" },
94225
+ title: { type: "array", description: "Optional new rich_text title." },
94226
+ properties: { type: "object", description: "Optional partial schema update." }
94227
+ },
94228
+ required: ["databaseId"]
94229
+ },
94230
+ request: {
94231
+ method: "PATCH",
94232
+ path: "/databases/{databaseId}",
94233
+ body: { title: "{title}", properties: "{properties}" }
94234
+ },
94235
+ cas: "native-idempotency",
94236
+ externalEffect: true
94094
94237
  }
94095
94238
  ]
94096
- });
94239
+ };
94240
+ async function databasesUpdate(inv) {
94241
+ const { title, properties } = inv.args;
94242
+ const body = {};
94243
+ if (title !== void 0) body.title = "{title}";
94244
+ if (properties !== void 0) body.properties = "{properties}";
94245
+ const response = await executeRestRequest(
94246
+ NOTION_SPEC,
94247
+ { method: "PATCH", path: "/databases/{databaseId}", body },
94248
+ inv
94249
+ );
94250
+ return {
94251
+ status: "committed",
94252
+ data: response.data,
94253
+ etagAfter: response.etag,
94254
+ committedAt: Date.now(),
94255
+ idempotentReplay: false
94256
+ };
94257
+ }
94258
+ function withNotionOverrides(base) {
94259
+ return {
94260
+ ...base,
94261
+ async executeMutation(inv) {
94262
+ if (inv.capabilityName === "databases.update") return databasesUpdate(inv);
94263
+ return base.executeMutation(inv);
94264
+ }
94265
+ };
94266
+ }
94267
+ var notionConnector = withNotionOverrides(declarativeRestConnector(NOTION_SPEC));
94268
+ function notion(opts) {
94269
+ const { clientId, clientSecret } = opts;
94270
+ return {
94271
+ ...withNotionOverrides(declarativeRestConnector(NOTION_SPEC)),
94272
+ /**
94273
+ * Notion's token endpoint follows RFC 6749 with one twist — it REQUIRES
94274
+ * HTTP Basic auth (client_id:client_secret) and does NOT accept the client
94275
+ * credentials in the form body, so we POST inline rather than via the
94276
+ * generic `exchangeAuthorizationCode` helper. The workspace_id/bot_id come
94277
+ * back in the response and we stash them in `metadata` so the agent can
94278
+ * address resources by workspace where useful.
94279
+ */
94280
+ async exchangeOAuth(input) {
94281
+ if (!clientId || !clientSecret) {
94282
+ throw new Error("Notion OAuth client not configured (NOTION_OAUTH_CLIENT_ID / _SECRET)");
94283
+ }
94284
+ const body = new URLSearchParams({
94285
+ grant_type: "authorization_code",
94286
+ code: input.code,
94287
+ redirect_uri: input.redirectUri,
94288
+ code_verifier: input.codeVerifier
94289
+ });
94290
+ const res = await fetch(TOKEN_URL18, {
94291
+ method: "POST",
94292
+ headers: {
94293
+ authorization: `Basic ${Buffer.from(`${clientId}:${clientSecret}`).toString("base64")}`,
94294
+ "content-type": "application/x-www-form-urlencoded",
94295
+ accept: "application/json",
94296
+ "Notion-Version": NOTION_VERSION
94297
+ },
94298
+ body,
94299
+ signal: AbortSignal.timeout(15e3)
94300
+ });
94301
+ if (!res.ok) {
94302
+ const text = await res.text().catch(() => "");
94303
+ throw new Error(`Notion OAuth token exchange failed: ${res.status} \u2014 ${text.slice(0, 200)}`);
94304
+ }
94305
+ const json = await res.json();
94306
+ return {
94307
+ credentials: {
94308
+ kind: "oauth2",
94309
+ accessToken: json.access_token,
94310
+ refreshToken: json.refresh_token
94311
+ },
94312
+ scopes: [],
94313
+ metadata: {
94314
+ botId: json.bot_id,
94315
+ workspaceId: json.workspace_id,
94316
+ workspaceName: json.workspace_name,
94317
+ // Operator picks the database in a follow-up step; default empty.
94318
+ databaseId: ""
94319
+ }
94320
+ };
94321
+ },
94322
+ /** Notion's standard tokens don't expire and don't ship a refresh_token.
94323
+ * If we have neither expiresAt nor refreshToken, treat the existing
94324
+ * access token as durable and return it unchanged. */
94325
+ async refreshToken(creds) {
94326
+ if (creds.kind !== "oauth2" || !creds.refreshToken) {
94327
+ if (creds.kind === "oauth2" && creds.accessToken && !creds.expiresAt) {
94328
+ return creds;
94329
+ }
94330
+ throw new Error("notion.refreshToken: missing refresh token");
94331
+ }
94332
+ const refreshed = await refreshAccessToken({
94333
+ tokenUrl: TOKEN_URL18,
94334
+ clientId,
94335
+ clientSecret,
94336
+ refreshToken: creds.refreshToken
94337
+ });
94338
+ return {
94339
+ kind: "oauth2",
94340
+ accessToken: refreshed.accessToken,
94341
+ refreshToken: refreshed.refreshToken ?? creds.refreshToken,
94342
+ expiresAt: refreshed.expiresIn ? Date.now() + refreshed.expiresIn * 1e3 : void 0
94343
+ };
94344
+ }
94345
+ };
94346
+ }
94097
94347
 
94098
94348
  // src/connectors/adapters/ntfy.ts
94099
94349
  var ntfyConnector = declarativeRestConnector({
@@ -111284,7 +111534,7 @@ var twinLabsConnector = declarativeRestConnector({
111284
111534
  });
111285
111535
 
111286
111536
  // src/connectors/adapters/twitter.ts
111287
- var AUTH_URL19 = "https://twitter.com/i/oauth2/authorize";
111537
+ var AUTH_URL18 = "https://twitter.com/i/oauth2/authorize";
111288
111538
  var TOKEN_URL19 = "https://api.twitter.com/2/oauth2/token";
111289
111539
  var SCOPES14 = ["tweet.read", "tweet.write", "users.read", "like.write", "offline.access"];
111290
111540
  var TWITTER_SPEC = {
@@ -111297,7 +111547,7 @@ var TWITTER_SPEC = {
111297
111547
  options: [
111298
111548
  {
111299
111549
  kind: "oauth2",
111300
- authorizationUrl: AUTH_URL19,
111550
+ authorizationUrl: AUTH_URL18,
111301
111551
  tokenUrl: TOKEN_URL19,
111302
111552
  scopes: SCOPES14,
111303
111553
  clientIdEnv: "TWITTER_OAUTH_CLIENT_ID",
@@ -118456,7 +118706,6 @@ export {
118456
118706
  microsoftCalendar,
118457
118707
  hubspot,
118458
118708
  slack,
118459
- notionDatabase,
118460
118709
  docuseal,
118461
118710
  twilioSmsConnector,
118462
118711
  phonyConnector,
@@ -118693,6 +118942,8 @@ export {
118693
118942
  ghostcmsConnector,
118694
118943
  gistlyConnector,
118695
118944
  googleSearchConsoleConnector,
118945
+ googleAnalyticsConnector,
118946
+ googleMeetConnector,
118696
118947
  youtubeDataConnector,
118697
118948
  googleCloudStorageConnector,
118698
118949
  googleBigqueryConnector,
@@ -118770,12 +119021,9 @@ export {
118770
119021
  microsoftDynamics365BusinessCentralConnector,
118771
119022
  microsoft365PlannerConnector,
118772
119023
  microsoftPowerBiConnector,
118773
- microsoftOutlookCalendarConnector,
118774
119024
  microsoftOnenoteConnector,
118775
- microsoftOutlookConnector,
118776
119025
  microsoftExcel365Connector,
118777
119026
  microsoftTodoConnector,
118778
- microsoftSharepointConnector,
118779
119027
  millionverifierConnector,
118780
119028
  mindeeConnector,
118781
119029
  mixmaxConnector,
@@ -118806,12 +119054,12 @@ export {
118806
119054
  mollieConnector,
118807
119055
  metabaseConnector,
118808
119056
  mindStudioConnector,
118809
- microsoftOnedriveConnector,
118810
119057
  mongodbConnector,
118811
119058
  niftyConnector,
118812
119059
  ninjapipeConnector,
118813
119060
  nocodbConnector,
118814
119061
  notionConnector,
119062
+ notion,
118815
119063
  ntfyConnector,
118816
119064
  odooConnector,
118817
119065
  omniCoConnector,
@@ -118940,4 +119188,4 @@ export {
118940
119188
  pipedreamConnector,
118941
119189
  adapters_exports
118942
119190
  };
118943
- //# sourceMappingURL=chunk-ZMAMOCJZ.js.map
119191
+ //# sourceMappingURL=chunk-6MUBOVI4.js.map