@openclaw/google-meet 2026.7.2-beta.2 → 2026.7.2-beta.4

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.
@@ -2,7 +2,7 @@ import { t as googleApiError } from "./google-api-errors-CDUYkIcK.js";
2
2
  import { uniqueStrings } from "openclaw/plugin-sdk/string-coerce-runtime";
3
3
  import { readProviderJsonResponse, readProviderTextResponse } from "openclaw/plugin-sdk/provider-http";
4
4
  import { fetchWithSsrFGuard } from "openclaw/plugin-sdk/ssrf-runtime";
5
- import { addTimerTimeoutGraceMs } from "openclaw/plugin-sdk/number-runtime";
5
+ import { asMeetingBrowserTabs, callMeetingBrowserProxyOnNode, readMeetingBrowserTab, resolveMeetingBrowserNode, resolveMeetingBrowserNodeInfo } from "openclaw/plugin-sdk/meeting-runtime";
6
6
  import { sleep } from "openclaw/plugin-sdk/runtime-env";
7
7
  //#region extensions/google-meet/src/drive.ts
8
8
  const GOOGLE_DRIVE_API_BASE_URL = "https://www.googleapis.com/drive/v3";
@@ -49,7 +49,7 @@ async function exportGoogleDriveDocumentText(params) {
49
49
  }
50
50
  }
51
51
  //#endregion
52
- //#region extensions/google-meet/src/meet.ts
52
+ //#region extensions/google-meet/src/meet-api.ts
53
53
  const GOOGLE_MEET_API_BASE_URL = `https://meet.googleapis.com/v2`;
54
54
  const GOOGLE_MEET_URL_HOST = "meet.google.com";
55
55
  const GOOGLE_MEET_API_HOST = "meet.googleapis.com";
@@ -341,6 +341,36 @@ async function listGoogleMeetSmartNotes(params) {
341
341
  errorPrefix: "Google Meet conferenceRecords.smartNotes.list"
342
342
  });
343
343
  }
344
+ async function resolveConferenceRecordQuery(params) {
345
+ if (params.conferenceRecord?.trim()) {
346
+ const conferenceRecord = await fetchGoogleMeetConferenceRecord({
347
+ accessToken: params.accessToken,
348
+ conferenceRecord: params.conferenceRecord
349
+ });
350
+ return {
351
+ input: params.conferenceRecord.trim(),
352
+ conferenceRecords: [conferenceRecord]
353
+ };
354
+ }
355
+ if (!params.meeting?.trim()) throw new Error("Meeting input or conference record is required");
356
+ const space = await fetchGoogleMeetSpace({
357
+ accessToken: params.accessToken,
358
+ meeting: params.meeting
359
+ });
360
+ const conferenceRecords = await listGoogleMeetConferenceRecords({
361
+ accessToken: params.accessToken,
362
+ meeting: space.name,
363
+ pageSize: params.allConferenceRecords ? params.pageSize : 1,
364
+ maxItems: params.allConferenceRecords ? void 0 : 1
365
+ });
366
+ return {
367
+ input: params.meeting,
368
+ space,
369
+ conferenceRecords
370
+ };
371
+ }
372
+ //#endregion
373
+ //#region extensions/google-meet/src/meet.ts
344
374
  function getParticipantDisplayName(participant) {
345
375
  return participant.signedinUser?.displayName ?? participant.anonymousUser?.displayName ?? participant.phoneUser?.displayName;
346
376
  }
@@ -456,34 +486,6 @@ function mergeAttendanceRows(rows, conferenceRecord, params) {
456
486
  }
457
487
  return [...grouped.values()].map((row) => decorateAttendanceRow(row, conferenceRecord, params));
458
488
  }
459
- async function resolveConferenceRecordQuery(params) {
460
- if (params.conferenceRecord?.trim()) {
461
- const conferenceRecord = await fetchGoogleMeetConferenceRecord({
462
- accessToken: params.accessToken,
463
- conferenceRecord: params.conferenceRecord
464
- });
465
- return {
466
- input: params.conferenceRecord.trim(),
467
- conferenceRecords: [conferenceRecord]
468
- };
469
- }
470
- if (!params.meeting?.trim()) throw new Error("Meeting input or conference record is required");
471
- const space = await fetchGoogleMeetSpace({
472
- accessToken: params.accessToken,
473
- meeting: params.meeting
474
- });
475
- const conferenceRecords = await listGoogleMeetConferenceRecords({
476
- accessToken: params.accessToken,
477
- meeting: space.name,
478
- pageSize: params.allConferenceRecords ? params.pageSize : 1,
479
- maxItems: params.allConferenceRecords ? void 0 : 1
480
- });
481
- return {
482
- input: params.meeting,
483
- space,
484
- conferenceRecords
485
- };
486
- }
487
489
  async function fetchGoogleMeetArtifacts(params) {
488
490
  const resolved = await resolveConferenceRecordQuery(params);
489
491
  const artifacts = await Promise.all(resolved.conferenceRecords.map(async (conferenceRecord) => {
@@ -597,7 +599,37 @@ function buildGoogleMeetPreflightReport(params) {
597
599
  };
598
600
  }
599
601
  //#endregion
602
+ //#region extensions/google-meet/src/transports/google-meet-platform-constants.ts
603
+ const GOOGLE_MEET_NODE_COMMAND = "googlemeet.chrome";
604
+ const GOOGLE_MEET_BROWSER_NODE_ADAPTER = {
605
+ displayName: "Google Meet",
606
+ nodeCommandName: GOOGLE_MEET_NODE_COMMAND,
607
+ nodeConfigPath: "plugins.entries.google-meet.config.chromeNode.node"
608
+ };
609
+ //#endregion
600
610
  //#region extensions/google-meet/src/transports/chrome-browser-proxy.ts
611
+ async function resolveChromeNodeInfo(params) {
612
+ return await resolveMeetingBrowserNodeInfo({
613
+ ...params,
614
+ adapter: GOOGLE_MEET_BROWSER_NODE_ADAPTER
615
+ });
616
+ }
617
+ async function resolveChromeNode(params) {
618
+ return await resolveMeetingBrowserNode({
619
+ ...params,
620
+ adapter: GOOGLE_MEET_BROWSER_NODE_ADAPTER
621
+ });
622
+ }
623
+ async function callBrowserProxyOnNode(params) {
624
+ return await callMeetingBrowserProxyOnNode({
625
+ ...params,
626
+ adapter: GOOGLE_MEET_BROWSER_NODE_ADAPTER
627
+ });
628
+ }
629
+ const asBrowserTabs = asMeetingBrowserTabs;
630
+ const readBrowserTab = readMeetingBrowserTab;
631
+ //#endregion
632
+ //#region extensions/google-meet/src/transports/google-meet-urls.ts
601
633
  function forceMeetEnglishUi(url) {
602
634
  try {
603
635
  const parsed = new URL(url);
@@ -612,7 +644,7 @@ function normalizeMeetUrlForReuse(url) {
612
644
  try {
613
645
  const parsed = new URL(url);
614
646
  if (parsed.protocol !== "https:" || parsed.hostname.toLowerCase() !== "meet.google.com") return;
615
- const match = parsed.pathname.match(/^\/(new|[a-z]{3}-[a-z]{4}-[a-z]{3})(?:\/)?$/i);
647
+ const match = parsed.pathname.match(/^\/([a-z]{3}-[a-z]{4}-[a-z]{3})(?:\/)?$/i);
616
648
  if (!match?.[1]) return;
617
649
  return `https://meet.google.com/${match[1].toLowerCase()}`;
618
650
  } catch {
@@ -633,99 +665,18 @@ function isEnglishMeetTab(url) {
633
665
  return false;
634
666
  }
635
667
  }
636
- function isGoogleMeetNode(node) {
637
- const commands = Array.isArray(node.commands) ? node.commands : [];
638
- const caps = Array.isArray(node.caps) ? node.caps : [];
639
- return node.connected === true && commands.includes("googlemeet.chrome") && (commands.includes("browser.proxy") || caps.includes("browser"));
640
- }
641
- function matchesRequestedNode(node, requested) {
642
- return [
643
- node.nodeId,
644
- node.displayName,
645
- node.remoteIp
646
- ].some((value) => value === requested);
647
- }
648
- function formatNodeLabel(node) {
649
- const parts = [
650
- node.displayName,
651
- node.nodeId,
652
- node.remoteIp
653
- ].filter(Boolean);
654
- return parts.length > 0 ? parts.join(" / ") : "unknown node";
655
- }
656
- function describeNodeUsabilityIssues(node) {
657
- const commands = Array.isArray(node.commands) ? node.commands : [];
658
- const caps = Array.isArray(node.caps) ? node.caps : [];
659
- const issues = [];
660
- if (node.connected !== true) issues.push("offline");
661
- if (!commands.includes("googlemeet.chrome")) issues.push("missing googlemeet.chrome");
662
- if (!commands.includes("browser.proxy") && !caps.includes("browser")) issues.push("missing browser.proxy/browser capability");
663
- return issues;
664
- }
665
- async function listGoogleMeetNodes(runtime, params) {
668
+ function readMeetAuthUser(url) {
669
+ if (!url) return;
666
670
  try {
667
- return params ? await runtime.nodes.list(params) : await runtime.nodes.list();
668
- } catch (error) {
669
- throw new Error("Google Meet node inventory unavailable", { cause: error });
670
- }
671
- }
672
- async function resolveChromeNodeInfo(params) {
673
- const requested = params.requestedNode?.trim();
674
- if (requested) {
675
- const matches = (await listGoogleMeetNodes(params.runtime)).nodes.filter((node) => matchesRequestedNode(node, requested));
676
- if (matches.length > 1) throw new Error(`Configured Google Meet node ${requested} is ambiguous (${matches.length} matches). Pin chromeNode.node to a unique node id, display name, or remote IP.`);
677
- const [node] = matches;
678
- if (!node) throw new Error(`Configured Google Meet node ${requested} was not found. Run \`openclaw nodes status\` and start or approve the Chrome node.`);
679
- if (isGoogleMeetNode(node)) return node;
680
- throw new Error(`Configured Google Meet node ${requested} is not usable (${formatNodeLabel(node)}): ${describeNodeUsabilityIssues(node).join("; ")}. Start or reinstall \`openclaw node run\` on that Chrome host, approve pairing, and allow googlemeet.chrome plus browser.proxy.`);
681
- }
682
- const nodes = (await listGoogleMeetNodes(params.runtime, { connected: true })).nodes.filter(isGoogleMeetNode);
683
- const [node] = nodes;
684
- if (!node) throw new Error("No connected Google Meet-capable node with browser proxy. Run `openclaw node run` on the Chrome host with browser proxy enabled, approve pairing, and allow googlemeet.chrome plus browser.proxy.");
685
- if (nodes.length === 1) return node;
686
- throw new Error("Multiple Google Meet-capable nodes connected. Set plugins.entries.google-meet.config.chromeNode.node.");
687
- }
688
- async function resolveChromeNode(params) {
689
- const node = await resolveChromeNodeInfo(params);
690
- if (!node.nodeId) throw new Error("Google Meet node did not include a node id.");
691
- return node.nodeId;
692
- }
693
- function unwrapNodeInvokePayload(raw) {
694
- const record = raw && typeof raw === "object" ? raw : {};
695
- if (typeof record.payloadJSON === "string" && record.payloadJSON.trim()) try {
696
- return JSON.parse(record.payloadJSON);
697
- } catch (error) {
698
- throw new Error("Google Meet browser proxy returned malformed payloadJSON.", { cause: error });
671
+ return new URL(url).searchParams.get("authuser") ?? void 0;
672
+ } catch {
673
+ return;
699
674
  }
700
- if ("payload" in record) return record.payload;
701
- return raw;
702
- }
703
- function parseBrowserProxyResult(raw) {
704
- const payload = unwrapNodeInvokePayload(raw);
705
- const proxy = payload && typeof payload === "object" ? payload : void 0;
706
- if (!proxy || !("result" in proxy)) throw new Error("Google Meet browser proxy returned an invalid result.");
707
- return proxy.result;
708
- }
709
- async function callBrowserProxyOnNode(params) {
710
- return parseBrowserProxyResult(await params.runtime.nodes.invoke({
711
- nodeId: params.nodeId,
712
- command: "browser.proxy",
713
- params: {
714
- method: params.method,
715
- path: params.path,
716
- body: params.body,
717
- timeoutMs: params.timeoutMs
718
- },
719
- timeoutMs: addTimerTimeoutGraceMs(params.timeoutMs) ?? 1,
720
- scopes: ["operator.admin"]
721
- }));
722
- }
723
- function asBrowserTabs(result) {
724
- const record = result && typeof result === "object" ? result : {};
725
- return Array.isArray(record.tabs) ? record.tabs : [];
726
675
  }
727
- function readBrowserTab(result) {
728
- return result && typeof result === "object" ? result : void 0;
676
+ function isRecoverableMeetTab(tab, url) {
677
+ if (url) return isSameMeetUrlForReuse(tab.url, url);
678
+ if (normalizeMeetUrlForReuse(tab.url)) return true;
679
+ return (tab.url ?? "").startsWith("https://accounts.google.com/") && /sign in|google accounts|meet/i.test(tab.title ?? "");
729
680
  }
730
681
  //#endregion
731
682
  //#region extensions/google-meet/src/transports/chrome-create.ts
@@ -990,4 +941,4 @@ async function createMeetWithBrowserProxyOnNode(params) {
990
941
  throw new Error(lastResult?.manualAction ?? `Google Meet did not return a meeting URL from the browser create flow before timeout.${lastError ? ` Last browser automation error: ${formatBrowserAutomationError(lastError)}` : ""}`);
991
942
  }
992
943
  //#endregion
993
- export { fetchGoogleMeetSpace as _, forceMeetEnglishUi as a, normalizeMeetUrlForReuse as c, resolveChromeNodeInfo as d, buildGoogleMeetPreflightReport as f, fetchGoogleMeetAttendance as g, fetchGoogleMeetArtifacts as h, callBrowserProxyOnNode as i, readBrowserTab as l, endGoogleMeetActiveConference as m, isGoogleMeetBrowserManualActionError as n, isEnglishMeetTab as o, createGoogleMeetSpace as p, asBrowserTabs as r, isSameMeetUrlForReuse as s, createMeetWithBrowserProxyOnNode as t, resolveChromeNode as u, fetchLatestGoogleMeetConferenceRecord as v };
944
+ export { endGoogleMeetActiveConference as _, isRecoverableMeetTab as a, readMeetAuthUser as c, resolveChromeNodeInfo as d, GOOGLE_MEET_NODE_COMMAND as f, createGoogleMeetSpace as g, fetchGoogleMeetAttendance as h, isEnglishMeetTab as i, callBrowserProxyOnNode as l, fetchGoogleMeetArtifacts as m, isGoogleMeetBrowserManualActionError as n, isSameMeetUrlForReuse as o, buildGoogleMeetPreflightReport as p, forceMeetEnglishUi as r, normalizeMeetUrlForReuse as s, createMeetWithBrowserProxyOnNode as t, resolveChromeNode as u, fetchGoogleMeetSpace as v, fetchLatestGoogleMeetConferenceRecord as y };