@openclaw/google-meet 2026.9.3 → 2026.9.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.
@@ -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-DkI5A7LT.js";
2
- import { i as resolveGoogleMeetGatewayOperationTimeoutMs } from "./config-wBK8loBb.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-RSH2DZTl.js";
2
+ import { i as resolveGoogleMeetGatewayOperationTimeoutMs } from "./config-C-6enWkx.js";
3
3
  import { buildGoogleMeetAuthUrl, exchangeGoogleMeetAuthCode, resolveGoogleMeetAccessToken, waitForGoogleMeetAuthCode } from "./oauth-DgBscjXK.js";
4
- import { n as hasCreateSpaceConfigInput, r as resolveCreateSpaceConfig } from "./create-BbQ9g_AK.js";
4
+ import { n as hasCreateSpaceConfigInput, r as resolveCreateSpaceConfig } from "./create-Cr6rg236.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";
@@ -92,6 +92,7 @@ const DEFAULT_GOOGLE_MEET_CHROME_AUDIO_FORMAT = "pcm16-24khz";
92
92
  const DEFAULT_GOOGLE_MEET_BARGE_IN_RMS_THRESHOLD = 650;
93
93
  const DEFAULT_GOOGLE_MEET_BARGE_IN_PEAK_THRESHOLD = 2500;
94
94
  const DEFAULT_GOOGLE_MEET_BARGE_IN_COOLDOWN_MS = 900;
95
+ const DEFAULT_GOOGLE_MEET_REALTIME_MODEL = void 0;
95
96
  const DEFAULT_GOOGLE_MEET_REALTIME_INSTRUCTIONS = `You are joining a private Google Meet as an OpenClaw voice transport. Keep spoken replies brief and natural. In agent mode, wait for OpenClaw consult results and speak them exactly. In bidi mode, answer directly and call ${REALTIME_VOICE_AGENT_CONSULT_TOOL_NAME} for deeper reasoning, current information, or tools.`;
96
97
  const DEFAULT_GOOGLE_MEET_REALTIME_INTRO_MESSAGE = "Say exactly: I'm here and listening.";
97
98
  const DEFAULT_GOOGLE_MEET_CONFIG = {
@@ -128,6 +129,7 @@ const DEFAULT_GOOGLE_MEET_CONFIG = {
128
129
  strategy: "agent",
129
130
  provider: "openai",
130
131
  transcriptionProvider: "openai",
132
+ model: DEFAULT_GOOGLE_MEET_REALTIME_MODEL,
131
133
  instructions: DEFAULT_GOOGLE_MEET_REALTIME_INSTRUCTIONS,
132
134
  introMessage: DEFAULT_GOOGLE_MEET_REALTIME_INTRO_MESSAGE,
133
135
  toolPolicy: "safe-read-only",
@@ -1,4 +1,4 @@
1
- import { h as __exportAll, l as createGoogleMeetSpace } from "./plugin-helpers-DkI5A7LT.js";
1
+ import { h as __exportAll, l as createGoogleMeetSpace } from "./plugin-helpers-RSH2DZTl.js";
2
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";
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
- 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-ona5lHdz.js";
3
+ import { r as resolveGoogleMeetConfig } from "./config-C-6enWkx.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-DLs9YDzZ.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";
@@ -1,5 +1,5 @@
1
1
  import { n as GOOGLE_MEET_NODE_COMMAND } from "./google-meet-platform-constants-Bs5iAg3E.js";
2
- import { n as DEFAULT_GOOGLE_MEET_AUDIO_OUTPUT_COMMAND, t as DEFAULT_GOOGLE_MEET_AUDIO_INPUT_COMMAND } from "./config-wBK8loBb.js";
2
+ import { n as DEFAULT_GOOGLE_MEET_AUDIO_OUTPUT_COMMAND, t as DEFAULT_GOOGLE_MEET_AUDIO_INPUT_COMMAND } from "./config-C-6enWkx.js";
3
3
  import { t as GOOGLE_MEET_PLATFORM_ADAPTER } from "./google-meet-platform-adapter-C3J-iFRE.js";
4
4
  import { MeetingPlatformAdapter } from "openclaw/plugin-sdk/meeting-runtime";
5
5
  //#region extensions/google-meet/src/node-host.ts
@@ -1,4 +1,4 @@
1
- import { c as loadGoogleMeetCliModule, p as resolveMeetingInput } from "./plugin-registration-ona5lHdz.js";
1
+ import { c as loadGoogleMeetCliModule, p as resolveMeetingInput } from "./plugin-registration-DLs9YDzZ.js";
2
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";
@@ -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-BbQ9g_AK.js").then((n) => n.t));
776
+ const loadGoogleMeetCreateModule = createLazyRuntimeModule(() => import("./create-Cr6rg236.js").then((n) => n.t));
777
777
  async function createMeetFromParams(params) {
778
778
  return (await loadGoogleMeetCreateModule()).createMeetFromParams(params);
779
779
  }
@@ -1,13 +1,13 @@
1
1
  import { i as isGoogleMeetBrowserManualActionError, n as GOOGLE_MEET_NODE_COMMAND } from "./google-meet-platform-constants-Bs5iAg3E.js";
2
- import { i as resolveGoogleMeetGatewayOperationTimeoutMs } from "./config-wBK8loBb.js";
2
+ import { i as resolveGoogleMeetGatewayOperationTimeoutMs } from "./config-C-6enWkx.js";
3
3
  import { asNonArrayRecord as asParamRecord, 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
  //#region extensions/google-meet/src/plugin-registration.ts
7
- const loadGoogleMeetPluginHelpers = createLazyRuntimeModule(() => import("./plugin-helpers-DkI5A7LT.js").then((n) => n.r));
8
- const loadGoogleMeetCliModule = createLazyRuntimeModule(() => import("./cli-HxUMx7pI.js"));
9
- const loadGoogleMeetNodeHostModule = createLazyRuntimeModule(() => import("./node-host-BXtXbsMa.js"));
10
- const loadGoogleMeetRuntimeModule = createLazyRuntimeModule(() => import("./runtime-BKbf6Uj_.js"));
7
+ const loadGoogleMeetPluginHelpers = createLazyRuntimeModule(() => import("./plugin-helpers-RSH2DZTl.js").then((n) => n.r));
8
+ const loadGoogleMeetCliModule = createLazyRuntimeModule(() => import("./cli-BCUxht2Q.js"));
9
+ const loadGoogleMeetNodeHostModule = createLazyRuntimeModule(() => import("./node-host-DS-lLN37.js"));
10
+ const loadGoogleMeetRuntimeModule = createLazyRuntimeModule(() => import("./runtime-CXfjJvPN.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);
@@ -1,14 +1,13 @@
1
- import { n as GOOGLE_MEET_NODE_COMMAND } from "./google-meet-platform-constants-Bs5iAg3E.js";
1
+ import { n as GOOGLE_MEET_NODE_COMMAND, t as GOOGLE_MEET_BROWSER_NODE_ADAPTER } from "./google-meet-platform-constants-Bs5iAg3E.js";
2
2
  import { t as normalizeMeetUrl } from "./meet-url-BP2Jlvjs.js";
3
3
  import { c as callBrowserProxyOnNode, l as resolveChromeNode, u as resolveChromeNodeInfo } from "./chrome-create-PKAyxCiL.js";
4
4
  import { n as normalizeDialInNumber, t as GOOGLE_MEET_PLATFORM_ADAPTER } from "./google-meet-platform-adapter-C3J-iFRE.js";
5
5
  import { asOptionalRecord, asRecord, normalizeOptionalString, uniqueStrings } from "openclaw/plugin-sdk/string-coerce-runtime";
6
6
  import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
7
- import { addTimerTimeoutGraceMs } from "openclaw/plugin-sdk/number-runtime";
8
7
  import { GatewayClient, startGatewayClientWhenEventLoopReady } from "openclaw/plugin-sdk/gateway-runtime";
9
8
  import path from "node:path";
10
9
  import { isBlockedHostnameOrIp } from "openclaw/plugin-sdk/ssrf-runtime";
11
- import { MeetingPlatformAdapter, MeetingSessionRuntime, addMeetingSetupCheck, createLocalMeetingRealtimeAudioTransport, createMeetingRealtimeEngineBindings, createMeetingSession, createMeetingSetupStatus, createMeetingVoiceCallGateway, createNodeMeetingRealtimeAudioTransport, endMeetingVoiceCallGatewayCall, getMeetingVoiceCallGatewayCall, isMeetingVoiceCallMissingError, joinMeetingViaVoiceCallGateway, leaveMeetingWithBrowser, openMeetingWithBrowser, readMeetingTranscriptWithBrowser, recoverMeetingBrowserTab, resolveLocalMeetingBrowserRequest, speakMeetingViaVoiceCallGateway, startMeetingAgentRealtimeEngine, startMeetingRealtimeEngine } from "openclaw/plugin-sdk/meeting-runtime";
10
+ import { MeetingPlatformAdapter, MeetingSessionRuntime, addMeetingSetupCheck, createMeetingSession, createMeetingSetupStatus, createMeetingVoiceCallGateway, endMeetingVoiceCallGatewayCall, getMeetingVoiceCallGatewayCall, isMeetingVoiceCallMissingError, joinMeetingViaVoiceCallGateway, leaveMeetingWithBrowser, readMeetingTranscriptWithBrowser, recoverMeetingBrowserTab, resolveLocalMeetingBrowserRequest, speakMeetingViaVoiceCallGateway } from "openclaw/plugin-sdk/meeting-runtime";
12
11
  import { resolveDefaultAgentId } from "openclaw/plugin-sdk/agent-runtime";
13
12
  import { normalizeAgentId } from "openclaw/plugin-sdk/routing";
14
13
  import fs from "node:fs";
@@ -206,126 +205,28 @@ function addGoogleMeetSetupCheck(status, check) {
206
205
  }
207
206
  //#endregion
208
207
  //#region extensions/google-meet/src/transports/chrome.ts
209
- function shouldCaptureCaptions(mode, fullConfig) {
210
- return mode === "transcribe" || !fullConfig || resolveTranscriptsConfig(fullConfig.transcripts).enabled;
211
- }
212
- async function prepareGoogleMeetAudioRuntime(params) {
213
- const audio = MeetingPlatformAdapter.resolveAudioRuntimeForFormat({
214
- backend: params.config.chrome.audioBackend,
215
- bufferBytes: params.config.chrome.audioBufferBytes,
216
- format: params.config.chrome.audioFormat,
217
- inputCommand: params.config.chrome.audioInputCommandOverride,
218
- outputCommand: params.config.chrome.audioOutputCommandOverride
219
- });
220
- await MeetingPlatformAdapter.ensureAudioBackend({
221
- backend: audio.backend,
222
- timeoutMs: params.timeoutMs,
223
- run: async (argv, timeoutMs) => {
224
- const result = await params.runtime.system.runCommandWithTimeout(argv, { timeoutMs });
225
- return {
226
- ...result,
227
- code: result.code ?? 1
228
- };
229
- }
230
- });
231
- return audio;
232
- }
233
- async function assertGoogleMeetAudioAvailable(params) {
234
- await prepareGoogleMeetAudioRuntime(params);
235
- }
208
+ const chromeTransport = MeetingPlatformAdapter.createChromeTransportWithExternalAudio({
209
+ browserNodeAdapter: GOOGLE_MEET_BROWSER_NODE_ADAPTER,
210
+ isRealtimeRouteReady: (mode, health) => !MeetingPlatformAdapter.isTalkBackMode(mode) || MeetingPlatformAdapter.isRealtimeRouteReady(mode, health),
211
+ isTalkBackMode: MeetingPlatformAdapter.isTalkBackMode,
212
+ meetingLabel: "Google Meet",
213
+ nodeCommandName: GOOGLE_MEET_NODE_COMMAND,
214
+ platform: GOOGLE_MEET_PLATFORM_ADAPTER,
215
+ preserveTrackedBrowserOnEngineFailure: false,
216
+ startupFailurePolicy: "owned",
217
+ runtime: MeetingPlatformAdapter.createChromeRuntimeBindings()
218
+ });
219
+ const assertGoogleMeetAudioAvailable = chromeTransport.assertAudioDeviceAvailable;
220
+ const launchChromeMeetOnNode = chromeTransport.launchOnNode;
236
221
  async function launchChromeMeet(params) {
237
- let audio;
238
- const checkRealtimeAudioPrerequisites = async () => {
239
- if (!MeetingPlatformAdapter.isTalkBackMode(params.mode)) return;
240
- audio = await prepareGoogleMeetAudioRuntime({
241
- runtime: params.runtime,
242
- config: params.config,
243
- timeoutMs: Math.min(params.config.chrome.joinTimeoutMs, 1e4)
244
- });
245
- if (params.config.chrome.audioBridgeHealthCommand) {
246
- const health = await params.runtime.system.runCommandWithTimeout(params.config.chrome.audioBridgeHealthCommand, { timeoutMs: params.config.chrome.joinTimeoutMs });
247
- if (health.code !== 0) throw new Error(`Chrome audio bridge health check failed: ${health.stderr || health.stdout || health.code}`);
248
- }
249
- };
250
- const startRealtimeAudioBridge = async () => {
251
- if (!MeetingPlatformAdapter.isTalkBackMode(params.mode)) return;
252
- if (params.config.chrome.audioBridgeCommand) {
253
- if (params.mode === "agent") throw new Error("Chrome agent mode requires chrome.audioInputCommand and chrome.audioOutputCommand so OpenClaw can run STT and regular TTS directly.");
254
- const bridge = await params.runtime.system.runCommandWithTimeout(params.config.chrome.audioBridgeCommand, { timeoutMs: params.config.chrome.joinTimeoutMs });
255
- if (bridge.code !== 0) throw new Error(`failed to start Chrome audio bridge: ${bridge.stderr || bridge.stdout || bridge.code}`);
256
- return { type: "external-command" };
257
- }
258
- if (!params.config.chrome.audioInputCommand || !params.config.chrome.audioOutputCommand) throw new Error("Chrome talk-back mode requires chrome.audioInputCommand and chrome.audioOutputCommand, or chrome.audioBridgeCommand for an external bridge.");
259
- if (!audio) throw new Error("Google Meet audio backend was not prepared.");
260
- const transport = createLocalMeetingRealtimeAudioTransport({
261
- inputCommand: audio.inputCommand,
262
- outputCommand: audio.outputCommand,
263
- audioFormat: params.config.chrome.audioFormat,
264
- bargeInInputCommand: params.config.chrome.bargeInInputCommand,
265
- bargeInRmsThreshold: params.config.chrome.bargeInRmsThreshold,
266
- bargeInPeakThreshold: params.config.chrome.bargeInPeakThreshold,
267
- bargeInCooldownMs: params.config.chrome.bargeInCooldownMs,
268
- logger: params.logger,
269
- logScope: GOOGLE_MEET_PLATFORM_ADAPTER.logScope
270
- });
271
- const bindings = createMeetingRealtimeEngineBindings({
272
- platform: GOOGLE_MEET_PLATFORM_ADAPTER,
273
- ...params
274
- });
275
- const engine = params.mode === "agent" ? await startMeetingAgentRealtimeEngine({
276
- config: params.config,
277
- fullConfig: params.fullConfig,
278
- runtime: params.runtime,
279
- platform: bindings.platform,
280
- meetingSessionId: params.meetingSessionId,
281
- requesterSessionKey: params.requesterSessionKey,
282
- transport,
283
- logger: params.logger,
284
- consultAgent: bindings.consultAgent
285
- }) : await startMeetingRealtimeEngine({
286
- config: {
287
- ...params.config,
288
- realtime: {
289
- ...params.config.realtime,
290
- strategy: "bidi"
291
- }
292
- },
293
- fullConfig: params.fullConfig,
294
- runtime: params.runtime,
295
- ...bindings,
296
- meetingSessionId: params.meetingSessionId,
297
- requesterSessionKey: params.requesterSessionKey,
298
- transport,
299
- logger: params.logger
300
- });
301
- return {
302
- type: "command-pair",
303
- inputCommand: audio.inputCommand,
304
- outputCommand: audio.outputCommand,
305
- ...engine
306
- };
307
- };
308
- await checkRealtimeAudioPrerequisites();
309
- const result = await openOrRecoverMeetWithBrowser({
310
- callBrowser: await resolveLocalMeetingBrowserRequest(params.runtime),
311
- config: params.config,
312
- captureCaptions: shouldCaptureCaptions(params.mode, params.fullConfig),
313
- locationLabel: "in local Chrome",
314
- meetingSessionId: params.meetingSessionId,
315
- mode: params.mode,
316
- url: params.url
317
- });
318
- const audioBridge = MeetingPlatformAdapter.isRealtimeRouteReady(params.mode, result.browser) ? await startRealtimeAudioBridge() : void 0;
222
+ const result = await chromeTransport.launchInChrome(params);
319
223
  return {
320
224
  ...result,
321
- audioBackend: audio?.backend,
322
- audioBridge
225
+ audioBridge: result.audioBridge
323
226
  };
324
227
  }
325
- function parseNodeStartResult(raw) {
326
- const value = raw && typeof raw === "object" && "payload" in raw ? raw.payload : raw;
327
- if (!value || typeof value !== "object") throw new Error("Google Meet node returned an invalid start result.");
328
- return value;
228
+ function shouldCaptureCaptions(mode, fullConfig) {
229
+ return mode === "transcribe" || !fullConfig || resolveTranscriptsConfig(fullConfig.transcripts).enabled;
329
230
  }
330
231
  function chromeNodeBrowserRequest(runtime, nodeId) {
331
232
  return async (request) => await callBrowserProxyOnNode({
@@ -367,43 +268,6 @@ async function readChromeMeetTranscript(params) {
367
268
  timeoutMs: Math.min(Math.max(1e3, params.config.chrome.joinTimeoutMs), 1e4)
368
269
  });
369
270
  }
370
- async function openOrRecoverMeetWithBrowser(params) {
371
- if (!params.config.chrome.launch) {
372
- const recovered = await recoverMeetingBrowserTab({
373
- adapter: GOOGLE_MEET_PLATFORM_ADAPTER,
374
- allowSessionAdoption: true,
375
- autoJoin: params.config.chrome.autoJoin,
376
- callBrowser: params.callBrowser,
377
- captureCaptions: params.captureCaptions,
378
- config: params.config.chrome,
379
- locationLabel: params.locationLabel,
380
- meetingSessionId: params.meetingSessionId,
381
- mode: params.mode,
382
- requestedMeetingUrl: params.url,
383
- trackedMeetingUrl: params.url,
384
- trackedTargetId: void 0
385
- });
386
- return {
387
- launched: false,
388
- browser: recovered.browser,
389
- tab: recovered.targetId ? {
390
- targetId: recovered.targetId,
391
- openedByPlugin: false
392
- } : void 0
393
- };
394
- }
395
- return await openMeetingWithBrowser({
396
- adapter: GOOGLE_MEET_PLATFORM_ADAPTER,
397
- callBrowser: params.callBrowser,
398
- config: params.config.chrome,
399
- session: {
400
- captureCaptions: params.captureCaptions,
401
- mode: params.mode,
402
- meetingSessionId: params.meetingSessionId,
403
- url: params.url
404
- }
405
- });
406
- }
407
271
  async function recoverCurrentMeetTab(params) {
408
272
  const node = params.transport === "chrome-node" ? { nodeId: await resolveChromeNode({
409
273
  runtime: params.runtime,
@@ -428,155 +292,6 @@ async function recoverCurrentMeetTab(params) {
428
292
  })
429
293
  };
430
294
  }
431
- async function launchChromeMeetOnNode(params) {
432
- const nodeId = await resolveChromeNode({
433
- runtime: params.runtime,
434
- requestedNode: params.config.chromeNode.node
435
- });
436
- try {
437
- await params.runtime.nodes.invoke({
438
- nodeId,
439
- command: GOOGLE_MEET_NODE_COMMAND,
440
- params: {
441
- action: "stopByUrl",
442
- url: params.url,
443
- mode: params.mode
444
- },
445
- timeoutMs: 5e3
446
- });
447
- } catch (error) {
448
- params.logger.debug?.(`[google-meet] node bridge cleanup before join ignored: ${error instanceof Error ? error.message : String(error)}`);
449
- }
450
- const setup = MeetingPlatformAdapter.isTalkBackMode(params.mode) ? parseNodeStartResult(await params.runtime.nodes.invoke({
451
- nodeId,
452
- command: GOOGLE_MEET_NODE_COMMAND,
453
- params: {
454
- action: "setup",
455
- audioBackend: params.config.chrome.audioBackend,
456
- audioFormat: params.config.chrome.audioFormat,
457
- audioBufferBytes: params.config.chrome.audioBufferBytes,
458
- ...params.config.chrome.audioInputCommandOverride ? { audioInputCommand: params.config.chrome.audioInputCommandOverride } : {},
459
- ...params.config.chrome.audioOutputCommandOverride ? { audioOutputCommand: params.config.chrome.audioOutputCommandOverride } : {}
460
- },
461
- timeoutMs: 12e3
462
- })) : void 0;
463
- const browserControl = await openOrRecoverMeetWithBrowser({
464
- callBrowser: chromeNodeBrowserRequest(params.runtime, nodeId),
465
- locationLabel: "on the selected Chrome node",
466
- config: params.config,
467
- captureCaptions: shouldCaptureCaptions(params.mode, params.fullConfig),
468
- mode: params.mode,
469
- meetingSessionId: params.meetingSessionId,
470
- url: params.url
471
- });
472
- if (MeetingPlatformAdapter.isTalkBackMode(params.mode) && !MeetingPlatformAdapter.isRealtimeRouteReady(params.mode, browserControl.browser)) return {
473
- nodeId,
474
- launched: browserControl.launched,
475
- audioBackend: setup?.audioBackend,
476
- browser: browserControl.browser,
477
- tab: browserControl.tab
478
- };
479
- const result = parseNodeStartResult(await params.runtime.nodes.invoke({
480
- nodeId,
481
- command: GOOGLE_MEET_NODE_COMMAND,
482
- params: {
483
- action: "start",
484
- url: params.url,
485
- mode: params.mode,
486
- launch: false,
487
- browserProfile: params.config.chrome.browserProfile,
488
- joinTimeoutMs: params.config.chrome.joinTimeoutMs,
489
- audioBackend: params.config.chrome.audioBackend,
490
- audioFormat: params.config.chrome.audioFormat,
491
- audioBufferBytes: params.config.chrome.audioBufferBytes,
492
- ...params.config.chrome.audioInputCommandOverride ? { audioInputCommand: params.config.chrome.audioInputCommandOverride } : {},
493
- ...params.config.chrome.audioOutputCommandOverride ? { audioOutputCommand: params.config.chrome.audioOutputCommandOverride } : {},
494
- audioBridgeCommand: params.config.chrome.audioBridgeCommand,
495
- audioBridgeHealthCommand: params.config.chrome.audioBridgeHealthCommand
496
- },
497
- timeoutMs: addTimerTimeoutGraceMs(params.config.chrome.joinTimeoutMs) ?? 1
498
- }));
499
- if (result.audioBridge?.type === "node-command-pair") {
500
- if (!result.bridgeId) throw new Error("Google Meet node did not return an audio bridge id.");
501
- const transport = createNodeMeetingRealtimeAudioTransport({
502
- runtime: params.runtime,
503
- nodeId,
504
- bridgeId: result.bridgeId,
505
- audioFormat: params.config.chrome.audioFormat,
506
- logger: params.logger,
507
- commandName: GOOGLE_MEET_NODE_COMMAND,
508
- logScope: GOOGLE_MEET_PLATFORM_ADAPTER.logScope,
509
- logPrefix: params.mode === "agent" ? "node agent" : "node"
510
- });
511
- Reflect.set(transport, Symbol.for("openclaw.internal.meeting-node-output-generation.v1"), result.audioBridge.outputGeneration === true);
512
- const bindings = createMeetingRealtimeEngineBindings({
513
- platform: GOOGLE_MEET_PLATFORM_ADAPTER,
514
- ...params
515
- });
516
- const engine = params.mode === "agent" ? await startMeetingAgentRealtimeEngine({
517
- config: params.config,
518
- fullConfig: params.fullConfig,
519
- runtime: params.runtime,
520
- platform: bindings.platform,
521
- meetingSessionId: params.meetingSessionId,
522
- requesterSessionKey: params.requesterSessionKey,
523
- logPrefix: "node",
524
- transport,
525
- logger: params.logger,
526
- consultAgent: bindings.consultAgent
527
- }) : await startMeetingRealtimeEngine({
528
- config: {
529
- ...params.config,
530
- realtime: {
531
- ...params.config.realtime,
532
- strategy: "bidi"
533
- }
534
- },
535
- fullConfig: params.fullConfig,
536
- runtime: params.runtime,
537
- ...bindings,
538
- meetingSessionId: params.meetingSessionId,
539
- requesterSessionKey: params.requesterSessionKey,
540
- logPrefix: "node",
541
- talkSessionId: `google-meet:${params.meetingSessionId}:${result.bridgeId}:node-realtime`,
542
- talkContext: {
543
- nodeId,
544
- bridgeId: result.bridgeId
545
- },
546
- transport,
547
- logger: params.logger
548
- });
549
- const bridge = {
550
- type: "node-command-pair",
551
- nodeId,
552
- bridgeId: result.bridgeId,
553
- ...engine
554
- };
555
- return {
556
- nodeId,
557
- launched: browserControl.launched || result.launched === true,
558
- audioBackend: result.audioBackend ?? setup?.audioBackend,
559
- audioBridge: bridge,
560
- browser: browserControl.browser ?? result.browser,
561
- tab: browserControl.tab
562
- };
563
- }
564
- if (result.audioBridge?.type === "external-command") return {
565
- nodeId,
566
- launched: browserControl.launched || result.launched === true,
567
- audioBackend: result.audioBackend ?? setup?.audioBackend,
568
- audioBridge: { type: "external-command" },
569
- browser: browserControl.browser ?? result.browser,
570
- tab: browserControl.tab
571
- };
572
- return {
573
- nodeId,
574
- launched: browserControl.launched || result.launched === true,
575
- audioBackend: result.audioBackend ?? setup?.audioBackend,
576
- browser: browserControl.browser ?? result.browser,
577
- tab: browserControl.tab
578
- };
579
- }
580
295
  //#endregion
581
296
  //#region extensions/google-meet/src/runtime-setup.ts
582
297
  function collectChromeAudioCommands(config) {
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "id": "google-meet",
3
+ "categories": ["voice", "tools"],
3
4
  "doctorContract": {
4
5
  "configRepair": true
5
6
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/google-meet",
3
- "version": "2026.9.3",
3
+ "version": "2026.9.4",
4
4
  "description": "OpenClaw Google Meet participant plugin for joining calls through Chrome or Twilio transports.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -12,7 +12,7 @@
12
12
  "typebox": "1.3.18"
13
13
  },
14
14
  "peerDependencies": {
15
- "openclaw": ">=2026.9.3"
15
+ "openclaw": ">=2026.9.4"
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.3"
32
+ "pluginApi": ">=2026.9.4"
33
33
  },
34
34
  "build": {
35
- "openclawVersion": "2026.9.3"
35
+ "openclawVersion": "2026.9.4"
36
36
  },
37
37
  "release": {
38
38
  "publishToClawHub": true,