@openclaw/google-meet 2026.10.10 → 2026.11.5-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/assets/activity.svg +1 -1
  2. package/dist/.setup/{chrome-create-DIcW4QCh.mjs → chrome-create-BlDlV2YP.mjs} +11 -30
  3. package/dist/.setup/{cli-9linTFHb.mjs → cli-C-MrY7IZ.mjs} +275 -309
  4. package/dist/.setup/{cli-export-CaDYoSP8.mjs → cli-export-6eiywS3T.mjs} +16 -35
  5. package/dist/.setup/{cli-output-mode-BJSm88N9.mjs → cli-output-mode-DztqqVeZ.mjs} +5 -6
  6. package/dist/.setup/config-CMTw0Anh.mjs +110 -0
  7. package/dist/.setup/{create-D3fHR8uX.mjs → create-DMk4zbMq.mjs} +23 -9
  8. package/dist/.setup/{google-meet-platform-adapter-D7poqL1J.mjs → google-meet-platform-adapter-DgchqNLV.mjs} +52 -18
  9. package/dist/.setup/{node-host-B196lvNZ.mjs → node-host-BIZD9InM.mjs} +2 -2
  10. package/dist/.setup/{node-invoke-policy-BzRAe25r.mjs → node-invoke-policy-bg7p_BWB.mjs} +1 -1
  11. package/dist/.setup/oauth-DZkuGMs1.mjs +1 -0
  12. package/dist/.setup/{plugin-helpers-Buhixxsx.mjs → plugin-helpers-ChCBuyAl.mjs} +363 -69
  13. package/dist/.setup/{plugin-registration-B_nOxAym.mjs → plugin-registration-CAW7_zO_.mjs} +8 -8
  14. package/dist/.setup/{runtime-D-dwEsSW.mjs → runtime-Cyc6bv1i.mjs} +37 -38
  15. package/dist/.source-module-urls/c06239f68b6f4959b5d3db7e0cee004911d8eb43092f4135c729b507e37f6333.json +1 -1
  16. package/dist/cli-metadata.js +1 -1
  17. package/dist/doctor-contract-api.js +25 -21
  18. package/dist/index.js +14 -13
  19. package/node_modules/typebox/build/format/duration.d.mts +2 -2
  20. package/node_modules/typebox/build/format/duration.mjs +2 -2
  21. package/node_modules/typebox/build/format/idn_email.d.mts +1 -0
  22. package/node_modules/typebox/build/format/idn_email.mjs +1 -0
  23. package/node_modules/typebox/build/format/idn_hostname.d.mts +1 -1
  24. package/node_modules/typebox/build/format/idn_hostname.mjs +1 -1
  25. package/node_modules/typebox/build/format/ipv4.d.mts +2 -2
  26. package/node_modules/typebox/build/format/ipv4.mjs +2 -2
  27. package/node_modules/typebox/build/format/ipv6.d.mts +1 -1
  28. package/node_modules/typebox/build/format/ipv6.mjs +1 -1
  29. package/node_modules/typebox/build/format/relative_json_pointer.d.mts +2 -2
  30. package/node_modules/typebox/build/format/relative_json_pointer.mjs +2 -2
  31. package/node_modules/typebox/build/schema/build.mjs +1 -0
  32. package/node_modules/typebox/build/schema/engine/_unique.d.mts +4 -2
  33. package/node_modules/typebox/build/schema/engine/_unique.mjs +7 -3
  34. package/node_modules/typebox/build/schema/engine/additionalItems.mjs +3 -3
  35. package/node_modules/typebox/build/schema/engine/additionalProperties.d.mts +0 -3
  36. package/node_modules/typebox/build/schema/engine/additionalProperties.mjs +15 -17
  37. package/node_modules/typebox/build/schema/engine/contains.mjs +3 -3
  38. package/node_modules/typebox/build/schema/engine/index.d.mts +1 -0
  39. package/node_modules/typebox/build/schema/engine/index.mjs +1 -0
  40. package/node_modules/typebox/build/schema/engine/items.mjs +7 -4
  41. package/node_modules/typebox/build/schema/engine/maxContains.mjs +2 -2
  42. package/node_modules/typebox/build/schema/engine/minContains.mjs +3 -3
  43. package/node_modules/typebox/build/schema/engine/oneOf.mjs +2 -2
  44. package/node_modules/typebox/build/schema/engine/patternProperties.mjs +2 -2
  45. package/node_modules/typebox/build/schema/engine/propertyNames.mjs +2 -2
  46. package/node_modules/typebox/build/schema/engine/unevaluatedItems.mjs +2 -2
  47. package/node_modules/typebox/build/schema/engine/unevaluatedProperties.mjs +2 -2
  48. package/node_modules/typebox/build/system/hashing/hash.mjs +63 -34
  49. package/node_modules/typebox/build/system/locale/en_US.mjs +2 -1
  50. package/node_modules/typebox/build/system/memory/assign.d.mts +2 -8
  51. package/node_modules/typebox/build/system/memory/assign.mjs +13 -6
  52. package/node_modules/typebox/build/system/memory/clone.d.mts +4 -5
  53. package/node_modules/typebox/build/system/memory/clone.mjs +8 -96
  54. package/node_modules/typebox/build/system/memory/create.d.mts +1 -5
  55. package/node_modules/typebox/build/system/memory/create.mjs +18 -13
  56. package/node_modules/typebox/build/system/memory/deep.d.mts +2 -0
  57. package/node_modules/typebox/build/system/memory/deep.mjs +108 -0
  58. package/node_modules/typebox/build/system/memory/discard.d.mts +1 -1
  59. package/node_modules/typebox/build/system/memory/discard.mjs +9 -8
  60. package/node_modules/typebox/build/system/memory/finalize.d.mts +4 -0
  61. package/node_modules/typebox/build/system/memory/finalize.mjs +30 -0
  62. package/node_modules/typebox/build/system/memory/keys.d.mts +2 -0
  63. package/node_modules/typebox/build/system/memory/keys.mjs +8 -0
  64. package/node_modules/typebox/build/system/memory/update.d.mts +1 -4
  65. package/node_modules/typebox/build/system/memory/update.mjs +43 -16
  66. package/node_modules/typebox/build/type/engine/call/index.d.mts +1 -0
  67. package/node_modules/typebox/build/type/engine/call/index.mjs +1 -0
  68. package/node_modules/typebox/build/type/engine/evaluate/composite.d.mts +2 -24
  69. package/node_modules/typebox/build/type/engine/evaluate/composite.mjs +2 -29
  70. package/node_modules/typebox/build/type/engine/evaluate/index.d.mts +1 -0
  71. package/node_modules/typebox/build/type/engine/evaluate/index.mjs +1 -0
  72. package/node_modules/typebox/build/type/engine/evaluate/narrow.d.mts +5 -1
  73. package/node_modules/typebox/build/type/engine/evaluate/narrow.mjs +6 -1
  74. package/node_modules/typebox/build/type/engine/evaluate/property.d.mts +30 -0
  75. package/node_modules/typebox/build/type/engine/evaluate/property.mjs +29 -0
  76. package/node_modules/typebox/build/type/engine/immutable/instantiate_add.d.mts +1 -3
  77. package/node_modules/typebox/build/type/engine/immutable/instantiate_add.mjs +1 -4
  78. package/node_modules/typebox/build/type/engine/object/from_intersect.d.mts +2 -2
  79. package/node_modules/typebox/build/type/engine/object/from_intersect.mjs +2 -2
  80. package/node_modules/typebox/build/type/engine/object/from_union.d.mts +2 -2
  81. package/node_modules/typebox/build/type/engine/object/from_union.mjs +2 -2
  82. package/node_modules/typebox/build/type/engine/optional/instantiate_add.d.mts +1 -3
  83. package/node_modules/typebox/build/type/engine/optional/instantiate_add.mjs +1 -4
  84. package/node_modules/typebox/build/type/engine/readonly/instantiate_add.d.mts +1 -3
  85. package/node_modules/typebox/build/type/engine/readonly/instantiate_add.mjs +1 -4
  86. package/node_modules/typebox/build/type/engine/this/index.d.mts +1 -0
  87. package/node_modules/typebox/build/type/engine/this/index.mjs +1 -0
  88. package/node_modules/typebox/build/value/clone/clone.d.mts +4 -3
  89. package/node_modules/typebox/build/value/clone/clone.mjs +5 -7
  90. package/node_modules/typebox/build/value/repair/from_cyclic.d.mts +2 -0
  91. package/node_modules/typebox/build/value/repair/from_cyclic.mjs +6 -0
  92. package/node_modules/typebox/build/value/shared/union_priority_sort.mjs +25 -14
  93. package/node_modules/typebox/package.json +1 -1
  94. package/node_modules/typebox/readme.md +1 -1
  95. package/package.json +5 -5
  96. package/dist/.setup/config-Cu3zsl_3.mjs +0 -239
  97. package/dist/.setup/oauth-DGv28ZgA.mjs +0 -158
  98. package/node_modules/typebox/build/system/memory/freeze.d.mts +0 -4
  99. package/node_modules/typebox/build/system/memory/freeze.mjs +0 -6
@@ -1,23 +1,18 @@
1
- import { m as resolveMeetingInput } from "./plugin-registration-B_nOxAym.mjs";
2
- import { n as requestGoogleApi } from "./google-api-B5FR9zy2.mjs";
1
+ import { r as resolveGoogleMeetConfig } from "./config-CMTw0Anh.mjs";
2
+ import { m as resolveMeetingInput } from "./plugin-registration-CAW7_zO_.mjs";
3
+ import { n as requestGoogleApi, t as readGoogleApiErrorDetail } from "./google-api-B5FR9zy2.mjs";
3
4
  import { t as normalizeMeetUrl } from "./meet-url-DzLdrq0Z.mjs";
4
- import { normalizeOptionalString, uniqueStrings } from "openclaw/plugin-sdk/string-coerce-runtime";
5
+ import { normalizeOptionalString, readNonBlankString, uniqueStrings } from "openclaw/plugin-sdk/string-coerce-runtime";
5
6
  import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
6
7
  import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
7
- import { parseDateStringTimestampMs, timestampMsToIsoString } from "openclaw/plugin-sdk/number-runtime";
8
+ import { MAX_DATE_TIMESTAMP_MS, parseDateStringTimestampMs, resolveDateTimestampMs, resolveExpiresAtMsFromDurationSeconds, timestampMsToIsoString } from "openclaw/plugin-sdk/number-runtime";
8
9
  import { readPositiveIntegerParam } from "openclaw/plugin-sdk/channel-actions";
9
10
  import { readProviderJsonResponse, readProviderTextResponse } from "openclaw/plugin-sdk/provider-http";
10
- // \0rolldown/runtime.js
11
- var __defProp = Object.defineProperty;
12
- var __exportAll = (all, no_symbols) => {
13
- let target = {};
14
- for (var name in all) __defProp(target, name, {
15
- get: all[name],
16
- enumerable: true
17
- });
18
- if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
19
- return target;
20
- };
11
+ import { fetchWithSsrFGuard } from "openclaw/plugin-sdk/ssrf-runtime";
12
+ import { isDeepStrictEqual } from "node:util";
13
+ import { parseOAuthCallbackInput, waitForLocalOAuthCallback } from "openclaw/plugin-sdk/provider-auth-runtime";
14
+ import { createHash, randomUUID } from "node:crypto";
15
+ import { createOAuthRefreshError, createOAuthRefreshResponseError, isRecoverableOAuthRefreshFailure, readOAuthRefreshErrorReason } from "openclaw/plugin-sdk/provider-oauth-runtime";
21
16
  // extensions/google-meet/src/calendar.ts
22
17
  const GOOGLE_CALENDAR_API_BASE_URL = "https://www.googleapis.com/calendar/v3";
23
18
  const GOOGLE_CALENDAR_API_HOST = "www.googleapis.com";
@@ -214,9 +209,9 @@ async function listGoogleMeetCollection(params) {
214
209
  }
215
210
  });
216
211
  const pageItems = assertResourceArray(payload[params.collectionKey], params.collectionKey, `Google Meet ${params.operation}`);
217
- const remaining = typeof params.maxItems === "number" ? Math.max(params.maxItems - items.length, 0) : void 0;
212
+ const remaining = params.maxItems !== void 0 ? Math.max(params.maxItems - items.length, 0) : void 0;
218
213
  items.push(...remaining === void 0 ? pageItems : pageItems.slice(0, remaining));
219
- if (typeof params.maxItems === "number" && items.length >= params.maxItems) break;
214
+ if (params.maxItems !== void 0 && items.length >= params.maxItems) break;
220
215
  pageToken = typeof payload.nextPageToken === "string" ? payload.nextPageToken : void 0;
221
216
  } while (pageToken);
222
217
  return items;
@@ -384,9 +379,6 @@ async function exportGoogleDriveDocumentText(params) {
384
379
  }, (response) => readProviderTextResponse(response, "Google Drive files.export"));
385
380
  }
386
381
  // extensions/google-meet/src/meet.ts
387
- function getParticipantDisplayName(participant) {
388
- return participant.signedinUser?.displayName ?? participant.anonymousUser?.displayName ?? participant.phoneUser?.displayName;
389
- }
390
382
  async function attachDocumentText(accessToken, resource) {
391
383
  const destination = resource.docsDestination;
392
384
  const documentId = extractGoogleDriveDocumentId(destination?.document) ?? extractGoogleDriveDocumentId(destination?.documentId) ?? extractGoogleDriveDocumentId(destination?.file);
@@ -410,32 +402,20 @@ function timestampBound(values, bound) {
410
402
  const parsed = values.map(parseDateStringTimestampMs).filter((value) => value !== void 0);
411
403
  return parsed.length > 0 ? timestampMsToIsoString(bound(...parsed)) : void 0;
412
404
  }
413
- function sumSessionDurationMs(sessions, fallbackStart, fallbackEnd) {
414
- const sessionTotal = sessions.reduce((total, session) => {
415
- const startMs = parseDateStringTimestampMs(session.startTime);
416
- const endMs = parseDateStringTimestampMs(session.endTime);
417
- return startMs !== void 0 && endMs !== void 0 && endMs > startMs ? total + (endMs - startMs) : total;
418
- }, 0);
419
- if (sessionTotal > 0) return sessionTotal;
420
- const startMs = parseDateStringTimestampMs(fallbackStart);
421
- const endMs = parseDateStringTimestampMs(fallbackEnd);
422
- return startMs !== void 0 && endMs !== void 0 && endMs > startMs ? endMs - startMs : void 0;
423
- }
424
- function attendanceMergeKey(row) {
425
- return (row.user ?? row.displayName ?? row.participant).trim().toLocaleLowerCase();
426
- }
427
- function sortSessions(sessions) {
428
- return sessions.toSorted((left, right) => (parseDateStringTimestampMs(left.startTime) ?? 0) - (parseDateStringTimestampMs(right.startTime) ?? 0));
429
- }
430
405
  function decorateAttendanceRow(row, conferenceRecord, params) {
431
- const sessions = sortSessions(row.sessions);
406
+ const sessions = row.sessions.toSorted((left, right) => (parseDateStringTimestampMs(left.startTime) ?? 0) - (parseDateStringTimestampMs(right.startTime) ?? 0));
432
407
  const firstJoinTime = timestampBound([row.earliestStartTime, ...sessions.map((session) => session.startTime)], Math.min);
433
408
  const lastLeaveTime = timestampBound([row.latestEndTime, ...sessions.map((session) => session.endTime)], Math.max);
434
- const durationMs = sumSessionDurationMs(sessions, firstJoinTime, lastLeaveTime);
435
409
  const conferenceStartMs = parseDateStringTimestampMs(conferenceRecord.startTime);
436
410
  const conferenceEndMs = parseDateStringTimestampMs(conferenceRecord.endTime);
437
411
  const firstJoinMs = parseDateStringTimestampMs(firstJoinTime);
438
412
  const lastLeaveMs = parseDateStringTimestampMs(lastLeaveTime);
413
+ const sessionTotal = sessions.reduce((total, session) => {
414
+ const startMs = parseDateStringTimestampMs(session.startTime);
415
+ const endMs = parseDateStringTimestampMs(session.endTime);
416
+ return startMs !== void 0 && endMs !== void 0 && endMs > startMs ? total + (endMs - startMs) : total;
417
+ }, 0);
418
+ const durationMs = sessionTotal > 0 ? sessionTotal : firstJoinMs !== void 0 && lastLeaveMs !== void 0 && lastLeaveMs > firstJoinMs ? lastLeaveMs - firstJoinMs : void 0;
439
419
  const lateGraceMs = (params.lateAfterMinutes ?? 5) * 6e4;
440
420
  const earlyGraceMs = (params.earlyBeforeMinutes ?? 5) * 6e4;
441
421
  const lateByMs = conferenceStartMs !== void 0 && firstJoinMs !== void 0 ? Math.max(firstJoinMs - conferenceStartMs, 0) : void 0;
@@ -464,7 +444,7 @@ function mergeAttendanceRows(rows, conferenceRecord, params) {
464
444
  if (params.mergeDuplicateParticipants === false) return rows.map((row) => decorateAttendanceRow(row, conferenceRecord, params));
465
445
  const grouped = /* @__PURE__ */ new Map();
466
446
  for (const row of rows) {
467
- const key = attendanceMergeKey(row);
447
+ const key = (row.user ?? row.displayName ?? row.participant).trim().toLocaleLowerCase();
468
448
  const existing = grouped.get(key);
469
449
  if (!existing) {
470
450
  grouped.set(key, {
@@ -545,7 +525,7 @@ async function fetchGoogleMeetAttendance(params) {
545
525
  return mergeAttendanceRows(await Promise.all(participants.map(async (participant) => ({
546
526
  conferenceRecord: conferenceRecord.name,
547
527
  participant: participant.name,
548
- displayName: getParticipantDisplayName(participant),
528
+ displayName: participant.signedinUser?.displayName ?? participant.anonymousUser?.displayName ?? participant.phoneUser?.displayName,
549
529
  user: participant.signedinUser?.user,
550
530
  earliestStartTime: participant.earliestStartTime,
551
531
  latestEndTime: participant.latestEndTime,
@@ -577,32 +557,346 @@ function buildGoogleMeetPreflightReport(params) {
577
557
  blockers
578
558
  };
579
559
  }
560
+ // extensions/google-meet/src/oauth.ts
561
+ const GOOGLE_MEET_REDIRECT_URI = "http://localhost:8085/oauth2callback";
562
+ const GOOGLE_MEET_AUTH_URL = "https://accounts.google.com/o/oauth2/v2/auth";
563
+ const GOOGLE_MEET_TOKEN_URL = "https://oauth2.googleapis.com/token";
564
+ const GOOGLE_MEET_TOKEN_HOST = "oauth2.googleapis.com";
565
+ const GOOGLE_MEET_DEFAULT_TOKEN_LIFETIME_SECONDS = 3600;
566
+ const GOOGLE_OAUTH_TOKEN_JSON_MAX_BYTES = 262144;
567
+ const GOOGLE_OAUTH_REQUEST_TIMEOUT_MS = 3e4;
568
+ const GOOGLE_MEET_SCOPES = [
569
+ "https://www.googleapis.com/auth/meetings.space.created",
570
+ "https://www.googleapis.com/auth/meetings.space.readonly",
571
+ "https://www.googleapis.com/auth/meetings.space.settings",
572
+ "https://www.googleapis.com/auth/meetings.conference.media.readonly",
573
+ "https://www.googleapis.com/auth/calendar.events.readonly",
574
+ "https://www.googleapis.com/auth/drive.meet.readonly"
575
+ ];
576
+ function resolveGoogleMeetTokenExpiresAt(value) {
577
+ const now = resolveDateTimestampMs(Date.now());
578
+ if (typeof value === "number" && Number.isFinite(value) && value <= 0) return now;
579
+ return resolveExpiresAtMsFromDurationSeconds(value, { nowMs: now }) ?? resolveExpiresAtMsFromDurationSeconds(GOOGLE_MEET_DEFAULT_TOKEN_LIFETIME_SECONDS, { nowMs: now }) ?? now;
580
+ }
581
+ function buildGoogleMeetAuthUrl(params) {
582
+ const search = new URLSearchParams({
583
+ client_id: params.clientId,
584
+ response_type: "code",
585
+ redirect_uri: GOOGLE_MEET_REDIRECT_URI,
586
+ scope: GOOGLE_MEET_SCOPES.join(" "),
587
+ code_challenge: params.challenge,
588
+ code_challenge_method: "S256",
589
+ access_type: "offline",
590
+ prompt: "consent",
591
+ state: params.state
592
+ });
593
+ return `${GOOGLE_MEET_AUTH_URL}?${search.toString()}`;
594
+ }
595
+ async function executeGoogleTokenRequest(body) {
596
+ const refreshing = body.get("grant_type") === "refresh_token";
597
+ let dispatched = false;
598
+ const { response, release } = await fetchWithSsrFGuard({
599
+ beforeRequest: () => {
600
+ dispatched = true;
601
+ },
602
+ url: GOOGLE_MEET_TOKEN_URL,
603
+ init: {
604
+ method: "POST",
605
+ headers: {
606
+ "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",
607
+ Accept: "application/json"
608
+ },
609
+ body
610
+ },
611
+ policy: { allowedHostnames: [GOOGLE_MEET_TOKEN_HOST] },
612
+ auditContext: "google-meet.oauth.token",
613
+ timeoutMs: GOOGLE_OAUTH_REQUEST_TIMEOUT_MS
614
+ }).catch((cause) => {
615
+ if (!refreshing) throw cause;
616
+ throw createOAuthRefreshError("Google Meet OAuth refresh transport failed", dispatched ? {
617
+ version: 1,
618
+ phase: "token-response",
619
+ outcome: "unchanged",
620
+ recovery: {
621
+ kind: "later",
622
+ evidence: "documented-reusable-grant"
623
+ }
624
+ } : {
625
+ version: 1,
626
+ phase: "before-dispatch",
627
+ outcome: "not-attempted",
628
+ recovery: {
629
+ kind: "later",
630
+ evidence: "dispatch-not-started"
631
+ }
632
+ }, { cause });
633
+ });
634
+ try {
635
+ if (!response.ok && !refreshing) {
636
+ const detail = await readGoogleApiErrorDetail(response);
637
+ throw new Error(`Google OAuth token request failed (${response.status}): ${detail}`);
638
+ }
639
+ let payload;
640
+ try {
641
+ payload = await readProviderJsonResponse(response, "Google OAuth token", { maxBytes: GOOGLE_OAUTH_TOKEN_JSON_MAX_BYTES });
642
+ } catch (cause) {
643
+ if (!refreshing) throw cause;
644
+ if (!response.ok) throw createOAuthRefreshResponseError("Google Meet OAuth refresh", response.status, void 0, "documented-reusable-grant");
645
+ throw createOAuthRefreshError(cause instanceof Error && cause.message.startsWith("Google OAuth token:") ? cause.message : "Google Meet OAuth refresh response could not be read", {
646
+ version: 1,
647
+ phase: "token-response",
648
+ outcome: "unchanged",
649
+ recovery: {
650
+ kind: "later",
651
+ evidence: "documented-reusable-grant"
652
+ }
653
+ }, { cause });
654
+ }
655
+ if (refreshing && (!response.ok || readOAuthRefreshErrorReason(payload))) throw createOAuthRefreshResponseError("Google Meet OAuth refresh", response.status, payload, "documented-reusable-grant");
656
+ const accessToken = typeof payload?.access_token === "string" ? payload.access_token.trim() : void 0;
657
+ if (!accessToken) throw createOAuthRefreshError("Google OAuth token response was missing access_token", {
658
+ version: 1,
659
+ phase: "after-token-response",
660
+ outcome: "unknown",
661
+ status: response.status
662
+ });
663
+ if (refreshing && payload.refresh_token !== void 0 && (typeof payload.refresh_token !== "string" || !payload.refresh_token.trim())) throw createOAuthRefreshError("Google Meet OAuth refresh returned an invalid refresh_token", {
664
+ version: 1,
665
+ phase: "after-token-response",
666
+ outcome: "unknown",
667
+ status: response.status
668
+ });
669
+ return {
670
+ accessToken,
671
+ expiresAt: resolveGoogleMeetTokenExpiresAt(payload.expires_in),
672
+ refreshToken: typeof payload.refresh_token === "string" ? payload.refresh_token.trim() || void 0 : void 0,
673
+ scope: typeof payload.scope === "string" ? payload.scope.trim() || void 0 : void 0,
674
+ tokenType: typeof payload.token_type === "string" ? payload.token_type.trim() || void 0 : void 0
675
+ };
676
+ } finally {
677
+ await release();
678
+ }
679
+ }
680
+ function tokenRequestBody(values) {
681
+ const body = new URLSearchParams();
682
+ for (const [key, value] of Object.entries(values)) if (value?.trim()) body.set(key, value);
683
+ return body;
684
+ }
685
+ async function exchangeGoogleMeetAuthCode(params) {
686
+ return await executeGoogleTokenRequest(tokenRequestBody({
687
+ client_id: params.clientId,
688
+ client_secret: params.clientSecret,
689
+ code: params.code,
690
+ grant_type: "authorization_code",
691
+ redirect_uri: GOOGLE_MEET_REDIRECT_URI,
692
+ code_verifier: params.verifier
693
+ }));
694
+ }
695
+ async function refreshGoogleMeetAccessToken(params) {
696
+ return await executeGoogleTokenRequest(tokenRequestBody({
697
+ client_id: params.clientId,
698
+ client_secret: params.clientSecret,
699
+ grant_type: "refresh_token",
700
+ refresh_token: params.refreshToken
701
+ }));
702
+ }
703
+ function shouldUseCachedGoogleMeetAccessToken(params) {
704
+ const now = Date.now();
705
+ return Boolean(params.accessToken?.trim() && typeof params.expiresAt === "number" && Number.isFinite(params.expiresAt) && params.expiresAt <= MAX_DATE_TIMESTAMP_MS && params.expiresAt > now + 6e4);
706
+ }
707
+ async function resolveGoogleMeetAccessToken(params) {
708
+ if (params.accessToken && shouldUseCachedGoogleMeetAccessToken(params)) return {
709
+ accessToken: params.accessToken.trim(),
710
+ expiresAt: params.expiresAt,
711
+ refreshed: false
712
+ };
713
+ if (!params.clientId?.trim() || !params.refreshToken?.trim()) throw new Error("Missing Google Meet OAuth credentials. Configure oauth.clientId and oauth.refreshToken, or pass --client-id and --refresh-token.");
714
+ const refreshed = await refreshGoogleMeetAccessToken({
715
+ clientId: params.clientId,
716
+ clientSecret: params.clientSecret,
717
+ refreshToken: params.refreshToken
718
+ });
719
+ if (refreshed.refreshToken && refreshed.refreshToken !== params.refreshToken) throw new Error("Google Meet refresh-token rotation requires a durable credential owner. Use the configured Google Meet plugin route, or reauthorize and save the replacement in the external credential owner.");
720
+ return {
721
+ accessToken: refreshed.accessToken,
722
+ expiresAt: refreshed.expiresAt,
723
+ refreshed: true
724
+ };
725
+ }
726
+ function isLocalCallbackListenerError(error) {
727
+ if (!(error instanceof Error)) return false;
728
+ return error.message.includes("EADDRINUSE") || error.message.includes("port") || error.message.includes("listen");
729
+ }
730
+ async function waitForGoogleMeetAuthCode(params) {
731
+ async function readManualGoogleMeetAuthCode() {
732
+ const { state, promptInput } = params;
733
+ const input = await promptInput("Paste the full redirect URL here: ");
734
+ const parsed = parseOAuthCallbackInput(input, {
735
+ missingState: "Missing 'state' parameter. Paste the full redirect URL.",
736
+ invalidInput: "Paste the full redirect URL, not just the code."
737
+ });
738
+ if ("error" in parsed) throw new Error(parsed.error);
739
+ if (parsed.state !== state) throw new Error("OAuth state mismatch - please try again");
740
+ return parsed.code;
741
+ }
742
+ params.writeLine(`Open this URL in your browser:\n\n${params.authUrl}\n`);
743
+ if (params.manual) return await readManualGoogleMeetAuthCode();
744
+ try {
745
+ return (await waitForLocalOAuthCallback({
746
+ expectedState: params.state,
747
+ timeoutMs: params.timeoutMs,
748
+ port: 8085,
749
+ callbackPath: "/oauth2callback",
750
+ redirectUri: GOOGLE_MEET_REDIRECT_URI,
751
+ successTitle: "Google Meet OAuth complete"
752
+ })).code;
753
+ } catch (error) {
754
+ if (!isLocalCallbackListenerError(error)) throw error;
755
+ params.writeLine("Local callback server failed. Switching to manual mode...");
756
+ return await readManualGoogleMeetAuthCode();
757
+ }
758
+ }
759
+ // extensions/google-meet/src/oauth-owner.ts
760
+ const tasks = /* @__PURE__ */ new WeakMap();
761
+ function lineageOf(oauth) {
762
+ const grant = JSON.stringify([
763
+ oauth.clientId,
764
+ oauth.clientSecret,
765
+ oauth.refreshToken,
766
+ oauth.accessToken,
767
+ oauth.expiresAt
768
+ ]);
769
+ return createHash("sha256").update(grant).digest("hex");
770
+ }
771
+ /** Config identifies the grant; this plugin-owned row owns all later rotations. */
772
+ async function resolveManagedGoogleMeetAccessToken(oauth, runtime) {
773
+ const lineage = lineageOf(oauth);
774
+ const assertCurrent = () => {
775
+ const entry = runtime.config.current().plugins?.entries?.["google-meet"];
776
+ const current = resolveGoogleMeetConfig(entry?.config);
777
+ if (entry?.enabled === false || !current.enabled) throw new Error("Google Meet is disabled; enable it before using its OAuth grant");
778
+ if (lineageOf(current.oauth) !== lineage) throw new Error("Google Meet OAuth account changed; retry with its current configuration");
779
+ };
780
+ assertCurrent();
781
+ const pending = tasks.get(runtime)?.get(lineage);
782
+ if (pending) return await pending;
783
+ const task = (async () => {
784
+ if (!oauth.clientId || !oauth.refreshToken) {
785
+ const { resolveGoogleMeetAccessToken } = await import("./oauth-DZkuGMs1.mjs");
786
+ return await resolveGoogleMeetAccessToken(oauth);
787
+ }
788
+ const store = runtime.state.openKeyedStoreV2({
789
+ namespace: "oauth-credential",
790
+ maxEntries: 1,
791
+ overflowPolicy: "reject-new"
792
+ }, { assertCurrent });
793
+ let observed = await store.observe("current");
794
+ if (observed.value?.lineage !== lineage) {
795
+ const initialized = await store.compareAndApply("current", observed.comparison, {
796
+ operation: "update",
797
+ action: "set",
798
+ value: {
799
+ lineage,
800
+ credential: {
801
+ accessToken: oauth.accessToken,
802
+ refreshToken: oauth.refreshToken,
803
+ expiresAt: oauth.expiresAt
804
+ }
805
+ }
806
+ });
807
+ observed = initialized.status === "conflict" ? initialized.current : await store.observe("current");
808
+ }
809
+ assertCurrent();
810
+ if (!observed.value || observed.value.lineage !== lineage || !("credential" in observed.value)) throw new Error("Google Meet OAuth refresh is pending or its outcome is uncertain; reauthorize the configured grant");
811
+ const credential = observed.value.credential;
812
+ if (credential.accessToken && shouldUseCachedGoogleMeetAccessToken(credential)) return {
813
+ accessToken: credential.accessToken,
814
+ expiresAt: credential.expiresAt,
815
+ refreshed: false
816
+ };
817
+ const claimId = randomUUID();
818
+ const claim = {
819
+ lineage,
820
+ credential,
821
+ claim: claimId
822
+ };
823
+ if ((await store.compareAndApply("current", observed.comparison, {
824
+ operation: "update",
825
+ action: "set",
826
+ value: claim
827
+ })).status !== "applied") throw new Error("Google Meet OAuth grant changed before refresh; retry with the current owner");
828
+ const settle = async (replacement) => {
829
+ const current = await store.observe("current");
830
+ if (!isDeepStrictEqual(current.value, claim)) throw new Error("Google Meet OAuth refresh owner changed before settlement");
831
+ if ((await store.compareAndApply("current", current.comparison, {
832
+ operation: "update",
833
+ action: "set",
834
+ value: {
835
+ lineage,
836
+ credential: replacement
837
+ }
838
+ })).status !== "applied") throw new Error("Google Meet OAuth refresh owner changed before settlement");
839
+ assertCurrent();
840
+ };
841
+ assertCurrent();
842
+ let refreshed;
843
+ try {
844
+ refreshed = await refreshGoogleMeetAccessToken({
845
+ clientId: oauth.clientId,
846
+ clientSecret: oauth.clientSecret,
847
+ refreshToken: credential.refreshToken
848
+ });
849
+ } catch (error) {
850
+ if (isRecoverableOAuthRefreshFailure(error)) await settle(credential);
851
+ else {
852
+ const current = await store.observe("current");
853
+ if (isDeepStrictEqual(current.value, claim)) await store.compareAndApply("current", current.comparison, {
854
+ operation: "update",
855
+ action: "set",
856
+ value: {
857
+ lineage,
858
+ claim: claimId
859
+ }
860
+ });
861
+ }
862
+ throw error;
863
+ }
864
+ await settle({
865
+ accessToken: refreshed.accessToken,
866
+ refreshToken: refreshed.refreshToken ?? credential.refreshToken,
867
+ expiresAt: refreshed.expiresAt
868
+ });
869
+ return {
870
+ accessToken: refreshed.accessToken,
871
+ expiresAt: refreshed.expiresAt,
872
+ refreshed: true
873
+ };
874
+ })();
875
+ let owned = tasks.get(runtime);
876
+ if (!owned) {
877
+ owned = /* @__PURE__ */ new Map();
878
+ tasks.set(runtime, owned);
879
+ }
880
+ owned.set(lineage, task);
881
+ try {
882
+ return await task;
883
+ } finally {
884
+ if (owned.get(lineage) === task) owned.delete(lineage);
885
+ }
886
+ }
580
887
  // extensions/google-meet/src/plugin-helpers.ts
581
- var plugin_helpers_exports = /* @__PURE__ */ __exportAll({
582
- buildGoogleMeetCalendarDayWindow: () => buildGoogleMeetCalendarDayWindow,
583
- buildGoogleMeetExportRequest: () => buildGoogleMeetExportRequest,
584
- buildGoogleMeetPreflightReport: () => buildGoogleMeetPreflightReport,
585
- endGoogleMeetActiveConference: () => endGoogleMeetActiveConference,
586
- exportGoogleMeetBundleFromParams: () => exportGoogleMeetBundleFromParams,
587
- fetchLatestGoogleMeetConferenceRecord: () => fetchLatestGoogleMeetConferenceRecord,
588
- fetchResolvedGoogleMeetArtifacts: () => fetchResolvedGoogleMeetArtifacts,
589
- fetchResolvedGoogleMeetAttendance: () => fetchResolvedGoogleMeetAttendance,
590
- listGoogleMeetCalendarEvents: () => listGoogleMeetCalendarEvents,
591
- resolveArtifactQueryFromParams: () => resolveArtifactQueryFromParams,
592
- resolveGoogleMeetTokenFromParams: () => resolveGoogleMeetTokenFromParams,
593
- resolveMeetingFromParams: () => resolveMeetingFromParams,
594
- resolveSpaceFromParams: () => resolveSpaceFromParams
595
- });
596
- const loadGoogleMeetExportModule = createLazyRuntimeModule(() => import("./cli-export-CaDYoSP8.mjs").then((n) => n.t));
597
- async function resolveGoogleMeetTokenFromParams(config, raw) {
598
- const { resolveGoogleMeetAccessToken } = await import("./oauth-DGv28ZgA.mjs");
599
- return resolveGoogleMeetAccessToken({
888
+ const loadGoogleMeetExportModule = createLazyRuntimeModule(() => import("./cli-export-6eiywS3T.mjs"));
889
+ async function resolveGoogleMeetTokenFromParams(config, raw, runtime) {
890
+ const { resolveGoogleMeetAccessToken } = await import("./oauth-DZkuGMs1.mjs");
891
+ const oauth = {
600
892
  clientId: normalizeOptionalString(raw.clientId) ?? config.oauth.clientId,
601
893
  clientSecret: normalizeOptionalString(raw.clientSecret) ?? config.oauth.clientSecret,
602
894
  refreshToken: normalizeOptionalString(raw.refreshToken) ?? config.oauth.refreshToken,
603
895
  accessToken: normalizeOptionalString(raw.accessToken) ?? config.oauth.accessToken,
604
896
  expiresAt: typeof raw.expiresAt === "number" ? raw.expiresAt : config.oauth.expiresAt
605
- });
897
+ };
898
+ const configured = isDeepStrictEqual(oauth, config.oauth);
899
+ return runtime && configured ? resolveManagedGoogleMeetAccessToken(config.oauth, runtime) : resolveGoogleMeetAccessToken(oauth);
606
900
  }
607
901
  function wantsCalendarLookup(raw) {
608
902
  return raw.today === true || Boolean(normalizeOptionalString(raw.event));
@@ -623,8 +917,8 @@ async function resolveMeetingFromParams(params) {
623
917
  }
624
918
  return { meeting: resolveMeetingInput(params.config, params.raw.meeting) };
625
919
  }
626
- async function resolveSpaceFromParams(config, raw) {
627
- const token = await resolveGoogleMeetTokenFromParams(config, raw);
920
+ async function resolveSpaceFromParams(config, raw, runtime) {
921
+ const token = await resolveGoogleMeetTokenFromParams(config, raw, runtime);
628
922
  const { meeting, calendarEvent } = await resolveMeetingFromParams({
629
923
  config,
630
924
  raw,
@@ -640,10 +934,10 @@ async function resolveSpaceFromParams(config, raw) {
640
934
  calendarEvent
641
935
  };
642
936
  }
643
- async function resolveArtifactQueryFromParams(config, raw) {
937
+ async function resolveArtifactQueryFromParams(config, raw, runtime) {
644
938
  const meeting = normalizeOptionalString(raw.meeting) ?? config.defaults.meeting;
645
939
  const conferenceRecord = normalizeOptionalString(raw.conferenceRecord);
646
- const token = await resolveGoogleMeetTokenFromParams(config, raw);
940
+ const token = await resolveGoogleMeetTokenFromParams(config, raw, runtime);
647
941
  const resolvedMeeting = conferenceRecord ? { meeting } : wantsCalendarLookup(raw) ? await resolveMeetingFromParams({
648
942
  config,
649
943
  raw,
@@ -692,8 +986,8 @@ function buildGoogleMeetExportRequest(resolved, calendarId) {
692
986
  ...resolved.earlyBeforeMinutes !== void 0 ? { earlyBeforeMinutes: resolved.earlyBeforeMinutes } : {}
693
987
  };
694
988
  }
695
- async function exportGoogleMeetBundleFromParams(config, raw) {
696
- const resolved = await resolveArtifactQueryFromParams(config, raw);
989
+ async function exportGoogleMeetBundleFromParams(config, raw, runtime) {
990
+ const resolved = await resolveArtifactQueryFromParams(config, raw, runtime);
697
991
  const [artifacts, attendance] = await Promise.all([fetchResolvedGoogleMeetArtifacts(resolved), fetchResolvedGoogleMeetAttendance(resolved)]);
698
992
  const { exportGoogleMeetBundle } = await loadGoogleMeetExportModule();
699
993
  return exportGoogleMeetBundle({
@@ -702,9 +996,9 @@ async function exportGoogleMeetBundleFromParams(config, raw) {
702
996
  request: buildGoogleMeetExportRequest(resolved, normalizeOptionalString(raw.calendarId)),
703
997
  tokenSource: resolved.token.refreshed ? "refresh-token" : "cached-access-token",
704
998
  calendarEvent: resolved.calendarEvent,
705
- outputDir: normalizeOptionalString(raw.outputDir) ?? normalizeOptionalString(raw.output),
999
+ outputDir: readNonBlankString(raw.outputDir) ?? readNonBlankString(raw.output),
706
1000
  zip: raw.zip === true,
707
1001
  dryRun: raw.dryRun === true
708
1002
  });
709
1003
  }
710
- export { resolveArtifactQueryFromParams as a, resolveSpaceFromParams as c, endGoogleMeetActiveConference as d, fetchGoogleMeetSpace as f, __exportAll as g, listGoogleMeetCalendarEvents as h, plugin_helpers_exports as i, buildGoogleMeetPreflightReport as l, buildGoogleMeetCalendarDayWindow as m, fetchResolvedGoogleMeetArtifacts as n, resolveGoogleMeetTokenFromParams as o, fetchLatestGoogleMeetConferenceRecord as p, fetchResolvedGoogleMeetAttendance as r, resolveMeetingFromParams as s, buildGoogleMeetExportRequest as t, createGoogleMeetSpace as u };
1004
+ export { shouldUseCachedGoogleMeetAccessToken as a, buildGoogleMeetCalendarDayWindow, buildGoogleMeetExportRequest, buildGoogleMeetPreflightReport, fetchGoogleMeetSpace as c, endGoogleMeetActiveConference, exportGoogleMeetBundleFromParams, fetchLatestGoogleMeetConferenceRecord, fetchResolvedGoogleMeetArtifacts, fetchResolvedGoogleMeetAttendance, resolveGoogleMeetAccessToken as i, listGoogleMeetCalendarEvents, exchangeGoogleMeetAuthCode as n, waitForGoogleMeetAuthCode as o, refreshGoogleMeetAccessToken as r, resolveArtifactQueryFromParams, resolveGoogleMeetTokenFromParams, resolveMeetingFromParams, resolveSpaceFromParams, createGoogleMeetSpace as s, buildGoogleMeetAuthUrl as t };
@@ -1,15 +1,15 @@
1
1
  import { n as GOOGLE_MEET_NODE_COMMAND, r as GoogleMeetBrowserManualActionError } from "./google-meet-platform-constants-C83Cdmpd.mjs";
2
- import { i as resolveGoogleMeetGatewayOperationTimeoutMs } from "./config-Cu3zsl_3.mjs";
2
+ import { i as resolveGoogleMeetGatewayOperationTimeoutMs } from "./config-CMTw0Anh.mjs";
3
3
  import { asNonArrayRecord, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
4
4
  import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
5
5
  import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
6
6
  // extensions/google-meet/src/plugin-registration.ts
7
- const loadGoogleMeetPluginHelpers = createLazyRuntimeModule(() => import("./plugin-helpers-Buhixxsx.mjs").then((n) => n.i));
8
- const loadGoogleMeetCliModule = createLazyRuntimeModule(() => import("./cli-9linTFHb.mjs"));
9
- const loadGoogleMeetCreateModule = createLazyRuntimeModule(() => import("./create-D3fHR8uX.mjs").then((n) => n.n));
10
- const loadGoogleMeetNodeHostModule = createLazyRuntimeModule(() => import("./node-host-B196lvNZ.mjs"));
11
- const loadGoogleMeetRuntimeModule = createLazyRuntimeModule(() => import("./runtime-D-dwEsSW.mjs"));
12
- const loadGoogleMeetNodeInvokePolicyModule = createLazyRuntimeModule(() => import("./node-invoke-policy-BzRAe25r.mjs"));
7
+ const loadGoogleMeetPluginHelpers = createLazyRuntimeModule(() => import("./plugin-helpers-ChCBuyAl.mjs"));
8
+ const loadGoogleMeetCliModule = createLazyRuntimeModule(() => import("./cli-C-MrY7IZ.mjs"));
9
+ const loadGoogleMeetCreateModule = createLazyRuntimeModule(() => import("./create-DMk4zbMq.mjs").then((n) => n.n));
10
+ const loadGoogleMeetNodeHostModule = createLazyRuntimeModule(() => import("./node-host-BIZD9InM.mjs"));
11
+ const loadGoogleMeetRuntimeModule = createLazyRuntimeModule(() => import("./runtime-Cyc6bv1i.mjs"));
12
+ const loadGoogleMeetNodeInvokePolicyModule = createLazyRuntimeModule(() => import("./node-invoke-policy-bg7p_BWB.mjs"));
13
13
  const loadGoogleMeetGatewayRuntimeModule = createLazyRuntimeModule(() => import("openclaw/plugin-sdk/gateway-runtime"));
14
14
  function normalizeTransport(value) {
15
15
  return value === "chrome" || value === "chrome-node" || value === "twilio" ? value : void 0;
@@ -164,7 +164,7 @@ function sendGoogleMeetGatewayError(respond, err, code = "UNAVAILABLE") {
164
164
  const payload = formatGoogleMeetGatewayError(err);
165
165
  respond(false, payload, {
166
166
  code,
167
- message: typeof payload.error === "string" ? payload.error : "Google Meet request failed",
167
+ message: payload.error,
168
168
  details: payload
169
169
  });
170
170
  }