@openclaw/google-meet 2026.9.1-beta.1 → 2026.9.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.
@@ -1,7 +1,7 @@
1
- import { a as resolveGoogleMeetTokenFromParams, c as buildGoogleMeetPreflightReport, d as fetchGoogleMeetSpace, f as fetchLatestGoogleMeetConferenceRecord, i as resolveArtifactQueryFromParams, l as createGoogleMeetSpace, m as listGoogleMeetCalendarEvents, n as fetchResolvedGoogleMeetAttendance, o as resolveMeetingFromParams, p as buildGoogleMeetCalendarDayWindow, s as resolveSpaceFromParams, t as fetchResolvedGoogleMeetArtifacts, u as endGoogleMeetActiveConference } from "./plugin-helpers-C9-Y0Ago.js";
1
+ import { a as resolveGoogleMeetTokenFromParams, c as buildGoogleMeetPreflightReport, d as fetchGoogleMeetSpace, f as fetchLatestGoogleMeetConferenceRecord, i as resolveArtifactQueryFromParams, l as createGoogleMeetSpace, m as listGoogleMeetCalendarEvents, n as fetchResolvedGoogleMeetAttendance, o as resolveMeetingFromParams, p as buildGoogleMeetCalendarDayWindow, s as resolveSpaceFromParams, t as fetchResolvedGoogleMeetArtifacts, u as endGoogleMeetActiveConference } from "./plugin-helpers-WF-JVJhh.js";
2
2
  import { i as resolveGoogleMeetGatewayOperationTimeoutMs } from "./config-wBK8loBb.js";
3
- import { buildGoogleMeetAuthUrl, exchangeGoogleMeetAuthCode, resolveGoogleMeetAccessToken, waitForGoogleMeetAuthCode } from "./oauth-9sUJ68Mw.js";
4
- import { n as hasCreateSpaceConfigInput, r as resolveCreateSpaceConfig } from "./create-BEDHM6uL.js";
3
+ import { buildGoogleMeetAuthUrl, exchangeGoogleMeetAuthCode, resolveGoogleMeetAccessToken, waitForGoogleMeetAuthCode } from "./oauth-DgBscjXK.js";
4
+ import { n as hasCreateSpaceConfigInput, r as resolveCreateSpaceConfig } from "./create-Djmk2CQz.js";
5
5
  import { clampTimerTimeoutMs, parseStrictNonNegativeInteger, parseStrictPositiveInteger } from "openclaw/plugin-sdk/number-runtime";
6
6
  import { callGatewayFromCli, isGatewayClientRequestError, isGatewayTransportError } from "openclaw/plugin-sdk/gateway-runtime";
7
7
  import { generateHexPkceVerifierChallenge } from "openclaw/plugin-sdk/provider-auth";
@@ -139,7 +139,8 @@ async function callGoogleMeetGateway(params) {
139
139
  }
140
140
  function formatDuration(value) {
141
141
  if (value === void 0) return "n/a";
142
- return formatDurationCompact(Math.max(0, Math.round(value / 1e3) * 1e3), {
142
+ const roundedMs = Math.max(0, Math.round(value / 1e3) * 1e3);
143
+ return formatDurationCompact(roundedMs, {
143
144
  showYears: true,
144
145
  spaced: true
145
146
  }) ?? "0ms";
@@ -656,6 +657,9 @@ async function resolveCliArtifactQuery(context, options) {
656
657
  earlyBeforeMinutes
657
658
  };
658
659
  }
660
+ function resolveTokenSource(refreshed) {
661
+ return refreshed ? "refresh-token" : "cached-access-token";
662
+ }
659
663
  function registerGoogleMeetArtifactCommands(context) {
660
664
  const params = context;
661
665
  const { root } = context;
@@ -665,7 +669,7 @@ function registerGoogleMeetArtifactCommands(context) {
665
669
  if (options.json) {
666
670
  await writeCliOutput(options, JSON.stringify({
667
671
  ...result,
668
- tokenSource: resolved.token.refreshed ? "refresh-token" : "cached-access-token"
672
+ tokenSource: resolveTokenSource(resolved.token.refreshed)
669
673
  }, null, 2));
670
674
  return;
671
675
  }
@@ -675,7 +679,7 @@ function registerGoogleMeetArtifactCommands(context) {
675
679
  }
676
680
  if (options.format && options.format !== "summary") throw new Error("Unsupported format. Expected summary or markdown.");
677
681
  writeArtifactsSummary(result);
678
- writeStdoutLine("token source: %s", resolved.token.refreshed ? "refresh-token" : "cached-access-token");
682
+ writeStdoutLine("token source: %s", resolveTokenSource(resolved.token.refreshed));
679
683
  });
680
684
  addGoogleMeetArtifactOptions(root.command("attendance").description("List Meet participants and participant sessions")).option("--no-merge-duplicates", "Keep duplicate participant resources as separate rows").option("--late-after-minutes <n>", "Mark participants late after this many minutes", "5").option("--early-before-minutes <n>", "Mark early leavers before this many minutes", "5").option("--format <format>", "Output format: summary, markdown, or csv", "summary").option("--output <path>", "Write output to a file instead of stdout").option("--json", "Print JSON output", false).action(async (options) => {
681
685
  const resolved = await resolveCliArtifactQuery(params, options);
@@ -683,7 +687,7 @@ function registerGoogleMeetArtifactCommands(context) {
683
687
  if (options.json) {
684
688
  await writeCliOutput(options, JSON.stringify({
685
689
  ...result,
686
- tokenSource: resolved.token.refreshed ? "refresh-token" : "cached-access-token"
690
+ tokenSource: resolveTokenSource(resolved.token.refreshed)
687
691
  }, null, 2));
688
692
  return;
689
693
  }
@@ -697,7 +701,7 @@ function registerGoogleMeetArtifactCommands(context) {
697
701
  }
698
702
  if (options.format && options.format !== "summary") throw new Error("Unsupported format. Expected summary, markdown, or csv.");
699
703
  writeAttendanceSummary(result);
700
- writeStdoutLine("token source: %s", resolved.token.refreshed ? "refresh-token" : "cached-access-token");
704
+ writeStdoutLine("token source: %s", resolveTokenSource(resolved.token.refreshed));
701
705
  });
702
706
  addGoogleMeetArtifactOptions(root.command("export").description("Write Meet artifacts, attendance, transcript, and raw JSON into a folder")).option("--no-transcript-entries", "Skip structured transcript entry lookup").option("--include-doc-bodies", "Export linked transcript and smart-note Google Docs text").option("--no-merge-duplicates", "Keep duplicate participant resources as separate rows").option("--late-after-minutes <n>", "Mark participants late after this many minutes", "5").option("--early-before-minutes <n>", "Mark early leavers before this many minutes", "5").option("--output <dir>", "Output directory").option("--zip", "Also write a portable .zip archive").option("--dry-run", "Fetch export data and print the manifest without writing files", false).option("--json", "Print JSON output", false).action(async (options) => {
703
707
  const resolved = await resolveCliArtifactQuery(params, options);
@@ -725,11 +729,11 @@ function registerGoogleMeetArtifactCommands(context) {
725
729
  attendance,
726
730
  files: googleMeetExportFileNames(),
727
731
  request,
728
- tokenSource: resolved.token.refreshed ? "refresh-token" : "cached-access-token",
732
+ tokenSource: resolveTokenSource(resolved.token.refreshed),
729
733
  ...resolved.calendarEvent ? { calendarEvent: resolved.calendarEvent } : {}
730
734
  }),
731
735
  ...resolved.calendarEvent ? { calendarEvent: resolved.calendarEvent } : {},
732
- tokenSource: resolved.token.refreshed ? "refresh-token" : "cached-access-token"
736
+ tokenSource: resolveTokenSource(resolved.token.refreshed)
733
737
  });
734
738
  return;
735
739
  }
@@ -739,13 +743,13 @@ function registerGoogleMeetArtifactCommands(context) {
739
743
  attendance,
740
744
  zip: Boolean(options.zip),
741
745
  request,
742
- tokenSource: resolved.token.refreshed ? "refresh-token" : "cached-access-token",
746
+ tokenSource: resolveTokenSource(resolved.token.refreshed),
743
747
  ...resolved.calendarEvent ? { calendarEvent: resolved.calendarEvent } : {}
744
748
  });
745
749
  const payload = {
746
750
  ...bundle,
747
751
  ...resolved.calendarEvent ? { calendarEvent: resolved.calendarEvent } : {},
748
- tokenSource: resolved.token.refreshed ? "refresh-token" : "cached-access-token"
752
+ tokenSource: resolveTokenSource(resolved.token.refreshed)
749
753
  };
750
754
  if (options.json) {
751
755
  writeStdoutJson(payload);
@@ -1323,17 +1327,18 @@ function registerGoogleMeetCli(params) {
1323
1327
  challenge,
1324
1328
  state
1325
1329
  });
1330
+ const code = await waitForGoogleMeetAuthCode({
1331
+ state,
1332
+ manual: Boolean(options.manual),
1333
+ timeoutMs: resolveGoogleMeetOAuthCallbackTimeoutMs(options.timeoutSec),
1334
+ authUrl,
1335
+ promptInput,
1336
+ writeLine: (message) => writeStdoutLine("%s", message)
1337
+ });
1326
1338
  const tokens = await exchangeGoogleMeetAuthCode({
1327
1339
  clientId,
1328
1340
  clientSecret,
1329
- code: await waitForGoogleMeetAuthCode({
1330
- state,
1331
- manual: Boolean(options.manual),
1332
- timeoutMs: resolveGoogleMeetOAuthCallbackTimeoutMs(options.timeoutSec),
1333
- authUrl,
1334
- promptInput,
1335
- writeLine: (message) => writeStdoutLine("%s", message)
1336
- }),
1341
+ code,
1337
1342
  verifier
1338
1343
  });
1339
1344
  if (!tokens.refreshToken) throw new Error("Google OAuth did not return a refresh token. Re-run the flow with consent and offline access.");
@@ -1,5 +1,5 @@
1
- import { h as __exportAll, l as createGoogleMeetSpace } from "./plugin-helpers-C9-Y0Ago.js";
2
- import { resolveGoogleMeetAccessToken } from "./oauth-9sUJ68Mw.js";
1
+ import { h as __exportAll, l as createGoogleMeetSpace } from "./plugin-helpers-WF-JVJhh.js";
2
+ import { resolveGoogleMeetAccessToken } from "./oauth-DgBscjXK.js";
3
3
  import { t as createMeetWithBrowserProxyOnNode } from "./chrome-create-PKAyxCiL.js";
4
4
  import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
5
5
  //#region extensions/google-meet/src/create.ts
@@ -20,7 +20,9 @@ const legacyConfigRules = [{
20
20
  match: hasLegacyGoogleRealtimeProvider
21
21
  }];
22
22
  function migrateGoogleMeetLegacyRealtimeProvider(config) {
23
- const rawRealtime = asNullableRecord(asNullableRecord(asNullableRecord(config.plugins?.entries?.["google-meet"])?.config)?.realtime);
23
+ const rawEntry = asNullableRecord(config.plugins?.entries?.["google-meet"]);
24
+ const rawPluginConfig = asNullableRecord(rawEntry?.config);
25
+ const rawRealtime = asNullableRecord(rawPluginConfig?.realtime);
24
26
  if (!rawRealtime || !hasLegacyGoogleRealtimeProvider(rawRealtime)) return null;
25
27
  const nextConfig = structuredClone(config);
26
28
  const nextPlugins = asNullableRecord(nextConfig.plugins) ?? {};
@@ -1,7 +1,7 @@
1
1
  import { readResponseTextLimited } from "openclaw/plugin-sdk/provider-http";
2
2
  //#region extensions/google-meet/src/google-api-errors.ts
3
3
  const REAUTH_HINT = "Re-run `openclaw googlemeet auth login` and store the refreshed oauth block.";
4
- const GOOGLE_API_ERROR_BODY_LIMIT_BYTES = 8 * 1024;
4
+ const GOOGLE_API_ERROR_BODY_LIMIT_BYTES = 8192;
5
5
  function scopeText(scopes) {
6
6
  return scopes.map((scope) => `\`${scope}\``).join(", ");
7
7
  }
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { t as GOOGLE_MEET_CLI_DESCRIPTOR } from "./cli-output-mode-BwH_6tH8.js";
2
2
  import { n as GOOGLE_MEET_NODE_COMMAND } from "./google-meet-platform-constants-Bs5iAg3E.js";
3
3
  import { r as resolveGoogleMeetConfig } from "./config-wBK8loBb.js";
4
- import { a as createLazyGoogleMeetNodeInvokePolicy, c as loadGoogleMeetCliModule, d as normalizeMode, f as normalizeTransport, h as shouldJoinCreatedMeet, i as createGoogleMeetRuntimeAccessor, l as loadGoogleMeetNodeHostModule, m as sendGoogleMeetGatewayError, n as assertGoogleMeetAgentToolActionSupported, o as formatGoogleMeetGatewayError, p as resolveMeetingInput, r as callGoogleMeetGatewayFromTool, s as keepTrustedToolAgentId, t as asParamRecord, u as loadGoogleMeetPluginHelpers } from "./plugin-registration-Csi-NdQU.js";
4
+ import { a as createLazyGoogleMeetNodeInvokePolicy, c as loadGoogleMeetCliModule, d as normalizeMode, f as normalizeTransport, h as shouldJoinCreatedMeet, i as createGoogleMeetRuntimeAccessor, l as loadGoogleMeetNodeHostModule, m as sendGoogleMeetGatewayError, n as assertGoogleMeetAgentToolActionSupported, o as formatGoogleMeetGatewayError, p as resolveMeetingInput, r as callGoogleMeetGatewayFromTool, s as keepTrustedToolAgentId, t as asParamRecord, u as loadGoogleMeetPluginHelpers } from "./plugin-registration-NIwMvP6X.js";
5
5
  import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
6
6
  import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
7
7
  import { jsonResult } from "openclaw/plugin-sdk/tool-results";
@@ -338,7 +338,10 @@ var google_meet_default = definePluginEntry({
338
338
  case "calendar_events":
339
339
  case "artifacts":
340
340
  case "attendance": return jsonResult(await queryActions[raw.action](raw));
341
- case "export": return jsonResult(await (await loadGoogleMeetPluginHelpers()).exportGoogleMeetBundleFromParams(config, raw));
341
+ case "export": {
342
+ const helpers = await loadGoogleMeetPluginHelpers();
343
+ return jsonResult(await helpers.exportGoogleMeetBundleFromParams(config, raw));
344
+ }
342
345
  case "leave":
343
346
  case "speak":
344
347
  if (!normalizeOptionalString(raw.sessionId)) throw new Error("sessionId required");
@@ -1,4 +1,4 @@
1
- import { n as readGoogleApiErrorDetail } from "./google-api-errors-CDUYkIcK.js";
1
+ import { n as readGoogleApiErrorDetail } from "./google-api-errors-BDYXfKRa.js";
2
2
  import { MAX_DATE_TIMESTAMP_MS, resolveDateTimestampMs, resolveExpiresAtMsFromDurationSeconds } from "openclaw/plugin-sdk/number-runtime";
3
3
  import { parseOAuthCallbackInput, waitForLocalOAuthCallback } from "openclaw/plugin-sdk/provider-auth-runtime";
4
4
  import { readProviderJsonResponse } from "openclaw/plugin-sdk/provider-http";
@@ -9,7 +9,7 @@ const GOOGLE_MEET_AUTH_URL = "https://accounts.google.com/o/oauth2/v2/auth";
9
9
  const GOOGLE_MEET_TOKEN_URL = "https://oauth2.googleapis.com/token";
10
10
  const GOOGLE_MEET_TOKEN_HOST = "oauth2.googleapis.com";
11
11
  const GOOGLE_MEET_DEFAULT_TOKEN_LIFETIME_SECONDS = 3600;
12
- const GOOGLE_OAUTH_TOKEN_JSON_MAX_BYTES = 256 * 1024;
12
+ const GOOGLE_OAUTH_TOKEN_JSON_MAX_BYTES = 262144;
13
13
  const GOOGLE_OAUTH_REQUEST_TIMEOUT_MS = 3e4;
14
14
  const GOOGLE_MEET_SCOPES = [
15
15
  "https://www.googleapis.com/auth/meetings.space.created",
@@ -123,7 +123,8 @@ function isLocalCallbackListenerError(error) {
123
123
  return error.message.includes("EADDRINUSE") || error.message.includes("port") || error.message.includes("listen");
124
124
  }
125
125
  async function readManualGoogleMeetAuthCode(params) {
126
- const parsed = parseOAuthCallbackInput(await params.promptInput("Paste the full redirect URL here: "), {
126
+ const input = await params.promptInput("Paste the full redirect URL here: ");
127
+ const parsed = parseOAuthCallbackInput(input, {
127
128
  missingState: "Missing 'state' parameter. Paste the full redirect URL.",
128
129
  invalidInput: "Paste the full redirect URL, not just the code."
129
130
  });
@@ -1,5 +1,5 @@
1
- import { c as loadGoogleMeetCliModule, p as resolveMeetingInput } from "./plugin-registration-Csi-NdQU.js";
2
- import { t as googleApiError } from "./google-api-errors-CDUYkIcK.js";
1
+ import { c as loadGoogleMeetCliModule, p as resolveMeetingInput } from "./plugin-registration-NIwMvP6X.js";
2
+ import { t as googleApiError } from "./google-api-errors-BDYXfKRa.js";
3
3
  import { t as normalizeMeetUrl } from "./meet-url-BP2Jlvjs.js";
4
4
  import { normalizeOptionalString, uniqueStrings } from "openclaw/plugin-sdk/string-coerce-runtime";
5
5
  import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
@@ -87,7 +87,7 @@ function rankCalendarEvent(event, nowMs) {
87
87
  const endMs = parseCalendarEventTime(event.end) ?? startMs;
88
88
  if (startMs <= nowMs && endMs >= nowMs) return 0;
89
89
  if (startMs > nowMs) return startMs - nowMs;
90
- return nowMs - startMs + 720 * 60 * 60 * 1e3;
90
+ return nowMs - startMs + 2592e6;
91
91
  }
92
92
  function chooseBestMeetCalendarEvent(events, now) {
93
93
  const nowMs = now.getTime();
@@ -773,7 +773,7 @@ var plugin_helpers_exports = /* @__PURE__ */ __exportAll({
773
773
  resolveMeetingFromParams: () => resolveMeetingFromParams,
774
774
  resolveSpaceFromParams: () => resolveSpaceFromParams
775
775
  });
776
- const loadGoogleMeetCreateModule = createLazyRuntimeModule(() => import("./create-BEDHM6uL.js").then((n) => n.t));
776
+ const loadGoogleMeetCreateModule = createLazyRuntimeModule(() => import("./create-Djmk2CQz.js").then((n) => n.t));
777
777
  async function createMeetFromParams(params) {
778
778
  return (await loadGoogleMeetCreateModule()).createMeetFromParams(params);
779
779
  }
@@ -781,7 +781,7 @@ async function createAndJoinMeetFromParams(params) {
781
781
  return (await loadGoogleMeetCreateModule()).createAndJoinMeetFromParams(params);
782
782
  }
783
783
  async function resolveGoogleMeetTokenFromParams(config, raw) {
784
- const { resolveGoogleMeetAccessToken } = await import("./oauth-9sUJ68Mw.js");
784
+ const { resolveGoogleMeetAccessToken } = await import("./oauth-DgBscjXK.js");
785
785
  return resolveGoogleMeetAccessToken({
786
786
  clientId: normalizeOptionalString(raw.clientId) ?? config.oauth.clientId,
787
787
  clientSecret: normalizeOptionalString(raw.clientSecret) ?? config.oauth.clientSecret,
@@ -4,10 +4,10 @@ import { asNonArrayRecord as asParamRecord, normalizeOptionalString } from "open
4
4
  import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
5
5
  import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
6
6
  //#region extensions/google-meet/src/plugin-registration.ts
7
- const loadGoogleMeetPluginHelpers = createLazyRuntimeModule(() => import("./plugin-helpers-C9-Y0Ago.js").then((n) => n.r));
8
- const loadGoogleMeetCliModule = createLazyRuntimeModule(() => import("./cli-Bd63VJ5q.js"));
7
+ const loadGoogleMeetPluginHelpers = createLazyRuntimeModule(() => import("./plugin-helpers-WF-JVJhh.js").then((n) => n.r));
8
+ const loadGoogleMeetCliModule = createLazyRuntimeModule(() => import("./cli-Cwc266K3.js"));
9
9
  const loadGoogleMeetNodeHostModule = createLazyRuntimeModule(() => import("./node-host-BXtXbsMa.js"));
10
- const loadGoogleMeetRuntimeModule = createLazyRuntimeModule(() => import("./runtime-B8d1beHo.js"));
10
+ const loadGoogleMeetRuntimeModule = createLazyRuntimeModule(() => import("./runtime-0IuZTlpN.js"));
11
11
  const loadGoogleMeetNodeInvokePolicyModule = createLazyRuntimeModule(() => import("./node-invoke-policy-B0gOlLJR.js"));
12
12
  const loadGoogleMeetGatewayRuntimeModule = createLazyRuntimeModule(() => import("openclaw/plugin-sdk/gateway-runtime"));
13
13
  const loadGoogleMeetNodeInvokePolicy = async (config) => (await loadGoogleMeetNodeInvokePolicyModule()).createGoogleMeetChromeNodeInvokePolicy(config);
@@ -71,7 +71,8 @@ function resolveUserPath(input) {
71
71
  }
72
72
  function isProviderUnreachableWebhookUrl(webhookUrl) {
73
73
  try {
74
- return isBlockedHostnameOrIp(new URL(webhookUrl).hostname);
74
+ const parsed = new URL(webhookUrl);
75
+ return isBlockedHostnameOrIp(parsed.hostname);
75
76
  } catch {
76
77
  return false;
77
78
  }
@@ -355,10 +356,24 @@ function parseNodeStartResult(raw) {
355
356
  if (!value || typeof value !== "object") throw new Error("Google Meet node returned an invalid start result.");
356
357
  return value;
357
358
  }
359
+ function chromeNodeBrowserRequest(runtime, nodeId) {
360
+ return async (request) => await callBrowserProxyOnNode({
361
+ runtime,
362
+ nodeId,
363
+ method: request.method,
364
+ path: request.path,
365
+ body: request.body,
366
+ timeoutMs: request.timeoutMs
367
+ });
368
+ }
358
369
  async function leaveChromeMeet(params) {
370
+ const node = params.transport === "chrome-node" ? { nodeId: params.nodeId ?? await resolveChromeNode({
371
+ runtime: params.runtime,
372
+ requestedNode: params.config.chromeNode.node
373
+ }) } : void 0;
359
374
  return await leaveMeetingWithBrowser({
360
375
  adapter: GOOGLE_MEET_PLATFORM_ADAPTER,
361
- callBrowser: await resolveLocalMeetingBrowserRequest(params.runtime),
376
+ callBrowser: node ? chromeNodeBrowserRequest(params.runtime, node.nodeId) : await resolveLocalMeetingBrowserRequest(params.runtime),
362
377
  launch: params.config.chrome.launch,
363
378
  meetingSessionId: params.meetingSessionId,
364
379
  meetingUrl: params.meetingUrl,
@@ -367,59 +382,18 @@ async function leaveChromeMeet(params) {
367
382
  });
368
383
  }
369
384
  async function readChromeMeetTranscript(params) {
370
- return await readMeetingTranscriptWithBrowser({
371
- adapter: GOOGLE_MEET_PLATFORM_ADAPTER,
372
- callBrowser: await resolveLocalMeetingBrowserRequest(params.runtime),
373
- finalize: params.finalize === true,
374
- meetingUrl: params.meetingUrl,
375
- meetingSessionId: params.meetingSessionId,
376
- tab: params.tab,
377
- timeoutMs: Math.min(Math.max(1e3, params.config.chrome.joinTimeoutMs), 1e4)
378
- });
379
- }
380
- async function readChromeMeetTranscriptOnNode(params) {
381
- const nodeId = params.nodeId ?? await resolveChromeNode({
385
+ const node = params.transport === "chrome-node" ? { nodeId: params.nodeId ?? await resolveChromeNode({
382
386
  runtime: params.runtime,
383
387
  requestedNode: params.config.chromeNode.node
384
- });
385
- const timeoutMs = Math.min(Math.max(1e3, params.config.chrome.joinTimeoutMs), 1e4);
388
+ }) } : void 0;
386
389
  return await readMeetingTranscriptWithBrowser({
387
390
  adapter: GOOGLE_MEET_PLATFORM_ADAPTER,
388
- callBrowser: async (request) => await callBrowserProxyOnNode({
389
- runtime: params.runtime,
390
- nodeId,
391
- method: request.method,
392
- path: request.path,
393
- body: request.body,
394
- timeoutMs: request.timeoutMs
395
- }),
391
+ callBrowser: node ? chromeNodeBrowserRequest(params.runtime, node.nodeId) : await resolveLocalMeetingBrowserRequest(params.runtime),
396
392
  finalize: params.finalize === true,
397
393
  meetingUrl: params.meetingUrl,
398
394
  meetingSessionId: params.meetingSessionId,
399
395
  tab: params.tab,
400
- timeoutMs
401
- });
402
- }
403
- async function leaveChromeMeetOnNode(params) {
404
- const nodeId = params.nodeId ?? await resolveChromeNode({
405
- runtime: params.runtime,
406
- requestedNode: params.config.chromeNode.node
407
- });
408
- return await leaveMeetingWithBrowser({
409
- adapter: GOOGLE_MEET_PLATFORM_ADAPTER,
410
- callBrowser: async (request) => await callBrowserProxyOnNode({
411
- runtime: params.runtime,
412
- nodeId,
413
- method: request.method,
414
- path: request.path,
415
- body: request.body,
416
- timeoutMs: request.timeoutMs
417
- }),
418
- launch: params.config.chrome.launch,
419
- meetingSessionId: params.meetingSessionId,
420
- meetingUrl: params.meetingUrl,
421
- tab: params.tab,
422
- timeoutMs: params.config.chrome.joinTimeoutMs
396
+ timeoutMs: Math.min(Math.max(1e3, params.config.chrome.joinTimeoutMs), 1e4)
423
397
  });
424
398
  }
425
399
  async function openMeetWithBrowserProxy(params) {
@@ -468,43 +442,21 @@ async function openMeetWithBrowserProxy(params) {
468
442
  });
469
443
  }
470
444
  async function recoverCurrentMeetTab(params) {
471
- return {
472
- transport: "chrome",
473
- ...await recoverMeetingBrowserTab({
474
- adapter: GOOGLE_MEET_PLATFORM_ADAPTER,
475
- callBrowser: await resolveLocalMeetingBrowserRequest(params.runtime),
476
- captureCaptions: shouldCaptureCaptions(params.mode ?? "bidi", params.fullConfig),
477
- config: params.config.chrome,
478
- locationLabel: "in local Chrome",
479
- mode: params.mode ?? "bidi",
480
- readOnly: params.readOnly,
481
- requestedMeetingUrl: params.url,
482
- trackedMeetingUrl: params.trackedMeetingUrl,
483
- trackedTargetId: params.trackedTargetId
484
- })
485
- };
486
- }
487
- async function recoverCurrentMeetTabOnNode(params) {
488
- const nodeId = await resolveChromeNode({
445
+ const node = params.transport === "chrome-node" ? { nodeId: await resolveChromeNode({
489
446
  runtime: params.runtime,
490
447
  requestedNode: params.config.chromeNode.node
491
- });
448
+ }) } : void 0;
492
449
  return {
493
- transport: "chrome-node",
494
- nodeId,
450
+ ...node ? {
451
+ transport: "chrome-node",
452
+ nodeId: node.nodeId
453
+ } : { transport: "chrome" },
495
454
  ...await recoverMeetingBrowserTab({
496
455
  adapter: GOOGLE_MEET_PLATFORM_ADAPTER,
497
- callBrowser: async (request) => await callBrowserProxyOnNode({
498
- runtime: params.runtime,
499
- nodeId,
500
- method: request.method,
501
- path: request.path,
502
- body: request.body,
503
- timeoutMs: request.timeoutMs
504
- }),
456
+ callBrowser: node ? chromeNodeBrowserRequest(params.runtime, node.nodeId) : await resolveLocalMeetingBrowserRequest(params.runtime),
505
457
  captureCaptions: shouldCaptureCaptions(params.mode ?? "bidi", params.fullConfig),
506
458
  config: params.config.chrome,
507
- locationLabel: "on the selected Chrome node",
459
+ locationLabel: node ? "on the selected Chrome node" : "in local Chrome",
508
460
  mode: params.mode ?? "bidi",
509
461
  readOnly: params.readOnly,
510
462
  requestedMeetingUrl: params.url,
@@ -665,11 +617,12 @@ async function launchChromeMeetOnNode(params) {
665
617
  //#endregion
666
618
  //#region extensions/google-meet/src/runtime-setup.ts
667
619
  function collectChromeAudioCommands(config) {
668
- return uniqueStrings((config.chrome.audioBridgeCommand ? [config.chrome.audioBridgeCommand[0]] : [
620
+ const commands = config.chrome.audioBridgeCommand ? [config.chrome.audioBridgeCommand[0]] : [
669
621
  config.chrome.audioInputCommand?.[0],
670
622
  config.chrome.audioOutputCommand?.[0],
671
623
  config.chrome.bargeInInputCommand?.[0]
672
- ]).filter((value) => Boolean(value?.trim())));
624
+ ];
625
+ return uniqueStrings(commands.filter((value) => Boolean(value?.trim())));
673
626
  }
674
627
  async function commandExists(runtime, command) {
675
628
  return (await runtime.system.runCommandWithTimeout([
@@ -964,15 +917,11 @@ var GoogleMeetRuntime = class {
964
917
  const transport = resolveTransport(request.transport, this.params.config);
965
918
  if (transport === "twilio") throw new Error("recover_current_tab only supports chrome or chrome-node transports");
966
919
  const url = request.url ? GOOGLE_MEET_PLATFORM_ADAPTER.urls.validateAndNormalize(request.url) : void 0;
967
- return transport === "chrome-node" ? await recoverCurrentMeetTabOnNode({
968
- runtime: this.params.runtime,
969
- config: this.params.config,
970
- fullConfig: this.params.fullConfig,
971
- url
972
- }) : await recoverCurrentMeetTab({
920
+ return await recoverCurrentMeetTab({
973
921
  runtime: this.params.runtime,
974
922
  config: this.params.config,
975
923
  fullConfig: this.params.fullConfig,
924
+ transport,
976
925
  url
977
926
  });
978
927
  }
@@ -1009,16 +958,7 @@ var GoogleMeetRuntime = class {
1009
958
  async #joinTransport(request, session, context) {
1010
959
  if (isBrowserTransport(session.transport)) {
1011
960
  const chromeConfig = withSessionAgentConfig(this.params.config, session.agentId);
1012
- const result = session.transport === "chrome-node" ? await launchChromeMeetOnNode({
1013
- runtime: this.params.runtime,
1014
- config: chromeConfig,
1015
- fullConfig: this.params.fullConfig,
1016
- meetingSessionId: session.id,
1017
- requesterSessionKey: request.requesterSessionKey,
1018
- mode: session.mode,
1019
- url: session.url,
1020
- logger: this.params.logger
1021
- }) : await launchChromeMeet({
961
+ const result = await (session.transport === "chrome-node" ? launchChromeMeetOnNode : launchChromeMeet)({
1022
962
  runtime: this.params.runtime,
1023
963
  config: chromeConfig,
1024
964
  fullConfig: this.params.fullConfig,
@@ -1125,15 +1065,7 @@ var GoogleMeetRuntime = class {
1125
1065
  node: session.chrome.nodeId
1126
1066
  } } : {}
1127
1067
  };
1128
- const result = session.transport === "chrome-node" ? await launchChromeMeetOnNode({
1129
- runtime: this.params.runtime,
1130
- config: recoveryConfig,
1131
- fullConfig: this.params.fullConfig,
1132
- meetingSessionId: session.id,
1133
- mode: session.mode,
1134
- url: session.url,
1135
- logger: this.params.logger
1136
- }) : await launchChromeMeet({
1068
+ const result = await (session.transport === "chrome-node" ? launchChromeMeetOnNode : launchChromeMeet)({
1137
1069
  runtime: this.params.runtime,
1138
1070
  config: recoveryConfig,
1139
1071
  fullConfig: this.params.fullConfig,
@@ -1147,19 +1079,11 @@ var GoogleMeetRuntime = class {
1147
1079
  }
1148
1080
  async #refreshBrowserHealth(session, options = {}) {
1149
1081
  try {
1150
- const result = session.transport === "chrome-node" ? await recoverCurrentMeetTabOnNode({
1151
- runtime: this.params.runtime,
1152
- config: this.params.config,
1153
- fullConfig: this.params.fullConfig,
1154
- mode: session.mode,
1155
- readOnly: options.readOnly,
1156
- trackedMeetingUrl: session.url,
1157
- trackedTargetId: session.chrome?.browserTab?.targetId,
1158
- url: session.url
1159
- }) : await recoverCurrentMeetTab({
1082
+ const result = await recoverCurrentMeetTab({
1160
1083
  runtime: this.params.runtime,
1161
1084
  config: this.params.config,
1162
1085
  fullConfig: this.params.fullConfig,
1086
+ transport: session.transport === "chrome-node" ? "chrome-node" : "chrome",
1163
1087
  mode: session.mode,
1164
1088
  readOnly: options.readOnly,
1165
1089
  trackedMeetingUrl: session.url,
@@ -1236,16 +1160,12 @@ var GoogleMeetRuntime = class {
1236
1160
  async #captureTranscript(session, options = {}) {
1237
1161
  const tab = session.chrome?.browserTab;
1238
1162
  if (!tab) return;
1239
- return session.transport === "chrome-node" ? await readChromeMeetTranscriptOnNode({
1240
- runtime: this.params.runtime,
1241
- nodeId: session.chrome?.nodeId,
1242
- config: this.params.config,
1243
- ...options.finalize === void 0 ? {} : { finalize: options.finalize },
1244
- meetingUrl: session.url,
1245
- meetingSessionId: session.id,
1246
- tab
1247
- }) : await readChromeMeetTranscript({
1163
+ return await readChromeMeetTranscript({
1248
1164
  runtime: this.params.runtime,
1165
+ ...session.transport === "chrome-node" ? {
1166
+ transport: "chrome-node",
1167
+ nodeId: session.chrome?.nodeId
1168
+ } : {},
1249
1169
  config: this.params.config,
1250
1170
  ...options.finalize === void 0 ? {} : { finalize: options.finalize },
1251
1171
  meetingUrl: session.url,
@@ -1268,15 +1188,12 @@ var GoogleMeetRuntime = class {
1268
1188
  }
1269
1189
  let left;
1270
1190
  try {
1271
- const result = session.transport === "chrome-node" ? await leaveChromeMeetOnNode({
1272
- runtime: this.params.runtime,
1273
- nodeId: session.chrome?.nodeId,
1274
- config: this.params.config,
1275
- meetingSessionId: session.id,
1276
- meetingUrl: session.url,
1277
- tab
1278
- }) : await leaveChromeMeet({
1191
+ const result = await leaveChromeMeet({
1279
1192
  runtime: this.params.runtime,
1193
+ ...session.transport === "chrome-node" ? {
1194
+ transport: "chrome-node",
1195
+ nodeId: session.chrome?.nodeId
1196
+ } : {},
1280
1197
  config: this.params.config,
1281
1198
  meetingSessionId: session.id,
1282
1199
  meetingUrl: session.url,
@@ -1,4 +1,4 @@
1
- const Email = /^(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[^"\\]|\\.)*")@(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)*|\[(?:IPv6:[a-f0-9:]+|(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(?:\.(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3})\])$/i;
1
+ const Email = /^(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[^"\\]|\\[\x20-\x7e])*")@(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)*|\[(?:IPv6:[a-f0-9:]+|(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(?:\.(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3})\])$/i;
2
2
  /**
3
3
  * Returns true if the value is an Email
4
4
  * @specification https://datatracker.ietf.org/doc/html/rfc5322
@@ -1,6 +1,9 @@
1
1
  import * as FormatBidi from './format/bidi.mjs';
2
2
  import * as LabelUnicode from './label/unicode.mjs';
3
3
  import * as LabelPuny from './label/puny.mjs';
4
+ // ------------------------------------------------------------------
5
+ // IsLabel
6
+ // ------------------------------------------------------------------
4
7
  function IsValidLabelLength(value) {
5
8
  return value.length > 0 && value.length <= 63;
6
9
  }
@@ -8,9 +11,24 @@ function IsLabel(value) {
8
11
  return IsValidLabelLength(value) && (LabelPuny.IsPunyLabel(value) ||
9
12
  LabelUnicode.IsUnicodeLabel(value));
10
13
  }
14
+ // ------------------------------------------------------------------
15
+ // NormalizeHostname
16
+ //
17
+ // Normalizes a hostname for label validation. Normalizes for NFC
18
+ // such that equivalent codepoint sequences can be uniformly
19
+ // compared. It also removes codepoints that IDNA mapping ignores,
20
+ // and converts full stop variants to ASCII '.' so the hostname can
21
+ // be split into labels.
22
+ // ------------------------------------------------------------------
11
23
  function NormalizeHostname(value) {
12
- return value.normalize('NFC').replace(/[\u002E\u3002\uFF0E\uFF61]/g, '.');
24
+ return value
25
+ .normalize('NFC')
26
+ .replace(/[\u00ad\u034f\u180b-\u180d\u200b\ufe00-\ufe0f\u{e0100}-\u{e01ef}]/gu, '') // RE_IGNORED_MAPPING
27
+ .replace(/[\u002E\u3002\uFF0E\uFF61]/g, '.'); // RE_FULL_STOP_MAPPING
13
28
  }
29
+ // ------------------------------------------------------------------
30
+ // IsIdnHostname
31
+ // ------------------------------------------------------------------
14
32
  export function IsIdnHostname(value) {
15
33
  if (value.length === 0 || value.includes(' '))
16
34
  return false;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "typebox",
3
3
  "description": "Json Schema Type Builder with Static Type Resolution for TypeScript",
4
- "version": "1.3.16",
4
+ "version": "1.3.17",
5
5
  "keywords": [
6
6
  "typescript",
7
7
  "jsonschema"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/google-meet",
3
- "version": "2026.9.1-beta.1",
3
+ "version": "2026.9.1",
4
4
  "description": "OpenClaw Google Meet participant plugin for joining calls through Chrome or Twilio transports.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -9,10 +9,10 @@
9
9
  "type": "module",
10
10
  "dependencies": {
11
11
  "jszip": "3.10.1",
12
- "typebox": "1.3.16"
12
+ "typebox": "1.3.17"
13
13
  },
14
14
  "peerDependencies": {
15
- "openclaw": ">=2026.9.1-beta.1"
15
+ "openclaw": ">=2026.9.1"
16
16
  },
17
17
  "peerDependenciesMeta": {
18
18
  "openclaw": {
@@ -29,10 +29,10 @@
29
29
  "minHostVersion": ">=2026.4.20"
30
30
  },
31
31
  "compat": {
32
- "pluginApi": ">=2026.9.1-beta.1"
32
+ "pluginApi": ">=2026.9.1"
33
33
  },
34
34
  "build": {
35
- "openclawVersion": "2026.9.1-beta.1"
35
+ "openclawVersion": "2026.9.1"
36
36
  },
37
37
  "release": {
38
38
  "publishToClawHub": true,