@openclaw/google-meet 2026.7.2-beta.1 → 2026.7.2-beta.3

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";
@@ -597,7 +597,37 @@ function buildGoogleMeetPreflightReport(params) {
597
597
  };
598
598
  }
599
599
  //#endregion
600
+ //#region extensions/google-meet/src/transports/google-meet-platform-constants.ts
601
+ const GOOGLE_MEET_NODE_COMMAND = "googlemeet.chrome";
602
+ const GOOGLE_MEET_BROWSER_NODE_ADAPTER = {
603
+ displayName: "Google Meet",
604
+ nodeCommandName: GOOGLE_MEET_NODE_COMMAND,
605
+ nodeConfigPath: "plugins.entries.google-meet.config.chromeNode.node"
606
+ };
607
+ //#endregion
600
608
  //#region extensions/google-meet/src/transports/chrome-browser-proxy.ts
609
+ async function resolveChromeNodeInfo(params) {
610
+ return await resolveMeetingBrowserNodeInfo({
611
+ ...params,
612
+ adapter: GOOGLE_MEET_BROWSER_NODE_ADAPTER
613
+ });
614
+ }
615
+ async function resolveChromeNode(params) {
616
+ return await resolveMeetingBrowserNode({
617
+ ...params,
618
+ adapter: GOOGLE_MEET_BROWSER_NODE_ADAPTER
619
+ });
620
+ }
621
+ async function callBrowserProxyOnNode(params) {
622
+ return await callMeetingBrowserProxyOnNode({
623
+ ...params,
624
+ adapter: GOOGLE_MEET_BROWSER_NODE_ADAPTER
625
+ });
626
+ }
627
+ const asBrowserTabs = asMeetingBrowserTabs;
628
+ const readBrowserTab = readMeetingBrowserTab;
629
+ //#endregion
630
+ //#region extensions/google-meet/src/transports/google-meet-urls.ts
601
631
  function forceMeetEnglishUi(url) {
602
632
  try {
603
633
  const parsed = new URL(url);
@@ -612,7 +642,7 @@ function normalizeMeetUrlForReuse(url) {
612
642
  try {
613
643
  const parsed = new URL(url);
614
644
  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);
645
+ const match = parsed.pathname.match(/^\/([a-z]{3}-[a-z]{4}-[a-z]{3})(?:\/)?$/i);
616
646
  if (!match?.[1]) return;
617
647
  return `https://meet.google.com/${match[1].toLowerCase()}`;
618
648
  } catch {
@@ -633,99 +663,18 @@ function isEnglishMeetTab(url) {
633
663
  return false;
634
664
  }
635
665
  }
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) {
666
+ function readMeetAuthUser(url) {
667
+ if (!url) return;
666
668
  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 });
669
+ return new URL(url).searchParams.get("authuser") ?? void 0;
670
+ } catch {
671
+ return;
699
672
  }
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
673
  }
727
- function readBrowserTab(result) {
728
- return result && typeof result === "object" ? result : void 0;
674
+ function isRecoverableMeetTab(tab, url) {
675
+ if (url) return isSameMeetUrlForReuse(tab.url, url);
676
+ if (normalizeMeetUrlForReuse(tab.url)) return true;
677
+ return (tab.url ?? "").startsWith("https://accounts.google.com/") && /sign in|google accounts|meet/i.test(tab.title ?? "");
729
678
  }
730
679
  //#endregion
731
680
  //#region extensions/google-meet/src/transports/chrome-create.ts
@@ -990,4 +939,4 @@ async function createMeetWithBrowserProxyOnNode(params) {
990
939
  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
940
  }
992
941
  //#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 };
942
+ export { fetchGoogleMeetAttendance as _, isRecoverableMeetTab as a, readMeetAuthUser as c, resolveChromeNodeInfo as d, GOOGLE_MEET_NODE_COMMAND as f, fetchGoogleMeetArtifacts as g, endGoogleMeetActiveConference as h, isEnglishMeetTab as i, callBrowserProxyOnNode as l, createGoogleMeetSpace 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 };
@@ -1,7 +1,7 @@
1
- import { a as buildGoogleMeetCalendarDayWindow, i as resolveGoogleMeetGatewayOperationTimeoutMs, o as findGoogleMeetCalendarEvent, s as listGoogleMeetCalendarEvents } from "./config-BeoHH_z5.js";
2
- import { _ as fetchGoogleMeetSpace, f as buildGoogleMeetPreflightReport, g as fetchGoogleMeetAttendance, h as fetchGoogleMeetArtifacts, m as endGoogleMeetActiveConference, p as createGoogleMeetSpace, v as fetchLatestGoogleMeetConferenceRecord } from "./chrome-create-DM1XJCOH.js";
1
+ import { a as buildGoogleMeetCalendarDayWindow, i as resolveGoogleMeetGatewayOperationTimeoutMs, o as findGoogleMeetCalendarEvent, s as listGoogleMeetCalendarEvents } from "./config-BcaS1BDr.js";
2
+ import { _ as fetchGoogleMeetAttendance, g as fetchGoogleMeetArtifacts, h as endGoogleMeetActiveConference, m as createGoogleMeetSpace, p as buildGoogleMeetPreflightReport, v as fetchGoogleMeetSpace, y as fetchLatestGoogleMeetConferenceRecord } from "./chrome-create-CBdUFMBH.js";
3
3
  import { buildGoogleMeetAuthUrl, createGoogleMeetOAuthState, createGoogleMeetPkce, exchangeGoogleMeetAuthCode, resolveGoogleMeetAccessToken, waitForGoogleMeetAuthCode } from "./oauth-DOfMKlGp.js";
4
- import { hasCreateSpaceConfigInput, resolveCreateSpaceConfig } from "./create-CWcFI0ub.js";
4
+ import { hasCreateSpaceConfigInput, resolveCreateSpaceConfig } from "./create-DK5lNDEp.js";
5
5
  import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
6
6
  import { callGatewayFromCli } from "openclaw/plugin-sdk/gateway-runtime";
7
7
  import { clampTimerTimeoutMs, parseStrictNonNegativeInteger, parseStrictPositiveInteger } from "openclaw/plugin-sdk/number-runtime";
@@ -578,9 +578,12 @@ function renderAttendanceMarkdown(result) {
578
578
  }
579
579
  return `${lines.join("\n")}\n`;
580
580
  }
581
+ function neutralizeSpreadsheetFormulaCell(text) {
582
+ return /^[ \t\r\n]*[=+\-@\uFF0B\uFF0D\uFF1D\uFF20]/u.test(text) || /^[\t\r\n]/.test(text) ? `'${text}` : text;
583
+ }
581
584
  function csvCell(value) {
582
- const text = value === void 0 || value === null ? "" : typeof value === "string" || typeof value === "number" || typeof value === "boolean" ? String(value) : JSON.stringify(value);
583
- return /[",\n]/.test(text) ? `"${text.replaceAll("\"", "\"\"")}"` : text;
585
+ const safeText = neutralizeSpreadsheetFormulaCell(value === void 0 || value === null ? "" : typeof value === "string" || typeof value === "number" || typeof value === "boolean" ? String(value) : JSON.stringify(value));
586
+ return /[",\r\n]/.test(safeText) ? `"${safeText.replaceAll("\"", "\"\"")}"` : safeText;
584
587
  }
585
588
  function renderAttendanceCsv(result) {
586
589
  const rows = [[
@@ -2,6 +2,7 @@ import { t as googleApiError } from "./google-api-errors-CDUYkIcK.js";
2
2
  import { asRecord, normalizeOptionalLowercaseString, normalizeOptionalString, normalizeOptionalTrimmedStringList } from "openclaw/plugin-sdk/string-coerce-runtime";
3
3
  import { readProviderJsonResponse } from "openclaw/plugin-sdk/provider-http";
4
4
  import { fetchWithSsrFGuard } from "openclaw/plugin-sdk/ssrf-runtime";
5
+ import { buildMeetingSoxAudioCommands } from "openclaw/plugin-sdk/meeting-runtime";
5
6
  import { addTimerTimeoutGraceMs, resolvePositiveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
6
7
  import { REALTIME_VOICE_AGENT_CONSULT_TOOL_NAME, resolveRealtimeVoiceAgentConsultToolPolicy } from "openclaw/plugin-sdk/realtime-voice";
7
8
  //#region extensions/google-meet/src/meet-url.ts
@@ -180,85 +181,31 @@ const SOX_DEFAULT_BUFFER_BYTES = 8192;
180
181
  const SOX_MIN_BUFFER_BYTES = 17;
181
182
  const DEFAULT_GOOGLE_MEET_AUDIO_BUFFER_BYTES = SOX_DEFAULT_BUFFER_BYTES / 2;
182
183
  const PLAIN_DECIMAL_NUMBER_RE = /^\d+(?:\.\d+)?$/;
183
- function withSoxBuffer(command, bufferBytes) {
184
- return [
185
- command[0] ?? "sox",
186
- "-q",
187
- "--buffer",
188
- String(bufferBytes),
189
- ...command.slice(2)
190
- ];
191
- }
192
- const DEFAULT_GOOGLE_MEET_AUDIO_INPUT_COMMAND_BASE = [
193
- "sox",
194
- "-q",
195
- "-t",
196
- "coreaudio",
197
- "BlackHole 2ch",
198
- "-t",
199
- "raw",
200
- "-r",
201
- "24000",
202
- "-c",
203
- "1",
204
- "-e",
205
- "signed-integer",
206
- "-b",
207
- "16",
208
- "-L",
209
- "-"
210
- ];
211
- const DEFAULT_GOOGLE_MEET_AUDIO_OUTPUT_COMMAND_BASE = [
212
- "sox",
213
- "-q",
214
- "-t",
215
- "raw",
216
- "-r",
217
- "24000",
218
- "-c",
219
- "1",
220
- "-e",
221
- "signed-integer",
222
- "-b",
223
- "16",
224
- "-L",
225
- "-",
226
- "-t",
227
- "coreaudio",
228
- "BlackHole 2ch"
229
- ];
230
- const LEGACY_GOOGLE_MEET_AUDIO_INPUT_COMMAND_BASE = [
231
- "rec",
232
- "-q",
233
- "-t",
234
- "raw",
235
- "-r",
236
- "8000",
237
- "-c",
238
- "1",
239
- "-e",
240
- "mu-law",
241
- "-b",
242
- "8",
243
- "-"
244
- ];
245
- const LEGACY_GOOGLE_MEET_AUDIO_OUTPUT_COMMAND_BASE = [
246
- "play",
247
- "-q",
248
- "-t",
249
- "raw",
250
- "-r",
251
- "8000",
252
- "-c",
253
- "1",
254
- "-e",
255
- "mu-law",
256
- "-b",
257
- "8",
258
- "-"
259
- ];
260
- const DEFAULT_GOOGLE_MEET_AUDIO_INPUT_COMMAND = withSoxBuffer(DEFAULT_GOOGLE_MEET_AUDIO_INPUT_COMMAND_BASE, DEFAULT_GOOGLE_MEET_AUDIO_BUFFER_BYTES);
261
- const DEFAULT_GOOGLE_MEET_AUDIO_OUTPUT_COMMAND = withSoxBuffer(DEFAULT_GOOGLE_MEET_AUDIO_OUTPUT_COMMAND_BASE, DEFAULT_GOOGLE_MEET_AUDIO_BUFFER_BYTES);
184
+ function buildGoogleMeetSoxAudioCommands(format, bufferBytes) {
185
+ return format === "g711-ulaw-8khz" ? buildMeetingSoxAudioCommands({
186
+ bufferBytes,
187
+ format: {
188
+ sampleRate: 8e3,
189
+ channels: 1,
190
+ encoding: "mu-law",
191
+ bits: 8
192
+ }
193
+ }) : buildMeetingSoxAudioCommands({
194
+ bufferBytes,
195
+ device: "BlackHole 2ch",
196
+ deviceType: "coreaudio",
197
+ format: {
198
+ sampleRate: 24e3,
199
+ channels: 1,
200
+ encoding: "signed-integer",
201
+ bits: 16,
202
+ endian: "little"
203
+ }
204
+ });
205
+ }
206
+ const DEFAULT_GOOGLE_MEET_SOX_COMMANDS = buildGoogleMeetSoxAudioCommands("pcm16-24khz", DEFAULT_GOOGLE_MEET_AUDIO_BUFFER_BYTES);
207
+ const DEFAULT_GOOGLE_MEET_AUDIO_INPUT_COMMAND = DEFAULT_GOOGLE_MEET_SOX_COMMANDS.inputCommand;
208
+ const DEFAULT_GOOGLE_MEET_AUDIO_OUTPUT_COMMAND = DEFAULT_GOOGLE_MEET_SOX_COMMANDS.outputCommand;
262
209
  const DEFAULT_GOOGLE_MEET_CHROME_AUDIO_FORMAT = "pcm16-24khz";
263
210
  const DEFAULT_GOOGLE_MEET_BARGE_IN_RMS_THRESHOLD = 650;
264
211
  const DEFAULT_GOOGLE_MEET_BARGE_IN_PEAK_THRESHOLD = 2500;
@@ -405,10 +352,10 @@ function resolveAudioBufferBytes(value, fallback) {
405
352
  return Math.max(SOX_MIN_BUFFER_BYTES, Math.trunc(number));
406
353
  }
407
354
  function defaultAudioInputCommand(format, bufferBytes) {
408
- return withSoxBuffer(format === "g711-ulaw-8khz" ? LEGACY_GOOGLE_MEET_AUDIO_INPUT_COMMAND_BASE : DEFAULT_GOOGLE_MEET_AUDIO_INPUT_COMMAND_BASE, bufferBytes);
355
+ return buildGoogleMeetSoxAudioCommands(format, bufferBytes).inputCommand;
409
356
  }
410
357
  function defaultAudioOutputCommand(format, bufferBytes) {
411
- return withSoxBuffer(format === "g711-ulaw-8khz" ? LEGACY_GOOGLE_MEET_AUDIO_OUTPUT_COMMAND_BASE : DEFAULT_GOOGLE_MEET_AUDIO_OUTPUT_COMMAND_BASE, bufferBytes);
358
+ return buildGoogleMeetSoxAudioCommands(format, bufferBytes).outputCommand;
412
359
  }
413
360
  function resolveGoogleMeetConfig(input) {
414
361
  return resolveGoogleMeetConfigWithEnv(input);
@@ -1,4 +1,4 @@
1
- import { p as createGoogleMeetSpace, t as createMeetWithBrowserProxyOnNode } from "./chrome-create-DM1XJCOH.js";
1
+ import { m as createGoogleMeetSpace, t as createMeetWithBrowserProxyOnNode } from "./chrome-create-CBdUFMBH.js";
2
2
  import { resolveGoogleMeetAccessToken } from "./oauth-DOfMKlGp.js";
3
3
  import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
4
4
  //#region extensions/google-meet/src/create.ts